From 327fb31cb0509c9c55e970f7f90a11e375d00b4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 20 Apr 2017 15:58:52 +0200 Subject: [PATCH 001/157] #1030 Don't automatically create summary plots of preference is turned off --- ApplicationCode/Application/RiaPreferences.cpp | 2 +- .../Commands/RicImportSummaryCaseFeature.cpp | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index a8307d799f..43d55343d5 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -86,7 +86,7 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitFieldNoDefault(&readerSettings, "readerSettings", "Reader settings", "", "", ""); readerSettings = new RifReaderSettings; - CAF_PDM_InitField(&autoCreatePlotsOnImport, "AutoCreatePlotsOnImport", true, "Create Summary Plots When Importing Eclipse Case", "", "", ""); + CAF_PDM_InitField(&autoCreatePlotsOnImport, "AutoCreatePlotsOnImport", true, "Automatically Create Summary Plots On Import", "", "", ""); autoCreatePlotsOnImport.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); CAF_PDM_InitField(&defaultCurveFilter, "DefaultCurveFilter", QString("F*PT"), "Default Vector Selection Filter", "", "", ""); diff --git a/ApplicationCode/Commands/RicImportSummaryCaseFeature.cpp b/ApplicationCode/Commands/RicImportSummaryCaseFeature.cpp index da00e9c3e4..66ed83b6e5 100644 --- a/ApplicationCode/Commands/RicImportSummaryCaseFeature.cpp +++ b/ApplicationCode/Commands/RicImportSummaryCaseFeature.cpp @@ -19,6 +19,7 @@ #include "RicImportSummaryCaseFeature.h" #include "RiaApplication.h" +#include "RiaPreferences.h" #include "RimGridSummaryCase.h" #include "RimMainPlotCollection.h" @@ -102,10 +103,14 @@ bool RicImportSummaryCaseFeature::createAndAddSummaryCaseFromFile(const QString& RimSummaryCase* newSumCase = sumCaseColl->createAndAddSummaryCaseFromFileName(fileName); newSumCase->loadCase(); - RimMainPlotCollection* mainPlotColl = proj->mainPlotCollection(); - RimSummaryPlotCollection* summaryPlotColl = mainPlotColl->summaryPlotCollection(); - RicNewSummaryPlotFeature::createNewSummaryPlot(summaryPlotColl, newSumCase); + if (app->preferences()->autoCreatePlotsOnImport()) + { + RimMainPlotCollection* mainPlotColl = proj->mainPlotCollection(); + RimSummaryPlotCollection* summaryPlotColl = mainPlotColl->summaryPlotCollection(); + + RicNewSummaryPlotFeature::createNewSummaryPlot(summaryPlotColl, newSumCase); + } sumCaseColl->updateConnectedEditors(); app->addToRecentFiles(fileName); From 2745d857d09a55cb26a5d8d8f78326b5de5c8eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 18 Apr 2017 16:47:37 +0200 Subject: [PATCH 002/157] #1381 Wip: Well Alloc Plots split by phase without flow diagnostics This is implemented, but turned off as Ert did not seem to deliver correct phase flow rates. Can be enabled as soon as Ert is improved and updated. --- .../FileInterface/RifReaderEclipseOutput.cpp | 6 +++ .../Flow/RimWellAllocationPlot.cpp | 32 +++++------- .../RigAccWellFlowCalculator.cpp | 50 +++++++------------ .../RigAccWellFlowCalculator.h | 5 +- .../RigFlowDiagResultAddress.h | 4 ++ .../RigSingleWellResultsData.h | 44 +++++++++++++++- 6 files changed, 85 insertions(+), 56 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index 13649d6759..4bc4cf0ec0 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -908,6 +908,9 @@ RigWellResultPoint RifReaderEclipseOutput::createWellResultPoint(const RigGridBa int cellK = well_conn_get_k( ert_connection ); bool isCellOpen = well_conn_open( ert_connection ); double volumeRate = well_conn_get_volume_rate( ert_connection); + double oilRate = well_conn_get_oil_rate(ert_connection) ; + double gasRate = well_conn_get_gas_rate(ert_connection); + double waterRate = well_conn_get_water_rate(ert_connection); // If a well is defined in fracture region, the K-value is from (cellCountK - 1) -> cellCountK*2 - 1 // Adjust K so index is always in valid grid region @@ -960,6 +963,9 @@ RigWellResultPoint RifReaderEclipseOutput::createWellResultPoint(const RigGridBa resultPoint.m_ertBranchId = ertBranchId; resultPoint.m_ertSegmentId = ertSegmentId; resultPoint.m_flowRate = volumeRate; + resultPoint.m_oilRate = oilRate; + resultPoint.m_gasRate = gasRate; + resultPoint.m_waterRate = waterRate; } return resultPoint; diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp index 86b343ef96..3aeec6add7 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp @@ -250,7 +250,6 @@ void RimWellAllocationPlot::updateFromWell() depthType == RimWellLogPlot::TRUE_VERTICAL_DEPTH ? wfCalculator->trueVerticalDepth(brIdx) : std::vector(); - if ( m_flowDiagSolution ) { std::vector tracerNames = wfCalculator->tracerNames(); for (const QString& tracerName: tracerNames) @@ -273,24 +272,7 @@ void RimWellAllocationPlot::updateFromWell() //TODO: THIs is the data to be plotted... } } - else - { - const std::vector* accFlow = nullptr; - if (depthType == RimWellLogPlot::CONNECTION_NUMBER) - { - accFlow = &(m_flowType == ACCUMULATED ? - wfCalculator->accumulatedFlowPrConnection(brIdx): - wfCalculator->flowPrConnection( brIdx)); - } - else if ( depthType == RimWellLogPlot::PSEUDO_LENGTH || depthType == RimWellLogPlot::TRUE_VERTICAL_DEPTH) - { - accFlow = &(m_flowType == ACCUMULATED ? - wfCalculator->accumulatedFlowPrPseudoLength(brIdx): - wfCalculator->flowPrPseudoLength( brIdx)); - } - addStackedCurve("Total", depthValues, *accFlow, plotTrack); - } updateWellFlowPlotXAxisTitle(plotTrack); @@ -407,10 +389,20 @@ void RimWellAllocationPlot::addStackedCurve(const QString& tracerName, curve->setFlowValuesPrDepthValue(tracerName, depthValues, accFlow); if ( m_flowDiagSolution ) + { curve->setColor(m_flowDiagSolution->tracerColor(tracerName)); + } else - curve->setColor(cvf::Color3f::DARK_GRAY); - + { + cvf::Color3f color = cvf::Color3f::DARK_GRAY; + + if (tracerName == RIG_FLOW_OIL_NAME) color = cvf::Color3f::DARK_GREEN; + if (tracerName == RIG_FLOW_GAS_NAME) color = cvf::Color3f::DARK_RED; + if (tracerName == RIG_FLOW_WATER_NAME) color = cvf::Color3f::BLUE; + + curve->setColor(color); + } + plotTrack->addCurve(curve); curve->loadDataAndUpdate(); diff --git a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp index 1493a91208..98f662ebbf 100644 --- a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp @@ -46,6 +46,8 @@ size_t RigEclCellIndexCalculator::resultCellIndex(size_t gridIndex, size_t gridC /// //================================================================================================== +//#define USE_WELL_PHASE_RATES + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -93,8 +95,14 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto m_connectionFlowPrBranch.resize(m_pipeBranchesCellIds.size()); m_pseudoLengthFlowPrBranch.resize(m_pipeBranchesCellIds.size()); +#ifdef USE_WELL_PHASE_RATES + m_tracerNames.push_back(RIG_FLOW_OIL_NAME); + m_tracerNames.push_back(RIG_FLOW_GAS_NAME); + m_tracerNames.push_back(RIG_FLOW_WATER_NAME); +#else m_tracerNames.push_back(RIG_FLOW_TOTAL_NAME); - +#endif + calculateAccumulatedFlowPrConnection(0, 1); calculateFlowPrPseudoLength(0, 0.0); } @@ -107,13 +115,6 @@ const std::vector& RigAccWellFlowCalculator::connectionNumbersFromTop(si return m_connectionFlowPrBranch[branchIdx].depthValuesFromTop; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& RigAccWellFlowCalculator::accumulatedFlowPrConnection(size_t branchIdx) const -{ - return accumulatedTracerFlowPrConnection(RIG_FLOW_TOTAL_NAME, branchIdx); -} //-------------------------------------------------------------------------------------------------- /// @@ -133,13 +134,6 @@ const std::vector& RigAccWellFlowCalculator::accumulatedTracerFlowPrConn } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& RigAccWellFlowCalculator::flowPrConnection(size_t branchIdx) const -{ - return tracerFlowPrConnection(RIG_FLOW_TOTAL_NAME, branchIdx); -} //-------------------------------------------------------------------------------------------------- /// @@ -176,13 +170,6 @@ const std::vector& RigAccWellFlowCalculator::trueVerticalDepth(size_t br return m_pseudoLengthFlowPrBranch[branchIdx].trueVerticalDepth; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& RigAccWellFlowCalculator::accumulatedFlowPrPseudoLength(size_t branchIdx) const -{ - return accumulatedTracerFlowPrPseudoLength(RIG_FLOW_TOTAL_NAME, branchIdx); -} //-------------------------------------------------------------------------------------------------- /// @@ -202,13 +189,6 @@ const std::vector& RigAccWellFlowCalculator::accumulatedTracerFlowPrPseu } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& RigAccWellFlowCalculator::flowPrPseudoLength(size_t branchIdx) const -{ - return tracerFlowPrPseudoLength(RIG_FLOW_TOTAL_NAME, branchIdx); -} //-------------------------------------------------------------------------------------------------- /// @@ -273,7 +253,7 @@ std::vector > RigAccWellFlowCalculator::totalTracerFr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RigAccWellFlowCalculator::isWellFlowConsistent( bool isProducer) const +bool RigAccWellFlowCalculator::isWellFlowConsistent() const { bool isConsistent = true; for (const std::vector & branch : m_pipeBranchesCellIds) @@ -332,6 +312,8 @@ bool RigAccWellFlowCalculator::isConnectionFlowConsistent(const RigWellResultPoi //-------------------------------------------------------------------------------------------------- bool RigAccWellFlowCalculator::isFlowRateConsistent(double flowRate) const { + if (!m_tracerCellFractionValues) return true; // No flow diagnostics. + return (flowRate >= 0.0 && m_isProducer) || (flowRate <= 0.0 && !m_isProducer); } @@ -674,7 +656,13 @@ std::vector RigAccWellFlowCalculator::calculateWellCellFlowPrTracer(cons } else { + #ifdef USE_WELL_PHASE_RATES + flowPrTracer[0] = wellCell.oilRate(); + flowPrTracer[1] = wellCell.gasRate(); + flowPrTracer[2] = wellCell.waterRate(); + #else flowPrTracer[0] = wellCell.flowRate(); + #endif } return flowPrTracer; @@ -787,7 +775,7 @@ void RigAccWellFlowCalculator::groupSmallContributions() std::vector tracersToGroup; { - bool hasConsistentWellFlow = isWellFlowConsistent(m_isProducer); + bool hasConsistentWellFlow = isWellFlowConsistent(); std::vector > totalTracerFractions = this->totalTracerFractions(); diff --git a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h index 7ffee68554..ea7d3a6d9f 100644 --- a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h +++ b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h @@ -68,14 +68,11 @@ public: double smallContribThreshold); const std::vector& connectionNumbersFromTop(size_t branchIdx) const; - const std::vector& accumulatedFlowPrConnection( size_t branchIdx) const; const std::vector& accumulatedTracerFlowPrConnection(const QString& tracerName, size_t branchIdx) const; - const std::vector& flowPrConnection( size_t branchIdx) const; const std::vector& tracerFlowPrConnection(const QString& tracerName, size_t branchIdx) const; const std::vector& pseudoLengthFromTop(size_t branchIdx) const; const std::vector& trueVerticalDepth(size_t branchIdx) const; - const std::vector& accumulatedFlowPrPseudoLength( size_t branchIdx) const; const std::vector& accumulatedTracerFlowPrPseudoLength(const QString& tracerName, size_t branchIdx) const; const std::vector& flowPrPseudoLength( size_t branchIdx) const; const std::vector& tracerFlowPrPseudoLength(const QString& tracerName, size_t branchIdx) const; @@ -102,7 +99,7 @@ private: void groupSmallTracers(std::map >* branchFlowSet, const std::vector& tracersToGroup); - bool isWellFlowConsistent(bool isProducer) const; + bool isWellFlowConsistent() const; std::vector calculateAccumulatedFractions(const std::vector& accumulatedFlowPrTracer) const; std::vector wrpToUniqueWrpIndexFromBottom(const std::vector &branchCells) const; static size_t connectionIndexFromTop( const std::vector& resPointToConnectionIndexFromBottom, size_t clSegIdx) ; diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagResultAddress.h b/ApplicationCode/ReservoirDataModel/RigFlowDiagResultAddress.h index 00194712b2..7b0844988e 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagResultAddress.h +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagResultAddress.h @@ -26,6 +26,10 @@ #define RIG_FLD_COMMUNICATION_RESNAME "Communication" #define RIG_FLOW_TOTAL_NAME "Total" +#define RIG_FLOW_OIL_NAME "Oil" +#define RIG_FLOW_GAS_NAME "Gas" +#define RIG_FLOW_WATER_NAME "Water" + #define RIG_RESERVOIR_TRACER_NAME "Reservoir" #define RIG_TINY_TRACER_GROUP_NAME "Other" diff --git a/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h b/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h index 7a002a94f8..7d33fff0d6 100644 --- a/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h +++ b/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h @@ -40,7 +40,10 @@ struct RigWellResultPoint m_ertBranchId(-1), m_ertSegmentId(-1), m_bottomPosition(cvf::Vec3d::UNDEFINED), - m_flowRate(0.0) + m_flowRate(0.0), + m_oilRate(0.0), + m_gasRate(0.0), + m_waterRate(0.0) { } bool isPointValid() const @@ -70,6 +73,42 @@ struct RigWellResultPoint } } + double oilRate() const + { + if ( isCell() && m_isOpen) + { + return m_oilRate; + } + else + { + return 0.0; + } + } + + double gasRate() const + { + if ( isCell() && m_isOpen) + { + return m_gasRate; + } + else + { + return 0.0; + } + } + + double waterRate() const + { + if ( isCell() && m_isOpen) + { + return m_waterRate; + } + else + { + return 0.0; + } + } + bool isEqual(const RigWellResultPoint& other ) const { return ( m_gridIndex == other.m_gridIndex @@ -90,6 +129,9 @@ struct RigWellResultPoint cvf::Vec3d m_bottomPosition; //< The estimated bottom position of the well segment, when we have no grid cell connections for the segment. double m_flowRate; + double m_oilRate; + double m_gasRate; + double m_waterRate; }; //================================================================================================== From b113e813854c2093f4afe97fea8decec5e6bfdec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 20 Apr 2017 15:27:41 +0200 Subject: [PATCH 003/157] #1418 Hide the relative results options in GeoMech Result Definition Avoid decorating the Active Fomation Names with "_D" if relative results is enabled --- .../RimGeoMechResultDefinition.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.cpp index 6fe9f60be4..c7f1c50155 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechResultDefinition.cpp @@ -114,10 +114,13 @@ void RimGeoMechResultDefinition::defineUiOrdering(QString uiConfigName, caf::Pdm uiOrdering.add(&m_resultPositionTypeUiField); uiOrdering.add(&m_resultVariableUiField); - caf::PdmUiGroup * timeLapseGr = uiOrdering.addNewGroup("Relative Result Options"); - timeLapseGr->add(&m_isTimeLapseResultUiField); - if (m_isTimeLapseResultUiField()) - timeLapseGr->add(&m_timeLapseBaseTimestepUiField); + if ( m_resultPositionTypeUiField() != RIG_FORMATION_NAMES ) + { + caf::PdmUiGroup * timeLapseGr = uiOrdering.addNewGroup("Relative Result Options"); + timeLapseGr->add(&m_isTimeLapseResultUiField); + if ( m_isTimeLapseResultUiField() ) + timeLapseGr->add(&m_timeLapseBaseTimestepUiField); + } uiOrdering.skipRemainingFields(true); } @@ -137,7 +140,9 @@ QList RimGeoMechResultDefinition::calculateValueOptions( std::map > fieldCompNames = getResultMetaDataForUIFieldSetting(); QStringList uiVarNames; QStringList varNames; - getUiAndResultVariableStringList(&uiVarNames, &varNames, fieldCompNames, m_isTimeLapseResultUiField, m_timeLapseBaseTimestepUiField); + bool isNeedingTimeLapseStrings = m_isTimeLapseResultUiField() && (m_resultPositionTypeUiField() != RIG_FORMATION_NAMES); + + getUiAndResultVariableStringList(&uiVarNames, &varNames, fieldCompNames, isNeedingTimeLapseStrings, m_timeLapseBaseTimestepUiField); for (int oIdx = 0; oIdx < uiVarNames.size(); ++oIdx) { @@ -189,7 +194,8 @@ void RimGeoMechResultDefinition::fieldChangedByUi(const caf::PdmFieldHandle* cha std::map > fieldCompNames = getResultMetaDataForUIFieldSetting(); QStringList uiVarNames; QStringList varNames; - getUiAndResultVariableStringList(&uiVarNames, &varNames, fieldCompNames, m_isTimeLapseResultUiField, m_timeLapseBaseTimestepUiField); + bool isNeedingTimeLapseStrings = m_isTimeLapseResultUiField() && (m_resultPositionTypeUiField() != RIG_FORMATION_NAMES); + getUiAndResultVariableStringList(&uiVarNames, &varNames, fieldCompNames, isNeedingTimeLapseStrings, m_timeLapseBaseTimestepUiField); if (m_resultPositionTypeUiField() == m_resultPositionType() && m_isTimeLapseResultUiField() == m_isTimeLapseResult() From fdac0ea887b7d2de3b3f1ff35abdba9dc39b9bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 20 Apr 2017 16:21:48 +0200 Subject: [PATCH 004/157] #1419 Ensure property filters of categories are loaded properly from file The category list was not set properly in the propertyFilter base class when the project was loaded. The concept that list has to be set, and updated is fragile. --- .../ProjectDataModel/RimEclipsePropertyFilterCollection.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimEclipsePropertyFilterCollection.cpp b/ApplicationCode/ProjectDataModel/RimEclipsePropertyFilterCollection.cpp index 40d65b47d7..e2c976eab9 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipsePropertyFilterCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipsePropertyFilterCollection.cpp @@ -70,7 +70,10 @@ void RimEclipsePropertyFilterCollection::loadAndInitializePropertyFilters() for (size_t i = 0; i < propertyFilters.size(); i++) { RimEclipsePropertyFilter* propertyFilter = propertyFilters[i]; + propertyFilter->resultDefinition->setEclipseCase(reservoirView()->eclipseCase()); propertyFilter->initAfterRead(); + propertyFilter->resultDefinition->loadResult(); + propertyFilter->computeResultValueRange(); } } From 9d5fcaf5a19b91c742eaa9169cb5ac7b78242e96 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 20 Apr 2017 21:21:12 +0200 Subject: [PATCH 005/157] Regression tests : Add support for 'rsp' project file extension --- .../Application/RiaApplication.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 6e41ddc34b..275ce313d2 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -143,7 +143,7 @@ namespace RegTestNames const QString generatedFolderName = "RegTestGeneratedImages"; const QString diffFolderName = "RegTestDiffImages"; const QString baseFolderName = "RegTestBaseImages"; - const QString testProjectName = "RegressionTest.rip"; + const QString testProjectName = "RegressionTest"; const QString testFolderFilter = "TestCase*"; const QString imageCompareExeName = "compare"; const QString reportFileName = "ResInsightRegressionTestReport.html"; @@ -2336,9 +2336,22 @@ void RiaApplication::runRegressionTest(const QString& testRootPath) for (int dirIdx = 0; dirIdx < folderList.size(); ++dirIdx) { QDir testCaseFolder(folderList[dirIdx].filePath()); - if (testCaseFolder.exists(regTestProjectName)) + + QString projectFileName; + + if (testCaseFolder.exists(regTestProjectName + ".rip")) { - loadProject(testCaseFolder.filePath(regTestProjectName)); + projectFileName = regTestProjectName + ".rip"; + } + + if (testCaseFolder.exists(regTestProjectName + ".rsp")) + { + projectFileName = regTestProjectName + ".rsp"; + } + + if (!projectFileName.isEmpty()) + { + loadProject(testCaseFolder.filePath(projectFileName)); // Wait until all command objects have completed while (!m_commandQueueLock.tryLock()) From ed2010c0b769175b9da9a250d72aa824979124fb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 20 Apr 2017 22:34:15 +0200 Subject: [PATCH 006/157] Regression tests : Add basic timing with reporting by logging --- .../Application/RiaApplication.cpp | 78 ++++++++++++------- 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 275ce313d2..7547f93d1e 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -2259,6 +2259,18 @@ void removeDirectoryWithContent(QDir dirToDelete ) dirToDelete.rmdir("."); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void logInfoTextWithTimeInSeconds(const QTime& time, const QString& msg) +{ + double timeRunning = time.elapsed() / 1000.0; + + QString timeText = QString("(%1 s) ").arg(timeRunning, 0, 'f', 1); + + RiaLogging::info(timeText + msg); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -2315,6 +2327,11 @@ void RiaApplication::runRegressionTest(const QString& testRootPath) } } + QTime timeStamp; + timeStamp.start(); + + logInfoTextWithTimeInSeconds(timeStamp, "Starting regression tests\n"); + for (int dirIdx = 0; dirIdx < folderList.size(); ++dirIdx) { QDir testCaseFolder(folderList[dirIdx].filePath()); @@ -2351,44 +2368,51 @@ void RiaApplication::runRegressionTest(const QString& testRootPath) if (!projectFileName.isEmpty()) { - loadProject(testCaseFolder.filePath(projectFileName)); + logInfoTextWithTimeInSeconds(timeStamp, "Initializing test :" + testCaseFolder.absolutePath()); - // Wait until all command objects have completed - while (!m_commandQueueLock.tryLock()) - { - processEvents(); - } - m_commandQueueLock.unlock(); + loadProject(testCaseFolder.filePath(projectFileName)); - regressionTestConfigureProject(); + // Wait until all command objects have completed + while (!m_commandQueueLock.tryLock()) + { + processEvents(); + } + m_commandQueueLock.unlock(); - QString fullPathGeneratedFolder = testCaseFolder.absoluteFilePath(generatedFolderName); - saveSnapshotForAllViews(fullPathGeneratedFolder); + regressionTestConfigureProject(); - RicSnapshotAllPlotsToFileFeature::exportSnapshotOfAllPlotsIntoFolder(fullPathGeneratedFolder); + QString fullPathGeneratedFolder = testCaseFolder.absoluteFilePath(generatedFolderName); + saveSnapshotForAllViews(fullPathGeneratedFolder); - QDir baseDir(testCaseFolder.filePath(baseFolderName)); - QDir genDir(testCaseFolder.filePath(generatedFolderName)); - QDir diffDir(testCaseFolder.filePath(diffFolderName)); - if (!diffDir.exists()) testCaseFolder.mkdir(diffFolderName); - baseDir.setFilter(QDir::Files); - QStringList baseImageFileNames = baseDir.entryList(); + RicSnapshotAllPlotsToFileFeature::exportSnapshotOfAllPlotsIntoFolder(fullPathGeneratedFolder); - for (int fIdx = 0; fIdx < baseImageFileNames.size(); ++fIdx) - { - QString fileName = baseImageFileNames[fIdx]; - RiaImageFileCompare imgComparator(RegTestNames::imageCompareExeName); - bool ok = imgComparator.runComparison(genDir.filePath(fileName), baseDir.filePath(fileName), diffDir.filePath(fileName)); - if (!ok) - { + QDir baseDir(testCaseFolder.filePath(baseFolderName)); + QDir genDir(testCaseFolder.filePath(generatedFolderName)); + QDir diffDir(testCaseFolder.filePath(diffFolderName)); + if (!diffDir.exists()) testCaseFolder.mkdir(diffFolderName); + baseDir.setFilter(QDir::Files); + QStringList baseImageFileNames = baseDir.entryList(); + + for (int fIdx = 0; fIdx < baseImageFileNames.size(); ++fIdx) + { + QString fileName = baseImageFileNames[fIdx]; + RiaImageFileCompare imgComparator(RegTestNames::imageCompareExeName); + bool ok = imgComparator.runComparison(genDir.filePath(fileName), baseDir.filePath(fileName), diffDir.filePath(fileName)); + if (!ok) + { qDebug() << "Error comparing :" << imgComparator.errorMessage() << "\n" << imgComparator.errorDetails(); - } - } + } + } - closeProject(); + closeProject(); + + logInfoTextWithTimeInSeconds(timeStamp, "Completed test :" + testCaseFolder.absolutePath()); } } + RiaLogging::info("\n"); + logInfoTextWithTimeInSeconds(timeStamp, "Completed regression tests"); + m_runningRegressionTests = false; } From 029809bf90a24686e7ed73eb295bee0740da88aa Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 21 Apr 2017 09:17:55 +0200 Subject: [PATCH 007/157] Upped to version 2016.11.flow.13 --- ResInsightVersion.cmake | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index a1bc942c82..03735e9f7f 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -1,7 +1,7 @@ set(RESINSIGHT_MAJOR_VERSION 2016) set(RESINSIGHT_MINOR_VERSION 11) -set(RESINSIGHT_INCREMENT_VERSION "flow.12") +set(RESINSIGHT_INCREMENT_VERSION "flow.13") # https://github.com/CRAVA/crava/tree/master/libs/nrlib @@ -10,12 +10,14 @@ set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") # https://github.com/Ensembles/ert set(ERT_GITHUB_SHA "e2a5a9cc20705537d07822958d925e092a323367") -set(OPM_COMMON_GITHUB_SHA "1216bc052542f24ec6fcfbe1947d52e6300ff754") -set(OPM_PARSER_GITHUB_SHA "a3496df501a4369fd827fbf0ff893d03deff425f") - +# https://github.com/OPM/opm-flowdiagnostics set(OPM_FLOWDIAGNOSTICS_SHA "a14dc4ba1302bcc1e0aeb35c5de6b4bd39bce98") + +# https://github.com/OPM/opm-flowdiagnostics-applications set(OPM_FLOWDIAGNOSTICS_APPLICATIONS_SHA "afd3f6c454f52dcfa0a6aa96be9823176a6daa48") +# https://github.com/OPM/opm-parser/blob/master/opm/parser/eclipse/Units/Units.hpp +# This file was moved from opm-core to opm-parser october 2016 # sha for Units.hpp 9a679071dd0066236154852c39a9e0b3c3ac4873 set(STRPRODUCTVER ${RESINSIGHT_MAJOR_VERSION}.${RESINSIGHT_MINOR_VERSION}.${RESINSIGHT_INCREMENT_VERSION}) From 201ff5699d1783bf0a7d6bd1718c78b2eda50ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Fri, 21 Apr 2017 12:02:48 +0200 Subject: [PATCH 008/157] #1004 Add reload function to eclipse cases to reload all data from file --- .../Commands/CMakeLists_files.cmake | 4 ++ .../Commands/RicReloadCaseFeature.cpp | 69 +++++++++++++++++++ .../Commands/RicReloadCaseFeature.h | 32 +++++++++ .../RimContextCommandBuilder.cpp | 1 + .../ProjectDataModel/RimEclipseCase.cpp | 66 +++++++++--------- .../ProjectDataModel/RimEclipseCase.h | 3 + .../ProjectDataModel/RimEclipseInputCase.cpp | 9 +++ .../ProjectDataModel/RimEclipseInputCase.h | 1 + .../ProjectDataModel/RimEclipseResultCase.cpp | 10 +++ .../ProjectDataModel/RimEclipseResultCase.h | 1 + .../RimEclipseStatisticsCase.cpp | 9 +++ .../RimEclipseStatisticsCase.h | 1 + 12 files changed, 172 insertions(+), 34 deletions(-) create mode 100644 ApplicationCode/Commands/RicReloadCaseFeature.cpp create mode 100644 ApplicationCode/Commands/RicReloadCaseFeature.h diff --git a/ApplicationCode/Commands/CMakeLists_files.cmake b/ApplicationCode/Commands/CMakeLists_files.cmake index 04a024ff4b..806e5bc397 100644 --- a/ApplicationCode/Commands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/CMakeLists_files.cmake @@ -45,6 +45,8 @@ ${CEE_CURRENT_LIST_DIR}RicDeleteItemFeature.h ${CEE_CURRENT_LIST_DIR}RicDeleteSubItemsFeature.h ${CEE_CURRENT_LIST_DIR}RicCommandFeature.h + +${CEE_CURRENT_LIST_DIR}RicReloadCaseFeature.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -83,6 +85,8 @@ ${CEE_CURRENT_LIST_DIR}RicDeleteItemExecData.cpp ${CEE_CURRENT_LIST_DIR}RicDeleteItemFeature.cpp ${CEE_CURRENT_LIST_DIR}RicDeleteSubItemsFeature.cpp + +${CEE_CURRENT_LIST_DIR}RicReloadCaseFeature.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Commands/RicReloadCaseFeature.cpp b/ApplicationCode/Commands/RicReloadCaseFeature.cpp new file mode 100644 index 0000000000..63470c4a23 --- /dev/null +++ b/ApplicationCode/Commands/RicReloadCaseFeature.cpp @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicReloadCaseFeature.h" + +#include "RimEclipseCase.h" + +#include "cafPdmObject.h" +#include "cafSelectionManager.h" + +#include + +CAF_CMD_SOURCE_INIT(RicReloadCaseFeature, "RicReloadCaseFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicReloadCaseFeature::isCommandEnabled() +{ + std::vector selectedFormationNamesCollObjs; + caf::SelectionManager::instance()->objectsByType(&selectedFormationNamesCollObjs); + for (caf::PdmObject* pdmObject : selectedFormationNamesCollObjs) { + if (dynamic_cast(pdmObject)) + { + return true; + } + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicReloadCaseFeature::onActionTriggered(bool isChecked) +{ + std::vector selectedEclipseCases; + caf::SelectionManager::instance()->objectsByType(&selectedEclipseCases); + + for (RimEclipseCase* selectedCase : selectedEclipseCases) + { + selectedCase->releaseResultData(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicReloadCaseFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("Reload"); + actionToSetup->setIcon(QIcon(":/Refresh-32.png")); +} diff --git a/ApplicationCode/Commands/RicReloadCaseFeature.h b/ApplicationCode/Commands/RicReloadCaseFeature.h new file mode 100644 index 0000000000..95bf4b7752 --- /dev/null +++ b/ApplicationCode/Commands/RicReloadCaseFeature.h @@ -0,0 +1,32 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +class RicReloadCaseFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + virtual bool isCommandEnabled(); + virtual void onActionTriggered(bool isChecked); + virtual void setupActionLook(QAction* actionToSetup); +}; diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index f506b0f14f..834191df57 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -407,6 +407,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection() } else if (dynamic_cast(uiItem)) { + commandIds << "RicReloadCaseFeature"; commandIds << "RicExecuteScriptForCasesFeature"; } else if (dynamic_cast(uiItem)) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp index a3915c08bb..3d919e0324 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp @@ -297,40 +297,7 @@ void RimEclipseCase::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c { if (changedField == &releaseResultMemory) { - if (this->eclipseCaseData()) - { - for (size_t i = 0; i < reservoirViews().size(); i++) - { - RimEclipseView* reservoirView = reservoirViews()[i]; - CVF_ASSERT(reservoirView); - - RimEclipseCellColors* result = reservoirView->cellResult; - CVF_ASSERT(result); - - result->setResultVariable(RimDefines::undefinedResultName()); - result->loadResult(); - - RimCellEdgeColors* cellEdgeResult = reservoirView->cellEdgeResult; - CVF_ASSERT(cellEdgeResult); - - cellEdgeResult->setResultVariable(RimDefines::undefinedResultName()); - cellEdgeResult->loadResult(); - - reservoirView->createDisplayModelAndRedraw(); - } - - RigCaseCellResultsData* matrixModelResults = eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS); - if (matrixModelResults) - { - matrixModelResults->clearAllResults(); - } - - RigCaseCellResultsData* fractureModelResults = eclipseCaseData()->results(RifReaderInterface::FRACTURE_RESULTS); - if (fractureModelResults) - { - fractureModelResults->clearAllResults(); - } - } + releaseResultData(); releaseResultMemory = oldValue.toBool(); } @@ -664,6 +631,37 @@ QString RimEclipseCase::timeStepName(int frameIdx) return date.toString(m_timeStepFormatString); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseCase::releaseResultData() +{ + if (this->eclipseCaseData()) + { + RigCaseCellResultsData* matrixModelResults = eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS); + if (matrixModelResults) + { + matrixModelResults->clearAllResults(); + } + + RigCaseCellResultsData* fractureModelResults = eclipseCaseData()->results(RifReaderInterface::FRACTURE_RESULTS); + if (fractureModelResults) + { + fractureModelResults->clearAllResults(); + + } + + reloadEclipseGridFile(); + + for (size_t i = 0; i < reservoirViews().size(); i++) + { + RimEclipseView* reservoirView = reservoirViews()[i]; + CVF_ASSERT(reservoirView); + reservoirView->loadDataAndUpdate(); + } + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimEclipseCase.h b/ApplicationCode/ProjectDataModel/RimEclipseCase.h index e6060f8f64..0531451a0a 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseCase.h +++ b/ApplicationCode/ProjectDataModel/RimEclipseCase.h @@ -95,6 +95,9 @@ public: virtual cvf::BoundingBox allCellsBoundingBox() const; virtual cvf::Vec3d displayModelOffset() const; + void releaseResultData(); + virtual void reloadEclipseGridFile() = 0; + // Overridden methods from PdmObject public: diff --git a/ApplicationCode/ProjectDataModel/RimEclipseInputCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseInputCase.cpp index f84bd630cb..edf2842f37 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseInputCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseInputCase.cpp @@ -228,6 +228,15 @@ bool RimEclipseInputCase::openEclipseGridFile() return true; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseInputCase::reloadEclipseGridFile() +{ + setReservoirData(nullptr); + openEclipseGridFile(); +} + #define for_all(stdVector, indexName) for (size_t indexName = 0; indexName < stdVector.size(); ++indexName) //-------------------------------------------------------------------------------------------------- /// Loads input property data from the gridFile and additional files diff --git a/ApplicationCode/ProjectDataModel/RimEclipseInputCase.h b/ApplicationCode/ProjectDataModel/RimEclipseInputCase.h index 6be893714d..73d286284b 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseInputCase.h +++ b/ApplicationCode/ProjectDataModel/RimEclipseInputCase.h @@ -53,6 +53,7 @@ public: // RimCase overrides virtual bool openEclipseGridFile(); // Find grid file among file set. Read, Find read and validate property date. Syncronize child property sets. + virtual void reloadEclipseGridFile(); // Overrides from RimCase virtual QString locationOnDisc() const; diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp index cadcfabb64..9aebabc9fb 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp @@ -148,6 +148,16 @@ bool RimEclipseResultCase::openEclipseGridFile() return true; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseResultCase::reloadEclipseGridFile() +{ + m_gridAndWellDataIsReadFromFile = false; + m_activeCellInfoIsReadFromFile = false; + openEclipseGridFile(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.h b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.h index 35243183b2..b55640cbee 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.h +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.h @@ -44,6 +44,7 @@ public: void setCaseInfo(const QString& userDescription, const QString& caseFileName); virtual bool openEclipseGridFile(); + virtual void reloadEclipseGridFile(); bool openAndReadActiveCellData(RigEclipseCaseData* mainEclipseCase); void readGridDimensions(std::vector< std::vector >& gridDimensions); diff --git a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp index 4730387c9d..a34dad5f4f 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp @@ -174,6 +174,15 @@ bool RimEclipseStatisticsCase::openEclipseGridFile() return true; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseStatisticsCase::reloadEclipseGridFile() +{ + setReservoirData(nullptr); + openEclipseGridFile(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.h b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.h index 0a2af3edf6..9dd9d434b0 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.h +++ b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.h @@ -61,6 +61,7 @@ public: void updateConnectedEditorsAndReservoirViews(); virtual bool openEclipseGridFile(); + virtual void reloadEclipseGridFile(); RimCaseCollection* parentStatisticsCaseCollection(); From 813652477d135ed4283914156d964e5f7e83c724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Fri, 21 Apr 2017 16:05:25 +0200 Subject: [PATCH 009/157] #1001 Reload all plots when a case is reloaded --- .../Flow/RimWellAllocationPlot.h | 2 +- .../ProjectDataModel/RimEclipseCase.cpp | 36 +++++++++++++++++++ .../ProjectDataModel/RimEclipseInputCase.cpp | 2 +- .../ProjectDataModel/RimEclipseResultCase.cpp | 3 +- .../RimEclipseStatisticsCase.cpp | 2 +- .../ProjectDataModel/Summary/RimSummaryPlot.h | 2 +- 6 files changed, 42 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h index 0015a4ecfd..ccb401c3d2 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h @@ -61,7 +61,7 @@ public: void setDescription(const QString& description); QString description() const; - void loadDataAndUpdate(); + virtual void loadDataAndUpdate() override; virtual QWidget* viewWidget() override; virtual void zoomAll() override; diff --git a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp index 3d919e0324..371d1a8ddd 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp @@ -42,6 +42,12 @@ #include "RimProject.h" #include "RimMainPlotCollection.h" #include "RimWellLogPlotCollection.h" +#include "RimSummaryPlotCollection.h" +#include "RimFlowPlotCollection.h" +#include "RimWellLogPlot.h" +#include "RimSummaryPlot.h" +#include "RimFlowCharacteristicsPlot.h" +#include "RimWellAllocationPlot.h" #include "cafPdmDocument.h" #include "cafProgressInfo.h" @@ -659,6 +665,36 @@ void RimEclipseCase::releaseResultData() CVF_ASSERT(reservoirView); reservoirView->loadDataAndUpdate(); } + + RimProject* project = RiaApplication::instance()->project(); + if (project) + { + if (project->mainPlotCollection()) + { + RimWellLogPlotCollection* wellPlotCollection = project->mainPlotCollection()->wellLogPlotCollection(); + RimSummaryPlotCollection* summaryPlotCollection = project->mainPlotCollection()->summaryPlotCollection(); + RimFlowPlotCollection* flowPlotCollection = project->mainPlotCollection()->flowPlotCollection(); + + if (wellPlotCollection) + { + for (size_t i = 0; i < wellPlotCollection->wellLogPlots().size(); ++i) + { + wellPlotCollection->wellLogPlots()[i]->loadDataAndUpdate(); + } + } + if (summaryPlotCollection) + { + for (size_t i = 0; i < summaryPlotCollection->summaryPlots().size(); ++i) + { + summaryPlotCollection->summaryPlots()[i]->loadDataAndUpdate(); + } + } + if (flowPlotCollection) + { + flowPlotCollection->loadDataAndUpdate(); + } + } + } } } diff --git a/ApplicationCode/ProjectDataModel/RimEclipseInputCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseInputCase.cpp index edf2842f37..98700b1092 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseInputCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseInputCase.cpp @@ -234,7 +234,7 @@ bool RimEclipseInputCase::openEclipseGridFile() void RimEclipseInputCase::reloadEclipseGridFile() { setReservoirData(nullptr); - openEclipseGridFile(); + openReserviorCase(); } #define for_all(stdVector, indexName) for (size_t indexName = 0; indexName < stdVector.size(); ++indexName) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp index 9aebabc9fb..3bf93c0448 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp @@ -155,7 +155,8 @@ void RimEclipseResultCase::reloadEclipseGridFile() { m_gridAndWellDataIsReadFromFile = false; m_activeCellInfoIsReadFromFile = false; - openEclipseGridFile(); + setReservoirData(nullptr); + openReserviorCase(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp index a34dad5f4f..4e4c402dd7 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp @@ -180,7 +180,7 @@ bool RimEclipseStatisticsCase::openEclipseGridFile() void RimEclipseStatisticsCase::reloadEclipseGridFile() { setReservoirData(nullptr); - openEclipseGridFile(); + openReserviorCase(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h index fc7d9c2478..186ef8881c 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h @@ -64,7 +64,7 @@ public: caf::PdmObject* findRimCurveFromQwtCurve(const QwtPlotCurve* curve) const; size_t curveCount() const; - void loadDataAndUpdate(); + virtual void loadDataAndUpdate() override; void detachAllCurves(); void updateCaseNameHasChanged(); From 117126bce2e7eb2a895cd94bb9e79d066963e316 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 24 Apr 2017 09:23:32 +0200 Subject: [PATCH 010/157] #1384 Regression Test : Add static method for default widget size --- ApplicationCode/Application/RiaApplication.cpp | 10 +++++++++- ApplicationCode/Application/RiaApplication.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 7547f93d1e..fde2ee8733 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -2845,8 +2845,16 @@ void RiaApplication::regressionTestConfigureProject() } // This size is set to match the regression test reference images - riv->viewer()->setFixedSize(1000, 745); + riv->viewer()->setFixedSize(RiaApplication::regressionDefaultImageSize()); } } } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize RiaApplication::regressionDefaultImageSize() +{ + return QSize(1000, 745); +} diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 229883247c..915208e3cc 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -215,6 +215,7 @@ private: void storeTreeViewState(); + static QSize regressionDefaultImageSize(); private slots: void slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void slotUpdateScheduledDisplayModels(); From c75a79a260f29e45d9534d2abb09ab46c2e2e4e8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 24 Apr 2017 09:24:34 +0200 Subject: [PATCH 011/157] #1384 Make regression functions tests private --- ApplicationCode/Application/RiaApplication.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 915208e3cc..6fe2a450e4 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -137,8 +137,6 @@ public: void saveSnapshotForAllViews(const QString& snapshotFolderName); void runMultiCaseSnapshots(const QString& templateProjectFileName, std::vector gridFileNames, const QString& snapshotFolderName); void runRegressionTest(const QString& testRootPath); - void updateRegressionTest(const QString& testRootPath ); - void regressionTestConfigureProject(); void processNonGuiEvents(); @@ -215,6 +213,8 @@ private: void storeTreeViewState(); + void updateRegressionTest(const QString& testRootPath); + void regressionTestConfigureProject(); static QSize regressionDefaultImageSize(); private slots: void slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); From c23ac3c8aec1efb7485555336f0977630d2e691b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 24 Apr 2017 09:39:54 +0200 Subject: [PATCH 012/157] #1384 Regression test : Add resize of plot windows --- .../Application/RiaApplication.cpp | 33 ++++++++++++++++++- ApplicationCode/Application/RiaApplication.h | 2 ++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index fde2ee8733..65dac59957 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -2381,6 +2381,8 @@ void RiaApplication::runRegressionTest(const QString& testRootPath) regressionTestConfigureProject(); + resizeMaximizedPlotWindows(); + QString fullPathGeneratedFolder = testCaseFolder.absoluteFilePath(generatedFolderName); saveSnapshotForAllViews(fullPathGeneratedFolder); @@ -2416,6 +2418,36 @@ void RiaApplication::runRegressionTest(const QString& testRootPath) m_runningRegressionTests = false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::resizeMaximizedPlotWindows() +{ + std::vector viewWindows; + for (auto viewWindow : viewWindows) + { + if (viewWindow->isMdiWindow()) + { + RimMdiWindowGeometry wndGeo = viewWindow->mdiWindowGeometry(); + if (wndGeo.isMaximized) + { + QWidget* viewWidget = viewWindow->viewWidget(); + + if (viewWidget) + { + QMdiSubWindow* mdiWindow = m_mainPlotWindow->findMdiSubWindow(viewWidget); + if (mdiWindow) + { + mdiWindow->showNormal(); + + viewWidget->resize(RiaApplication::regressionDefaultImageSize()); + } + } + } + } + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -2810,7 +2842,6 @@ void RiaApplication::executeRegressionTests(const QString& regressionTestPath) } } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 6fe2a450e4..79de925275 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -213,9 +213,11 @@ private: void storeTreeViewState(); + void resizeMaximizedPlotWindows(); void updateRegressionTest(const QString& testRootPath); void regressionTestConfigureProject(); static QSize regressionDefaultImageSize(); + private slots: void slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void slotUpdateScheduledDisplayModels(); From 009218e3ecf98c49b54b78d1de8f303d09d62102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 24 Apr 2017 09:52:28 +0200 Subject: [PATCH 013/157] #1422 WLP: Set case and flow diag solution in resultDefinition when switching case in gui. Use the case from the result definition instead of wrong search when updating default flow solution --- .../RimEclipseResultDefinition.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index 084ea432e8..8f96a08926 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -137,6 +137,8 @@ void RimEclipseResultDefinition::simpleCopy(const RimEclipseResultDefinition* ot void RimEclipseResultDefinition::setEclipseCase(RimEclipseCase* eclipseCase) { m_eclipseCase = eclipseCase; + + assignFlowSolutionFromCase(); } @@ -323,16 +325,15 @@ void RimEclipseResultDefinition::setTofAndSelectTracer(const QString& tracerName //-------------------------------------------------------------------------------------------------- void RimEclipseResultDefinition::assignFlowSolutionFromCase() { - RimEclipseResultCase* eclCase = nullptr; - this->firstAncestorOrThisOfType(eclCase); + RimFlowDiagSolution* defaultFlowDiagSolution = nullptr; + + RimEclipseResultCase* eclCase = dynamic_cast(m_eclipseCase.p()); + if (eclCase) { - RimFlowDiagSolution* defaultFlowDiagSolution = eclCase->defaultFlowDiagSolution(); - if (defaultFlowDiagSolution) - { - this->setFlowSolution(defaultFlowDiagSolution); - } + defaultFlowDiagSolution = eclCase->defaultFlowDiagSolution(); } + this->setFlowSolution(defaultFlowDiagSolution); } //-------------------------------------------------------------------------------------------------- @@ -464,8 +465,7 @@ QList RimEclipseResultDefinition::calculateValueOptions( } else if (fieldNeedingOptions == &m_flowSolutionUiField) { - RimEclipseResultCase* eclCase; - this->firstAncestorOrThisOfType(eclCase); + RimEclipseResultCase* eclCase = dynamic_cast(m_eclipseCase.p()); if (eclCase) { std::vector flowSols = eclCase->flowDiagSolutions(); From 07b95da98fe7f4f8334ff48f64a8e61a3b127eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 24 Apr 2017 11:23:28 +0200 Subject: [PATCH 014/157] Show Plot Data: Add "Data" to "Show Total Allocation" --- .../Commands/FlowCommands/RicShowTotalAllocationDataFeature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/FlowCommands/RicShowTotalAllocationDataFeature.cpp b/ApplicationCode/Commands/FlowCommands/RicShowTotalAllocationDataFeature.cpp index 3a862f488d..37a77bb1a0 100644 --- a/ApplicationCode/Commands/FlowCommands/RicShowTotalAllocationDataFeature.cpp +++ b/ApplicationCode/Commands/FlowCommands/RicShowTotalAllocationDataFeature.cpp @@ -76,7 +76,7 @@ void RicShowTotalAllocationDataFeature::onActionTriggered(bool isChecked) //-------------------------------------------------------------------------------------------------- void RicShowTotalAllocationDataFeature::setupActionLook(QAction* actionToSetup) { - actionToSetup->setText("Show Total Allocation"); + actionToSetup->setText("Show Total Allocation Data"); //actionToSetup->setIcon(QIcon(":/PlotWindow24x24.png")); } From 274a108235587742693f8f45ab3a9db56e185df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Mon, 24 Apr 2017 11:20:02 +0200 Subject: [PATCH 015/157] #1429 Fix issue with curve colors and symbols for all cases being the same --- .../Summary/RimSummaryCurveAppearanceCalculator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp index 6e8213b440..cd6ce06d03 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveAppearanceCalculator.cpp @@ -150,7 +150,7 @@ void RimSummaryCurveAppearanceCalculator::updateApperanceIndices() int idx = 0; for (auto& pair : m_caseToAppearanceIdxMap) { - pair.second = static_cast(caseAppearanceIndices[pair.first->caseName().toUtf8().constData()]); + pair.second = static_cast(caseAppearanceIndices[pair.first->summaryHeaderFilename().toUtf8().constData()]); } } { From 05fb8b8da35ca4919022dbb3f93b3acddb09e78d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Mon, 24 Apr 2017 12:04:49 +0200 Subject: [PATCH 016/157] Better naming of eclipse reload data function --- ApplicationCode/Commands/RicReloadCaseFeature.cpp | 2 +- ApplicationCode/ProjectDataModel/RimEclipseCase.cpp | 5 ++--- ApplicationCode/ProjectDataModel/RimEclipseCase.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/Commands/RicReloadCaseFeature.cpp b/ApplicationCode/Commands/RicReloadCaseFeature.cpp index 63470c4a23..7519b4c719 100644 --- a/ApplicationCode/Commands/RicReloadCaseFeature.cpp +++ b/ApplicationCode/Commands/RicReloadCaseFeature.cpp @@ -55,7 +55,7 @@ void RicReloadCaseFeature::onActionTriggered(bool isChecked) for (RimEclipseCase* selectedCase : selectedEclipseCases) { - selectedCase->releaseResultData(); + selectedCase->reloadDataAndUpdate(); } } diff --git a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp index 371d1a8ddd..b800d32ea3 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp @@ -303,7 +303,7 @@ void RimEclipseCase::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c { if (changedField == &releaseResultMemory) { - releaseResultData(); + reloadDataAndUpdate(); releaseResultMemory = oldValue.toBool(); } @@ -640,7 +640,7 @@ QString RimEclipseCase::timeStepName(int frameIdx) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimEclipseCase::releaseResultData() +void RimEclipseCase::reloadDataAndUpdate() { if (this->eclipseCaseData()) { @@ -654,7 +654,6 @@ void RimEclipseCase::releaseResultData() if (fractureModelResults) { fractureModelResults->clearAllResults(); - } reloadEclipseGridFile(); diff --git a/ApplicationCode/ProjectDataModel/RimEclipseCase.h b/ApplicationCode/ProjectDataModel/RimEclipseCase.h index 0531451a0a..81cf3f1b46 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseCase.h +++ b/ApplicationCode/ProjectDataModel/RimEclipseCase.h @@ -95,7 +95,7 @@ public: virtual cvf::BoundingBox allCellsBoundingBox() const; virtual cvf::Vec3d displayModelOffset() const; - void releaseResultData(); + void reloadDataAndUpdate(); virtual void reloadEclipseGridFile() = 0; // Overridden methods from PdmObject From 938c8ff69abd90ca2492df47bde7e567a031bc1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 24 Apr 2017 14:41:33 +0200 Subject: [PATCH 017/157] Update opm-flowdiagnostics-application to include handling of new Ert --- ResInsightVersion.cmake | 2 +- .../CMakeLists.txt | 29 +++++++++++++++++++ .../opm/utility/ECLResultData.cpp | 22 ++++++++++++-- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 03735e9f7f..3d40216e55 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -14,7 +14,7 @@ set(ERT_GITHUB_SHA "e2a5a9cc20705537d07822958d925e092a323367") set(OPM_FLOWDIAGNOSTICS_SHA "a14dc4ba1302bcc1e0aeb35c5de6b4bd39bce98") # https://github.com/OPM/opm-flowdiagnostics-applications -set(OPM_FLOWDIAGNOSTICS_APPLICATIONS_SHA "afd3f6c454f52dcfa0a6aa96be9823176a6daa48") +set(OPM_FLOWDIAGNOSTICS_APPLICATIONS_SHA "1b521494ce9c09a1286dd0a81a1333caa123c680") # https://github.com/OPM/opm-parser/blob/master/opm/parser/eclipse/Units/Units.hpp # This file was moved from opm-core to opm-parser october 2016 diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/CMakeLists.txt b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/CMakeLists.txt index 482918b86e..a34a4a9b59 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/CMakeLists.txt +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/CMakeLists.txt @@ -73,6 +73,35 @@ include (${project}-prereqs) include (CMakeLists_files.cmake) macro (config_hook) + if (NOT ERT_FOUND) + set (HAVE_ERT_ECL_TYPE_H 0) + else () + # ERT_FOUND + cmake_push_check_state () + + set (CMAKE_REQUIRED_INCLUDES ${ERT_INCLUDE_DIR}) + set (CMAKE_REQUIRED_LIBRARIES ${ERT_LIBRARIES}) + + check_cxx_source_compiles ( +" +#include + +#include +#include + +int main () +{ + ecl_kw_type* kw = nullptr; + + std::cout << ecl_type_get_type(ecl_kw_get_data_type(kw)) << std::endl; +} +" + HAVE_ERT_ECL_TYPE_H) + + cmake_pop_check_state () + endif () + + list (APPEND "${project}_CONFIG_VARS" HAVE_ERT_ECL_TYPE_H) endmacro (config_hook) macro (prereqs_hook) diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.cpp index 21174ee78e..9677d7b180 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.cpp @@ -46,11 +46,27 @@ #include #include +#if defined(HAVE_ERT_ECL_TYPE_H) && HAVE_ERT_ECL_TYPE_H +#include +#endif // defined(HAVE_ERT_ECL_TYPE_H) && HAVE_ERT_ECL_TYPE_H + /// \file /// /// Implementation of ECL Result-Set Interface. namespace { + inline ecl_type_enum + getKeywordElementType(const ecl_kw_type* kw) + { +#if defined(HAVE_ERT_ECL_TYPE_H) && HAVE_ERT_ECL_TYPE_H + return ecl_type_get_type(ecl_kw_get_data_type(kw)); + +#else // ! (defined(HAVE_ERT_ECL_TYPE_H) && HAVE_ERT_ECL_TYPE_H) + + return ecl_kw_get_type(kw); +#endif // defined(HAVE_ERT_ECL_TYPE_H) && HAVE_ERT_ECL_TYPE_H + } + namespace ECLImpl { using FilePtr = ::ERT::ert_unique_ptr; @@ -294,7 +310,7 @@ namespace { static std::vector as(const ecl_kw_type* kw, std::false_type) { - assert (ecl_kw_get_type(kw) == Input); + assert (getKeywordElementType(kw) == Input); return Details::getData< T, typename Details::ElementType::type @@ -352,7 +368,7 @@ namespace { static std::vector as(const ecl_kw_type* kw, std::true_type) { - assert (ecl_kw_get_type(kw) == ECL_CHAR_TYPE); + assert (getKeywordElementType(kw) == ECL_CHAR_TYPE); auto result = std::vector{}; result.reserve(ecl_kw_get_size(kw)); @@ -758,7 +774,7 @@ namespace Opm { const auto makeStringVector = typename std::is_same::type{}; - switch (ecl_kw_get_type(kw)) { + switch (getKeywordElementType(kw)) { case ECL_CHAR_TYPE: return ECLImpl::GetKeywordData:: as(kw, makeStringVector); From 50d9904cf7f6bec038b20fda81bbc20b1d25f4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Mon, 24 Apr 2017 16:42:01 +0200 Subject: [PATCH 018/157] #1006 Add support for toggling legend and don't show legend for curves without a name --- .../RimGridTimeHistoryCurve.cpp | 1 + .../ProjectDataModel/RimPlotCurve.cpp | 41 +++++++++++++++++++ .../ProjectDataModel/RimPlotCurve.h | 4 ++ .../Summary/RimSummaryCurve.cpp | 1 + .../Summary/RimSummaryCurveFilter.cpp | 9 ++++ .../Summary/RimSummaryCurveFilter.h | 1 + .../Summary/RimSummaryPlot.cpp | 36 +++++++++++++++- .../ProjectDataModel/Summary/RimSummaryPlot.h | 2 + 8 files changed, 94 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp b/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp index f05a9dcf19..ba42a7f85f 100644 --- a/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp @@ -428,6 +428,7 @@ void RimGridTimeHistoryCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiO } uiOrdering.add(&m_plotAxis); + uiOrdering.add(&m_showLegend); caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance"); RimPlotCurve::appearanceUiOrdering(*appearanceGroup); diff --git a/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp b/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp index af9d01e787..8e836719de 100644 --- a/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp @@ -90,6 +90,8 @@ RimPlotCurve::RimPlotCurve() CAF_PDM_InitField(&m_symbolSkipPixelDistance, "SymbolSkipPxDist", 0.0f, "Symbol Skip Distance", "", "Minimum pixel distance between symbols", ""); + CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Show Legend", "", "", ""); + m_qwtPlotCurve = new RiuLineSegmentQwtPlotCurve; m_parentQwtPlot = NULL; @@ -139,6 +141,10 @@ void RimPlotCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField, con updateCurveName(); } + else if (changedField == &m_showLegend) + { + updateLegendVisibility(); + } if (m_parentQwtPlot) m_parentQwtPlot->replot(); } @@ -255,6 +261,7 @@ void RimPlotCurve::updateCurveName() } m_qwtPlotCurve->setTitle(m_curveName); + updateLegendVisibility(); } //-------------------------------------------------------------------------------------------------- @@ -420,3 +427,37 @@ void RimPlotCurve::setLineThickness(int thickness) m_curveThickness = thickness; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotCurve::showLegend(bool show) +{ + m_showLegend = show; + updateLegendVisibility(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotCurve::updateLegendVisibility() +{ + if (m_showLegend()) { + if (m_curveName().isEmpty()) + { + m_qwtPlotCurve->setItemAttribute(QwtPlotItem::Legend, false); + } + else + { + m_qwtPlotCurve->setItemAttribute(QwtPlotItem::Legend, true); + } + } + else + { + m_qwtPlotCurve->setItemAttribute(QwtPlotItem::Legend, false); + } + + if (m_parentQwtPlot != nullptr) + { + m_parentQwtPlot->updateLegend(); + } +} diff --git a/ApplicationCode/ProjectDataModel/RimPlotCurve.h b/ApplicationCode/ProjectDataModel/RimPlotCurve.h index f199262c2b..f6f3cd802f 100644 --- a/ApplicationCode/ProjectDataModel/RimPlotCurve.h +++ b/ApplicationCode/ProjectDataModel/RimPlotCurve.h @@ -78,6 +78,9 @@ public: QString curveName() const { return m_curveName; } void updateCurveVisibility(); + void updateLegendVisibility(); + + void showLegend(bool show); protected: @@ -107,6 +110,7 @@ protected: caf::PdmField m_showCurve; caf::PdmField m_curveName; caf::PdmField m_customCurveName; + caf::PdmField m_showLegend; caf::PdmField m_isUsingAutoName; caf::PdmField m_curveColor; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index c607cc34f6..3f25468a2f 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -446,6 +446,7 @@ void RimSummaryCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& curveVarSelectionGroup->add(&m_uiFilterResultSelection); uiOrdering.add(&m_plotAxis); + uiOrdering.add(&m_showLegend); caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance"); RimPlotCurve::appearanceUiOrdering(*appearanceGroup); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp index bf17751da4..cd01636a56 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp @@ -112,6 +112,7 @@ RimSummaryCurveFilter::RimSummaryCurveFilter() CAF_PDM_InitFieldNoDefault(&m_regionAppearanceType, "RegionAppearanceType", "Region", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_plotAxis, "PlotAxis", "Axis", "", "", ""); + CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Contribute To Legend", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_curveNameConfig, "SummaryCurveNameConfig", "SummaryCurveNameConfig", "", "", ""); m_curveNameConfig.uiCapability()->setUiHidden(true); @@ -197,6 +198,7 @@ void RimSummaryCurveFilter::defineUiOrdering(QString uiConfigName, caf::PdmUiOrd curveVarSelectionGroup->add(&m_uiFilterResultMultiSelection); uiOrdering.add(&m_plotAxis); + uiOrdering.add(&m_showLegend); caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance settings"); appearanceGroup->setCollapsedByDefault(true); @@ -271,6 +273,13 @@ void RimSummaryCurveFilter::fieldChangedByUi(const caf::PdmFieldHandle* changedF plotNeedsRedraw = true; } + else if (changedField == &m_showLegend) + { + for (size_t i = 0; i < m_curves().size(); ++i) + { + m_curves()[i]->showLegend(m_showLegend()); + } + } else { plotNeedsRedraw = true; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.h index ac4e07b024..c60da52986 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.h @@ -110,6 +110,7 @@ private: caf::PdmChildArrayField m_curves; caf::PdmField< caf::AppEnum< RimDefines::PlotAxis > > m_plotAxis; + caf::PdmField m_showLegend; // Filter fields diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index e0af1b01ec..b2e94f5a7b 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -36,6 +36,7 @@ #include "cvfColor3.h" #include "cafPdmUiTreeOrdering.h" +#include "cafPdmUiCheckBoxEditor.h" #include #include @@ -43,6 +44,8 @@ #include "qwt_plot_curve.h" #include "qwt_plot_renderer.h" +#include "qwt_abstract_legend.h" +#include "qwt_legend.h" CAF_PDM_SOURCE_INIT(RimSummaryPlot, "SummaryPlot"); @@ -56,6 +59,9 @@ RimSummaryPlot::RimSummaryPlot() CAF_PDM_InitField(&m_userName, "PlotDescription", QString("Summary Plot"), "Name", "", "", ""); CAF_PDM_InitField(&m_showPlotTitle, "ShowPlotTitle", true, "Show Plot Title", "", "", ""); + m_showPlotTitle.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Show Legend", "", "", ""); + m_showLegend.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); CAF_PDM_InitFieldNoDefault(&m_curveFilters, "SummaryCurveFilters", "", "", "", ""); m_curveFilters.uiCapability()->setUiTreeHidden(true); @@ -693,7 +699,8 @@ void RimSummaryPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c RimViewWindow::fieldChangedByUi(changedField, oldValue, newValue); if (changedField == &m_userName || - changedField == &m_showPlotTitle) + changedField == &m_showPlotTitle || + changedField == &m_showLegend) { updateMdiWindowTitle(); } @@ -896,6 +903,18 @@ void RimSummaryPlot::updateMdiWindowTitle() { m_qwtPlot->setTitle(""); } + + + if (m_showLegend) + { + // Will be released in plot destructor or when a new legend is set + QwtLegend* legend = new QwtLegend(m_qwtPlot); + m_qwtPlot->insertLegend(legend, QwtPlot::BottomLegend); + } + else + { + m_qwtPlot->insertLegend(nullptr); + } } } @@ -957,3 +976,18 @@ size_t RimSummaryPlot::curveCount() const { return m_summaryCurves.size() + m_gridTimeHistoryCurves.size(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute) +{ + if (field == &m_showLegend || field == &m_showPlotTitle) + { + caf::PdmUiCheckBoxEditorAttribute* myAttr = static_cast(attribute); + if (myAttr) + { + myAttr->m_useNativeCheckBoxLabel = true; + } + } +} diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h index 186ef8881c..d4cd5c2284 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h @@ -95,6 +95,7 @@ protected: virtual caf::PdmFieldHandle* userDescriptionField() { return &m_userName; } virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; virtual void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override; + virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute); virtual QImage snapshotWindowContent() override; @@ -118,6 +119,7 @@ private: private: caf::PdmField m_showPlotTitle; + caf::PdmField m_showLegend; caf::PdmField m_userName; caf::PdmChildArrayField m_gridTimeHistoryCurves; From 7efe0a996af99dea9bd7f82f43f8626098919e9e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 24 Apr 2017 21:40:46 +0200 Subject: [PATCH 019/157] #1384 Add missing population of view windows --- ApplicationCode/Application/RiaApplication.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 65dac59957..8141bb3e6a 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -2424,6 +2424,8 @@ void RiaApplication::runRegressionTest(const QString& testRootPath) void RiaApplication::resizeMaximizedPlotWindows() { std::vector viewWindows; + m_project->mainPlotCollection()->descendantsIncludingThisOfType(viewWindows); + for (auto viewWindow : viewWindows) { if (viewWindow->isMdiWindow()) From c701750330857887cd09543d824bc74860176149 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 24 Apr 2017 21:53:45 +0200 Subject: [PATCH 020/157] #1396 Update to libert from https://github.com/Statoil/libecl --- ResInsightVersion.cmake | 4 +- ThirdParty/Ert/.travis.yml | 77 +- ThirdParty/Ert/CMakeLists.txt | 36 +- ThirdParty/Ert/README | 341 -- ThirdParty/Ert/README.md | 301 ++ ThirdParty/Ert/cmake/cmake_pyc | 4 +- ThirdParty/Ert/cmake/cmake_pyc_file | 2 +- ThirdParty/Ert/cmake/cmake_pyc_tree | 2 +- ThirdParty/Ert/cmake/ert_api_check.cmake | 13 +- ThirdParty/Ert/cmake/ert_build_check.cmake | 4 + .../course/config/jobs/snake_oil_simulator.py | 2 +- .../Ert/docs/user/distributions/index.rst | 172 - ThirdParty/Ert/docs/user/index.rst | 15 - ThirdParty/Ert/docs/user/keywords/index.rst | 1869 ---------- .../Ert/docs/user/localization/index.rst | 602 --- .../Ert/docs/user/magic_strings/index.rst | 30 - .../Ert/docs/user/observations/index.rst | 463 --- ThirdParty/Ert/docs/user/tutorial/index.rst | 3 - .../Ert/docs/user/workflows/built_in.rst | 401 -- ThirdParty/Ert/docs/user/workflows/index.rst | 30 - .../Ert/docs/user/workflows/plugins.rst | 246 -- .../Ert/docs/user/workflows/workflows.rst | 369 -- .../etc-example/ERT/Scripts/job_dispatch.py | 308 -- .../Ert/etc-example/ERT/Scripts/run_RMS_20xx | 394 -- .../etc-example/ERT/Scripts/run_eclipse.py | 228 -- ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE | 3 - .../etc-example/ERT/jobs/ECLIPSE100_2009.2 | 3 - .../ERT/jobs/ECLIPSE100_2009.2_NOTARGET | 2 - .../Ert/etc-example/ERT/jobs/RUN_RMS_20XX | 8 - ThirdParty/Ert/etc-example/ERT/site-config | 79 - ThirdParty/Ert/etc-example/README | 42 - ThirdParty/Ert/libanalysis/CMakeLists.txt | 14 - .../libanalysis/applications/CMakeLists.txt | 20 - .../applications/ert_module_test.c | 58 - .../Ert/libanalysis/applications/main_test.c | 32 - .../Ert/libanalysis/cmake/ert_module.cmake | 23 - .../include/ert/analysis/analysis_module.h | 134 - .../include/ert/analysis/analysis_table.h | 95 - .../include/ert/analysis/cv_enkf.h | 52 - .../include/ert/analysis/enkf_linalg.h | 115 - .../include/ert/analysis/fwd_step_enkf.h | 40 - .../include/ert/analysis/fwd_step_log.h | 45 - .../include/ert/analysis/module_data_block.h | 52 - .../ert/analysis/module_data_block_vector.h | 42 - .../include/ert/analysis/module_info.h | 42 - .../include/ert/analysis/module_obs_block.h | 52 - .../ert/analysis/module_obs_block_vector.h | 43 - .../include/ert/analysis/std_enkf.h | 56 - .../Ert/libanalysis/modules/CMakeLists.txt | 49 - .../libanalysis/modules/deprecated/rml_enkf.c | 427 --- ThirdParty/Ert/libanalysis/modules/rml_enkf.c | 824 ---- .../Ert/libanalysis/modules/rml_enkf_common.c | 91 - .../Ert/libanalysis/modules/rml_enkf_common.h | 15 - .../Ert/libanalysis/modules/rml_enkf_config.c | 168 - .../Ert/libanalysis/modules/rml_enkf_config.h | 64 - .../Ert/libanalysis/modules/rml_enkf_log.c | 110 - .../Ert/libanalysis/modules/rml_enkf_log.h | 45 - .../Ert/libanalysis/modules/std_enkf_debug.c | 245 -- .../libanalysis/modules/tests/CMakeLists.txt | 5 - .../modules/tests/analysis_rml_enkf_common.c | 133 - .../Ert/libanalysis/script/CMakeLists.txt | 8 - ThirdParty/Ert/libanalysis/script/ert_module | 239 -- ThirdParty/Ert/libanalysis/src/CMakeLists.txt | 33 - .../Ert/libanalysis/src/analysis_module.c | 463 --- .../Ert/libanalysis/src/bootstrap_enkf.c | 300 -- ThirdParty/Ert/libanalysis/src/cv_enkf.c | 721 ---- ThirdParty/Ert/libanalysis/src/enkf_linalg.c | 860 ----- .../Ert/libanalysis/src/fwd_step_enkf.c | 549 --- ThirdParty/Ert/libanalysis/src/fwd_step_log.c | 105 - .../Ert/libanalysis/src/module_data_block.c | 67 - .../src/module_data_block_vector.c | 64 - ThirdParty/Ert/libanalysis/src/module_info.c | 66 - .../Ert/libanalysis/src/module_obs_block.c | 67 - .../libanalysis/src/module_obs_block_vector.c | 82 - ThirdParty/Ert/libanalysis/src/modules.txt | 212 -- ThirdParty/Ert/libanalysis/src/null_enkf.c | 86 - ThirdParty/Ert/libanalysis/src/sqrt_enkf.c | 223 -- ThirdParty/Ert/libanalysis/src/std_enkf.c | 368 -- .../Ert/libanalysis/tests/CMakeLists.txt | 21 - .../tests/analysis_test_external_module.c | 106 - .../tests/analysis_test_module_info.c | 50 - ThirdParty/Ert/libconfig/CMakeLists.txt | 4 - .../Ert/libconfig/applications/conf_test.c | 213 -- .../Ert/libconfig/applications/config_test.c | 59 - .../Ert/libconfig/include/ert/config/conf.h | 354 -- .../libconfig/include/ert/config/conf_data.h | 61 - .../libconfig/include/ert/config/conf_util.h | 26 - .../include/ert/config/config_content.h | 84 - .../include/ert/config/config_content_item.h | 69 - .../include/ert/config/config_content_node.h | 63 - .../include/ert/config/config_error.h | 45 - .../include/ert/config/config_parser.h | 105 - .../include/ert/config/config_path_elm.h | 44 - .../include/ert/config/config_root_path.h | 40 - .../include/ert/config/config_schema_item.h | 109 - .../include/ert/config/config_settings.h | 67 - ThirdParty/Ert/libconfig/src/CMakeLists.txt | 17 - ThirdParty/Ert/libconfig/src/conf.c | 1569 -------- ThirdParty/Ert/libconfig/src/conf_data.c | 259 -- ThirdParty/Ert/libconfig/src/conf_util.c | 161 - ThirdParty/Ert/libconfig/src/config_content.c | 424 --- .../Ert/libconfig/src/config_content_item.c | 293 -- .../Ert/libconfig/src/config_content_node.c | 242 -- ThirdParty/Ert/libconfig/src/config_error.c | 86 - ThirdParty/Ert/libconfig/src/config_get.c | 103 - ThirdParty/Ert/libconfig/src/config_parser.c | 719 ---- .../Ert/libconfig/src/config_path_elm.c | 139 - .../Ert/libconfig/src/config_root_path.c | 101 - .../Ert/libconfig/src/config_schema_item.c | 583 --- .../Ert/libconfig/src/config_settings.c | 340 -- .../Ert/libconfig/src/testcase/test.txt | 76 - .../Ert/libconfig/src/testcase/test2.txt | 9 - ThirdParty/Ert/libconfig/tests/CMakeLists.txt | 61 - .../Ert/libconfig/tests/config_append_test.c | 55 - ThirdParty/Ert/libconfig/tests/config_argc.c | 90 - .../Ert/libconfig/tests/config_config.c | 36 - .../Ert/libconfig/tests/config_content.c | 37 - .../Ert/libconfig/tests/config_content_item.c | 57 - .../Ert/libconfig/tests/config_content_node.c | 76 - .../Ert/libconfig/tests/config_define.c | 80 - ThirdParty/Ert/libconfig/tests/config_error.c | 43 - .../Ert/libconfig/tests/config_include_test.c | 135 - .../Ert/libconfig/tests/config_node_test.c | 57 - .../Ert/libconfig/tests/config_path_elm.c | 92 - .../Ert/libconfig/tests/config_root_path.c | 78 - .../Ert/libconfig/tests/config_schema_item.c | 48 - .../Ert/libconfig/tests/config_typeFail.c | 71 - .../Ert/libconfig/tests/config_typeOK.c | 53 - .../Ert/libconfig/tests/data/append_test | 4 - ThirdParty/Ert/libconfig/tests/data/argc_OK | 1 - ThirdParty/Ert/libconfig/tests/data/argc_less | 1 - ThirdParty/Ert/libconfig/tests/data/argc_more | 2 - .../libconfig/tests/data/content_item_test | 1 - .../Ert/libconfig/tests/data/define_test | 5 - .../Ert/libconfig/tests/data/include_test | 3 - .../Ert/libconfig/tests/data/path/include1 | 5 - .../tests/data/path/subpath/include2 | 1 - .../tests/data/path/subpath/include3 | 1 - .../data/path/subpath/subsubpath/include4 | 1 - .../Ert/libconfig/tests/data/type_testFail | 6 - .../Ert/libconfig/tests/data/type_testOK | 4 - ThirdParty/Ert/libecl/applications/ecl_pack.c | 3 +- .../Ert/libecl/applications/grdecl_grid.c | 8 +- .../Ert/libecl/applications/grdecl_test.c | 2 +- .../Ert/libecl/include/ert/ecl/ecl_file.h | 5 +- .../Ert/libecl/include/ert/ecl/ecl_file_kw.h | 2 +- .../libecl/include/ert/ecl/ecl_file_view.h | 5 +- .../Ert/libecl/include/ert/ecl/ecl_grid.h | 12 + .../Ert/libecl/include/ert/ecl/ecl_kw.h | 28 +- .../libecl/include/ert/ecl/ecl_kw_grdecl.h | 16 +- .../libecl/include/ert/ecl/ecl_nnc_geometry.h | 50 + .../Ert/libecl/include/ert/ecl/ecl_type.h | 150 + .../Ert/libecl/include/ert/ecl/ecl_util.h | 69 +- ThirdParty/Ert/libecl/src/CMakeLists.txt | 139 +- ThirdParty/Ert/libecl/src/ecl_file.c | 11 +- ThirdParty/Ert/libecl/src/ecl_file_kw.c | 43 +- ThirdParty/Ert/libecl/src/ecl_file_view.c | 15 +- ThirdParty/Ert/libecl/src/ecl_grid.c | 703 ++-- ThirdParty/Ert/libecl/src/ecl_init_file.c | 9 +- ThirdParty/Ert/libecl/src/ecl_kw.c | 395 +- ThirdParty/Ert/libecl/src/ecl_kw_grdecl.c | 57 +- ThirdParty/Ert/libecl/src/ecl_nnc_geometry.c | 126 + ThirdParty/Ert/libecl/src/ecl_region.c | 21 +- ThirdParty/Ert/libecl/src/ecl_rft_node.c | 23 +- ThirdParty/Ert/libecl/src/ecl_rst_file.c | 15 +- ThirdParty/Ert/libecl/src/ecl_rsthead.c | 8 +- ThirdParty/Ert/libecl/src/ecl_smspec.c | 15 +- ThirdParty/Ert/libecl/src/ecl_subsidence.c | 4 +- ThirdParty/Ert/libecl/src/ecl_sum_data.c | 2 +- ThirdParty/Ert/libecl/src/ecl_sum_tstep.c | 5 +- ThirdParty/Ert/libecl/src/ecl_type.c | 172 + ThirdParty/Ert/libecl/src/ecl_type_python.c | 108 + ThirdParty/Ert/libecl/src/ecl_util.c | 132 +- ThirdParty/Ert/libecl/src/fault_block_layer.c | 6 +- ThirdParty/Ert/libecl/tests/CMakeLists.txt | 5 + .../Ert/libecl/tests/ecl_alloc_cpgrid.c | 112 + .../Ert/libecl/tests/ecl_fault_block_layer.c | 13 +- .../tests/ecl_fault_block_layer_statoil.c | 2 +- ThirdParty/Ert/libecl/tests/ecl_fortio.c | 1 - .../Ert/libecl/tests/ecl_grid_cell_contains.c | 245 +- .../tests/ecl_grid_cell_contains_wellpath.c | 101 + ThirdParty/Ert/libecl/tests/ecl_grid_corner.c | 1 - ThirdParty/Ert/libecl/tests/ecl_init_file.c | 5 +- .../Ert/libecl/tests/ecl_kw_cmp_string.c | 3 +- ThirdParty/Ert/libecl/tests/ecl_kw_equal.c | 7 +- ThirdParty/Ert/libecl/tests/ecl_kw_fread.c | 2 +- ThirdParty/Ert/libecl/tests/ecl_kw_grdecl.c | 8 +- ThirdParty/Ert/libecl/tests/ecl_kw_init.c | 6 +- ThirdParty/Ert/libecl/tests/ecl_kw_ix_types.c | 2 +- ThirdParty/Ert/libecl/tests/ecl_layer.c | 1 - .../Ert/libecl/tests/ecl_layer_statoil.c | 2 +- ThirdParty/Ert/libecl/tests/ecl_lfs.c | 3 +- ThirdParty/Ert/libecl/tests/ecl_nnc_export.c | 15 + .../Ert/libecl/tests/ecl_nnc_geometry.c | 60 + ThirdParty/Ert/libecl/tests/ecl_rst_file.c | 55 +- .../Ert/libecl/tests/statoil_tests.cmake | 78 +- ThirdParty/Ert/libecl/tests/tests.cmake | 64 +- .../Ert/libecl_well/tests/statoil_tests.cmake | 20 +- ThirdParty/Ert/libecl_well/tests/tests.cmake | 14 +- .../Ert/libeclxx/include/ert/ecl/EclKW.hpp | 6 +- ThirdParty/Ert/libeclxx/src/EclFilename.cpp | 27 +- ThirdParty/Ert/libeclxx/tests/CMakeLists.txt | 12 +- ThirdParty/Ert/libeclxx/tests/eclxx_kw.cpp | 2 +- ThirdParty/Ert/libeclxx/tests/eclxx_types.cpp | 63 + ThirdParty/Ert/libenkf/CMakeLists.txt | 5 - .../CMake/config/ert_build_config_file.h.in | 3 - .../applications/ert_tui/CMakeLists.txt | 35 - .../Ert/libenkf/applications/ert_tui/ERT.h | 34 - .../applications/ert_tui/enkf_tui_QC.h | 28 - .../applications/ert_tui/enkf_tui_analysis.c | 160 - .../applications/ert_tui/enkf_tui_analysis.h | 27 - .../applications/ert_tui/enkf_tui_export.c | 687 ---- .../applications/ert_tui/enkf_tui_export.h | 26 - .../applications/ert_tui/enkf_tui_fs.c | 354 -- .../applications/ert_tui/enkf_tui_fs.h | 24 - .../applications/ert_tui/enkf_tui_help.c | 232 -- .../applications/ert_tui/enkf_tui_help.h | 33 - .../applications/ert_tui/enkf_tui_init.c | 140 - .../applications/ert_tui/enkf_tui_init.h | 26 - .../applications/ert_tui/enkf_tui_main.c | 71 - .../applications/ert_tui/enkf_tui_main.h | 27 - .../applications/ert_tui/enkf_tui_misc.c | 76 - .../applications/ert_tui/enkf_tui_misc.h | 26 - .../applications/ert_tui/enkf_tui_ranking.c | 220 -- .../applications/ert_tui/enkf_tui_ranking.h | 28 - .../applications/ert_tui/enkf_tui_run.c | 242 -- .../applications/ert_tui/enkf_tui_run.h | 28 - .../applications/ert_tui/enkf_tui_simple.c | 62 - .../applications/ert_tui/enkf_tui_simple.h | 26 - .../applications/ert_tui/enkf_tui_table.c | 248 -- .../applications/ert_tui/enkf_tui_table.h | 24 - .../applications/ert_tui/enkf_tui_util.c | 401 -- .../applications/ert_tui/enkf_tui_util.h | 45 - .../applications/ert_tui/enkf_tui_workflow.c | 112 - .../applications/ert_tui/enkf_tui_workflow.h | 24 - .../applications/ert_tui/ert_tui_const.h | 31 - .../Ert/libenkf/applications/ert_tui/main.c | 171 - .../applications/ert_tui/upgrade_fs104.c | 320 -- .../include/ert/enkf/README.new_type.h | 124 - .../include/ert/enkf/README.new_type_config.h | 28 - .../libenkf/include/ert/enkf/active_config.h | 23 - .../libenkf/include/ert/enkf/active_list.h | 54 - .../libenkf/include/ert/enkf/active_node.h | 29 - .../include/ert/enkf/analysis_config.h | 121 - .../include/ert/enkf/analysis_iter_config.h | 48 - .../include/ert/enkf/block_fs_driver.h | 48 - .../Ert/libenkf/include/ert/enkf/block_obs.h | 96 - .../libenkf/include/ert/enkf/cases_config.h | 39 - .../libenkf/include/ert/enkf/config_keys.h | 166 - .../libenkf/include/ert/enkf/config_parser.h | 22 - .../Ert/libenkf/include/ert/enkf/container.h | 43 - .../include/ert/enkf/container_config.h | 50 - .../Ert/libenkf/include/ert/enkf/custom_kw.h | 56 - .../include/ert/enkf/custom_kw_config.h | 43 - .../include/ert/enkf/custom_kw_config_set.h | 30 - .../libenkf/include/ert/enkf/data_ranking.h | 51 - .../Ert/libenkf/include/ert/enkf/ecl_config.h | 114 - .../include/ert/enkf/ecl_refcase_list.h | 49 - .../Ert/libenkf/include/ert/enkf/enkf.h | 29 - .../libenkf/include/ert/enkf/enkf_analysis.h | 57 - .../include/ert/enkf/enkf_config_node.h | 234 -- .../include/ert/enkf/enkf_config_private.h | 27 - .../libenkf/include/ert/enkf/enkf_defaults.h | 296 -- .../Ert/libenkf/include/ert/enkf/enkf_fs.h | 123 - .../libenkf/include/ert/enkf/enkf_fs_type.h | 23 - .../libenkf/include/ert/enkf/enkf_macros.h | 355 -- .../Ert/libenkf/include/ert/enkf/enkf_main.h | 327 -- .../libenkf/include/ert/enkf/enkf_main_jobs.h | 35 - .../include/ert/enkf/enkf_main_update.h | 28 - .../Ert/libenkf/include/ert/enkf/enkf_node.h | 199 - .../Ert/libenkf/include/ert/enkf/enkf_obs.h | 103 - .../libenkf/include/ert/enkf/enkf_plot_data.h | 52 - .../include/ert/enkf/enkf_plot_gen_kw.h | 55 - .../ert/enkf/enkf_plot_gen_kw_vector.h | 47 - .../include/ert/enkf/enkf_plot_gendata.h | 57 - .../include/ert/enkf/enkf_plot_genvector.h | 45 - .../include/ert/enkf/enkf_plot_tvector.h | 59 - .../libenkf/include/ert/enkf/enkf_serialize.h | 58 - .../Ert/libenkf/include/ert/enkf/enkf_state.h | 135 - .../Ert/libenkf/include/ert/enkf/enkf_types.h | 253 -- .../Ert/libenkf/include/ert/enkf/enkf_util.h | 349 -- .../include/ert/enkf/ensemble_config.h | 96 - .../include/ert/enkf/ert_init_context.h | 62 - .../Ert/libenkf/include/ert/enkf/ert_log.h | 45 - .../include/ert/enkf/ert_run_context.h | 78 - .../libenkf/include/ert/enkf/ert_template.h | 61 - .../include/ert/enkf/ert_test_context.h | 55 - .../include/ert/enkf/ert_workflow_list.h | 69 - .../Ert/libenkf/include/ert/enkf/field.h | 103 - .../libenkf/include/ert/enkf/field_common.h | 37 - .../libenkf/include/ert/enkf/field_config.h | 203 - .../libenkf/include/ert/enkf/field_trans.h | 44 - .../include/ert/enkf/forward_load_context.h | 59 - .../Ert/libenkf/include/ert/enkf/fs_driver.h | 241 -- .../Ert/libenkf/include/ert/enkf/fs_types.h | 77 - .../Ert/libenkf/include/ert/enkf/gen_common.h | 39 - .../Ert/libenkf/include/ert/enkf/gen_data.h | 79 - .../include/ert/enkf/gen_data_common.h | 36 - .../include/ert/enkf/gen_data_config.h | 95 - .../Ert/libenkf/include/ert/enkf/gen_kw.h | 89 - .../libenkf/include/ert/enkf/gen_kw_common.h | 36 - .../libenkf/include/ert/enkf/gen_kw_config.h | 66 - .../Ert/libenkf/include/ert/enkf/gen_obs.h | 57 - .../libenkf/include/ert/enkf/hook_manager.h | 62 - .../libenkf/include/ert/enkf/hook_workflow.h | 54 - .../libenkf/include/ert/enkf/local_config.h | 57 - .../libenkf/include/ert/enkf/local_context.h | 64 - .../libenkf/include/ert/enkf/local_dataset.h | 50 - .../libenkf/include/ert/enkf/local_ministep.h | 70 - .../libenkf/include/ert/enkf/local_obsdata.h | 55 - .../include/ert/enkf/local_obsdata_node.h | 55 - .../include/ert/enkf/local_updatestep.h | 45 - .../Ert/libenkf/include/ert/enkf/meas_data.h | 68 - .../libenkf/include/ert/enkf/member_config.h | 67 - .../include/ert/enkf/misfit_ensemble.h | 65 - .../ert/enkf/misfit_ensemble_typedef.h | 6 - .../libenkf/include/ert/enkf/misfit_member.h | 44 - .../libenkf/include/ert/enkf/misfit_ranking.h | 54 - .../Ert/libenkf/include/ert/enkf/misfit_ts.h | 43 - .../libenkf/include/ert/enkf/model_config.h | 100 - .../Ert/libenkf/include/ert/enkf/obs_data.h | 81 - .../Ert/libenkf/include/ert/enkf/obs_vector.h | 113 - .../libenkf/include/ert/enkf/pca_plot_data.h | 47 - .../include/ert/enkf/pca_plot_vector.h | 46 - .../libenkf/include/ert/enkf/plain_driver.h | 33 - .../include/ert/enkf/plain_driver_obs.h | 36 - .../libenkf/include/ert/enkf/plot_settings.h | 28 - .../libenkf/include/ert/enkf/ranking_common.h | 25 - .../libenkf/include/ert/enkf/ranking_table.h | 67 - .../Ert/libenkf/include/ert/enkf/rng_config.h | 50 - .../Ert/libenkf/include/ert/enkf/run_arg.h | 73 - .../libenkf/include/ert/enkf/run_arg_type.h | 25 - .../libenkf/include/ert/enkf/runpath_list.h | 51 - .../libenkf/include/ert/enkf/scalar_config.h | 50 - .../libenkf/include/ert/enkf/site_config.h | 107 - .../Ert/libenkf/include/ert/enkf/state_map.h | 60 - .../Ert/libenkf/include/ert/enkf/summary.h | 61 - .../libenkf/include/ert/enkf/summary_config.h | 85 - .../include/ert/enkf/summary_key_matcher.h | 28 - .../include/ert/enkf/summary_key_set.h | 34 - .../libenkf/include/ert/enkf/summary_obs.h | 97 - .../Ert/libenkf/include/ert/enkf/surface.h | 57 - .../libenkf/include/ert/enkf/surface_config.h | 50 - .../Ert/libenkf/include/ert/enkf/time_map.h | 69 - .../Ert/libenkf/include/ert/enkf/trans_func.h | 49 - ThirdParty/Ert/libenkf/src/CMakeLists.txt | 239 -- .../Ert/libenkf/src/README.new_config_draft | 251 -- ThirdParty/Ert/libenkf/src/README.new_type.c | 343 -- ThirdParty/Ert/libenkf/src/README.obs | 52 - ThirdParty/Ert/libenkf/src/README.paths | 25 - ThirdParty/Ert/libenkf/src/active_list.c | 224 -- ThirdParty/Ert/libenkf/src/active_node.c | 63 - ThirdParty/Ert/libenkf/src/analysis_config.c | 714 ---- .../Ert/libenkf/src/analysis_iter_config.c | 131 - ThirdParty/Ert/libenkf/src/block_fs_driver.c | 511 --- ThirdParty/Ert/libenkf/src/block_obs.c | 466 --- ThirdParty/Ert/libenkf/src/cases_config.c | 86 - ThirdParty/Ert/libenkf/src/container.c | 83 - ThirdParty/Ert/libenkf/src/container_config.c | 76 - ThirdParty/Ert/libenkf/src/custom_kw.c | 149 - ThirdParty/Ert/libenkf/src/custom_kw_config.c | 304 -- .../Ert/libenkf/src/custom_kw_config_set.c | 143 - ThirdParty/Ert/libenkf/src/data_ranking.c | 151 - ThirdParty/Ert/libenkf/src/dependencies | 71 - ThirdParty/Ert/libenkf/src/ecl_config.c | 1012 ----- ThirdParty/Ert/libenkf/src/ecl_refcase_list.c | 397 -- ThirdParty/Ert/libenkf/src/enkf_analysis.c | 190 - ThirdParty/Ert/libenkf/src/enkf_config_node.c | 1072 ------ ThirdParty/Ert/libenkf/src/enkf_defaults.c | 24 - ThirdParty/Ert/libenkf/src/enkf_fs.c | 1058 ------ ThirdParty/Ert/libenkf/src/enkf_main.c | 3304 ----------------- ThirdParty/Ert/libenkf/src/enkf_main_jobs.c | 552 --- .../Ert/libenkf/src/enkf_main_manage_fs.c | 683 ---- ThirdParty/Ert/libenkf/src/enkf_main_update.c | 39 - ThirdParty/Ert/libenkf/src/enkf_node.c | 1077 ------ ThirdParty/Ert/libenkf/src/enkf_obs.c | 1270 ------- ThirdParty/Ert/libenkf/src/enkf_plot_data.c | 151 - ThirdParty/Ert/libenkf/src/enkf_plot_gen_kw.c | 147 - .../Ert/libenkf/src/enkf_plot_gen_kw_vector.c | 96 - .../Ert/libenkf/src/enkf_plot_gendata.c | 203 - .../Ert/libenkf/src/enkf_plot_genvector.c | 95 - .../Ert/libenkf/src/enkf_plot_tvector.c | 181 - ThirdParty/Ert/libenkf/src/enkf_serialize.c | 276 -- ThirdParty/Ert/libenkf/src/enkf_state.c | 1654 --------- ThirdParty/Ert/libenkf/src/enkf_types.c | 144 - ThirdParty/Ert/libenkf/src/enkf_util.c | 369 -- ThirdParty/Ert/libenkf/src/ensemble_config.c | 1002 ----- ThirdParty/Ert/libenkf/src/ert_init_context.c | 154 - ThirdParty/Ert/libenkf/src/ert_log.c | 113 - ThirdParty/Ert/libenkf/src/ert_run_context.c | 278 -- ThirdParty/Ert/libenkf/src/ert_template.c | 258 -- ThirdParty/Ert/libenkf/src/ert_test_context.c | 183 - ThirdParty/Ert/libenkf/src/ert_users.c | 48 - .../Ert/libenkf/src/ert_workflow_list.c | 365 -- ThirdParty/Ert/libenkf/src/field.c | 1564 -------- ThirdParty/Ert/libenkf/src/field_config.c | 1048 ------ ThirdParty/Ert/libenkf/src/field_convert.c | 68 - ThirdParty/Ert/libenkf/src/field_test.c | 64 - ThirdParty/Ert/libenkf/src/field_trans.c | 289 -- .../Ert/libenkf/src/forward_load_context.c | 269 -- ThirdParty/Ert/libenkf/src/fs_driver.c | 162 - ThirdParty/Ert/libenkf/src/fs_types.c | 73 - ThirdParty/Ert/libenkf/src/gen_common.c | 139 - ThirdParty/Ert/libenkf/src/gen_data.c | 745 ---- ThirdParty/Ert/libenkf/src/gen_data_config.c | 653 ---- ThirdParty/Ert/libenkf/src/gen_kw.c | 501 --- ThirdParty/Ert/libenkf/src/gen_kw_config.c | 327 -- ThirdParty/Ert/libenkf/src/gen_obs.c | 522 --- ThirdParty/Ert/libenkf/src/gen_test.c | 28 - ThirdParty/Ert/libenkf/src/hook_manager.c | 254 -- ThirdParty/Ert/libenkf/src/hook_workflow.c | 105 - ThirdParty/Ert/libenkf/src/local_config.c | 298 -- ThirdParty/Ert/libenkf/src/local_context.c | 132 - ThirdParty/Ert/libenkf/src/local_dataset.c | 137 - ThirdParty/Ert/libenkf/src/local_ministep.c | 274 -- ThirdParty/Ert/libenkf/src/local_obsdata.c | 165 - .../Ert/libenkf/src/local_obsdata_node.c | 174 - ThirdParty/Ert/libenkf/src/local_updatestep.c | 118 - ThirdParty/Ert/libenkf/src/meas_data.c | 451 --- ThirdParty/Ert/libenkf/src/member_config.c | 174 - ThirdParty/Ert/libenkf/src/migrate_bfs.c | 131 - ThirdParty/Ert/libenkf/src/misfit_ensemble.c | 249 -- ThirdParty/Ert/libenkf/src/misfit_member.c | 122 - ThirdParty/Ert/libenkf/src/misfit_ranking.c | 254 -- ThirdParty/Ert/libenkf/src/misfit_ts.c | 100 - ThirdParty/Ert/libenkf/src/model_config.c | 636 ---- ThirdParty/Ert/libenkf/src/obs_data.c | 762 ---- ThirdParty/Ert/libenkf/src/obs_vector.c | 1118 ------ ThirdParty/Ert/libenkf/src/pca_plot_data.c | 107 - ThirdParty/Ert/libenkf/src/pca_plot_vector.c | 108 - ThirdParty/Ert/libenkf/src/plain_driver.c | 273 -- ThirdParty/Ert/libenkf/src/plain_driver_obs.c | 186 - ThirdParty/Ert/libenkf/src/plot_settings.c | 64 - ThirdParty/Ert/libenkf/src/ranking_table.c | 163 - ThirdParty/Ert/libenkf/src/readme.overview | 55 - ThirdParty/Ert/libenkf/src/rng_config.c | 160 - ThirdParty/Ert/libenkf/src/run_arg.c | 250 -- ThirdParty/Ert/libenkf/src/runpath_list.c | 236 -- ThirdParty/Ert/libenkf/src/scalar_config.c | 87 - ThirdParty/Ert/libenkf/src/site_config.c | 987 ----- ThirdParty/Ert/libenkf/src/state_map.c | 285 -- ThirdParty/Ert/libenkf/src/summary.c | 332 -- ThirdParty/Ert/libenkf/src/summary_config.c | 135 - .../Ert/libenkf/src/summary_key_matcher.c | 77 - ThirdParty/Ert/libenkf/src/summary_key_set.c | 170 - ThirdParty/Ert/libenkf/src/summary_obs.c | 228 -- ThirdParty/Ert/libenkf/src/surface.c | 230 -- ThirdParty/Ert/libenkf/src/surface_config.c | 81 - ThirdParty/Ert/libenkf/src/test.c | 39 - ThirdParty/Ert/libenkf/src/time_map.c | 714 ---- ThirdParty/Ert/libenkf/src/trans_errf.m | 3 - ThirdParty/Ert/libenkf/src/trans_func.c | 416 --- ThirdParty/Ert/libenkf/src/trans_test.m | 12 - ThirdParty/Ert/libenkf/tests/CMakeLists.txt | 4 - .../tests/data/config/analysis_load_config | 1 - .../data/config/analysis_load_site_config | 2 - .../libenkf/tests/data/config/ert_report_list | 3 - .../data/config/forward/ert/FAULT_TEMPLATE | 1 - .../tests/data/config/forward/ert/MULTFLT.TXT | 1 - .../config/forward/ert/config_GEN_KW_false | 8 - .../config/forward/ert/config_GEN_KW_true | 10 - .../config/forward/ert/config_GEN_PARAM_false | 9 - .../config/forward/ert/config_GEN_PARAM_true | 10 - .../tests/data/config/forward/ert/script.sh | 1 - .../config/gen_kw_logarithmic/FAULT_TEMPLATE | 1 - .../config/gen_kw_logarithmic/FAULT_TEMPLATE2 | 1 - .../config/gen_kw_logarithmic/MULTFLT.TXT | 1 - .../config/gen_kw_logarithmic/MULTFLT2.TXT | 1 - .../config_GEN_KW_logarithmic | 9 - .../data/config/gen_kw_logarithmic/script.sh | 1 - .../data/config/gen_kw_plot/Parameters.txt | 5 - .../data/config/gen_kw_plot/Template.tmpl | 1 - .../tests/data/config/gen_kw_plot/config | 2 - ThirdParty/Ert/libenkf/tests/data/config/rng | 6 - .../data/config/runpath_list/ARGECHO_JOB | 2 - .../tests/data/config/runpath_list/ARGECHO_WF | 1 - .../data/config/runpath_list/arg_echo.sh | 3 - .../tests/data/config/runpath_list/config | 5 - .../Ert/libenkf/tests/data/config/script.sh | 2 - .../data/config/test_context/FAULT_TEMPLATE | 1 - .../data/config/test_context/MULTFLT.TXT | 1 - .../tests/data/config/test_context/config | 11 - .../tests/data/config/test_context/script.sh | 1 - .../tests/data/config/test_context/wf_job | 5 - .../data/config/test_context/wf_job_fail | 5 - .../Ert/libenkf/tests/data/ensemble/GEN_PARAM | 1 - .../libenkf/tests/data/workflow_jobs/CONF1 | 5 - .../libenkf/tests/data/workflow_jobs/CONF2 | 2 - .../libenkf/tests/data/workflow_jobs/CONF2@1 | 5 - .../tests/data/workflow_jobs/CONF3@1.2.3 | 5 - .../tests/data/workflow_jobs/CONF4@1.2.0 | 5 - .../tests/data/workflow_jobs/CONF5@1.2 | 5 - .../tests/data/workflow_jobs/CONF5@1.2.0 | 1 - .../Ert/libenkf/tests/enkf_active_list.c | 65 - .../Ert/libenkf/tests/enkf_analysis_config.c | 198 - .../enkf_analysis_config_analysis_load.c | 51 - .../tests/enkf_analysis_config_ext_module.c | 65 - .../libenkf/tests/enkf_analysis_update_job.c | 99 - ThirdParty/Ert/libenkf/tests/enkf_block_obs.c | 79 - .../Ert/libenkf/tests/enkf_cases_config.c | 44 - .../Ert/libenkf/tests/enkf_config_node.c | 31 - .../Ert/libenkf/tests/enkf_ecl_config.c | 54 - .../libenkf/tests/enkf_ecl_config_config.c | 60 - .../tests/enkf_enkf_config_node_gen_data.c | 36 - ThirdParty/Ert/libenkf/tests/enkf_ensemble.c | 46 - .../libenkf/tests/enkf_ensemble_GEN_PARAM.c | 60 - .../Ert/libenkf/tests/enkf_ensemble_config.c | 53 - .../Ert/libenkf/tests/enkf_ert_run_context.c | 126 - .../Ert/libenkf/tests/enkf_ert_test_context.c | 153 - .../libenkf/tests/enkf_ert_workflow_list.c | 86 - .../libenkf/tests/enkf_export_field_test.c | 135 - .../tests/enkf_export_inactive_cells.c | 204 - .../libenkf/tests/enkf_forward_init_FIELD.c | 155 - .../libenkf/tests/enkf_forward_init_GEN_KW.c | 163 - .../tests/enkf_forward_init_GEN_PARAM.c | 154 - .../libenkf/tests/enkf_forward_init_SURFACE.c | 161 - .../tests/enkf_forward_init_transform.c | 115 - .../libenkf/tests/enkf_forward_load_context.c | 132 - ThirdParty/Ert/libenkf/tests/enkf_fs.c | 158 - .../Ert/libenkf/tests/enkf_gen_data_config.c | 373 -- .../tests/enkf_gen_data_config_parse.c | 253 -- .../Ert/libenkf/tests/enkf_gen_obs_load.c | 58 - .../libenkf/tests/enkf_hook_manager_test.c | 49 - .../Ert/libenkf/tests/enkf_iter_config.c | 105 - .../Ert/libenkf/tests/enkf_local_obsdata.c | 63 - .../libenkf/tests/enkf_local_obsdata_node.c | 103 - .../tests/enkf_magic_string_in_workflows.c | 77 - ThirdParty/Ert/libenkf/tests/enkf_main.c | 66 - ThirdParty/Ert/libenkf/tests/enkf_main_fs.c | 124 - .../tests/enkf_main_fs_current_file_test.c | 96 - ThirdParty/Ert/libenkf/tests/enkf_meas_data.c | 85 - .../Ert/libenkf/tests/enkf_model_config.c | 62 - ThirdParty/Ert/libenkf/tests/enkf_obs_fs.c | 124 - ThirdParty/Ert/libenkf/tests/enkf_obs_tests.c | 62 - .../Ert/libenkf/tests/enkf_obs_vector.c | 85 - .../Ert/libenkf/tests/enkf_obs_vector_fs.c | 116 - ThirdParty/Ert/libenkf/tests/enkf_pca_plot.c | 133 - ThirdParty/Ert/libenkf/tests/enkf_plot_data.c | 46 - .../Ert/libenkf/tests/enkf_plot_data_fs.c | 125 - .../Ert/libenkf/tests/enkf_plot_gen_kw.c | 55 - .../Ert/libenkf/tests/enkf_plot_gen_kw_fs.c | 80 - .../libenkf/tests/enkf_plot_gen_kw_vector.c | 44 - .../Ert/libenkf/tests/enkf_plot_gendata.c | 54 - .../Ert/libenkf/tests/enkf_plot_gendata_fs.c | 96 - .../Ert/libenkf/tests/enkf_plot_genvector.c | 45 - .../Ert/libenkf/tests/enkf_plot_tvector.c | 114 - .../Ert/libenkf/tests/enkf_refcase_list.c | 128 - ThirdParty/Ert/libenkf/tests/enkf_rng.c | 130 - ThirdParty/Ert/libenkf/tests/enkf_run_arg.c | 158 - .../Ert/libenkf/tests/enkf_runpath_list.c | 155 - .../libenkf/tests/enkf_scale_correlated_std.c | 61 - .../Ert/libenkf/tests/enkf_select_case_job.c | 58 - .../Ert/libenkf/tests/enkf_site_config.c | 122 - .../tests/enkf_state_manual_load_test.c | 79 - ThirdParty/Ert/libenkf/tests/enkf_state_map.c | 368 -- .../tests/enkf_state_report_step_compatible.c | 70 - .../tests/enkf_state_skip_summary_load_test.c | 71 - ThirdParty/Ert/libenkf/tests/enkf_time_map.c | 398 -- .../libenkf/tests/enkf_umask_config_test.c | 60 - .../libenkf/tests/enkf_workflow_job_test.c | 494 --- .../tests/enkf_workflow_job_test_version.c | 80 - .../libenkf/tests/gen_kw_logarithmic_test.c | 110 - ThirdParty/Ert/libenkf/tests/gen_kw_test.c | 134 - .../Ert/libenkf/tests/obs_vector_tests.c | 244 -- .../Ert/libenkf/tests/statoil_tests.cmake | 220 -- ThirdParty/Ert/libenkf/tests/tests.cmake | 254 -- .../include/ert/util/ert_api_config.h.in | 2 +- .../include/ert/util/struct_vector.h | 6 +- .../libert_util/include/ert/util/test_util.h | 6 + .../include/ert/util/test_util_abort.h | 40 - .../Ert/libert_util/include/ert/util/util.h | 2 + ThirdParty/Ert/libert_util/src/CMakeLists.txt | 9 +- .../Ert/libert_util/src/struct_vector.c | 60 +- ThirdParty/Ert/libert_util/src/test_util.c | 35 +- .../Ert/libert_util/src/test_work_area.c | 5 +- .../Ert/libert_util/src/util_abort_gnu.c | 5 +- .../Ert/libert_util/tests/CMakeLists.txt | 108 +- .../tests/ert_util_abort_gnu_tests.c | 3 +- .../libert_util/tests/ert_util_addr2line.c | 53 +- .../Ert/libert_util/tests/ert_util_matrix.c | 54 +- .../Ert/libert_util/tests/ert_util_ping.c | 8 - .../tests/ert_util_struct_vector.c | 57 +- .../tests/ert_util_type_vector_test.c | 1 - .../Ert/libert_utilxx/tests/CMakeLists.txt | 4 +- ThirdParty/Ert/libgeometry/src/geo_surface.c | 37 +- .../Ert/libgeometry/tests/CMakeLists.txt | 8 +- ThirdParty/Ert/libjob_queue/CMakeLists.txt | 37 - .../libjob_queue/applications/CMakeLists.txt | 9 - .../libjob_queue/applications/block_node.c | 284 -- .../include/ert/job_queue/ext_job.h | 91 - .../include/ert/job_queue/ext_joblist.h | 51 - .../include/ert/job_queue/forward_model.h | 52 - .../include/ert/job_queue/job_list.h | 53 - .../include/ert/job_queue/job_node.h | 122 - .../include/ert/job_queue/job_queue.h | 115 - .../include/ert/job_queue/job_queue_manager.h | 55 - .../include/ert/job_queue/job_queue_status.h | 45 - .../include/ert/job_queue/local_driver.h | 53 - .../libjob_queue/include/ert/job_queue/lsb.h | 56 - .../include/ert/job_queue/lsf_driver.h | 109 - .../include/ert/job_queue/lsf_job_stat.h | 32 - .../include/ert/job_queue/queue_driver.h | 143 - .../include/ert/job_queue/rsh_driver.h | 57 - .../include/ert/job_queue/torque_driver.h | 88 - .../include/ert/job_queue/workflow.h | 56 - .../include/ert/job_queue/workflow_job.h | 64 - .../include/ert/job_queue/workflow_joblist.h | 46 - .../Ert/libjob_queue/src/CMakeLists.txt | 30 - ThirdParty/Ert/libjob_queue/src/ext_job.c | 985 ----- ThirdParty/Ert/libjob_queue/src/ext_joblist.c | 186 - .../Ert/libjob_queue/src/forward_model.c | 259 -- ThirdParty/Ert/libjob_queue/src/job_list.c | 150 - ThirdParty/Ert/libjob_queue/src/job_node.c | 626 ---- ThirdParty/Ert/libjob_queue/src/job_queue.c | 1357 ------- .../Ert/libjob_queue/src/job_queue_manager.c | 182 - .../Ert/libjob_queue/src/job_queue_status.c | 150 - .../Ert/libjob_queue/src/local_driver.c | 202 - ThirdParty/Ert/libjob_queue/src/lsb.c | 207 -- ThirdParty/Ert/libjob_queue/src/lsf_driver.c | 1306 ------- .../Ert/libjob_queue/src/queue_driver.c | 390 -- ThirdParty/Ert/libjob_queue/src/rsh_driver.c | 484 --- .../Ert/libjob_queue/src/torque_driver.c | 544 --- ThirdParty/Ert/libjob_queue/src/workflow.c | 265 -- .../Ert/libjob_queue/src/workflow_job.c | 409 -- .../Ert/libjob_queue/src/workflow_joblist.c | 99 - .../Ert/libjob_queue/tests/CMakeLists.txt | 87 - .../Ert/libjob_queue/tests/create_file.c | 28 - .../Ert/libjob_queue/tests/data/externalFail | 5 - .../Ert/libjob_queue/tests/data/externalOK | 6 - .../Ert/libjob_queue/tests/data/external_job | 5 - .../Ert/libjob_queue/tests/data/internalFail | 6 - .../Ert/libjob_queue/tests/data/internalOK | 7 - .../Ert/libjob_queue/tests/data/internal_job | 5 - .../tests/data/jobs/util/COPY_FILE | 2 - .../libjob_queue/tests/data/jobs/util/REPLACE | 6 - .../tests/data/jobs/util/STORE_FILE | 5 - .../libjob_queue/tests/data/jobs/util/SYMLINK | 6 - .../tests/data/qsub_emulators/qdel | 5 - .../tests/data/qsub_emulators/qstat | 1 - .../tests/data/qsub_emulators/qsub | 6 - .../Ert/libjob_queue/tests/ext_joblist_test.c | 35 - .../libjob_queue/tests/job_job_queue_test.c | 491 --- .../Ert/libjob_queue/tests/job_list_test.c | 80 - .../Ert/libjob_queue/tests/job_loadFail.c | 60 - .../Ert/libjob_queue/tests/job_loadOK.c | 60 - ThirdParty/Ert/libjob_queue/tests/job_lsb.c | 47 - .../tests/job_lsf_exclude_hosts_test.c | 90 - .../tests/job_lsf_library_submit_test.c | 64 - .../tests/job_lsf_parse_bsub_stdout.c | 87 - .../tests/job_lsf_remote_submit_test.c | 94 - .../tests/job_lsf_submit_library_test.c | 66 - .../Ert/libjob_queue/tests/job_lsf_test.c | 95 - .../Ert/libjob_queue/tests/job_node_test.c | 61 - .../Ert/libjob_queue/tests/job_program.c | 35 - .../libjob_queue/tests/job_program_output.c | 35 - .../tests/job_queue_driver_test.c | 170 - .../libjob_queue/tests/job_queue_manager.c | 48 - .../tests/job_queue_stress_task.c | 58 - .../tests/job_queue_stress_test.c | 313 -- .../tests/job_queue_timeout_test.c | 149 - .../Ert/libjob_queue/tests/job_status_test.c | 126 - .../tests/job_torque_submit_test.c | 117 - .../Ert/libjob_queue/tests/job_torque_test.c | 129 - .../libjob_queue/tests/job_workflow_test.c | 182 - .../Ert/libjob_queue/tests/lsf_tests.cmake | 57 - ThirdParty/Ert/librms/CMakeLists.txt | 10 - .../Ert/librms/applications/CMakeLists.txt | 26 - .../Ert/librms/applications/rms_extract.c | 104 - .../Ert/librms/applications/rms_setname.c | 56 - ThirdParty/Ert/librms/applications/rms_stat.c | 119 - ThirdParty/Ert/librms/applications/rms_test.c | 100 - ThirdParty/Ert/librms/applications/tag_list.c | 43 - .../Ert/librms/include/ert/rms/rms_export.h | 38 - .../Ert/librms/include/ert/rms/rms_file.h | 59 - .../Ert/librms/include/ert/rms/rms_stats.h | 33 - .../Ert/librms/include/ert/rms/rms_tag.h | 56 - .../Ert/librms/include/ert/rms/rms_tagkey.h | 80 - .../Ert/librms/include/ert/rms/rms_type.h | 49 - .../Ert/librms/include/ert/rms/rms_util.h | 52 - ThirdParty/Ert/librms/src/CMakeLists.txt | 19 - ThirdParty/Ert/librms/src/readme.overview | 55 - ThirdParty/Ert/librms/src/rms_export.c | 94 - ThirdParty/Ert/librms/src/rms_file.c | 492 --- ThirdParty/Ert/librms/src/rms_stats.c | 143 - ThirdParty/Ert/librms/src/rms_tag.c | 315 -- ThirdParty/Ert/librms/src/rms_tagkey.c | 718 ---- ThirdParty/Ert/librms/src/rms_type.c | 53 - ThirdParty/Ert/librms/src/rms_util.c | 178 - ThirdParty/Ert/librms/tests/CMakeLists.txt | 12 - ThirdParty/Ert/librms/tests/rms_file_test.c | 57 - ThirdParty/Ert/libsched/CMakeLists.txt | 8 - .../Ert/libsched/applications/CMakeLists.txt | 30 - .../Ert/libsched/applications/get_well_list.c | 56 - .../Ert/libsched/applications/gruptree_test.c | 92 - .../applications/perturb_history/group_rate.c | 220 -- .../applications/perturb_history/group_rate.h | 38 - .../applications/perturb_history/pert.conf | 15 - .../applications/perturb_history/pert_util.c | 186 - .../applications/perturb_history/pert_util.h | 33 - .../perturb_history/perturb_history.c | 240 -- .../applications/perturb_history/well_rate.c | 259 -- .../applications/perturb_history/well_rate.h | 46 - .../Ert/libsched/applications/sched_summary.c | 65 - .../Ert/libsched/applications/sched_test.c | 51 - .../Ert/libsched/applications/update_ir.c | 109 - .../include/ert/sched/group_history.h | 61 - .../libsched/include/ert/sched/group_index.h | 48 - .../Ert/libsched/include/ert/sched/gruptree.h | 45 - .../Ert/libsched/include/ert/sched/history.h | 76 - .../libsched/include/ert/sched/sched_blob.h | 38 - .../libsched/include/ert/sched/sched_file.h | 92 - .../include/ert/sched/sched_history.h | 57 - .../Ert/libsched/include/ert/sched/sched_kw.h | 63 - .../include/ert/sched/sched_kw_compdat.h | 40 - .../include/ert/sched/sched_kw_dates.h | 53 - .../include/ert/sched/sched_kw_gruptree.h | 47 - .../include/ert/sched/sched_kw_include.h | 37 - .../include/ert/sched/sched_kw_tstep.h | 53 - .../include/ert/sched/sched_kw_untyped.h | 53 - .../include/ert/sched/sched_kw_wconhist.h | 91 - .../include/ert/sched/sched_kw_wconinj.h | 47 - .../include/ert/sched/sched_kw_wconinje.h | 73 - .../include/ert/sched/sched_kw_wconinjh.h | 73 - .../include/ert/sched/sched_kw_wconprod.h | 42 - .../include/ert/sched/sched_kw_welspecs.h | 56 - .../libsched/include/ert/sched/sched_macros.h | 100 - .../libsched/include/ert/sched/sched_time.h | 38 - .../libsched/include/ert/sched/sched_types.h | 146 - .../libsched/include/ert/sched/sched_util.h | 49 - .../libsched/include/ert/sched/well_history.h | 62 - .../libsched/include/ert/sched/well_index.h | 49 - ThirdParty/Ert/libsched/src/CMakeLists.txt | 24 - ThirdParty/Ert/libsched/src/group_history.c | 391 -- ThirdParty/Ert/libsched/src/group_index.c | 102 - ThirdParty/Ert/libsched/src/gruptree.c | 546 --- ThirdParty/Ert/libsched/src/history.c | 280 -- ThirdParty/Ert/libsched/src/sched_blob.c | 84 - ThirdParty/Ert/libsched/src/sched_file.c | 1013 ----- ThirdParty/Ert/libsched/src/sched_history.c | 756 ---- ThirdParty/Ert/libsched/src/sched_kw.c | 564 --- .../Ert/libsched/src/sched_kw_compdat.c | 306 -- ThirdParty/Ert/libsched/src/sched_kw_dates.c | 203 - .../Ert/libsched/src/sched_kw_gruptree.c | 164 - .../Ert/libsched/src/sched_kw_include.c | 107 - ThirdParty/Ert/libsched/src/sched_kw_tstep.c | 151 - .../Ert/libsched/src/sched_kw_untyped.c | 184 - .../Ert/libsched/src/sched_kw_wconhist.c | 719 ---- .../Ert/libsched/src/sched_kw_wconinj.c | 126 - .../Ert/libsched/src/sched_kw_wconinje.c | 526 --- .../Ert/libsched/src/sched_kw_wconinjh.c | 436 --- .../Ert/libsched/src/sched_kw_wconprod.c | 134 - .../Ert/libsched/src/sched_kw_welspecs.c | 507 --- ThirdParty/Ert/libsched/src/sched_time.c | 112 - ThirdParty/Ert/libsched/src/sched_types.c | 261 -- ThirdParty/Ert/libsched/src/sched_util.c | 359 -- .../Ert/libsched/src/tests/sched_test_01.SCH | 2371 ------------ .../Ert/libsched/src/tests/sched_test_02.SCH | 24 - .../Ert/libsched/src/tests/sched_test_04.SCH | 175 - ThirdParty/Ert/libsched/src/well_history.c | 309 -- ThirdParty/Ert/libsched/src/well_index.c | 129 - ThirdParty/Ert/libsched/tests/CMakeLists.txt | 18 - .../libsched/tests/sched_history_summary.c | 72 - ThirdParty/Ert/python/CMakeLists.txt | 15 +- .../python/cmake/python_module_versions.cmake | 40 - .../cmake/python_package_versions.cmake | 46 + ThirdParty/Ert/python/python/CMakeLists.txt | 7 +- .../Ert/python/python/bin/CMakeLists.txt | 24 + .../Ert/python/python/bin/ert_tcp_server | 53 + .../Ert/python/python/bin/ert_upgrade_fs107 | 76 + ThirdParty/Ert/python/python/bin/ertshell | 35 + .../Ert/python/python/cwrap/basecclass.py | 19 +- .../Ert/python/python/cwrap/basecenum.py | 8 +- .../Ert/python/python/cwrap/basecvalue.py | 11 +- ThirdParty/Ert/python/python/cwrap/cfile.py | 3 +- .../Ert/python/python/cwrap/metacwrap.py | 5 + .../Ert/python/python/ert/CMakeLists.txt | 16 - ThirdParty/Ert/python/python/ert/__init__.py | 3 + .../python/python/ert/analysis/CMakeLists.txt | 9 - .../python/python/ert/analysis/__init__.py | 35 - .../python/ert/analysis/analysis_module.py | 188 - .../python/ert/analysis/enums/CMakeLists.txt | 10 - .../python/ert/analysis/enums/__init__.py | 3 - .../enums/analysis_module_load_status_enum.py | 35 - .../enums/analysis_module_options_enum.py | 36 - .../Ert/python/python/ert/analysis/linalg.py | 37 - .../python/python/ert/config/CMakeLists.txt | 13 - .../Ert/python/python/ert/config/__init__.py | 32 - .../python/ert/config/config_content.py | 204 - .../python/python/ert/config/config_error.py | 47 - .../python/python/ert/config/config_parser.py | 84 - .../python/ert/config/config_settings.py | 141 - .../python/ert/config/content_type_enum.py | 43 - .../python/python/ert/config/schema_item.py | 100 - .../python/ert/config/unrecognized_enum.py | 27 - .../Ert/python/python/ert/ecl/CMakeLists.txt | 4 +- .../Ert/python/python/ert/ecl/__init__.py | 10 +- ThirdParty/Ert/python/python/ert/ecl/ecl.py | 98 - .../Ert/python/python/ert/ecl/ecl_3dkw.py | 24 +- .../Ert/python/python/ert/ecl/ecl_case.py | 190 - .../Ert/python/python/ert/ecl/ecl_file.py | 69 +- .../python/python/ert/ecl/ecl_file_view.py | 81 +- .../Ert/python/python/ert/ecl/ecl_grid.py | 337 +- .../python/ert/ecl/ecl_grid_generator.py | 351 ++ .../Ert/python/python/ert/ecl/ecl_kw.py | 455 +-- .../Ert/python/python/ert/ecl/ecl_npv.py | 2 +- .../Ert/python/python/ert/ecl/ecl_queue.py | 0 .../Ert/python/python/ert/ecl/ecl_region.py | 196 +- .../Ert/python/python/ert/ecl/ecl_rft.py | 84 +- .../Ert/python/python/ert/ecl/ecl_rft_cell.py | 36 +- .../python/python/ert/ecl/ecl_smspec_node.py | 31 +- .../Ert/python/python/ert/ecl/ecl_sum.py | 3 +- .../Ert/python/python/ert/ecl/ecl_sum_node.py | 7 +- .../python/python/ert/ecl/ecl_sum_vector.py | 34 +- .../Ert/python/python/ert/ecl/ecl_type.py | 162 + .../Ert/python/python/ert/ecl/ecl_util.py | 24 - .../Ert/python/python/ert/ecl/faults/fault.py | 387 +- .../python/ert/ecl/faults/fault_block.py | 1 + .../ert/ecl/faults/fault_block_layer.py | 6 +- .../python/ert/ecl/faults/fault_collection.py | 92 +- .../Ert/python/python/ert/ecl/faults/layer.py | 6 +- .../Ert/python/python/ert/ecl/fortio.py | 73 +- .../Ert/python/python/ert/enkf/CMakeLists.txt | 56 - .../Ert/python/python/ert/enkf/__init__.py | 96 - .../Ert/python/python/ert/enkf/active_list.py | 60 - .../python/python/ert/enkf/analysis_config.py | 151 - .../python/ert/enkf/analysis_iter_config.py | 81 - .../python/ert/enkf/config/CMakeLists.txt | 13 - .../python/python/ert/enkf/config/__init__.py | 16 - .../ert/enkf/config/custom_kw_config.py | 120 - .../ert/enkf/config/enkf_config_node.py | 143 - .../python/ert/enkf/config/field_config.py | 98 - .../python/ert/enkf/config/gen_data_config.py | 99 - .../python/ert/enkf/config/gen_kw_config.py | 95 - .../python/ert/enkf/config/summary_config.py | 28 - .../python/ert/enkf/custom_kw_config_set.py | 47 - .../python/ert/enkf/data/CMakeLists.txt | 11 - .../python/python/ert/enkf/data/__init__.py | 11 - .../python/python/ert/enkf/data/custom_kw.py | 92 - .../python/python/ert/enkf/data/enkf_node.py | 138 - .../Ert/python/python/ert/enkf/data/field.py | 52 - .../python/python/ert/enkf/data/gen_data.py | 62 - .../Ert/python/python/ert/enkf/data/gen_kw.py | 152 - .../Ert/python/python/ert/enkf/ecl_config.py | 181 - .../Ert/python/python/ert/enkf/enkf_fs.py | 163 - .../python/python/ert/enkf/enkf_fs_manager.py | 304 -- .../Ert/python/python/ert/enkf/enkf_linalg.py | 20 - .../Ert/python/python/ert/enkf/enkf_main.py | 316 -- .../Ert/python/python/ert/enkf/enkf_obs.py | 174 - .../python/ert/enkf/enkf_simulation_runner.py | 44 - .../Ert/python/python/ert/enkf/enkf_state.py | 93 - .../python/python/ert/enkf/ensemble_config.py | 114 - .../python/ert/enkf/enums/CMakeLists.txt | 18 - .../python/python/ert/enkf/enums/__init__.py | 27 - .../python/ert/enkf/enums/active_mode_enum.py | 27 - .../enkf/enums/enkf_field_file_format_enum.py | 36 - .../ert/enkf/enums/enkf_fs_type_enum.py | 27 - .../ert/enkf/enums/enkf_init_modes_enum.py | 27 - .../ert/enkf/enums/enkf_obs_impl_type_enum.py | 26 - .../python/ert/enkf/enums/enkf_run_enum.py | 29 - .../ert/enkf/enums/enkf_truncation_type.py | 26 - .../ert/enkf/enums/enkf_var_type_enum.py | 33 - .../ert/enkf/enums/ert_impl_type_enum.py | 42 - .../ert/enkf/enums/gen_data_file_type_enum.py | 32 - .../ert/enkf/enums/hook_runtime_enum.py | 29 - .../ert/enkf/enums/load_fail_type_enum.py | 27 - .../ert/enkf/enums/realization_state_enum.py | 30 - .../Ert/python/python/ert/enkf/ert_log.py | 20 - .../python/python/ert/enkf/ert_run_context.py | 71 - .../python/python/ert/enkf/ert_template.py | 44 - .../python/python/ert/enkf/ert_templates.py | 49 - .../python/ert/enkf/ert_workflow_list.py | 77 - .../Ert/python/python/ert/enkf/es_update.py | 35 - .../python/ert/enkf/export/CMakeLists.txt | 15 - .../python/python/ert/enkf/export/__init__.py | 20 - .../python/ert/enkf/export/arg_loader.py | 46 - .../ert/enkf/export/custom_kw_collector.py | 66 - .../ert/enkf/export/design_matrix_reader.py | 15 - .../ert/enkf/export/gen_data_collector.py | 45 - .../export/gen_data_observation_collector.py | 73 - .../ert/enkf/export/gen_kw_collector.py | 73 - .../ert/enkf/export/misfit_collector.py | 53 - .../ert/enkf/export/summary_collector.py | 67 - .../export/summary_observation_collector.py | 65 - .../python/ert/enkf/forward_load_context.py | 51 - .../python/python/ert/enkf/hook_manager.py | 54 - .../python/python/ert/enkf/hook_workflow.py | 20 - .../Ert/python/python/ert/enkf/key_manager.py | 172 - .../python/python/ert/enkf/local_config.py | 164 - .../python/python/ert/enkf/local_dataset.py | 88 - .../python/python/ert/enkf/local_ministep.py | 64 - .../python/python/ert/enkf/local_obsdata.py | 148 - .../python/ert/enkf/local_obsdata_node.py | 59 - .../python/ert/enkf/local_updatestep.py | 43 - .../Ert/python/python/ert/enkf/meas_block.py | 98 - .../Ert/python/python/ert/enkf/meas_data.py | 99 - .../python/python/ert/enkf/model_config.py | 120 - .../Ert/python/python/ert/enkf/node_id.py | 23 - .../Ert/python/python/ert/enkf/obs_block.py | 65 - .../Ert/python/python/ert/enkf/obs_data.py | 93 - .../ert/enkf/observations/CMakeLists.txt | 11 - .../python/ert/enkf/observations/__init__.py | 5 - .../enkf/observations/block_data_config.py | 41 - .../enkf/observations/block_observation.py | 105 - .../ert/enkf/observations/gen_observation.py | 116 - .../ert/enkf/observations/obs_vector.py | 167 - .../enkf/observations/summary_observation.py | 84 - .../python/ert/enkf/plot/CMakeLists.txt | 16 - .../python/python/ert/enkf/plot/__init__.py | 10 - .../plot/block_observation_data_fetcher.py | 107 - .../python/ert/enkf/plot/data_fetcher.py | 30 - .../enkf/plot/ensemble_block_data_fetcher.py | 109 - .../ert/enkf/plot/ensemble_data_fetcher.py | 73 - .../enkf/plot/ensemble_gen_data_fetcher.py | 71 - .../ert/enkf/plot/ensemble_gen_kw_fetcher.py | 80 - .../ert/enkf/plot/observation_data_fetcher.py | 91 - .../enkf/plot/observation_gen_data_fetcher.py | 115 - .../python/ert/enkf/plot/pca_fetcher.py | 182 - .../ert/enkf/plot/refcase_data_fetcher.py | 81 - .../python/ert/enkf/plot_data/CMakeLists.txt | 17 - .../python/ert/enkf/plot_data/__init__.py | 12 - .../ert/enkf/plot_data/ensemble_plot_data.py | 54 - .../plot_data/ensemble_plot_data_vector.py | 35 - .../enkf/plot_data/ensemble_plot_gen_data.py | 83 - .../ensemble_plot_gen_data_vector.py | 48 - .../enkf/plot_data/ensemble_plot_gen_kw.py | 93 - .../plot_data/ensemble_plot_gen_kw_vector.py | 49 - .../ert/enkf/plot_data/pca_plot_data.py | 63 - .../ert/enkf/plot_data/pca_plot_vector.py | 64 - .../ert/enkf/plot_data/plot_block_data.py | 44 - .../enkf/plot_data/plot_block_data_loader.py | 98 - .../ert/enkf/plot_data/plot_block_vector.py | 39 - .../python/python/ert/enkf/plot_settings.py | 35 - .../Ert/python/python/ert/enkf/run_arg.py | 47 - .../python/python/ert/enkf/runpath_list.py | 86 - .../Ert/python/python/ert/enkf/site_config.py | 196 - .../Ert/python/python/ert/enkf/state_map.py | 143 - .../python/ert/enkf/summary_key_matcher.py | 41 - .../python/python/ert/enkf/summary_key_set.py | 51 - .../python/ert/enkf/util/CMakeLists.txt | 7 - .../python/python/ert/enkf/util/__init__.py | 1 - .../python/python/ert/enkf/util/time_map.py | 209 -- .../Ert/python/python/ert/geo/CMakeLists.txt | 3 +- .../Ert/python/python/ert/geo/__init__.py | 4 +- .../Ert/python/python/ert/geo/cpolyline.py | 2 +- .../Ert/python/python/ert/geo/geo_pointset.py | 79 + .../Ert/python/python/ert/geo/geo_region.py | 121 + .../Ert/python/python/ert/geo/surface.py | 76 +- .../python/ert/job_queue/CMakeLists.txt | 22 - .../python/python/ert/job_queue/__init__.py | 102 - .../Ert/python/python/ert/job_queue/driver.py | 158 - .../python/python/ert/job_queue/ert_plugin.py | 48 - .../python/python/ert/job_queue/ert_script.py | 116 - .../python/python/ert/job_queue/ext_job.py | 147 - .../python/ert/job_queue/ext_joblist.py | 78 - .../ert/job_queue/external_ert_script.py | 25 - .../python/ert/job_queue/forward_model.py | 49 - .../ert/job_queue/function_ert_script.py | 64 - .../Ert/python/python/ert/job_queue/job.py | 88 - .../python/ert/job_queue/job_queue_manager.py | 96 - .../ert/job_queue/job_status_type_enum.py | 51 - .../Ert/python/python/ert/job_queue/queue.py | 260 -- .../python/python/ert/job_queue/workflow.py | 105 - .../python/ert/job_queue/workflow_job.py | 181 - .../python/ert/job_queue/workflow_joblist.py | 66 - .../python/ert/job_queue/workflow_runner.py | 63 - .../Ert/python/python/ert/rms/CMakeLists.txt | 8 - .../Ert/python/python/ert/rms/__init__.py | 6 - .../Ert/python/python/ert/rms/librms.py | 0 ThirdParty/Ert/python/python/ert/rms/rms.py | 1 - .../python/python/ert/server/CMakeLists.txt | 9 - .../Ert/python/python/ert/server/__init__.py | 3 - .../python/python/ert/server/ertrpcclient.py | 228 -- .../python/python/ert/server/ertrpcserver.py | 342 -- .../python/ert/server/simulation_context.py | 95 - .../Ert/python/python/ert/test/CMakeLists.txt | 1 + .../Ert/python/python/ert/test/__init__.py | 1 + .../python/ert/test/ert_test_context.py | 28 +- .../python/ert/test/extended_testcase.py | 117 +- .../python/python/ert/test/lint_test_case.py | 61 + .../python/ert/test/source_enumerator.py | 40 +- .../Ert/python/python/ert/util/__init__.py | 3 + .../Ert/python/python/ert/util/bool_vector.py | 22 - .../Ert/python/python/ert/util/profiler.py | 10 +- .../Ert/python/python/ert/util/stringlist.py | 71 +- .../Ert/python/python/ert/util/ui_return.py | 7 +- .../python/python/ert/util/vector_template.py | 100 +- .../Ert/python/python/ert/util/version.py | 9 + .../python/python/ert/well/well_connection.py | 2 +- .../Ert/python/python/ert_gui/CMakeLists.txt | 19 - .../Ert/python/python/ert_gui/README.txt | 43 - .../Ert/python/python/ert_gui/__init__.py | 23 - .../Ert/python/python/ert_gui/about_dialog.py | 123 - .../Ert/python/python/ert_gui/ert_splash.py | 106 - .../Ert/python/python/ert_gui/ertnotifier.py | 50 - .../Ert/python/python/ert_gui/ertplot.py | 87 - .../python/ert_gui/ertwidgets/CMakeLists.txt | 23 - .../python/ert_gui/ertwidgets/__init__.py | 74 - .../python/ert_gui/ertwidgets/activelabel.py | 28 - .../ertwidgets/analysismoduleselector.py | 71 - .../analysismodulevariablespanel.py | 142 - .../python/ert_gui/ertwidgets/caselist.py | 114 - .../python/ert_gui/ertwidgets/caseselector.py | 55 - .../python/ert_gui/ertwidgets/checklist.py | 174 - .../ert_gui/ertwidgets/closabledialog.py | 73 - .../python/ert_gui/ertwidgets/customdialog.py | 115 - .../python/ert_gui/ertwidgets/legend.py | 61 - .../python/ert_gui/ertwidgets/listeditbox.py | 186 - .../ert_gui/ertwidgets/models/CMakeLists.txt | 15 - .../models/activerealizationsmodel.py | 33 - .../ertwidgets/models/all_cases_model.py | 69 - .../models/analysismodulevariablesmodel.py | 92 - .../ert_gui/ertwidgets/models/ertmodel.py | 172 - .../ert_gui/ertwidgets/models/ertsummary.py | 58 - .../ert_gui/ertwidgets/models/path_model.py | 48 - .../models/selectable_list_model.py | 43 - .../ertwidgets/models/targetcasemodel.py | 36 - .../ert_gui/ertwidgets/models/valuemodel.py | 20 - .../python/ert_gui/ertwidgets/pathchooser.py | 207 -- .../python/ert_gui/ertwidgets/searchbox.py | 69 - .../python/ert_gui/ertwidgets/stringbox.py | 102 - .../python/ert_gui/ertwidgets/summarypanel.py | 100 - .../ert_gui/ertwidgets/validateddialog.py | 131 - .../ert_gui/ertwidgets/validationsupport.py | 110 - .../Ert/python/python/ert_gui/gert_main.py | 255 -- .../python/python/ert_gui/ide/CMakeLists.txt | 12 - .../ert_gui/ide/completers/CMakeLists.txt | 7 - .../ert_gui/ide/completers/path_completer.py | 71 - .../python/python/ert_gui/ide/highlighter.py | 105 - .../Ert/python/python/ert_gui/ide/keyword.py | 96 - .../ert_gui/ide/keywords/CMakeLists.txt | 24 - .../python/ert_gui/ide/keywords/__init__.py | 2 - .../ert_gui/ide/keywords/advanced_keywords.py | 56 - .../ide/keywords/analysis_module_keywords.py | 106 - .../keywords/configuration_line_builder.py | 110 - .../ide/keywords/configuration_line_parser.py | 80 - .../ert_gui/ide/keywords/data/CMakeLists.txt | 11 - .../ert_gui/ide/keywords/data/__init__.py | 7 - .../ert_gui/ide/keywords/data/argument.py | 27 - .../ide/keywords/data/configuration_line.py | 89 - .../ert_gui/ide/keywords/data/keyword.py | 19 - .../python/ert_gui/ide/keywords/data/token.py | 36 - .../ide/keywords/data/validation_status.py | 35 - .../ide/keywords/definitions/CMakeLists.txt | 20 - .../ide/keywords/definitions/__init__.py | 16 - .../definitions/argument_definition.py | 30 - .../ide/keywords/definitions/bool_argument.py | 36 - .../configuration_line_definition.py | 32 - .../keywords/definitions/float_argument.py | 59 - .../keywords/definitions/integer_argument.py | 56 - .../definitions/keyword_definition.py | 9 - .../number_list_string_argument.py | 43 - .../ide/keywords/definitions/path_argument.py | 50 - .../keywords/definitions/percent_argument.py | 56 - .../definitions/proper_name_argument.py | 48 - .../proper_name_format_argument.py | 48 - .../proper_name_format_string_argument.py | 45 - .../definitions/range_string_argument.py | 71 - .../keywords/definitions/string_argument.py | 47 - .../ert_gui/ide/keywords/eclipse_keywords.py | 101 - .../ide/keywords/enkf_control_keywords.py | 240 -- .../ert_gui/ide/keywords/ensemble_keywords.py | 135 - .../ert_gui/ide/keywords/ert_keywords.py | 73 - .../ide/keywords/parametrization_keywords.py | 128 - .../ert_gui/ide/keywords/plot_keywords.py | 135 - .../ert_gui/ide/keywords/qc_keywords.py | 31 - .../ide/keywords/queue_system_keywords.py | 128 - .../ert_gui/ide/keywords/run_keywords.py | 144 - .../keywords/simulation_control_keywords.py | 43 - .../ide/keywords/unix_environment_keywords.py | 40 - .../ert_gui/ide/keywords/workflow_keywords.py | 115 - .../python/python/ert_gui/ide/parameter.py | 19 - .../python/ert_gui/ide/wizards/CMakeLists.txt | 9 - .../python/ert_gui/ide/wizards/__init__.py | 3 - .../python/ert_gui/ide/wizards/tree_item.py | 38 - .../python/ert_gui/ide/wizards/tree_model.py | 97 - .../python/ert_gui/ide/wizards/wizard_view.py | 42 - .../Ert/python/python/ert_gui/main_window.py | 128 - .../Ert/python/python/ert_gui/newconfig.py | 107 - .../python/ert_gui/plottery/CMakeLists.txt | 14 - .../python/ert_gui/plottery/__init__.py | 7 - .../python/ert_gui/plottery/plot_config.py | 305 -- .../ert_gui/plottery/plot_config_factory.py | 45 - .../ert_gui/plottery/plot_config_history.py | 46 - .../python/ert_gui/plottery/plot_context.py | 80 - .../ert_gui/plottery/plot_data_gatherer.py | 159 - .../python/ert_gui/plottery/plot_limits.py | 105 - .../python/ert_gui/plottery/plot_style.py | 112 - .../ert_gui/plottery/plots/CMakeLists.txt | 16 - .../python/ert_gui/plottery/plots/__init__.py | 14 - .../python/ert_gui/plottery/plots/ccsp.py | 221 -- .../ert_gui/plottery/plots/distribution.py | 77 - .../python/ert_gui/plottery/plots/ensemble.py | 56 - .../ert_gui/plottery/plots/gaussian_kde.py | 63 - .../ert_gui/plottery/plots/histogram.py | 183 - .../python/ert_gui/plottery/plots/history.py | 33 - .../ert_gui/plottery/plots/observations.py | 54 - .../ert_gui/plottery/plots/plot_tools.py | 109 - .../python/ert_gui/plottery/plots/refcase.py | 26 - .../ert_gui/plottery/plots/statistics.py | 117 - .../python/ert_gui/shell/CMakeLists.txt | 28 - .../python/python/ert_gui/shell/__init__.py | 34 - .../python/ert_gui/shell/analysis_module.py | 119 - .../Ert/python/python/ert_gui/shell/cases.py | 174 - .../python/ert_gui/shell/custom_kw_keys.py | 37 - .../Ert/python/python/ert_gui/shell/debug.py | 59 - .../ert_gui/shell/ert_shell_collection.py | 19 - .../python/ert_gui/shell/ert_shell_context.py | 20 - .../python/python/ert_gui/shell/ertshell.py | 192 - .../Ert/python/python/ert_gui/shell/export.py | 68 - .../python/ert_gui/shell/gen_data_keys.py | 32 - .../python/ert_gui/shell/gen_kw_keys.py | 31 - .../ert_gui/shell/libshell/CMakeLists.txt | 12 - .../python/ert_gui/shell/libshell/__init__.py | 6 - .../shell/libshell/shell_collection.py | 171 - .../ert_gui/shell/libshell/shell_context.py | 23 - .../ert_gui/shell/libshell/shell_function.py | 62 - .../shell/libshell/shell_path_tools.py | 26 - .../ert_gui/shell/libshell/shell_property.py | 90 - .../ert_gui/shell/libshell/shell_tools.py | 136 - .../python/ert_gui/shell/observations.py | 67 - .../python/ert_gui/shell/plot_settings.py | 178 - .../python/python/ert_gui/shell/plugins.py | 190 - .../python/python/ert_gui/shell/results.py | 50 - .../Ert/python/python/ert_gui/shell/server.py | 105 - .../python/python/ert_gui/shell/shell_plot.py | 236 -- .../python/ert_gui/shell/simulations.py | 58 - .../python/python/ert_gui/shell/smoother.py | 88 - .../python/python/ert_gui/shell/storage.py | 90 - .../python/ert_gui/shell/summary_keys.py | 95 - .../python/python/ert_gui/shell/workflows.py | 48 - .../python/ert_gui/simulation/CMakeLists.txt | 16 - .../python/ert_gui/simulation/__init__.py | 9 - .../simulation/ensemble_experiment_panel.py | 52 - .../simulation/ensemble_smoother_panel.py | 64 - .../iterated_ensemble_smoother_panel.py | 78 - .../ert_gui/simulation/models/CMakeLists.txt | 12 - .../ert_gui/simulation/models/__init__.py | 6 - .../simulation/models/base_run_model.py | 206 - .../simulation/models/ensemble_experiment.py | 30 - .../simulation/models/ensemble_smoother.py | 65 - .../models/iterated_ensemble_smoother.py | 109 - .../models/multiple_data_assimilation.py | 174 - .../simulation/models/simulations_tracker.py | 87 - .../multiple_data_assimilation_panel.py | 110 - .../python/ert_gui/simulation/progress.py | 123 - .../python/ert_gui/simulation/run_dialog.py | 208 -- .../ert_gui/simulation/simple_progress.py | 55 - .../simulation/simulation_config_panel.py | 30 - .../ert_gui/simulation/simulation_panel.py | 135 - .../python/ert_gui/tools/CMakeLists.txt | 17 - .../python/python/ert_gui/tools/__init__.py | 2 - .../ert_gui/tools/export/CMakeLists.txt | 11 - .../python/ert_gui/tools/export/__init__.py | 5 - .../tools/export/export_keyword_model.py | 113 - .../ert_gui/tools/export/export_model.py | 107 - .../ert_gui/tools/export/export_panel.py | 186 - .../ert_gui/tools/export/export_tool.py | 47 - .../python/ert_gui/tools/export/exporter.py | 77 - .../python/ert_gui/tools/help/CMakeLists.txt | 8 - .../python/ert_gui/tools/help/__init__.py | 2 - .../python/ert_gui/tools/help/help_tool.py | 26 - .../python/ert_gui/tools/help/help_window.py | 86 - .../python/ert_gui/tools/help_center.py | 107 - .../python/ert_gui/tools/ide/CMakeLists.txt | 10 - .../python/ert_gui/tools/ide/__init__.py | 4 - .../ert_gui/tools/ide/configuration_panel.py | 124 - .../python/ert_gui/tools/ide/ide_panel.py | 211 -- .../python/ert_gui/tools/ide/ide_tool.py | 24 - .../python/ert_gui/tools/ide/ide_window.py | 59 - .../ert_gui/tools/load_results/CMakeLists.txt | 10 - .../ert_gui/tools/load_results/__init__.py | 3 - .../tools/load_results/load_results_model.py | 77 - .../tools/load_results/load_results_panel.py | 101 - .../tools/load_results/load_results_tool.py | 50 - .../ert_gui/tools/manage_cases/CMakeLists.txt | 8 - .../ert_gui/tools/manage_cases/__init__.py | 1 - .../manage_cases/case_init_configuration.py | 206 - .../tools/manage_cases/manage_cases_tool.py | 20 - .../python/ert_gui/tools/plot/CMakeLists.txt | 20 - .../python/ert_gui/tools/plot/__init__.py | 20 - .../ert_gui/tools/plot/color_chooser.py | 54 - .../tools/plot/customize/CMakeLists.txt | 12 - .../ert_gui/tools/plot/customize/__init__.py | 6 - .../plot/customize/customization_view.py | 144 - .../plot/customize/customize_plot_dialog.py | 292 -- .../customize/default_customization_view.py | 69 - .../customize/limits_customization_view.py | 251 -- .../statistics_customization_view.py | 125 - .../customize/style_customization_view.py | 94 - .../tools/plot/data_type_keys_list_model.py | 77 - .../tools/plot/data_type_keys_widget.py | 78 - .../tools/plot/data_type_proxy_model.py | 92 - .../python/ert_gui/tools/plot/filter_popup.py | 58 - .../tools/plot/filterable_kw_list_model.py | 55 - .../ert_gui/tools/plot/plot_case_model.py | 69 - .../tools/plot/plot_case_selection_widget.py | 119 - .../python/ert_gui/tools/plot/plot_tool.py | 14 - .../python/ert_gui/tools/plot/plot_widget.py | 112 - .../python/ert_gui/tools/plot/plot_window.py | 199 - .../ert_gui/tools/plot/style_chooser.py | 161 - .../ert_gui/tools/plot/widgets/CMakeLists.txt | 9 - .../ert_gui/tools/plot/widgets/__init__.py | 1 - .../tools/plot/widgets/clearable_line_edit.py | 97 - .../plot/widgets/copy_style_to_dialog.py | 62 - .../tools/plot/widgets/custom_date_edit.py | 53 - .../ert_gui/tools/plugins/CMakeLists.txt | 11 - .../python/ert_gui/tools/plugins/__init__.py | 5 - .../python/ert_gui/tools/plugins/plugin.py | 54 - .../ert_gui/tools/plugins/plugin_handler.py | 37 - .../ert_gui/tools/plugins/plugin_runner.py | 91 - .../ert_gui/tools/plugins/plugins_tool.py | 34 - .../tools/plugins/process_job_dialog.py | 121 - .../ert_gui/tools/run_analysis/CMakeLists.txt | 7 - .../ert_gui/tools/run_analysis/__init__.py | 2 - .../tools/run_analysis/run_analysis_panel.py | 47 - .../tools/run_analysis/run_analysis_tool.py | 68 - .../Ert/python/python/ert_gui/tools/tool.py | 57 - .../ert_gui/tools/workflows/CMakeLists.txt | 9 - .../ert_gui/tools/workflows/__init__.py | 2 - .../tools/workflows/run_workflow_widget.py | 146 - .../tools/workflows/workflow_dialog.py | 46 - .../ert_gui/tools/workflows/workflows_tool.py | 20 - ThirdParty/Ert/python/python/test_env.py.in | 6 + ThirdParty/Ert/python/tests/CMakeLists.txt | 27 +- .../Ert/python/tests/core/CMakeLists.txt | 10 - .../Ert/python/tests/core/ecl/__init__.py | 0 .../python/tests/core/ecl/test_deprecation.py | 258 -- .../Ert/python/tests/core/ecl/test_grid.py | 245 -- .../python/tests/core/ecl/test_legacy_ecl.py | 43 - .../python/tests/core/geometry/CMakeLists.txt | 24 - .../python/tests/core/geometry/__init__.py | 0 .../Ert/python/tests/core/util/CMakeLists.txt | 41 - .../Ert/python/tests/core/util/__init__.py | 0 .../Ert/python/tests/core/well/CMakeLists.txt | 14 - .../Ert/python/tests/core/well/__init__.py | 0 .../Ert/python/tests/cwrap/CMakeLists.txt | 12 +- .../Ert/python/tests/cwrap/test_metawrap.py | 17 +- .../tests/{core => }/ecl/CMakeLists.txt | 8 +- .../models => tests/ecl}/__init__.py | 0 .../Ert/python/tests/ecl/test_deprecation.py | 50 + .../tests/{core => }/ecl/test_ecl_3dkw.py | 24 +- .../tests/{core => }/ecl/test_ecl_cmp.py | 0 .../tests/{core => }/ecl/test_ecl_file.py | 80 +- .../{core => }/ecl/test_ecl_file_statoil.py | 2 +- .../{core => }/ecl/test_ecl_init_file.py | 2 +- .../tests/{core => }/ecl/test_ecl_kw.py | 106 +- .../{core => }/ecl/test_ecl_kw_statoil.py | 20 +- .../{core => }/ecl/test_ecl_restart_file.py | 2 +- .../tests/{core => }/ecl/test_ecl_sum.py | 0 .../{core => }/ecl/test_ecl_sum_tstep.py | 0 .../{core => }/ecl/test_ecl_sum_vector.py | 0 .../Ert/python/tests/ecl/test_ecl_type.py | 93 + .../tests/{core => }/ecl/test_ecl_util.py | 0 .../tests/{core => }/ecl/test_fault_blocks.py | 42 +- .../ecl/test_fault_blocks_statoil.py | 4 +- .../tests/{core => }/ecl/test_faults.py | 34 +- .../tests/{core => }/ecl/test_fortio.py | 14 +- .../tests/{core => }/ecl/test_geertsma.py | 24 +- .../python/tests/{core => }/ecl/test_grav.py | 4 +- .../tests/{core => }/ecl/test_grdecl.py | 0 ThirdParty/Ert/python/tests/ecl/test_grid.py | 553 +++ .../tests/{core => }/ecl/test_grid_statoil.py | 36 +- .../tests/{core => }/ecl/test_indexed_read.py | 12 +- .../tests/{core => }/ecl/test_kw_function.py | 4 +- .../python/tests/{core => }/ecl/test_layer.py | 2 +- .../python/tests/{core => }/ecl/test_npv.py | 0 .../Ert/python/tests/ecl/test_region.py | 37 + .../test_region_statoil.py} | 18 +- .../tests/{core => }/ecl/test_removed.py | 5 +- .../tests/{core => }/ecl/test_restart.py | 4 +- .../python/tests/{core => }/ecl/test_rft.py | 6 +- .../tests/{core => }/ecl/test_rft_cell.py | 7 - .../tests/{core => }/ecl/test_rft_statoil.py | 2 +- .../{core => }/ecl/test_statoil_faults.py | 6 +- .../python/tests/{core => }/ecl/test_sum.py | 0 .../tests/{core => }/ecl/test_sum_statoil.py | 26 +- .../Ert/python/tests/ert/CMakeLists.txt | 14 - ThirdParty/Ert/python/tests/ert/__init__.py | 0 .../python/tests/ert/analysis/CMakeLists.txt | 19 - .../Ert/python/tests/ert/analysis/__init__.py | 0 .../ert/analysis/test_analysis_module.py | 153 - .../python/tests/ert/analysis/test_linalg.py | 47 - .../tests/ert/analysis/test_options_enum.py | 25 - .../Ert/python/tests/ert/analysis/test_rml.py | 129 - .../tests/ert/analysis/test_std_enkf.py | 52 - .../tests/ert/analysis/test_std_enkf_debug.py | 53 - .../python/tests/ert/config/CMakeLists.txt | 8 - .../Ert/python/tests/ert/config/__init__.py | 0 .../python/tests/ert/config/test_config.py | 366 -- .../Ert/python/tests/ert/enkf/CMakeLists.txt | 87 - .../Ert/python/tests/ert/enkf/__init__.py | 0 .../python/tests/ert/enkf/data/CMakeLists.txt | 21 - .../python/tests/ert/enkf/data/__init__.py | 1 - .../tests/ert/enkf/data/test_custom_kw.py | 123 - .../ert/enkf/data/test_custom_kw_config.py | 130 - .../tests/ert/enkf/data/test_field_config.py | 31 - .../tests/ert/enkf/data/test_gen_data.py | 30 - .../ert/enkf/data/test_gen_data_config.py | 74 - .../python/tests/ert/enkf/data/test_gen_kw.py | 134 - .../tests/ert/enkf/data/test_gen_kw_config.py | 55 - .../tests/ert/enkf/export/CMakeLists.txt | 31 - .../python/tests/ert/enkf/export/__init__.py | 0 .../tests/ert/enkf/export/test_arg_loader.py | 24 - .../enkf/export/test_custom_kw_collector.py | 40 - .../ert/enkf/export/test_design_matrix.py | 94 - .../tests/ert/enkf/export/test_export_join.py | 90 - .../enkf/export/test_gen_data_collector.py | 21 - .../test_gen_data_observation_collector.py | 33 - .../ert/enkf/export/test_gen_kw_collector.py | 32 - .../ert/enkf/export/test_misfit_collector.py | 23 - .../ert/enkf/export/test_numpy_and_pandas.py | 82 - .../ert/enkf/export/test_summary_collector.py | 34 - .../test_summary_observation_collector.py | 45 - .../python/tests/ert/enkf/plot/CMakeLists.txt | 12 - .../python/tests/ert/enkf/plot/__init__.py | 1 - .../tests/ert/enkf/plot/test_plot_data.py | 101 - .../tests/ert/enkf/plot/test_plot_settings.py | 56 - .../python/tests/ert/enkf/test_active_list.py | 66 - .../tests/ert/enkf/test_analysis_config.py | 48 - .../ert/enkf/test_analysis_iter_config.py | 37 - .../python/tests/ert/enkf/test_block_obs.py | 55 - .../ert/enkf/test_custom_kw_config_set.py | 80 - .../python/tests/ert/enkf/test_deprecation.py | 37 - .../python/tests/ert/enkf/test_ecl_config.py | 135 - .../Ert/python/tests/ert/enkf/test_enkf.py | 189 - .../Ert/python/tests/ert/enkf/test_enkf_fs.py | 67 - .../tests/ert/enkf/test_enkf_fs_manager1.py | 45 - .../tests/ert/enkf/test_enkf_fs_manager2.py | 37 - .../tests/ert/enkf/test_enkf_library.py | 56 - .../enkf/test_enkf_load_results_manually.py | 36 - .../python/tests/ert/enkf/test_enkf_obs.py | 258 -- .../tests/ert/enkf/test_ensemble_config.py | 17 - .../python/tests/ert/enkf/test_ert_context.py | 95 - .../Ert/python/tests/ert/enkf/test_ert_log.py | 31 - .../python/tests/ert/enkf/test_es_update.py | 19 - .../tests/ert/enkf/test_field_config.py | 73 - .../tests/ert/enkf/test_field_export.py | 81 - .../ert/enkf/test_forward_load_context.py | 9 - .../Ert/python/tests/ert/enkf/test_gen_obs.py | 52 - .../tests/ert/enkf/test_hook_workflow.py | 9 - .../python/tests/ert/enkf/test_labscale.py | 76 - .../Ert/python/tests/ert/enkf/test_linalg.py | 39 - .../tests/ert/enkf/test_local_config.py | 187 - .../tests/ert/enkf/test_local_obsdata_node.py | 22 - .../python/tests/ert/enkf/test_meas_block.py | 103 - .../python/tests/ert/enkf/test_meas_data.py | 75 - .../python/tests/ert/enkf/test_obs_block.py | 51 - .../python/tests/ert/enkf/test_obs_data.py | 53 - .../tests/ert/enkf/test_runpath_list.py | 155 - .../python/tests/ert/enkf/test_state_map.py | 105 - .../ert/enkf/test_summary_key_matcher.py | 28 - .../tests/ert/enkf/test_summary_key_set.py | 99 - .../python/tests/ert/enkf/test_summary_obs.py | 41 - .../python/tests/ert/enkf/test_time_map.py | 184 - .../Ert/python/tests/ert/enkf/test_update.py | 82 - .../python/tests/ert/job_queue/CMakeLists.txt | 25 - .../python/tests/ert/job_queue/__init__.py | 0 .../tests/ert/job_queue/test_ert_plugin.py | 86 - .../tests/ert/job_queue/test_ert_script.py | 82 - .../tests/ert/job_queue/test_ext_job.py | 77 - .../ert/job_queue/test_function_ert_script.py | 27 - .../tests/ert/job_queue/test_job_queue.py | 11 - .../tests/ert/job_queue/test_workflow.py | 56 - .../tests/ert/job_queue/test_workflow_job.py | 101 - .../ert/job_queue/test_workflow_joblist.py | 42 - .../ert/job_queue/test_workflow_runner.py | 128 - .../tests/ert/job_queue/workflow_common.py | 140 - .../Ert/python/tests/ert/run/CMakeLists.txt | 8 - .../Ert/python/tests/ert/run/__init__.py | 0 .../Ert/python/tests/ert/run/test_run.py | 67 - .../Ert/python/tests/ert/sched/CMakeLists.txt | 10 - .../Ert/python/tests/ert/sched/__init__.py | 0 .../Ert/python/tests/ert/sched/test_sched.py | 61 - .../python/tests/ert/server/CMakeLists.txt | 12 - .../Ert/python/tests/ert/server/__init__.py | 43 - .../tests/ert/server/test_rpc_service.py | 186 - .../tests/ert/server/test_rpc_storage.py | 124 - .../ert/server/test_simulation_context.py | 97 - .../python/tests/ert/testcase/CMakeLists.txt | 10 - .../Ert/python/tests/ert/testcase/__init__.py | 1 - .../tests/ert/testcase/test_mini_config.py | 49 - .../tests/ert/testcase/test_testcase.py | 26 - .../Ert/python/tests/geometry/CMakeLists.txt | 28 + .../ide => tests/geometry}/__init__.py | 0 .../{core => }/geometry/test_convex_hull.py | 0 .../{core => }/geometry/test_cpolyline.py | 0 .../geometry/test_cpolyline_collection.py | 0 .../tests/geometry/test_geo_pointset.py | 27 + .../python/tests/geometry/test_geo_region.py | 88 + .../geometry/test_geometry_tools.py | 0 .../{core => }/geometry/test_intersection.py | 0 .../geometry/test_point_in_polygon.py | 0 .../geometry/test_polygon_slicing.py | 0 .../{core => }/geometry/test_polyline.py | 0 .../tests/{core => }/geometry/test_surface.py | 10 + .../Ert/python/tests/gui/CMakeLists.txt | 12 - ThirdParty/Ert/python/tests/gui/__init__.py | 0 .../python/tests/gui/ertshell/CMakeLists.txt | 27 - .../Ert/python/tests/gui/ertshell/__init__.py | 0 .../gui/ertshell/ert_shell_test_context.py | 56 - .../gui/ertshell/test_ertshell_analysis.py | 46 - .../gui/ertshell/test_ertshell_context.py | 31 - .../ertshell/test_ertshell_observations.py | 28 - .../ertshell/test_ertshell_plot_settings.py | 60 - .../gui/ertshell/test_ertshell_server.py | 23 - .../gui/ertshell/test_ertshell_smoother.py | 53 - .../gui/ertshell/test_shell_collection.py | 97 - .../tests/gui/ertshell/test_shell_function.py | 148 - .../tests/gui/ertshell/test_shell_property.py | 317 -- .../Ert/python/tests/gui/ide/CMakeLists.txt | 37 - .../Ert/python/tests/gui/ide/__init__.py | 0 .../tests/gui/ide/test_bool_argument.py | 53 - .../tests/gui/ide/test_configuration_line.py | 72 - .../ide/test_configuration_line_builder.py | 130 - .../ide/test_configuration_line_definition.py | 45 - .../gui/ide/test_configuration_line_parser.py | 98 - .../python/tests/gui/ide/test_ert_keywords.py | 186 - .../tests/gui/ide/test_float_argument.py | 99 - .../tests/gui/ide/test_integer_argument.py | 99 - .../tests/gui/ide/test_path_argument.py | 15 - .../tests/gui/ide/test_percent_argument.py | 99 - .../gui/ide/test_proper_name_argument.py | 18 - .../ide/test_proper_name_format_argument.py | 18 - ...test_proper_name_format_string_argument.py | 21 - .../gui/ide/test_range_string_argument.py | 28 - .../Ert/python/tests/gui/ide/test_tokens.py | 60 - .../tests/gui/ide/wizards/CMakeLists.txt | 8 - .../python/tests/gui/ide/wizards/__init__.py | 0 .../gui/ide/wizards/test_tree_structure.py | 65 - .../python/tests/gui/plottery/CMakeLists.txt | 12 - .../Ert/python/tests/gui/plottery/__init__.py | 0 .../gui/plottery/test_plot_config_history.py | 46 - .../tests/gui/plottery/test_plot_limits.py | 124 - .../tests/gui/plottery/test_plot_style.py | 164 - .../gui/test_multiple_data_assimilation.py | 44 - .../python/tests/share/test_synthesizer.py | 2 +- .../test_pylint.py} | 29 +- .../Ert/python/tests/util/CMakeLists.txt | 41 + .../ide/completers => tests/util}/__init__.py | 0 .../tests/{core => }/util/test_arg_pack.py | 2 +- .../tests/{core => }/util/test_cstring.py | 0 .../{core => }/util/test_cthread_pool.py | 2 +- .../tests/{core => }/util/test_ctime.py | 0 .../python/tests/{core => }/util/test_hash.py | 0 .../{core => }/util/test_lookup_table.py | 0 .../tests/{core => }/util/test_matrix.py | 0 .../{core => }/util/test_path_context.py | 0 .../python/tests/{core => }/util/test_rng.py | 0 .../tests/{core => }/util/test_spawn.py | 0 .../python/tests/{core => }/util/test_stat.py | 0 .../tests/{core => }/util/test_string_list.py | 6 +- .../{core => }/util/test_substitution_list.py | 0 .../tests/{core => }/util/test_thread_pool.py | 0 .../tests/{core => }/util/test_ui_return.py | 0 .../tests/{core => }/util/test_vectors.py | 0 .../tests/{core => }/util/test_version.py | 15 + .../tests/{core => }/util/test_work_area.py | 0 .../Ert/python/tests/well/CMakeLists.txt | 14 + .../python/tests/{core => well}/__init__.py | 0 .../tests/{core => }/well/test_ecl_well.py | 0 .../tests/{core => }/well/test_ecl_well2.py | 0 .../tests/{core => }/well/test_ecl_well3.py | 0 ThirdParty/Ert/release-notes.txt | 169 +- ThirdParty/Ert/script/download-pr | 78 + ThirdParty/Ert/script/job_dispatch.py | 354 -- .../Ert/share/gui/doc/documentation.txt | 70 - ThirdParty/Ert/share/gui/doc/info.txt | 244 -- ThirdParty/Ert/share/gui/doc/initializers | 201 - ThirdParty/Ert/share/gui/doc/run_info | 36 - ThirdParty/Ert/share/gui/doc/tmp_info.txt | 69 - .../help/config/analysis/analysis_module.html | 1 - .../analysis/iterated_analysis_module.html | 1 - .../gui/help/config/init/history_length.html | 1 - .../add_fixed_length_schedule_kw.html | 1 - .../help/config/keywords/add_static_kw.html | 15 - .../help/config/keywords/analysis_copy.html | 1 - .../config/keywords/analysis_enkf_update.html | 1 - .../help/config/keywords/analysis_load.html | 1 - .../help/config/keywords/analysis_select.html | 1 - .../config/keywords/analysis_set_var.html | 1 - .../help/config/keywords/analysis_update.html | 1 - .../gui/help/config/keywords/case_table.html | 1 - .../gui/help/config/keywords/config_help.py | 12 - .../gui/help/config/keywords/create_case.html | 1 - .../gui/help/config/keywords/data_file.html | 1 - .../gui/help/config/keywords/data_kw.html | 1 - .../help/config/keywords/data_ranking.html | 1 - .../gui/help/config/keywords/define.html | 1 - .../help/config/keywords/delete_runpath.html | 1 - .../gui/help/config/keywords/eclbase.html | 5 - .../gui/help/config/keywords/end_date.html | 1 - .../gui/help/config/keywords/enkf_alpha.html | 1 - .../help/config/keywords/enkf_bootstrap.html | 1 - .../help/config/keywords/enkf_cv_folds.html | 1 - .../config/keywords/enkf_force_ncomp.html | 1 - .../help/config/keywords/enkf_local_cv.html | 1 - .../keywords/enkf_merge_observations.html | 1 - .../gui/help/config/keywords/enkf_mode.html | 1 - .../gui/help/config/keywords/enkf_ncomp.html | 1 - .../help/config/keywords/enkf_pen_press.html | 1 - .../gui/help/config/keywords/enkf_rerun.html | 1 - .../help/config/keywords/enkf_scaling.html | 1 - .../help/config/keywords/enkf_truncation.html | 1 - .../help/config/keywords/ensemble_run.html | 1 - .../gui/help/config/keywords/enspath.html | 1 - .../help/config/keywords/export_field.html | 1 - .../keywords/export_field_ecl_grdecl.html | 1 - .../keywords/export_field_rms_roff.html | 1 - .../help/config/keywords/export_ranking.html | 1 - .../share/gui/help/config/keywords/field.html | 1 - .../help/config/keywords/forward_model.html | 1 - .../gui/help/config/keywords/gen_data.html | 1 - .../gui/help/config/keywords/gen_kw.html | 1 - .../gui/help/config/keywords/gen_param.html | 1 - .../share/gui/help/config/keywords/grid.html | 1 - .../help/config/keywords/history_source.html | 9 - .../gui/help/config/keywords/image_type.html | 1 - .../help/config/keywords/image_viewer.html | 5 - .../keywords/init_case_from_existing.html | 1 - .../config/keywords/init_misfit_table.html | 1 - .../help/config/keywords/init_section.html | 6 - .../gui/help/config/keywords/install_job.html | 1 - .../gui/help/config/keywords/job_script.html | 7 - .../gui/help/config/keywords/jobname.html | 1 - .../gui/help/config/keywords/keywords.txt | 94 - .../help/config/keywords/license_path.html | 1 - .../help/config/keywords/load_results.html | 1 - .../config/keywords/load_results_iter.html | 1 - .../help/config/keywords/local_config.html | 1 - .../gui/help/config/keywords/log_file.html | 1 - .../gui/help/config/keywords/log_level.html | 1 - .../gui/help/config/keywords/lsf_queue.html | 2 - .../help/config/keywords/lsf_resources.html | 1 - .../gui/help/config/keywords/lsf_server.html | 1 - .../help/config/keywords/max_resample.html | 1 - .../config/keywords/max_running_local.html | 1 - .../help/config/keywords/max_running_lsf.html | 1 - .../help/config/keywords/max_running_rsh.html | 1 - .../gui/help/config/keywords/max_runtime.html | 1 - .../gui/help/config/keywords/max_submit.html | 1 - .../config/keywords/min_realizations.html | 1 - .../config/keywords/num_realizations.html | 1 - .../gui/help/config/keywords/obs_config.html | 1 - .../config/keywords/observation_ranking.html | 1 - .../gui/help/config/keywords/plot_driver.html | 7 - .../help/config/keywords/plot_errorbar.html | 1 - .../config/keywords/plot_errorbar_max.html | 5 - .../gui/help/config/keywords/plot_height.html | 2 - .../gui/help/config/keywords/plot_path.html | 3 - .../help/config/keywords/plot_refcase.html | 1 - .../gui/help/config/keywords/plot_width.html | 2 - .../config/keywords/pre_clear_runpath.html | 1 - .../gui/help/config/keywords/qc_path.html | 1 - .../gui/help/config/keywords/qc_workflow.html | 1 - .../help/config/keywords/queue_system.html | 8 - .../gui/help/config/keywords/refcase.html | 1 - .../help/config/keywords/refcase_list.html | 1 - .../gui/help/config/keywords/rerun_start.html | 1 - .../gui/help/config/keywords/result_path.html | 1 - .../gui/help/config/keywords/rft_config.html | 1 - .../gui/help/config/keywords/rftpath.html | 1 - .../gui/help/config/keywords/rsh_command.html | 1 - .../gui/help/config/keywords/rsh_host.html | 6 - .../help/config/keywords/run_smoother.html | 1 - .../keywords/run_smoother_with_iter.html | 1 - .../help/config/keywords/run_template.html | 1 - .../gui/help/config/keywords/runpath.html | 12 - .../help/config/keywords/runpath_file.html | 1 - .../help/config/keywords/schedule_file.html | 1 - .../keywords/schedule_prediction_file.html | 1 - .../gui/help/config/keywords/select_case.html | 1 - .../gui/help/config/keywords/setenv.html | 4 - .../config/keywords/stop_long_running.html | 1 - .../gui/help/config/keywords/summary.html | 1 - .../gui/help/config/keywords/surface.html | 1 - .../help/config/keywords/update_log_path.html | 1 - .../gui/help/config/keywords/update_path.html | 1 - .../share/gui/help/config/run/runpath.html | 3 - .../simulation/active_realizations.html | 1 - .../config/simulation/analysis_module.html | 1 - .../iterated_target_case_format.html | 1 - .../config/simulation/iteration_weights.html | 7 - .../simulation/number_of_iterations.html | 1 - .../sensitivity_parameter_constant_value.html | 1 - .../sensitivity_parameter_is_included.html | 1 - .../sensitivity_target_case_format.html | 1 - .../help/config/simulation/target_case.html | 1 - .../Ert/share/gui/help/init/case_list.html | 1 - .../gui/help/init/current_case_selection.html | 1 - .../help/init/initialize_from_existing.html | 1 - .../help/init/initialize_from_scratch.html | 1 - .../gui/help/init/select_case_for_info.html | 1 - .../share/gui/help/init/select_members.html | 1 - .../gui/help/init/select_parameters.html | 1 - .../gui/help/init/selected_case_info.html | 1 - .../Ert/share/gui/help/init/source_case.html | 1 - .../share/gui/help/run/simulation_mode.html | 4 - .../share/gui/help/run/start_simulation.html | 1 - .../Ert/share/gui/help/run/workflow.html | 1 - ThirdParty/Ert/share/gui/help/template.html | 1 - .../Ert/share/gui/help/tools/export.html | 1 - ThirdParty/Ert/share/gui/help/tools/help.html | 1 - ThirdParty/Ert/share/gui/help/tools/ide.html | 1 - .../share/gui/help/tools/manage_cases.html | 1 - ThirdParty/Ert/share/gui/help/tools/plot.html | 1 - .../Ert/share/gui/help/tools/workflows.html | 1 - .../Ert/share/gui/help/welcome_to_ert.html | 17 - ThirdParty/Ert/share/gui/img/add.png | Bin 394 -> 0 bytes .../share/gui/img/application/window_icon.png | Bin 11344 -> 0 bytes .../img/application/window_icon_cutout.png | Bin 33266 -> 0 bytes ThirdParty/Ert/share/gui/img/calendar.png | Bin 705 -> 0 bytes ThirdParty/Ert/share/gui/img/checked.png | Bin 243 -> 0 bytes ThirdParty/Ert/share/gui/img/copy_from.png | Bin 3890 -> 0 bytes ThirdParty/Ert/share/gui/img/copy_to.png | Bin 3795 -> 0 bytes .../Ert/share/gui/img/ide/chart_curve_add.png | Bin 2257 -> 0 bytes ThirdParty/Ert/share/gui/img/ide/cog.png | Bin 2104 -> 0 bytes ThirdParty/Ert/share/gui/img/ide/cog_edit.png | Bin 2230 -> 0 bytes .../share/gui/img/ide/control_play_blue.png | Bin 1971 -> 0 bytes .../Ert/share/gui/img/ide/database_gear.png | Bin 1923 -> 0 bytes ThirdParty/Ert/share/gui/img/ide/disk.png | Bin 1555 -> 0 bytes .../Ert/share/gui/img/ide/gear_in_play.png | Bin 2019 -> 0 bytes ThirdParty/Ert/share/gui/img/ide/help.png | Bin 2271 -> 0 bytes ThirdParty/Ert/share/gui/img/ide/loading.gif | Bin 3897 -> 0 bytes ThirdParty/Ert/share/gui/img/ide/plugin.png | Bin 1743 -> 0 bytes .../Ert/share/gui/img/ide/readme-fatcow.txt | 21 - ThirdParty/Ert/share/gui/img/ide/save_as.png | Bin 1590 -> 0 bytes .../Ert/share/gui/img/ide/small/add.png | Bin 698 -> 0 bytes .../gui/img/ide/small/chart_curve_go.png | Bin 819 -> 0 bytes .../Ert/share/gui/img/ide/small/cog_edit.png | Bin 909 -> 0 bytes .../Ert/share/gui/img/ide/small/delete.png | Bin 695 -> 0 bytes .../Ert/share/gui/img/ide/small/folder.png | Bin 632 -> 0 bytes .../Ert/share/gui/img/ide/table_export.png | Bin 1144 -> 0 bytes .../Ert/share/gui/img/ide/table_import.png | Bin 1122 -> 0 bytes .../gui/img/ide/to_do_list_checked_1.png | Bin 1640 -> 0 bytes .../Ert/share/gui/img/ide/transform_scale.png | Bin 1255 -> 0 bytes ThirdParty/Ert/share/gui/img/ide/widgets.png | Bin 2363 -> 0 bytes ThirdParty/Ert/share/gui/img/notchecked.png | Bin 194 -> 0 bytes ThirdParty/Ert/share/gui/img/page_copy.png | Bin 593 -> 0 bytes ThirdParty/Ert/share/gui/img/redo.png | Bin 1288 -> 0 bytes ThirdParty/Ert/share/gui/img/remove.png | Bin 266 -> 0 bytes .../Ert/share/gui/img/remove_favorite.png | Bin 661 -> 0 bytes ThirdParty/Ert/share/gui/img/splash.jpg | Bin 43888 -> 0 bytes ThirdParty/Ert/share/gui/img/undo.png | Bin 1307 -> 0 bytes ThirdParty/Ert/share/gui/img/update.png | Bin 814 -> 0 bytes .../Ert/share/lib/synthesizer/__init__.py | 4 - .../share/lib/synthesizer/oil_simulator.py | 168 - .../Ert/share/lib/synthesizer/perlin.py | 57 - .../share/lib/synthesizer/prime_generator.py | 40 - .../share/lib/synthesizer/shaped_perlin.py | 106 - ThirdParty/Ert/share/site-config | 7 - .../Ert/share/viewer/shaders/default.fp | 4 - .../Ert/share/viewer/shaders/default.vp | 33 - .../Ert/share/viewer/shaders/texturing.fp | 49 - .../jobs/internal-gui/config/CREATE_CASE | 6 - .../jobs/internal-gui/config/CSV_EXPORT | 9 - .../internal-gui/config/EXPORT_MISFIT_DATA | 6 - .../config/GEN_DATA_RFT_CSV_EXPORT | 8 - .../config/INIT_CASE_FROM_EXISTING | 7 - .../jobs/internal-gui/config/SELECT_CASE | 6 - .../internal-gui/config/UPDATE_RUNPATH_LIST | 6 - .../jobs/internal-gui/scripts/create_case.py | 7 - .../jobs/internal-gui/scripts/csv_export.py | 189 - .../scripts/export_misfit_data.py | 78 - .../scripts/gen_data_rft_export.py | 199 - .../scripts/init_case_from_existing.py | 16 - .../jobs/internal-gui/scripts/select_case.py | 9 - .../scripts/update_runpath_list.py | 37 - .../jobs/internal-tui/config/CREATE_CASE | 6 - .../config/INIT_CASE_FROM_EXISTING | 7 - .../jobs/internal-tui/config/PLOT_ALL_SUMMARY | 5 - .../jobs/internal-tui/config/SELECT_CASE | 6 - .../internal/config/ANALYSIS_SELECT_MODULE | 5 - .../jobs/internal/config/ANALYSIS_UPDATE | 6 - .../jobs/internal/config/DATA_RANKING | 8 - .../jobs/internal/config/ENSEMBLE_RUN | 6 - .../workflows/jobs/internal/config/EXIT_ERT | 4 - .../jobs/internal/config/EXPORT_FIELD | 7 - .../internal/config/EXPORT_FIELD_ECL_GRDECL | 7 - .../internal/config/EXPORT_FIELD_RMS_ROFF | 7 - .../jobs/internal/config/EXPORT_RANKING | 7 - .../jobs/internal/config/EXPORT_RUNPATH | 3 - .../jobs/internal/config/INIT_MISFIT_TABLE | 4 - .../jobs/internal/config/LOAD_RESULTS | 3 - .../jobs/internal/config/LOAD_RESULTS_ITER | 5 - .../jobs/internal/config/OBSERVATION_RANKING | 4 - .../internal/config/RUN_ITERATED_SMOOTHER | 4 - .../jobs/internal/config/RUN_SMOOTHER | 7 - .../internal/config/RUN_SMOOTHER_WITH_ITER | 8 - .../workflows/jobs/internal/config/SCALE_STD | 5 - .../internal/config/STD_SCALE_CORRELATED_OBS | 3 - .../local/config/gen_data/REFCASE.SMSPEC | Bin 340 -> 0 bytes .../local/config/gen_data/REFCASE.UNSMRY | Bin 11088 -> 0 bytes .../test-data/local/config/gen_data/config | 8 - .../local/config/gen_data/gen_obs_data | 4 - .../local/config/gen_data/observations | 19 - .../Ert/test-data/local/config/simple_config | 214 -- .../custom_kw/Observations/observation_1 | 5 - .../custom_kw/Observations/observation_2 | 5 - .../custom_kw/Observations/observation_3 | 5 - .../local/custom_kw/Observations/observations | 17 - .../custom_kw/Observations/perlin_obs_1.txt | 100 - .../custom_kw/Observations/perlin_obs_2.txt | 100 - .../custom_kw/Observations/perlin_obs_3.txt | 100 - .../custom_kw/Parameters/PERLIN_PARAMS.txt | 7 - .../Ert/test-data/local/custom_kw/RandomSeed | 1 - .../local/custom_kw/Refcase/CASE.EGRID | Bin 22000 -> 0 bytes .../local/custom_kw/Template/PERLIN_TEMPLATE | 7 - .../fail_storage/Run/realisation-0/iter-0/OK | 1 - .../Run/realisation-0/iter-0/aggregated.txt | 4 - .../realisation-0/iter-0/aggregator.stderr | 0 .../realisation-0/iter-0/aggregator.stdout | 0 .../Run/realisation-0/iter-0/parameters.txt | 7 - .../Run/realisation-0/iter-0/perlin.stderr | 0 .../Run/realisation-0/iter-0/perlin.stdout | 0 .../Run/realisation-0/iter-0/perlin_1.txt | 100 - .../Run/realisation-0/iter-0/perlin_2.txt | 100 - .../Run/realisation-0/iter-0/perlin_3.txt | 100 - .../realisation-0/iter-0/perlin_fail.status | 1 - .../realisation-0/iter-0/perlin_params.txt | 7 - .../Run/realisation-0/iter-0/realization.ok | 1 - .../fail_storage/Run/realisation-1/iter-0/OK | 1 - .../Run/realisation-1/iter-0/aggregated.txt | 4 - .../realisation-1/iter-0/aggregator.stderr | 0 .../realisation-1/iter-0/aggregator.stdout | 0 .../Run/realisation-1/iter-0/parameters.txt | 7 - .../Run/realisation-1/iter-0/perlin.stderr | 0 .../Run/realisation-1/iter-0/perlin.stdout | 0 .../Run/realisation-1/iter-0/perlin_2.txt | 100 - .../Run/realisation-1/iter-0/perlin_3.txt | 100 - .../realisation-1/iter-0/perlin_fail.status | 1 - .../realisation-1/iter-0/perlin_params.txt | 7 - .../Run/realisation-1/iter-0/realization.ok | 1 - .../Run/realisation-2/iter-0/ERROR | 8 - .../Run/realisation-2/iter-0/EXIT | 8 - .../Run/realisation-2/iter-0/aggregated.txt | 4 - .../realisation-2/iter-0/aggregator.stderr | 0 .../realisation-2/iter-0/aggregator.stdout | 0 .../Run/realisation-2/iter-0/parameters.txt | 7 - .../Run/realisation-2/iter-0/perlin.stderr | 0 .../Run/realisation-2/iter-0/perlin.stdout | 0 .../Run/realisation-2/iter-0/perlin_1.txt | 100 - .../Run/realisation-2/iter-0/perlin_3.txt | 100 - .../realisation-2/iter-0/perlin_fail.status | 1 - .../realisation-2/iter-0/perlin_params.txt | 7 - .../Run/realisation-3/iter-0/ERROR | 8 - .../Run/realisation-3/iter-0/EXIT | 8 - .../Run/realisation-3/iter-0/aggregated.txt | 4 - .../realisation-3/iter-0/aggregator.stderr | 0 .../realisation-3/iter-0/aggregator.stdout | 0 .../Run/realisation-3/iter-0/parameters.txt | 7 - .../Run/realisation-3/iter-0/perlin.stderr | 0 .../Run/realisation-3/iter-0/perlin.stdout | 0 .../Run/realisation-3/iter-0/perlin_1.txt | 100 - .../Run/realisation-3/iter-0/perlin_2.txt | 100 - .../realisation-3/iter-0/perlin_fail.status | 1 - .../realisation-3/iter-0/perlin_params.txt | 7 - .../fail_storage/Run/realisation-4/iter-0/OK | 1 - .../Run/realisation-4/iter-0/aggregated.txt | 4 - .../realisation-4/iter-0/aggregator.stderr | 0 .../realisation-4/iter-0/aggregator.stdout | 0 .../Run/realisation-4/iter-0/parameters.txt | 7 - .../Run/realisation-4/iter-0/perlin.stderr | 0 .../Run/realisation-4/iter-0/perlin.stdout | 0 .../Run/realisation-4/iter-0/perlin_2.txt | 100 - .../Run/realisation-4/iter-0/perlin_3.txt | 100 - .../realisation-4/iter-0/perlin_fail.status | 1 - .../realisation-4/iter-0/perlin_params.txt | 7 - .../Run/realisation-4/iter-0/realization.ok | 1 - .../Run/realisation-5/iter-0/ERROR | 8 - .../Run/realisation-5/iter-0/EXIT | 8 - .../Run/realisation-5/iter-0/aggregated.txt | 4 - .../realisation-5/iter-0/aggregator.stderr | 0 .../realisation-5/iter-0/aggregator.stdout | 0 .../Run/realisation-5/iter-0/parameters.txt | 7 - .../Run/realisation-5/iter-0/perlin.stderr | 0 .../Run/realisation-5/iter-0/perlin.stdout | 0 .../Run/realisation-5/iter-0/perlin_1.txt | 100 - .../Run/realisation-5/iter-0/perlin_3.txt | 100 - .../realisation-5/iter-0/perlin_fail.status | 1 - .../realisation-5/iter-0/perlin_params.txt | 7 - .../fail_storage/Run/realisation-6/iter-0/OK | 1 - .../Run/realisation-6/iter-0/aggregated.txt | 4 - .../realisation-6/iter-0/aggregator.stderr | 0 .../realisation-6/iter-0/aggregator.stdout | 0 .../Run/realisation-6/iter-0/parameters.txt | 7 - .../Run/realisation-6/iter-0/perlin.stderr | 0 .../Run/realisation-6/iter-0/perlin.stdout | 0 .../Run/realisation-6/iter-0/perlin_1.txt | 100 - .../Run/realisation-6/iter-0/perlin_2.txt | 100 - .../realisation-6/iter-0/perlin_fail.status | 1 - .../realisation-6/iter-0/perlin_params.txt | 7 - .../Run/realisation-6/iter-0/realization.ok | 1 - .../Run/realisation-7/iter-0/ERROR | 8 - .../Run/realisation-7/iter-0/EXIT | 8 - .../Run/realisation-7/iter-0/aggregated.txt | 4 - .../realisation-7/iter-0/aggregator.stderr | 0 .../realisation-7/iter-0/aggregator.stdout | 0 .../Run/realisation-7/iter-0/parameters.txt | 7 - .../Run/realisation-7/iter-0/perlin.stderr | 0 .../Run/realisation-7/iter-0/perlin.stdout | 0 .../Run/realisation-7/iter-0/perlin_1.txt | 100 - .../Run/realisation-7/iter-0/perlin_2.txt | 100 - .../Run/realisation-7/iter-0/perlin_3.txt | 100 - .../realisation-7/iter-0/perlin_fail.status | 1 - .../realisation-7/iter-0/perlin_params.txt | 7 - .../fail_storage/Run/realisation-8/iter-0/OK | 1 - .../Run/realisation-8/iter-0/aggregated.txt | 4 - .../realisation-8/iter-0/aggregator.stderr | 0 .../realisation-8/iter-0/aggregator.stdout | 0 .../Run/realisation-8/iter-0/parameters.txt | 7 - .../Run/realisation-8/iter-0/perlin.stderr | 0 .../Run/realisation-8/iter-0/perlin.stdout | 0 .../Run/realisation-8/iter-0/perlin_1.txt | 100 - .../Run/realisation-8/iter-0/perlin_2.txt | 100 - .../Run/realisation-8/iter-0/perlin_3.txt | 100 - .../realisation-8/iter-0/perlin_fail.status | 1 - .../realisation-8/iter-0/perlin_params.txt | 7 - .../Run/realisation-8/iter-0/realization.ok | 1 - .../fail_storage/Run/realisation-9/iter-0/OK | 1 - .../Run/realisation-9/iter-0/aggregated.txt | 4 - .../realisation-9/iter-0/aggregator.stderr | 0 .../realisation-9/iter-0/aggregator.stdout | 0 .../Run/realisation-9/iter-0/parameters.txt | 7 - .../Run/realisation-9/iter-0/perlin.stderr | 0 .../Run/realisation-9/iter-0/perlin.stdout | 0 .../Run/realisation-9/iter-0/perlin_1.txt | 100 - .../Run/realisation-9/iter-0/perlin_2.txt | 100 - .../Run/realisation-9/iter-0/perlin_3.txt | 100 - .../realisation-9/iter-0/perlin_fail.status | 1 - .../realisation-9/iter-0/perlin_params.txt | 7 - .../Run/realisation-9/iter-0/realization.ok | 1 - .../fail_storage/ertensemble/current_case | 1 - .../default/0001/files/PERLIN_active | Bin 105 -> 0 bytes .../default/0002/files/PERLIN_active | Bin 105 -> 0 bytes .../default/0003/files/PERLIN_active | Bin 105 -> 0 bytes .../default/Ensemble/mod_0/ANALYZED.data_0 | 0 .../default/Ensemble/mod_0/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_0/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_0/FORECAST.data_0 | Bin 2816 -> 0 bytes .../default/Ensemble/mod_0/FORECAST.index | Bin 184 -> 0 bytes .../default/Ensemble/mod_0/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_0/PARAMETER.data_0 | Bin 128 -> 0 bytes .../default/Ensemble/mod_0/PARAMETER.index | Bin 69 -> 0 bytes .../default/Ensemble/mod_0/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_0/STATIC.data_0 | 0 .../default/Ensemble/mod_0/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_0/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_1/ANALYZED.data_0 | 0 .../default/Ensemble/mod_1/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_1/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_1/FORECAST.data_0 | Bin 1920 -> 0 bytes .../default/Ensemble/mod_1/FORECAST.index | Bin 145 -> 0 bytes .../default/Ensemble/mod_1/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_1/PARAMETER.data_0 | Bin 128 -> 0 bytes .../default/Ensemble/mod_1/PARAMETER.index | Bin 69 -> 0 bytes .../default/Ensemble/mod_1/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_1/STATIC.data_0 | 0 .../default/Ensemble/mod_1/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_1/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_10/ANALYZED.data_0 | 0 .../default/Ensemble/mod_10/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_10/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_10/FORECAST.data_0 | 0 .../default/Ensemble/mod_10/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_10/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_10/PARAMETER.data_0 | 0 .../default/Ensemble/mod_10/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_10/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_10/STATIC.data_0 | 0 .../default/Ensemble/mod_10/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_10/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_11/ANALYZED.data_0 | 0 .../default/Ensemble/mod_11/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_11/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_11/FORECAST.data_0 | 0 .../default/Ensemble/mod_11/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_11/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_11/PARAMETER.data_0 | 0 .../default/Ensemble/mod_11/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_11/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_11/STATIC.data_0 | 0 .../default/Ensemble/mod_11/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_11/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_12/ANALYZED.data_0 | 0 .../default/Ensemble/mod_12/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_12/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_12/FORECAST.data_0 | 0 .../default/Ensemble/mod_12/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_12/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_12/PARAMETER.data_0 | 0 .../default/Ensemble/mod_12/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_12/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_12/STATIC.data_0 | 0 .../default/Ensemble/mod_12/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_12/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_13/ANALYZED.data_0 | 0 .../default/Ensemble/mod_13/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_13/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_13/FORECAST.data_0 | 0 .../default/Ensemble/mod_13/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_13/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_13/PARAMETER.data_0 | 0 .../default/Ensemble/mod_13/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_13/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_13/STATIC.data_0 | 0 .../default/Ensemble/mod_13/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_13/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_14/ANALYZED.data_0 | 0 .../default/Ensemble/mod_14/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_14/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_14/FORECAST.data_0 | 0 .../default/Ensemble/mod_14/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_14/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_14/PARAMETER.data_0 | 0 .../default/Ensemble/mod_14/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_14/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_14/STATIC.data_0 | 0 .../default/Ensemble/mod_14/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_14/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_15/ANALYZED.data_0 | 0 .../default/Ensemble/mod_15/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_15/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_15/FORECAST.data_0 | 0 .../default/Ensemble/mod_15/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_15/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_15/PARAMETER.data_0 | 0 .../default/Ensemble/mod_15/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_15/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_15/STATIC.data_0 | 0 .../default/Ensemble/mod_15/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_15/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_16/ANALYZED.data_0 | 0 .../default/Ensemble/mod_16/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_16/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_16/FORECAST.data_0 | 0 .../default/Ensemble/mod_16/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_16/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_16/PARAMETER.data_0 | 0 .../default/Ensemble/mod_16/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_16/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_16/STATIC.data_0 | 0 .../default/Ensemble/mod_16/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_16/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_17/ANALYZED.data_0 | 0 .../default/Ensemble/mod_17/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_17/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_17/FORECAST.data_0 | 0 .../default/Ensemble/mod_17/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_17/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_17/PARAMETER.data_0 | 0 .../default/Ensemble/mod_17/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_17/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_17/STATIC.data_0 | 0 .../default/Ensemble/mod_17/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_17/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_18/ANALYZED.data_0 | 0 .../default/Ensemble/mod_18/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_18/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_18/FORECAST.data_0 | 0 .../default/Ensemble/mod_18/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_18/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_18/PARAMETER.data_0 | 0 .../default/Ensemble/mod_18/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_18/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_18/STATIC.data_0 | 0 .../default/Ensemble/mod_18/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_18/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_19/ANALYZED.data_0 | 0 .../default/Ensemble/mod_19/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_19/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_19/FORECAST.data_0 | 0 .../default/Ensemble/mod_19/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_19/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_19/PARAMETER.data_0 | 0 .../default/Ensemble/mod_19/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_19/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_19/STATIC.data_0 | 0 .../default/Ensemble/mod_19/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_19/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_2/ANALYZED.data_0 | 0 .../default/Ensemble/mod_2/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_2/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_2/FORECAST.data_0 | 0 .../default/Ensemble/mod_2/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_2/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_2/PARAMETER.data_0 | Bin 128 -> 0 bytes .../default/Ensemble/mod_2/PARAMETER.index | Bin 69 -> 0 bytes .../default/Ensemble/mod_2/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_2/STATIC.data_0 | 0 .../default/Ensemble/mod_2/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_2/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_20/ANALYZED.data_0 | 0 .../default/Ensemble/mod_20/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_20/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_20/FORECAST.data_0 | 0 .../default/Ensemble/mod_20/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_20/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_20/PARAMETER.data_0 | 0 .../default/Ensemble/mod_20/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_20/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_20/STATIC.data_0 | 0 .../default/Ensemble/mod_20/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_20/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_21/ANALYZED.data_0 | 0 .../default/Ensemble/mod_21/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_21/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_21/FORECAST.data_0 | 0 .../default/Ensemble/mod_21/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_21/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_21/PARAMETER.data_0 | 0 .../default/Ensemble/mod_21/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_21/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_21/STATIC.data_0 | 0 .../default/Ensemble/mod_21/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_21/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_22/ANALYZED.data_0 | 0 .../default/Ensemble/mod_22/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_22/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_22/FORECAST.data_0 | 0 .../default/Ensemble/mod_22/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_22/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_22/PARAMETER.data_0 | 0 .../default/Ensemble/mod_22/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_22/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_22/STATIC.data_0 | 0 .../default/Ensemble/mod_22/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_22/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_23/ANALYZED.data_0 | 0 .../default/Ensemble/mod_23/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_23/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_23/FORECAST.data_0 | 0 .../default/Ensemble/mod_23/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_23/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_23/PARAMETER.data_0 | 0 .../default/Ensemble/mod_23/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_23/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_23/STATIC.data_0 | 0 .../default/Ensemble/mod_23/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_23/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_24/ANALYZED.data_0 | 0 .../default/Ensemble/mod_24/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_24/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_24/FORECAST.data_0 | 0 .../default/Ensemble/mod_24/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_24/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_24/PARAMETER.data_0 | 0 .../default/Ensemble/mod_24/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_24/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_24/STATIC.data_0 | 0 .../default/Ensemble/mod_24/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_24/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_25/ANALYZED.data_0 | 0 .../default/Ensemble/mod_25/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_25/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_25/FORECAST.data_0 | 0 .../default/Ensemble/mod_25/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_25/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_25/PARAMETER.data_0 | 0 .../default/Ensemble/mod_25/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_25/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_25/STATIC.data_0 | 0 .../default/Ensemble/mod_25/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_25/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_26/ANALYZED.data_0 | 0 .../default/Ensemble/mod_26/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_26/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_26/FORECAST.data_0 | 0 .../default/Ensemble/mod_26/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_26/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_26/PARAMETER.data_0 | 0 .../default/Ensemble/mod_26/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_26/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_26/STATIC.data_0 | 0 .../default/Ensemble/mod_26/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_26/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_27/ANALYZED.data_0 | 0 .../default/Ensemble/mod_27/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_27/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_27/FORECAST.data_0 | 0 .../default/Ensemble/mod_27/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_27/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_27/PARAMETER.data_0 | 0 .../default/Ensemble/mod_27/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_27/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_27/STATIC.data_0 | 0 .../default/Ensemble/mod_27/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_27/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_28/ANALYZED.data_0 | 0 .../default/Ensemble/mod_28/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_28/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_28/FORECAST.data_0 | 0 .../default/Ensemble/mod_28/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_28/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_28/PARAMETER.data_0 | 0 .../default/Ensemble/mod_28/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_28/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_28/STATIC.data_0 | 0 .../default/Ensemble/mod_28/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_28/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_29/ANALYZED.data_0 | 0 .../default/Ensemble/mod_29/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_29/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_29/FORECAST.data_0 | 0 .../default/Ensemble/mod_29/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_29/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_29/PARAMETER.data_0 | 0 .../default/Ensemble/mod_29/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_29/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_29/STATIC.data_0 | 0 .../default/Ensemble/mod_29/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_29/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_3/ANALYZED.data_0 | 0 .../default/Ensemble/mod_3/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_3/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_3/FORECAST.data_0 | 0 .../default/Ensemble/mod_3/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_3/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_3/PARAMETER.data_0 | Bin 128 -> 0 bytes .../default/Ensemble/mod_3/PARAMETER.index | Bin 69 -> 0 bytes .../default/Ensemble/mod_3/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_3/STATIC.data_0 | 0 .../default/Ensemble/mod_3/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_3/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_30/ANALYZED.data_0 | 0 .../default/Ensemble/mod_30/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_30/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_30/FORECAST.data_0 | 0 .../default/Ensemble/mod_30/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_30/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_30/PARAMETER.data_0 | 0 .../default/Ensemble/mod_30/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_30/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_30/STATIC.data_0 | 0 .../default/Ensemble/mod_30/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_30/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_31/ANALYZED.data_0 | 0 .../default/Ensemble/mod_31/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_31/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_31/FORECAST.data_0 | 0 .../default/Ensemble/mod_31/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_31/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_31/PARAMETER.data_0 | 0 .../default/Ensemble/mod_31/PARAMETER.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_31/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_31/STATIC.data_0 | 0 .../default/Ensemble/mod_31/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_31/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_4/ANALYZED.data_0 | 0 .../default/Ensemble/mod_4/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_4/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_4/FORECAST.data_0 | Bin 1920 -> 0 bytes .../default/Ensemble/mod_4/FORECAST.index | Bin 145 -> 0 bytes .../default/Ensemble/mod_4/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_4/PARAMETER.data_0 | Bin 128 -> 0 bytes .../default/Ensemble/mod_4/PARAMETER.index | Bin 69 -> 0 bytes .../default/Ensemble/mod_4/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_4/STATIC.data_0 | 0 .../default/Ensemble/mod_4/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_4/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_5/ANALYZED.data_0 | 0 .../default/Ensemble/mod_5/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_5/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_5/FORECAST.data_0 | 0 .../default/Ensemble/mod_5/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_5/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_5/PARAMETER.data_0 | Bin 128 -> 0 bytes .../default/Ensemble/mod_5/PARAMETER.index | Bin 69 -> 0 bytes .../default/Ensemble/mod_5/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_5/STATIC.data_0 | 0 .../default/Ensemble/mod_5/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_5/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_6/ANALYZED.data_0 | 0 .../default/Ensemble/mod_6/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_6/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_6/FORECAST.data_0 | Bin 1920 -> 0 bytes .../default/Ensemble/mod_6/FORECAST.index | Bin 145 -> 0 bytes .../default/Ensemble/mod_6/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_6/PARAMETER.data_0 | Bin 128 -> 0 bytes .../default/Ensemble/mod_6/PARAMETER.index | Bin 69 -> 0 bytes .../default/Ensemble/mod_6/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_6/STATIC.data_0 | 0 .../default/Ensemble/mod_6/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_6/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_7/ANALYZED.data_0 | 0 .../default/Ensemble/mod_7/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_7/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_7/FORECAST.data_0 | 0 .../default/Ensemble/mod_7/FORECAST.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_7/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_7/PARAMETER.data_0 | Bin 128 -> 0 bytes .../default/Ensemble/mod_7/PARAMETER.index | Bin 69 -> 0 bytes .../default/Ensemble/mod_7/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_7/STATIC.data_0 | 0 .../default/Ensemble/mod_7/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_7/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_8/ANALYZED.data_0 | 0 .../default/Ensemble/mod_8/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_8/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_8/FORECAST.data_0 | Bin 2816 -> 0 bytes .../default/Ensemble/mod_8/FORECAST.index | Bin 184 -> 0 bytes .../default/Ensemble/mod_8/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_8/PARAMETER.data_0 | Bin 128 -> 0 bytes .../default/Ensemble/mod_8/PARAMETER.index | Bin 69 -> 0 bytes .../default/Ensemble/mod_8/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_8/STATIC.data_0 | 0 .../default/Ensemble/mod_8/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_8/STATIC.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_9/ANALYZED.data_0 | 0 .../default/Ensemble/mod_9/ANALYZED.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_9/ANALYZED.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_9/FORECAST.data_0 | Bin 2816 -> 0 bytes .../default/Ensemble/mod_9/FORECAST.index | Bin 184 -> 0 bytes .../default/Ensemble/mod_9/FORECAST.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_9/PARAMETER.data_0 | Bin 128 -> 0 bytes .../default/Ensemble/mod_9/PARAMETER.index | Bin 69 -> 0 bytes .../default/Ensemble/mod_9/PARAMETER.mnt | Bin 8 -> 0 bytes .../default/Ensemble/mod_9/STATIC.data_0 | 0 .../default/Ensemble/mod_9/STATIC.index | Bin 24 -> 0 bytes .../default/Ensemble/mod_9/STATIC.mnt | Bin 8 -> 0 bytes .../ertensemble/default/Index/INDEX.data_0 | 0 .../ertensemble/default/Index/INDEX.index | Bin 24 -> 0 bytes .../ertensemble/default/Index/INDEX.mnt | Bin 8 -> 0 bytes .../ertensemble/default/ert_fstab | Bin 207 -> 0 bytes .../ertensemble/default/files/case_config | Bin 4 -> 0 bytes .../default/files/custom_kw_config_set | Bin 88 -> 0 bytes .../ertensemble/default/files/state-map | Bin 48 -> 0 bytes .../ertensemble/default/files/summary-key-set | Bin 4 -> 0 bytes .../test-data/local/custom_kw/jobs/AGGREGATOR | 4 - .../Ert/test-data/local/custom_kw/jobs/PERLIN | 4 - .../local/custom_kw/jobs/PERLIN_FAIL | 3 - .../local/custom_kw/jobs/REALIZATION_FAIL | 3 - .../local/custom_kw/jobs/aggregator.py | 26 - .../test-data/local/custom_kw/jobs/perlin.py | 176 - .../local/custom_kw/jobs/perlin_fail.py | 21 - .../local/custom_kw/jobs/realization_fail.py | 11 - .../Ert/test-data/local/custom_kw/mini_config | 40 - .../local/custom_kw/mini_fail_config | 43 - .../storage/Run/realisation-0/iter-0/OK | 1 - .../Run/realisation-0/iter-0/aggregated.txt | 4 - .../realisation-0/iter-0/aggregator.stderr | 0 .../realisation-0/iter-0/aggregator.stdout | 0 .../Run/realisation-0/iter-0/parameters.txt | 7 - .../Run/realisation-0/iter-0/perlin.stderr | 0 .../Run/realisation-0/iter-0/perlin.stdout | 0 .../Run/realisation-0/iter-0/perlin_1.txt | 100 - .../Run/realisation-0/iter-0/perlin_2.txt | 100 - .../Run/realisation-0/iter-0/perlin_3.txt | 100 - .../realisation-0/iter-0/perlin_params.txt | 7 - .../storage/Run/realisation-1/iter-0/OK | 1 - .../Run/realisation-1/iter-0/aggregated.txt | 4 - .../realisation-1/iter-0/aggregator.stderr | 0 .../realisation-1/iter-0/aggregator.stdout | 0 .../Run/realisation-1/iter-0/parameters.txt | 7 - .../Run/realisation-1/iter-0/perlin.stderr | 0 .../Run/realisation-1/iter-0/perlin.stdout | 0 .../Run/realisation-1/iter-0/perlin_1.txt | 100 - .../Run/realisation-1/iter-0/perlin_2.txt | 100 - .../Run/realisation-1/iter-0/perlin_3.txt | 100 - .../realisation-1/iter-0/perlin_params.txt | 7 - .../storage/Run/realisation-2/iter-0/OK | 1 - .../Run/realisation-2/iter-0/aggregated.txt | 4 - .../realisation-2/iter-0/aggregator.stderr | 0 .../realisation-2/iter-0/aggregator.stdout | 0 .../Run/realisation-2/iter-0/parameters.txt | 7 - .../Run/realisation-2/iter-0/perlin.stderr | 0 .../Run/realisation-2/iter-0/perlin.stdout | 0 .../Run/realisation-2/iter-0/perlin_1.txt | 100 - .../Run/realisation-2/iter-0/perlin_2.txt | 100 - .../Run/realisation-2/iter-0/perlin_3.txt | 100 - .../realisation-2/iter-0/perlin_params.txt | 7 - .../storage/Run/realisation-3/iter-0/OK | 1 - .../Run/realisation-3/iter-0/aggregated.txt | 4 - .../realisation-3/iter-0/aggregator.stderr | 0 .../realisation-3/iter-0/aggregator.stdout | 0 .../Run/realisation-3/iter-0/parameters.txt | 7 - .../Run/realisation-3/iter-0/perlin.stderr | 0 .../Run/realisation-3/iter-0/perlin.stdout | 0 .../Run/realisation-3/iter-0/perlin_1.txt | 100 - .../Run/realisation-3/iter-0/perlin_2.txt | 100 - .../Run/realisation-3/iter-0/perlin_3.txt | 100 - .../realisation-3/iter-0/perlin_params.txt | 7 - .../storage/Run/realisation-4/iter-0/OK | 1 - .../Run/realisation-4/iter-0/aggregated.txt | 4 - .../realisation-4/iter-0/aggregator.stderr | 0 .../realisation-4/iter-0/aggregator.stdout | 0 .../Run/realisation-4/iter-0/parameters.txt | 7 - .../Run/realisation-4/iter-0/perlin.stderr | 0 .../Run/realisation-4/iter-0/perlin.stdout | 0 .../Run/realisation-4/iter-0/perlin_1.txt | 100 - .../Run/realisation-4/iter-0/perlin_2.txt | 100 - .../Run/realisation-4/iter-0/perlin_3.txt | 100 - .../realisation-4/iter-0/perlin_params.txt | 7 - .../storage/Run/realisation-5/iter-0/OK | 1 - .../Run/realisation-5/iter-0/aggregated.txt | 4 - .../realisation-5/iter-0/aggregator.stderr | 0 .../realisation-5/iter-0/aggregator.stdout | 0 .../Run/realisation-5/iter-0/parameters.txt | 7 - .../Run/realisation-5/iter-0/perlin.stderr | 0 .../Run/realisation-5/iter-0/perlin.stdout | 0 .../Run/realisation-5/iter-0/perlin_1.txt | 100 - .../Run/realisation-5/iter-0/perlin_2.txt | 100 - .../Run/realisation-5/iter-0/perlin_3.txt | 100 - .../realisation-5/iter-0/perlin_params.txt | 7 - .../storage/Run/realisation-6/iter-0/OK | 1 - .../Run/realisation-6/iter-0/aggregated.txt | 4 - .../realisation-6/iter-0/aggregator.stderr | 0 .../realisation-6/iter-0/aggregator.stdout | 0 .../Run/realisation-6/iter-0/parameters.txt | 7 - .../Run/realisation-6/iter-0/perlin.stderr | 0 .../Run/realisation-6/iter-0/perlin.stdout | 0 .../Run/realisation-6/iter-0/perlin_1.txt | 100 - .../Run/realisation-6/iter-0/perlin_2.txt | 100 - .../Run/realisation-6/iter-0/perlin_3.txt | 100 - .../realisation-6/iter-0/perlin_params.txt | 7 - .../storage/Run/realisation-7/iter-0/OK | 1 - .../Run/realisation-7/iter-0/aggregated.txt | 4 - .../realisation-7/iter-0/aggregator.stderr | 0 .../realisation-7/iter-0/aggregator.stdout | 0 .../Run/realisation-7/iter-0/parameters.txt | 7 - .../Run/realisation-7/iter-0/perlin.stderr | 0 .../Run/realisation-7/iter-0/perlin.stdout | 0 .../Run/realisation-7/iter-0/perlin_1.txt | 100 - .../Run/realisation-7/iter-0/perlin_2.txt | 100 - .../Run/realisation-7/iter-0/perlin_3.txt | 100 - .../realisation-7/iter-0/perlin_params.txt | 7 - .../storage/Run/realisation-8/iter-0/OK | 1 - .../storage/Run/realisation-8/iter-0/STATUS | 3 - .../Run/realisation-8/iter-0/aggregated.txt | 4 - .../realisation-8/iter-0/aggregator.stderr | 0 .../realisation-8/iter-0/aggregator.stdout | 0 .../storage/Run/realisation-8/iter-0/jobs.py | 28 - .../Run/realisation-8/iter-0/parameters.txt | 7 - .../Run/realisation-8/iter-0/perlin.stderr | 0 .../Run/realisation-8/iter-0/perlin.stdout | 0 .../Run/realisation-8/iter-0/perlin_1.txt | 100 - .../Run/realisation-8/iter-0/perlin_2.txt | 100 - .../Run/realisation-8/iter-0/perlin_3.txt | 100 - .../realisation-8/iter-0/perlin_params.txt | 7 - .../storage/Run/realisation-9/iter-0/OK | 1 - .../Run/realisation-9/iter-0/aggregated.txt | 4 - .../realisation-9/iter-0/aggregator.stderr | 0 .../realisation-9/iter-0/aggregator.stdout | 0 .../Run/realisation-9/iter-0/parameters.txt | 7 - .../Run/realisation-9/iter-0/perlin.stderr | 0 .../Run/realisation-9/iter-0/perlin.stdout | 0 .../Run/realisation-9/iter-0/perlin_1.txt | 100 - .../Run/realisation-9/iter-0/perlin_2.txt | 100 - .../Run/realisation-9/iter-0/perlin_3.txt | 100 - .../realisation-9/iter-0/perlin_params.txt | 7 - .../storage/ertensemble/current_case | 1 - .../test_run/0001/files/PERLIN_active | Bin 105 -> 0 bytes .../test_run/0002/files/PERLIN_active | Bin 105 -> 0 bytes .../test_run/0003/files/PERLIN_active | Bin 105 -> 0 bytes .../test_run/Ensemble/mod_0/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_0/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_0/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_0/FORECAST.data_0 | Bin 2816 -> 0 bytes .../test_run/Ensemble/mod_0/FORECAST.index | Bin 184 -> 0 bytes .../test_run/Ensemble/mod_0/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_0/PARAMETER.data_0 | Bin 128 -> 0 bytes .../test_run/Ensemble/mod_0/PARAMETER.index | Bin 69 -> 0 bytes .../test_run/Ensemble/mod_0/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_0/STATIC.data_0 | 0 .../test_run/Ensemble/mod_0/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_0/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_1/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_1/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_1/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_1/FORECAST.data_0 | Bin 2816 -> 0 bytes .../test_run/Ensemble/mod_1/FORECAST.index | Bin 184 -> 0 bytes .../test_run/Ensemble/mod_1/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_1/PARAMETER.data_0 | Bin 128 -> 0 bytes .../test_run/Ensemble/mod_1/PARAMETER.index | Bin 69 -> 0 bytes .../test_run/Ensemble/mod_1/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_1/STATIC.data_0 | 0 .../test_run/Ensemble/mod_1/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_1/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_10/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_10/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_10/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_10/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_10/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_10/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_10/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_10/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_10/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_10/STATIC.data_0 | 0 .../test_run/Ensemble/mod_10/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_10/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_11/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_11/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_11/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_11/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_11/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_11/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_11/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_11/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_11/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_11/STATIC.data_0 | 0 .../test_run/Ensemble/mod_11/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_11/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_12/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_12/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_12/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_12/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_12/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_12/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_12/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_12/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_12/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_12/STATIC.data_0 | 0 .../test_run/Ensemble/mod_12/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_12/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_13/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_13/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_13/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_13/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_13/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_13/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_13/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_13/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_13/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_13/STATIC.data_0 | 0 .../test_run/Ensemble/mod_13/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_13/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_14/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_14/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_14/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_14/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_14/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_14/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_14/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_14/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_14/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_14/STATIC.data_0 | 0 .../test_run/Ensemble/mod_14/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_14/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_15/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_15/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_15/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_15/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_15/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_15/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_15/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_15/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_15/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_15/STATIC.data_0 | 0 .../test_run/Ensemble/mod_15/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_15/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_16/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_16/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_16/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_16/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_16/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_16/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_16/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_16/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_16/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_16/STATIC.data_0 | 0 .../test_run/Ensemble/mod_16/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_16/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_17/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_17/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_17/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_17/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_17/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_17/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_17/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_17/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_17/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_17/STATIC.data_0 | 0 .../test_run/Ensemble/mod_17/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_17/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_18/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_18/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_18/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_18/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_18/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_18/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_18/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_18/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_18/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_18/STATIC.data_0 | 0 .../test_run/Ensemble/mod_18/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_18/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_19/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_19/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_19/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_19/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_19/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_19/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_19/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_19/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_19/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_19/STATIC.data_0 | 0 .../test_run/Ensemble/mod_19/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_19/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_2/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_2/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_2/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_2/FORECAST.data_0 | Bin 2816 -> 0 bytes .../test_run/Ensemble/mod_2/FORECAST.index | Bin 184 -> 0 bytes .../test_run/Ensemble/mod_2/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_2/PARAMETER.data_0 | Bin 128 -> 0 bytes .../test_run/Ensemble/mod_2/PARAMETER.index | Bin 69 -> 0 bytes .../test_run/Ensemble/mod_2/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_2/STATIC.data_0 | 0 .../test_run/Ensemble/mod_2/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_2/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_20/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_20/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_20/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_20/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_20/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_20/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_20/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_20/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_20/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_20/STATIC.data_0 | 0 .../test_run/Ensemble/mod_20/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_20/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_21/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_21/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_21/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_21/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_21/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_21/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_21/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_21/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_21/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_21/STATIC.data_0 | 0 .../test_run/Ensemble/mod_21/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_21/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_22/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_22/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_22/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_22/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_22/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_22/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_22/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_22/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_22/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_22/STATIC.data_0 | 0 .../test_run/Ensemble/mod_22/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_22/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_23/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_23/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_23/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_23/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_23/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_23/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_23/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_23/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_23/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_23/STATIC.data_0 | 0 .../test_run/Ensemble/mod_23/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_23/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_24/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_24/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_24/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_24/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_24/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_24/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_24/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_24/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_24/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_24/STATIC.data_0 | 0 .../test_run/Ensemble/mod_24/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_24/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_25/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_25/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_25/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_25/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_25/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_25/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_25/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_25/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_25/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_25/STATIC.data_0 | 0 .../test_run/Ensemble/mod_25/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_25/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_26/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_26/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_26/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_26/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_26/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_26/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_26/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_26/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_26/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_26/STATIC.data_0 | 0 .../test_run/Ensemble/mod_26/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_26/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_27/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_27/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_27/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_27/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_27/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_27/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_27/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_27/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_27/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_27/STATIC.data_0 | 0 .../test_run/Ensemble/mod_27/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_27/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_28/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_28/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_28/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_28/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_28/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_28/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_28/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_28/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_28/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_28/STATIC.data_0 | 0 .../test_run/Ensemble/mod_28/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_28/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_29/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_29/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_29/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_29/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_29/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_29/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_29/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_29/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_29/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_29/STATIC.data_0 | 0 .../test_run/Ensemble/mod_29/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_29/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_3/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_3/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_3/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_3/FORECAST.data_0 | Bin 2816 -> 0 bytes .../test_run/Ensemble/mod_3/FORECAST.index | Bin 184 -> 0 bytes .../test_run/Ensemble/mod_3/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_3/PARAMETER.data_0 | Bin 128 -> 0 bytes .../test_run/Ensemble/mod_3/PARAMETER.index | Bin 69 -> 0 bytes .../test_run/Ensemble/mod_3/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_3/STATIC.data_0 | 0 .../test_run/Ensemble/mod_3/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_3/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_30/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_30/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_30/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_30/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_30/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_30/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_30/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_30/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_30/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_30/STATIC.data_0 | 0 .../test_run/Ensemble/mod_30/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_30/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_31/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_31/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_31/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_31/FORECAST.data_0 | 0 .../test_run/Ensemble/mod_31/FORECAST.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_31/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_31/PARAMETER.data_0 | 0 .../test_run/Ensemble/mod_31/PARAMETER.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_31/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_31/STATIC.data_0 | 0 .../test_run/Ensemble/mod_31/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_31/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_4/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_4/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_4/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_4/FORECAST.data_0 | Bin 2816 -> 0 bytes .../test_run/Ensemble/mod_4/FORECAST.index | Bin 184 -> 0 bytes .../test_run/Ensemble/mod_4/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_4/PARAMETER.data_0 | Bin 128 -> 0 bytes .../test_run/Ensemble/mod_4/PARAMETER.index | Bin 69 -> 0 bytes .../test_run/Ensemble/mod_4/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_4/STATIC.data_0 | 0 .../test_run/Ensemble/mod_4/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_4/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_5/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_5/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_5/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_5/FORECAST.data_0 | Bin 2816 -> 0 bytes .../test_run/Ensemble/mod_5/FORECAST.index | Bin 184 -> 0 bytes .../test_run/Ensemble/mod_5/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_5/PARAMETER.data_0 | Bin 128 -> 0 bytes .../test_run/Ensemble/mod_5/PARAMETER.index | Bin 69 -> 0 bytes .../test_run/Ensemble/mod_5/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_5/STATIC.data_0 | 0 .../test_run/Ensemble/mod_5/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_5/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_6/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_6/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_6/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_6/FORECAST.data_0 | Bin 2816 -> 0 bytes .../test_run/Ensemble/mod_6/FORECAST.index | Bin 184 -> 0 bytes .../test_run/Ensemble/mod_6/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_6/PARAMETER.data_0 | Bin 128 -> 0 bytes .../test_run/Ensemble/mod_6/PARAMETER.index | Bin 69 -> 0 bytes .../test_run/Ensemble/mod_6/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_6/STATIC.data_0 | 0 .../test_run/Ensemble/mod_6/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_6/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_7/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_7/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_7/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_7/FORECAST.data_0 | Bin 2816 -> 0 bytes .../test_run/Ensemble/mod_7/FORECAST.index | Bin 184 -> 0 bytes .../test_run/Ensemble/mod_7/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_7/PARAMETER.data_0 | Bin 128 -> 0 bytes .../test_run/Ensemble/mod_7/PARAMETER.index | Bin 69 -> 0 bytes .../test_run/Ensemble/mod_7/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_7/STATIC.data_0 | 0 .../test_run/Ensemble/mod_7/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_7/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_8/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_8/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_8/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_8/FORECAST.data_0 | Bin 2816 -> 0 bytes .../test_run/Ensemble/mod_8/FORECAST.index | Bin 184 -> 0 bytes .../test_run/Ensemble/mod_8/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_8/PARAMETER.data_0 | Bin 128 -> 0 bytes .../test_run/Ensemble/mod_8/PARAMETER.index | Bin 69 -> 0 bytes .../test_run/Ensemble/mod_8/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_8/STATIC.data_0 | 0 .../test_run/Ensemble/mod_8/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_8/STATIC.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_9/ANALYZED.data_0 | 0 .../test_run/Ensemble/mod_9/ANALYZED.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_9/ANALYZED.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_9/FORECAST.data_0 | Bin 2816 -> 0 bytes .../test_run/Ensemble/mod_9/FORECAST.index | Bin 184 -> 0 bytes .../test_run/Ensemble/mod_9/FORECAST.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_9/PARAMETER.data_0 | Bin 128 -> 0 bytes .../test_run/Ensemble/mod_9/PARAMETER.index | Bin 69 -> 0 bytes .../test_run/Ensemble/mod_9/PARAMETER.mnt | Bin 8 -> 0 bytes .../test_run/Ensemble/mod_9/STATIC.data_0 | 0 .../test_run/Ensemble/mod_9/STATIC.index | Bin 24 -> 0 bytes .../test_run/Ensemble/mod_9/STATIC.mnt | Bin 8 -> 0 bytes .../ertensemble/test_run/Index/INDEX.data_0 | 0 .../ertensemble/test_run/Index/INDEX.index | Bin 24 -> 0 bytes .../ertensemble/test_run/Index/INDEX.mnt | Bin 8 -> 0 bytes .../storage/ertensemble/test_run/ert_fstab | Bin 207 -> 0 bytes .../ertensemble/test_run/files/case_config | Bin 4 -> 0 bytes .../test_run/files/custom_kw_config_set | Bin 88 -> 0 bytes .../ertensemble/test_run/files/state-map | Bin 48 -> 0 bytes .../test_run/files/summary-key-set | Bin 4 -> 0 bytes .../Ert/test-data/local/custom_kw/time_map | 4 - .../local/resopt/config/simple/config | 5 - ThirdParty/Ert/test-data/local/run/config.txt | 0 ThirdParty/Ert/test-data/local/snake_oil/SEED | 1 - .../local/snake_oil/jobs/SNAKE_OIL_DIFF | 4 - .../local/snake_oil/jobs/SNAKE_OIL_NPV | 4 - .../local/snake_oil/jobs/SNAKE_OIL_SIMULATOR | 4 - .../local/snake_oil/jobs/snake_oil_diff.py | 24 - .../local/snake_oil/jobs/snake_oil_npv.py | 103 - .../snake_oil/jobs/snake_oil_simulator.py | 200 - .../snake_oil/observations/observations.txt | 56 - .../snake_oil/observations/wpr_diff_obs.txt | 4 - .../parameters/snake_oil_parameters.txt | 11 - .../snake_oil/refcase/SNAKE_OIL_FIELD.SMSPEC | Bin 1584 -> 0 bytes .../snake_oil/refcase/SNAKE_OIL_FIELD.UNSMRY | Bin 503200 -> 0 bytes .../snake_oil/refcase/refcase_readme.txt | 1 - .../local/snake_oil/refcase/seed.txt | 1 - .../snake_oil/refcase/snake_oil_params.txt | 10 - .../local/snake_oil/refcase/time_map.txt | 2000 ---------- .../test-data/local/snake_oil/snake_oil.ert | 39 - .../storage/snake_oil/ensemble/current_case | 1 - .../0199/files/SNAKE_OIL_GPR_DIFF_active | Bin 2005 -> 0 bytes .../0199/files/SNAKE_OIL_OPR_DIFF_active | Bin 2005 -> 0 bytes .../0199/files/SNAKE_OIL_WPR_DIFF_active | Bin 2005 -> 0 bytes .../default_0/Ensemble/mod_0/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_0/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_0/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_0/FORECAST.data_0 | Bin 107136 -> 0 bytes .../default_0/Ensemble/mod_0/FORECAST.index | Bin 1702 -> 0 bytes .../default_0/Ensemble/mod_0/FORECAST.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_0/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_0/PARAMETER.index | Bin 72 -> 0 bytes .../default_0/Ensemble/mod_0/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_0/STATIC.data_0 | 0 .../default_0/Ensemble/mod_0/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_0/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_1/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_1/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_1/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_1/FORECAST.data_0 | Bin 106560 -> 0 bytes .../default_0/Ensemble/mod_1/FORECAST.index | Bin 1702 -> 0 bytes .../default_0/Ensemble/mod_1/FORECAST.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_1/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_1/PARAMETER.index | Bin 72 -> 0 bytes .../default_0/Ensemble/mod_1/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_1/STATIC.data_0 | 0 .../default_0/Ensemble/mod_1/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_1/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_10/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_10/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_10/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_10/FORECAST.data_0 | Bin 101824 -> 0 bytes .../default_0/Ensemble/mod_10/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_10/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_10/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_10/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_10/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_10/STATIC.data_0 | 0 .../default_0/Ensemble/mod_10/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_10/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_11/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_11/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_11/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_11/FORECAST.data_0 | Bin 100480 -> 0 bytes .../default_0/Ensemble/mod_11/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_11/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_11/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_11/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_11/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_11/STATIC.data_0 | 0 .../default_0/Ensemble/mod_11/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_11/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_12/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_12/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_12/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_12/FORECAST.data_0 | Bin 108224 -> 0 bytes .../default_0/Ensemble/mod_12/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_12/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_12/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_12/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_12/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_12/STATIC.data_0 | 0 .../default_0/Ensemble/mod_12/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_12/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_13/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_13/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_13/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_13/FORECAST.data_0 | Bin 107712 -> 0 bytes .../default_0/Ensemble/mod_13/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_13/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_13/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_13/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_13/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_13/STATIC.data_0 | 0 .../default_0/Ensemble/mod_13/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_13/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_14/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_14/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_14/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_14/FORECAST.data_0 | Bin 104128 -> 0 bytes .../default_0/Ensemble/mod_14/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_14/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_14/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_14/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_14/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_14/STATIC.data_0 | 0 .../default_0/Ensemble/mod_14/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_14/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_15/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_15/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_15/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_15/FORECAST.data_0 | Bin 107776 -> 0 bytes .../default_0/Ensemble/mod_15/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_15/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_15/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_15/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_15/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_15/STATIC.data_0 | 0 .../default_0/Ensemble/mod_15/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_15/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_16/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_16/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_16/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_16/FORECAST.data_0 | Bin 108224 -> 0 bytes .../default_0/Ensemble/mod_16/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_16/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_16/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_16/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_16/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_16/STATIC.data_0 | 0 .../default_0/Ensemble/mod_16/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_16/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_17/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_17/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_17/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_17/FORECAST.data_0 | Bin 108288 -> 0 bytes .../default_0/Ensemble/mod_17/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_17/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_17/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_17/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_17/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_17/STATIC.data_0 | 0 .../default_0/Ensemble/mod_17/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_17/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_18/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_18/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_18/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_18/FORECAST.data_0 | Bin 102656 -> 0 bytes .../default_0/Ensemble/mod_18/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_18/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_18/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_18/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_18/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_18/STATIC.data_0 | 0 .../default_0/Ensemble/mod_18/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_18/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_19/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_19/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_19/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_19/FORECAST.data_0 | Bin 107648 -> 0 bytes .../default_0/Ensemble/mod_19/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_19/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_19/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_19/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_19/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_19/STATIC.data_0 | 0 .../default_0/Ensemble/mod_19/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_19/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_2/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_2/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_2/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_2/FORECAST.data_0 | Bin 107520 -> 0 bytes .../default_0/Ensemble/mod_2/FORECAST.index | Bin 1702 -> 0 bytes .../default_0/Ensemble/mod_2/FORECAST.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_2/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_2/PARAMETER.index | Bin 72 -> 0 bytes .../default_0/Ensemble/mod_2/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_2/STATIC.data_0 | 0 .../default_0/Ensemble/mod_2/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_2/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_20/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_20/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_20/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_20/FORECAST.data_0 | Bin 106112 -> 0 bytes .../default_0/Ensemble/mod_20/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_20/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_20/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_20/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_20/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_20/STATIC.data_0 | 0 .../default_0/Ensemble/mod_20/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_20/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_21/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_21/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_21/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_21/FORECAST.data_0 | Bin 108160 -> 0 bytes .../default_0/Ensemble/mod_21/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_21/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_21/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_21/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_21/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_21/STATIC.data_0 | 0 .../default_0/Ensemble/mod_21/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_21/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_22/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_22/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_22/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_22/FORECAST.data_0 | Bin 106752 -> 0 bytes .../default_0/Ensemble/mod_22/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_22/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_22/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_22/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_22/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_22/STATIC.data_0 | 0 .../default_0/Ensemble/mod_22/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_22/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_23/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_23/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_23/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_23/FORECAST.data_0 | Bin 108224 -> 0 bytes .../default_0/Ensemble/mod_23/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_23/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_23/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_23/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_23/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_23/STATIC.data_0 | 0 .../default_0/Ensemble/mod_23/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_23/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_24/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_24/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_24/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_24/FORECAST.data_0 | Bin 108032 -> 0 bytes .../default_0/Ensemble/mod_24/FORECAST.index | Bin 1745 -> 0 bytes .../default_0/Ensemble/mod_24/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_24/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_24/PARAMETER.index | Bin 73 -> 0 bytes .../default_0/Ensemble/mod_24/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_24/STATIC.data_0 | 0 .../default_0/Ensemble/mod_24/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_24/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_25/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_25/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_25/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_25/FORECAST.data_0 | 0 .../default_0/Ensemble/mod_25/FORECAST.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_25/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_25/PARAMETER.data_0 | 0 .../default_0/Ensemble/mod_25/PARAMETER.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_25/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_25/STATIC.data_0 | 0 .../default_0/Ensemble/mod_25/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_25/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_26/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_26/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_26/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_26/FORECAST.data_0 | 0 .../default_0/Ensemble/mod_26/FORECAST.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_26/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_26/PARAMETER.data_0 | 0 .../default_0/Ensemble/mod_26/PARAMETER.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_26/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_26/STATIC.data_0 | 0 .../default_0/Ensemble/mod_26/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_26/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_27/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_27/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_27/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_27/FORECAST.data_0 | 0 .../default_0/Ensemble/mod_27/FORECAST.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_27/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_27/PARAMETER.data_0 | 0 .../default_0/Ensemble/mod_27/PARAMETER.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_27/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_27/STATIC.data_0 | 0 .../default_0/Ensemble/mod_27/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_27/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_28/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_28/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_28/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_28/FORECAST.data_0 | 0 .../default_0/Ensemble/mod_28/FORECAST.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_28/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_28/PARAMETER.data_0 | 0 .../default_0/Ensemble/mod_28/PARAMETER.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_28/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_28/STATIC.data_0 | 0 .../default_0/Ensemble/mod_28/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_28/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_29/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_29/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_29/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_29/FORECAST.data_0 | 0 .../default_0/Ensemble/mod_29/FORECAST.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_29/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_29/PARAMETER.data_0 | 0 .../default_0/Ensemble/mod_29/PARAMETER.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_29/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_29/STATIC.data_0 | 0 .../default_0/Ensemble/mod_29/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_29/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_3/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_3/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_3/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_3/FORECAST.data_0 | Bin 105216 -> 0 bytes .../default_0/Ensemble/mod_3/FORECAST.index | Bin 1702 -> 0 bytes .../default_0/Ensemble/mod_3/FORECAST.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_3/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_3/PARAMETER.index | Bin 72 -> 0 bytes .../default_0/Ensemble/mod_3/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_3/STATIC.data_0 | 0 .../default_0/Ensemble/mod_3/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_3/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_30/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_30/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_30/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_30/FORECAST.data_0 | 0 .../default_0/Ensemble/mod_30/FORECAST.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_30/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_30/PARAMETER.data_0 | 0 .../default_0/Ensemble/mod_30/PARAMETER.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_30/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_30/STATIC.data_0 | 0 .../default_0/Ensemble/mod_30/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_30/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_31/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_31/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_31/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_31/FORECAST.data_0 | 0 .../default_0/Ensemble/mod_31/FORECAST.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_31/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_31/PARAMETER.data_0 | 0 .../default_0/Ensemble/mod_31/PARAMETER.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_31/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_31/STATIC.data_0 | 0 .../default_0/Ensemble/mod_31/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_31/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_4/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_4/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_4/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_4/FORECAST.data_0 | Bin 106944 -> 0 bytes .../default_0/Ensemble/mod_4/FORECAST.index | Bin 1702 -> 0 bytes .../default_0/Ensemble/mod_4/FORECAST.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_4/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_4/PARAMETER.index | Bin 72 -> 0 bytes .../default_0/Ensemble/mod_4/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_4/STATIC.data_0 | 0 .../default_0/Ensemble/mod_4/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_4/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_5/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_5/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_5/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_5/FORECAST.data_0 | Bin 103296 -> 0 bytes .../default_0/Ensemble/mod_5/FORECAST.index | Bin 1702 -> 0 bytes .../default_0/Ensemble/mod_5/FORECAST.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_5/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_5/PARAMETER.index | Bin 72 -> 0 bytes .../default_0/Ensemble/mod_5/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_5/STATIC.data_0 | 0 .../default_0/Ensemble/mod_5/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_5/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_6/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_6/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_6/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_6/FORECAST.data_0 | Bin 107456 -> 0 bytes .../default_0/Ensemble/mod_6/FORECAST.index | Bin 1702 -> 0 bytes .../default_0/Ensemble/mod_6/FORECAST.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_6/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_6/PARAMETER.index | Bin 72 -> 0 bytes .../default_0/Ensemble/mod_6/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_6/STATIC.data_0 | 0 .../default_0/Ensemble/mod_6/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_6/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_7/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_7/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_7/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_7/FORECAST.data_0 | Bin 102144 -> 0 bytes .../default_0/Ensemble/mod_7/FORECAST.index | Bin 1702 -> 0 bytes .../default_0/Ensemble/mod_7/FORECAST.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_7/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_7/PARAMETER.index | Bin 72 -> 0 bytes .../default_0/Ensemble/mod_7/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_7/STATIC.data_0 | 0 .../default_0/Ensemble/mod_7/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_7/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_8/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_8/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_8/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_8/FORECAST.data_0 | Bin 106688 -> 0 bytes .../default_0/Ensemble/mod_8/FORECAST.index | Bin 1702 -> 0 bytes .../default_0/Ensemble/mod_8/FORECAST.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_8/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_8/PARAMETER.index | Bin 72 -> 0 bytes .../default_0/Ensemble/mod_8/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_8/STATIC.data_0 | 0 .../default_0/Ensemble/mod_8/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_8/STATIC.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_9/ANALYZED.data_0 | 0 .../default_0/Ensemble/mod_9/ANALYZED.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_9/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_9/FORECAST.data_0 | Bin 106880 -> 0 bytes .../default_0/Ensemble/mod_9/FORECAST.index | Bin 1702 -> 0 bytes .../default_0/Ensemble/mod_9/FORECAST.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_9/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_0/Ensemble/mod_9/PARAMETER.index | Bin 72 -> 0 bytes .../default_0/Ensemble/mod_9/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_0/Ensemble/mod_9/STATIC.data_0 | 0 .../default_0/Ensemble/mod_9/STATIC.index | Bin 24 -> 0 bytes .../default_0/Ensemble/mod_9/STATIC.mnt | Bin 8 -> 0 bytes .../ensemble/default_0/Index/INDEX.data_0 | 0 .../ensemble/default_0/Index/INDEX.index | Bin 24 -> 0 bytes .../ensemble/default_0/Index/INDEX.mnt | Bin 8 -> 0 bytes .../snake_oil/ensemble/default_0/ert_fstab | Bin 207 -> 0 bytes .../ensemble/default_0/files/case_config | Bin 4 -> 0 bytes .../default_0/files/custom_kw_config_set | Bin 53 -> 0 bytes .../ensemble/default_0/files/state-map | Bin 108 -> 0 bytes .../ensemble/default_0/files/summary-key-set | Bin 463 -> 0 bytes .../ensemble/default_0/files/time-map | Bin 1620 -> 0 bytes .../default_1/Ensemble/mod_0/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_0/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_0/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_0/FORECAST.data_0 | Bin 106560 -> 0 bytes .../default_1/Ensemble/mod_0/FORECAST.index | Bin 1702 -> 0 bytes .../default_1/Ensemble/mod_0/FORECAST.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_0/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_0/PARAMETER.index | Bin 72 -> 0 bytes .../default_1/Ensemble/mod_0/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_0/STATIC.data_0 | 0 .../default_1/Ensemble/mod_0/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_0/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_1/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_1/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_1/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_1/FORECAST.data_0 | Bin 106496 -> 0 bytes .../default_1/Ensemble/mod_1/FORECAST.index | Bin 1702 -> 0 bytes .../default_1/Ensemble/mod_1/FORECAST.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_1/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_1/PARAMETER.index | Bin 72 -> 0 bytes .../default_1/Ensemble/mod_1/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_1/STATIC.data_0 | 0 .../default_1/Ensemble/mod_1/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_1/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_10/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_10/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_10/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_10/FORECAST.data_0 | Bin 107008 -> 0 bytes .../default_1/Ensemble/mod_10/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_10/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_10/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_10/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_10/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_10/STATIC.data_0 | 0 .../default_1/Ensemble/mod_10/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_10/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_11/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_11/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_11/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_11/FORECAST.data_0 | Bin 107072 -> 0 bytes .../default_1/Ensemble/mod_11/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_11/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_11/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_11/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_11/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_11/STATIC.data_0 | 0 .../default_1/Ensemble/mod_11/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_11/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_12/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_12/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_12/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_12/FORECAST.data_0 | Bin 104320 -> 0 bytes .../default_1/Ensemble/mod_12/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_12/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_12/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_12/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_12/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_12/STATIC.data_0 | 0 .../default_1/Ensemble/mod_12/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_12/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_13/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_13/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_13/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_13/FORECAST.data_0 | Bin 105152 -> 0 bytes .../default_1/Ensemble/mod_13/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_13/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_13/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_13/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_13/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_13/STATIC.data_0 | 0 .../default_1/Ensemble/mod_13/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_13/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_14/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_14/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_14/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_14/FORECAST.data_0 | Bin 106688 -> 0 bytes .../default_1/Ensemble/mod_14/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_14/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_14/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_14/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_14/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_14/STATIC.data_0 | 0 .../default_1/Ensemble/mod_14/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_14/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_15/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_15/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_15/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_15/FORECAST.data_0 | Bin 101120 -> 0 bytes .../default_1/Ensemble/mod_15/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_15/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_15/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_15/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_15/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_15/STATIC.data_0 | 0 .../default_1/Ensemble/mod_15/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_15/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_16/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_16/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_16/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_16/FORECAST.data_0 | Bin 103360 -> 0 bytes .../default_1/Ensemble/mod_16/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_16/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_16/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_16/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_16/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_16/STATIC.data_0 | 0 .../default_1/Ensemble/mod_16/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_16/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_17/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_17/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_17/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_17/FORECAST.data_0 | Bin 108096 -> 0 bytes .../default_1/Ensemble/mod_17/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_17/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_17/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_17/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_17/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_17/STATIC.data_0 | 0 .../default_1/Ensemble/mod_17/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_17/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_18/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_18/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_18/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_18/FORECAST.data_0 | Bin 103680 -> 0 bytes .../default_1/Ensemble/mod_18/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_18/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_18/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_18/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_18/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_18/STATIC.data_0 | 0 .../default_1/Ensemble/mod_18/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_18/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_19/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_19/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_19/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_19/FORECAST.data_0 | Bin 107712 -> 0 bytes .../default_1/Ensemble/mod_19/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_19/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_19/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_19/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_19/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_19/STATIC.data_0 | 0 .../default_1/Ensemble/mod_19/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_19/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_2/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_2/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_2/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_2/FORECAST.data_0 | Bin 107200 -> 0 bytes .../default_1/Ensemble/mod_2/FORECAST.index | Bin 1702 -> 0 bytes .../default_1/Ensemble/mod_2/FORECAST.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_2/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_2/PARAMETER.index | Bin 72 -> 0 bytes .../default_1/Ensemble/mod_2/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_2/STATIC.data_0 | 0 .../default_1/Ensemble/mod_2/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_2/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_20/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_20/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_20/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_20/FORECAST.data_0 | Bin 108160 -> 0 bytes .../default_1/Ensemble/mod_20/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_20/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_20/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_20/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_20/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_20/STATIC.data_0 | 0 .../default_1/Ensemble/mod_20/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_20/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_21/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_21/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_21/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_21/FORECAST.data_0 | Bin 108352 -> 0 bytes .../default_1/Ensemble/mod_21/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_21/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_21/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_21/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_21/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_21/STATIC.data_0 | 0 .../default_1/Ensemble/mod_21/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_21/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_22/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_22/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_22/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_22/FORECAST.data_0 | Bin 108352 -> 0 bytes .../default_1/Ensemble/mod_22/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_22/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_22/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_22/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_22/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_22/STATIC.data_0 | 0 .../default_1/Ensemble/mod_22/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_22/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_23/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_23/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_23/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_23/FORECAST.data_0 | Bin 102528 -> 0 bytes .../default_1/Ensemble/mod_23/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_23/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_23/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_23/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_23/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_23/STATIC.data_0 | 0 .../default_1/Ensemble/mod_23/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_23/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_24/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_24/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_24/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_24/FORECAST.data_0 | Bin 101056 -> 0 bytes .../default_1/Ensemble/mod_24/FORECAST.index | Bin 1745 -> 0 bytes .../default_1/Ensemble/mod_24/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_24/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_24/PARAMETER.index | Bin 73 -> 0 bytes .../default_1/Ensemble/mod_24/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_24/STATIC.data_0 | 0 .../default_1/Ensemble/mod_24/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_24/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_25/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_25/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_25/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_25/FORECAST.data_0 | 0 .../default_1/Ensemble/mod_25/FORECAST.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_25/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_25/PARAMETER.data_0 | 0 .../default_1/Ensemble/mod_25/PARAMETER.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_25/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_25/STATIC.data_0 | 0 .../default_1/Ensemble/mod_25/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_25/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_26/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_26/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_26/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_26/FORECAST.data_0 | 0 .../default_1/Ensemble/mod_26/FORECAST.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_26/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_26/PARAMETER.data_0 | 0 .../default_1/Ensemble/mod_26/PARAMETER.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_26/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_26/STATIC.data_0 | 0 .../default_1/Ensemble/mod_26/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_26/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_27/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_27/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_27/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_27/FORECAST.data_0 | 0 .../default_1/Ensemble/mod_27/FORECAST.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_27/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_27/PARAMETER.data_0 | 0 .../default_1/Ensemble/mod_27/PARAMETER.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_27/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_27/STATIC.data_0 | 0 .../default_1/Ensemble/mod_27/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_27/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_28/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_28/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_28/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_28/FORECAST.data_0 | 0 .../default_1/Ensemble/mod_28/FORECAST.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_28/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_28/PARAMETER.data_0 | 0 .../default_1/Ensemble/mod_28/PARAMETER.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_28/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_28/STATIC.data_0 | 0 .../default_1/Ensemble/mod_28/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_28/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_29/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_29/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_29/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_29/FORECAST.data_0 | 0 .../default_1/Ensemble/mod_29/FORECAST.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_29/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_29/PARAMETER.data_0 | 0 .../default_1/Ensemble/mod_29/PARAMETER.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_29/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_29/STATIC.data_0 | 0 .../default_1/Ensemble/mod_29/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_29/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_3/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_3/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_3/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_3/FORECAST.data_0 | Bin 106944 -> 0 bytes .../default_1/Ensemble/mod_3/FORECAST.index | Bin 1702 -> 0 bytes .../default_1/Ensemble/mod_3/FORECAST.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_3/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_3/PARAMETER.index | Bin 72 -> 0 bytes .../default_1/Ensemble/mod_3/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_3/STATIC.data_0 | 0 .../default_1/Ensemble/mod_3/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_3/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_30/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_30/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_30/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_30/FORECAST.data_0 | 0 .../default_1/Ensemble/mod_30/FORECAST.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_30/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_30/PARAMETER.data_0 | 0 .../default_1/Ensemble/mod_30/PARAMETER.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_30/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_30/STATIC.data_0 | 0 .../default_1/Ensemble/mod_30/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_30/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_31/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_31/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_31/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_31/FORECAST.data_0 | 0 .../default_1/Ensemble/mod_31/FORECAST.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_31/FORECAST.mnt | Bin 8 -> 0 bytes .../Ensemble/mod_31/PARAMETER.data_0 | 0 .../default_1/Ensemble/mod_31/PARAMETER.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_31/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_31/STATIC.data_0 | 0 .../default_1/Ensemble/mod_31/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_31/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_4/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_4/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_4/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_4/FORECAST.data_0 | Bin 103040 -> 0 bytes .../default_1/Ensemble/mod_4/FORECAST.index | Bin 1702 -> 0 bytes .../default_1/Ensemble/mod_4/FORECAST.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_4/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_4/PARAMETER.index | Bin 72 -> 0 bytes .../default_1/Ensemble/mod_4/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_4/STATIC.data_0 | 0 .../default_1/Ensemble/mod_4/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_4/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_5/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_5/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_5/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_5/FORECAST.data_0 | Bin 105216 -> 0 bytes .../default_1/Ensemble/mod_5/FORECAST.index | Bin 1702 -> 0 bytes .../default_1/Ensemble/mod_5/FORECAST.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_5/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_5/PARAMETER.index | Bin 72 -> 0 bytes .../default_1/Ensemble/mod_5/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_5/STATIC.data_0 | 0 .../default_1/Ensemble/mod_5/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_5/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_6/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_6/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_6/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_6/FORECAST.data_0 | Bin 106688 -> 0 bytes .../default_1/Ensemble/mod_6/FORECAST.index | Bin 1702 -> 0 bytes .../default_1/Ensemble/mod_6/FORECAST.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_6/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_6/PARAMETER.index | Bin 72 -> 0 bytes .../default_1/Ensemble/mod_6/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_6/STATIC.data_0 | 0 .../default_1/Ensemble/mod_6/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_6/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_7/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_7/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_7/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_7/FORECAST.data_0 | Bin 105728 -> 0 bytes .../default_1/Ensemble/mod_7/FORECAST.index | Bin 1702 -> 0 bytes .../default_1/Ensemble/mod_7/FORECAST.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_7/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_7/PARAMETER.index | Bin 72 -> 0 bytes .../default_1/Ensemble/mod_7/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_7/STATIC.data_0 | 0 .../default_1/Ensemble/mod_7/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_7/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_8/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_8/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_8/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_8/FORECAST.data_0 | Bin 106496 -> 0 bytes .../default_1/Ensemble/mod_8/FORECAST.index | Bin 1702 -> 0 bytes .../default_1/Ensemble/mod_8/FORECAST.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_8/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_8/PARAMETER.index | Bin 72 -> 0 bytes .../default_1/Ensemble/mod_8/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_8/STATIC.data_0 | 0 .../default_1/Ensemble/mod_8/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_8/STATIC.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_9/ANALYZED.data_0 | 0 .../default_1/Ensemble/mod_9/ANALYZED.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_9/ANALYZED.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_9/FORECAST.data_0 | Bin 106240 -> 0 bytes .../default_1/Ensemble/mod_9/FORECAST.index | Bin 1702 -> 0 bytes .../default_1/Ensemble/mod_9/FORECAST.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_9/PARAMETER.data_0 | Bin 192 -> 0 bytes .../default_1/Ensemble/mod_9/PARAMETER.index | Bin 72 -> 0 bytes .../default_1/Ensemble/mod_9/PARAMETER.mnt | Bin 8 -> 0 bytes .../default_1/Ensemble/mod_9/STATIC.data_0 | 0 .../default_1/Ensemble/mod_9/STATIC.index | Bin 24 -> 0 bytes .../default_1/Ensemble/mod_9/STATIC.mnt | Bin 8 -> 0 bytes .../ensemble/default_1/Index/INDEX.data_0 | 0 .../ensemble/default_1/Index/INDEX.index | Bin 24 -> 0 bytes .../ensemble/default_1/Index/INDEX.mnt | Bin 8 -> 0 bytes .../snake_oil/ensemble/default_1/ert_fstab | Bin 207 -> 0 bytes .../ensemble/default_1/files/case_config | Bin 4 -> 0 bytes .../default_1/files/custom_kw_config_set | Bin 53 -> 0 bytes .../ensemble/default_1/files/state-map | Bin 108 -> 0 bytes .../ensemble/default_1/files/summary-key-set | Bin 463 -> 0 bytes .../ensemble/default_1/files/time-map | Bin 1620 -> 0 bytes .../snake_oil/templates/seed_template.txt | 1 - .../templates/snake_oil_template.txt | 10 - .../Ert/test-data/local/snake_oil_field/SEED | 1 - .../snake_oil_field/fields/permx0.grdecl | 127 - .../snake_oil_field/fields/permx1.grdecl | 127 - .../snake_oil_field/fields/permx2.grdecl | 127 - .../snake_oil_field/fields/permx3.grdecl | 127 - .../snake_oil_field/fields/permx4.grdecl | 127 - .../snake_oil_field/fields/permx5.grdecl | 127 - .../snake_oil_field/fields/permx6.grdecl | 127 - .../snake_oil_field/fields/permx7.grdecl | 127 - .../snake_oil_field/fields/permx8.grdecl | 127 - .../snake_oil_field/fields/permx9.grdecl | 127 - .../local/snake_oil_field/fields/poro0.grdecl | 127 - .../local/snake_oil_field/fields/poro1.grdecl | 127 - .../local/snake_oil_field/fields/poro2.grdecl | 127 - .../local/snake_oil_field/fields/poro3.grdecl | 127 - .../local/snake_oil_field/fields/poro4.grdecl | 127 - .../local/snake_oil_field/fields/poro5.grdecl | 127 - .../local/snake_oil_field/fields/poro6.grdecl | 127 - .../local/snake_oil_field/fields/poro7.grdecl | 127 - .../local/snake_oil_field/fields/poro8.grdecl | 127 - .../local/snake_oil_field/fields/poro9.grdecl | 127 - .../local/snake_oil_field/grid/CASE.EGRID | Bin 22000 -> 0 bytes .../local/snake_oil_field/jobs/SNAKE_OIL_DIFF | 4 - .../local/snake_oil_field/jobs/SNAKE_OIL_NPV | 4 - .../snake_oil_field/jobs/SNAKE_OIL_SIMULATOR | 4 - .../snake_oil_field/jobs/snake_oil_diff.py | 24 - .../snake_oil_field/jobs/snake_oil_npv.py | 103 - .../jobs/snake_oil_simulator.py | 185 - .../local/snake_oil_field/make_data.py | 51 - .../observations/observations.txt | 56 - .../observations/wpr_diff_obs.txt | 4 - .../parameters/snake_oil_parameters.txt | 11 - .../refcase/SNAKE_OIL_FIELD.SMSPEC | Bin 1416 -> 0 bytes .../refcase/SNAKE_OIL_FIELD.UNSMRY | Bin 455200 -> 0 bytes .../refcase/refcase_readme.txt | 1 - .../local/snake_oil_field/refcase/seed.txt | 1 - .../refcase/snake_oil_params.txt | 10 - .../snake_oil_field/refcase/time_map.txt | 2000 ---------- .../local/snake_oil_field/snake_oil.ert | 50 - .../templates/seed_template.txt | 1 - .../templates/snake_oil_template.txt | 10 - .../test-data/local/snake_oil_no_data/SEED | 1 - .../snake_oil_no_data/jobs/SNAKE_OIL_DIFF | 4 - .../snake_oil_no_data/jobs/SNAKE_OIL_NPV | 4 - .../jobs/SNAKE_OIL_SIMULATOR | 4 - .../snake_oil_no_data/jobs/snake_oil_diff.py | 24 - .../snake_oil_no_data/jobs/snake_oil_npv.py | 103 - .../jobs/snake_oil_simulator.py | 185 - .../observations/observations.txt | 56 - .../observations/wpr_diff_obs.txt | 4 - .../parameters/snake_oil_parameters.txt | 11 - .../refcase/SNAKE_OIL_FIELD.SMSPEC | Bin 1416 -> 0 bytes .../refcase/SNAKE_OIL_FIELD.UNSMRY | Bin 455200 -> 0 bytes .../refcase/refcase_readme.txt | 1 - .../local/snake_oil_no_data/refcase/seed.txt | 1 - .../refcase/snake_oil_params.txt | 10 - .../snake_oil_no_data/refcase/time_map.txt | 2000 ---------- .../local/snake_oil_no_data/snake_oil.ert | 40 - .../snake_oil_no_data/snake_oil_GEO_ID.ert | 39 - .../templates/seed_template.txt | 1 - .../templates/snake_oil_template.txt | 10 - 3618 files changed, 6410 insertions(+), 171524 deletions(-) delete mode 100644 ThirdParty/Ert/README create mode 100644 ThirdParty/Ert/README.md delete mode 100644 ThirdParty/Ert/docs/user/distributions/index.rst delete mode 100644 ThirdParty/Ert/docs/user/index.rst delete mode 100644 ThirdParty/Ert/docs/user/keywords/index.rst delete mode 100644 ThirdParty/Ert/docs/user/localization/index.rst delete mode 100644 ThirdParty/Ert/docs/user/magic_strings/index.rst delete mode 100644 ThirdParty/Ert/docs/user/observations/index.rst delete mode 100644 ThirdParty/Ert/docs/user/tutorial/index.rst delete mode 100644 ThirdParty/Ert/docs/user/workflows/built_in.rst delete mode 100644 ThirdParty/Ert/docs/user/workflows/index.rst delete mode 100644 ThirdParty/Ert/docs/user/workflows/plugins.rst delete mode 100644 ThirdParty/Ert/docs/user/workflows/workflows.rst delete mode 100644 ThirdParty/Ert/etc-example/ERT/Scripts/job_dispatch.py delete mode 100644 ThirdParty/Ert/etc-example/ERT/Scripts/run_RMS_20xx delete mode 100644 ThirdParty/Ert/etc-example/ERT/Scripts/run_eclipse.py delete mode 100644 ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE delete mode 100644 ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE100_2009.2 delete mode 100644 ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE100_2009.2_NOTARGET delete mode 100644 ThirdParty/Ert/etc-example/ERT/jobs/RUN_RMS_20XX delete mode 100644 ThirdParty/Ert/etc-example/ERT/site-config delete mode 100644 ThirdParty/Ert/etc-example/README delete mode 100644 ThirdParty/Ert/libanalysis/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libanalysis/applications/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libanalysis/applications/ert_module_test.c delete mode 100644 ThirdParty/Ert/libanalysis/applications/main_test.c delete mode 100644 ThirdParty/Ert/libanalysis/cmake/ert_module.cmake delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/analysis_module.h delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/analysis_table.h delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/cv_enkf.h delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/enkf_linalg.h delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/fwd_step_enkf.h delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/fwd_step_log.h delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/module_data_block.h delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/module_data_block_vector.h delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/module_info.h delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/module_obs_block.h delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/module_obs_block_vector.h delete mode 100644 ThirdParty/Ert/libanalysis/include/ert/analysis/std_enkf.h delete mode 100644 ThirdParty/Ert/libanalysis/modules/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libanalysis/modules/deprecated/rml_enkf.c delete mode 100644 ThirdParty/Ert/libanalysis/modules/rml_enkf.c delete mode 100644 ThirdParty/Ert/libanalysis/modules/rml_enkf_common.c delete mode 100644 ThirdParty/Ert/libanalysis/modules/rml_enkf_common.h delete mode 100644 ThirdParty/Ert/libanalysis/modules/rml_enkf_config.c delete mode 100644 ThirdParty/Ert/libanalysis/modules/rml_enkf_config.h delete mode 100644 ThirdParty/Ert/libanalysis/modules/rml_enkf_log.c delete mode 100644 ThirdParty/Ert/libanalysis/modules/rml_enkf_log.h delete mode 100644 ThirdParty/Ert/libanalysis/modules/std_enkf_debug.c delete mode 100644 ThirdParty/Ert/libanalysis/modules/tests/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libanalysis/modules/tests/analysis_rml_enkf_common.c delete mode 100644 ThirdParty/Ert/libanalysis/script/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libanalysis/script/ert_module delete mode 100644 ThirdParty/Ert/libanalysis/src/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libanalysis/src/analysis_module.c delete mode 100644 ThirdParty/Ert/libanalysis/src/bootstrap_enkf.c delete mode 100644 ThirdParty/Ert/libanalysis/src/cv_enkf.c delete mode 100644 ThirdParty/Ert/libanalysis/src/enkf_linalg.c delete mode 100644 ThirdParty/Ert/libanalysis/src/fwd_step_enkf.c delete mode 100644 ThirdParty/Ert/libanalysis/src/fwd_step_log.c delete mode 100644 ThirdParty/Ert/libanalysis/src/module_data_block.c delete mode 100644 ThirdParty/Ert/libanalysis/src/module_data_block_vector.c delete mode 100644 ThirdParty/Ert/libanalysis/src/module_info.c delete mode 100644 ThirdParty/Ert/libanalysis/src/module_obs_block.c delete mode 100644 ThirdParty/Ert/libanalysis/src/module_obs_block_vector.c delete mode 100644 ThirdParty/Ert/libanalysis/src/modules.txt delete mode 100644 ThirdParty/Ert/libanalysis/src/null_enkf.c delete mode 100644 ThirdParty/Ert/libanalysis/src/sqrt_enkf.c delete mode 100644 ThirdParty/Ert/libanalysis/src/std_enkf.c delete mode 100644 ThirdParty/Ert/libanalysis/tests/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libanalysis/tests/analysis_test_external_module.c delete mode 100644 ThirdParty/Ert/libanalysis/tests/analysis_test_module_info.c delete mode 100644 ThirdParty/Ert/libconfig/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libconfig/applications/conf_test.c delete mode 100644 ThirdParty/Ert/libconfig/applications/config_test.c delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/conf.h delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/conf_data.h delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/conf_util.h delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/config_content.h delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/config_content_item.h delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/config_content_node.h delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/config_error.h delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/config_parser.h delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/config_path_elm.h delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/config_root_path.h delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/config_schema_item.h delete mode 100644 ThirdParty/Ert/libconfig/include/ert/config/config_settings.h delete mode 100644 ThirdParty/Ert/libconfig/src/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libconfig/src/conf.c delete mode 100644 ThirdParty/Ert/libconfig/src/conf_data.c delete mode 100644 ThirdParty/Ert/libconfig/src/conf_util.c delete mode 100644 ThirdParty/Ert/libconfig/src/config_content.c delete mode 100644 ThirdParty/Ert/libconfig/src/config_content_item.c delete mode 100644 ThirdParty/Ert/libconfig/src/config_content_node.c delete mode 100644 ThirdParty/Ert/libconfig/src/config_error.c delete mode 100644 ThirdParty/Ert/libconfig/src/config_get.c delete mode 100644 ThirdParty/Ert/libconfig/src/config_parser.c delete mode 100644 ThirdParty/Ert/libconfig/src/config_path_elm.c delete mode 100644 ThirdParty/Ert/libconfig/src/config_root_path.c delete mode 100644 ThirdParty/Ert/libconfig/src/config_schema_item.c delete mode 100644 ThirdParty/Ert/libconfig/src/config_settings.c delete mode 100644 ThirdParty/Ert/libconfig/src/testcase/test.txt delete mode 100644 ThirdParty/Ert/libconfig/src/testcase/test2.txt delete mode 100644 ThirdParty/Ert/libconfig/tests/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libconfig/tests/config_append_test.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_argc.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_config.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_content.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_content_item.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_content_node.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_define.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_error.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_include_test.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_node_test.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_path_elm.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_root_path.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_schema_item.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_typeFail.c delete mode 100644 ThirdParty/Ert/libconfig/tests/config_typeOK.c delete mode 100644 ThirdParty/Ert/libconfig/tests/data/append_test delete mode 100644 ThirdParty/Ert/libconfig/tests/data/argc_OK delete mode 100644 ThirdParty/Ert/libconfig/tests/data/argc_less delete mode 100644 ThirdParty/Ert/libconfig/tests/data/argc_more delete mode 100644 ThirdParty/Ert/libconfig/tests/data/content_item_test delete mode 100644 ThirdParty/Ert/libconfig/tests/data/define_test delete mode 100644 ThirdParty/Ert/libconfig/tests/data/include_test delete mode 100644 ThirdParty/Ert/libconfig/tests/data/path/include1 delete mode 100644 ThirdParty/Ert/libconfig/tests/data/path/subpath/include2 delete mode 100644 ThirdParty/Ert/libconfig/tests/data/path/subpath/include3 delete mode 100644 ThirdParty/Ert/libconfig/tests/data/path/subpath/subsubpath/include4 delete mode 100644 ThirdParty/Ert/libconfig/tests/data/type_testFail delete mode 100644 ThirdParty/Ert/libconfig/tests/data/type_testOK create mode 100644 ThirdParty/Ert/libecl/include/ert/ecl/ecl_nnc_geometry.h create mode 100644 ThirdParty/Ert/libecl/include/ert/ecl/ecl_type.h create mode 100644 ThirdParty/Ert/libecl/src/ecl_nnc_geometry.c create mode 100644 ThirdParty/Ert/libecl/src/ecl_type.c create mode 100644 ThirdParty/Ert/libecl/src/ecl_type_python.c create mode 100644 ThirdParty/Ert/libecl/tests/ecl_alloc_cpgrid.c create mode 100644 ThirdParty/Ert/libecl/tests/ecl_grid_cell_contains_wellpath.c create mode 100644 ThirdParty/Ert/libecl/tests/ecl_nnc_geometry.c create mode 100644 ThirdParty/Ert/libeclxx/tests/eclxx_types.cpp delete mode 100644 ThirdParty/Ert/libenkf/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/CMake/config/ert_build_config_file.h.in delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/ERT.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_QC.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_analysis.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_analysis.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_export.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_export.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_fs.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_fs.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_help.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_help.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_init.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_init.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_main.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_main.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_misc.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_misc.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_ranking.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_ranking.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_run.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_run.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_simple.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_simple.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_table.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_table.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_util.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_util.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_workflow.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_workflow.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/ert_tui_const.h delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/main.c delete mode 100644 ThirdParty/Ert/libenkf/applications/ert_tui/upgrade_fs104.c delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/README.new_type.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/README.new_type_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/active_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/active_list.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/active_node.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/analysis_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/analysis_iter_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/block_fs_driver.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/block_obs.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/cases_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/config_keys.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/config_parser.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/container.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/container_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw_config_set.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/data_ranking.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/ecl_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/ecl_refcase_list.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_analysis.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_config_node.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_config_private.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_defaults.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_fs.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_fs_type.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_macros.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main_jobs.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main_update.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_node.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_obs.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_data.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gen_kw.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gen_kw_vector.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gendata.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_genvector.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_tvector.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_serialize.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_state.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_types.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/enkf_util.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/ensemble_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/ert_init_context.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/ert_log.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/ert_run_context.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/ert_template.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/ert_test_context.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/ert_workflow_list.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/field.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/field_common.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/field_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/field_trans.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/forward_load_context.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/fs_driver.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/fs_types.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/gen_common.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/gen_data.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/gen_data_common.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/gen_data_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw_common.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/gen_obs.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/hook_manager.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/hook_workflow.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/local_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/local_context.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/local_dataset.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/local_ministep.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/local_obsdata.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/local_obsdata_node.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/local_updatestep.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/meas_data.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/member_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ensemble.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ensemble_typedef.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/misfit_member.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ranking.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ts.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/model_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/obs_data.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/obs_vector.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/pca_plot_data.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/pca_plot_vector.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/plain_driver.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/plain_driver_obs.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/plot_settings.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/ranking_common.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/ranking_table.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/rng_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/run_arg.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/run_arg_type.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/runpath_list.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/scalar_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/site_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/state_map.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/summary.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/summary_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/summary_key_matcher.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/summary_key_set.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/summary_obs.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/surface.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/surface_config.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/time_map.h delete mode 100644 ThirdParty/Ert/libenkf/include/ert/enkf/trans_func.h delete mode 100644 ThirdParty/Ert/libenkf/src/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libenkf/src/README.new_config_draft delete mode 100644 ThirdParty/Ert/libenkf/src/README.new_type.c delete mode 100644 ThirdParty/Ert/libenkf/src/README.obs delete mode 100644 ThirdParty/Ert/libenkf/src/README.paths delete mode 100644 ThirdParty/Ert/libenkf/src/active_list.c delete mode 100644 ThirdParty/Ert/libenkf/src/active_node.c delete mode 100644 ThirdParty/Ert/libenkf/src/analysis_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/analysis_iter_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/block_fs_driver.c delete mode 100644 ThirdParty/Ert/libenkf/src/block_obs.c delete mode 100644 ThirdParty/Ert/libenkf/src/cases_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/container.c delete mode 100644 ThirdParty/Ert/libenkf/src/container_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/custom_kw.c delete mode 100644 ThirdParty/Ert/libenkf/src/custom_kw_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/custom_kw_config_set.c delete mode 100644 ThirdParty/Ert/libenkf/src/data_ranking.c delete mode 100644 ThirdParty/Ert/libenkf/src/dependencies delete mode 100644 ThirdParty/Ert/libenkf/src/ecl_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/ecl_refcase_list.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_analysis.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_config_node.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_defaults.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_fs.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_main.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_main_jobs.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_main_manage_fs.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_main_update.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_node.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_obs.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_plot_data.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_plot_gen_kw.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_plot_gen_kw_vector.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_plot_gendata.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_plot_genvector.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_plot_tvector.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_serialize.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_state.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_types.c delete mode 100644 ThirdParty/Ert/libenkf/src/enkf_util.c delete mode 100644 ThirdParty/Ert/libenkf/src/ensemble_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/ert_init_context.c delete mode 100644 ThirdParty/Ert/libenkf/src/ert_log.c delete mode 100644 ThirdParty/Ert/libenkf/src/ert_run_context.c delete mode 100644 ThirdParty/Ert/libenkf/src/ert_template.c delete mode 100644 ThirdParty/Ert/libenkf/src/ert_test_context.c delete mode 100644 ThirdParty/Ert/libenkf/src/ert_users.c delete mode 100644 ThirdParty/Ert/libenkf/src/ert_workflow_list.c delete mode 100644 ThirdParty/Ert/libenkf/src/field.c delete mode 100644 ThirdParty/Ert/libenkf/src/field_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/field_convert.c delete mode 100644 ThirdParty/Ert/libenkf/src/field_test.c delete mode 100644 ThirdParty/Ert/libenkf/src/field_trans.c delete mode 100644 ThirdParty/Ert/libenkf/src/forward_load_context.c delete mode 100644 ThirdParty/Ert/libenkf/src/fs_driver.c delete mode 100644 ThirdParty/Ert/libenkf/src/fs_types.c delete mode 100644 ThirdParty/Ert/libenkf/src/gen_common.c delete mode 100644 ThirdParty/Ert/libenkf/src/gen_data.c delete mode 100644 ThirdParty/Ert/libenkf/src/gen_data_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/gen_kw.c delete mode 100644 ThirdParty/Ert/libenkf/src/gen_kw_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/gen_obs.c delete mode 100644 ThirdParty/Ert/libenkf/src/gen_test.c delete mode 100644 ThirdParty/Ert/libenkf/src/hook_manager.c delete mode 100644 ThirdParty/Ert/libenkf/src/hook_workflow.c delete mode 100644 ThirdParty/Ert/libenkf/src/local_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/local_context.c delete mode 100644 ThirdParty/Ert/libenkf/src/local_dataset.c delete mode 100644 ThirdParty/Ert/libenkf/src/local_ministep.c delete mode 100644 ThirdParty/Ert/libenkf/src/local_obsdata.c delete mode 100644 ThirdParty/Ert/libenkf/src/local_obsdata_node.c delete mode 100644 ThirdParty/Ert/libenkf/src/local_updatestep.c delete mode 100644 ThirdParty/Ert/libenkf/src/meas_data.c delete mode 100644 ThirdParty/Ert/libenkf/src/member_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/migrate_bfs.c delete mode 100644 ThirdParty/Ert/libenkf/src/misfit_ensemble.c delete mode 100644 ThirdParty/Ert/libenkf/src/misfit_member.c delete mode 100644 ThirdParty/Ert/libenkf/src/misfit_ranking.c delete mode 100644 ThirdParty/Ert/libenkf/src/misfit_ts.c delete mode 100644 ThirdParty/Ert/libenkf/src/model_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/obs_data.c delete mode 100644 ThirdParty/Ert/libenkf/src/obs_vector.c delete mode 100644 ThirdParty/Ert/libenkf/src/pca_plot_data.c delete mode 100644 ThirdParty/Ert/libenkf/src/pca_plot_vector.c delete mode 100644 ThirdParty/Ert/libenkf/src/plain_driver.c delete mode 100644 ThirdParty/Ert/libenkf/src/plain_driver_obs.c delete mode 100644 ThirdParty/Ert/libenkf/src/plot_settings.c delete mode 100644 ThirdParty/Ert/libenkf/src/ranking_table.c delete mode 100644 ThirdParty/Ert/libenkf/src/readme.overview delete mode 100644 ThirdParty/Ert/libenkf/src/rng_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/run_arg.c delete mode 100644 ThirdParty/Ert/libenkf/src/runpath_list.c delete mode 100644 ThirdParty/Ert/libenkf/src/scalar_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/site_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/state_map.c delete mode 100644 ThirdParty/Ert/libenkf/src/summary.c delete mode 100644 ThirdParty/Ert/libenkf/src/summary_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/summary_key_matcher.c delete mode 100644 ThirdParty/Ert/libenkf/src/summary_key_set.c delete mode 100644 ThirdParty/Ert/libenkf/src/summary_obs.c delete mode 100644 ThirdParty/Ert/libenkf/src/surface.c delete mode 100644 ThirdParty/Ert/libenkf/src/surface_config.c delete mode 100644 ThirdParty/Ert/libenkf/src/test.c delete mode 100644 ThirdParty/Ert/libenkf/src/time_map.c delete mode 100644 ThirdParty/Ert/libenkf/src/trans_errf.m delete mode 100644 ThirdParty/Ert/libenkf/src/trans_func.c delete mode 100644 ThirdParty/Ert/libenkf/src/trans_test.m delete mode 100644 ThirdParty/Ert/libenkf/tests/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/analysis_load_config delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/analysis_load_site_config delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/ert_report_list delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/forward/ert/FAULT_TEMPLATE delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/forward/ert/MULTFLT.TXT delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_KW_false delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_KW_true delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_PARAM_false delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_PARAM_true delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/forward/ert/script.sh delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/FAULT_TEMPLATE delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/FAULT_TEMPLATE2 delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/MULTFLT.TXT delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/MULTFLT2.TXT delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/config_GEN_KW_logarithmic delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/script.sh delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/Parameters.txt delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/Template.tmpl delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/config delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/rng delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/runpath_list/ARGECHO_JOB delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/runpath_list/ARGECHO_WF delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/runpath_list/arg_echo.sh delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/runpath_list/config delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/script.sh delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/test_context/FAULT_TEMPLATE delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/test_context/MULTFLT.TXT delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/test_context/config delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/test_context/script.sh delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/test_context/wf_job delete mode 100644 ThirdParty/Ert/libenkf/tests/data/config/test_context/wf_job_fail delete mode 100644 ThirdParty/Ert/libenkf/tests/data/ensemble/GEN_PARAM delete mode 100644 ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF1 delete mode 100644 ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF2 delete mode 100644 ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF2@1 delete mode 100644 ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF3@1.2.3 delete mode 100644 ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF4@1.2.0 delete mode 100644 ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF5@1.2 delete mode 100644 ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF5@1.2.0 delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_active_list.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_analysis_config.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_analysis_config_analysis_load.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_analysis_config_ext_module.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_analysis_update_job.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_block_obs.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_cases_config.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_config_node.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_ecl_config.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_ecl_config_config.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_enkf_config_node_gen_data.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_ensemble.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_ensemble_GEN_PARAM.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_ensemble_config.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_ert_run_context.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_ert_test_context.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_ert_workflow_list.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_export_field_test.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_export_inactive_cells.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_forward_init_FIELD.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_forward_init_GEN_KW.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_forward_init_GEN_PARAM.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_forward_init_SURFACE.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_forward_init_transform.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_forward_load_context.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_fs.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_gen_data_config.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_gen_data_config_parse.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_gen_obs_load.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_hook_manager_test.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_iter_config.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_local_obsdata.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_local_obsdata_node.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_magic_string_in_workflows.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_main.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_main_fs.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_main_fs_current_file_test.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_meas_data.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_model_config.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_obs_fs.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_obs_tests.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_obs_vector.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_obs_vector_fs.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_pca_plot.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_plot_data.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_plot_data_fs.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw_fs.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw_vector.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_plot_gendata.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_plot_gendata_fs.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_plot_genvector.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_plot_tvector.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_refcase_list.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_rng.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_run_arg.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_runpath_list.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_scale_correlated_std.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_select_case_job.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_site_config.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_state_manual_load_test.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_state_map.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_state_report_step_compatible.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_state_skip_summary_load_test.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_time_map.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_umask_config_test.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_workflow_job_test.c delete mode 100644 ThirdParty/Ert/libenkf/tests/enkf_workflow_job_test_version.c delete mode 100644 ThirdParty/Ert/libenkf/tests/gen_kw_logarithmic_test.c delete mode 100644 ThirdParty/Ert/libenkf/tests/gen_kw_test.c delete mode 100644 ThirdParty/Ert/libenkf/tests/obs_vector_tests.c delete mode 100644 ThirdParty/Ert/libenkf/tests/statoil_tests.cmake delete mode 100644 ThirdParty/Ert/libenkf/tests/tests.cmake delete mode 100644 ThirdParty/Ert/libert_util/include/ert/util/test_util_abort.h delete mode 100644 ThirdParty/Ert/libjob_queue/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libjob_queue/applications/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libjob_queue/applications/block_node.c delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/ext_job.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/ext_joblist.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/forward_model.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_list.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_node.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue_manager.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue_status.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/local_driver.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsb.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsf_driver.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsf_job_stat.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/queue_driver.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/rsh_driver.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/torque_driver.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow_job.h delete mode 100644 ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow_joblist.h delete mode 100644 ThirdParty/Ert/libjob_queue/src/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libjob_queue/src/ext_job.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/ext_joblist.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/forward_model.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/job_list.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/job_node.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/job_queue.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/job_queue_manager.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/job_queue_status.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/local_driver.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/lsb.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/lsf_driver.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/queue_driver.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/rsh_driver.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/torque_driver.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/workflow.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/workflow_job.c delete mode 100644 ThirdParty/Ert/libjob_queue/src/workflow_joblist.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libjob_queue/tests/create_file.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/externalFail delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/externalOK delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/external_job delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/internalFail delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/internalOK delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/internal_job delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/jobs/util/COPY_FILE delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/jobs/util/REPLACE delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/jobs/util/STORE_FILE delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/jobs/util/SYMLINK delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qdel delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qstat delete mode 100644 ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qsub delete mode 100644 ThirdParty/Ert/libjob_queue/tests/ext_joblist_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_job_queue_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_list_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_loadFail.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_loadOK.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_lsb.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_lsf_exclude_hosts_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_lsf_library_submit_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_lsf_parse_bsub_stdout.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_lsf_remote_submit_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_lsf_submit_library_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_lsf_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_node_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_program.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_program_output.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_queue_driver_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_queue_manager.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_queue_stress_task.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_queue_stress_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_queue_timeout_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_status_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_torque_submit_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_torque_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/job_workflow_test.c delete mode 100644 ThirdParty/Ert/libjob_queue/tests/lsf_tests.cmake delete mode 100644 ThirdParty/Ert/librms/CMakeLists.txt delete mode 100644 ThirdParty/Ert/librms/applications/CMakeLists.txt delete mode 100644 ThirdParty/Ert/librms/applications/rms_extract.c delete mode 100644 ThirdParty/Ert/librms/applications/rms_setname.c delete mode 100644 ThirdParty/Ert/librms/applications/rms_stat.c delete mode 100644 ThirdParty/Ert/librms/applications/rms_test.c delete mode 100644 ThirdParty/Ert/librms/applications/tag_list.c delete mode 100644 ThirdParty/Ert/librms/include/ert/rms/rms_export.h delete mode 100644 ThirdParty/Ert/librms/include/ert/rms/rms_file.h delete mode 100644 ThirdParty/Ert/librms/include/ert/rms/rms_stats.h delete mode 100644 ThirdParty/Ert/librms/include/ert/rms/rms_tag.h delete mode 100644 ThirdParty/Ert/librms/include/ert/rms/rms_tagkey.h delete mode 100644 ThirdParty/Ert/librms/include/ert/rms/rms_type.h delete mode 100644 ThirdParty/Ert/librms/include/ert/rms/rms_util.h delete mode 100644 ThirdParty/Ert/librms/src/CMakeLists.txt delete mode 100644 ThirdParty/Ert/librms/src/readme.overview delete mode 100644 ThirdParty/Ert/librms/src/rms_export.c delete mode 100644 ThirdParty/Ert/librms/src/rms_file.c delete mode 100644 ThirdParty/Ert/librms/src/rms_stats.c delete mode 100644 ThirdParty/Ert/librms/src/rms_tag.c delete mode 100644 ThirdParty/Ert/librms/src/rms_tagkey.c delete mode 100644 ThirdParty/Ert/librms/src/rms_type.c delete mode 100644 ThirdParty/Ert/librms/src/rms_util.c delete mode 100644 ThirdParty/Ert/librms/tests/CMakeLists.txt delete mode 100644 ThirdParty/Ert/librms/tests/rms_file_test.c delete mode 100644 ThirdParty/Ert/libsched/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libsched/applications/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libsched/applications/get_well_list.c delete mode 100644 ThirdParty/Ert/libsched/applications/gruptree_test.c delete mode 100644 ThirdParty/Ert/libsched/applications/perturb_history/group_rate.c delete mode 100644 ThirdParty/Ert/libsched/applications/perturb_history/group_rate.h delete mode 100644 ThirdParty/Ert/libsched/applications/perturb_history/pert.conf delete mode 100644 ThirdParty/Ert/libsched/applications/perturb_history/pert_util.c delete mode 100644 ThirdParty/Ert/libsched/applications/perturb_history/pert_util.h delete mode 100644 ThirdParty/Ert/libsched/applications/perturb_history/perturb_history.c delete mode 100644 ThirdParty/Ert/libsched/applications/perturb_history/well_rate.c delete mode 100644 ThirdParty/Ert/libsched/applications/perturb_history/well_rate.h delete mode 100644 ThirdParty/Ert/libsched/applications/sched_summary.c delete mode 100644 ThirdParty/Ert/libsched/applications/sched_test.c delete mode 100644 ThirdParty/Ert/libsched/applications/update_ir.c delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/group_history.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/group_index.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/gruptree.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/history.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_blob.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_file.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_history.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_compdat.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_dates.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_gruptree.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_include.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_tstep.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_untyped.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconhist.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinj.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinje.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinjh.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconprod.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_kw_welspecs.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_macros.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_time.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_types.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/sched_util.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/well_history.h delete mode 100644 ThirdParty/Ert/libsched/include/ert/sched/well_index.h delete mode 100644 ThirdParty/Ert/libsched/src/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libsched/src/group_history.c delete mode 100644 ThirdParty/Ert/libsched/src/group_index.c delete mode 100644 ThirdParty/Ert/libsched/src/gruptree.c delete mode 100644 ThirdParty/Ert/libsched/src/history.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_blob.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_file.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_history.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_compdat.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_dates.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_gruptree.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_include.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_tstep.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_untyped.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_wconhist.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_wconinj.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_wconinje.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_wconinjh.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_wconprod.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_kw_welspecs.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_time.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_types.c delete mode 100644 ThirdParty/Ert/libsched/src/sched_util.c delete mode 100644 ThirdParty/Ert/libsched/src/tests/sched_test_01.SCH delete mode 100644 ThirdParty/Ert/libsched/src/tests/sched_test_02.SCH delete mode 100644 ThirdParty/Ert/libsched/src/tests/sched_test_04.SCH delete mode 100644 ThirdParty/Ert/libsched/src/well_history.c delete mode 100644 ThirdParty/Ert/libsched/src/well_index.c delete mode 100644 ThirdParty/Ert/libsched/tests/CMakeLists.txt delete mode 100644 ThirdParty/Ert/libsched/tests/sched_history_summary.c delete mode 100644 ThirdParty/Ert/python/cmake/python_module_versions.cmake create mode 100644 ThirdParty/Ert/python/cmake/python_package_versions.cmake create mode 100644 ThirdParty/Ert/python/python/bin/CMakeLists.txt create mode 100644 ThirdParty/Ert/python/python/bin/ert_tcp_server create mode 100644 ThirdParty/Ert/python/python/bin/ert_upgrade_fs107 create mode 100644 ThirdParty/Ert/python/python/bin/ertshell delete mode 100644 ThirdParty/Ert/python/python/ert/analysis/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/analysis/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/analysis/analysis_module.py delete mode 100644 ThirdParty/Ert/python/python/ert/analysis/enums/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/analysis/enums/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/analysis/enums/analysis_module_load_status_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/analysis/enums/analysis_module_options_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/analysis/linalg.py delete mode 100644 ThirdParty/Ert/python/python/ert/config/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/config/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/config/config_content.py delete mode 100644 ThirdParty/Ert/python/python/ert/config/config_error.py delete mode 100644 ThirdParty/Ert/python/python/ert/config/config_parser.py delete mode 100644 ThirdParty/Ert/python/python/ert/config/config_settings.py delete mode 100644 ThirdParty/Ert/python/python/ert/config/content_type_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/config/schema_item.py delete mode 100644 ThirdParty/Ert/python/python/ert/config/unrecognized_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/ecl/ecl.py delete mode 100644 ThirdParty/Ert/python/python/ert/ecl/ecl_case.py create mode 100644 ThirdParty/Ert/python/python/ert/ecl/ecl_grid_generator.py delete mode 100644 ThirdParty/Ert/python/python/ert/ecl/ecl_queue.py create mode 100644 ThirdParty/Ert/python/python/ert/ecl/ecl_type.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/active_list.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/analysis_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/analysis_iter_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/config/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/config/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/config/custom_kw_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/config/enkf_config_node.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/config/field_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/config/gen_data_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/config/gen_kw_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/config/summary_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/custom_kw_config_set.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/data/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/data/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/data/custom_kw.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/data/enkf_node.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/data/field.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/data/gen_data.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/data/gen_kw.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/ecl_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enkf_fs.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enkf_fs_manager.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enkf_linalg.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enkf_main.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enkf_obs.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enkf_simulation_runner.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enkf_state.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/ensemble_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/active_mode_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/enkf_field_file_format_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/enkf_fs_type_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/enkf_init_modes_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/enkf_obs_impl_type_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/enkf_run_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/enkf_truncation_type.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/enkf_var_type_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/ert_impl_type_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/gen_data_file_type_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/hook_runtime_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/load_fail_type_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/enums/realization_state_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/ert_log.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/ert_run_context.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/ert_template.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/ert_templates.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/ert_workflow_list.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/es_update.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/export/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/export/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/export/arg_loader.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/export/custom_kw_collector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/export/design_matrix_reader.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/export/gen_data_collector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/export/gen_data_observation_collector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/export/gen_kw_collector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/export/misfit_collector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/export/summary_collector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/export/summary_observation_collector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/forward_load_context.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/hook_manager.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/hook_workflow.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/key_manager.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/local_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/local_dataset.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/local_ministep.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/local_obsdata.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/local_obsdata_node.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/local_updatestep.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/meas_block.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/meas_data.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/model_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/node_id.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/obs_block.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/obs_data.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/observations/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/observations/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/observations/block_data_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/observations/block_observation.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/observations/gen_observation.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/observations/obs_vector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/observations/summary_observation.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/block_observation_data_fetcher.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/data_fetcher.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_block_data_fetcher.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_data_fetcher.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_gen_data_fetcher.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_gen_kw_fetcher.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/observation_data_fetcher.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/observation_gen_data_fetcher.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/pca_fetcher.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot/refcase_data_fetcher.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_data.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_data_vector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_data.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_data_vector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_kw.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_kw_vector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/pca_plot_data.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/pca_plot_vector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_data.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_data_loader.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_vector.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/plot_settings.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/run_arg.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/runpath_list.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/site_config.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/state_map.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/summary_key_matcher.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/summary_key_set.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/util/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/util/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/enkf/util/time_map.py create mode 100644 ThirdParty/Ert/python/python/ert/geo/geo_pointset.py create mode 100644 ThirdParty/Ert/python/python/ert/geo/geo_region.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/driver.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/ert_plugin.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/ert_script.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/ext_job.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/ext_joblist.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/external_ert_script.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/forward_model.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/function_ert_script.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/job.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/job_queue_manager.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/job_status_type_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/queue.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/workflow.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/workflow_job.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/workflow_joblist.py delete mode 100644 ThirdParty/Ert/python/python/ert/job_queue/workflow_runner.py delete mode 100644 ThirdParty/Ert/python/python/ert/rms/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/rms/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/rms/librms.py delete mode 100644 ThirdParty/Ert/python/python/ert/rms/rms.py delete mode 100644 ThirdParty/Ert/python/python/ert/server/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/server/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/server/ertrpcclient.py delete mode 100644 ThirdParty/Ert/python/python/ert/server/ertrpcserver.py delete mode 100644 ThirdParty/Ert/python/python/ert/server/simulation_context.py create mode 100644 ThirdParty/Ert/python/python/ert/test/lint_test_case.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/README.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/about_dialog.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ert_splash.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertnotifier.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertplot.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/activelabel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/analysismoduleselector.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/analysismodulevariablespanel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/caselist.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/caseselector.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/checklist.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/closabledialog.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/customdialog.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/legend.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/listeditbox.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/activerealizationsmodel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/all_cases_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/analysismodulevariablesmodel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/ertmodel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/ertsummary.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/path_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/selectable_list_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/targetcasemodel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/valuemodel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/pathchooser.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/searchbox.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/stringbox.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/summarypanel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/validateddialog.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ertwidgets/validationsupport.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/gert_main.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/completers/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/completers/path_completer.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/highlighter.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keyword.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/advanced_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/analysis_module_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/configuration_line_builder.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/configuration_line_parser.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/configuration_line.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/keyword.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/token.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/validation_status.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/argument_definition.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/bool_argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/configuration_line_definition.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/float_argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/integer_argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/keyword_definition.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/number_list_string_argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/path_argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/percent_argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_format_argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_format_string_argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/range_string_argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/string_argument.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/eclipse_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/enkf_control_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/ensemble_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/ert_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/parametrization_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/plot_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/qc_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/queue_system_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/run_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/simulation_control_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/unix_environment_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/keywords/workflow_keywords.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/parameter.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/wizards/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/wizards/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/wizards/tree_item.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/wizards/tree_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/ide/wizards/wizard_view.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/main_window.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/newconfig.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plot_config.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plot_config_factory.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plot_config_history.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plot_context.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plot_data_gatherer.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plot_limits.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plot_style.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/ccsp.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/distribution.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/ensemble.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/gaussian_kde.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/histogram.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/history.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/observations.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/plot_tools.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/refcase.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/plottery/plots/statistics.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/analysis_module.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/cases.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/custom_kw_keys.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/debug.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/ert_shell_collection.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/ert_shell_context.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/ertshell.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/export.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/gen_data_keys.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/gen_kw_keys.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/libshell/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/libshell/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_collection.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_context.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_function.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_path_tools.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_property.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_tools.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/observations.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/plot_settings.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/plugins.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/results.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/server.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/shell_plot.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/simulations.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/smoother.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/storage.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/summary_keys.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/shell/workflows.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/ensemble_experiment_panel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/ensemble_smoother_panel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/iterated_ensemble_smoother_panel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/models/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/models/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/models/base_run_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/models/ensemble_experiment.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/models/ensemble_smoother.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/models/iterated_ensemble_smoother.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/models/multiple_data_assimilation.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/models/simulations_tracker.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/multiple_data_assimilation_panel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/progress.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/run_dialog.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/simple_progress.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/simulation_config_panel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/simulation/simulation_panel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/export/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/export/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/export/export_keyword_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/export/export_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/export/export_panel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/export/export_tool.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/export/exporter.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/help/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/help/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/help/help_tool.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/help/help_window.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/help_center.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/ide/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/ide/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/ide/configuration_panel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_panel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_tool.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_window.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/load_results/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/load_results/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_panel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_tool.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/case_init_configuration.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/manage_cases_tool.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/color_chooser.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/customization_view.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/customize_plot_dialog.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/default_customization_view.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/limits_customization_view.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/statistics_customization_view.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/style_customization_view.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_keys_list_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_keys_widget.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_proxy_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/filter_popup.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/filterable_kw_list_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_case_model.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_case_selection_widget.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_tool.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_widget.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_window.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/style_chooser.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/clearable_line_edit.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/copy_style_to_dialog.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/custom_date_edit.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plugins/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plugins/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin_handler.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin_runner.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugins_tool.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/plugins/process_job_dialog.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/run_analysis_panel.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/run_analysis_tool.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/tool.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/workflows/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/workflows/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/workflows/run_workflow_widget.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/workflows/workflow_dialog.py delete mode 100644 ThirdParty/Ert/python/python/ert_gui/tools/workflows/workflows_tool.py create mode 100644 ThirdParty/Ert/python/python/test_env.py.in delete mode 100644 ThirdParty/Ert/python/tests/core/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/core/ecl/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/core/ecl/test_deprecation.py delete mode 100644 ThirdParty/Ert/python/tests/core/ecl/test_grid.py delete mode 100644 ThirdParty/Ert/python/tests/core/ecl/test_legacy_ecl.py delete mode 100644 ThirdParty/Ert/python/tests/core/geometry/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/core/geometry/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/core/util/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/core/util/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/core/well/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/core/well/__init__.py rename ThirdParty/Ert/python/tests/{core => }/ecl/CMakeLists.txt (93%) rename ThirdParty/Ert/python/{python/ert_gui/ertwidgets/models => tests/ecl}/__init__.py (100%) create mode 100644 ThirdParty/Ert/python/tests/ecl/test_deprecation.py rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_3dkw.py (84%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_cmp.py (100%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_file.py (80%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_file_statoil.py (98%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_init_file.py (93%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_kw.py (72%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_kw_statoil.py (85%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_restart_file.py (95%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_sum.py (100%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_sum_tstep.py (100%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_sum_vector.py (100%) create mode 100644 ThirdParty/Ert/python/tests/ecl/test_ecl_type.py rename ThirdParty/Ert/python/tests/{core => }/ecl/test_ecl_util.py (100%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_fault_blocks.py (91%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_fault_blocks_statoil.py (94%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_faults.py (95%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_fortio.py (89%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_geertsma.py (83%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_grav.py (79%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_grdecl.py (100%) create mode 100644 ThirdParty/Ert/python/tests/ecl/test_grid.py rename ThirdParty/Ert/python/tests/{core => }/ecl/test_grid_statoil.py (93%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_indexed_read.py (87%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_kw_function.py (92%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_layer.py (99%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_npv.py (100%) create mode 100644 ThirdParty/Ert/python/tests/ecl/test_region.py rename ThirdParty/Ert/python/tests/{core/ecl/test_region.py => ecl/test_region_statoil.py} (91%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_removed.py (87%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_restart.py (97%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_rft.py (83%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_rft_cell.py (91%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_rft_statoil.py (99%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_statoil_faults.py (97%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_sum.py (100%) rename ThirdParty/Ert/python/tests/{core => }/ecl/test_sum_statoil.py (96%) delete mode 100644 ThirdParty/Ert/python/tests/ert/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/analysis/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/analysis/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/analysis/test_analysis_module.py delete mode 100644 ThirdParty/Ert/python/tests/ert/analysis/test_linalg.py delete mode 100644 ThirdParty/Ert/python/tests/ert/analysis/test_options_enum.py delete mode 100644 ThirdParty/Ert/python/tests/ert/analysis/test_rml.py delete mode 100644 ThirdParty/Ert/python/tests/ert/analysis/test_std_enkf.py delete mode 100644 ThirdParty/Ert/python/tests/ert/analysis/test_std_enkf_debug.py delete mode 100644 ThirdParty/Ert/python/tests/ert/config/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/config/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/config/test_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/data/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/data/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/data/test_custom_kw.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/data/test_custom_kw_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/data/test_field_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_data.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_data_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_kw.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_kw_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/test_arg_loader.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/test_custom_kw_collector.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/test_design_matrix.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/test_export_join.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_data_collector.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_data_observation_collector.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_kw_collector.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/test_misfit_collector.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/test_numpy_and_pandas.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/test_summary_collector.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/export/test_summary_observation_collector.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/plot/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/plot/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/plot/test_plot_data.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/plot/test_plot_settings.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_active_list.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_analysis_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_analysis_iter_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_block_obs.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_custom_kw_config_set.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_deprecation.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_ecl_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_enkf.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs_manager1.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs_manager2.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_enkf_library.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_enkf_load_results_manually.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_enkf_obs.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_ensemble_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_ert_context.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_ert_log.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_es_update.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_field_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_field_export.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_forward_load_context.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_gen_obs.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_hook_workflow.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_labscale.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_linalg.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_local_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_local_obsdata_node.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_meas_block.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_meas_data.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_obs_block.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_obs_data.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_runpath_list.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_state_map.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_summary_key_matcher.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_summary_key_set.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_summary_obs.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_time_map.py delete mode 100644 ThirdParty/Ert/python/tests/ert/enkf/test_update.py delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/test_ert_plugin.py delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/test_ert_script.py delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/test_ext_job.py delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/test_function_ert_script.py delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/test_job_queue.py delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/test_workflow.py delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_job.py delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_joblist.py delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_runner.py delete mode 100644 ThirdParty/Ert/python/tests/ert/job_queue/workflow_common.py delete mode 100644 ThirdParty/Ert/python/tests/ert/run/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/run/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/run/test_run.py delete mode 100644 ThirdParty/Ert/python/tests/ert/sched/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/sched/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/sched/test_sched.py delete mode 100644 ThirdParty/Ert/python/tests/ert/server/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/server/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/server/test_rpc_service.py delete mode 100644 ThirdParty/Ert/python/tests/ert/server/test_rpc_storage.py delete mode 100644 ThirdParty/Ert/python/tests/ert/server/test_simulation_context.py delete mode 100644 ThirdParty/Ert/python/tests/ert/testcase/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ert/testcase/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/ert/testcase/test_mini_config.py delete mode 100644 ThirdParty/Ert/python/tests/ert/testcase/test_testcase.py create mode 100644 ThirdParty/Ert/python/tests/geometry/CMakeLists.txt rename ThirdParty/Ert/python/{python/ert_gui/ide => tests/geometry}/__init__.py (100%) rename ThirdParty/Ert/python/tests/{core => }/geometry/test_convex_hull.py (100%) rename ThirdParty/Ert/python/tests/{core => }/geometry/test_cpolyline.py (100%) rename ThirdParty/Ert/python/tests/{core => }/geometry/test_cpolyline_collection.py (100%) create mode 100644 ThirdParty/Ert/python/tests/geometry/test_geo_pointset.py create mode 100644 ThirdParty/Ert/python/tests/geometry/test_geo_region.py rename ThirdParty/Ert/python/tests/{core => }/geometry/test_geometry_tools.py (100%) rename ThirdParty/Ert/python/tests/{core => }/geometry/test_intersection.py (100%) rename ThirdParty/Ert/python/tests/{core => }/geometry/test_point_in_polygon.py (100%) rename ThirdParty/Ert/python/tests/{core => }/geometry/test_polygon_slicing.py (100%) rename ThirdParty/Ert/python/tests/{core => }/geometry/test_polyline.py (100%) rename ThirdParty/Ert/python/tests/{core => }/geometry/test_surface.py (92%) delete mode 100644 ThirdParty/Ert/python/tests/gui/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/gui/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/ert_shell_test_context.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_analysis.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_context.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_observations.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_plot_settings.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_server.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_smoother.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/test_shell_collection.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/test_shell_function.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ertshell/test_shell_property.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_bool_argument.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_configuration_line.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_builder.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_definition.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_parser.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_ert_keywords.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_float_argument.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_integer_argument.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_path_argument.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_percent_argument.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_proper_name_argument.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_proper_name_format_argument.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_proper_name_format_string_argument.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_range_string_argument.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/test_tokens.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/wizards/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/wizards/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/gui/ide/wizards/test_tree_structure.py delete mode 100644 ThirdParty/Ert/python/tests/gui/plottery/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/gui/plottery/__init__.py delete mode 100644 ThirdParty/Ert/python/tests/gui/plottery/test_plot_config_history.py delete mode 100644 ThirdParty/Ert/python/tests/gui/plottery/test_plot_limits.py delete mode 100644 ThirdParty/Ert/python/tests/gui/plottery/test_plot_style.py delete mode 100644 ThirdParty/Ert/python/tests/gui/test_multiple_data_assimilation.py rename ThirdParty/Ert/python/{python/ert/enkf/config/field_type_enum.py => tests/test_pylint.py} (50%) create mode 100644 ThirdParty/Ert/python/tests/util/CMakeLists.txt rename ThirdParty/Ert/python/{python/ert_gui/ide/completers => tests/util}/__init__.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_arg_pack.py (95%) rename ThirdParty/Ert/python/tests/{core => }/util/test_cstring.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_cthread_pool.py (97%) rename ThirdParty/Ert/python/tests/{core => }/util/test_ctime.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_hash.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_lookup_table.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_matrix.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_path_context.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_rng.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_spawn.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_stat.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_string_list.py (95%) rename ThirdParty/Ert/python/tests/{core => }/util/test_substitution_list.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_thread_pool.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_ui_return.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_vectors.py (100%) rename ThirdParty/Ert/python/tests/{core => }/util/test_version.py (86%) rename ThirdParty/Ert/python/tests/{core => }/util/test_work_area.py (100%) create mode 100644 ThirdParty/Ert/python/tests/well/CMakeLists.txt rename ThirdParty/Ert/python/tests/{core => well}/__init__.py (100%) rename ThirdParty/Ert/python/tests/{core => }/well/test_ecl_well.py (100%) rename ThirdParty/Ert/python/tests/{core => }/well/test_ecl_well2.py (100%) rename ThirdParty/Ert/python/tests/{core => }/well/test_ecl_well3.py (100%) create mode 100644 ThirdParty/Ert/script/download-pr delete mode 100644 ThirdParty/Ert/script/job_dispatch.py delete mode 100644 ThirdParty/Ert/share/gui/doc/documentation.txt delete mode 100644 ThirdParty/Ert/share/gui/doc/info.txt delete mode 100644 ThirdParty/Ert/share/gui/doc/initializers delete mode 100644 ThirdParty/Ert/share/gui/doc/run_info delete mode 100644 ThirdParty/Ert/share/gui/doc/tmp_info.txt delete mode 100644 ThirdParty/Ert/share/gui/help/config/analysis/analysis_module.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/analysis/iterated_analysis_module.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/init/history_length.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/add_fixed_length_schedule_kw.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/add_static_kw.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/analysis_copy.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/analysis_enkf_update.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/analysis_load.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/analysis_select.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/analysis_set_var.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/analysis_update.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/case_table.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/config_help.py delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/create_case.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/data_file.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/data_kw.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/data_ranking.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/define.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/delete_runpath.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/eclbase.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/end_date.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_alpha.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_bootstrap.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_cv_folds.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_force_ncomp.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_local_cv.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_merge_observations.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_mode.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_ncomp.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_pen_press.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_rerun.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_scaling.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enkf_truncation.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/ensemble_run.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/enspath.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/export_field.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/export_field_ecl_grdecl.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/export_field_rms_roff.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/export_ranking.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/field.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/forward_model.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/gen_data.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/gen_kw.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/gen_param.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/grid.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/history_source.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/image_type.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/image_viewer.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/init_case_from_existing.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/init_misfit_table.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/init_section.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/install_job.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/job_script.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/jobname.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/keywords.txt delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/license_path.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/load_results.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/load_results_iter.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/local_config.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/log_file.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/log_level.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/lsf_queue.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/lsf_resources.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/lsf_server.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/max_resample.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/max_running_local.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/max_running_lsf.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/max_running_rsh.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/max_runtime.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/max_submit.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/min_realizations.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/num_realizations.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/obs_config.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/observation_ranking.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/plot_driver.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/plot_errorbar.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/plot_errorbar_max.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/plot_height.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/plot_path.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/plot_refcase.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/plot_width.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/pre_clear_runpath.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/qc_path.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/qc_workflow.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/queue_system.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/refcase.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/refcase_list.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/rerun_start.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/result_path.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/rft_config.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/rftpath.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/rsh_command.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/rsh_host.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/run_smoother.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/run_smoother_with_iter.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/run_template.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/runpath.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/runpath_file.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/schedule_file.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/schedule_prediction_file.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/select_case.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/setenv.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/stop_long_running.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/summary.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/surface.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/update_log_path.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/keywords/update_path.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/run/runpath.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/simulation/active_realizations.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/simulation/analysis_module.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/simulation/iterated_target_case_format.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/simulation/iteration_weights.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/simulation/number_of_iterations.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_parameter_constant_value.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_parameter_is_included.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_target_case_format.html delete mode 100644 ThirdParty/Ert/share/gui/help/config/simulation/target_case.html delete mode 100644 ThirdParty/Ert/share/gui/help/init/case_list.html delete mode 100644 ThirdParty/Ert/share/gui/help/init/current_case_selection.html delete mode 100644 ThirdParty/Ert/share/gui/help/init/initialize_from_existing.html delete mode 100644 ThirdParty/Ert/share/gui/help/init/initialize_from_scratch.html delete mode 100644 ThirdParty/Ert/share/gui/help/init/select_case_for_info.html delete mode 100644 ThirdParty/Ert/share/gui/help/init/select_members.html delete mode 100644 ThirdParty/Ert/share/gui/help/init/select_parameters.html delete mode 100644 ThirdParty/Ert/share/gui/help/init/selected_case_info.html delete mode 100644 ThirdParty/Ert/share/gui/help/init/source_case.html delete mode 100644 ThirdParty/Ert/share/gui/help/run/simulation_mode.html delete mode 100644 ThirdParty/Ert/share/gui/help/run/start_simulation.html delete mode 100644 ThirdParty/Ert/share/gui/help/run/workflow.html delete mode 100644 ThirdParty/Ert/share/gui/help/template.html delete mode 100644 ThirdParty/Ert/share/gui/help/tools/export.html delete mode 100644 ThirdParty/Ert/share/gui/help/tools/help.html delete mode 100644 ThirdParty/Ert/share/gui/help/tools/ide.html delete mode 100644 ThirdParty/Ert/share/gui/help/tools/manage_cases.html delete mode 100644 ThirdParty/Ert/share/gui/help/tools/plot.html delete mode 100644 ThirdParty/Ert/share/gui/help/tools/workflows.html delete mode 100644 ThirdParty/Ert/share/gui/help/welcome_to_ert.html delete mode 100644 ThirdParty/Ert/share/gui/img/add.png delete mode 100644 ThirdParty/Ert/share/gui/img/application/window_icon.png delete mode 100644 ThirdParty/Ert/share/gui/img/application/window_icon_cutout.png delete mode 100644 ThirdParty/Ert/share/gui/img/calendar.png delete mode 100644 ThirdParty/Ert/share/gui/img/checked.png delete mode 100644 ThirdParty/Ert/share/gui/img/copy_from.png delete mode 100644 ThirdParty/Ert/share/gui/img/copy_to.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/chart_curve_add.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/cog.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/cog_edit.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/control_play_blue.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/database_gear.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/disk.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/gear_in_play.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/help.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/loading.gif delete mode 100644 ThirdParty/Ert/share/gui/img/ide/plugin.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/readme-fatcow.txt delete mode 100644 ThirdParty/Ert/share/gui/img/ide/save_as.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/small/add.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/small/chart_curve_go.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/small/cog_edit.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/small/delete.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/small/folder.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/table_export.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/table_import.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/to_do_list_checked_1.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/transform_scale.png delete mode 100644 ThirdParty/Ert/share/gui/img/ide/widgets.png delete mode 100644 ThirdParty/Ert/share/gui/img/notchecked.png delete mode 100644 ThirdParty/Ert/share/gui/img/page_copy.png delete mode 100644 ThirdParty/Ert/share/gui/img/redo.png delete mode 100644 ThirdParty/Ert/share/gui/img/remove.png delete mode 100644 ThirdParty/Ert/share/gui/img/remove_favorite.png delete mode 100644 ThirdParty/Ert/share/gui/img/splash.jpg delete mode 100644 ThirdParty/Ert/share/gui/img/undo.png delete mode 100644 ThirdParty/Ert/share/gui/img/update.png delete mode 100644 ThirdParty/Ert/share/lib/synthesizer/__init__.py delete mode 100644 ThirdParty/Ert/share/lib/synthesizer/oil_simulator.py delete mode 100644 ThirdParty/Ert/share/lib/synthesizer/perlin.py delete mode 100644 ThirdParty/Ert/share/lib/synthesizer/prime_generator.py delete mode 100644 ThirdParty/Ert/share/lib/synthesizer/shaped_perlin.py delete mode 100644 ThirdParty/Ert/share/site-config delete mode 100644 ThirdParty/Ert/share/viewer/shaders/default.fp delete mode 100644 ThirdParty/Ert/share/viewer/shaders/default.vp delete mode 100644 ThirdParty/Ert/share/viewer/shaders/texturing.fp delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/config/CREATE_CASE delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/config/CSV_EXPORT delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/config/EXPORT_MISFIT_DATA delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/config/GEN_DATA_RFT_CSV_EXPORT delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/config/INIT_CASE_FROM_EXISTING delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/config/SELECT_CASE delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/config/UPDATE_RUNPATH_LIST delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/create_case.py delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/csv_export.py delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/export_misfit_data.py delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/init_case_from_existing.py delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/select_case.py delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/update_runpath_list.py delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-tui/config/CREATE_CASE delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-tui/config/INIT_CASE_FROM_EXISTING delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-tui/config/PLOT_ALL_SUMMARY delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal-tui/config/SELECT_CASE delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/ANALYSIS_SELECT_MODULE delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/ANALYSIS_UPDATE delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/DATA_RANKING delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/ENSEMBLE_RUN delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/EXIT_ERT delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD_ECL_GRDECL delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD_RMS_ROFF delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_RANKING delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_RUNPATH delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/INIT_MISFIT_TABLE delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/LOAD_RESULTS delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/LOAD_RESULTS_ITER delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/OBSERVATION_RANKING delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_ITERATED_SMOOTHER delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_SMOOTHER delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_SMOOTHER_WITH_ITER delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/SCALE_STD delete mode 100644 ThirdParty/Ert/share/workflows/jobs/internal/config/STD_SCALE_CORRELATED_OBS delete mode 100644 ThirdParty/Ert/test-data/local/config/gen_data/REFCASE.SMSPEC delete mode 100644 ThirdParty/Ert/test-data/local/config/gen_data/REFCASE.UNSMRY delete mode 100644 ThirdParty/Ert/test-data/local/config/gen_data/config delete mode 100644 ThirdParty/Ert/test-data/local/config/gen_data/gen_obs_data delete mode 100644 ThirdParty/Ert/test-data/local/config/gen_data/observations delete mode 100644 ThirdParty/Ert/test-data/local/config/simple_config delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_1 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_2 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_3 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/Observations/observations delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/Parameters/PERLIN_PARAMS.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/RandomSeed delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/Refcase/CASE.EGRID delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/Template/PERLIN_TEMPLATE delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_fail.status delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/realization.ok delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_fail.status delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/realization.ok delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/ERROR delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/EXIT delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_fail.status delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/ERROR delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/EXIT delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_fail.status delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_fail.status delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/realization.ok delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/ERROR delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/EXIT delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_fail.status delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_fail.status delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/realization.ok delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/ERROR delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/EXIT delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_fail.status delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_fail.status delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/realization.ok delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_fail.status delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/realization.ok delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/current_case delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/0001/files/PERLIN_active delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/0002/files/PERLIN_active delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/0003/files/PERLIN_active delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_10/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_11/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_12/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_13/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_14/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_15/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_16/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_17/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_18/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_19/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_2/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_20/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_21/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_22/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_23/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_24/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_25/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_26/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_27/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_28/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_29/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_30/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_31/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_5/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Index/INDEX.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Index/INDEX.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Index/INDEX.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/ert_fstab delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/files/case_config delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/files/custom_kw_config_set delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/files/state-map delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/files/summary-key-set delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/jobs/AGGREGATOR delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/jobs/PERLIN delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/jobs/PERLIN_FAIL delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/jobs/REALIZATION_FAIL delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/jobs/aggregator.py delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/jobs/perlin.py delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/jobs/perlin_fail.py delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/jobs/realization_fail.py delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/mini_config delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/mini_fail_config delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/STATUS delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/jobs.py delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/OK delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/aggregated.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/aggregator.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/aggregator.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin.stderr delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin.stdout delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_1.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_2.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_3.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/current_case delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/0001/files/PERLIN_active delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/0002/files/PERLIN_active delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/0003/files/PERLIN_active delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_10/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_11/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_12/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_13/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_14/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_15/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_16/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_17/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_18/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_19/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_20/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_21/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_22/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_23/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_24/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_25/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_26/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_27/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_28/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_29/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_30/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_31/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Index/INDEX.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Index/INDEX.index delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Index/INDEX.mnt delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/ert_fstab delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/files/case_config delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/files/custom_kw_config_set delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/files/state-map delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/files/summary-key-set delete mode 100644 ThirdParty/Ert/test-data/local/custom_kw/time_map delete mode 100644 ThirdParty/Ert/test-data/local/resopt/config/simple/config delete mode 100644 ThirdParty/Ert/test-data/local/run/config.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/SEED delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/jobs/SNAKE_OIL_DIFF delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/jobs/SNAKE_OIL_NPV delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/jobs/SNAKE_OIL_SIMULATOR delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/jobs/snake_oil_diff.py delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/jobs/snake_oil_npv.py delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/jobs/snake_oil_simulator.py delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/observations/observations.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/observations/wpr_diff_obs.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/parameters/snake_oil_parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/refcase/SNAKE_OIL_FIELD.SMSPEC delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/refcase/SNAKE_OIL_FIELD.UNSMRY delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/refcase/refcase_readme.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/refcase/seed.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/refcase/snake_oil_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/refcase/time_map.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/snake_oil.ert delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/current_case delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/0199/files/SNAKE_OIL_GPR_DIFF_active delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/0199/files/SNAKE_OIL_OPR_DIFF_active delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/0199/files/SNAKE_OIL_WPR_DIFF_active delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_25/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_26/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_27/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_28/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_29/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_30/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_31/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Index/INDEX.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Index/INDEX.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Index/INDEX.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/ert_fstab delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/files/case_config delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/files/custom_kw_config_set delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/files/state-map delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/files/summary-key-set delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/files/time-map delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_10/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_11/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_25/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_26/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_27/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_28/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_29/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_30/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_31/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/ANALYZED.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/ANALYZED.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/ANALYZED.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/FORECAST.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/FORECAST.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/FORECAST.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/PARAMETER.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/PARAMETER.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/PARAMETER.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/STATIC.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/STATIC.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/STATIC.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Index/INDEX.data_0 delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Index/INDEX.index delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Index/INDEX.mnt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/ert_fstab delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/files/case_config delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/files/custom_kw_config_set delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/files/state-map delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/files/summary-key-set delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/files/time-map delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/templates/seed_template.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil/templates/snake_oil_template.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/SEED delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx0.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx1.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx2.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx3.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx4.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx5.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx6.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx7.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx8.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx9.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro0.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro1.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro2.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro3.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro4.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro5.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro6.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro7.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro8.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro9.grdecl delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/grid/CASE.EGRID delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_DIFF delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_NPV delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_SIMULATOR delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_diff.py delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_npv.py delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_simulator.py delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/make_data.py delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/observations/observations.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/observations/wpr_diff_obs.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/parameters/snake_oil_parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/refcase/SNAKE_OIL_FIELD.SMSPEC delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/refcase/SNAKE_OIL_FIELD.UNSMRY delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/refcase/refcase_readme.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/refcase/seed.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/refcase/snake_oil_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/refcase/time_map.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/snake_oil.ert delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/templates/seed_template.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_field/templates/snake_oil_template.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/SEED delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_DIFF delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_NPV delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_SIMULATOR delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_diff.py delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_npv.py delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_simulator.py delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/observations/observations.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/observations/wpr_diff_obs.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/parameters/snake_oil_parameters.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/SNAKE_OIL_FIELD.SMSPEC delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/SNAKE_OIL_FIELD.UNSMRY delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/refcase_readme.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/seed.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/snake_oil_params.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/time_map.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/snake_oil.ert delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/snake_oil_GEO_ID.ert delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/templates/seed_template.txt delete mode 100644 ThirdParty/Ert/test-data/local/snake_oil_no_data/templates/snake_oil_template.txt diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 3d40216e55..aa44761c48 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -7,8 +7,8 @@ set(RESINSIGHT_INCREMENT_VERSION "flow.13") # https://github.com/CRAVA/crava/tree/master/libs/nrlib set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") -# https://github.com/Ensembles/ert -set(ERT_GITHUB_SHA "e2a5a9cc20705537d07822958d925e092a323367") +# https://github.com/Statoil/libecl +set(ERT_GITHUB_SHA "f39d2e7fd196350ab1db86bb1bd5a3faca72d75d") # https://github.com/OPM/opm-flowdiagnostics set(OPM_FLOWDIAGNOSTICS_SHA "a14dc4ba1302bcc1e0aeb35c5de6b4bd39bce98") diff --git a/ThirdParty/Ert/.travis.yml b/ThirdParty/Ert/.travis.yml index a9693afcdb..81671386ce 100644 --- a/ThirdParty/Ert/.travis.yml +++ b/ThirdParty/Ert/.travis.yml @@ -1,65 +1,38 @@ +dist: trusty +sudo: false language: c -matrix: - fast_finish: true - allow_failures: - - os: osx - include: - - os: osx - osx_image: xcode7.3 - compiler: clang - - os: linux - compiler: gcc - addons: apt: sources: - - ubuntu-toolchain-r-test + - ubuntu-toolchain-r-test packages: - - liblapack-dev - - valgrind - - gcc-4.8 - - g++-4.8 - - clang - -install: - - if [[ "$CC" == "gcc" ]]; then export CXX="g++-4.8"; fi - - - export TRAVIS_PYTHON_VERSION="2.7" - # We do this conditionally because it saves us some downloading if the version is the same. - - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - wget https://repo.continuum.io/miniconda/Miniconda-latest-MacOSX-x86_64.sh -O miniconda.sh; - else - wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh; - fi - else - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - wget https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda.sh; - else - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; - fi - fi - - - bash miniconda.sh -b -p $HOME/miniconda - - export CONDA_HOME="$HOME/miniconda" - - export PATH="$CONDA_HOME/bin:$PATH" - - hash -r - - conda config --set always_yes yes --set changeps1 no - - conda update -q conda - # Useful for debugging any issues with conda - - conda info -a - - conda install pyqt=4 scipy=0.16.1 numpy pandas matplotlib + - liblapack-dev + - valgrind + - gcc-4.8 + - g++-4.8 env: global: - - ERT_SHOW_BACKTRACE=1 + - ERT_SHOW_BACKTRACE=1 + +install: +- if [[ "$CC" == "gcc" ]]; then export CXX="g++-4.8"; fi +- wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh +- bash miniconda.sh -b -p $HOME/miniconda +- export CONDA_HOME="$HOME/miniconda" +- export PATH="$CONDA_HOME/bin:$PATH" +- hash -r +- conda config --set always_yes yes --set changeps1 no +- conda update -q conda +- conda info -a # Useful for debugging any issues with conda +- conda install pylint numpy pandas before_script: - - mkdir build - - cd build - - cmake -DBUILD_ERT=ON -DERT_BUILD_GUI=ON -DBUILD_TESTS=ON -DBUILD_APPLICATIONS=ON -DBUILD_PYTHON=ON -DERT_USE_OPENMP=ON -DERT_DOC=OFF -DERT_BUILD_CXX=ON .. +- mkdir build +- cd build +- cmake -DBUILD_TESTS=ON -DBUILD_PYTHON=ON -DERT_BUILD_CXX=ON -DBUILD_APPLICATIONS=ON .. script: - - make - - ctest --output-on-failure +- make +- ctest --output-on-failure -E ert_util_ping diff --git a/ThirdParty/Ert/CMakeLists.txt b/ThirdParty/Ert/CMakeLists.txt index 0e213519f9..af90f27865 100644 --- a/ThirdParty/Ert/CMakeLists.txt +++ b/ThirdParty/Ert/CMakeLists.txt @@ -8,7 +8,7 @@ endif() #----------------------------------------------------------------- set( ERT_VERSION_MAJOR 2 ) # Remember to update release notes whenever -set( ERT_VERSION_MINOR 1 ) # you change the ERT_VERSION_MINOR or MAJOR +set( ERT_VERSION_MINOR 2 ) # you change the ERT_VERSION_MINOR or MAJOR set( ERT_VERSION_MICRO git ) # with "new in Ert Version X.X.X"! # If the micro version is not integer, that should be interpreted as a @@ -16,14 +16,12 @@ set( ERT_VERSION_MICRO git ) # with "new in Ert Version X.X.X"! #----------------------------------------------------------------- -option( BUILD_ERT "Build the full ERT application - Linux only" OFF) option( BUILD_TESTS "Should the tests be built" OFF) option( BUILD_APPLICATIONS "Should we build small utility applications" OFF) option( BUILD_ECL_SUMMARY "Build the commandline application ecl_summary" OFF) option( BUILD_PYTHON "Run py_compile on the python wrappers" ON ) option( BUILD_SHARED_LIBS "Build shared libraries" ON ) option( INSTALL_ERT "Should anything be installed when issuing make install?" ON ) -option( ERT_BUILD_GUI "Should the PyQt based GUI be compiled and installed" OFF) option( ERT_USE_OPENMP "Use OpenMP" OFF ) option( ERT_DOC "Build ERT documantation" OFF) option( ERT_BUILD_CXX "Build some CXX wrappers" ON) @@ -182,38 +180,6 @@ include_directories( ${PROJECT_SOURCE_DIR}/libecl_well/include ) add_subdirectory( libecl_well ) -#----------------------------------------------------------------- -if (BUILD_ERT) -#----------------------------------------------------------------- - if (BUILD_TESTS) - option( ERT_LSF_SUBMIT_TEST "Build and run tests of LSF submit" OFF) - endif() - add_subdirectory( bin ) - - include(cmake/ert_module_name.cmake) - - include_directories( ${PROJECT_SOURCE_DIR}/libconfig/include ) - add_subdirectory( libconfig ) - - include_directories( ${PROJECT_SOURCE_DIR}/libsched/include ) - add_subdirectory( libsched ) - - include_directories( ${PROJECT_SOURCE_DIR}/librms/include ) - add_subdirectory( librms ) - - include_directories( ${PROJECT_SOURCE_DIR}/libanalysis/include ) - add_subdirectory( libanalysis ) - - include_directories( ${PROJECT_SOURCE_DIR}/libjob_queue/include ) - add_subdirectory( libjob_queue ) - - include_directories( ${PROJECT_SOURCE_DIR}/libenkf/include ) - add_subdirectory( libenkf ) - - install(DIRECTORY ${PROJECT_SOURCE_DIR}/share DESTINATION ${CMAKE_INSTALL_PREFIX}) -endif() - - if (BUILD_PYTHON) if (ERT_WINDOWS) message(STATUS "Python is not supported on Windows") diff --git a/ThirdParty/Ert/README b/ThirdParty/Ert/README deleted file mode 100644 index dcae8cff53..0000000000 --- a/ThirdParty/Ert/README +++ /dev/null @@ -1,341 +0,0 @@ -Coming from OPM?? ------------------ - -ERT is a package for handling an ensemble of reservoir models, an -important part of that is beeing able to read and write the files from -standard reservoir applications; ert has quite extensive support for -reading and writing the result files from the ECLIPSE reservoir -simulator. The capabilities to read and write ECLIPSE result files is -used by the OPM simulator codes. - -The ERT build system has many configuration options, but when -compiling for OPM you should be able to use the all defaults route: - - git clone https://github.com/Ensembles/ert.git - cd ert - mkdir build - cd build - cmake .. - make - -The OPM build system can find an ERT distribution in the sibling -location, i.e. if you have cloned ert beside the opm modules like: - - ert/ - opm-common/ - opm-parser/ - opm-material/ - .... - -The opm build system will find the ert distribution in-place, -otherwise you should install ert with 'make install' and the normal -cmake machinery of the opm build system should find it. - - ------------------------------------------------------------------------- - - _________________________________ - / \ - | ______ ______ _______ | - | | ____| | __ \ |__ __| | - | | |__ | |__) | | | | - | | __| | _ / | | | - | | |____ | | \ \ | | | - | |______| |_| \_\ |_| | - | | - | Ensemble based Reservoir Tool | - \_________________________________/ - - ------------------------------------------------------------------------- - - 1. ERT - 2. ECLIPSE utilities. - 3. Building ERT - 3.1 CMake settings you might want to adjust - 4. The code: - 4.1 The different libraries - 4.2 The general structure - 4.3 Python wrappers - 5. Tests - ------------------------------------------------------------------------- - -1. ERT - -ERT - Ensemble based Reservoir Tool is a tool for managing an ensemble -of reservoir models. The initial motivation for creating ERT was a as -tool to do assisted history matching with the Ensemble Kalman Filter -(EnKF). Very briefly, the process of using EnKF for history matching -can be summarized as: - - 1. Sample initial reservoir parameters from a (Gaussian) initial - distribution. - - 2. Simulate the ensemble of of reservoir forward in time through a - part of the historical period for which data is available. - - 3. Load the results, compare with the observed data, update the - parameters and the state of reservoir by filtering out the most - inacurate results, and restart the forward simulations. - -This recipe is quite complex technically, and in particular involves -the ability to read and write input and output files from the -reservoir simulator (i.e. ECLIPSE in the case of ERT), run simulations -with arbitrary external programs, plotting data and so on. This -implies that a quite significant technical machinery must be in place -before the EnKF algorithm as such can be utilizied. This in particular -applies to real industry reservoir models, where typically -imperfections of all kinds flourish. - -Despite the fact that the initial motivation for creating ERT was to -be able to use the EnKF algorithm for history matching, ERT is -currently more used with the Ensemble Smoother and also purely as a -workflow manager, i.e. herding a large collection of reservoir models -through the required simulations steps. - - -2. ECLIPSE Utilities - -ERT has a quite large amount of code devoted to reading and writing -the ECLIPSE output files (grid/rft/restart/init/summary). In addition, -there is also reasonable support for reading and writing the grdecl -input files, but there is no general .DATA file parser. The ability to -read and write ECLIPSE output files is valuable in many reservoir -applications, and it is possible to only build and use the libecl -(with support libraries) library for working with ECLIPSE files. In -fact, the default build setup is to only build the ECLIPSE related -library and utilities. This part of the ERT distribution can also be -built on Windows with Visual Studio (albeit with maaaany warnings) and -with MinGW. - - -3. Building ERT - -CMake is the build system for ERT. The top level CMakeLists.txt file -is located in the top level directory of the repository, and this -CMakeLists.txt file includes individual CMakeLists.txt files for the -different libraries. - -Building with CMake is performed like this: - - 1. Create a build directory, this can in principle be anywhere in - the filesystem. One level above the toplevel source directory is - a practical choice. - - 2. Go to the build directory and invoke the command: - - ccmake - - Go through several 'configure' steps with CMake and generate - native build files. - - 3. Exit ccmake and invoke the native build system, i.e. ordinarily - 'make' on Linux. - - 4. Subsequent builds can be performed using just the native make - command, as in step 3. - -3.1 CMake settings you might want to adjust - -The main setting you should adjust is BUILD_ERT which is default to -OFF, i.e. by default only the ECLIPSE related utilities will be -built. The build system has numerous configurations checks; the -ECLIPSE utilities should build on Windows, but to build all of ERT you -will need a Linux (Posix) system. - - -4. The code - -The code is mainly a collection of libraries written in C. - -4.1 The different libraries - -The provided libraries are: - - libert_util: This library is a collection of utilities of various - sorts; if C++ had been chosen as implementation language, most of - these utilities could probably be replaced by standard C++ classes. - - libgeometry: This is a very small geometry library; the main code - is a small implementantion of an alorithm to determine whether a - point is inside a polyhedron. The ECLIPSE library has some - geometry related code which should be moved here. - - libwell: This library will load well information from an ECLIPSE - restart file. This is mainly for the purpose of visualization - of the existing wells, and can not be used to update or model - the well configuration. - - libecl: This library will read and (partly) write the various - binary ECLIPSE files, including GRID/EGRID, summary, INIT, - restart and RFT files. There is also support for reading an - writing grdecl formatted files, but there is no support for - general parsing of the ECLIPSE input format. - - ---------------------------------------------------------------------------- - - librms: This is a library for reading and writing RMS Roff - files. It turns out that ECLIPSE file formats is by far the most - common external file format for RMS and that the ROFF support is - not essential for this reason. - - libconfig: This library implements a parser for the ERT config file - format, this format is used in the main ERT configuration file, - and also in several small special-purpose configuration files used - by ERT. The config format parsed by this library was inspired by - the ECLIPSE format, in retrospect that was a mistake - it should - have been based on a standard format like xml. - - To confuse things even further, the libconfig library implements - /two/ formats for configuration files -- the 'second format' is - implemented in the file conf.c, and only used as format for the - observations in ERT. - - libplot: A *very* simple library for creating plots which only - satisfies the needs of ERT. - - libanalysis: The EnKF algorithm is implemented in this library. - - libjob_queue: This library implements a system to manage and run - simulations in the form of external programs. The library has a - queue manager, and a system with drivers which communicate with - the underlying system. Currently, the library has a LSF driver - to work with LSF, a LOCAL driver which starts simulations on the - current workstation and a RSH driver which submits jobs to a - 'cluster' of workstation using ssh. - - libenkf: This is the main functionality which is ERT specific; this - library is too large. - - -4.2 General structure - -The code is written in C, but conventions give a 'scent of object -orientation'. Most of the code is uses the following conventions: - - - Every file 'xxx' implements a data type 'xxx_type' - this naming - convention is quite strong. - - - All the structure definitions are in the source files, - i.e. external scopes must access the data of a structure - through accessor functions. - - - All functions which operate on a type 'xxx_type' take a pointer - to xxx_type as their first argument, the structure closely - resemble the 'self' argument used when implementing Python - classes. - - - Memory management is manual; however there are some conventions: - * Functions allocating storage have _alloc_ as part of the name. - * For all functions xxx_alloc() which allocate memory, there - should be a matching xxx_free() function to discard the objects. - * Containers can optionally destroy their content if the content - is installed with a destructor. - - - In libert_util/src/type_macros.h there is a macro based - 'type-system' which is used to runtime check casts of (void *). - - -4.3 Python wrappers - -Some of the code, in particular the ECLIPSE related functionality, has -been wrapped for usage in Python. Using these wrappers, it is quite -easy work with ECLIPSE files. The python wrappers are quite well -documented both in the directory python/docs and in the Python classes -themselves. - - -5. Tests - -The ERT codebase has a small but increasing test coverage. The tests -are typically located in a per-library subdirectory tests/. The test -framework is based on ctest which basically works like this: - - 1. In the CMakeLists.txt file testing is enabled with - ENABLE_TESTING(). - - 2. Tests are added with: - - add_test( test_name test_executable arg1 arg2 arg3 ... ) - - If the executable exits with status 0 the test has passed, - otherwise it has failed. The executable run by the test can - typically be an executable built as part of the solution, but can - in principle be an arbitrary executable like a dedicated test - runner or e.g. the Python interpreter. - -5.1 Testing of C code - -The main part of the testing infrastructure are small C applications -which are added like this: - - add_executable( test_exe test_source.c ) - target_link_libraries( test_exe lib ) - add_test( test_name ${EXECUTABLE_OUTPUT_PATH}/test_exe commandline_arg1 commandline_arg2 ) - -Where the first two lines create the test executable in the normal -way, and the last line adds it as a test. - -5.2 Testing of Python Code - -In python/test there are several files with Python tests, these files -are executable files and they are invoked directly from the command -line. A limited number of the tests have been integrated in the ctest -system. - -5.3 Test names - -The tests in the cmake build system follow the naming convention of -the library regarding the functionality which they are testing: For -example, all tests for the libecl library use a name starting with -'ecl' and all tests for the tests for the config library are prefixed -by 'config'. The ctest options -R and -E can be used to include and -exclude tests based on their name - - ctest -R ecl # Run all tests containing the regular expression 'ecl' - ctest -E ecl # Run all tests NOT containing the regular expression 'ecl' - - -5.4 Test labels - -Using the cmake set_property() function it is possible to assign -labels to the test, and the -L and -LE options to ctest can be used to -limit which tests to run. A test can only have one label; in the -current ctest setup different labels are combined into one composite -label with a ":" separator, e.g. - - set_property( TEST test_xxx PROPERTY LABELS StatoilData:Python) - -will set the 'StatoilData' and 'Python' properties on test_xxx. The -labels currently available in the ERT test setup are: - - StatoilData: This implies that the test makes use of Statoil - internal data. If you are work for the Bergen office of Statoil, - you can read the the file test-data/README for instructions on - how to make this data available. - - If you are not for Statoil in Bergen, you must pass the option: - "-EL StatoilData" to ctest to skip all the tests which require - Statoil internal data. - - StatoilBuild: There is one python test which makes use of Statoil - internal configuration data, this test is labeled with - StatoilBuild. If you want to run this test, you must set the - cmake option ECL_LOCAL_TARGET to point to a file which contains - these local configuration settings, e.g. where the ECLIPSE binary - is installed. - - Python: This label is used to indicate that the test uses Python. - - LSF: This labels indicates that the test needs a working LSF - environment to run. - - -5.5 ctest examples - - ctest -L Statoil # Run all tests labeled with Statoil - both - # StatoilData and StatoilBuild - - ctest -EL "Statoil|LSF" # Exclude all tests labeled with Statoil or LSF. - diff --git a/ThirdParty/Ert/README.md b/ThirdParty/Ert/README.md new file mode 100644 index 0000000000..783bfb5291 --- /dev/null +++ b/ThirdParty/Ert/README.md @@ -0,0 +1,301 @@ +# libecl [![Build Status](https://travis-ci.org/Statoil/libecl.svg?branch=master)](https://travis-ci.org/Statoil/libecl) + + +## Coming from OPM? + +`libecl` is a package for handling an ensemble of reservoir models, an +important part of that is beeing able to read and write the files from +standard reservoir applications; `libecl` has quite extensive support for +reading and writing the result files from the ECLIPSE reservoir +simulator. The capabilities to read and write ECLIPSE result files is +used by the OPM simulator codes. + +The `libecl` build system has many configuration options, but when +compiling for OPM you should be able to use the all defaults route: + +```bash +git clone https://github.com/Statoil/libecl.git +cd libecl +mkdir build +cd build +cmake .. +make +``` + +The OPM build system can find an `libecl` distribution in the sibling +location, i.e. if you have cloned ert beside the opm modules like: + +``` +libecl/ +opm-common/ +opm-parser/ +opm-material/ +... +``` + +The opm build system will find the ert distribution in-place, +otherwise you should install ert with 'make install' and the normal +cmake machinery of the opm build system should find it. + +``` +------------------------------------------------------------------------ + + _________________________________ + / \ + | ______ ______ _______ | + | | ____| | __ \ |__ __| | + | | |__ | |__) | | | | + | | __| | _ / | | | + | | |____ | | \ \ | | | + | |______| |_| \_\ |_| | + | | + | Ensemble based Reservoir Tool | + \_________________________________/ + + +------------------------------------------------------------------------ +``` + +1. `libecl` +2. ECLIPSE utilities. +3. Building `libecl` + 1. CMake settings you might want to adjust +4. The code: + 1. The different libraries + 2. The general structure + 3. Python wrappers +5. Tests + +------------------------------------------------------------------------ + +## 1. `libecl` + +`libecl` - Ensemble based Reservoir Tool is a tool for managing an ensemble +of reservoir models. The initial motivation for creating `libecl` was a as +tool to do assisted history matching with the Ensemble Kalman Filter +(EnKF). Very briefly, the process of using EnKF for history matching +can be summarized as: + +1. Sample initial reservoir parameters from a (Gaussian) initial +distribution. +2. Simulate the ensemble of of reservoir forward in time through a +part of the historical period for which data is available. +3. Load the results, compare with the observed data, update the +parameters and the state of reservoir by filtering out the most +inacurate results, and restart the forward simulations. + +This recipe is quite complex technically, and in particular involves +the ability to read and write input and output files from the +reservoir simulator (i.e. ECLIPSE in the case of `libecl`), run simulations +with arbitrary external programs, plotting data and so on. This +implies that a quite significant technical machinery must be in place +before the EnKF algorithm as such can be utilizied. This in particular +applies to real industry reservoir models, where typically +imperfections of all kinds flourish. + +Despite the fact that the initial motivation for creating `libecl` was to +be able to use the EnKF algorithm for history matching, `libecl` is +currently more used with the Ensemble Smoother and also purely as a +workflow manager, i.e. herding a large collection of reservoir models +through the required simulations steps. + + +## 2. ECLIPSE Utilities + +`libecl` has a quite large amount of code devoted to reading and writing +the ECLIPSE output files (grid/rft/restart/init/summary). In addition, +there is also reasonable support for reading and writing the grdecl +input files, but there is no general .DATA file parser. The ability to +read and write ECLIPSE output files is valuable in many reservoir +applications, and it is possible to only build and use the libecl +(with support libraries) library for working with ECLIPSE files. In +fact, the default build setup is to only build the ECLIPSE related +library and utilities. This part of the `libecl` distribution can also be +built on Windows with Visual Studio (albeit with maaaany warnings) and +with MinGW. + + +## 3. Building `libecl` + +CMake is the build system for `libecl`. The top level CMakeLists.txt file +is located in the top level directory of the repository, and this +CMakeLists.txt file includes individual CMakeLists.txt files for the +different libraries. + +Building with CMake is performed like this: + +1. Create a build directory, this can in principle be anywhere in the +filesystem. One level above the toplevel source directory is a practical choice. +2. Go to the build directory and invoke the command: +``` +ccmake +``` +Go through several 'configure' steps with CMake and generate native build files. +3. Exit ccmake and invoke the native build system, i.e. ordinarily 'make' on +Linux. +4. Subsequent builds can be performed using just the native make command, as in +step 3. + +### 3.1 CMake settings you might want to adjust + +The main setting you should adjust is `BUILD_ERT` which is default to +`OFF`, i.e. by default only the ECLIPSE related utilities will be +built. The build system has numerous configurations checks; the +ECLIPSE utilities should build on Windows, but to build all of `libecl` you +will need a Linux (Posix) system. + + +## 4. The code + +The code is mainly a collection of libraries written in C. + +### 4.1 The different libraries + +The _provided libraries_ are: + +* `libert_util`: This library is a collection of utilities of various sorts; if +C++ had been chosen as implementation language, most of these utilities could +probably be replaced by standard C++ classes. +* `libgeometry`: This is a very small geometry library; the main code is a small +implementantion of an alorithm to determine whether a point is inside a +polyhedron. The ECLIPSE library has some geometry related code which should be +moved here. +* `libwell`: This library will load well information from an ECLIPSE restart +file. This is mainly for the purpose of visualization of the existing wells, +and can not be used to update or model the well configuration. +* `libecl`: This library will read and (partly) write the various binary ECLIPSE +files, including `GRID/EGRID`, summary, `INIT`, restart and `RFT` files. There +is also support for reading an writing grdecl formatted files, but there is no +support for general parsing of the _ECLIPSE_ input format. + + + +### 4.2 General structure + +The code is written in C, but conventions give a 'scent of object +orientation'. Most of the code is uses the following conventions: + +* Every file 'xxx' implements a data type 'xxx_type' - this naming convention is +quite strong. +* All the structure definitions are in the source files, i.e. external scopes +must access the data of a structure through accessor functions. +* All functions which operate on a type 'xxx_type' take a pointer to xxx_type as +their first argument, the structure closely resemble the 'self' argument used +when implementing Python classes. +* Memory management is manual; however there are some conventions: + * Functions allocating storage have _alloc_ as part of the name. + * For all functions xxx_alloc() which allocate memory, there +should be a matching xxx_free() function to discard the objects. + * Containers can optionally destroy their content if the content +is installed with a destructor. +* In `libert_util/src/type_macros.h` there is a macro based +'type-system' which is used to runtime check casts of (void *). + + +### 4.3 Python wrappers + +Some of the code, in particular the ECLIPSE related functionality, has +been wrapped for usage in Python. Using these wrappers, it is quite +easy work with ECLIPSE files. The python wrappers are quite well +documented both in the directory python/docs and in the Python classes +themselves. + + +## 5. Tests + +The `libecl` codebase has a small but increasing test coverage. The tests +are typically located in a per-library subdirectory tests/. The test +framework is based on ctest which basically works like this: + +1. In the CMakeLists.txt file testing is enabled with `ENABLE_TESTING()`. +2. Tests are added with: +```python +add_test( test_name test_executable arg1 arg2 arg3 ... ) +``` + +If the executable exits with status 0 the test has passed, +otherwise it has failed. The executable run by the test can +typically be an executable built as part of the solution, but can +in principle be an arbitrary executable like a dedicated test +runner or e.g. the Python interpreter. + +### 5.1 Testing of C code + +The main part of the testing infrastructure are small C applications +which are added like this: + +``` +add_executable( test_exe test_source.c ) +target_link_libraries( test_exe lib ) +add_test( test_name ${EXECUTABLE_OUTPUT_PATH}/test_exe commandline_arg1 commandline_arg2 ) +``` + +Where the first two lines create the test executable in the normal +way, and the last line adds it as a test. + +### 5.2 Testing of Python Code + +In python/test there are several files with Python tests, these files +are executable files and they are invoked directly from the command +line. A limited number of the tests have been integrated in the ctest +system. + +### 5.3 Test names + +The tests in the cmake build system follow the naming convention of +the library regarding the functionality which they are testing: For +example, all tests for the libecl library use a name starting with +'ecl' and all tests for the tests for the config library are prefixed +by 'config'. The ctest options -R and -E can be used to include and +exclude tests based on their name + +``` +ctest -R ecl # Run all tests containing the regular expression 'ecl' +ctest -E ecl # Run all tests NOT containing the regular expression 'ecl' +``` + +### 5.4 Test labels + +Using the cmake set_property() function it is possible to assign +labels to the test, and the -L and -LE options to ctest can be used to +limit which tests to run. A test can only have one label; in the +current ctest setup different labels are combined into one composite +label with a ":" separator, e.g. + +``` +set_property( TEST test_xxx PROPERTY LABELS StatoilData:Python) +``` + +will set the 'StatoilData' and 'Python' properties on test_xxx. The +labels currently available in the `libecl` test setup are: + + StatoilData: This implies that the test makes use of Statoil + internal data. If you are work for the Bergen office of Statoil, + you can read the the file test-data/README for instructions on + how to make this data available. + + If you are not for Statoil in Bergen, you must pass the option: + "-EL StatoilData" to ctest to skip all the tests which require + Statoil internal data. + + StatoilBuild: There is one python test which makes use of Statoil + internal configuration data, this test is labeled with + StatoilBuild. If you want to run this test, you must set the + cmake option ECL_LOCAL_TARGET to point to a file which contains + these local configuration settings, e.g. where the ECLIPSE binary + is installed. + + Python: This label is used to indicate that the test uses Python. + + LSF: This labels indicates that the test needs a working LSF + environment to run. + + +### 5.5 ctest examples + +``` +ctest -L Statoil # Run all tests labeled with Statoil - both + # StatoilData and StatoilBuild + +ctest -EL "Statoil|LSF" # Exclude all tests labeled with Statoil or LSF. +``` diff --git a/ThirdParty/Ert/cmake/cmake_pyc b/ThirdParty/Ert/cmake/cmake_pyc index 03fd6507e2..7d0ab553b6 100644 --- a/ThirdParty/Ert/cmake/cmake_pyc +++ b/ThirdParty/Ert/cmake/cmake_pyc @@ -20,8 +20,8 @@ def compile_file(src_file , target_file): os.makedirs( path ) try: py_compile.compile( src_file , cfile = target_file , doraise = True) - except Exception,error: - sys.exit(1) + except Exception as error: + sys.exit(str(error)) target_path = sys.argv[-1] diff --git a/ThirdParty/Ert/cmake/cmake_pyc_file b/ThirdParty/Ert/cmake/cmake_pyc_file index 9304f69c0f..22c7425a4d 100644 --- a/ThirdParty/Ert/cmake/cmake_pyc_file +++ b/ThirdParty/Ert/cmake/cmake_pyc_file @@ -9,7 +9,7 @@ import os.path for file in sys.argv[1:]: try: py_compile.compile( file , doraise = True ) - except Exception,error: + except Exception as error: sys.exit("py_compile(%s) failed:%s" % (file , error)) diff --git a/ThirdParty/Ert/cmake/cmake_pyc_tree b/ThirdParty/Ert/cmake/cmake_pyc_tree index eeeaa389b6..249eb84ede 100644 --- a/ThirdParty/Ert/cmake/cmake_pyc_tree +++ b/ThirdParty/Ert/cmake/cmake_pyc_tree @@ -24,7 +24,7 @@ for (root , dir_list , file_list) in os.walk( root_path ): try: print "Compiling: %s" % py_file py_compile.compile( py_file , doraise = True ) - except Exception,error: + except Exception as error: sys.exit("py_compile(%s) failed:%s" % (py_file , error)) diff --git a/ThirdParty/Ert/cmake/ert_api_check.cmake b/ThirdParty/Ert/cmake/ert_api_check.cmake index 972ae76eb5..1362cd0235 100644 --- a/ThirdParty/Ert/cmake/ert_api_check.cmake +++ b/ThirdParty/Ert/cmake/ert_api_check.cmake @@ -16,6 +16,8 @@ endif() find_library( LAPACK_LIBRARY NAMES lapack) if (LAPACK_LIBRARY) set(ERT_HAVE_LAPACK ON) +else() + set(ERT_HAVE_LAPACK OFF) endif() #----------------------------------------------------------------- @@ -25,9 +27,13 @@ find_path( ZLIB_HEADER zlib.h /usr/include ) if (ZLIB_LIBRARY AND ZLIB_HEADER) set( ERT_HAVE_ZLIB ON ) else() - message("ZLib not found - zlib support will not be included." ) + if(NOT DEFINED ZLIB_LIBRARY) + message(STATUS "ZLib library not found - zlib support will not be included." ) + endif() + if(NOT DEFINED ZLIB_HEADER) + message(STATUS "zlib.h not found - zlib support will not be included.") + endif() endif() - #----------------------------------------------------------------- try_compile( ERT_HAVE_ISFINITE ${CMAKE_BINARY_DIR} ${PROJECT_SOURCE_DIR}/cmake/Tests/test_isfinite.c ) @@ -70,5 +76,4 @@ endif() find_program(PING_PATH NAMES ping) if (PING_PATH) set( ERT_HAVE_PING ON ) - add_definitions( -DPING_CMD="${PING_PATH}" ) -endif() \ No newline at end of file +endif() diff --git a/ThirdParty/Ert/cmake/ert_build_check.cmake b/ThirdParty/Ert/cmake/ert_build_check.cmake index 6abfd821f1..ea9d7b9c14 100644 --- a/ThirdParty/Ert/cmake/ert_build_check.cmake +++ b/ThirdParty/Ert/cmake/ert_build_check.cmake @@ -73,4 +73,8 @@ if (NOT HAVE_CXX_SHARED_PTR) set( BUILD_CXX OFF ) endif() +if (HAVE_FORK AND HAVE_PTHREAD AND HAVE_EXECINFO AND HAVE_GETPWUID) + set( HAVE_UTIL_ABORT_INTERCEPT ON) + set( HAVE_BACKTRACE ON) +endif() diff --git a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py b/ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py index 1724cea874..cf1557b19b 100644 --- a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py +++ b/ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py @@ -9,7 +9,7 @@ from ert.test import ExtendedTestCase try: from synthesizer import OilSimulator except ImportError as e: - share_lib_path = os.path.join(ExtendedTestCase.findShareRoot(), "lib") + share_lib_path = ExtendedTestCase.createShareRoot("lib") sys.path.insert(0, share_lib_path) synthesizer_module = __import__("synthesizer") diff --git a/ThirdParty/Ert/docs/user/distributions/index.rst b/ThirdParty/Ert/docs/user/distributions/index.rst deleted file mode 100644 index eb52a90a2d..0000000000 --- a/ThirdParty/Ert/docs/user/distributions/index.rst +++ /dev/null @@ -1,172 +0,0 @@ -.. toctree:: - :maxdepth: 1 - -.. _prior_distributions: - -Prior distributions avaliable in ERT -==================================== - -The :ref:`GEN_KW ` keyword is typically used in sensitivy -studies and as parameters which are updated with the Ensemble Smoother -in a model updating project. In your configuration file the -:ref:`GEN_KW ` keyword is configured as: - -:: - - GEN_KW ID my_template.txt my_eclipse_include.txt my_priors.txt - -The file ``my_priors.txt`` contains the names of the variables -you are considering, and specifies the distribution which should be -used for the initial sampling. - - -NORMAL ------- -To set a normal (Gaussian) prior, use the keyword NORMAL. It takes two -arguments, a mean value and a standard deviation. Thus, the following -example will assign a normal prior with mean 0 and standard deviation -1 to the variable VAR1: - -:: - - VAR1 NORMAL 0 1 - -LOGNORMAL ---------- -A stochastic variable is log normally distributed if the logarithm of -the variable is normally distributed. In other words, if X is normally -distributed, then Y = exp(X) is log normally distributed. - -A log normal prior is suited to model positive quanties with a heavy -tail (tendency to take large values). To set a log normal prior, use -the keyword LOGNORMAL. It takes two arguments, the mean and standard -deviation of the *logarithm* of the variable: - -:: - - VAR2 LOGNORMAL 0 - -TRUNCATED_NORMAL ------------------ - -This *TRUNCATED_NORMAL* distribution works as follows: - - 1. Draw random variable X ~ N(mu,std) - 2. Clamp X to the interval [min, max] - -This is **not** a proper truncated normal distribution; hence the -clamping to ``[min,max]` should be an exceptional event. To configure -this distribution for a situation with mean 1, standard deviation 0.25 -and hard limits 0 and 10: - -:: - - VAR3 TRUNCATED_NORMAL 1 0.25 0 10 - - -UNIFORM -------- - -A stochastic variable is uniformly distributed if has a constant -probability density on a closed interval. Thus, the uniform -distribution is completely characterized by it's minimum and maximum -value. To assign a uniform distribution to a variable, use the keyword -UNIFORM, which takes a minimum and a maximum value for a the -variable. Here is an example, which assigns a uniform distribution -between 0 and 1 to a variable ``VAR4``: - -:: - - VAR4 UNIFORM 0 1 - -It can be shown that among all distributions bounded below by a and -above by b, the uniform distribution with parameters a and b has the -maximal entropy (contains the least information). Thus, the uniform -distribution should be your preferred prior distribution for robust -modeling of bounded variables. - - -LOGUNIF -------- - -A stochastic variable is log uniformly distributed if it's logarithm -is uniformly distributed on the interval [a,b]. To assign a log -uniform distribution to a a variable, use the keyword LOGUNIF, which -takes a minimum and a maximum value for the output variable as -arguments. The example - -:: - - VAR5 LOGUNIF 0.00001 1 - -will give values in the range [0.00001,1] - with considerably more -weight towards the lower limit. The log uniform distribution is useful -when modeling a bounded positive variable who has most of it's -probability weight towards one of the bounds. - -CONST ------ - -The keyword CONST is used to assign a Dirac distribution to a -variable, i.e. set it to a constant value. Here is an example of use: - -:: - - CONST 1.0 - -DUNIF ------ - -The keyword DUNIF is used to assign a discrete uniform distribution. It takes three arguments, the number bins, a minimum and maximum value. Here is an example which creates a discrete uniform distribution on [0,1] with 25 bins: - -:: - - DUNIF 25 0 1 - -ERRF ------ - -The ERRF keyword is used to define a prior resulting from applying the error function to a normally distributed variable with mean 0 and variance 1. The keyword takes four arguments: - -:: - - ERRF MIN MAX SKEWNESS WIDTH - -The arguments MIN and MAX sets the minimum and maximum value of the transform. Zero SKEWNESS results in a symmetric distribution, whereas negative SKEWNESS will shift the distribution towards the left and positive SKEWNESS will shift it towards the right. Letting WIDTH be larger than one will cause the distribution to be unimodal, whereas WIDTH less than one will create a bi-modal distribution. - - -DERRF ------ - -The keyword DERRF is similar to ERRF, but will create a discrete output. DERRF takes 5 arguments: - -:: - - DERRF NBINS MIN MAX SKEWNESS WIDTH - -NBINS set the number of discrete values, and the other arguments have the same effect as in ERRF. - - -Priors and transformations -========================== - -The Ensemble Smoother method, which ERT uses for updating of -parameters, works with normally distributed variables. So internally -in ERT the interplay between ``GEN_KW`` variables and updates is as -follows: - - 1. ERT samples a random variable ``x ~ N(0,1)`` - before outputing - to the forward model this is *transformed* to ``y ~ F(Y)`` where - the the distribution ``F(Y)`` is the correct prior distribution. - - 2. When the prior simulations are complete ERT calculates misfits - between simulated and observed values and *updates* the - parameters; hence the variables ``x`` now represent samples from - a posterior distribution which is Normal with mean and standard - deviation *different from (0,1)*. - -The transformation prescribed by ``F(y)`` still "works" - but it no -longer maps to a distribution in the same family as initially -specified by the prior. A consequence of this is that the update -process can *not* give you a posterior with updated parameters in the -same distribution family as the Prior. diff --git a/ThirdParty/Ert/docs/user/index.rst b/ThirdParty/Ert/docs/user/index.rst deleted file mode 100644 index 79949d3ae5..0000000000 --- a/ThirdParty/Ert/docs/user/index.rst +++ /dev/null @@ -1,15 +0,0 @@ -User documentation for ERT -========================== - -Contents: - -.. toctree:: - :maxdepth: 1 - - tutorial/index - keywords/index - workflows/index - magic_strings/index - observations/index - distributions/index - localization/index diff --git a/ThirdParty/Ert/docs/user/keywords/index.rst b/ThirdParty/Ert/docs/user/keywords/index.rst deleted file mode 100644 index 3d0befe551..0000000000 --- a/ThirdParty/Ert/docs/user/keywords/index.rst +++ /dev/null @@ -1,1869 +0,0 @@ -.. _ert_kw_full_doc: - -Keywords for the configuration file -=================================== - -:ref:`Go to main ERT page ` - - -General overview ----------------- -The enkf application is started with a single argument, which is the name of the configuration file to be used. The enkf configuration file serves several purposes, which are: - -* Defining which ECLIPSE model to use, i.e. giving a data, grid and schedule file. -* Defining which observation file to use. -* Defining how to run simulations. -* Defining where to store results. -* Creating a parametrization of the ECLIPSE model. - -The configuration file is a plain text file, with one statement per line. The first word on each line is a keyword, which then is followed by a set of arguments that are unique to the particular keyword. Except for the DEFINE keyword, ordering of the keywords is not significant. Similarly to ECLIPSE data files, lines starting with "--" are treated as comments. - -The keywords in the enkf configuration file can roughly be divded into two groups: - -* Basic required keywords not related to parametrization. I.e., keywords giving the data, grid, schedule and observation file, defining how to run simulations and how to store results. These keywords are described in :ref:`Basic required keywords.` -* Basic optional keywords not related to parametrization. These keywords are described in :ref:`Basic optional keywords `. -* Keywords related to parametrization of the ECLIPSE model. These keywords are described in :ref:`Parametrization keywords`. -* Advanced keywords not related to parametrization. These keywords are described in :ref:`Advanced optional keywords`. - - -List of keywords ----------------- - -===================================================================== ====================================== ============================== ============================================================================================================================================== -Keyword name Required by user? Default value Purpose -===================================================================== ====================================== ============================== ============================================================================================================================================== -:ref:`ADD_FIXED_LENGTH_SCHEDULE_KW ` NO Supporting unknown SCHEDULE keywords. -:ref:`ANALYSIS_COPY ` NO Create new instance of analysis module -:ref:`ANALYSIS_LOAD ` NO Load analysis module -:ref:`ANALYSIS_SET_VAR ` NO Set analysis module internal state variable -:ref:`ANALYSIS_SELECT ` NO STD_ENKF Select analysis module to use in update -:ref:`CASE_TABLE ` NO For running sensitivities you can give the cases descriptive names -:ref:`CONTAINER ` NO ... -:ref:`CUSTOM_KW ` NO Ability to load arbitrary values from the forward model. -:ref:`DATA_FILE ` YES Provide an ECLIPSE data file for the problem. -:ref:`DATA_KW ` NO Replace strings in ECLIPSE .DATA files -:ref:`DBASE_TYPE ` NO BLOCK_FS Which 'database' system should be used for storage -:ref:`DEFINE ` NO Define keywords with config scope -:ref:`DELETE_RUNPATH ` NO Explicitly tell ert to delete the runpath when a job is complete -:ref:`ECLBASE ` YES Define a name for the ECLIPSE simulations. -:ref:`END_DATE ` NO You can tell ERT how lon the simulations should be - for error check -:ref:`ENKF_ALPHA ` NO 1.50 Parameter controlling outlier behaviour in EnKF algorithm -:ref:`ENKF_BOOTSTRAP ` NO FALSE Should we bootstrap the Kalman gain estimate -:ref:`ENKF_CROSS_VALIDATION ` NO ... -:ref:`ENKF_CV_FOLDS ` NO 10 Number of folds used in the Cross-Validation scheme -:ref:`ENKF_KERNEL_PARAM ` NO 1 -:ref:`ENKF_LOCAL_CV ` NO FALSE Should we estimate the subspace dimenseion using Cross-Validation -:ref:`ENKF_MERGE_OBSERVATIONS ` NO FALSE Should observations from many times be merged together -:ref:`ENKF_MODE ` NO STANDARD Which EnKF should be used -:ref:`ENKF_PEN_PRESS ` NO FALSE Should we want to use a penalised PRESS statistic in model selection? -:ref:`ENKF_RERUN ` NO FALSE Should the simulations be restarted from time zero after each update. -:ref:`ENKF_SCALING ` NO TRUE Do we want to normalize the data ensemble to have unit variance? -:ref:`ENKF_TRUNCATION ` NO 0.99 Cutoff used on singular value spectrum. -:ref:`ENSPATH ` NO storage Folder used for storage of simulation results. -:ref:`FIELD ` NO Ads grid parameters -:ref:`FORWARD_MODEL ` NO Add the running of a job to the simulation forward model. -:ref:`GEN_DATA ` NO Specify a general type of data created/updated by the forward model. -:ref:`GEN_KW ` NO Add a scalar parameter. -:ref:`GEN_KW_TAG_FORMAT ` NO <%s> Format used to add keys in the GEN_KW template files. -:ref:`GEN_KW_EXPORT_FILE ` NO parameter.txt Name of file to export GEN_KW parameters to. -:ref:`GEN_PARAM ` NO Add a general parameter. -:ref:`GRID ` NO Provide an ECLIPSE grid for the reservoir model. -:ref:`HISTORY_SOURCE ` NO REFCASE_HISTORY Source used for historical values. -:ref:`HOOK_WORKFLOW ` NO Install a workflow to be run automatically. -:ref:`IGNORE_SCHEDULE ` NO -:ref:`INSTALL_JOB ` NO Install a job for use in a forward model. -:ref:`ITER_CASE ` NO IES%d Case name format - iterated ensemble smoother -:ref:`ITER_COUNT ` NO 4 Number of iterations - iterated ensemble smoother -:ref:`ITER_RETRY_COUNT ` NO 4 Number of retries for a iteration - iterated ensemble smoother -:ref:`JOBNAME ` NO Name used for simulation files. An alternative to ECLBASE. -:ref:`JOB_SCRIPT ` NO Python script managing the forward model. -:ref:`LOAD_SEED ` NO Load random seed from given file. -:ref:`LOAD_WORKFLOW ` NO Load a workflow into ERT. -:ref:`LOAD_WORKFLOW_JOB ` NO Load a workflow job into ERT. -:ref:`LICENSE_PATH ` NO A path where ert-licenses to e.g. RMS are stored. -:ref:`LOCAL_CONFIG ` NO A file with configuration information for local analysis. -:ref:`LOG_FILE ` NO log Name of log file -:ref:`LOG_LEVEL ` NO 1 How much logging? -:ref:`LSF_QUEUE ` NO normal Name of LSF queue. -:ref:`LSF_RESOURCES ` NO -:ref:`LSF_SERVER ` NO Set server used when submitting LSF jobs. -:ref:`MAX_ITER_COUNT ` NO Maximal number of iterations - iterated ensemble smoother. -:ref:`MAX_RESAMPLE ` NO 1 How many times should ert resample & retry a simulation. -:ref:`MAX_RUNNING_RSH ` NO The maximum number of running jobs when using RSH queue system. -:ref:`MAX_RUNTIME ` NO 0 Set the maximum runtime in seconds for a realization. -:ref:`MAX_SUBMIT ` NO 2 How many times should the queue system retry a simulation. -:ref:`MIN_REALIZATIONS ` NO 0 Set the number of minimum reservoir realizations to run before long running realizations are stopped. Keyword STOP_LONG_RUNNING must be set to TRUE when MIN_REALIZATIONS are set. -:ref:`NUM_REALIZATIONS ` YES Set the number of reservoir realizations to use. -:ref:`OBS_CONFIG ` NO File specifying observations with uncertainties. -:ref:`PLOT_SETTINGS ` NO Possibility to configure some aspects of plotting. -:ref:`PRE_CLEAR_RUNPATH ` NO FALSE Should the runpath be cleared before initializing? -:ref:`QUEUE_SYSTEM ` NO System used for running simulation jobs. -:ref:`REFCASE ` NO (see HISTORY_SOURCE and SUMMARY) Reference case used for observations and plotting. -:ref:`REFCASE_LIST ` NO Full path to Eclipse .DATA files containing completed runs (which you can add to plots) -:ref:`RERUN_PATH ` NO ... -:ref:`RERUN_START ` NO 0 ... -:ref:`RFT_CONFIG ` NO Config file specifying wellnames and dates for rft-measurments. Used for plotting. The format has to be name day month year (ex. Q-2FI 02 08 1973), with a new entry on a new line. -:ref:`RFTPATH ` NO rft Path to where the rft well observations are stored -:ref:`RSH_COMMAND ` NO Command used for remote shell operations. -:ref:`RSH_HOST ` NO Remote host used to run forward model. -:ref:`RUNPATH ` NO simulations/realization%d Directory to run simulations -:ref:`RUN_TEMPLATE ` NO Install arbitrary files in the runpath directory. -:ref:`STD_SCALE_CORRELATED_OBS ` NO FALSE Try to estimate the correlations in the data to inflate the observation std. -:ref:`SCHEDULE_FILE ` NO Provide an ECLIPSE schedule file for the problem. -:ref:`SCHEDULE_PREDICTION_FILE ` NO Schedule prediction file. -:ref:`SETENV ` NO You can modify the UNIX environment with SETENV calls. -:ref:`SINGLE_NODE_UPDATE ` NO FALSE ... -:ref:`STOP_LONG_RUNNING ` NO FALSE Stop long running realizations after minimum number of realizations (MIN_REALIZATIONS) have run. -:ref:`STORE_SEED ` NO File where the random seed used is stored. -:ref:`SUMMARY ` NO Add summary variables for internalization. -:ref:`SURFACE ` NO Surface parameter read from RMS IRAP file. -:ref:`TORQUE_QUEUE ` NO ... -:ref:`TIME_MAP ` NO Ability to manually enter a list of dates to establish report step <-> dates mapping. -:ref:`UMASK ` NO Control the permissions on files created by ERT. -:ref:`UPDATE_LOG_PATH ` NO update_log Summary of the EnKF update steps are stored in this directory. -:ref:`UPDATE_PATH ` NO Modify a UNIX path variable like LD_LIBRARY_PATH. -:ref:`UPDATE_SETTINGS ` NO Possibility to configure some common aspects of the Smoother update.| -:ref:`WORKFLOW_JOB_DIRECTORY ` NO Directory containing workflow jobs. -===================================================================== ====================================== ============================== ============================================================================================================================================== - - -:ref:` <>` - -Basic required keywords ------------------------ -.. _basic_required_keywords: - -These keywords must be set to make the enkf function properly. - -.. _data_file: -.. topic:: DATA_FILE - - | This is the name of ECLIPSE data file used to control the simulations. The data file should be prepared according to the guidelines given in Preparing an ECLIPSE reservoir model for use with enkf. - - *Example:* - - :: - - -- Load the data file called ECLIPSE.DATA - DATA_FILE ECLIPSE.DATA - - - - -.. _eclbase: -.. topic:: ECLBASE - - | The ECLBASE keyword sets the basename used for the ECLIPSE simulations. It can (and should, for your convenience) contain a %d specifier, which will be replaced with the realization numbers when running ECLIPSE. Note that due to limitations in ECLIPSE, the ECLBASE string must be in strictly upper or lower case. - - *Example:* - - :: - - -- Use MY_VERY_OWN_OIL_FIELD-0 etc. as basename. - -- When ECLIPSE is running, the %d will be, - -- replaced with realization number, giving: - -- - -- MY_VERY_OWN_OIL_FIELD-0 - -- MY_VERY_OWN_OIL_FIELD-1 - -- MY_VERY_OWN_OIL_FIELD-2 - -- ... - -- and so on. - ECLBASE MY_VERY_OWN_OIL_FIELD-%d - -.. _jobname: -.. topic:: JOBNAME - - As an alternative to the ECLBASE keyword you can use the JOBNAME keyword; in particular in cases where your forward model does not include ECLIPSE at all that makes more sense. If JOBANME is used instead of ECLBASE the same rules of no-mixed-case apply. - -.. _grid: -.. topic:: GRID - - This is the name of an existing GRID/EGRID file for your ECLIPSE model. If you had to create a new grid file when preparing your ECLIPSE reservoir model for use with enkf, this should point to the new .EGRID file. - - *Example:* - - :: - - -- Load the .EGRID file called MY_GRID.EGRID - GRID MY_GRID.EGRID - - -.. _num_realizations: -.. topic:: NUM_REALIZATIONS - - This is just the size of the ensemble, i.e. the number of realizations/members in the ensemble. - - *Example:* - - :: - - -- Use 200 realizations/members - NUM_REALIZATIONS 200 - - -.. _schedule_file: -.. topic:: SCHEDULE_FILE - - This keyword should be the name a text file containing the SCHEDULE section of the ECLIPSE data file. It should be prepared in accordance with the guidelines given in Preparing an ECLIPSE reservoir model for use with enkf. This SCHEDULE section will be used to control the ECLIPSE simulations. You can optionally give a second filename, which is the name of file which will be written into the directories for running ECLIPSE. - - *Example:* - - :: - - -- Parse MY_SCHEDULE.SCH, call the generated file ECLIPSE_SCHEDULE.SCH - SCHEDULE_FILE MY_SCHEDULE.SCH ECLIPSE_SCHEDULE.SCH - - Observe that the SCHEDULE_FILE keyword is only required when you need ERT to stop and restart your simulations; i.e. when you are using the EnKF algorithm. If you are only using ERT to your simulations; or using smoother update it is recommended to leave the SCHEDULE_FILE keyword out. In that case you must make sure that the ECLIPSE datafile correctly includes the SCHEDULE section. - - -Basic optional keywords ------------------------ -.. _basic_optional_keywords: - -These keywords are optional. However, they serve many useful purposes, and it is recommended that you read through this section to get a thorough idea of what's possible to do with the enkf application. - -.. _data_kw: -.. topic:: DATA_KW - - The keyword DATA_KW can be used for inserting strings into placeholders in the ECLIPSE data file. For instance, it can be used to insert include paths. - - *Example:* - - :: - - -- Define the alias MY_PATH using DATA_KW. Any instances of (yes, with brackets) - -- in the ECLIPSE data file will now be replaced with /mnt/my_own_disk/my_reservoir_model - -- when running the ECLIPSE jobs. - DATA_KW MY_PATH /mnt/my_own_disk/my_reservoir_model - - The DATA_KW keyword is of course optional. Note also that the enkf has some built in magic strings. - -.. _delete_runpath: -.. topic:: DELETE_RUNPATH - - When the ert application is running it creates directories for - the forward model simulations, one for each realization. When - the simulations are done, ert will load the results into the - internal database. By default the realization folders will be - left intact after ert has loaded the results, but using the - keyword DELETE_RUNPATH you can request to have (some of) the - directories deleted after results have been loaded. - - *Example A:* - - :: - - -- Delete simulation directories 0 to 99 - DELETE_RUNPATH 0-99 - - *Example B:* - - :: - - -- Delete simulation directories 0 to 10 as well as 12, 15 and 20. - DELETE_RUNPATH 0 - 10, 12, 15, 20 - - The DELETE_RUNPATH keyword is optional. - - -.. _end_date: -.. topic:: END_DATE - - When running a set of models from beginning to end ERT does - not now in advance how long the simulation is supposed to be, - it is therefor impossible beforehand to determine which - restart file number should be used as target file, and the - procedure used for EnKF runs can not be used to verify that an - ECLIPSE simulation has run to the end. - - By using the END_DATE keyword you can tell ERT that the - simulation should go at least up to the date given by - END_DATE, otherwise they will be regarded as failed. The - END_DATE does not need to correspond exactly to the end date - of the simulation, it must just be set so that all simulations - which go to or beyond END_DATE are regarded as successfull. - - *Example:* - - :: - END_DATE 10/10/2010 - - With this END_DATE setting all simulations which have gone to - at least 10.th of October 2010 are OK. - - -.. _enspath: -.. topic:: ENSPATH - - The ENSPATH should give the name of a folder that will be used - for storage by the enkf application. Note that the contents of - this folder is not intended for human inspection. By default, - ENSPATH is set to "storage". - - *Example:* - - :: - - -- Use internal storage in /mnt/my_big_enkf_disk - ENSPATH /mnt/my_big_enkf_disk - - The ENSPATH keyword is optional. - - -.. _history_source: -.. topic:: HISTORY_SOURCE - - In the observation configuration file you can enter - observations with the keyword HISTORY_OBSERVATION; this means - that ERT will the observed 'true' values from the model - history. Practically the historical values can be fetched - either from the SCHEDULE file or from a reference case. What - source to use for the historical values can be controlled with - the HISTORY_SOURCE keyword. The different possible values for - the HISTORY_SOURCE keyword are: - - - REFCASE_HISTORY - This is the default value for HISTORY_SOURCE, - ERT will fetch the historical values from the *xxxH* - keywords in the refcase summary, e.g. observations of - WGOR:OP_1 is based the WGORH:OP_1 vector from the - refcase summary. - - REFCASE_SIMULATED - In this case the historical values are based on the simulated values from the refcase, this is mostly relevant when a you want compare with another case which serves as 'the truth'. - - SCHEDULE - Load historical values from the WCONHIST and WCONINJE keywords in the Schedule file. - - - When setting HISTORY_SOURCE to either REFCASE_SIMULATED or REFCASE_HISTORY you must also set the REFCASE variable to point to the ECLIPSE data file in an existing reference case (should be created with the same schedule file as you are using now). - - *Example:* - - :: - - -- Use historic data from reference case - HISTORY_SOURCE REFCASE_HISTORY - REFCASE /somefolder/ECLIPSE.DATA - - The HISTORY_SOURCE keyword is optional. - -.. _refcase: -.. topic:: REFCASE - - With the REFCASE key you can supply ert with a reference case which can be used for observations (see HISTORY_SOURCE), if you want to use wildcards with the SUMMARY keyword you also must supply a REFCASE keyword. The REFCASE keyword should just point to an existing ECLIPSE data file; ert will then look up and load the corresponding summary results. - - *Example:* - - :: - - -- The REFCASE keyword points to the datafile of an existing ECLIPSE simulation. - REFCASE /path/to/somewhere/SIM_01_BASE.DATA - - -.. _install_job: -.. topic:: INSTALL_JOB - - The INSTALL_JOB keyword is used to learn the enkf application how to run external applications and scripts, i.e. defining a job. After a job has been defined with INSTALL_JOB, it can be used with the FORWARD_MODEL keyword. For example, if you have a script which generates relative permeability curves from a set of parameters, it can be added as a job, allowing you to do history matching and sensitivity analysis on the parameters defining the relative permeability curves. - - The INSTALL_JOB keyword takes two arguments, a job name and the name of a configuration file for that particular job. - - *Example:* - - :: - - -- Define a Lomeland relative permeabilty job. - -- The file jobs/lomeland.txt contains a detailed - -- specification of the job. - INSTALL_JOB LOMELAND jobs/lomeland.txt - - The configuration file used to specify an external job is easy to use and very flexible. It is documented in Customizing the simulation workflow in enkf. - - The INSTALL_JOB keyword is optional. - -.. _obs_config: -.. topic:: OBS_CONFIG - - The OBS_CONFIG key should point to a file defining observations and associated uncertainties. The file should be in plain text and formatted according to the guidelines given in Creating an observation file for use with enkf. - - *Example:* - - :: - - -- Use the observations in my_observations.txt - OBS_CONFIG my_observations.txt - - The OBS_CONFIG keyword is optional, but for your own convenience, it is strongly recommended to provide an observation file. - -.. _result_path: -.. topic:: RESULT_PATH - - The enkf application will print some simple tabulated results at each report step. The RESULT_PATH keyword should point to a folder where the tabulated results are to be written. It can contain a %d specifier, which will be replaced with the report step by enkf. The default value for RESULT_PATH is "results/step_%d". - - *Example:* - - :: - - -- Changing RESULT_PATH - RESULT_PATH my_nice_results/step-%d - - The RESULT_PATH keyword is optional. - -.. _runpath: -.. topic:: RUNPATH - - The RUNPATH keyword should give the name of the folders where the ECLIPSE simulations are executed. It should contain at least one %d specifier, which will be replaced by the realization number when the enkf creates the folders. Optionally, it can contain one more %d specifier, which will be replaced by the iteration number. - - By default, RUNPATH is set to "simulations/realization-%d". - - *Example A:* - - :: - -- Giving a RUNPATH with just one %d specifer. - RUNPATH /mnt/my_scratch_disk/realization-%d - - *Example B:* - - :: - - -- Giving a RUNPATH with two %d specifers. - RUNPATH /mnt/my_scratch_disk/realization-%d/iteration-%d - - The RUNPATH keyword is optional. - - -.. _runpath_file: -.. topic:: RUNPATH_FILE - -When running workflows based on external scripts it is necessary to 'tell' the external script in some way or another were all the realisations are located in the filesystem. Since the number of realisations can be quite high this will easily overflow the commandline buffer; the solution which is used is therefor to let ert write a reagular file which looks like this:: - - 0 /path/to/realisation0 CASE0 iter - 1 /path/to/realisation1 CASE1 iter - ... - N /path/to/realisationN CASEN iter - -The path to this file can then be passed to the scripts using the -magic string . The RUNPATH_FILE will by default be -stored as .ert_runpath_list in the same directory as the configuration -file, but you can set it to something else with the RUNPATH_FILE key. - -Keywords controlling the simulations ------------------------------------- -.. _keywords_controlling_the_simulations: - -.. _min_realizations: -.. topic:: MIN_REALIZATIONS - - MIN_REALIZATIONS is the minimum number of realizations that must have succeeded for the simulation to be regarded as a success. - - MIN_REALIZATIONS can also be used in combination with STOP_LONG_RUNNING, see the documentation for STOP_LONG_RUNNING for a description of this. - - *Example:* - - :: - - MIN_REALIZATIONS 20 - - The MIN_REALIZATIONS key can also be set as a percentage of NUM_REALIZATIONS - - :: - - MIN_REALIZATIONS 10% - - The MIN_REALIZATIONS key is optional. - - -.. _stop_long_running: -.. topic:: STOP_LONG_RUNNING - - The STOP_LONG_RUNNING key is used in combination with the MIN_REALIZATIONS key to control the runtime of simulations. When STOP_LONG_RUNNING is set to TRUE, MIN_REALIZATIONS is the minimum number of realizations run before the simulation is stopped. After MIN_REALIZATIONS have succeded successfully, the realizatons left are allowed to run for 25% of the average runtime for successfull realizations, and then killed. - - *Example:* - - :: - - -- Stop long running realizations after 20 realizations have succeeded - MIN_REALIZATIONS 20 - STOP_LONG_RUNNING TRUE - - The STOP_LONG_RUNNING key is optional. The MIN_REALIZATIONS key must be set when STOP_LONG_RUNNING is set to TRUE. - - -.. _max_runtime: -.. topic:: MAX_RUNTIME - - The MAX_RUNTIME keyword is used to control the runtime of simulations. When MAX_RUNTIME is set, a job is only allowed to run for MAX_RUNTIME, given in seconds. A value of 0 means unlimited runtime. - - *Example:* - - :: - - -- Let each realizations run for 50 seconds - MAX_RUNTIME 50 - - The MAX_RUNTIME key is optional. - - -Parameterization keywords -------------------------- -.. _parameterization_keywords: - -The keywords in this section are used to define a parametrization of the ECLIPSE model. I.e., defining which parameters to change in a sensitivity analysis and/or history matching project. For some parameters, it necessary to specify a prior distribution. See Prior distributions available in enkf for a complete list of available priors. - -.. _field: -.. topic:: FIELD - - The FIELD keyword is used to parametrize quantities which have extent over the full grid. Both dynamic properties like pressure, and static properties like porosity, are implemented in terms of FIELD objects. When adding fields in the config file the syntax is a bit different for dynamic fields (typically solution data from ECLIPSE) and parameter fields like permeability and porosity. - - **Dynamic fields** - - To add a dynamic field the entry in the configuration file looks like this: - - :: - FIELD DYNAMIC MIN:X MAX:Y - - In this case ID is not an arbitrary string; it must coincide with the keyword name found in the ECLIPSE restart file, e.g. PRESSURE. Optionally, you can add a minimum and/or a maximum value with MIN:X and MAX:Y. - - *Example A:* - - :: - - -- Adding pressure field (unbounded) - FIELD PRESSURE DYNAMIC - - *Example B:* - - :: - - -- Adding a bounded water saturation field - FIELD SWAT DYNAMIC MIN:0.2 MAX:0.95 - - **Parameter fields** - - A parameter field (e.g. porosity or permeability) is defined as follows: - - :: - - FIELD ID PARAMETER INIT_FILES:/path/%d MIN:X MAX:Y OUTPUT_TRANSFORM:FUNC INIT_TRANSFORM:FUNC - - Here ID is again an arbitrary string, ECLIPSE_FILE is the name of the file the enkf will export this field to when running simulations. Note that there should be an IMPORT statement in the ECLIPSE data file corresponding to the name given with ECLIPSE_FILE. INIT_FILES is a filename (with an embedded %d) to load the initial field from. Can be RMS ROFF format, ECLIPSE restart format or ECLIPSE GRDECL format. - - The input arguments MIN, MAX, INIT_TRANSFORM and OUTPUT_TRANSFORM are all optional. MIN and MAX are as for dynamic fields. - - For Assisted history matching, the variables in ERT should be normally distributed internally - the purpose of the transformations is to enable working with normally distributed variables internally in ERT. Thus, the optional arguments INIT_TRANSFORM:FUNC and OUTPUT_TRANSFORM:FUNC are used to transform the user input of parameter distribution. INIT_TRANSFORM:FUNC is a function which will be applied when they are loaded to ERT. OUTPUT_TRANSFORM:FUNC is a function which will be applied to the field when it is exported from ERT, and FUNC is the name of a transformation function to be applied. The avaialble functions are listed below: - - "POW10" : This function will raise x to the power of 10: y = 10^x. - "TRUNC_POW10" : This function will raise x to the power of 10 - and truncate lower values at 0.001. - "LOG" : This function will take the NATURAL logarithm of x: y = ln(x). - "LN" : This function will take the NATURAL logarithm of x: y = ln(x). - "LOG10" : This function will take the log10 logarithm of x: y = log10(x). - "EXP" : This function will calculate y = exp(x). - "LN0" : This function will calculate y = ln(x + 0.000001 - "EXP0" : This function will calculate y = exp(x) - 0.000001 - - For example, the most common scenario is that underlying log-normal distributed permeability in RMS are transformed to normally distributted in ERT, then you do: - - INIT_TRANSFORM:LOG To ensure that the variables which were initially log-normal distributed are transformed to normal distribution when they are loaded into ert. - - OUTPUT_TRANSFORM:EXP To ensure that the variables are reexponentiated to be log-normal distributed before going out to Eclipse. - - If users specify the wrong function name (e.g INIT_TRANSFORM:I_DONT_KNOW), ERT will stop and print all the valid function names. - - Regarding format of ECLIPSE_FILE: The default format for the parameter fields is binary format of the same type as used in the ECLIPSE restart files. This requires that the ECLIPSE datafile contains an IMPORT statement. The advantage with using a binary format is that the files are smaller, and reading/writing is faster than for plain text files. If you give the ECLIPSE_FILE with the extension .grdecl (arbitrary case), enkf will produce ordinary .grdecl files, which are loaded with an INCLUDE statement. This is probably what most users are used to beforehand - but we recomend the IMPORT form. - - **General fields** - - In addition to dynamic and parameter field there is also a general field, where you have fine grained control over input/output. Use of the general field type is only relevant for advanced features. The arguments for the general field type are as follows: - - :: - - FIELD ID GENERAL FILE_GENERATED_BY_ENKF FILE_LOADED_BY_ENKF - - The OPTIONS argument is the same as for the parameter field. - -.. _gen_data: -.. topic:: GEN_DATA - - The GEN_DATA keyword is used when estimating data types which enkf does not know anything about. GEN_DATA is very similar to GEN_PARAM, but GEN_DATA is used for data which are updated/created by the forward model like e.g. seismic data. In the main configuration file the input for a GEN_DATA instance is as follows: - - :: - - GEN_DATA ID RESULT_FILE:yyy INPUT_FORMAT:xx REPORT_STEPS:10,20 ECL_FILE:xxx OUTPUT_FORMAT:xx INIT_FILES:/path/files%d TEMPLATE:/template_file TEMPLATE_KEY:magic_string - - The GEN_DATA keyword has many options; in many cases you can leave many of them off. We therefor list the required and the optional options separately: - - **Required GEN_DATA options** - - * RESULT_FILE - This if the name the file generated by the forward model and read by ERT. This filename _must_ have a %d as part of the name, that %d will be replaced by report step when loading. - * INPUT_FORMAT - The format of the file written by the forward model (i.e. RESULT_FILE) and read by ERT, valid values are ASCII, BINARY_DOUBLE and BINARY_FLOAT. - * REPORT_STEPS A list of the report step(s) where you expect the forward model to create a result file. I.e. if the forward model should create a result file for report steps 50 and 100 this setting should be: REPORT_STEPS:50,100. If you have observations of this GEN_DATA data the RESTART setting of the corresponding GENERAL_OBSERVATION must match one of the values given by REPORT_STEPS. - - **Optional GEN_DATA options** - - * ECL_FILE - This is the name of file written by enkf to be read by the forward model. - * OUTPUT_FORMAT - The format of the files written by enkf and read by the forward model, valid values are ASCII, BINARY_DOUBLE, BINARY_FLOAT and ASCII_TEMPLATE. If you use ASCII_TEMPLATE you must also supply values for TEMPLATE and TEMPLATE_KEY. - * INIT_FILES - Format string with '%d' of files to load the initial data from. - - *Example:* - - :: - - GEN_DATA 4DWOC INPUT_FORMAT:ASCII RESULT_FILE:SimulatedWOC%d.txt REPORT_STEPS:10,100 - - Here we introduce a GEN_DATA instance with name 4DWOC. When the forward model has run it should create two files with name SimulatedWOC10.txt and SimulatedWOC100.txt. The result files are in ASCII format, ERT will look for these files and load the content. The files should be pure numbers - without any header. - - **Observe that the GEN_DATA RESULT_FILE setting must have a %d format specifier, that will be replaced with the report step..** - - -.. _custom_kw: -.. topic:: CUSTOM_KW - - The keyword CUSTOM_KW enables custom data key:value pairs - to be stored in ERT storage. Custom KW has many - similarities to Gen KW and Gen Data but is fully defined by - the user and contain only key_value pairs. - - *Example:* - - :: - - CUSTOM_KW GROUP_NAME - - --GROUP_NAME - This is similar to Gen KW where every keyword is prefixed with the GROUP_NAME like this: GROUP_NAME:KEYWORD - - --input_file - This is the input file expected to be generated by a forward model. - - --Example - CUSTOM_KW COMPOSITION composition.txt - - With this setup ERT will expect the file composition.txt to be present in the runpath. - This file may look like this - - :: - - oil 0.5 - water 0.2 - gas 0.2 - unknown 0.1 - state good - - Every key-value pair must be a string followed by a space and a value. - The value can either be a number or a string (all numbers are interpreted as floats). - - After a successful run, ERT will store the COMPOSITION - Custom KW in its filesystem and will be available for every - realization. An export will present the values produced as: - - * COMPOSITION:oil - * COMPOSITION:water - * COMPOSITION:gas - * COMPOSITION:unknown - * COMPOSITION:state - - -.. _gen_kw: -.. topic:: GEN_KW - - The GEN_KW (abbreviation of general keyword) parameter is based on a template file and substitution. In the main config file a GEN_KW instance is defined as follows: - - :: - - GEN_KW ID my_template.txt my_eclipse_include.txt my_priors.txt - - Here ID is an (arbitrary) unique string, my_template.txt is - the name of a template file, my_eclipse_include.txt is the - name of the file which is made for each member based on - my_template.txt and my_priors.txt is a file containing a list - of parametrized keywords and a prior distribution for - each. Note that you must manually edit the ECLIPSE data file - so that my_eclipse_include.txt is included. - - Let us consider an example where the GEN_KW parameter type is - used to estimate pore volume multipliers. We would then - declare a GEN_KW instance in the main enkf configuration file: - - :: - - GEN_KW PAR_MULTPV multpv_template.txt multpv.txt multpv_priors.txt - - In the GRID or EDIT section of the ECLIPSE data file, we would - insert the following include statement: - - :: - - INCLUDE - 'multpv.txt' / - - The template file multpv_template.txt would contain some - parametrized ECLIPSE statements: - - :: - - BOX - 1 10 1 30 13 13 / - MULTPV - 300* / - ENDBOX - - BOX - 1 10 1 30 14 14 / - MULTPV - 300* / - ENDBOX - - Here, and will act as magic - strings. Note that the '<' '>' must be present around the - magic strings. In this case, the parameter configuration file - multpv_priors.txt could look like this: - - :: - - MULTPV_BOX2 UNIFORM 0.98 1.03 - MULTPV_BOX1 UNIFORM 0.85 1.00 - - In general, the first keyword on each line in the parameter - configuration file defines a key, which when found in the - template file enclosed in '<' and '>', is replaced with a - value. The rest of the line defines a prior distribution for - the key. See Prior distributions available in enkf for a list - of available prior distributions. - - **Example: Using GEN_KW to estimate fault transmissibility multipliers** - - Previously enkf supported a datatype MULTFLT for estimating - fault transmissibility multipliers. This has now been - depreceated, as the functionality can be easily achieved with - the help of GEN_KW. In th enkf config file: - - :: - - GEN_KW MY-FAULTS MULTFLT.tmpl MULTFLT.INC MULTFLT.txt - - Here MY-FAULTS is the (arbitrary) key assigned to the fault - multiplers, MULTFLT.tmpl is the template file, which can look - like this: - - :: - - MULTFLT - 'FAULT1' / - 'FAULT2' / - / - - and finally the initial distribution of the parameters FAULT1 - and FAULT2 are defined in the file MULTFLT.txt: - - :: - - FAULT1 LOGUNIF 0.00001 0.1 - FAULT2 UNIFORM 0.00 1.0 - - The various prior distributions available for the ``GEN_KW`` - keyword are here :ref:`prior distributions available in ERT ` - - - Loading GEN_KW values from an external file - - The default use of the GEN_KW keyword is to let the ERT - application sample random values for the elements in the - GEN_KW instance, but it is also possible to tell ERT to load a - precreated set of data files, this can for instance be used as - a component in a experimental design based workflow. When - using external files to initialize the GEN_KW instances you - supply an extra keyword ``INIT_FILE:/path/to/priors/files%d`` - which tells where the prior files are: - - :: - - GEN_KW MY-FAULTS MULTFLT.tmpl MULTFLT.INC MULTFLT.txt INIT_FILES:priors/multflt/faults%d - - In the example above you must prepare files - priors/multflt/faults0, priors/multflt/faults1, - ... priors/multflt/faultsn which ert will load when you - initialize the case. The format of the GEN_KW input files can - be of two varieties: - - 1. The files can be plain ASCII text files with a list of numbers: - - :: - - 1.25 - 2.67 - - The numbers will be assigned to parameters in the order found in the MULTFLT.txt file. - - 2. Alternatively values and keywords can be interleaved as in: - - :: - - FAULT1 1.25 - FAULT2 2.56 - - in this case the ordering can differ in the init files and the parameter file. - - The heritage of the ERT program is based on the EnKF algorithm, and the EnKF algorithm evolves around Gaussian variables - internally the GEN_KW variables are assumed to be samples from the N(0,1) distribution, and the distributions specified in the parameters file are based on transformations starting with a N(0,1) distributed variable. The slightly awkward consequence of this is that to let your sampled values pass through ERT unmodified you must configure the distribution NORMAL 0 1 in the parameter file; alternatively if you do not intend to update the GEN_KW variable you can use the distribution RAW. - - -.. _gen_param: -.. topic:: GEN_PARAM - - The GEN_PARAM parameter type is used to estimate parameters which do not really fit into any of the other categories. As an example, consider the following situation: - - Some external Software (e.g. Cohiba) makes a large vector of random numbers which will serve as input to the forward model. (It is no requirement that the parameter set is large, but if it only consists of a few parameters the GEN_KW type will be easier to use.) - We want to update this parameter with enkf. - In the main configuration file the input for a GEN_PARAM instance is as follows: - - :: - - GEN_PARAM ID ECLIPSE_FILE INPUT_FORMAT:xx OUTPUT_FORMAT:xx INIT_FILES:/path/to/init/files%d (TEMPLATE:/template_file KEY:magic_string) - - here ID is the usual unique string identifying this instance and ECLIPSE_FILE is the name of the file which is written into the run directories. The three arguments GEN_PARAM, ID and ECLIPSE_FILE must be the three first arguments. In addition you must have three additional arguments, INPUT_FORMAT, OUTPUT_FORMAT and INIT_FILES. INPUT_FORMAT is the format of the files enkf should load to initialize, and OUTPUT_FORMAT is the format of the files enkf writes for the forward model. The valid values are: - - * ASCII - This is just text file with formatted numbers. - * ASCII_TEMPLATE - An plain text file with formatted numbers, and an arbitrary header/footer. - * BINARY_FLOAT - A vector of binary float numbers. - * BINARY_DOUBLE - A vector of binary double numbers. - - Regarding the different formats - observe the following: - - #. Except the format ASCII_TEMPLATE the files contain no header information. - #. The format ASCII_TEMPLATE can only be used as output format. - #. If you use the output format ASCII_TEMPLATE you must also supply a TEMPLATE:X and KEY:Y option. See documentation of this below. - #. For the binary formats files generated by Fortran can not be used - can easily be supported on request. - - **Regarding templates:** If you use OUTPUT_FORMAT:ASCII_TEMPLATE you must also supply the arguments TEMPLATE:/template/file and KEY:MaGiCKEY. The template file is an arbitrary existing text file, and KEY is a magic string found in this file. When enkf is running the magic string is replaced with parameter data when the ECLIPSE_FILE is written to the directory where the simulation is run from. Consider for example the follwing configuration: - - :: - - TEMPLATE:/some/file KEY:Magic123 - - The template file can look like this (only the Magic123 is special): - - :: - - Header line1 - Header line2 - ============ - Magic123 - ============ - Footer line1 - Footer line2 - - When enkf is running the string Magic123 is replaced with parameter values, and the resulting file will look like this: - - :: - - Header line1 - Header line2 - ============ - 1.6723 - 5.9731 - 4.8881 - ..... - ============ - Footer line1 - Footer line2 - -.. _surface: -.. topic:: SURFACE - - The SURFACE keyword can be used to work with surface from RMS in the irap format. The surface keyword is configured like this: - - :: - - SURFACE TOP OUTPUT_FILE:surf.irap INIT_FILES:Surfaces/surf%d.irap BASE_SURFACE:Surfaces/surf0.irap - - The first argument, TOP in the example above, is the identifier you want to use for this surface in ert. The OUTPUT_FILE key is the name of surface file which ERT will generate for you, INIT_FILES points to a list of files which are used to initialize, and BASE_SURFACE must point to one existing surface file. When loading the surfaces ERT will check that all the headers are compatible. An example of a surface IRAP file is: - - :: - - -996 511 50.000000 50.000000 - 444229.9688 457179.9688 6809537.0000 6835037.0000 - 260 -30.0000 444229.9688 6809537.0000 - 0 0 0 0 0 0 0 - 2735.7461 2734.8909 2736.9705 2737.4048 2736.2539 2737.0122 - 2740.2644 2738.4014 2735.3770 2735.7327 2733.4944 2731.6448 - 2731.5454 2731.4810 2730.4644 2730.5591 2729.8997 2726.2217 - 2721.0996 2716.5913 2711.4338 2707.7791 2705.4504 2701.9187 - .... - - The surface data will typically be fed into other programs like Cohiba or RMS. The data can be updated using e.g. the Smoother. - - **Initializing from the FORWARD MODEL** - - All the parameter types like FIELD,GEN_KW,GEN_PARAM and SURFACE can be initialized from the forward model. To achieve this you just add the setting FORWARD_INIT:True to the configuration. When using forward init the initialization will work like this: - - #. The explicit initialization from the case menu, or when you start a simulation, will be ignored. - #. When the FORWARD_MODEL is complete ERT will try to initialize the node based on files created by the forward model. If the init fails the job as a whole will fail. - #. If a node has been initialized, it will not be initialized again if you run again. [Should be possible to force this ....] - - When using FORWARD_INIT:True ERT will consider the INIT_FILES setting to find which file to initialize from. If the INIT_FILES setting contains a relative filename, it will be interpreted relativt to the runpath directory. In the example below we assume that RMS has created a file petro.grdecl which contains both the PERMX and the PORO fields in grdecl format; we wish to initialize PERMX and PORO nodes from these files: - - :: - - FIELD PORO PARAMETER poro.grdecl INIT_FILES:petro.grdecl FORWARD_INIT:True - FIELD PERMX PARAMETER permx.grdecl INIT_FILES:petro.grdecl FORWARD_INIT:True - - Observe that forward model has created the file petro.grdecl and the nodes PORO and PERMX create the ECLIPSE input files poro.grdecl and permx.grdecl, to ensure that ECLIPSE finds the input files poro.grdecl and permx.grdecl the forward model should contain a job which will copy/convert petro.grdecl -> (poro.grdecl,permx.grdecl), this job should not overwrite existing versions of permx.grdecl and poro.grdecl. This extra hoops is not strictly needed in all cases, but strongly recommended to ensure that you have control over which data is used, and that everything is consistent in the case where the forward model is run again. - - -.. _summary: -.. topic:: SUMMARY - - The SUMMARY keyword is used to add variables from the ECLIPSE summary file to the parametrization. The keyword expects a string, which should have the format VAR:WGRNAME. Here, VAR should be a quantity, such as WOPR, WGOR, RPR or GWCT. Moreover, WGRNAME should refer to a well, group or region. If it is a field property, such as FOPT, WGRNAME need not be set to FIELD. - - *Example:* - - :: - - -- Using the SUMMARY keyword to add diagnostic variables - SUMMARY WOPR:MY_WELL - SUMMARY RPR:8 - SUMMARY F* -- Use of wildcards requires that you have entered a REFCASE. - - The SUMMARY keyword has limited support for '*' wildcards, if your key contains one or more '*' characters all matching variables from the refcase are selected. Observe that if your summary key contains wildcards you must supply a refcase with the REFCASE key - otherwise it will fail hard. - - **Note:** Properties added using the SUMMARY keyword are only diagnostic. I.e., they have no effect on the sensitivity analysis or history match. - - -Keywords controlling the ES algorithm ------------------------------------------ -.. _keywords_controlling_the_es_algorithm: - -.. _enkf_alpha: -.. topic:: ENKF_ALPHA - -See the sub keyword :code:`OVERLAP_LIMIT` under the :code:`UPDATE_SETTINGS`keyword. - -.. _enkf_bootstrap: -.. topic:: ENKF_BOOTSTRAP - - Boolean specifying if we want to resample the Kalman gain matrix in the update step. The purpose is to avoid that the ensemble covariance collapses. When this keyword is true each ensemble member will be updated based on a Kalman gain matrix estimated from a resampling with replacement of the full ensemble. - - In theory and in practice this has worked well when one uses a small number of ensemble members. - - -.. _enkf_cv_folds: -.. topic:: ENKF_CV_FOLDS - - Integer specifying how many folds we should use in the Cross-Validation (CV) scheme. Possible choices are the integers between 2 and the ensemble size (2-fold CV and leave-one-out CV respectively). However, a robust choice for the number of CV-folds is 5 or 10 (depending on the ensemble size). - - *Example:* - - :: - - -- Setting the number of CV folds equal to 5 - ENKF_CV_FOLDS 5 - - Requires that the ENKF_LOCAL_CV keyword is set to TRUE - - -.. _enkf_force_ncomp: -.. topic:: ENKF_FORCE_NCOMP - - Bool specifying if we want to force the subspace dimension we want to use in the EnKF updating scheme (SVD-based) to a specific integer. This is an alternative to selecting the dimension using ENKF_TRUNCATION or ENKF_LOCAL_CV. - - *Example:* - - :: - - -- Setting the the subspace dimension to 2 - ENKF_FORCE_NCOMP TRUE - ENKF_NCOMP 2 - - - -.. _enkf_local_cv: -.. topic:: ENKF_LOCAL_CV - - Boolean specifying if we want to select the subspace dimension in the SVD-based EnKF algorithm using Cross-Validation (CV) [1]. This is a more robust alternative to selecting the subspace dimension based on the estimated singular values (See ENKF_TRUNCATION), because the predictive power of the estimated Kalman gain matrix is taken into account. - - *Example:* - - :: - - -- Select the subspace dimension using Cross-Validation - ENKF_LOCAL_CV TRUE - - - -.. _enkf_pen_press: -.. topic:: ENKF_PEN_PRESS - - Boolean specifying if we want to select the subspace dimension in the SVD-based EnKF algorithm using Cross-Validation (CV), and a penalised version of the predictive error sum of squares (PRESS) statistic [2]. This is recommended when overfitting is a severe problem (and when the number of ensemble members is small) - - *Example:* - - :: - - -- Select the subspace dimension using Cross-Validation - ENKF_LOCAL_CV TRUE - - -- Using penalised PRESS statistic - ENKF_PEN_PRESS TRUE - - - -.. _enkf_mode: -.. topic:: ENKF_MODE - - The ENKF_MODE keyword is used to select which EnKF algorithm to use. Use the value STANDARD for the original EnKF algorithm, or SQRT for the so-called square root scheme. The default value for ENKF_MODE is STANDARD. - - *Example A:* - - :: - - -- Using the square root update - ENKF_MODE SQRT - - *Example B:* - - :: - - -- Using the standard update - ENKF_MODE STANDARD - - The ENKF_MODE keyword is optional. - - -.. _enkf_merge_observations: -.. topic:: ENKF_MERGE_OBSERVATIONS - - If you use the ENKF_SCHED_FILE option to jump over several dates at a time you can choose whether you want to use all the observations in between, or just the final. If set to TRUE, all observations will be used. If set to FALSE, only the final observation is used. The default value for ENKF_MERGE_OBSERVATIONS is FALSE. - - *Example:* - - :: - - -- Merge observations - ENKF_MERGE_OBSERVATIONS TRUE - - -.. _enkf_ncomp: -.. topic:: ENKF_NCOMP - - Integer specifying the subspace dimension. Requires that ENKF_FORCE_NCOMP is TRUE. - -.. _enkf_rerun: -.. topic:: ENKF_RERUN - - This is a boolean switch - TRUE or FALSE. Should the simulation start from time zero after each update. - - - -.. _enkf_scaling: -.. topic:: ENKF_SCALING - - This is a boolean switch - TRUE (Default) or FALSE. If TRUE, we scale the data ensemble matrix to unit variance. This is generally recommended because the SVD-based EnKF algorithm is not scale invariant. - - -.. _enkf_truncation: -.. topic:: ENKF_TRUNCATION - - Truncation factor for the SVD-based EnKF algorithm (see Evensen, 2007). In this algorithm, the forecasted data will be projected into a low dimensional subspace before assimilation. This can substantially improve on the results obtained with the EnKF, especially if the data ensemble matrix is highly collinear (Saetrom and Omre, 2010). The subspace dimension, p, is selected such that - - :: - - \frac{\sum_{i=1}^{p} s_i^2}{\sum_{i=1}^r s_i^2} \geq \mathrm{ENKF\_TRUNCATION}, - - where si is the ith singular value of the centered data ensemble matrix and r is the rank of this matrix. This criterion is similar to the explained variance criterion used in Principal Component Analysis (see e.g. Mardia et al. 1979). - - The default value of ENKF_TRUNCATION is 0.99. If ensemble collapse is a big problem, a smaller value should be used (e.g 0.90 or smaller). However, this does not guarantee that the problem of ensemble collapse will disappear. Note that setting the truncation factor to 1.00, will recover the Standard-EnKF algorithm if and only if the covariance matrix for the observation errors is proportional to the identity matrix. - - -.. _std_scale_correlated_obs: -.. topic:: STD_SCALE_CORRELATED_OBS - - With this kewyord you can instruct ERT to use the simulated - data to estimate the correlations in the observations, and - then inflate the observation standard deviation as a way to - estimate the real information content in the observations. The - method is based on PCA, the scaling factor is calculated as: - - :: - - \sqrt{\frac{N_{\sigma}}{N_{\mathrm{obs}}} - - where $N_{\sigma}$ is the number of singular components, at - (fixed) truncation 0.95 and $N_{\mathrm{obs}}$ is the number - of observations. The STD_SCALE_CORRELATED_OBS keyword will - flatten all your observations, including temporal and spatial - correlations. For more fine grained control you can use the - STD_CALE_CORRELATED_OBS workflow job, or even write your own - plugins. - - - -.. _update_log_path: -.. topic:: UPDATE_LOG_PATH - - A summary of the data used for updates are stored in this directory. - - -**References** - -* Evensen, G. (2007). "Data Assimilation, the Ensemble Kalman Filter", Springer. -* Mardia, K. V., Kent, J. T. and Bibby, J. M. (1979). "Multivariate Analysis", Academic Press. -* Saetrom, J. and Omre, H. (2010). "Ensemble Kalman filtering with shrinkage regression techniques", Computational Geosciences (online first). - - -Analysis module ---------------- -.. _analysis_module: - -The final EnKF linear algebra is performed in an analysis module. The keywords to load, select and modify the analysis modules are documented here. - -.. _analysis_load: -.. topic:: ANALYSIS_LOAD - - The ANALYSIS_LOAD key is the main key to load an analysis module: - - :: - - ANALYSIS_LOAD ANAME analysis.so - - The first argument ANAME is just an arbitrary unique name which you want to use to refer to the module later. The second argument is the name of the shared library file implementing the module, this can either be an absolute path as /path/to/my/module/ana.so or a relative file name as analysis.so. The module is loaded with dlopen() and the normal shared library search semantics applies. - - -.. _analysis_select: -.. topic:: ANALYSIS_SELECT - - This command is used to select which analysis module to actually use in the updates: - - :: - - ANALYSIS_SELECT ANAME - - Here ANAME is the name you have assigned to the module when loading it with ANALYSIS_LOAD. - - -.. _analysis_set_var: -.. topic:: ANALYSIS_SET_VAR - - The analysis modules can have internal state, like e.g. truncation cutoff values, these values can be manipulated from the config file using the ANALYSIS_SET_VAR keyword: - - :: - - ANALYSIS_SET_VAR ANAME ENKF_TRUNCATION 0.97 - - To use this you must know which variables the module supports setting this way. If you try to set an unknown variable you will get an error message on stderr. - - -.. _analysis_copy: -.. topic:: ANALYSIS_COPY - - With the ANALYSIS_COPY keyword you can create a new instance of a module. This can be convenient if you want to run the same algorithm with the different settings: - - :: - - ANALYSIS_LOAD A1 analysis.so - ANALYISIS_COPY A1 A2 - - We load a module analysis.so and assign the name A1; then we copy A1 -> A2. The module A1 and A2 are now 100% identical. We then set the truncation to two different values: - - :: - - ANALYSIS_SET_VAR A1 ENKF_TRUNCATION 0.95 - ANALYSIS_SET_VAR A2 ENKF_TRUNCATION 0.98 - -**Developing analysis modules** - -In the analysis module the update equations are formulated based on familiar matrix expressions, and no knowledge of the innards of the ERT program are required. Some more details of how modules work can be found here modules.txt. In principle a module is 'just' a shared library following some conventions, and if you are sufficiently savy with gcc you can build them manually, but along with the ert installation you should have utility script ert_module which can be used to build a module; just write ert_module without any arguments to get a brief usage description. - -Advanced optional keywords --------------------------- -.. _advanced_optional_keywords: - -The keywords in this section, controls advanced features of the enkf application. Insight in the internals of the enkf application and/or ECLIPSE may be required to fully understand their effect. Moreover, many of these keywords are defined in the site configuration, and thus optional to set for the user, but required when installing the enkf application at a new site. - - -.. _add_fixed_length_schedule_kw: -.. topic:: ADD_FIXED_LENGTH_SCHEDULE_KW - - Real low level fix for some SCHEDULE parsing problems. - - -.. _define: -.. topic:: DEFINE - - With the DEFINE keyword you can define key-value pairs which will be substituted in the rest of the configuration file. The DEFINE keyword expects two arguments: A key and a value to replace for that key. Later instances of the key enclosed in '<' and '>' will be substituted with the value. The value can consist of several strings, in that case they will be joined by one single space. - - *Example:* - - :: - - -- Define ECLIPSE_PATH and ECLIPSE_BASE - DEFINE ECLIPSE_PATH /path/to/eclipse/run - DEFINE ECLIPSE_BASE STATF02 - DEFINE KEY VALUE1 VALUE2 VALUE3 VALUE4 - - -- Set the GRID in terms of the ECLIPSE_PATH - -- and ECLIPSE_BASE keys. - GRID /.EGRID - - Observe that when you refer to the keys later in the config file they must be enclosed in '<' and '>'. Furthermore, a key-value pair must be defined in the config file before it can be used. The final key define above KEY, will be replaced with VALUE1 VALUE2 VALUE3 VALUE4 - i.e. the extra spaces will be discarded. - - -.. _time_map: -.. topic:: TIME_MAP - - Normally the mapping between report steps and true dates is - inferred by ERT indirectly by loading the ECLIPSE summary - files. In cases where you do not have any ECLIPSE summary - files you can use the TIME_MAP keyword to specify a file with - dates which are used to establish this mapping: - - *Example:* - - :: - - -- Load a list of dates from external file: "time_map.txt" - TIME_MAP time_map.txt - - The format of the TIME_MAP file should just be a list of dates - formatted as dd/mm/yyyy. The example file below has four dates: - - :: - - 01/01/2000 - 01/07/2000 - 01/01/2001 - 01/07/2001 - - - -.. _schedule_prediction_file: -.. topic:: SCHEDULE_PREDICTION_FILE - - This is the name of a schedule prediction file. It can contain %d to get different files for different members. Observe that the ECLIPSE datafile should include only one schedule file, even if you are doing predictions. - - -Keywords related to running the forward model ---------------------------------------------- -.. _keywords_related_to_running_the_forward_model: - - - -.. _forward_model: -.. topic:: FORWARD_MODEL - - The FORWARD_MODEL keyword is used to define how the simulations are executed. E.g., which version of ECLIPSE to use, which rel.perm script to run, which rock physics model to use etc. Jobs (i.e. programs and scripts) that are to be used in the FORWARD_MODEL keyword must be defined using the INSTALL_JOB keyword. A set of default jobs are available, and by default FORWARD_MODEL takes the value ECLIPSE100. - - The FORWARD_MODEL keyword expects a series of keywords, each defined with INSTALL_JOB. The enkf will execute the jobs in sequentially in the order they are entered. Note that the ENKF_SCHED_FILE keyword can be used to change the FORWARD_MODEL for sub-sequences of the run. - - *Example A:* - - :: - - -- Suppose that "MY_RELPERM_SCRIPT" has been defined with - -- the INSTALL_JOB keyword. This FORWARD_MODEL will execute - -- "MY_RELPERM_SCRIPT" before ECLIPSE100. - FORWARD_MODEL MY_RELPERM_SCRIPT ECLIPSE100 - - *Example B:* - - :: - - -- Suppose that "MY_RELPERM_SCRIPT" and "MY_ROCK_PHYSICS_MODEL" - -- has been defined with the INSTALL_JOB keyword. - -- This FORWARD_MODEL will execute "MY_RELPERM_SCRIPT", then - -- "ECLIPSE100" and in the end "MY_ROCK_PHYSICS_MODEL". - FORWARD_MODEL MY_RELPERM_SCRIPT ECLIPSE100 MY_ROCK_PHYSICS_MODEL - - For advanced jobs you can pass string arguments to the job using a KEY=VALUE based approach, this is further described in: passing arguments. In available jobs in enkf you can see a list of the jobs which are available. - - -.. _job_script: -.. topic:: JOB_SCRIPT - - Running the forward model from enkf is a multi-level process which can be summarized as follows: - - #. A Python module called jobs.py is written and stored in the directory where the forward simulation is run. The jobs.py module contains a list of job-elements, where each element is a Python representation of the code entered when installing the job. - #. The enkf application submits a Python script to the enkf queue system, this script then loads the jobs.py module to find out which programs to run, and how to run them. - #. The job_script starts and monitors the individual jobs in the jobs.py module. - - The JOB_SCRIPT variable should point at the Python script which is managing the forward model. This should normally be set in the site wide configuration file. - - -.. _queue_system: -.. topic:: QUEUE_SYSTEM - - The keyword QUEUE_SYSTEM can be used to control where the - simulation jobs are executed. It can take the values LSF, - TORQUE, RSH and LOCAL. - - The LSF option will submit jobs to the LSF cluster at your - location, and is recommended whenever LSF is available. - - The TORQUE option will submit jobs to the TORQUE a torque - based system, using the commands qsub, qstat etc., if - available. - - If you do not have access to LSF or TORQUE you can submit to - your local workstation using the LOCAL option and to homemade - cluster of workstations using the RSH option. All of the queue - systems can be further configured, see separate sections. - - *Example:* - - :: - - -- Tell ert to use the LSF cluster. - QUEUE_SYSTEM LSF - - The QUEUE_SYSTEM keyword is optional, and usually defaults to - LSF (this is site dependent). - -Configuring LSF access ----------------------- -.. _configuring_lsf_access: - -The LSF system is the most useful of the queue alternatives, and also -the alternative with most options. The most important options are -related to how ert should submit jobs to the LSF system. Essentially -there are two methods ert can use when submitting jobs to the LSF -system: - -#. For workstations which have direct access to LSF ert can submit - directly with no further configuration. This is preferred solution, - but unfortunately not very common. -#. Alternatively ert can issue shell commands to bsub/bjobs/bkill to - submit jobs. These shell commands can be issued on the current - workstation, or alternatively on a remote workstation using ssh. - -The main switch between alternatives 1 and 2 above is the LSF_SERVER -option. - -.. _lsf_server: -.. topic:: LSF_SERVER - - By using the LSF_SERVER option you essentially tell ert two - things about how jobs should be submitted to LSF: - - #. You tell ert that jobs should be submitted using shell - commands. - #. You tell ert which server should be used when submitting - - So when your configuration file has the setting: - - :: - - LSF_SERVER be-grid01 - - ert will use ssh to submit your jobs using shell commands on - the server be-grid01. For this to work you must have - passwordless ssh to the server be-grid01. If you give the - special server name LOCAL ert will submit using shell commands - on the current workstation. - - **bsub/bjobs/bkill options** - - By default ert will use the shell commands bsub,bjobs and - bkill to interact with the queue system, i.e. whatever - binaries are first in your PATH will be used. For fine grained - control of the shell based submission you can tell ert which - programs to use: - - :: - - QUEUE_OPTION LSF BJOBS_CMD /path/to/my/bjobs - QUEUE_OPTION LSF BSUB_CMD /path/to/my/bsub - - *Example 1* - - :: - - LSF_SERVER be-grid01 - QUEUE_OPTION LSF BJOBS_CMD /path/to/my/bjobs - QUEUE_OPTION LSF BSUB_CMD /path/to/my/bsub - - In this example we tell ert to submit jobs from the - workstation be-grid01 using custom binaries for bsub and - bjobs. - - *Example 2* - - :: - - LSF_SERVER LOCAL - - In this example we will submit on the current workstation, - without using ssh first, and we will use the default bsub and - bjobs executables. The remaining LSF options apply - irrespective of which method has been used to submit the jobs. - - -.. _lsf_queue: -.. topic:: LSF_QUEUE - - The name of the LSF queue you are running ECLIPSE simulations in. - - -Configuring TORQUE access -------------------------- -.. _configuring_torque_access: - -The TORQUE system is the only available system on some clusters. The -most important options are related to how ert should submit jobs to -the TORQUE system. - -* Currently, the TORQUE option only works when the machine you are - logged into have direct access to the queue system. ert then submit - directly with no further configuration. - -The most basic invocation is in other words: - -:: - - QUEUE_SYSTEM TORQUE - -**qsub/qstat/qdel options** - -By default ert will use the shell commands qsub,qstat and qdel to -interact with the queue system, i.e. whatever binaries are first in -your PATH will be used. For fine grained control of the shell based -submission you can tell ert which programs to use: - -:: - - QUEUE_SYSTEM TORQUE - QUEUE_OPTION TORQUE QSUB_CMD /path/to/my/qsub - QUEUE_OPTION TORQUE QSTAT_CMD /path/to/my/qstat - QUEUE_OPTION TORQUE QDEL_CMD /path/to/my/qdel - -In this example we tell ert to submit jobs using custom binaries for -bsub and bjobs. - -**Name of queue** - -The name of the TORQUE queue you are running ECLIPSE simulations in. - -:: - - QUEUE_OPTION TORQUE QUEUE name_of_queue - -**Name of cluster (label)** - -The name of the TORQUE cluster you are running ECLIPSE simulations -in. This might be a label (serveral clusters), or a single one, as in -this example baloo. - -:: - - QUEUE_OPTION TORQUE CLUSTER_LABEL baloo - -**Max running jobs** - -The queue option MAX_RUNNING controls the maximum number of -simultaneous jobs submitted to the queue when using (in this case) the -TORQUE option in QUEUE_SYSTEM. - -:: - - QUEUE_SYSTEM TORQUE - -- Submit no more than 30 simultaneous jobs - -- to the TORQUE cluster. - QUEUE_OPTION TORQUE MAX_RUNNING 30 - -**Queue options controlling number of nodes and CPUs** - -When using TORQUE, you must specify how many nodes a single job is -should to use, and how many CPUs per node. The default setup in ert -will use one node and one CPU. These options are called NUM_NODES and -NUM_CPUS_PER_NODE. - -If the numbers specified is higher than supported by the cluster -(i.e. use 32 CPUs, but no node has more than 16), the job will not -start. - -If you wish to increase these number, the program running (typically -ECLIPSE) will usually also have to be told to correspondingly use more -processing units (keyword PARALLEL) - -:: - - QUEUE_SYSTEM TORQUE - -- Use more nodes and CPUs - -- in the TORQUE cluster per job submitted - -- This should (in theory) allow for 24 processing - -- units to be used by eg. ECLIPSE - QUEUE_OPTION TORQUE NUM_NODES 3 - QUEUE_OPTION TORQUE NUM_CPUS_PER_NODE 8 - -**Keep output from qsub** - -Sometimes the error messages from qsub can be useful, if something is -seriously wrong with the environment or setup. To keep this output -(stored in your home folder), use this: - -:: - - QUEUE_OPTION TORQUE KEEP_QSUB_OUTPUT 1 - - -** Slow submit to torque ** - -To be more gentle with the torqueue system you can instruct the driver -to sleep for every submit request. The argument to the SUBMIT_SLEEP is -the number of seconds to sleep for every submit, can be a fraction -like 0.5. - -:: - - QUEUE_OPTION TORQUE SUBMIT_SLEEP 0.25 - - -** Torque debug log ** - -You can ask the torqueu driver to store a debug log of the jobs -submitted, and the resulting job id. This is done with the queue -option DEBUG_OUTPUT: - -:: - - QUEUE_OPTION TORQUE DEBUG_OUTPUT torque_log.txt - - -Configuring the RSH queue -------------------------- -.. _configuring_the_rsh_queue: - -.. _rsh_host: -.. topic:: RSH_HOST - - You can run the forward model in enkf on workstations using remote-shell commands. To use the RSH queue system you must first set a list of computers which enkf can use for running jobs: - - :: - - RSH_HOST computer1:2 computer2:2 large_computer:8 - - Here you tell enkf that you can run on three different computers: computer1, computer2 and large_computer. The two first computers can accept two jobs from enkf, and the last can take eight jobs. Observe the following when using RSH: - - You must have passwordless login to the computers listed in RSH_HOST otherwise it will fail hard. enkf will not consider total load on the various computers; if have said it can take two jobs, it will get two jobs, irrespective of the existing load. - -.. _rsh_command: -.. topic:: RSH_COMMAND - - This is the name of the executable used to invoke remote shell operations. Will typically be either rsh or ssh. The command given to RSH_COMMAND must either be in PATH or an absolute path. - - :: - - MAX_RUNNING_RSH - - The keyword MAX_RUNNING_RSH controls the maximum number of simultaneous jobs running when using the RSH option in QUEUE_SYSTEM. It MAX_RUNNING_RSH exceeds the total capacity defined in RSH_HOST, it will automatically be truncated to that capacity. - - *Example:* - - :: - - -- No more than 10 simultaneous jobs - -- running via RSH. - MAX_RUNNING_RSH 10 - - - -Keywords related to plotting ----------------------------- -.. _keywords_related_to_plotting: - - -.. _plot_driver: -.. topic:: PLOT_DRIVER - - This is the name of the sub system used for creating plots. The default system is called 'PLPLOT' - all the other options regarding plotting are sub options which are only relevant when you are using PLPLOT. In addition to PLPLOT you can chose the value 'TEXT'; this will actually not produce any plots, just textfiles which can be used for plotting with your favorite plotting program. This is particularly relevant if you have some special requirements to the plots. - - -.. _plot_errorbar: -.. topic:: PLOT_ERRORBAR - - Should errorbars on the observations be plotted? - - -.. _plot_errorbar_max: -.. topic:: PLOT_ERRORBAR_MAX - - When plotting summary vectors for which observations have been 'installed' with the OBS_CONFIG keyword, ert will plot the observed values. If you have less than PLOT_ERRORBAR_MAX observations ert will use errorbars to show the observed values, otherwise it will use two dashed lines indicating +/- one standard deviation. This option is only meaningful when PLOT_PLOT_ERRORBAR is activated. - - To ensure that you always get errorbars you can set PLOT_ERRORBAR_MAX to a very large value, on the other hand setting PLOT_ERRORBAR_MAX to 0 will ensure that ert always plots observation uncertainty using dashed lines of +/- one standard deviation. - - The setting here will also affect the output when you are using the TEXT driver to plot. - - -.. _plot_height: -.. topic:: PLOT_HEIGHT - - When the PLPLOT driver creates a plot file, it will have the height (in pixels) given by the PLOT_HEIGHT keyword. The default value for PLOT_HEIGHT is 768 pixels. - - -.. _plot_refcase: -.. topic:: PLOT_REFCASE - - Boolean variable which is TRUE if you want to add the refcases to the plots. - - *Example:* - - :: - - PLOT_REFCASE TRUE - - - -.. refcase_list: -.. topic:: REFCASE_LIST - - Provide one or more Eclipse .DATA files for a refcase to be added in the plots. This refcase will be plotted in different colours. The summary files related to the refcase should be in the same folder as the refcase. - - *Example:* - - :: - - REFCASE_LIST /path/to/refcase1/file1.DATA /path/to/refcase2/file2.DATA - - - - - - -.. _plot_settings: -.. topic:: PLOT_SETTINGS - - The :code:`PLOT_SETTINGS` keyword is a "master keyword" which - can be used to configure some aspects of the plotting. These - settings will affect the default behaviour when you create a - new plot, you can still changes these settings interactively. - - When using the :code:`PLOT_SETTINGS` keyword you supply a - secondary keyword and a values as the tow arguments: - - :: - - PLOT_SETTINGS SHOW_REFCASE False - - Will make sure that your plots are created without the refcase - plotted as default. The available secondary keys are: - - SHOW_REFCASE : Default True - SHOW_HISTORY : Default True - - - - -.. _rft_config: -.. topic:: RFT_CONFIG - - RFT_CONFIGS argument is a file with the name of the rfts followed by date (day month year) Ex. - - :: - - RFT_CONFIG ../models/wells/rft/WELLNAME_AND_RFT_TIME.txt - - Where the contents of the file is something like - - :: - - be-linapp16(inmyr) -/models/wells/rft 34> more WELLNAME_AND_RFT_TIME.txt - A-1HP 06 05 1993 - A-9HW 31 07 1993 - C-1HP 11 12 2007 - C-5HP 21 12 1999 - C-6HR 09 11 1999 - D-4HP 10 07 2003 - K-3HW 09 02 2003 - K-6HW 08 11 2002 - K-7HW 21 04 2005 - D-6HP 22 04 2006 - - - -.. _rftpath: -.. topic:: RFTPATH - - - RFTPATHs argument is the path to where the rft-files are located - - :: - - RFTPATH ../models/wells/rft/ - - - - -.. _hook_workflow: -.. topic:: HOOK_WORKFLOW - -With the keyword :code:`HOOK_WORKFLOW` you can configure workflow -'hooks'; meaning workflows which will be run automatically at certain -points during ERTs execution. Currently there are four points in ERTs -flow of execution where you can hook in a workflow, before -the simulations start, :code:`PRE_SIMULATION`; after all the -simulations have completed :code:`POST_SIMULATION`; -before the update step, :code:`PRE_UPDATE` and after the update step, :code:`POST_UPDATE`. The -:code:`POST_SIMULATION` hook is typically used to trigger QC -workflows: - -:: - - HOOK_WORKFLOW initWFLOW PRE_SIMULATION - HOOK_WORKFLOW preUpdateWFLOW PRE_UPDATE - HOOK_WORKFLOW postUpdateWFLOW POST_UPDATE - HOOK_WORKFLOW QC_WFLOW1 POST_SIMULATION - HOOK_WORKFLOW QC_WFLOW2 POST_SIMULATION - - -In this example the workflow :code:`initWFLOW` will run after all -the simulation directories have been created, just before the forward -model is submitted to the queue. The workflow :code:`preUpdateWFLOW` will be run before the -update step and :code:`postUpdateWFLOW` will be run after the -update step. When all the simulations are complete -the two workflows :code:`QC_WFLOW1` and :code:`QC_WFLOW2` will be -run. - -Observe that the workflows being 'hooked in' with the -:code:`HOOK_WORKFLOW` must be loaded with the :code:`LOAD_WORKFLOW` -keyword. - -Currently, :code:`PRE_UPDATE` and :code:`POST_UPDATE` are only -available from python. - -Manipulating the Unix environment ---------------------------------- -.. _manipulating_the_unix_environment: - -The two keywords SETENV and UPDATE_PATH can be used to manipulate the Unix environment of the ERT process, tha manipulations only apply to the running ERT instance, and are not applied to the shell. - - -.. _setenv: -.. topic:: SETENV - - You can use the SETENV keyword to alter the unix environment enkf is running in. This is probably most relevant for setting up the environment for the external jobs invoked by enkf. - - *Example:* - - :: - - -- Setting up LSF - SETENV LSF_BINDIR /prog/LSF/7.0/linux2.6-glibc2.3-x86_64/bin - SETENV LSF_LIBDIR /prog/LSF/7.0/linux2.6-glibc2.3-x86_64/lib - SETENV LSF_UIDDIR /prog/LSF/7.0/linux2.6-glibc2.3-x86_64/lib/uid - SETENV LSF_SERVERDIR /prog/LSF/7.0/linux2.6-glibc2.3-x86_64/etc - SETENV LSF_ENVDIR /prog/LSF/conf - - Observe that the SETENV command is not as powerful as the corresponding shell utility. In particular you can not use $VAR to refer to the existing value of an environment variable. To add elements to the PATH variable it is easier to use the UPDATE_PATH keyword. - - -.. _update_path: -.. topic:: UPDATE_PATH - - The UPDATE_PATH keyword will prepend a new element to an existing PATH variable. I.e. the config - - :: - - UPDATE_PATH PATH /some/funky/path/bin - - will be equivalent to the shell command: - - :: - - setenv PATH /some/funky/path/bin:$PATH - - The whole thing is just a workaround because we can not use $PATH. - -.. _update_settings: -.. topic:: UPDATE_SETTINGS - -The :code:`UPDATE_SETTINGS` keyword is a *super-keyword* which can be -used to control parameters which apply to the Ensemble Smoother update -algorithm. The :code:`UPDATE_SETTINGS`currently supports the two -subkeywords: - - OVERLAP_LIMIT - Scaling factor used when detecting outliers. Increasing - this factor means that more observations will potentially be - included in the assimilation. The default value is 3.00.. - - Including outliers in the Smoother algorithm can dramatically - increase the coupling between the ensemble members. It is - therefore important to filter out these outlier data prior to - data assimilation. An observation, \textstyle d^o_i, will be - classified as an outlier if - - :: - - |d^o_i - \bar{d}_i| > \mathrm{ENKF\_ALPHA} \left(s_{d_i} + \sigma_{d^o_i}\right), - - where \textstyle\boldsymbol{d}^o is the vector of observed - data, \textstyle\boldsymbol{\bar{d}} is the average of the - forcasted data ensemble, \textstyle\boldsymbol{s_{d}} is the - vector of estimated standard deviations for the forcasted data - ensemble, and \textstyle\boldsymbol{s_{d}^o} is the vector - standard deviations for the observation error (specified a - priori). - - - STD_CUTOFF - If the ensemble variation for one particular measurment is - below this limit the observation will be deactivated. he - default value for this cutoff is 1e-6. - -Observe that for the updates many settings should be applied on the -analysis module in question. - - -.. _umask: -.. topic:: UMASK - - The `umask` is a concept used by Linux to controll the - permissions on newly created files. By default the files - created by ert will have the default permissions of your - account, but by using the keyword `UMASK` you can alter the - permissions of files created by ert. - - To determine the initial permissions on newly created files - start with the initial permissions `-rw-rw-rw-` (octal 0666) - for files and `-rwxrwxrwx` (octal 0777) for directories, and - then *~subtract* the current umask setting. So if you wish the - newly created files to have permissions `-rw-r-----` you need - to subtract write permissions for group and read and write - permissions for others - corresponding to `umask - 0026`. - - :: - - UMASK 0022 - - We remove write permissions from group and others, implying - that everyone can read the files and directories created by - ert, but only the owner can write to them. Also everyone can - execute the directories (i.e. list the content). - - :: - - UMASK 0 - - No permissions are removed, i.e. everyone can do everything - with the files and directories created by ert. - - The umask setting in ert is passed on to the forward model, - and should apply to the files/directories created by the - forward model also. However - the executables in the forward - model can in principle set it's own umask setting or alter - permissions in another way - so there is no guarantee that the - umask setting will apply to all files created by the forward - model. - - The octal permissions are based on three octal numbers for - owner, group and others, where each value is based on adding - the constants: - - 1: Execute permission - 2: Write permission - 4: Read permission - - So an octal permission of 0754 means: - - - Owner(7) can execute(1), write(2) and read(4). - - Group(5) can execute(1) and read(4). - - Others(2) can read(4) diff --git a/ThirdParty/Ert/docs/user/localization/index.rst b/ThirdParty/Ert/docs/user/localization/index.rst deleted file mode 100644 index 47ad720563..0000000000 --- a/ThirdParty/Ert/docs/user/localization/index.rst +++ /dev/null @@ -1,602 +0,0 @@ - -Keywords for the local configuration file -========================================= - - - -General overview ----------------- - -To create a configuration for localization you must "program" your own -local config commands by writing a Python script, and invoking it from a workflow. - - -**Local config python script example:** - -:: - - from ert.enkf import ErtScript - from ert.enkf import LocalConfig, LocalObsdata, LocalObsdataNode, LocalMinistep, LocalUpdateStep, LocalDataset, ActiveList - from ert.ecl import EclGrid, EclRegion, Ecl3DKW, EclFile, EclInitFile, EclKW, EclTypeEnum - - class LocalConfigJob(ErtScript): - - - def run(self): - - # This example can be used with the REEK data set from the ERT tutorial - - # Get the ert object - ert = self.ert() - - # Get local config object - local_config = ert.getLocalConfig() - - # Reset internal local config structure. From now you need to specify what to localize - local_config.clear() - - # There is only one update step - updatestep = local_config.getUpdatestep() - - # A ministep - ministep = local_config.createMinistep("MINISTEP" ) - - # Add some dataset you want to localize here. - dataset_multflt = local_config.createDataset("DATASET_MULTFLT") - - # Add some field and localize inside a box - data_poro = local_config.createDataset("DATA_PORO") - ecl_grid = local_config.getGrid() - ecl_region = EclRegion(ecl_grid, False) - ecl_region.select_box((0,0,0),(3,3,3)) - data_poro.addField("PORO", ecl_region) - - - # Add some index from MULTFLT to the dataset - dataset_multflt.addNode("MULTFLT") - active_list = dataset_multflt.getActiveList("MULTFLT") - active_list.addActiveIndex(0) - - # Add existing observations from WOPR:OP_1. Alternatively, use getObservations and filter the observations you want to use for this ministep. - obsdata_wopr = local_config.createObsdata("WOPR:OP_1_10") - for i in range(1,10): - obsdata_wopr.addNode("OBS"+str(i)) - - # Attach the created dataset and obsset to the ministep - ministep.attachDataset(dataset_multflt) - ministep.attachObsset(obsdata_wopr) - - # Then attach the ministep to the update step - updatestep.attachMinistep(ministep) - - # Write a .csv file for debugging. The generated file can be imported into Excel for better tabulation of the setup - local_config.writeSummaryFile("tmp/summary_local_config.csv") - -=========================================================================================== ============================================================================================================================================== -ERT script function Purpose -=========================================================================================== ============================================================================================================================================== -:ref:`getObservations ` Get the observations currently imported, use to filter the observations to localize -:ref:`getGrid ` Get the underlying grid use to define active cells in a field -:ref:`getUpdatestep ` Creates and gets default updatestep -:ref:`createMinistep ` Creates ministep -:ref:`createDataset ` Creates dataset -:ref:`copyDataset ` Deep copy of dataset -:ref:`createObsdata ` Creates observation set -:ref:`copyObsdata ` Deep copy of observation set -:ref:`attachMinistep ` Attaches ministep to update step -:ref:`attachDataset ` Attaches dataset to mini step -:ref:`attachObsset ` Attaches observation set to mini step -:ref:`addNode ` Adds data node to dataset -:ref:`del (data) ` Deletes observation node from dataset -:ref:`addNode, addNodeAndRange ` Adds observation node to observation set for all times or in a given time range -:ref:`del (obs) ` Deletes observation node from observation set -:ref:`clear ` Delete all the data keys from a dataset -:ref:`addActiveIndex (data) ` Adds several data indices to the list of active indices -:ref:`addActiveIndex (obs) ` Adds several observation indices to the list of active indices -:ref:`addField ` Adds field node to dataset -:ref:`EclGrid, EclInitFile ` Loads eclipse file in restart format -:ref:`EclRegion ` Creates a new region for use when defining active regions for fields -:ref:`select_active ` Selects or deselects cells in a region -:ref:`select_equal ` Selects or deselects cells in a region equal to given value -:ref:`select_less ` Selects or deselects cells in a region equal less than a given value -:ref:`select_more ` Selects or deselects cells in a region equal greater than a given value -:ref:`select_box ` Selects or deselects cells in a box -:ref:`select_islice, _jslice,_kslice ` Selects or deselects cells in a slice -:ref:`select_below_plane ` Selects or deselects cells in a half space defined by a plane -:ref:`select_inside_polygon ` Selects or deselects cells in region inside polygon -:ref:`Example create polygon ` Creates a geo-polygon based on coordinate list -:ref:`Example load polygon ` Loads polygon in Irap RMS format from file - -=========================================================================================== ============================================================================================================================================== - - -.. ########################################################################################################### - -.. _create_updatestep: -.. topic:: getUpdatestep - - | This function will create the default updatestep. - | Observe that you must get, otherwise it will not be able to do anything. - - *Example:* - - :: - - updatestep = local_config.getUpdatestep() - -.. ########################################################################################################### - -.. _all_obs: -.. topic:: getObservations - - | This function will retrieve ERT's observations - - *Example:* - - :: - - all_obs = local_config.getObservations() - -.. ########################################################################################################### - -.. _ert_grid: -.. topic:: getGrid - - | This function will retrieve ERT's grid - - *Example:* - - :: - - grid = local_config.getGrid() - -.. ########################################################################################################### - - -.. _create_ministep: -.. topic:: createMinistep - - | This function will create a new ministep with a given name and an optional analysis module. The default analysis module for this ministep is ERT's current analysis module. - | A given observation set can be attached to a given ministep with attachObsset.The ministep is then ready for adding data. Before the ministep can be used you must attach it to an updatestep with the attachMinistep command - - *Example:* - - :: - - ministep = local_config.createMinistep("MINISTEP") - - *Example:* - - :: - - analysis_config = ert.analysisConfig() - std_enkf_analysis_module = analysis_config.getModule("STD_ENKF") - ministep_using_std_enkf = local_config.createMinistep("MINISTEP", std_enkf_analysis_module) - - -.. ########################################################################################################### - -.. _create_dataset: -.. topic:: createDataset - - | This function will create a new dataset with a given name, i.e. a collection of enkf_nodes which should be updated together. Before you can actually use a dataset you must attach it to a ministep with the attachDataset command. - - - *Example:* - - :: - - dataset_multflt = local_config.createDataset("DATASET_MULTFLT") - -.. ########################################################################################################### - -.. _copy_dataset: -.. topic:: copyDataset - - | Will create a new local_obsset instance which is a copy of the - source dataset; this is a deep copy where also the lowest level active_list instances are copied, and can then subsequently be updated independently of each other. - - - *Example:* - - :: - - dataset_multflt_copy = local_config.copyDataset("DATASET_MULTFLT","DATASET_MULTFLT_COPY") - -.. ########################################################################################################### - -.. _create_obsset: -.. topic:: createObsdata - - | This function will create an observation set, i.e. a collection of observation keys which will be used as the observations in one ministep. Before the obsset can be used it must be attached to a ministep with the attachDataset command. - - - *Example:* - - :: - - obsset_obs_well = local_config.createObsdata("OBS_WELL") - - -.. ########################################################################################################### - -.. _copy_obsset: -.. topic:: copyObsdata - - | Will create a new local_obsset instance which is a copy of the - source dataset; this is a deep copy where also the lowest level active_list instances are copied, and can then subsequently be updated independently of each other. - - - *Example:* - - :: - - obsset_obs_well_copy = local_config.copyObsdata("OBS_WELL", "OBS_WELL_COPY") - -.. ########################################################################################################### - -.. _attach_ministep: -.. topic:: attachMinistep - - | This function will attach the ministep to the default updatestep. - - *Example:* - - :: - - update_step.attachMinistep(ministep) - - -.. ########################################################################################################### - -.. _attach_dataset: -.. topic:: attachDataset - - | Will attach the given dataset to the ministep. - - - *Example:* - - :: - - ministep.attachDataset(dataset_multflt) - - -.. ########################################################################################################### - -.. _attach_obsset: -.. topic:: attachObsset - - | Will attach the given obsset to the ministep. - - *Example:* - - :: - - ministep.attachObsset(obsset_obs_well) - - -.. ########################################################################################################### - -.. _add_data: -.. topic:: addNode - - | This function will add the data KEY as one enkf node which should be updated in this dataset. If you do not manipulate the KEY further with addActiveIndex, the KEY will be added as 'ALL_ACTIVE', i.e. all elements will be updated. - - - *Example:* - - :: - - dataset_multflt.addNode("MULTFLT") - -.. ########################################################################################################### - -.. _del_data: -.. topic:: del (data) - - | This function will delete the data 'KEY' from the dataset. - - - *Example:* - - :: - - del dataset_multflt["MULTFLT"] - - -.. ########################################################################################################### - -.. _add_obs: -.. topic:: addNode - - | This function will install the observation 'OBS_KEY' as an observation for this obsset - similarly to the addNode function. - - *Example:* - - :: - - -- The obsset has a time range - obsset_obs_well.addNodeAndRange("WOPR:OBS_WELL", 0, 1) - - -- All times are active - obsset_obs_well.addNode("WOPR:OBS_WELL") - - -.. ########################################################################################################### - -.. _del_obs: -.. topic:: del (obs) - - | This function will delete the obs 'OBS_KEY' from the obsset 'NAME_OF_OBSSET'. - - - *Example:* - - :: - - del obsset_obs_well["WOPR:OBS_WELL"] - - -.. ########################################################################################################### - -.. _dataset_del_all_data: -.. topic:: clear - - | This function will delete all the data keys from the dataset. - - *Example:* - - :: - - dataset_multflt.clear() - -.. ########################################################################################################### - -.. _active_list_add_data_index: -.. topic:: addActiveIndex (data) - - | This function will say that the data with name 'DATA_KEY' in dataset with name 'DATASTEP_NAME' should have the index 'INDEX' active. - - - *Example:* - - :: - - active_list = dataset_multflt.getActiveList("MULTFLT") - active_list.addActiveIndex(0); - -.. ########################################################################################################### - -.. _active_list_add_obs_index: -.. topic:: addActiveIndex (obs) - - | This function will say that the observation with name 'OBS_KEY' in obsset with name 'OBSSET_NAME' should have the index 'INDEX' active. - - *Example:* - - :: - - active_list = obsset_obs_well.getActiveList("WOPR:OBS_WELL") - active_list.addActiveIndex(0); - - -.. ########################################################################################################### - -.. _add_field: -.. topic:: addField - - | This function will install the node with name 'FIELD_NAME' in the dataset 'DATASET_NAME'. It will in addition select all the (currently) active cells in the region 'ECLREGION_NAME' as active for this field/ministep combination. The ADD_FIELD command is actually a shortcut of: ADD_DATA DATASET FIELD_NAME; followed by: ACTIVE_LIST_ADD_MANY_DATA_INDEX - - *Example:* - - :: - - # Load Eclipse grid - ecl_grid = EclGrid("path/to/LOCAL.GRDECL") - - with open("path/to/LOCAL.GRDECL","r") as fileH: - local_kw = Ecl3DKW.read_grdecl(ecl_grid, fileH, "LOCAL") - - # Define Eclipse region - eclreg_poro = EclRegion(ecl_grid, False) - eclreg_poro.select_more(local_kw, 1) - - # Create dataset and add field to dataset - data_poro = local_config.createDataset("DATA_PORO") - data_poro.addField("PORO", eclreg_poro) - - -.. ########################################################################################################### - -.. _load_file: -.. topic:: EclGrid, EclInitFile - - | This function will load an ECLIPSE file in restart format (i.e. restart file or INIT file), the keywords in this file can then subsequently be used in ECLREGION_SELECT_VALUE_XXX commands below. The 'KEY' argument is a string which will be used later when we refer to the content of this file. - - *Example:* - - :: - - # Load Eclipse grid and init file - ecl_grid = EclGrid("path/to/FULLMODEL.GRDECL") - refinit_file = EclInitFile(grid , "path/to/somefile.init") - -.. ########################################################################################################### - -.. _create_eclregion: -.. topic:: EclRegion - - | This function will create a new region 'ECLREGION_NAME', which can subsequently be used when defining active regions for fields. The second argument, SELECT_ALL, is a boolean value. If this value is set to true the region will start with all cells selected, if set to false the region will start with no cells selected. - - *Example:* - - :: - - # Define Eclipse region - eclreg_poro = EclRegion(ecl_grid, False) - -.. ########################################################################################################### - -.. _eclregion_select_all: -.. topic:: select_active - - | Will select all the cells in the region (or deselect if SELECT == FALSE). - - - *Example:* - - :: - - eclreg_poro.select_active() - - -.. ########################################################################################################### - -.. _eclregion_select_value_equal: -.. topic:: select_equal - - | This function will compare an ecl_kw instance loaded from file with a user supplied value, and select (or deselect) all cells which match this value. It is assumed that the ECLIPSE keyword is an INTEGER keyword, for float comparisons use the ECLREGION_SELECT_VALUE_LESS and ECLREGION_SELECT_VALUE_MORE functions. - - *Example:* - - :: - - # Load Eclipse grid - ecl_grid = EclGrid("path/to/LOCAL.GRDECL") - - with open("path/to/LOCAL.GRDECL","r") as fileH: - local_kw = Ecl3DKW.read_grdecl(ecl_grid, fileH, "LOCAL", ecl_type= EclTypeEnum.ECL_INT_TYPE) - - # Define Eclipse region - eclreg_poro = EclRegion(ecl_grid, False) - eclreg_poro.select_equal(local_kw, 1) - print 'GRID LOADED%s' % ecl_grid - print ecl_grid.getDims() - print local_kw.header - - - -.. ########################################################################################################### - -.. _eclregion_select_value_less: -.. topic:: select_less - - | This function will compare an ecl_kw instance loaded from disc with a numerical value, and select all cells which have numerical below the limiting value. The ecl_kw value should be a floating point value like e.g. PRESSURE or PORO. The arguments are just as for ECLREGION_SELECT_VALUE_EQUAL. - - *Example:* - - :: - - eclreg_poro.select_less(local_kw, 1) - - -.. ########################################################################################################### - -.. _eclregion_select_value_more: -.. topic:: select_more - - | This function will compare an ecl_kw instance loaded from disc with a numerical value, and select all cells which have numerical above the limiting value. The ecl_kw value should be a floating point value like e.g. PRESSURE or PORO. The arguments are just as for ECLREGION_SELECT_VALUE_EQUAL. - - - *Example:* - - :: - - eclreg_poro.select_more(local_kw, 1) - -.. ########################################################################################################### - -.. _eclregion_select_box: -.. topic:: select_box - - | This function will select (or deselect) all the cells in the box defined by the six coordinates i1 i2 j1 j2 k1 k2. The coordinates are inclusive, and the counting starts at 1. - - - *Example:* - - :: - - eclreg_poro.select_box((0,2,4),(1,3,5)) - - - -.. ########################################################################################################### - -.. _eclregion_select_slice: -.. topic:: select_islice, _jslice,_kslice - - | This function will select a slice in the direction given by 'dir', which can 'x', 'y' or 'z'. Depending on the value of 'dir' the numbers n1 and n2 are interpreted as (i1 i2), (j1 j2) or (k1 k2) respectively. The numbers n1 and n2 are inclusice and the counting starts at 1. It is OK to use very high/low values to imply "the rest of the cells" in one direction. - - - *Example:* - - :: - - eclreg_poro.select_kslice(2,3) - - -.. ########################################################################################################### - -.. _eclregion_select_plane: -.. topic:: select_below_plane - - | Will select all points which have positive (sign > 0) distance to the plane defined by normal vector n = (nx,ny,nz) and point p = (px,py,pz). If sign < 0 all cells with negative distance to plane will be selected. - - *Example:* - - :: - - eclreg_poro.select_below_plane((1,1,1),(0,0,0)) - - -.. ########################################################################################################### - -.. _eclregion_select_in_polygon: -.. topic:: select_inside_polygon - - | Well select all the points which are inside the polygon with name 'POLYGON_NAME'. The polygon should have been created with command CREATE_POLYGON or loaded with command 'LOAD_POLYGON' first. - - - - *Example:* - - :: - - polygon = [(0,0) , (0,1) , (1,0)] - eclreg_poro.select_inside_polygon(polygon) - -.. ########################################################################################################### - -.. _create_polygon: -.. topic:: Example create polygon - - | Will create a geo_polygon instance based on the coordinate list: (x1,y1), (x2,y2), (x3,y3), ... The polygon should not be explicitly closed - i.e. you should in general have (x1,y1) != (xn,yn). The polygon will be stored under the name 'POLYGON_NAME' - which should later be used when referring to the polygon in region select operations. - - - - *Example:* - - :: - - polygon = [(0,0) , (0,1) , (1,0)] - -.. ########################################################################################################### - -.. _load_polygon: -.. topic:: Example load polygon - - | Will load a polygon instance from the file 'FILENAME' - the file should be in irap RMS format. The polygon will be stored under the name 'POLYGON_NAME' which can then later be used to refer to the polygon for e.g. select operations. - - - *Example:* - - :: - - polygon = [] - with open("polygon.ply","r") as fileH: - for line in fileH.readlines(): - tmp = line.split() - polygon.append( (float(tmp[0]) , float(tmp[1]))) - - diff --git a/ThirdParty/Ert/docs/user/magic_strings/index.rst b/ThirdParty/Ert/docs/user/magic_strings/index.rst deleted file mode 100644 index 9252b0a1aa..0000000000 --- a/ThirdParty/Ert/docs/user/magic_strings/index.rst +++ /dev/null @@ -1,30 +0,0 @@ -.. _ert_magic_strings_full_doc: - -Magic Strings -=================================== - -Magic strings are special keywords that can be used in configuration files and templates which have special meanings. - -ERT Config ----------- - -These magic strings are available in the ERT config file. - -**** - -Inserts the config file name with extension into the config file. - -:: - - ENSPATH storage//ensemble - -If the config file is named *config.ert* then the resulting storage path will be: - -:: - - storage/config.ert/ensemble - - -**** - -Same as but inserts the config file name without the extension into the config file. diff --git a/ThirdParty/Ert/docs/user/observations/index.rst b/ThirdParty/Ert/docs/user/observations/index.rst deleted file mode 100644 index 47c019dafc..0000000000 --- a/ThirdParty/Ert/docs/user/observations/index.rst +++ /dev/null @@ -1,463 +0,0 @@ -Configuring observations for ERT -================================ - -General overview ----------------- - -When using ERT to condition on dynamic data, it is necessary to -specify which data to condition on. In particular, for a given piece -of data to condition on, the ERT application needs to know: - - - The actual measured value of the data. - - The uncertainty of the measured data. - - The time of measurement. - - How to simulate a response of the data given a parametrized ECLIPSE model. - - -To provide this observation to ERT, an observation file must be -created. The observation file is a plain text file, and is in essence -built around for different classes of observations and has an -associated keyword for each class: - - - Well or group rates from an existing ECLIPSE reference case: The - HISTORY_OBSERVATION keyword. - - - Well logs, RFTS and PLTs: The BLOCK_OBSERVATION keyword. - - - Separator tests, region pressures, etc.: The SUMMARY_OBSERVATION - keyword. - - - Exotic observations (e.g. data from 4D seismic): The - GENERAL_OBSERVATION keyword. - - -The HISTORY_OBSERVATION keyword -------------------------------- - -The keyword HISTORY_OBSERVATION is used to condition on observations -from the WCONHIST and WCONINJH keywords in schedule file provided to -the enkf project (or alternatively an ECLIPSE summary file if you have -changed the HISTORY_SOURCE keyword in the enkf project). The keyword -is typically used to condition on production and injection rates for -groups and wells, as well as bottom hole and tubing head pressures. An -observation entered with the HISTORY_OBSERVATION keyword will be -active at all report steps where data for the observation can be -found. - -In it's simplest form, a history observation is created as follows:: - - HISTORY_OBSERVATION WOPR:P1; - -This will condition on WOPR in well P1 using a default observation -error. The default observation error is a relative error of 10% to the -measurement with a minimum error of 0.10. See below on how explicitly -set the error. - -In general, to condition on variable VAR in well or group WGNAME, one -uses:: - - HISTORY_OBSERVATION VAR:WGNAME; - -Note that there must be a colon ":" between VAR and WGNAME and that -the statement shall end with a semi-colon ";". Thus, to condition on -WOPR, WWCT and WGOR in well C-17, and for the GOPR for the whole -field, one would add the following to the observation configuration:: - - HISTORY_OBSERVATION WOPR:C-17; - HISTORY_OBSERVATION WWCT:C-17; - HISTORY_OBSERVATION WGOR:C-17; - - HISTORY_OBSERVATION GOPR:FIELD; - -By default, the observation error is set to 10% of the observed value, -with a minimum of 0.10. It can be changed as follows:: - - HISTORY_OBSERVATION GOPR:FIELD - { - ERROR = 1000; - ERROR_MODE = ABS; - }; - -This will set the observation error to 1000 for all observations of -GOPR:FIELD. Note that both the items ERROR and ERROR_MODE as well as -the whole definition shall end with a semi-colon. - -The item ERROR_MODE can take three different values: ABS, REL or -RELMIN. If set to REL, all observation errors will be set to the -observed values multiplied by ERROR. Thus, the following will -condition on water injection rate for the whole field with 20% -observation uncertainity:: - - HISTORY_OBSERVATION GWIR:FIELD - { - ERROR = 0.20; - ERROR_MODE = REL; - }; - -If you do not want the observation error to drop below a given -threshold, say 100, you can use RELMIN and the keyword ERROR_MIN:: - - HISTORY_OBSERVATION GWIR:FIELD - { - ERROR = 0.20; - ERROR_MODE = RELMIN; - ERROR_MIN = 100; - }; - -Note that the configuration parser does not threat carriage return -different from space. Thus, the following statement is equivalent to -the previous:: - - HISTORY_OBSERVATION GWIR:FIELD { ERROR = 0.20; ERROR_MODE = RELMIN; ERROR_MIN = 100; }; - - -Also note that the special keyword include can be used to read an -external file. This can be very useful if you want to change the -standard configuration for a lot of observations in one go. For -example, consider the following code:: - - HISTORY_OBSERVATION WOPR:P1 { include "hist_obs_wells.txt"; }; - HISTORY_OBSERVATION WOPR:P2 { include "hist_obs_wells.txt"; }; - HISTORY_OBSERVATION WOPR:P3 { include "hist_obs_wells.txt"; }; - HISTORY_OBSERVATION WOPR:P4 { include "hist_obs_wells.txt"; }; - HISTORY_OBSERVATION WOPR:P5 { include "hist_obs_wells.txt"; }; - -Where the contents of the file hist_obs_wells.txt may be something -like:: - - ERROR_MODE = RELMIN; - ERROR = 0.25; - ERROR_MIN = 100; - -In this case, changing the file hist_obs_wells.txt will affect all of -the observations. - -Note that the keyword include can be used anywhere in the -configuration file. However, nested inclusion (use of include in a -file that has already been included with include) is not allowed. - -By default, an observation entered with the HISTORY_OBSERVATION -keyword will get the observed values, i.e. the 'true' values, from the -WCONHIST and WCONINJH keywords in the schedule file provided to the -ERT project. However it also possible to get the observed values from -a reference case. In that case you must set set HISTORY_SOURCE -variable in the ERT configuration file, see Creating a configuration -file for ERT. - -To change the observation error for a HISTORY_OBSERVATION for one or -more segments of the historic period, you can use the SEGMENT -keyword. For example:: - - HISTORY_OBSERVATION GWIR:FIELD - { - ERROR = 0.20; - ERROR_MODE = RELMIN; - ERROR_MIN = 100; - - SEGMENT FIRST_YEAR - { - START = 0; - STOP = 10; - ERROR = 0.50; - ERROR_MODE = REL; - }; - - SEGMENT SECOND_YEAR - { - START = 11; - STOP = 20; - ERRROR = 1000; - ERROR_MODE = ABS; - }; - }; - -The items START and STOP sets the start and stop of the segment in -terms of ECLIPSE restart steps. The keywords ERROR, ERROR_MODE and -ERROR_MIN behaves like before. If the segments overlap, they are -computed in alphabetical order. Error covariance for "merged" updates - -When merging the historical observations from several report steps -together in one update the different steps are not independent, and it -is beneficial to use a error covariance matrix, by using the keywords -AUTO_CORRF and AUTO_CORRF_PARAM ERT will automatically estimate a -error-covariance matrix based on the auto correlation function -specified by the AUTO_CORRF keyword, with the parameter given by the -AUTO_CORRF_PARAM parameter (i.e. the auto correlation length). The -currently available auto correlation functions are: - - EXP ~ exp(-x) - GAUSS ~ exp(-x*x/2) - -where the parameter x is given as: - - x = (t2 - t1) / AUTO_CORRF_PARAM - - -The SUMMARY_OBSERVATION keyword -------------------------------- - -The keyword SUMMARY_OBSERVATION can be used to condition on any -observation whos simulated value is written to the ECLIPSE summary -file, e.g. well rates, region properties, group and field rates etc. A -quite typical usage of SUMMARY_OBSERVATION is to condition on the -results of a separator test. - -Note: Although it is possible to condition on well and group rates -with SUMMARY_OBSERVATION, it is usually easier to use -HISTORY_OBSERVATION for this. - -In order to create a summary observation, four pieces of information -are needed: The observed value, the observation error, the time of -observation and a summary key. A typical summary observation is -created as follows:: - - SUMMARY_OBSERVATION SEP_TEST_2005 - { - VALUE = 100; - ERROR = 5; - DATE = 21/08/2005; - KEY = GOPR:BRENT; - }; - -This will create an observation of group oil production for the brent -group on 21th of august 2005. The observed value was 100 with a -standard deviation of 5. The name SEP_TEST_2005 will be used as a -label for the observation within the ERT and must be unique. - -Similarly to the name of a HISTORY_OBSERVATION, the item KEY in a -SUMMARY_OBSERVATION is used to look up the simulated value from the -summary file. And again, as when declaring a HISTORY_OBSERVATION, to -condition on VAR in well, group or region WGRNAME, one uses:: - - KEY = VAR:WGRNAME; - -For example, to condition on RPPW in region 8, one uses:: - - KEY = RPPW:8; - -It is also possible to give the observation time as a restart number -using the RESTART item or as time in days from simulation start using -the DAYS item. Here are two examples:: - - -- Giving the observation time in terms of restart number. - SUMMARY_OBSERVATION SEP_TEST_2005 - { - VALUE = 100; - ERROR = 5; - RESTART = 42; - KEY = GOPR:BRENT; - }; - - - -- Giving the observation time in terms of days - -- from simulation start. - SUMMARY_OBSERVATION SEP_TEST_2008 - { - VALUE = 213; - ERROR = 10; - DAYS = 911; - KEY = GOPR:NESS; - }; - - - -The BLOCK_OBSERVATION keyword ------------------------------- - -This is observations of variables in grid blocks/cells. The -observations can be of arbitrary ECLIPSE fields like PRESSURE -(typically for an RFT), PORO or PERM. A block observation is entered -with the BLOCK_OBSERVATION keyword. Here is an example of a typical -block observation:: - - BLOCK_OBSERVATION RFT_2006 - { - FIELD = PRESSURE; - DATE = 22/10/2006; - - OBS P1 { I = 1; J = 1; K = 1; VALUE = 100; ERROR = 5; }; - OBS P2 { I = 2; J = 2; K = 1; VALUE = 101; ERROR = 5; }; - OBS P3 { I = 2; J = 3; K = 1; VALUE = 102; ERROR = 5; }; - }; - -This will condition on observations of the pressure in grid blocks -(1,1,1), (2,2,1) and (2,3,1) on the 22/10/2006. - -By default the BLOCK_OBSERVATION requires that the specific field -which has been observed (e.g. PRESSURE in the example above) must have -been specified in main ERT configuration file using the FIELD keyword, -and ECLIPSE must be configured to produce a restart file for this -particular time. Alternatively it is possible to tell ERT to use the -summary vector as source of the data:: - - BLOCK_OBSERVATION RFT_2006 - { - FIELD = PRESSURE; - DATE = 22/10/2006; - SOURCE = SUMMARY; - - OBS P1 { I = 1; J = 1; K = 1; VALUE = 100; ERROR = 5; }; - OBS P2 { I = 2; J = 2; K = 1; VALUE = 101; ERROR = 5; }; - OBS P3 { I = 2; J = 3; K = 1; VALUE = 102; ERROR = 5; }; - }; - -In this case the data will be loaded from the BPR vectors in the -summary file. - -Note the use of the sub class OBS to specify the actUal observed -values, the observation errors and their grid location. Each OBS shall -have a unique key within the BLOCK_OBSERVATION instance, and is -required to have the items I, J, K, VALUE and ERROR. These are the -grid i,j and k indicies for the observation point, the observed value -and it's standard deviation. - -As with a SUMMARY_OBSERVATION, the observation time can be given as -either a date, days since simulation start or restart number. The -respective keys for setting giving it as date, days or restart number -are DATE, DAYS and RESTART. Note that each BLOCK_OBSERVATION instance -must have an unique global name (RFT_2006 in the example above). - -Block observations can often be quite long. Thus, it is often a good -idea to use the special keyword include in order to store the OBS -structures in a different file. This is done as follows:: - - BLOCK_OBSERVATION RFT_2006 - { - FIELD = PRESSURE; - RESTART = 20; - - include 'RFT_2006_OBS_DATA.txt'; - }; - -Where the file RFT_2006_OBS_DATA.txt contains the OBS instances:: - - OBS P1 { I = 1; J = 1; K = 1; VALUE = 100; ERROR = 5; }; - OBS P2 { I = 2; J = 2; K = 1; VALUE = 101; ERROR = 5; }; - OBS P3 { I = 2; J = 3; K = 1; VALUE = 112; ERROR = 5; }; - OBS P4 { I = 3; J = 3; K = 1; VALUE = 122; ERROR = 5; }; - OBS P5 { I = 4; J = 3; K = 1; VALUE = 112; ERROR = 5; }; - OBS P6 { I = 5; J = 3; K = 1; VALUE = 122; ERROR = 5; }; - - - -The GENERAL_OBSERVATION keyword --------------------------------- - -The GENERAL_OBSERVATION keyword is used together with the GEN_DATA and -GEN_PARAM type. This pair of observation and data types are typically -used when you want to update something special which does not fit into -any of the predefined enkf types. The ERT application just treats -GENERAL_OBSERVATION (and also GEN_DATA) as a range of number with no -particular structure, this is very flexible, but of course also a bit -more complex to use:: - - GENERAL_OBSERVATION GEN_OBS1{ - DATA = SOME_FIELD; - RESTART = 20; - OBS_FILE = some_file.txt; - }; - -This example a minimum GENERAL_OBSERVATION. The keyword DATA points to -the GEN_DATA instance this observation is 'observing', RESTART gives -the report step when this observation is active. OBS_FILE should be -the name of a file with observation values, and the corresponding -uncertainties. The file with observations should just be a plain text -file with numbers in it, observations and corresponding uncertainties -interleaved. An example of an OBS_FILE:: - - 1.46 0.26 - 25.0 5.0 - 5.00 1.00 - -This OBS_FILE has three observations: 1.46 +/- 0.26, 25.0 +/- 5.0 and -5.00 +/- 1.00. In the example above it is assumed that the DATA -instance we are observing (i.e. comparing with) has the same number of -elements as the observation, i.e. three in this case. By using the -keywords INDEX_LIST or INDEX_FILE you can select the elements of the -GEN_DATA instance you are interested in. Consider for example:: - - GENERAL_OBSERVATION GEN_OBS1{ - DATA = SOME_FIELD; - INDEX_LIST = 0,3,9; - RESTART = 20; - OBS_FILE = some_file.txt; - }; - -Here we use INDEX_LIST to indicate that we are interested in element -0,3 and 9 of the GEN_DATA instance:: - - GEN_DATA GEN_OBS1 - ======== =========== - 1.56 <---------------------> 1.46 0.26 - 23.0 /--------------> 25.0 5.00 - 56.0 | /---------> 5.00 1.00 - 27.0 <------/ | =========== - 0.2 | - 1.56 | - 1.78 | - 6.78 | - 9.00 | - 4.50 <-----------/ - ======== - -In addition to INDEX_LIST it is possible to use INDEX_FILE which -should just point at an plain text file with indexes (without any ',' -or anything). Finally, if your observation only has one value, you can -embed it in the config object with VALUE and ERROR. - -Matching GEN_OBS and GEN_DATA -............................. - -It is important to match up the GEN_OBS observations with the -corresponding GEN_DATA simulation data correctly. The GEN_DATA result -files must have an embedded '%d' to indicate the report step in them - -in the case of smoother based workflows the actual numerical value -here is not important. To ensure that GEN_OBS and corresponding -GEN_DATA values match up correctly only the RESTART method is allowed -for GEN_OBS when specifying the time. So consider a setup like this:: - - -- Config file: - GEN_DATA RFT_BH67 INPUT_FORMAT:ASCII RESULT_FILE:rft_BH67_%d REPORT_STEPS:20 - ... /|\ /|\ - ... | | - -- Observation file: | | - GENERAL_OBSERVATION GEN_OBS1{ +------------------/ - DATA = RFT_BH67; | - RESTART = 20; <------------------------------------/ - OBS_FILE = some_file.txt; - }; - -Here we see that the observation is active at report step 20, and we -expect the forward model to create a file rft_BH67_20 in each -realization directory. Error covariance - -The optional keyword ERROR_COVAR can be used to point to an existing -file, containing an error covariance matrix. The file should contain -the elements of the matrix as formatted numbers; newline formatting is -allowed but not necessary. Since the matrix should by construction be -symmetric there is no difference between column-major and row-major -order! The covariance matrix - - [ 1 0.75 -0.25] -C = [ 0.75 1.25 -0.50] - [-0.25 -0.50 0.85] - -Can be represented by the file:: - - 1 - 0.75 - -0.25 - 0.75 - 1.25 - -0.50 - -0.25 - -0.50 - 0.85 - -without newlines, or alternatively:: - - 1 0.75 -0.25 - 0.75 1.25 -0.50 - -0.25 -0.50 0.85 - -with newlines. diff --git a/ThirdParty/Ert/docs/user/tutorial/index.rst b/ThirdParty/Ert/docs/user/tutorial/index.rst deleted file mode 100644 index fdcc65dfe1..0000000000 --- a/ThirdParty/Ert/docs/user/tutorial/index.rst +++ /dev/null @@ -1,3 +0,0 @@ -ERT Tutorial -============ -Tutorial for ert diff --git a/ThirdParty/Ert/docs/user/workflows/built_in.rst b/ThirdParty/Ert/docs/user/workflows/built_in.rst deleted file mode 100644 index 60edeb4fa9..0000000000 --- a/ThirdParty/Ert/docs/user/workflows/built_in.rst +++ /dev/null @@ -1,401 +0,0 @@ -.. _built_in_workflow_jobs: - -Built in workflow jobs -====================== - - -ERT comes with a list of default workflow jobs which invoke internal -ERT functionality. The internal workflows include: - -Jobs related to case management -------------------------------- - -**SELECT_CASE** - -The job SELECT_CASE can be used to change the currently selected -case. The SELECT_CASE job should be used as: - -:: - - SELECT_CASE newCase - -if the case newCase does not exist it will be created. - -**CREATE_CASE** - -The job CREATE_CASE can be used to create a new case without selecting -it. The CREATE_CASE job should be used as: - -:: - - CREATE_CASE newCase - - -**INIT_CASE_FROM_EXISTING** - -The job INIT_CASE_FROM_EXISTING can be used to initialize a case from -an existing case. The argument to the workflow should be the name of -the workflow you are initializing from; so to initialize the current -case from the existing case "oldCase": - -:: - - INIT_CASE_FROM_EXISTING oldCase - -By default the job will initialize the 'current case', but optionally -you can give the name of a second case which should be initialized. In -this example we will initialize "newCase" from "oldCase": - -:: - - INIT_CASE_FROM_EXISTING oldCase newCase - -When giving the name of a second case as target for the initialization -job the 'current' case will not be affected. - - -Jobs related to export ----------------------- - -**EXPORT_FIELD** - -The EXPORT_FIELD workflow job exports field data to roff or grdecl -format dependent on the extension of the export file argument.The job -takes the following arguments: - -#. Field to be exported -#. Filename for export file, must contain %d -#. Report_step -#. Realization range - -The filename must contain a %d. This will be replaced with the -realization number. - -The realization range parameter is optional. Default is all -realizations. - - -Example use of this job in a workflow: - -:: - - EXPORT_FIELD PERMZ path_to_export/filename%d.grdecl 0 0,2 - -**EXPORT_FIELD_RMS_ROFF** - -The EXPORT_FIELD_RMS_ROFF workflow job exports field data to roff -format. The job takes the following arguments: - -#. Field to be exported -#. Filename for export file, must contain %d -#. Report_step -#. Realization range - -The filename must contain a %d. This will be replaced with the -realization number. - -The realization range parameter is optional. Default is all realizations. - - -Example uses of this job in a workflow: - -:: - - EXPORT_FIELD_RMS_ROFF PERMZ path_to_export/filename%d.roff 0 - EXPORT_FIELD_RMS_ROFF PERMX path_to_export/filename%d 0 0-5 - - -**EXPORT_FIELD_ECL_GRDECL** - -The EXPORT_FIELD_ECL_GRDECL workflow job exports field data to grdecl -format. The job takes the following arguments: - -#. Field to be exported -#. Filename for export file, must contain %d -#. Report_step -#. Realization range - -The filename must contain a %d. This will be replaced with the realization number. - -The realization range parameter is optional. Default is all realizations. - - -Example uses of this job in a workflow: - -:: - - EXPORT_FIELD_ECL_GRDECL PERMZ path_to_export/filename%d.grdecl 0 - EXPORT_FIELD_ECL_GRDECL PERMX path_to_export/filename%d 0 0-5 - - -**EXPORT_RUNPATH** - -The EXPORT_RUNPATH workflow job writes the runpath file RUNPATH_FILE -for the selected case. - -The job can have no arguments, or one can set a range of realizations -and a range of iterations as arguments. - -Example uses of this job in a workflow: - -:: - - EXPORT_RUNPATH - -With no arguments, entries for all realizations are written to the -runpath file. If the runpath supports iterations, entries for all -realizations in iter0 are written to the runpath file. - -:: - - EXPORT_RUNPATH 0-5 | * - -A range of realizations and a range of iterations can be given. "|" is -used as a delimiter to separate realizations and iterations. "*" can -be used to select all realizations or iterations. In the example -above, entries for realizations 0-5 for all iterations are written to -the runpath file. - - -Jobs related to analysis update -------------------------------- - -**ANALYSIS_UPDATE** - -This job will perform a update and store the updated parameters as -initial parameters of a different case. The name of the source case -and the target case must be given as arguments: - -:: - - ANALYSIS_UPDATE prior posterior - -Will fetch prior parameters and simulated responses from the -case:`prior` and store updated parameters in the case:`posterior`. If -you have configured local updates that will be respected, otherwise -all available data will be used - and all parameters will be updated. - - -Jobs related to running simulations - including updates -------------------------------------------------------- - -**RUN_SMOOTHER** - -The RUN_SMOOTHER job will run a simulation and perform an update. The -job has one required argument - the name of a case where the updated -parameters are stored. Optionally the job can take a second boolean -argument, if the second argument is set to true the job will rerun -based on the updated parameters. - -Run a simulation and an update. Store the updated parameters in the -specified case. This case is created if it does not exist: - -:: - - RUN_SMOOTHER new_case - - -Run a simulation and an update. Store the updated parameters in the -specified case, then run a simulation on this case: - -:: - - RUN_SMOOTHER new_case true - - - -**RUN_SMOOTHER_WITH_ITER** - -This is exactly like the RUN_SMOOTHER job, but it has an additional -first argumeent iter which can be used to control the iter number in -the RUNPATH. When using the RUN_SMOOTHER job the iter number will be -defaultetd to zero, and one in the optional rerun. - -**ENSEMBLE_RUN** - -The ENSEMBLE_RUN job will run a simulation, no update. The job take as -optional arguments a range and/or list of which realizations to run. - -:: - - ENSEMBLE_RUN - -:: - - ENSEMBLE_RUN 1-5, 8 - - -**LOAD_RESULTS** - -The LOAD_RESULTS loads result from simulation(s). The job takes as -optional arguments a range and/or list of which realizations to load -results from. If no realizations are specified, results for all -realizations are loaded. - -:: - - LOAD_RESULTS - -:: - - LOAD_RESULTS 1-5, 8 - -In the case of multi iteration jobs, like e.g. the integrated smoother -update, the LOAD_RESULTS job will load the results from iter==0. To -control which iteration is loaded from you can use the -LOAD_RESULTS_ITER job. - - -**LOAD_RESULTS_ITER** - -The LOAD_RESULTS_ITER job is similar to the LOAD_RESULTS job, but it -takes an additional first argument which is the iteration number to -load from. This should be used when manually loading results from a -multi iteration workflow: - -:: - - LOAD_RESULTS_ITER - -:: - - LOAD_RESULTS_ITER 3 1-3, 8-10 - -Will load the realisations 1,2,3 and 8,9,10 from the fourth iteration -(counting starts at zero). - - -**MDA_ES** - -This workflow job (plugin) is used to run the *Multiple Data -Assimilation Ensemble Smoother* :code:`MDA ES`. Only two arguments -are required to start the MDA ES process; target case format and -iteration weights. The weights implicitly indicate the number of -iterations and the normalized global standard deviation scaling -applied to the update step. - -:: - - MDA_ES target_case_%d observations/obs.txt - -This command will use the weights specified in the obs.txt file. This -file should have a single floating point number per line. -Alternatively the weights can be given as arguments as shown here. - -:: - - MDA_ES target_case_%d 8,4,2,1 - -This command will use the normalized version of the weights 8,4,2,1 -and run for four iterations. The prior will be in *target_case_0* and -the results from the last iteration will be in *target_case_4*. -**Note: the weights must be listed with no spaces and separated with -commas.** - -If this is run as a plugin from Ertshell or the GUI a convenient user -interface can be shown. - - -Jobs for ranking realizations ------------------------------ - -**OBSERVATION_RANKING** - -The OBSERVATION_RANKING job will rank realizations based on the delta -between observed and simulated values for selected variables and time -steps. The data for selected variables and time steps are summarized -for both observed and simulated values, and then the simulated versus -observed delta is used for ranking the realizations in increasing -order. The job takes a name for the ranking as the first parameter, -then the time steps, a "|" character and then variables to rank on. If -no time steps and/or no variables are given, all time steps and -variables are taken into account. - - -Rank the realizations on observation/simulation delta value for all -WOPR data for time steps 0-20: - -:: - - OBSERVATION_RANKING Ranking1 0-20 | WOPR:* - - -Rank the simulations on observation/simulation delta value for all -WOPR and WWCT data for time steps 1 and 10-50 - -:: - - OBSERVATION_RANKING Ranking2 1, 10-50 | WOPR:* WWCT:* - - -Rank the realizations on observation/simulation delta value for -WOPR:OP-1 data for all time steps - -:: - - OBSERVATION_RANKING Ranking3 | WOPR:OP-1 - -**DATA_RANKING** - -The DATA_RANKING job will rank realizations in increasing or -decreasing order on selected data value for a selected time step. The -job takes as parameters the name of the ranking, the data key to rank -on, increasing order and selected time steps. If no time step is -given, the default is the last timestep. - -Rank the realizations on PORO:1,2,3 on time step 0 in decreasing order - -:: - - DATA_RANKING Dataranking1 PORO:1,2,3 false 0 - - -**EXPORT_RANKING** - -The EXPORT_RANKING job exports ranking results to file. The job takes -two parameters; the name of the ranking to export and the file to -export to. - -:: - - EXPORT_RANKING Dataranking1 /tmp/dataranking1.txt - - -**INIT_MISFIT_TABLE** - -Calculating the misfit for all observations and all timesteps can -potentially be a bit timeconsuming, the results are therefor cached -internally. If you need to force the recalculation of this cache you -can use the INIT_MISFIT_TABLE job to initialize the misfit table that -is used in observation ranking. - -:: - - INIT_MISFIT_TABLE - - -**STD_SCALE_CORRELATED_OBS** - -The workflow job :code:`STD_SCALE_CORRELATED_OBS` is used to scale the -observation standard deviation in an attempt to reduce the effect of -correlations in the observed data. The job expects the observation -keys you want to consider as arguments: - -:: - - STD_SCALE_CORRELATED_OBS WWCT:OP_1 WWCT:OP_2 - -In this example the observation uncertainty corresponding to -:code:`WWCT:OP_1` and :code:`WWCT:OP_2` will be scaled. Observe that -the :code:`STD_SCALE_CORRELATED_OBS` keyword will "flatten" in both -time and spatial direction. Wildcards are allow, i.e. - -:: - - STD_SCALE_CORRELATED_OBS W*:OP_1 - -Will scale based on all the observations of well 'OP_1'. For more -advanced selections of observations, where you only want to scale -based on parts of the observation - spatially or temporaly you must -write your own plugin. - diff --git a/ThirdParty/Ert/docs/user/workflows/index.rst b/ThirdParty/Ert/docs/user/workflows/index.rst deleted file mode 100644 index 8a0f541975..0000000000 --- a/ThirdParty/Ert/docs/user/workflows/index.rst +++ /dev/null @@ -1,30 +0,0 @@ -Workflows and plugins -===================== - -Contents - -.. toctree:: - :maxdepth: 1 - - workflows - plugins - built_in - -The Forward Model in ERT runs in the context of a single realization, -i.e. there is no communication between the different processes, and -the jobs are run outside of the main ERT process. - -As an alternative to the forward model ERT has a system with -*workflows*. Using workflows way you can automate cumbersome normal -ERT processes, and also invoke external programs. The workflows are -run serially on the workstation actually running ERT, and should not -be used for computationally heavy tasks. - -In addition to workflows ERT has a system for *plugins*, a plugin is -quite similar to a workflow job, but the plugin appears in a gui -dropdown, and can even have a gui of it's own. A plugin is written in -Python and has *full access* to ERT internals. The plugins hook into -the running Python process, and can only be invoked from the gui or -:code:`ertshell`. - - diff --git a/ThirdParty/Ert/docs/user/workflows/plugins.rst b/ThirdParty/Ert/docs/user/workflows/plugins.rst deleted file mode 100644 index b3e6f93d14..0000000000 --- a/ThirdParty/Ert/docs/user/workflows/plugins.rst +++ /dev/null @@ -1,246 +0,0 @@ -Python plugins -============== - -When you are using one of the python based frontends :code:`gert` or -:code:`ertshell` you can write plugins to ert in Python. The plugins -will run as part of the running ert process, and can do anything ert -can do itself. Writing a plugin is quite similar to writing an -:ref:`ert_script` - the main difference is that the class should -inherit from :code:`ErtPlugin`. This plugin will print the ensemble -size in the console: - -.. code:: python - - from ert.util import DoubleVector - from ert.enkf import ErtScript - - class PrintEnsembleSize(ErtPlugin): - - # The run method is the entry point which is called - # when the plugin is invoked. - def run(self): - ert = self.ert() - print("Ensemble size: %d" % ert.getEnsembleSize( )) - - - # This is the name of the plugin which will appear in the - # "Plugin" menu in the gui. - def getName(self): - return "Size plugin" - - - -The plugins should be *installed* with a small configuration -file. Assume that the small code above is implemented in the script -file :code:`script/ens_size.py` then it is installed in ert as: - - INTERNAL TRUE -- The job will call an internal function of the current running ERT instance. - SCRIPT sripts/ens_size.py -- An existing Python script - -ERT will detect that the class inherits from :code:`ErtPlugin`, and -the functionality will be available as :code:`Size plugin` in the plugin menu. - -As an example of a more complete plugin is the :code:`CSV export` -plugin from the ert code, this code can be used to export simulated -results, parameters and observations to a CSV file[#csv_export]_. - -.. code:: python - - import os - import re - - import pandas - from PyQt4.QtGui import QCheckBox - - from ert.enkf import ErtPlugin, CancelPluginException - from ert.enkf.export import SummaryCollector, GenKwCollector, MisfitCollector, DesignMatrixReader, CustomKWCollector - from ert_gui.ertwidgets.customdialog import CustomDialog - from ert_gui.ertwidgets.listeditbox import ListEditBox - from ert_gui.ertwidgets.models.path_model import PathModel - from ert_gui.ertwidgets.pathchooser import PathChooser - - - class CSVExportJob(ErtPlugin): - """ - Export of summary, custom_kw, misfit, design matrix data and gen kw into a single CSV file. - - The script expects a single argument: - - output_file: this is the path to the file to output the CSV data to - - Optional arguments: - - case_list: a comma separated list of cases to export (no spaces allowed) - if no list is provided the current case is exported - a single * can be used to export all cases - - design_matrix: a path to a file containing the design matrix - - infer_iteration: If True the script will try to infer the iteration number by looking at the suffix of the case name - (i.e. default_2 = iteration 2) - If False the script will use the ordering of the case list: the first item will be iteration 0, - the second item will be iteration 1... - - The script also looks for default values for output path and design matrix path to present in the GUI. These can - be specified with DATA_KW keyword in the config file: - DATA_KW CSV_OUTPUT_PATH - DATA_KW DESIGN_MATRIX_PATH - """ - - INFER_HELP = ("" - "If this is checked the iteration number will be inferred from the name i.e.:" - "
    " - "
  • case_name -> iteration: 0
  • " - "
  • case_name_0 -> iteration: 0
  • " - "
  • case_name_2 -> iteration: 2
  • " - "
  • case_0, case_2, case_5 -> iterations: 0, 2, 5
  • " - "
" - "Leave this unchecked to set iteration number to the order of the listed cases:" - "
  • case_0, case_2, case_5 -> iterations: 0, 1, 2
" - "
" - "") - - def getName(self): - return "CSV Export" - - def getDescription(self): - return "Export GenKW, CustomKW, design matrix, misfit data and summary data into a single CSV file." - - def inferIterationNumber(self, case_name): - pattern = re.compile("_([0-9]+$)") - match = pattern.search(case_name) - - if match is not None: - return int(match.group(1)) - return 0 - - - def run(self, output_file, case_list=None, design_matrix_path=None, infer_iteration=True): - cases = [] - - if case_list is not None: - if case_list.strip() == "*": - cases = self.getAllCaseList() - else: - cases = case_list.split(",") - - if case_list is None or len(cases) == 0: - cases = [self.ert().getEnkfFsManager().getCurrentFileSystem().getCaseName()] - - if design_matrix_path is not None: - if not os.path.exists(design_matrix_path): - raise UserWarning("The design matrix file does not exists!") - - if not os.path.isfile(design_matrix_path): - raise UserWarning("The design matrix is not a file!") - - data = pandas.DataFrame() - - for index, case in enumerate(cases): - case = case.strip() - - if not self.ert().getEnkfFsManager().caseExists(case): - raise UserWarning("The case '%s' does not exist!" % case) - - if not self.ert().getEnkfFsManager().caseHasData(case): - raise UserWarning("The case '%s' does not have any data!" % case) - - if infer_iteration: - iteration_number = self.inferIterationNumber(case) - else: - iteration_number = index - - case_data = GenKwCollector.loadAllGenKwData(self.ert(), case) - - custom_kw_data = CustomKWCollector.loadAllCustomKWData(self.ert(), case) - if not custom_kw_data.empty: - case_data = case_data.join(custom_kw_data, how='outer') - - if design_matrix_path is not None: - design_matrix_data = DesignMatrixReader.loadDesignMatrix(design_matrix_path) - if not design_matrix_data.empty: - case_data = case_data.join(design_matrix_data, how='outer') - - misfit_data = MisfitCollector.loadAllMisfitData(self.ert(), case) - if not misfit_data.empty: - case_data = case_data.join(misfit_data, how='outer') - - summary_data = SummaryCollector.loadAllSummaryData(self.ert(), case) - if not summary_data.empty: - case_data = case_data.join(summary_data, how='outer') - else: - case_data["Date"] = None - case_data.set_index(["Date"], append=True, inplace=True) - - case_data["Iteration"] = iteration_number - case_data["Case"] = case - case_data.set_index(["Case", "Iteration"], append=True, inplace=True) - - data = pandas.concat([data, case_data]) - - data = data.reorder_levels(["Realization", "Iteration", "Date", "Case"]) - data.to_csv(output_file) - - export_info = "Exported %d rows and %d columns to %s." % (len(data.index), len(data.columns), output_file) - return export_info - - - def getArguments(self, parent=None): - description = "The CSV export requires some information before it starts:" - dialog = CustomDialog("CSV Export", description, parent) - - default_csv_output_path = self.getDataKWValue("CSV_OUTPUT_PATH", default="output.csv") - output_path_model = PathModel(default_csv_output_path) - output_path_chooser = PathChooser(output_path_model) - - design_matrix_default = self.getDataKWValue("DESIGN_MATRIX_PATH", default="") - design_matrix_path_model = PathModel(design_matrix_default, is_required=False, must_exist=True) - design_matrix_path_chooser = PathChooser(design_matrix_path_model) - - list_edit = ListEditBox(self.getAllCaseList()) - - infer_iteration_check = QCheckBox() - infer_iteration_check.setChecked(True) - infer_iteration_check.setToolTip(CSVExportJob.INFER_HELP) - - dialog.addLabeledOption("Output file path", output_path_chooser) - dialog.addLabeledOption("Design Matrix path", design_matrix_path_chooser) - dialog.addLabeledOption("List of cases to export", list_edit) - dialog.addLabeledOption("Infer iteration number", infer_iteration_check) - - dialog.addButtons() - - success = dialog.showAndTell() - - if success: - design_matrix_path = design_matrix_path_model.getPath() - if design_matrix_path.strip() == "": - design_matrix_path = None - - case_list = ",".join(list_edit.getItems()) - - return [output_path_model.getPath(), case_list, design_matrix_path, infer_iteration_check.isChecked()] - - raise CancelPluginException("User cancelled!") - - - def getDataKWValue(self, name, default): - data_kw = self.ert().getDataKW() - if name in data_kw: - return data_kw[data_kw.indexForKey(name)][1] - return default - - def getAllCaseList(self): - fs_manager = self.ert().getEnkfFsManager() - all_case_list = fs_manager.getCaseList() - all_case_list = [case for case in all_case_list if fs_manager.caseHasData(case)] - return all_case_list - - -.. rubric:: Footnotes - -.. [csv_export] There are many solutions for CSV export; this plugin - is an example which is implemented based on the - internal ert datastructures, other - probably more - widely used alterantives are based on an external - process running through the simulation folders. diff --git a/ThirdParty/Ert/docs/user/workflows/workflows.rst b/ThirdParty/Ert/docs/user/workflows/workflows.rst deleted file mode 100644 index b599aa5b5e..0000000000 --- a/ThirdParty/Ert/docs/user/workflows/workflows.rst +++ /dev/null @@ -1,369 +0,0 @@ -.. _workflows: - -Configuring workflows in ERT consists of two steps: *installing the -jobs* which should be available for ERT to use in workflows, and then -subsequently assemble one or more jobs, with arguments, in a -workflow. You can use predefined workflow jobs, or create your -own. There are no predefined complete workflows. - - - -Workflow jobs -============= - -The workflow jobs are quite similar to the jobs in the forward model, -in particular the jobs are described by a configuration file which -resembles the one used by the forward model jobs. The workflow jobs -can be of two fundamentally different types - *external* and *internal*. - - -External workflow jobs ----------------------- - -These jobs invoke an external program/script to do the job, this is -very similar to the jobs of the forward model, but instead of running -as separate jobs on the cluster - one for each realization, the -workflow jobs will be invoked on the workstation running ert, and -typically go through all the realizations in one loop. - -The executable invoked by the workflow job can be an executable you -have written yourself - in any language, or it can be an existing -Linux command like e.g. :code:`cp` or :code:`mv`. - -Internal workflow jobs ----------------------- - -These jobs invoke a function in the address space of the ERT program -itself; i.e. they are run as part of the running ERT process - and can -in principle do anything that ERT can do itself. There are two two -varieties of the internal workflow jobs: - - -Invoke a pre exported function -.............................. - -This is the simplest, where you can invoke a a predefined ERT -function. The function must already have been marked as *exported* in -the ert code base. The list of predefined workflow jobs based on this -method can be found here: :ref:`built_in_workflow_jobs`. Marking a new -function as exported is quite simple, but it requires changes to the -core code and a new version must be installed. - -.. _ert_script: -Run a Python Script -................... - -If you are using one of the Python based frontends, *gert* or -*erthsell*, you can write your own Python script which is run as part -of the existing process. By using the full ert Python api you get -access to powerful customization/automization features. Below is an -example of :code:`ErtScript` which calculates the misfit for all -observations and prints the result to a text file. All Python scripts -of this kind must: - - 1. Be implemented as a class which iherits from :code:`ErtScript` - 2. Have a method :code:`run(self)` which does the actual job - - -.. code:: python - - from ert.util import DoubleVector - from ert.enkf import ErtScript - - class ExportMisfit(ErtScript): - - def run(self): - # Get a handle to running ert instance - ert = self.ert() - - - # Get a handle to the case / filesystem we are interested in; - # this should ideally come as an argument - not just use current. - fs = ert.getEnkfFsManager().getCurrentFileSystem() - - - # How many realisations: - ens_size = ert.getEnsembleSize( ) - - - # Get a handle to all the observations - observations = ert.getObservations() - - - # Iterate through all the observations; each element in this - # iteration corresponds to one key in the observations file. - for obs in observations: - misfit = DoubleVector() - for iens in range(ens_size): - chi2 = obs.getTotalChi2( fs , iens ) - misfit[iens] = chi2 - - permutation = misfit.permutationSort( ) - - print " # Realisation Misfit:%s" % obs.getObservationKey() - print "-----------------------------------" - for index in range(len(misfit)): - iens = permutation[index] - print "%2d %2d %10.5f" % (index , iens , misfit[iens]) - - print "-----------------------------------\n" - - - - -Configuring workflow jobs -------------------------- - -Workflow jobs are configured with a small configuration file much like -the configuration file used to install forward model jobs. The -keywords used in the configuration file are in two *clases* - those -related to how the job should located/run and the arguments which -should passed from the workflow to the job. - - -Configure an internal job -......................... - -When configuring an internal workflow job the keyword :code:`INTERNAL` -is given the value :code:`TRUE` to indicate that this is an internal -job. In addition you give the name of the C function you wish to -invoke. By default the workflow job will search for the function -symbol in the current process space, but by passing the :code:`MODULE` -keyword you can request the loading of an external shared library: - -:: - - INTERNAL TRUE -- The job will call an internal function of the current running ERT instance. - FUNCTION enkf_main_plot_all -- Name of the ERT function we are calling; must be marked exportable. - MODULE /name/of/shared/library -- Very optional - to load an extra shared library. - - -Configure a an internal job: Python -................................... - -If you wish to implement your job as a Python class, derived from -:code:`ErtScript` you should use the :code:`SCRIPT` keyword instead of -:code:`FUNCTION`, to point to an existing Python script: - -:: - - INTERNAL TRUE -- The job will call an internal function of the current running ERT instance. - SCRIPT sripts/my_script.py -- An existing Python script - -Observe that the important thing here is the fact that we are writing -an *internal* Python script; if you are writing an external script to -loop through all your realization folders that will typically be an -*external* script, and in that case the implementation language - -i.e. Python, Perl, C++, F77 ... has no relevance. - - -Configure an external job -......................... - -An *external* job is a workflow job which is implemented in an -external executable, i.e. typically a script written in for instance -Python. When configuring an external job the most important keyword is -:code:`EXECUTABLE` which is used to give the path to the external -executable: - -:: - - INTERNAL FALSE -- This is the default - not necessary to include. - EXECUTABLE path/to/program -- Path to a program/script which will be invoked by the job. - - -Configuring the arguments -......................... - -In addition to the INTERNAL, FUNCTION, MODULE and EXECUTABLE keys -which are used to configure what the job should do there are some keys -which can be used to configure the number of arguments and their -type. These arguments apply to both internal and external jobs: - -:: - - MIN_ARG 2 -- The job should have at least 2 arguments. - MAX_ARG 3 -- The job should have maximum 3 arguments. - ARG_TYPE 0 INT -- The first argument should be an integer - ARG_TYPE 1 FLOAT -- The second argument should be a float value - ARG_TYPE 2 STRING -- The third argument should be a string - the default. - -The MIN_ARG,MAX_ARG and ARG_TYPE arguments are used to validate workflows. - - -**Example 1 : Plot variables** - -:: - - -- FILE: PLOT -- - INTERNAL TRUE - FUNCTION ert_tui_plot_JOB - MIN_ARG 1 - -This job will use the ERT internal function ert_tui_plot_JOB to plot -an ensemble of an arbitrary ERT variable. The job needs at least one -argument; there is no upper limit on the number of arguments. - - -**Example 2 : Run external script** - -:: - - -- FILE: ECL_HIST -- - EXECUTABLE Script/ecl_hist.py - MIN_ARG 3 - -This job will invoke the external script Script/ecl_host.py; the -script should have at least three commandline arguments. The path to -the script, Script/ecl_hist.py is interpreted relative to the location -of the configuration file. - - -Loading workflow jobs into ERT ------------------------------- - -Before the jobs can be used in workflows they must be 'loaded' into -ERT. This is done with two different ERT keywords: - -:: - - LOAD_WORKFLOW_JOB jobConfigFile JobName - -The LOAD_WORKFLOW_JOB keyword will load one workflow job. The name of -the job is optional, if not provided the job will get name from the -configuration file. Alternatively you can use the command -WORKFLOW_JOB_DIRECTORY which will load all the jobs in a -directory. The command: - -:: - - WORKFLOW_JOB_DIRECTORY /path/to/jobs - -will load all the workflow jobs in the /path/to/jobs -directory. Observe that all the files in the /path/to/jobs directory -should be job configuration files. The jobs loaded in this way will -all get the name of the file as the name of the job. The -:code:`WORKFLOW_OB_DIRECTORY` keyword will *not* load configuration -files recursively. - - - - -Complete Workflows -================== - -A workflow is a list of calls to jobs, with additional arguments. The -job name should be the first element on each line. Based on the two -jobs PLOT and ECL_HIST we can create a small workflow example: - -:: - - PLOT WWCT:OP_1 WWCT:OP_3 PRESSURE:10,10,10 - PLOT FGPT FOPT - ECL_HIST //wwct_hist WWCT:OP_1 WWCT:OP_2 - -In this workflow we create plots of the nodes -WWCT:OP_1;WWCT:OP_3,PRESSURE:10,10,10,FGPT and FOPT. The plot job we -have created in this example is completely general, if we limited -ourselves to ECLIPSE summary variables we could get wildcard -support. Then we invoke the ECL_HIST example job to create a -histogram. See below for documentation of , and -. - - -Loading workflows ------------------ - -Workflows are loaded with the configuration option LOAD_WORKFLOW: - -:: - - LOAD_WORKFLOW /path/to/workflow/WFLOW1 - LOAD_WORKFLOW /path/to/workflow/workflow2 WFLOW2 - -The LOAD_WORKFLOW takes the path to a workflow file as the first -argument. By default the workflow will be labeled with the filename -internally in ERT, but optionally you can supply a second extra -argument which will be used as name for the workflow. Alternatively -you can load a workflow interactively. - - -Automatically run workflows : HOOK_WORKFLOW -------------------------------------------- -.. _hook_workflow: -.. topic:: HOOK_WORKFLOW - -With the keyword :code:`HOOK_WORKFLOW` you can configure workflow -'hooks'; meaning workflows which will be run automatically at certain -points during ERTs execution. Currently there are four points in ERTs -flow of execution where you can hook in a workflow, before -the simulations start, :code:`PRE_SIMULATION`; after all the -simulations have completed :code:`POST_SIMULATION`; -before the update step, :code:`PRE_UPDATE` and after the update step, :code:`POST_UPDATE`. The -:code:`POST_SIMULATION` hook is typically used to trigger QC -workflows: - -:: - - HOOK_WORKFLOW initWFLOW PRE_SIMULATION - HOOK_WORKFLOW preUpdateWFLOW PRE_UPDATE - HOOK_WORKFLOW postUpdateWFLOW POST_UPDATE - HOOK_WORKFLOW QC_WFLOW1 POST_SIMULATION - HOOK_WORKFLOW QC_WFLOW2 POST_SIMULATION - - -In this example the workflow :code:`initWFLOW` will run after all -the simulation directories have been created, just before the forward -model is submitted to the queue. The workflow :code:`preUpdateWFLOW` will be run before the -update step and :code:`postUpdateWFLOW` will be run after the -update step. When all the simulations are complete -the two workflows :code:`QC_WFLOW1` and :code:`QC_WFLOW2` will be -run. - -Observe that the workflows being 'hooked in' with the -:code:`HOOK_WORKFLOW` must be loaded with the :code:`LOAD_WORKFLOW` -keyword. - -Currently, :code:`PRE_UPDATE` and :code:`POST_UPDATE` are only -available from python. - -Locating the realisations: ------------------------------------------ - -Context must be passed between the main ERT process and the script -through the use of string substitution, in particular the 'magic' key - has been introduced for this purpose. - -Many of the external workflow jobs involve looping over all the -realisations in a construction like this: - -:: - - for each realisation: - // Do something for realisation - summarize() - -When running an external job in a workflow there is no direct transfer -of information between the main ERT process and the external -script. We therefor must have a convention for transfering the -information of which realisations we have simulated on, and where they -are located in the filesystem. This is done through a file which looks -like this: - -:: - - 0 /path/to/real0 CASE_0000 - 1 /path/to/real1 CASE_0001 - ... - 9 /path/to/real9 CASE_0009 - -The name and location of this file is available as the magical string - and that is typically used as the first argument to -external workflow jobs which should iterate over all realisations. The -realisations referred to in the are meant to be last -simulations you have run; the file is updated every time you run -simulations. This implies that it is (currently) not so convenient to -alter which directories should be used when running a workflow. - - - diff --git a/ThirdParty/Ert/etc-example/ERT/Scripts/job_dispatch.py b/ThirdParty/Ert/etc-example/ERT/Scripts/job_dispatch.py deleted file mode 100644 index 147c6ad409..0000000000 --- a/ThirdParty/Ert/etc-example/ERT/Scripts/job_dispatch.py +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'job_dispatch.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -import sys -import os -import os.path -import socket -import time -import random - - -OK_file = "OK" -EXIT_file = "EXIT" -STATUS_file = "STATUS" -run_path = sys.argv[1] -sleep_time = 10 # Time to sleep before exiting the script - to let the disks sync up. -short_sleep = 2 - -################################################################# - -def redirect(file , fd , open_mode): - new_fd = os.open(file , open_mode , 0644) - os.dup2(new_fd , fd) - os.close(new_fd) - - -def cond_symlink(target , src): - if not os.path.exists(src): - os.symlink( target , src ) - - -def cond_unlink(file): - if os.path.exists(file): - os.unlink(file) - - - -def exec_job(job , executable): - if job["stdin"]: - redirect(job["stdin"] , 0 , os.O_RDONLY) - - if job["stdout"]: - redirect(job["stdout"] , 1 , os.O_WRONLY | os.O_TRUNC | os.O_CREAT ) - - if job["stderr"]: - redirect(job["stderr"] , 2 , os.O_WRONLY | os.O_TRUNC | os.O_CREAT ) - - if job["environment"]: - env = job["environment"] - for key in env.keys(): - os.putenv(key , env[key]) - os.execvp(executable , [executable] + job["argList"]) - - - -def unlink_empty(file): - if os.path.exists(file): - st = os.stat( file ) - if st.st_size == 0: - os.unlink( file ) - - - -def cleanup( job ): - if job["stdout"]: - unlink_empty( job["stdout"] ) - if job["stderr"]: - unlink_empty( job["stderr"] ) - - if job["license_link"]: - os.unlink(job["license_link"]) - - - -# This function implements a simple "personal license" system limiting -# how many instances of this job can run concurrently. Observe that the -# limiting is based on pr. invocation of the queue system (i.e. ERT -# binary) and pr user. The system works as follows: -# -# 1. The job is initilized with a license_path and a max_running -# variable. -# -# 2. In the licens_path directory a license file is made. -# -# 3. For each instance a random hard-link is created to the license -# file - this is how the number of concurrent uses is counted. -# -# 4. When the external program is finished the hard link is removed. - - -def license_check( job ): - job["license_link"] = None - if job.has_key("max_running"): - if job["max_running"]: - job["license_file"] = "%s/%s" % (job["license_path"] , job["name"]) - max_running = job["max_running"] - license_file = job["license_file"] - while True: - job["license_link"] = "%s/%d" % (job["license_path"] , random.randint(100000,999999)) - if not os.path.exists(job["license_link"]): - break - - - if not os.path.exists(license_file): - fileH = open(license_file , "w") - fileH.write("This is a license file for job:%s" % job["name"]) - fileH.close() - - - stat_info = os.stat(license_file) - currently_running = stat_info[3] - 1 - - while True: - stat_info = os.stat(license_file) - currently_running = stat_info[3] - 1 - if currently_running < max_running: - break - else: - time.sleep(5) - - os.link(license_file , job["license_link"]) - - while True: - stat_info = os.stat(license_file) - currently_running = stat_info[3] - 1 - if currently_running <= max_running: - break # OK - now we can leave the building - and let the job start - else: - time.sleep(5) - - -# Compatibility mode which must be retained until all ert prior to -# svn 2709 has been removed. - -def get_executable( job ): - executable = job.get("executable") - if not executable: - executable = job.get("portable_exe") - if not executable: - cpu = os.uname()[4] - if job["platform_exe"].has_key(cpu): - executable = job["platform_exe"][cpu] - else: - return (False, 0 , "%s : did not recognize platform:%s" % (job["name"] , cpu)) - - return executable - - - -def run_one(job): - license_check( job ) - if job["stdin"]: - if not os.path.exists(job["stdin"]): - return (False , 0 , "Could not locate stdin file: %s" % job["stdin"]) - - if job["start_file"]: - if not os.path.exists(job["start_file"]): - return (False , -1 , "Could not locate start_file:%s" % job["start_file"]) - - - - executable = get_executable( job ) - start_time = time.time() - pid = os.fork() - if pid == 0: - exec_job(job , executable) - else: - if job["max_running_minutes"]: - proc_path = "/proc/%d" % pid - # There is max run time on the job. - while True: - time.sleep( short_sleep ) - if os.path.exists( proc_path ): # Checking if the - run_time = time.time() - start_time - if run_time > (60 * job["max_running_minutes"]): - return (False , 0 , "Run time of %d minutes exceeded for job:%s" % ( job["max_running_minutes"] , job["name"])) - else: - break # The job is no longer running - - else: - (return_pid , exit_status) = os.waitpid(pid , 0) - - - if job["target_file"]: - if os.path.exists(job["target_file"]): - stat = os.stat(job["target_file"]) - if stat.st_ctime > start_time: - cleanup(job) - return (True , 0 , "") - else: - cleanup(job) - return (True , 0 , "Hmmm - seems the target file has not been updated - let the job suceed anyway...??") - else: - cleanup(job) - return (False , exit_status , "%s : could not find target_file:%s" % (job["name"] , job["target_file"])) - else: - cleanup(job) - return (True , exit_status , "Target file not speced") # Do not really look at exit status yet... - - - -################################################################# - -################################################################# - -os.nice(19) -if not os.path.exists( run_path ): - sys.stderr.write("*****************************************************************\n"); - sys.stderr.write("** FATAL Error: Could not find dirctory: %s \n" % run_path) - sys.stderr.write("** CWD: %s\n" % os.getcwd()) - sys.stderr.write("*****************************************************************\n"); - - fileH = open(EXIT_file , "w") - fileH.write("Could not locate:%s " % run_path) - fileH.write("CWD: %s" % os.getcwd()) - fileH.close() - sys.exit(-1) - -os.chdir( run_path ) -cond_unlink(EXIT_file) -cond_unlink(STATUS_file) -cond_unlink(OK_file) -fileH = open(STATUS_file , "a") -fileH.write("%-40s: %s/%s\n" % ("Current host:" , socket.gethostname() , os.uname()[4])) -fileH.close() - -sys.path.append( os.getcwd() ) -import jobs -random.seed() - -for job in jobs.jobList: - # To ensure compatibility with old versions. - if not job.has_key("max_running_minutes"): - job["max_running_minutes"] = None - -if len(sys.argv) == 2: - # Normal batch run. - for job in jobs.jobList: - fileH = open(STATUS_file , "a") - now = time.localtime() - fileH.write("%-32s: %02d:%02d:%02d .... " % (job["name"] , now.tm_hour , now.tm_min , now.tm_sec)) - fileH.close() - (OK , exit_status, error_msg) = run_one(job) - now = time.localtime() - if OK: - fileH = open(STATUS_file , "a") - fileH.write("%02d:%02d:%02d \n" % (now.tm_hour , now.tm_min , now.tm_sec)) - fileH.close() - else: - fileH = open(EXIT_file , "w") - fileH.write("%02d:%02d:%02d \n" % (now.tm_hour , now.tm_min , now.tm_sec)) - fileH.write("%s : failed\n" % job["name"]) - fileH.write("%s\n" % error_msg) - fileH.close() - sys.exit(exit_status) - - - if OK: - fileH = open("OK" , "w") - fileH.write("All jobs complete") - fileH.close() - time.sleep( sleep_time ) # Let the disks sync up -else: - #Interactive run - jobHash = {} - for job in jobs.jobList: - jobHash[job["name"]] = job - - for job_name in sys.argv[2:]: - if jobHash.has_key( job_name ): - job = jobHash[job_name] - print "Running job: %s ... " % job_name, - sys.stdout.flush() - (OK , exit_status, error_msg) = run_one( job ) - if OK: - print "OK" - else: - print "failed ...." - print "-----------------------------------------------------------------" - if job["stderr"]: - print "Error:%s " % error_msg - if os.path.exists(job["stderr"]): - fileH = open(job["stderr"],"r") - for line in fileH.readlines(): - print line, - fileH.close() - print "-----------------------------------------------------------------" - sys.exit() - else: - print "Job: %s does not exist. Available jobs:" % job_name - for j in jobs.jobList: - print " %s" % j["name"] - diff --git a/ThirdParty/Ert/etc-example/ERT/Scripts/run_RMS_20xx b/ThirdParty/Ert/etc-example/ERT/Scripts/run_RMS_20xx deleted file mode 100644 index 0fb8b6d027..0000000000 --- a/ThirdParty/Ert/etc-example/ERT/Scripts/run_RMS_20xx +++ /dev/null @@ -1,394 +0,0 @@ -#!/usr/bin/python -import sys -import os -import re -import random -import time - -if os.path.exists( "dot_master.py" ): - sys.path += [ os.getcwd() ] - import dot_master -else: - dot_master = None - -dot_master_fmt = "%-39s = %s\n" -error_file = "RMS_20XX_ERRORS_" -multi_seed_file = "random.seeds" - - -################################################################## -# -# The purpose of this script is to run a per-instance RMS workflow in -# batch from eg ERT. The script expects the following input as arguments -# on the commandline -# -# : The path to where the simulation should run. Directory -# must exist. -# -# : An integer saying which realiziton number this is. -# -# : This is a string which indicates which RMS version -# should be run. The allowed versions are the keys in -# the dictionary rms_version_table below, there should -# be no problems adding more versions to this table. -# -# : This is the (full) path to the source RMS project. -# -# -# : The absolute path (set in the RMS project) part which -# should be replaced with the current directory. -# -# : This is the name of the workflow we want to run. -# -# : This is the name of the workflow we want to run. -# -# : This is the name of the workflow we want to run. -# -# -# Example: -# -# bash% run_RMS_20xx.py 0 2009.3 /d/MyField/models/rms/geomodel.pro /OLDPATH WorkFlow1 WorkFlow2 ... -# -# The script works as follows: -# -# 1. The first commandline argument is the runpath of the script, and -# it will start by chdir() there. -# -# -# 2. The script recursively walks through the original project -# directory, and does the following: -# -# a) All directories found in the original project are created -# in the copy project, thus creating a empty project -# skeleton. -# If a non-directory entry with the same name is found in the -# copy project the script will exit (this is maybe a bit over -# the top strict??) -# -# b) For files in the source directory the script will do the -# following: -# -# o If the name of the file is ".master" the script will -# _copy_ the file from the source project to the copy -# project, and on the way it will perform the string -# substitutions asked for. -# -# or -# -# o If a file with this name already exists in the target -# project nothing will be done. -# -# else -# -# o A symlink will be created from the copy project to the -# original source project. -# -# -# 3. The lockfiles "project-lock-file" and ".lock" are removed. -# -# -# 4. The program loops as follows: -# o Updating the global seed (incrementing by one with each subsequent iteration). -# o Running the rms binary for each workflow. -# -# -# Observe that this script has no explicit built in support for -# per-instance files (i.e. IPL scripts). The way that is meant to be -# solved is that an external program writes those files to the target -# project (creating necessary directories on the way) prior to calling -# this script. -# -################################################################ - - -rms_license_file = "/prog/roxar/licensing/geomaticLM.lic" - - -rms_version_table = {"2010.1.1" : "/PATH/RMS/2010.1.1/linux-amd64-gcc_3_4-release/bin/rms", - "2010" : "/PATH/RMS/2010/linux-amd64-gcc_3_2-release/bin/rms", - "2009" : "/PATH/RMS/2009/linux-amd64-gcc_3_2-release/bin/rms", - "2009.2" : "/PATH/RMS/2009.2/linux-amd64-gcc_3_2-release/bin/rms", - "2009.3" : "/PATH/RMS/2009.3/linux-amd64-gcc_3_2-release/bin/rms", - "9.0.7.4" : "/PATH/RMS/9.0.7.4/linux-amd64-gcc_3_2-release/bin/rms"} - - - -# This function will write the error message on both "RMS_20XX_ERRORS_" and -# stderr, and then exit. -def fatal_error( msg ): - fileH = open(error_file , "w") - fileH.write( msg ) - fileH.close() - - sys.exit( msg ) - - -# This function will copy the file @src_entry to the file -# @target_entry, and on the way it will perform two different string -# substitutions. The .master file is organized like a key value list: -# -# key1 = Value1 -# key2 = Value2 -# ...... -# -# The input argument @value_subst is a list of tuples, where each -# occurence of the first element in the tuple is replaced with the -# second element in the tuple. -# -# The input argument @set_list is a dictionary, if the key in the -# .master file is in the @set_list dictionary the value in the .master -# will be replaced with the value in the set_List dictionary. - -def copy_dot_master( src_entry , target_entry , subst_list , set_list): - print "Copying %s -> %s" % (src_entry , target_entry) - if os.path.exists( target_entry ): - os.unlink( target_entry ) - - srcH = open( src_entry , "r") - targetH = open( target_entry , "w") - - for line in srcH.readlines(): - for (old , new) in subst_list: - line = line.replace( old , new ) - - tmp = re.split( "\s*=\s*" , line) - key = tmp[0] - if set_list.has_key( key) : - targetH.write( dot_master_fmt % (key , set_list[key])) - else: - targetH.write( line ) - - srcH.close() - targetH.close() - - - - -def create_project_directory( arg_dict , path , entries ): - offset = arg_dict["offset"] - target_root = arg_dict["target_root"] - src_path = arg_dict["src_path"] - subst = arg_dict["subst_list"] - set_list = arg_dict["set_list"] - - newpath = "%s/%s" % ( target_root , path[offset:] ) - - #Creating all the directories of the project - if not os.path.exists( newpath ): - os.makedirs( newpath ) - else: - if os.path.islink( newpath ): - fatal_error("Entry:%s already exists as a symbolic link. Clean up first..." % newpath) - - if not os.path.isdir( newpath ): - fatal_error("Entry:%s already exists - and it is not a directory. Clean up first..." % newpath) - - # Linking in all the files - for entry in entries: - src_entry = "%s/%s" % (path , entry) - if os.path.isfile( src_entry ): - target_entry = "%s/%s" % (newpath , entry) - if entry == ".master": - copy_dot_master( src_entry , target_entry , subst , set_list) - else: - if not os.path.exists( target_entry ): - os.symlink( src_entry , target_entry ) - - - - - -# This function duplicate the directory structure of the project -# located in src_path. The newly created project will be created in -# the current directory. All files are symlinked. - -def create_project_directories( src_path , project , target_path , subst_list , set_list): - src_project = os.path.join( src_path , project ) - arg_dict = {"offset" : len(src_path) , - "target_root": target_path , - "src_path" : src_path , - "subst_list" : subst_list , - "set_list" : set_list} - print "Creating all project directories: %s/%s" % (arg_dict["target_root"] , project ) - os.path.walk( src_project , create_project_directory , arg_dict) - print "Setting up RMS project complete." - - -################################################################# -# This function will update the seed in the master_file. The function -# will update the following lines in the master_file: -# -# global_seed = 12345678 -# seeds(n) = 09999999 -# -# All the lines will be updated with the __same_seed__. This function is -# only called once, with the root level .master file as argument, if -# there are other random seeds around they are not touched. -# -# -# What seed to use: -# ----------------- -# -# There are three different systems for choosing seed to use; the three -# methods are tried out in the following order: -# -# 1. If the file "RMS_SEED" exists in current working directory the -# script will use the value found in that file as seed. -# -# 2. If the file random.seeds exists the script will use integer -# nr @iens as seed. The format of the @multi_seed_file is just a -# list of integer, each on a separate line. The first integer should be the number of seeds -# -# 3. If neither of the seed files exist the script will use -# /dev/urandom to initialize the python rng, and then -# random.randint() to get a seed. -# -# The seed which is actually used in the end is appended to the file -# RMS_SEED_USED. Observe that for both the files RMS_SEED and -# @multi_seed_file the format "better" be right - the script will fail -# hard if these files are not formatted correctly. - - -def get_seed( target_path , project , iens): - single_seed_file = "%s/RMS_SEED" % target_path - if os.path.exists( single_seed_file ): - # Using existing single seed file - fileH = open( single_seed_file , "r" ) - new_seed = int( fileH.readline( ) ) - fileH.close() - elif os.path.exists( multi_seed_file ): - fileH = open( multi_seed_file , "r") - seed_list = [ int(x) for x in fileH.readlines() ] - fileH.close() - if seed_list[0] <= iens: - fatal_error("Asking for seed:%d seed_file:%s only has %d seeds\n" % (iens , multi_seed_file , seed_list[0])) - new_seed = seed_list[iens + 1] - else: - # Generate a seed from /dev/urandom - fileH = open( "/dev/urandom" , "r") - buffer = fileH.read( 64 ) - fileH.close() - random.seed( buffer ) - new_seed = random.randint( 0 , 21047483000 ) - - fileH = open("%s/RMS_SEED_USED" % target_path , "a+") - fileH.write("%s ... %d\n" % (time.strftime("%d-%m-%Y %H:%M:%S" , time.localtime(time.time())) , new_seed)) - fileH.close() - return new_seed - - -def set_seed( seed ): - master_file = "%s/%s/.master" % ( target_path , project ) - if not os.path.exists( master_file ): - fatal_error("Could not find rms master file: %s - seems like a broken project" % master_file ) - - fileH = open(master_file , "r") - linelist = fileH.readlines() - fileH.close() - - fileH = open( master_file , "w" ) - for line in linelist: - line = re.sub("^global_seed\s+=\s+\d+" , "global_seed = %d" % seed , line) - line = re.sub("^seeds\((\d+)\)\s+=\s+\d+" , "seeds(\1) = %d" % seed , line) - fileH.write( line ) - fileH.close() - - -################################################################# - -def init( arglist ): - if len(arglist) < 7: - msg = """ -The run_RMS_20xx script needs the following arguments -\n cwd iens rms_version path_to_project replace_path workflow1 | workflow2 workflow3 ... - -The available rms_versions are:%s -""" % rms_version_table.keys() - fatal_error( msg ) - - cwd = sys.argv[1] - iens = int( sys.argv[2] ) - - rms_version = sys.argv[3] - if rms_version_table.has_key( rms_version ): - rms_executable = rms_version_table[ rms_version ] - else: - fatal_error("Sorry: rms_version:%s not recognized - available:%s" % ( rms_version , rms_version_table.keys())) - - - src_project = arglist[4] - if os.path.exists( src_project ): - if os.path.isdir( src_project ): - (src_path , project) = os.path.split( src_project ) - else: - fatal_error("Fatal error - %s is not a directory" % src_project) - else: - fatal_error("Fatal error - project:%s does not exist" % src_project) - - replace_path = sys.argv[5] - - rms_workflows = sys.argv[6:] - - return (cwd , iens , rms_executable , src_path , project , replace_path , rms_workflows ) - - -################################################################# - - - -def unlink_lockfiles( project ): - lock_file1 = "%s/.lock" % project - if os.path.exists( lock_file1 ): - os.unlink( lock_file1 ) - - lock_file2 = "%s/project_lock_file" % project - if os.path.exists( lock_file2 ): - os.unlink( lock_file2 ) - - - -################################################################# - -def run_rms( rms_executable , project , workflow ): - os.environ["LM_LICENSE_FILE"] = rms_license_file - cmd = "%s -nomesa -project %s -batch %s" % ( rms_executable , project , workflow ) - print "Starting rms with command: \"%s\"" % cmd - os.system( cmd ) - print "RMS run is complete" - - - -################################################################# -################################################################# -# Main program starting: - -(target_path , iens , rms_executable , src_path , project , replace_path , rms_workflows) = init( sys.argv ) -if os.path.exists( target_path ): - os.chdir( target_path ) -else: - fatal_error("Directory:%s does not exist \n" % target_path ) - -subst_list = [(replace_path , target_path)] - -# If the dot_master module is present we ignore the replace_path commandline argument -if dot_master: - subst_list = dot_master.subst_list - set_list = dot_master.set_list -else: - set_list = {} - -create_project_directories( src_path , project , target_path , subst_list , set_list) -unlink_lockfiles( project ) -global_seed = get_seed( target_path , project , iens) -for workflow in rms_workflows: - set_seed( global_seed ) - run_rms( rms_executable , project , workflow ) - global_seed += 1 - - - - - - - - diff --git a/ThirdParty/Ert/etc-example/ERT/Scripts/run_eclipse.py b/ThirdParty/Ert/etc-example/ERT/Scripts/run_eclipse.py deleted file mode 100644 index c1ceb59ee6..0000000000 --- a/ThirdParty/Ert/etc-example/ERT/Scripts/run_eclipse.py +++ /dev/null @@ -1,228 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'run_eclipse.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -import os -import sys -import socket -################################################################# -# -# This is a small script used to run ECLIPSE simulations from ERT. The -# script will set up some environment variables, initialize file -# descriptors and then exec() to the ECLIPSE executable (or to mpirun in -# the case of parallell simulations). -# -# The script expects three commandline arguments: -# -# run_eclipse.py version eclipse_name -# -# The @version argument is one of the keys in the the dictionary -# version_table, below. @num_cpu is optional, it will default to one if -# not set. -# -# -################################################################# - - -# The first element in the tuple is the single CPU version to use, and -# the second element is the MPI version to use. - -version_table = {"2007.1" : ("/PATH/ECLIPSE/2007.1/bin/linux_x86_64/eclipse.exe" , "/PATH/ECLIPSE/2007.1/bin/linux_x86_64/eclipse_scampi.exe"), - "2007.2" : ("/PATH/ECLIPSE/2007.2/bin/linux_x86_64/eclipse.exe" , "/PATH/ECLIPSE/2007.2/bin/linux_x86_64/eclipse_scampi.exe"), - "2008.1" : ("/PATH/ECLIPSE/2008.1/bin/linux_x86_64/eclipse.exe" , "/PATH/ECLIPSE/2008.1/bin/linux_x86_64/eclipse_scampi.exe"), - "2008.2" : ("/PATH/ECLIPSE/2008.2/bin/linux_x86_64/eclipse.exe" , "/PATH/ECLIPSE/2008.2/bin/linux_x86_64/eclipse_scampi.exe"), - "2009.1" : ("/PATH/ECLIPSE/2009.1/bin/linux_x86_64/eclipse.exe" , "/PATH/ECLIPSE/2009.1/bin/linux_x86_64/eclipse_scampi.exe"), - "2009.2" : ("/PATH/ECLIPSE/2009.2/bin/linux_x86_64/eclipse.exe" , "/PATH/ECLIPSE/2009.2/bin/linux_x86_64/eclipse_scampi.exe")} - -scali_path = "/opt/scali" -ecldir = "/PATH/ECLIPSE" - -mpirun = "%s/bin/mpirun" % scali_path -config_file = "%s/macros/CONFIG.ECL" % ecldir - -config_link = "ECL.CFG" -env_variables = {"F_UFMTENDIAN" : "big", - "LM_LICENSE_FILE" : "flexlm.server.com" } - -max_cpu_sec = 10000000 -max_wall_sec = 99999999 - -stdin_file = "eclipse.stdin" -stdout_file = "eclipse.stdout" -stderr_file = "eclipse.stderr" - -# End of configuration options -################################################################# - - -# Will take a version string as input, and return the path to the -# executable file. If num_cpu == 1 it will return the serial version, -# whereas the Scali MPI version will be used if num_cpu > 1. -# -# If the @version input argument can not be found in the version_table -# dictionary, or the corresponding file does not exist, the function -# will fail with a fatal error. -def get_executable( version , num_cpu ): - t = version_table.get( version , None ) - if t: - if num_cpu == 1: - executable = t[0] - else: - executable = t[1] - else: - fatal_error("Eclipse version:\'%s\' not recognized. Available versions:%s" % (version , version_table.keys())) - - if not os.path.exists( executable ): - fatal_error("The executable:%s could not be found" % executable) - - return executable - - - - -def init_mpi( base_name , num_cpu ): - # Before the SCALI MPI executable can run we must update the path by prepending - # ECL_SCALI_LOC/bin and ECL_SCALI_LOC/lib64 to the $PATH and $LD_LIBRARY_PATH - # environment variables. - - env_variables["PATH"] = "%s/bin:%s" % ( scali_path , os.getenv("PATH")) - env_variables["LD_LIBRARY_PATH"] = "%s/lib64:%s" % ( scali_path , os.getenv("LD_LIBRARY_PATH")) - machine_list = [] - - - # If the environment variable LSB_HOSTS is set we assume the job is - # running on LSF - otherwise we assume it is running on the current host. - # - # If the LSB_HOSTS variable is indeed set it will be a string like this: - # - # host1 host1 host2 host3 - # - # i.e. each processs is listed with one hostname entry (i.e. NOT - # the :num_proc syntax which is used in LSB_MCPU_HOSTS variable. - - machine_file = "%s.mpi" % base_name - fileH = open( machine_file , "w") - - LSB_HOSTS = os.getenv("LSB_HOSTS") - if LSB_HOSTS: - for host in LSB_HOSTS.split(): - fileH.write("%s\n" % host) - else: - localhost = socket.gethostname() - for i in (range(num_cpu)): - fileH.write("%s\n" % localhost) - - fileH.close() - return machine_file - - - -def fatal_error( msg ): - fileH = open( stderr_file , "w") - fileH.write( msg ) - fileH.close() - sys.exit() - - - -def init_fd( base_name ): - # Creating a stupid input file which is connected to stdin - fileH = open(stdin_file , "w") - fileH.write("%s\n" % base_name); - fileH.write("%s\n" % base_name); - fileH.write("%d\n" % max_cpu_sec); - fileH.write("%d\n\n" % max_wall_sec); - fileH.close() - - # Redirecting stdin / stdout / stderr - fd_stdin = os.open(stdin_file , os.O_RDONLY , 0644) - fd_stdout = os.open(stdout_file , os.O_WRONLY | os.O_TRUNC | os.O_CREAT , 0644); - fd_stderr = os.open(stderr_file , os.O_WRONLY | os.O_TRUNC | os.O_CREAT , 0644); - - os.dup2(fd_stdin , 0) - os.dup2(fd_stdout , 1) - os.dup2(fd_stderr , 2) - - os.close(fd_stdin) - os.close(fd_stdout) - os.close(fd_stderr) - - - -def init_path( base_name ): - smspec_file = "%s.SMSPEC" % base_name - fsmspec_file = "%s.FSMSPEC" % base_name - - if os.path.exists( smspec_file ): - os.unlink( smspec_file ); - - if os.path.exists( fsmspec_file ): - os.unlink( fsmspec_file ); - - if not os.path.exists( config_link ): - os.symlink( config_file , config_link ) - - -def exec_single(executable , env_variables): - os.execve(executable , [ executable ] , env_variables) - - -def exec_mpi(executable , base_name , num_cpu , env_variables): - machine_file = init_mpi( base_name , num_cpu ) - os.execve( mpirun , [mpirun , "-np" , "%s" % num_cpu , "-machinefile" , machine_file , executable , base_name ] , env_variables) - - -################################################################# -# Main program starts. - -if len(sys.argv) < 3 or len(sys.argv) > 4: - fatal_error("The run_eclipse script needs two/three arguments: eclipse_version eclipse_base [num_cpu]") - - -version = sys.argv[1] -(run_path , file) = os.path.split( sys.argv[2] ) -(base_name , ext ) = os.path.splitext( file ) -if run_path: - try: - os.chdir( run_path ) - except: - fatal_error("The run_eclipse script could not change to directory:%s" % run_path) - -if len(sys.argv) == 4: - - # Must support older (svn version before ~ 2844) versions of ERT - # which do not provide a value for the the argument, so - # in this case the run_eclipse.py script will just get the string - # "", we catch the ValueError when converting to int, and - # use the default value num_cpu = 1. - - try: - num_cpu = int( sys.argv[3] ) - except ValueError: - num_cpu = 1 -else: - num_cpu = 1 - -executable = get_executable(version , num_cpu) -init_path( base_name ) -init_fd( base_name ) -if num_cpu == 1: - exec_single( executable , env_variables) -else: - exec_mpi( executable , base_name , num_cpu , env_variables ) - - diff --git a/ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE b/ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE deleted file mode 100644 index 5620171d37..0000000000 --- a/ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE +++ /dev/null @@ -1,3 +0,0 @@ -PORTABLE_EXE ../Scripts/run_eclipse.py -TARGET_FILE -ARGLIST diff --git a/ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE100_2009.2 b/ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE100_2009.2 deleted file mode 100644 index 79f5137a0c..0000000000 --- a/ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE100_2009.2 +++ /dev/null @@ -1,3 +0,0 @@ -PORTABLE_EXE ../Scripts/run_eclipse.py -TARGET_FILE -ARGLIST 2009.2 diff --git a/ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE100_2009.2_NOTARGET b/ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE100_2009.2_NOTARGET deleted file mode 100644 index a6d4718354..0000000000 --- a/ThirdParty/Ert/etc-example/ERT/jobs/ECLIPSE100_2009.2_NOTARGET +++ /dev/null @@ -1,2 +0,0 @@ -PORTABLE_EXE ../Scripts/run_eclipse.py -ARGLIST 2009.2 diff --git a/ThirdParty/Ert/etc-example/ERT/jobs/RUN_RMS_20XX b/ThirdParty/Ert/etc-example/ERT/jobs/RUN_RMS_20XX deleted file mode 100644 index 2870b39abd..0000000000 --- a/ThirdParty/Ert/etc-example/ERT/jobs/RUN_RMS_20XX +++ /dev/null @@ -1,8 +0,0 @@ -STDERR rms.stderr -STDOUT rms.stdout - -PORTABLE_EXE /project/res/etc/ERT/Scripts/run_RMS_20xx --- RMS_PROJECT should be the full path to the rms project -ARGLIST /ROXAR -TARGET_FILE -ENV LM_LICENSE_FILE /prog/roxar/licensing/geomaticLM.lic diff --git a/ThirdParty/Ert/etc-example/ERT/site-config b/ThirdParty/Ert/etc-example/ERT/site-config deleted file mode 100644 index a4a979f65f..0000000000 --- a/ThirdParty/Ert/etc-example/ERT/site-config +++ /dev/null @@ -1,79 +0,0 @@ --- This file is an example of site-wide configuration file for --- ERT. Observe that the user can override/add to everything which is set --- in this file in her per-project configuration file. Observe that --- prior to parsing this file ERT will issue a chdir() system call to --- the location of this file, i.e. you can safely use paths relative --- to the location of this file. - - --- Setting configuration information about the LSF system: -LSF_QUEUE normal -MAX_RUNNING_LSF 20 -LSF_RESOURCES select[cs && x86_64Linux] rusage[ecl100v2000=1:duration=5] - - --- Setting configuration information for running with rsh/ssh between --- workstations. Observe that to actually use this option the user --- must in addition specify which workstations to use in her project --- specific configuration file like: --- RSH_HOST_LIST host1:2 host2:4 host3:4 --- Which will run up to two jobs on 'host1' and four jobs on 'host2' --- and 'host3'; in addition it is essential to have passwordless login --- to the hosts 'hostx'. -MAX_RUNNING_RSH 100 -- You will never get more than the hosts allow anyway. -RSH_COMMAND /usr/bin/ssh - - --- Configuration for running the local workstation: -MAX_RUNNING_LOCAL 4 - - --- Which queue system will we use? -QUEUE_SYSTEM LSF - --- How many times will we submit a job before failing it. Setting this --- to two means first one submit, and then one more. -MAX_SUBMIT 2 - --- Not related to the conventional idea of a license - forget about it .... -LICENSE_PATH license - - --- The script used to run through the jobs in the forward model - a --- very important script. -JOB_SCRIPT Scripts/job_dispatch.py - - --- Installing a couple of jobs. A site will typically have a much --- longer list of available jobs. The arguments of the INSTALL_JOB --- command are first the short name of the job, which will be used --- to refer to the job when setting up the forward, and secondly a --- file with more details on how to run this job. Each of these files --- are used to populate on instance of ext_job_type which is --- implemented in libjob_queue/src/ext_job.c. -INSTALL_JOB RUN_RMS_20XX Config/jobs/RUN_RMS_20XX -INSTALL_JOB ECLIPSE100 Config/jobs/ECLIPSE100 -INSTALL_JOB ECLIPSE100_2009.2 Config/jobs/ECLIPSE100_2009.2 -INSTALL_JOB ECLIPSE100_2009.2_NOTARGET Config/jobs/ECLIPSE100_2009.2_NOTARGET - - - --- You can set environment variables with the SETENV command. The --- SETENV command understands $VAR, so you can also update variables. - --- The LSF variables must be set for LSF to work, this is similar to --- sourcing a LSF configuration file. -SETENV LSF_BINDIR /LSF_PATH/bin -SETENV LSF_LIBDIR /LSF_PATH/lib -SETENV XLSF_UIDDIR /LSF_PATH/lib/uid -SETENV LSF_SERVERDIR /LSF_PATH/etc -SETENV LSF_ENVDIR /LS_PATH/conf - --- In addition to SETENV you can also use UPDATE_PATH to update ':' --- separated path related environment variables. UPDATE_PATH will --- prepend the existing value of PATH with the new value. - -UPDATE_PATH PATH /funky/path/bin -SETENV LD_LIBRARY_PATH /funky/path/lib:$LD_LIBRARY_PATH - - diff --git a/ThirdParty/Ert/etc-example/README b/ThirdParty/Ert/etc-example/README deleted file mode 100644 index 9c12ddd5e2..0000000000 --- a/ThirdParty/Ert/etc-example/README +++ /dev/null @@ -1,42 +0,0 @@ -This directory contains some example configuration files / scripts for -ERT. This directory should typically be installed in shared location -where it is readably for everyone. The files/directories are: - -ERT/site-config ---------------- -This is the shared configuration file for all ERT users. - - -ERT/Scripts ------------ -This is a collection of scripts. These are: - - o ERT/Scripts/job_dispatch.py - the executable program started by - ERT, which again will start and run the other programs in the - forward model. A very important script; the path to this script is - set with the JOB_SCRIPT variable in the site-config file. - - o ERT/Scripts/run_eclipse.py: This a script to run ECLIPSE - nothing - special about this. If you want to use this script, you must at the - very least update the paths to the ECLIPSE binary. - - o ERT/Scripts/run_RMS_20xx: A script to run version 20xx of - RMS. Observe that this script is specifically designed to work - around a bug with exporting RMS datasets to a relative path; that - bug is now fixed in RMS. - - -ERT/jobs/*** -------------- -The files in directory ERT/jobs are job-description files which are -used to 'install' jobs into ERT. The directory ERT/jobs/ contains -small config files to install three different ECLIPSE jobs. (Make the -effort and understand the difference between ECLIPSE100_2009.2 and -ECLIPSE100_2009.2_NOTARGET, this will serve you well when debugging -problems with failed jobs). - -The jobs in ERT/jobs are installed into ERT with the INSTALL_JOB -commands in the sitewide configuration file. - - - diff --git a/ThirdParty/Ert/libanalysis/CMakeLists.txt b/ThirdParty/Ert/libanalysis/CMakeLists.txt deleted file mode 100644 index 883682c544..0000000000 --- a/ThirdParty/Ert/libanalysis/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -include(cmake/ert_module.cmake) - -add_subdirectory( script ) -add_subdirectory( src ) -add_subdirectory( modules ) - -if (BUILD_TESTS) - add_subdirectory( tests ) -endif() - -if (BUILD_APPLICATIONS) - add_subdirectory( applications ) -endif() - diff --git a/ThirdParty/Ert/libanalysis/applications/CMakeLists.txt b/ThirdParty/Ert/libanalysis/applications/CMakeLists.txt deleted file mode 100644 index 48241603c4..0000000000 --- a/ThirdParty/Ert/libanalysis/applications/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -add_executable( ert_module_test ert_module_test.c ) -target_link_libraries( ert_module_test analysis ert_util ) - -if (USE_RUNPATH) - add_runpath( ert_module_test ) -endif() - -set (destination ${CMAKE_INSTALL_PREFIX}/bin) - -install(TARGETS ert_module_test DESTINATION ${destination}) - -if (INSTALL_GROUP) - install(CODE "EXECUTE_PROCESS(COMMAND chgrp ${INSTALL_GROUP} ${destination}/ert_module_test)") - install(CODE "EXECUTE_PROCESS(COMMAND chmod g+w ${destination}/ert_module_test)") -endif() - -if (BUILD_TESTS) - ert_module_name( VAR_RML rml_enkf ${LIBRARY_OUTPUT_PATH} ) - add_test( analysis_module_test_RML ${EXECUTABLE_OUTPUT_PATH}/ert_module_test ${VAR_RML}) -endif() diff --git a/ThirdParty/Ert/libanalysis/applications/ert_module_test.c b/ThirdParty/Ert/libanalysis/applications/ert_module_test.c deleted file mode 100644 index b6ddd9be74..0000000000 --- a/ThirdParty/Ert/libanalysis/applications/ert_module_test.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'module_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - -#include - -#include - - -int check_module( rng_type * rng , const char * lib_name ) { - analysis_module_load_status_enum load_status; - analysis_module_type * module = analysis_module_alloc_external__( rng , lib_name , false , &load_status); - if (module != NULL) { - printf("Module loaded successfully\n"); - analysis_module_free( module ); - return 0; - } else { - if (load_status == DLOPEN_FAILURE) { - printf("\ndlerror(): %s\n\n",dlerror()); - printf("The runtime linker could not open the library:%s.\n", lib_name); - printf("For the runtime linker to succesfully open your library\n"); - printf("at least one of two must be satisfied: \n\n"); - printf(" 1. You give the FULL PATH to library - including .so extension\n\n"); - printf(" 2. The path containing the library is in LD_LIBRARY_PATH.\n\n"); - printf("In addition all libraries needed by your module must be found\n"); - } else if (load_status == LOAD_SYMBOL_TABLE_NOT_FOUND) { - printf("\nThe library %s was loaded successfully, however\n",lib_name); - printf("the symbol table:\'%s\' was not found. You must make sure\n",EXTERNAL_MODULE_NAME); - printf("that the \'analysis_table_type\' structure at the bottom\n"); - printf("of the source file is named exactly: \'analysis_table\'.\n"); - printf("See documentation of \'symbol_table\' in modules.txt.\n\n"); - } - } - return 1; -} - - - -int main( int argc , char ** argv) { - exit( check_module( NULL , argv[1] ) ); -} diff --git a/ThirdParty/Ert/libanalysis/applications/main_test.c b/ThirdParty/Ert/libanalysis/applications/main_test.c deleted file mode 100644 index 7f0449909e..0000000000 --- a/ThirdParty/Ert/libanalysis/applications/main_test.c +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -#include -#include - - -int main( int argc , char ** argv) { - rng_type * rng = NULL; - if (0) - { - analysis_module_type * module = analysis_module_alloc_external( rng , "./simple_enkf.so" , "SimpleEnKF" ); - if (module != NULL) { - analysis_module_set_var( module , "FLAG" , "42" ); - analysis_module_set_var( module , "VarX" , "42.77" ); - analysis_module_free( module ); - } else - fprintf(stderr,"Hmmmm - failed to load external analysis module. \n"); - - } - - - { - analysis_module_type * module = analysis_module_alloc_internal( rng , "simple_enkf_symbol_table", "SimpleEnKF" ); - if (module != NULL) { - analysis_module_set_var( module , "FLAG" , "42" ); - analysis_module_set_var( module , "VarX" , "42.7708" ); - analysis_module_free( module ); - } else - fprintf(stderr,"Hmmmm - failed to load internal analysis module. \n"); - } - -} diff --git a/ThirdParty/Ert/libanalysis/cmake/ert_module.cmake b/ThirdParty/Ert/libanalysis/cmake/ert_module.cmake deleted file mode 100644 index db3857f401..0000000000 --- a/ThirdParty/Ert/libanalysis/cmake/ert_module.cmake +++ /dev/null @@ -1,23 +0,0 @@ -function( ert_module target args source_files ) - - set( build_file ${target}.so ) - set( depends analysis ) - set( arg_string "${target} ${args}") - separate_arguments( arg_list UNIX_COMMAND "${arg_string}") - foreach (src_file ${source_files} ) - list(APPEND arg_list ${CMAKE_CURRENT_SOURCE_DIR}/${src_file} ) - list(APPEND depends ${CMAKE_CURRENT_SOURCE_DIR}/${src_file} ) - endforeach() - - add_custom_command( - OUTPUT ${build_file} - COMMAND ${PROJECT_SOURCE_DIR}/libanalysis/script/ert_module - ARGS ${arg_list} - DEPENDS ${depends}) - - install(FILES ${build_file} DESTINATION ${CMAKE_INSTALL_LIBDIR}) - - get_filename_component( module ${target} NAME ) - add_custom_target( ${module} ALL DEPENDS ${build_file} ) - -endfunction() diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/analysis_module.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/analysis_module.h deleted file mode 100644 index a20937786f..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/analysis_module.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'analysis_module.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ANALYSIS_MODULE_H -#define ERT_ANALYSIS_MODULE_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include - -/* - These are option flag values which are used by the core ert code to - query the module of it's needs and capabilities. For instance to to - determine whether the data should be scaled prior to analysis the - core code will issue the call: - - if (analysis_module_get_option( module, ANALYSIS_SCALE_DATA)) - obs_data_scale( obs_data , S , E , D , R , dObs ); - - It is the responsability of the module to set the various flags. -*/ - - -typedef enum { - ANALYSIS_NEED_ED = 1, - ANALYSIS_USE_A = 4, // The module will read the content of A - but not modify it. - ANALYSIS_UPDATE_A = 8, // The update will be based on modifying A directly, and not on an X matrix. - ANALYSIS_SCALE_DATA = 16, - ANALYSIS_ITERABLE = 32 // The module can bu used as an iterative smoother. -} analysis_module_flag_enum; - - -#define ANALYSIS_MODULE_FLAG_ENUM_SIZE 5 -#define ANALYSIS_MODULE_FLAG_ENUM_DEFS {.value = ANALYSIS_NEED_ED , .name = "ANALYSIS_NEED_ED"},\ - {.value = ANALYSIS_USE_A , .name = "ANALYSIS_USE_A"},\ - {.value = ANALYSIS_UPDATE_A , .name = "ANALYSIS_UPDATE_A"},\ - {.value = ANALYSIS_SCALE_DATA , .name = "ANALYSIS_SCALE_DATA"},\ - {.value = ANALYSIS_ITERABLE , .name = "ANALYSIS_ITERABLE"} - - -#define EXTERNAL_MODULE_NAME "analysis_table" -#define EXTERNAL_MODULE_SYMBOL analysis_table - - typedef enum { - LOAD_OK = 0, - DLOPEN_FAILURE = 1, - LOAD_SYMBOL_TABLE_NOT_FOUND = 2 - } analysis_module_load_status_enum; - - - typedef struct analysis_module_struct analysis_module_type; - - analysis_module_type * analysis_module_alloc_internal__( rng_type * rng , const char * symbol_table , bool verbose , analysis_module_load_status_enum * load_status); - analysis_module_type * analysis_module_alloc_internal( rng_type * rng , const char * symbol_table ); - - analysis_module_type * analysis_module_alloc_external__(rng_type * rng , const char * lib_name , bool verbose , analysis_module_load_status_enum * load_status); - analysis_module_type * analysis_module_alloc_external( rng_type * rng , const char * libname ); - - void analysis_module_free( analysis_module_type * module ); - void analysis_module_free__( void * arg); - - void analysis_module_initX(analysis_module_type * module , - matrix_type * X , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D); - - - void analysis_module_updateA(analysis_module_type * module , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D , - const module_info_type* module_info); - - - void analysis_module_init_update( analysis_module_type * module , - const bool_vector_type * ens_mask , - const matrix_type * S , - const matrix_type * R , - const matrix_type * dObs , - const matrix_type * E , - const matrix_type * D ); - - - const char * analysis_module_get_lib_name( const analysis_module_type * module); - bool analysis_module_internal( const analysis_module_type * module ); - bool analysis_module_set_var( analysis_module_type * module , const char * var_name , const char * string_value ); - const char * analysis_module_get_table_name( const analysis_module_type * module); - const char * analysis_module_get_name( const analysis_module_type * module ); - void analysis_module_set_name( analysis_module_type * module , const char * name); - bool analysis_module_check_option( const analysis_module_type * module , long flag); - void analysis_module_complete_update( analysis_module_type * module ); - - bool analysis_module_has_var( const analysis_module_type * module , const char * var ); - double analysis_module_get_double( const analysis_module_type * module , const char * var); - int analysis_module_get_int( const analysis_module_type * module , const char * var); - bool analysis_module_get_bool( const analysis_module_type * module , const char * var); - void * analysis_module_get_ptr( const analysis_module_type * module , const char * var); - const char * analysis_module_flag_enum_iget( int index, int * value); - - - - UTIL_IS_INSTANCE_HEADER( analysis_module ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/analysis_table.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/analysis_table.h deleted file mode 100644 index bbbbc7993e..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/analysis_table.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef ERT_ANALYSIS_TABLE_H -#define ERT_ANALYSIS_TABLE_H - -#ifdef __cplusplus -extern "C" { -#endif - - -#include -#include -#include - -#include - - - typedef void (analysis_updateA_ftype) (void * module_data , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D , - const module_info_type* module_info); - - - typedef void (analysis_initX_ftype) (void * module_data , - matrix_type * X , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D ); - - - typedef bool (analysis_set_int_ftype) (void * module_data , const char * flag , int value); - typedef bool (analysis_set_bool_ftype) (void * module_data , const char * flag , bool value); - typedef bool (analysis_set_double_ftype) (void * module_data , const char * var , double value); - typedef bool (analysis_set_string_ftype) (void * module_data , const char * var , const char * value); - typedef void (analysis_free_ftype) (void * ); - typedef void * (analysis_alloc_ftype) ( rng_type * rng ); - - - typedef void (analysis_init_update_ftype) (void * module_data, - const bool_vector_type * ens_mask , - const matrix_type * S , - const matrix_type * R , - const matrix_type * dObs , - const matrix_type * E , - const matrix_type * D); - - typedef void (analysis_complete_update_ftype) (void * module_data ); - - typedef long (analysis_get_options_ftype) (void * module_data , long option); - - typedef bool (analysis_has_var_ftype) (const void * module_data , const char * var_name); - typedef int (analysis_get_int_ftype) (const void * module_data , const char * var_name ); - typedef double (analysis_get_double_ftype) (const void * module_data , const char * var_name ); - typedef bool (analysis_get_bool_ftype) (const void * module_data , const char * var_name ); - typedef void * (analysis_get_ptr_ftype) (const void * module_data , const char * var_name ); - -/*****************************************************************/ - - -typedef struct { - const char * name; - analysis_updateA_ftype * updateA; - analysis_initX_ftype * initX; - analysis_init_update_ftype * init_update; - analysis_complete_update_ftype * complete_update; - - analysis_free_ftype * freef; - analysis_alloc_ftype * alloc; - - analysis_set_int_ftype * set_int; - analysis_set_double_ftype * set_double; - analysis_set_bool_ftype * set_bool; - analysis_set_string_ftype * set_string; - analysis_get_options_ftype * get_options; - - analysis_has_var_ftype * has_var; - analysis_get_int_ftype * get_int; - analysis_get_double_ftype * get_double; - analysis_get_bool_ftype * get_bool; - analysis_get_ptr_ftype * get_ptr; -} analysis_table_type; - - - - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/cv_enkf.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/cv_enkf.h deleted file mode 100644 index 1f5d518859..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/cv_enkf.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'cv_enkf.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -typedef struct cv_enkf_data_struct cv_enkf_data_type; - -void * cv_enkf_data_alloc( rng_type * rng ); -void cv_enkf_data_free( void * arg ); - -void cv_enkf_init_update( void * arg , - const bool_vector_type * ens_mask , - const matrix_type * S , - const matrix_type * R , - const matrix_type * dObs , - const matrix_type * E , - const matrix_type * D ); - -void cv_enkf_initX(void * module_data , - matrix_type * X , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D); - -bool cv_enkf_set_double( void * arg , const char * var_name , double value); -bool cv_enkf_set_int( void * arg , const char * var_name , int value); -bool cv_enkf_set_bool( void * arg , const char * var_name , bool value ); - -void cv_enkf_set_truncation( cv_enkf_data_type * data , double truncation ); -void cv_enkf_set_pen_press( cv_enkf_data_type * data , bool value ); -void cv_enkf_set_subspace_dimension( cv_enkf_data_type * data , int subspace_dimension); - diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/enkf_linalg.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/enkf_linalg.h deleted file mode 100644 index c4affb895e..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/enkf_linalg.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef ERT_ENKF_LINALG_H -#define ERT_ENKF_LINALG_H - -#include -#include -#include - - -int enkf_linalg_get_PC( const matrix_type * S0, - const matrix_type * dObs , - double truncation, - int ncomp, - matrix_type * PC, - matrix_type * PC_obs , - double_vector_type * singular_values); - -int enkf_linalg_num_PC(const matrix_type * S , double truncation ); - - -void enkf_linalg_init_stdX( matrix_type * X , - const matrix_type * S , - const matrix_type * D , - const matrix_type * W , - const double * eig , - bool bootstrap); - - -void enkf_linalg_init_sqrtX(matrix_type * X5 , - const matrix_type * S , - const matrix_type * randrot , - const matrix_type * innov , - const matrix_type * W , - const double * eig , - bool bootstrap); - - -void enkf_linalg_Cee(matrix_type * B, int nrens , const matrix_type * R , const matrix_type * U0 , const double * inv_sig0); - - -int enkf_linalg_svd_truncation(const matrix_type * S , - double truncation , - int ncomp , - dgesvd_vector_enum store_V0T , - double * sig0, - matrix_type * U0 , - matrix_type * V0T); - - -int enkf_linalg_svdS(const matrix_type * S , - double truncation , - int ncomp , - dgesvd_vector_enum jobVT , - double * sig0, - matrix_type * U0 , - matrix_type * V0T); - - - -matrix_type * enkf_linalg_alloc_innov( const matrix_type * dObs , const matrix_type * S); - -void enkf_linalg_lowrankCinv__(const matrix_type * S , - const matrix_type * R , - matrix_type * V0T , - matrix_type * Z, - double * eig , - matrix_type * U0, - double truncation, - int ncomp); - - - -void enkf_linalg_lowrankCinv(const matrix_type * S , - const matrix_type * R , - matrix_type * W , /* Corresponding to X1 from Eq. 14.29 */ - double * eig , /* Corresponding to 1 / (1 + Lambda_1) (14.29) */ - double truncation , - int ncomp); - -void enkf_linalg_lowrankE(const matrix_type * S , /* (nrobs x nrens) */ - const matrix_type * E , /* (nrobs x nrens) */ - matrix_type * W , /* (nrobs x nrmin) Corresponding to X1 from Eqs. 14.54-14.55 */ - double * eig , /* (nrmin) Corresponding to 1 / (1 + Lambda1^2) (14.54) */ - double truncation , - int ncomp); - -void enkf_linalg_genX2(matrix_type * X2 , const matrix_type * S , const matrix_type * W , const double * eig); -void enkf_linalg_genX3(matrix_type * X3 , const matrix_type * W , const matrix_type * D , const double * eig); - -void enkf_linalg_meanX5(const matrix_type * S , - const matrix_type * W , - const double * eig , - const matrix_type * innov , - matrix_type * X5); - - -void enkf_linalg_X5sqrt(matrix_type * X2 , matrix_type * X5 , const matrix_type * randrot, int nrobs); - -matrix_type * enkf_linalg_alloc_mp_randrot(int ens_size , rng_type * rng); -void enkf_linalg_set_randrot( matrix_type * Q , rng_type * rng); -void enkf_linalg_checkX(const matrix_type * X , bool bootstrap); - - -//rml_enkf functions - -void enkf_linalg_rml_enkfX1(matrix_type *X1, matrix_type * Udr ,matrix_type * S ,matrix_type *R); -void enkf_linalg_rml_enkfX2(matrix_type *X2, double *Wdr, matrix_type * X1 ,double a , int nsign); -void enkf_linalg_rml_enkfX3(matrix_type *X3, matrix_type *VdTr, double *Wdr,matrix_type *X2, int nsign); - -double enkf_linalg_data_mismatch(matrix_type *D , matrix_type *R , matrix_type *Sk); -void enkf_linalg_Covariance(matrix_type *Cd, const matrix_type *E, double nsc ,int nrobs); -void enkf_linalg_rml_enkfAm(matrix_type * Um, const double * Wm,int nsign1); - -void enkf_linalg_rml_enkfX7(matrix_type * X7, matrix_type * VdT, double * Wdr, double a,matrix_type * X6); - -#endif diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/fwd_step_enkf.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/fwd_step_enkf.h deleted file mode 100644 index 627ae5efd4..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/fwd_step_enkf.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'fwd_step_enkf.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include - -typedef struct fwd_step_enkf_data_struct fwd_step_enkf_data_type; - -void * fwd_step_enkf_data_alloc( rng_type * rng ); -void fwd_step_enkf_data_free( void * arg ); - -void fwd_step_enkf_updateA(void * module_data , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D , - const module_info_type* module_info); - - - diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/fwd_step_log.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/fwd_step_log.h deleted file mode 100644 index d48e587f98..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/fwd_step_log.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'fwd_step_log.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef FWD_STEP_LOG_H -#define FWD_STEP_LOG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - - typedef struct fwd_step_log_struct fwd_step_log_type; - - fwd_step_log_type * fwd_step_log_alloc(); - void fwd_step_log_free(fwd_step_log_type * fwd_step_log); - bool fwd_step_log_get_clear_log( const fwd_step_log_type * data ); - void fwd_step_log_set_clear_log( fwd_step_log_type * data , bool clear_log); - void fwd_step_log_set_log_file( fwd_step_log_type * data , const char * log_file ); - const char * fwd_step_log_get_log_file( const fwd_step_log_type * data); - void fwd_step_log_open( fwd_step_log_type * fwd_step_log ); - void fwd_step_log_close( fwd_step_log_type * fwd_step_log ); - void fwd_step_log_line( fwd_step_log_type * fwd_step_log , const char * fmt , ...); - bool fwd_step_log_is_open( const fwd_step_log_type * fwd_step_log ); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/module_data_block.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/module_data_block.h deleted file mode 100644 index aecac5803f..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/module_data_block.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'module_data_blocks.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef MODULE_DATA_BLOCKS_H -#define MODULE_DATA_BLOCKS_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - struct module_data_block_struct { - UTIL_TYPE_ID_DECLARATION; - char * key; - const int * index_list; - int A_row_start; - int n_active; - }; - - typedef struct module_data_block_struct module_data_block_type; - - module_data_block_type * module_data_block_alloc( const char * key, const int * index_list , const int row_start, const int n_active); - const char * module_data_block_get_key(const module_data_block_type * module_data_block); - const int module_data_block_get_row_start(const module_data_block_type * module_data_block); - const int module_data_block_get_row_end(const module_data_block_type * module_data_block); - const int * module_data_block_get_active_indices(const module_data_block_type * module_data_block ); - void module_data_block_free(module_data_block_type * module_data_block); - void module_data_block_free__( void * arg ); - - UTIL_IS_INSTANCE_HEADER( module_data_block ); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/module_data_block_vector.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/module_data_block_vector.h deleted file mode 100644 index 9ab86fbf8b..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/module_data_block_vector.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'module_data_block_vector.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#ifndef ERT_MODULE_DATA_BLOCK_VECTOR_H -#define ERT_MODULE_DATA_BLOCK_VECTOR_H - -#ifdef __cplusplus -extern "C" { -#endif - - - -#include - - typedef struct module_data_block_vector_struct module_data_block_vector_type; - - module_data_block_vector_type * module_data_block_vector_alloc(); - void module_data_block_vector_free(); - void module_data_block_vector_add_data_block( module_data_block_vector_type * module_data_block_vector , const module_data_block_type * data_block); - module_data_block_type * module_data_block_vector_iget_module_data_block(const module_data_block_vector_type * module_data_block_vector, int index); - int module_data_block_vector_get_size(const module_data_block_vector_type * module_data_block_vector); - - UTIL_IS_INSTANCE_HEADER( module_data_block_vector ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/module_info.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/module_info.h deleted file mode 100644 index a5783d17a3..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/module_info.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'module_info.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#ifndef ERT_MODULE_INFO_H -#define ERT_MODULE_INFO_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - - typedef struct module_info_struct module_info_type; - - module_info_type * module_info_alloc(const char* ministep_name); - void module_info_free(); - char * module_info_get_ministep_name(const module_info_type * module_info); - module_data_block_vector_type * module_info_get_data_block_vector(const module_info_type * module_info); - module_obs_block_vector_type * module_info_get_obs_block_vector(const module_info_type * module_info); - - UTIL_IS_INSTANCE_HEADER( module_info ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/module_obs_block.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/module_obs_block.h deleted file mode 100644 index e838e8ea16..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/module_obs_block.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'module_obs_blocks.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef MODULE_OBS_BLOCKS_H -#define MODULE_OBS_BLOCKS_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - struct module_obs_block_struct { - UTIL_TYPE_ID_DECLARATION; - char * key; - const int * index_list; - int D_row_start; - int n_active; - }; - - typedef struct module_obs_block_struct module_obs_block_type; - - module_obs_block_type * module_obs_block_alloc( const char * key, const int * index_list, const int row_start, const int n_active); - const char * module_obs_block_get_key(const module_obs_block_type * module_obs_block); - const int module_obs_block_get_row_start(const module_obs_block_type * module_obs_block); - const int module_obs_block_get_row_end(const module_obs_block_type * module_obs_block); - const int * module_obs_block_get_active_indices(const module_obs_block_type * module_obs_block ); - void module_obs_block_free(module_obs_block_type * module_obs_block); - void module_obs_block_free__( void * arg ); - - UTIL_IS_INSTANCE_HEADER( module_obs_block ); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/module_obs_block_vector.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/module_obs_block_vector.h deleted file mode 100644 index 75063e643c..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/module_obs_block_vector.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'module_obs_block_vector.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#ifndef ERT_MODULE_OBS_BLOCK_VECTOR_H -#define ERT_MODULE_OBS_BLOCK_VECTOR_H - -#ifdef __cplusplus -extern "C" { -#endif - - - -#include - - typedef struct module_obs_block_vector_struct module_obs_block_vector_type; - - module_obs_block_vector_type * module_obs_block_vector_alloc(); - void module_obs_block_vector_free(); - void module_obs_block_vector_add_obs_block( module_obs_block_vector_type * module_obs_block_vector , module_obs_block_type * obs_block); - module_obs_block_type * module_obs_block_vector_iget_module_obs_block(const module_obs_block_vector_type * module_obs_block_vector, int index); - const module_obs_block_type * module_obs_block_vector_search_module_obs_block(const module_obs_block_vector_type * module_obs_block_vector, int global_index); - int module_obs_block_vector_get_size(const module_obs_block_vector_type * module_obs_block_vector); - - UTIL_IS_INSTANCE_HEADER( module_obs_block_vector ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libanalysis/include/ert/analysis/std_enkf.h b/ThirdParty/Ert/libanalysis/include/ert/analysis/std_enkf.h deleted file mode 100644 index fabaa9969f..0000000000 --- a/ThirdParty/Ert/libanalysis/include/ert/analysis/std_enkf.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef ERT_STD_ENKF_H -#define ERT_STD_ENKF_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include - -#define DEFAULT_ENKF_TRUNCATION_ 0.98 -#define ENKF_TRUNCATION_KEY_ "ENKF_TRUNCATION" -#define ENKF_NCOMP_KEY_ "ENKF_NCOMP" -#define USE_EE_KEY_ "USE_EE" -#define USE_GE_KEY_ "USE_GE" -#define ANALYSIS_SCALE_DATA_KEY_ "ANALYSIS_SCALE_DATA" - - typedef struct std_enkf_data_struct std_enkf_data_type; - - - bool std_enkf_set_double( void * arg , const char * var_name , double value); - - int std_enkf_get_subspace_dimension( std_enkf_data_type * data ); - void std_enkf_set_truncation( std_enkf_data_type * data , double truncation ); - void std_enkf_set_subspace_dimension( std_enkf_data_type * data , int subspace_dimension); - void std_enkf_set_lambda0( std_enkf_data_type * data , double lambda0 ); - bool std_enkf_has_var( const void * arg, const char * var_name); - - double std_enkf_get_truncation( std_enkf_data_type * data ); - void * std_enkf_data_alloc( rng_type * rng); - void std_enkf_data_free( void * module_data ); - - bool std_enkf_get_bool( const void * arg, const char * var_name); - int std_enkf_get_int( const void * arg, const char * var_name); - double std_enkf_get_double( const void * arg, const char * var_name); - bool std_enkf_has_var( const void * arg, const char * var_name); - long std_enkf_get_options( void * arg , long flag ); - bool std_enkf_set_bool( void * arg , const char * var_name , bool value); - bool std_enkf_set_int( void * arg , const char * var_name , int value); - bool std_enkf_set_double( void * arg , const char * var_name , double value); - void std_enkf_initX(void * module_data , - matrix_type * X , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libanalysis/modules/CMakeLists.txt b/ThirdParty/Ert/libanalysis/modules/CMakeLists.txt deleted file mode 100644 index 799d533169..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - -set( RML_SOURCE_FILES - rml_enkf_config.c - rml_enkf_log.c - rml_enkf.c - rml_enkf_common.c ) - -set( header_files analysis_module.h enkf_linalg.h analysis_table.h std_enkf.h rml_enkf_common.h) -add_library( rml_enkf SHARED ${RML_SOURCE_FILES} ) -add_library( std_enkf_debug SHARED std_enkf_debug.c ) - -set_target_properties( rml_enkf PROPERTIES VERSION 1.0 SOVERSION 1.0 PREFIX "") -set_target_properties( std_enkf_debug PROPERTIES VERSION 1.0 SOVERSION 1.0 PREFIX "") - -target_link_libraries( rml_enkf analysis dl ) -target_link_libraries( std_enkf_debug analysis dl ) - -if (USE_RUNPATH) - add_runpath( rml_enkf ) - add_runpath( std_enkf_debug ) -endif() - -if (BUILD_TESTS) - add_subdirectory( tests ) -endif() - -if (INSTALL_ERT) - install(TARGETS rml_enkf DESTINATION ${CMAKE_INSTALL_LIBDIR}) - install(TARGETS std_enkf_debug DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif() - - -#----------------------------------------------------------------- - -# Alternative script based build: -#if (BUILD_TESTS) -# if (BUILD_APPLICATIONS) -#set( args "--silent --exclude-ert -I${PROJECT_SOURCE_DIR}/libanalysis/include -I${PROJECT_SOURCE_DIR}/libert_util/include -I${CMAKE_CURRENT_SOURCE_DIR} -I${PROJECT_BINARY_DIR}/libert_util/include") - - -#set( RML_SOURCE_FILES -# rml_enkf.c -# rml_enkf_common.c ) - -#ert_module( ${LIBRARY_OUTPUT_PATH}/rml_enkf ${args} "${RML_SOURCE_FILES}") - - - diff --git a/ThirdParty/Ert/libanalysis/modules/deprecated/rml_enkf.c b/ThirdParty/Ert/libanalysis/modules/deprecated/rml_enkf.c deleted file mode 100644 index d86ca89341..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/deprecated/rml_enkf.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rml_enkf.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -/* - A random 'magic' integer id which is used for run-time type checking - of the input data. -*/ -#define RML_ENKF_TYPE_ID 261123 - - - - -/* - Observe that only one of the settings subspace_dimension and - truncation can be valid at a time; otherwise the svd routine will - fail. This implies that the set_truncation() and - set_subspace_dimension() routines will set one variable, AND - INVALIDATE THE OTHER. For most situations this will be OK, but if - you have repeated calls to both of these functions the end result - might be a surprise. -*/ -#define INVALID_SUBSPACE_DIMENSION -1 -#define INVALID_TRUNCATION -1 -#define DEFAULT_SUBSPACE_DIMENSION INVALID_SUBSPACE_DIMENSION - - - - - -/* - The configuration data used by the rml_enkf module is contained in a - rml_enkf_data_struct instance. The data type used for the rml_enkf - module is quite simple; with only a few scalar variables, but there - are essentially no limits to what you can pack into such a datatype. - - All the functions in the module have a void pointer as the first - argument, this will immediately be casted to a rml_enkf_data_type - instance, to get some type safety the UTIL_TYPE_ID system should be - used (see documentation in util.h) - - The data structure holding the data for your analysis module should - be created and initialized by a constructor, which should be - registered with the '.alloc' element of the analysis table; in the - same manner the desctruction of this data should be handled by a - destructor or free() function registered with the .freef field of - the analysis table. -*/ - - -typedef struct rml_enkf_data_struct rml_enkf_data_type; - -struct rml_enkf_data_struct { - UTIL_TYPE_ID_DECLARATION; - double truncation; // Controlled by config key: ENKF_TRUNCATION_KEY - int subspace_dimension; // Controlled by config key: ENKF_NCOMP_KEY (-1: use Truncation instead) - long option_flags; - - int iteration_nr; // Keep track of the outer iteration loop - double lambda; // parameter to control the search direction in Marquardt levenberg optimization - double lambda0; // Initial lambda value - double Sk; // Objective function value - double Std; // Standard Deviation of the Objective function - matrix_type *state; - bool_vector_type * ens_mask; -}; - - -/* - This is a macro which will expand to generate a function: - - rml_enkf_data_type * rml_enkf_data_safe_cast( void * arg ) {} - - which is used for runtime type checking of all the functions which - accept a void pointer as first argument. -*/ -static UTIL_SAFE_CAST_FUNCTION( rml_enkf_data , RML_ENKF_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION_CONST( rml_enkf_data , RML_ENKF_TYPE_ID ) - - -double rml_enkf_get_truncation( rml_enkf_data_type * data ) { - return data->truncation; -} - -int rml_enkf_get_subspace_dimension( rml_enkf_data_type * data ) { - return data->subspace_dimension; -} - -void rml_enkf_set_truncation( rml_enkf_data_type * data , double truncation ) { - data->truncation = truncation; - if (truncation > 0.0) - data->subspace_dimension = INVALID_SUBSPACE_DIMENSION; -} - -void rml_enkf_set_lambda0(rml_enkf_data_type * data , double lambda0 ) { - data->lambda0 = lambda0; -} - -void rml_enkf_set_subspace_dimension( rml_enkf_data_type * data , int subspace_dimension) { - data->subspace_dimension = subspace_dimension; - if (subspace_dimension > 0) - data->truncation = INVALID_TRUNCATION; -} - -void rml_enkf_set_iteration_number( rml_enkf_data_type *data , int iteration_number ) { - data->iteration_nr = iteration_number; -} - - -void * rml_enkf_data_alloc( rng_type * rng) { - rml_enkf_data_type * data = util_malloc( sizeof * data ); - UTIL_TYPE_ID_INIT( data , RML_ENKF_TYPE_ID ); - - rml_enkf_set_truncation( data , DEFAULT_ENKF_TRUNCATION_ ); - rml_enkf_set_subspace_dimension( data , DEFAULT_SUBSPACE_DIMENSION ); - data->option_flags = ANALYSIS_NEED_ED + ANALYSIS_UPDATE_A + ANALYSIS_ITERABLE + ANALYSIS_SCALE_DATA; - data->iteration_nr = 0; - data->Std = 0; - data->state = matrix_alloc(1,1); // This will be resized under use; but we need a valid instance - data->lambda0 = -1.0; - data->ens_mask = bool_vector_alloc(0,false); - return data; -} - - -void rml_enkf_data_free( void * module_data ) { - rml_enkf_data_type * data = rml_enkf_data_safe_cast( module_data ); - matrix_free( data->state ); - bool_vector_free(data->ens_mask); - free( data ); -} - - - - - -/* - About the matrix Cd: The matrix Cd is calculated based on the content - of the E input matrix. In the original implementation this matrix was - only calculated in the first iteration, and then reused between subsequent - iterations. - - Due to deactivating outliers the number of active observations can change - from one iteration to the next, if the matrix Cd is then reused between - iterations we will get a matrix size mismatch in the linear algebra. In the - current implementation the Cd matrix is recalculated based on the E input - for each iteration. - */ - -void rml_enkf_updateA(void * module_data , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D) { - - - rml_enkf_data_type * data = rml_enkf_data_safe_cast( module_data ); - double truncation = data->truncation; - double Sk_new; - double Std_new; - - int ens_size = matrix_get_columns( S ); - int nrobs = matrix_get_rows( S ); - matrix_type * Cd = matrix_alloc( nrobs , nrobs); - double nsc = 1/sqrt(ens_size-1); - matrix_type * Skm = matrix_alloc(matrix_get_columns(D),matrix_get_columns(D)); - FILE *fp = util_fopen("rml_enkf_output","a"); - - int nrmin = util_int_min( ens_size , nrobs); - matrix_type * Ud = matrix_alloc( nrobs , nrmin ); /* Left singular vectors. */ - matrix_type * VdT = matrix_alloc( nrmin , ens_size ); /* Right singular vectors. */ - double * Wd = util_calloc( nrmin , sizeof * Wd ); - - - Cd = matrix_alloc( nrobs, nrobs ); - enkf_linalg_Covariance(Cd ,E ,nsc, nrobs); - matrix_inv(Cd); - - if (data->iteration_nr == 0) { - Sk_new = enkf_linalg_data_mismatch(D,Cd,Skm); //Calculate the intitial data mismatch term - Std_new = matrix_diag_std(Skm,Sk_new); - rml_enkf_common_store_state( data->state , A , data->ens_mask ); - - - - if (data->lambda0 < 0) - data->lambda = pow(10,floor(log10(Sk_new/(2*nrobs)))); - else - data->lambda = data->lambda0; - - rml_enkf_common_initA__(A,S,Cd,E,D,truncation,data->lambda,Ud,Wd,VdT); - data->Sk = Sk_new; - data->Std = Std_new; - printf("Prior Objective function value is %5.3f \n", data->Sk); - - fprintf(fp,"Iteration number\t Lamda Value \t Current Mean (OB FN) \t Old Mean\t Current Stddev\n"); - fprintf(fp, "\n\n"); - fprintf(fp,"%d \t\t NA \t %5.5f \t \t %5.5f \n",data->iteration_nr, Sk_new, Std_new); - - } else { - Sk_new = enkf_linalg_data_mismatch(D , Cd , Skm); //Calculate the intitial data mismatch term - Std_new= matrix_diag_std(Skm,Sk_new); - printf(" Current Objective function value is %5.3f \n\n",Sk_new); - printf("The old Objective function value is %5.3f \n", data->Sk); - - - if ((Sk_new< (data->Sk)) && (Std_new< (data->Std))) - { - if ( (1- (Sk_new/data->Sk)) < .0001) // check convergence ** model change norm has to be added in this!! - data-> iteration_nr = 16; - - - fprintf(fp,"%d \t\t %5.5f \t %5.5f \t %5.5f \t %5.5f \n",data->iteration_nr,data->lambda, Sk_new,data->Sk, Std_new); - data->lambda = data->lambda / 10 ; - data->Std = Std_new; - - rml_enkf_common_store_state( data->state , A , data->ens_mask ); - - data->Sk = Sk_new; - rml_enkf_common_initA__(A,S,Cd,E,D,truncation,data->lambda,Ud,Wd,VdT); - } - else if((Sk_new< (data->Sk)) && (Std_new > (data->Std))) - { - if ( (1- (Sk_new/data->Sk)) < .0001) // check convergence ** model change norm has to be added in this!! - data-> iteration_nr = 16; - - - fprintf(fp,"%d \t\t %5.5f \t %5.5f \t %5.5f \t %5.5f \n",data->iteration_nr,data->lambda, Sk_new,data->Sk, Std_new); - data->Std=Std_new; - - rml_enkf_common_store_state( data->state , A , data->ens_mask ); - - data->Sk = Sk_new; - rml_enkf_common_initA__(A,S,Cd,E,D,truncation,data->lambda,Ud,Wd,VdT); - } - else { - fprintf(fp,"%d \t\t %5.5f \t %5.5f \t %5.5f \t %5.5f \n",data->iteration_nr,data->lambda, Sk_new,data->Sk, Std_new); - printf("The previous step is rejected !!\n"); - data->lambda = data ->lambda * 4; - - rml_enkf_common_recover_state( data->state , A , data->ens_mask ); - - rml_enkf_common_initA__(A,S,Cd,E,D,truncation,data->lambda,Ud,Wd,VdT); - data->iteration_nr--; - } - } - data->iteration_nr++; - - // setting the lower bound for lambda - if (data->lambda <.01) - data->lambda= .01; - - - printf ("The current iteration number is %d \n ", data->iteration_nr); - - - matrix_free(Cd); - matrix_free(Ud); - matrix_free(VdT); - matrix_free(Skm); - free(Wd); - fclose(fp); -} - - -void rml_enkf_init_update(void * arg , - const bool_vector_type * ens_mask , - const matrix_type * S , - const matrix_type * R , - const matrix_type * dObs , - const matrix_type * E , - const matrix_type * D ) { - rml_enkf_data_type * module_data = rml_enkf_data_safe_cast( arg ); - bool_vector_memcpy( module_data->ens_mask , ens_mask ); -} - - - -bool rml_enkf_set_double( void * arg , const char * var_name , double value) { - rml_enkf_data_type * module_data = rml_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , ENKF_TRUNCATION_KEY_) == 0) - rml_enkf_set_truncation( module_data , value ); - else if (strcmp( var_name , ENKF_LAMBDA0_KEY_) == 0) - rml_enkf_set_lambda0( module_data , value ); - else - name_recognized = false; - - return name_recognized; - } -} - - -bool rml_enkf_set_int( void * arg , const char * var_name , int value) { - rml_enkf_data_type * module_data = rml_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , ENKF_NCOMP_KEY_) == 0) - rml_enkf_set_subspace_dimension( module_data , value ); - else if(strcmp( var_name , ENKF_ITER_KEY_) == 0) - rml_enkf_set_iteration_number( module_data , value ); - else - name_recognized = false; - - return name_recognized; - } -} - - -long rml_enkf_get_options( void * arg , long flag ) { - rml_enkf_data_type * module_data = rml_enkf_data_safe_cast( arg ); - { - return module_data->option_flags; - } -} - - - - bool rml_enkf_has_var( const void * arg, const char * var_name) { - bool ret = false; - - if ((strcmp(var_name , ENKF_ITER_KEY_) == 0) || - (strcmp(var_name , ENKF_TRUNCATION_KEY_) == 0) || - (strcmp(var_name , ENKF_LAMBDA0_KEY_) == 0)) { - ret = true; - } - return ret; - } - - - - - int rml_enkf_get_int( const void * arg, const char * var_name) { - const rml_enkf_data_type * module_data = rml_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , ENKF_ITER_KEY_) == 0) - return module_data->iteration_nr; - else - return -1; - } - } - - double rml_enkf_get_double( const void * arg, const char * var_name) { - const rml_enkf_data_type * module_data = rml_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , ENKF_TRUNCATION_KEY_) == 0) - return module_data->truncation; - else if (strcmp(var_name , ENKF_LAMBDA0_KEY_) == 0) - return module_data->lambda0; - else - return -1.0; - } - } - - - - -/** - gcc -fpic -c -I?? - gcc -shared -o -*/ - - - -#ifdef INTERNAL_LINK -#define SYMBOL_TABLE rml_enkf_symbol_table -#else -#define SYMBOL_TABLE EXTERNAL_MODULE_SYMBOL -#endif - - -analysis_table_type SYMBOL_TABLE = { - .alloc = rml_enkf_data_alloc, - .freef = rml_enkf_data_free, - .set_int = rml_enkf_set_int , - .set_double = rml_enkf_set_double , - .set_bool = NULL , - .set_string = NULL , - .get_options = rml_enkf_get_options , - .initX = NULL, - .updateA = rml_enkf_updateA , - .init_update = rml_enkf_init_update , - .complete_update = NULL, - .has_var = rml_enkf_has_var, - .get_int = rml_enkf_get_int, - .get_double = rml_enkf_get_double, - .get_ptr = NULL, -}; - diff --git a/ThirdParty/Ert/libanalysis/modules/rml_enkf.c b/ThirdParty/Ert/libanalysis/modules/rml_enkf.c deleted file mode 100644 index efba06b83d..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/rml_enkf.c +++ /dev/null @@ -1,824 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rml_enkf.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -typedef struct rml_enkf_data_struct rml_enkf_data_type; - - - -//********************************************** -// DEFAULT PARAMS -//********************************************** -/* - Observe that only one of the settings subspace_dimension and - truncation can be valid at a time; otherwise the svd routine will - fail. This implies that the set_truncation() and - set_subspace_dimension() routines will set one variable, AND - INVALIDATE THE OTHER. For most situations this will be OK, but if - you have repeated calls to both of these functions the end result - might be a surprise. -*/ - - - -#define USE_PRIOR_KEY "USE_PRIOR" -#define LAMBDA_REDUCE_FACTOR_KEY "LAMBDA_REDUCE" -#define LAMBDA_INCREASE_FACTOR_KEY "LAMBDA_INCREASE" -#define LAMBDA0_KEY "LAMBDA0" -#define LAMBDA_MIN_KEY "LAMBDA_MIN" -#define LAMBDA_RECALCULATE_KEY "LAMBDA_RECALCULATE" -#define ITER_KEY "ITER" -#define LOG_FILE_KEY "LOG_FILE" -#define CLEAR_LOG_KEY "CLEAR_LOG" - - - - -#define RML_ENKF_TYPE_ID 261123 - - -//********************************************** -// RML "object" data definition -//********************************************** -/* - The configuration data used by the rml_enkf module is contained in a - rml_enkf_data_struct instance. The data type used for the rml_enkf - module is quite simple; with only a few scalar variables, but there - are essentially no limits to what you can pack into such a datatype. - - All the functions in the module have a void pointer as the first - argument, this will immediately be casted to a rml_enkf_data_type - instance, to get some type safety the UTIL_TYPE_ID system should be - used (see documentation in util.h) - - The data structure holding the data for your analysis module should - be created and initialized by a constructor, which should be - registered with the '.alloc' element of the analysis table; in the - same manner the desctruction of this data should be handled by a - destructor or free() function registered with the .freef field of - the analysis table. -*/ - - - - - -struct rml_enkf_data_struct { - UTIL_TYPE_ID_DECLARATION; - - int iteration_nr; // Keep track of the outer iteration loop - double Sk; // Objective function value - double Std; // Standard Deviation of the Objective function - double * Csc; - bool_vector_type * ens_mask; - - matrix_type *Am; // Scaled right singular vectors of ensemble anomalies. - - matrix_type *global_prior; // m_pr - matrix_type *previous_state; // m_l - - - double lambda; // parameter to control the setp length in Marquardt levenberg optimization - - - rml_enkf_log_type * rml_log; - rml_enkf_config_type * config; -}; - - - -static UTIL_SAFE_CAST_FUNCTION( rml_enkf_data , RML_ENKF_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION_CONST( rml_enkf_data , RML_ENKF_TYPE_ID ) - - - - - - -//********************************************** -// Set / Get -//********************************************** - - -void rml_enkf_set_iteration_nr( rml_enkf_data_type * data , int iteration_nr) { - data->iteration_nr = iteration_nr; -} - -int rml_enkf_get_iteration_nr( const rml_enkf_data_type * data ) { - return data->iteration_nr; -} - - - - - -//********************************************** -// Log-file related stuff -//********************************************** - - -static void rml_enkf_write_log_header( rml_enkf_data_type * data, const char * format) { - if (rml_enkf_log_is_open( data->rml_log )) { - const char * column1 = "Iter#"; - const char * column2 = "Lambda"; - const char * column3 = "Sk old"; - const char * column4 = "Sk_new"; - const char * column5 = "std(Sk)"; - - rml_enkf_log_line(data->rml_log, format, column1, column2, column3, column4, column5); - } -} - -static void rml_enkf_write_iter_info( rml_enkf_data_type * data , double prev_Sk , double Sk_new, double Std_new ) { - if (rml_enkf_log_is_open( data->rml_log )) { - - const char * format = "\n%2d-->%-2d %-7.3f %-7.3f --> %-7.3f %-7.3f"; - const char * format_headers = "\n%-7s %-7s %-7s --> %-7s %-7s"; - static bool has_printed_header = false; - - if (!has_printed_header) { - rml_enkf_write_log_header( data, format_headers ); - has_printed_header = true; - } - - rml_enkf_log_line( data->rml_log , format, data->iteration_nr, data->iteration_nr+1, data->lambda, prev_Sk, Sk_new, Std_new); - } -} - - - - - -//********************************************** -// Memory -//********************************************** -void * rml_enkf_data_alloc( rng_type * rng) { - rml_enkf_data_type * data = util_malloc( sizeof * data); - UTIL_TYPE_ID_INIT( data , RML_ENKF_TYPE_ID ); - - data->config = rml_enkf_config_alloc(); - data->rml_log = rml_enkf_log_alloc(); - - data->Csc = NULL; - data->iteration_nr = 0; - data->Std = 0; - data->previous_state = matrix_alloc(1,1); - data->global_prior = NULL; - data->ens_mask = NULL; - return data; -} - -void rml_enkf_data_free( void * arg ) { - rml_enkf_data_type * data = rml_enkf_data_safe_cast( arg ); - - matrix_free( data->previous_state ); - if (data->global_prior) - matrix_free( data->global_prior ); - - rml_enkf_log_free( data->rml_log ); - rml_enkf_config_free( data->config ); - free( data ); -} - - - - - -//********************************************** -// Notation -//********************************************** -/* - * X1-X7, intermediate calculations in iterations. See D.Oliver algorithm - * - * Variable name in code <-> D.Oliver notation <-> Description - * ------------------------------------------------------------------------------------------------------------- - * A <-> m_l <-> Ensemble matrix. Updated in-place by iterations. - * data->previous_state <-> m_(l-1) <-> "A" from the previous iteration. Backs up A in case the update is bad. - * data->global_prior <-> <-> Previously: "active_prior". Stores A from before iter0, i.e. the actual prior. - * Acopy <-> <-> Eliminated from code. Copy of A (at each iteration, before acceptance/rejection decision) - - * - * Am <-> A_m <-> Am = Um*Wm^(-1) - * Csc <-> C_sc^(1/2) <-> State scalings. Note the square root. - * Dm (in init1__) <-> Delta m <-> Anomalies of prior wrt. its mean (row i scaled by 1/(Csc[i]*sqrt(N-1))) - * Dm (in initA__) <-> Csc * Delta m <-> Anomalies of A wrt. its mean (only scaled by 1/sqrt(N-1)) - * Dk1 (in init2__) <-> Delta m <-> Anomailes of A (row i scaled by 1/(Csc[i]*sqrt(N-1))) - * Dk (in init2__) <-> C_sc^(-1) * (m - m_pr ) <-> Anomalies wrt. prior (as opposed to the mean; only scaled by Csc) - * dA1 (in initA__) <-> delta m_1 <-> Ensemble updates coming from data mismatch - * dA2 (in init2__) <-> delta m_2 <-> Ensemble updates coming from prior mismatch -*/ - - - - -//********************************************** -// Actual Algorithm, called through updateA() -//********************************************** - -// Just (pre)calculates data->Am = Um*Wm^(-1). -static void rml_enkf_init1__( rml_enkf_data_type * data) { - // Differentiate this routine from init2__, which actually calculates the prior mismatch update. - // This routine does not change any ensemble matrix. - // Um*Wm^(-1) are the scaled, truncated, right singular vectors of data->global_prior - - matrix_type * prior = matrix_alloc_column_compressed_copy( data->global_prior , data->ens_mask); - int state_size = matrix_get_rows( prior ); - int ens_size = matrix_get_columns( prior ); - int nrmin = util_int_min( ens_size , state_size); - matrix_type * Dm = matrix_alloc_copy( prior ); - matrix_type * Um = matrix_alloc( state_size , nrmin ); /* Left singular vectors. */ - matrix_type * VmT = matrix_alloc( nrmin , ens_size ); /* Right singular vectors. */ - double * Wm = util_calloc( nrmin , sizeof * Wm ); - double nsc = 1/sqrt(ens_size - 1); - - matrix_subtract_row_mean(Dm); - { - const double * Csc = data->Csc; - for (int i=0; i < state_size; i++){ - double sc = nsc / (Csc[i]); - matrix_scale_row( Dm , i , sc); - } - } - - // Um Wm VmT = Dm; nsign1 = num of non-zero singular values. - int nsign1 = enkf_linalg_svd_truncation(Dm , rml_enkf_config_get_truncation( data->config ) , -1 , DGESVD_MIN_RETURN , Wm , Um , VmT); - - // Am = Um*Wm^(-1). I.e. scale *columns* of Um - enkf_linalg_rml_enkfAm(Um, Wm, nsign1); - - data->Am = matrix_alloc_copy( Um ); - matrix_free(Um); - matrix_free(VmT); - matrix_free(Dm); - matrix_free(prior); - free(Wm); -} - - - -// Creates state scaling matrix -void rml_enkf_init_Csc(const rml_enkf_data_type * data ){ - // This seems a strange choice of scaling matrix. Review? - matrix_type * prior = matrix_alloc_column_compressed_copy( data->global_prior , data->ens_mask ); - { - int state_size = matrix_get_rows( prior ); - int ens_size = matrix_get_columns( prior ); - - for (int row=0; row < state_size; row++) { - double sumrow = matrix_get_row_sum(prior , row); - double tmp = sumrow / ens_size; - - if (abs(tmp)< 1) - data->Csc[row] = 0.05; - else - data->Csc[row] = 1.00; - - } - matrix_free( prior ); - } -} - -// Calculates update from data mismatch (delta m_1). Also provides SVD for later use. -static void rml_enkf_initA__(rml_enkf_data_type * data, matrix_type * A, matrix_type * S, matrix_type * Cd, matrix_type * E, matrix_type * D, matrix_type * Udr, double * Wdr, matrix_type * VdTr) { - - int ens_size = matrix_get_columns( S ); - int state_size = matrix_get_rows( A ); - double nsc = 1/sqrt(ens_size-1); - int nsign; - - // Perform SVD of tmp, where: tmp = diag_sqrt(Cd^(-1)) * centered(S) / sqrt(N-1) = Ud * Wd * Vd(T) - { - int nrobs = matrix_get_rows( S ); - matrix_type *tmp = matrix_alloc (nrobs, ens_size); - matrix_subtract_row_mean( S ); // Center S - matrix_inplace_diag_sqrt(Cd); // Assumes that Cd is diag! - matrix_matmul(tmp , Cd , S ); // - matrix_scale(tmp , nsc); // - - nsign = enkf_linalg_svd_truncation(tmp , rml_enkf_config_get_truncation( data->config ) , -1 , DGESVD_MIN_RETURN , Wdr , Udr , VdTr); - matrix_free( tmp ); - } - - // Calc X3 - { - matrix_type * X3 = matrix_alloc( ens_size, ens_size ); - { - matrix_type * X1 = matrix_alloc( nsign, ens_size); - matrix_type * X2 = matrix_alloc( nsign, ens_size ); - - - // See LM-EnRML algorithm in Oliver'2013 (Comp. Geo.) for meaning - enkf_linalg_rml_enkfX1(X1, Udr ,D ,Cd ); // X1 = Ud(T)*Cd(-1/2)*D -- D= -(dk-d0) - enkf_linalg_rml_enkfX2(X2, Wdr ,X1 ,data->lambda + 1 , nsign); // X2 = ((a*Ipd)+Wd^2)^-1 * X1 - enkf_linalg_rml_enkfX3(X3, VdTr ,Wdr,X2, nsign); // X3 = Vd *Wd*X2 - - matrix_free(X2); - matrix_free(X1); - } - - // Update A - { - matrix_type * dA1 = matrix_alloc( state_size , ens_size); - matrix_type * Dm = matrix_alloc_copy( A ); - - matrix_subtract_row_mean( Dm ); /* Remove the mean from the ensemble of model parameters*/ - matrix_scale(Dm, nsc); - - matrix_matmul(dA1, Dm , X3); - matrix_inplace_add(A,dA1); // dA - - matrix_free(Dm); - matrix_free(dA1); - } - matrix_free(X3); - - } -} - -// Calculate prior mismatch update (delta m_2). -void rml_enkf_init2__( rml_enkf_data_type * data, matrix_type *A, double * Wdr, matrix_type * VdTr) { - // Distinguish from init1__ which only makes preparations, and is only called at iter=0 - - - int state_size = matrix_get_rows( A ); - int ens_size = matrix_get_columns( A ); - double nsc = 1/sqrt(ens_size-1); - - matrix_type *Am = matrix_alloc_copy(data->Am); - matrix_type *Apr = matrix_alloc_column_compressed_copy(data->global_prior , data->ens_mask ); - - // fprintf(stdout,"\n"); - // fprintf(stdout,"A: %d x %d\n", matrix_get_rows(A), matrix_get_columns(A)); - // fprintf(stdout,"prior : %d x %d\n", matrix_get_rows(data->global_prior), matrix_get_columns(data->global_prior)); - // fprintf(stdout,"state : %d x %d\n", matrix_get_rows(data->previous_state), matrix_get_columns(data->previous_state)); - // fprintf(stdout,"Apr : %d x %d\n", matrix_get_rows(Apr), matrix_get_columns(Apr)); - // fprintf(stdout,"Am : %d x %d\n", matrix_get_rows(Am), matrix_get_columns(Am)); - // Example: - // A : 27760 x 10 - // prior : 27760 x 10 - // state : 27760 x 50 - // prior0 : 27760 x 50 - // Apr : 27760 x 10 - // Am : 27760 x 1 - - - int nsign1 = matrix_get_columns(data->Am); - - - matrix_type * X4 = matrix_alloc(nsign1,ens_size); - matrix_type * X5 = matrix_alloc(state_size,ens_size); - matrix_type * X6 = matrix_alloc(ens_size,ens_size); - matrix_type * X7 = matrix_alloc(ens_size,ens_size); - matrix_type * dA2 = matrix_alloc(state_size , ens_size); - matrix_type * Dk1 = matrix_alloc_copy( A ); - - // Dk = Csc^(-1) * (A - Aprior) - // X4 = Am' * Dk - { - matrix_type * Dk = matrix_alloc_copy( A ); - - matrix_inplace_sub( Dk , Apr ); - rml_enkf_common_scaleA(Dk , data->Csc , true); - - matrix_dgemm(X4 , Am , Dk , true, false, 1.0, 0.0); - matrix_free(Dk); - } - // X5 = Am * X4 - matrix_matmul(X5 , Am , X4); - - // Dk1 = Csc^(-1)/sqrt(N-1) * A*(I - 1/N*ones(m,N)) - matrix_subtract_row_mean(Dk1); // Dk1 = Dk1 * (I - 1/N*ones(m,N)) - rml_enkf_common_scaleA(Dk1 , data->Csc , true); // Dk1 = Csc^(-1) * Dk1 - matrix_scale(Dk1,nsc); // Dk1 = Dk1 / sqrt(N-1) - - // X6 = Dk1' * X5 - matrix_dgemm(X6, Dk1, X5, true, false, 1.0, 0.0); - - // X7 - enkf_linalg_rml_enkfX7(X7, VdTr , Wdr , data->lambda + 1, X6); - - // delta m_2 - rml_enkf_common_scaleA(Dk1 , data->Csc , false); - matrix_matmul(dA2 , Dk1 , X7); - matrix_inplace_sub(A, dA2); - - matrix_free(Am); - matrix_free(Apr); - matrix_free(X4); - matrix_free(X5); - matrix_free(X6); - matrix_free(X7); - matrix_free(dA2); - matrix_free(Dk1); -} - -// Initialize state and prior from A. Initialize lambda0, lambda. Call initA__, init1__ -static void rml_enkf_updateA_iter0(rml_enkf_data_type * data, matrix_type * A, matrix_type * S, matrix_type * R, matrix_type * dObs, matrix_type * E, matrix_type * D, matrix_type * Cd) { - - int ens_size = matrix_get_columns( S ); - int nrobs = matrix_get_rows( S ); - int nrmin = util_int_min( ens_size , nrobs); - int state_size = matrix_get_rows( A ); - matrix_type * Skm = matrix_alloc(ens_size, ens_size); // Mismatch - matrix_type * Ud = matrix_alloc( nrobs , nrmin ); /* Left singular vectors. */ - matrix_type * VdT = matrix_alloc( nrmin , ens_size ); /* Right singular vectors. */ - double * Wd = util_calloc( nrmin , sizeof * Wd ); - - data->Csc = util_calloc(state_size , sizeof * data->Csc); - data->Sk = enkf_linalg_data_mismatch(D,Cd,Skm); - data->Std = matrix_diag_std(Skm,data->Sk); - - { - double lambda0 = rml_enkf_config_get_lambda0( data->config ); - if (lambda0 < 0) - data->lambda = pow(10 , floor(log10(data->Sk/(2*nrobs))) ); - else - data->lambda = lambda0; - } - - - // state = A - rml_enkf_common_store_state( data->previous_state , A , data->ens_mask ); - - // prior = A - data->global_prior = matrix_alloc_copy( data->previous_state ); - - // Update dependant on data mismatch - rml_enkf_initA__(data , A, S , Cd , E , D , Ud , Wd , VdT); - // Update dependant on prior mismatch. This should be zero (coz iter0). - // Therefore the purpose of init1__ is just to prepare some matrices. - if (rml_enkf_config_get_use_prior(data->config)) { - rml_enkf_init_Csc( data ); - rml_enkf_init1__( data ); - } - - rml_enkf_write_iter_info(data, data->Sk , data->Sk, data->Std); - - matrix_free( Skm ); - matrix_free( Ud ); - matrix_free( VdT ); - free( Wd ); -} - - -void rml_enkf_updateA(void * module_data, matrix_type * A, matrix_type * S, matrix_type * R, matrix_type * dObs, matrix_type * E, matrix_type * D, const module_info_type* module_info) { -// A : ensemble matrix -// R : (Inv?) Obs error cov. -// S : measured ensemble -// dObs: observed data -// E : perturbations for obs -// D = dObs + E - S : Innovations (wrt pert. obs) -// module_info: Information on parameters/data for internal logging - - - - double Sk_new; // Mismatch - double Std_new; // Std dev(Mismatch) - rml_enkf_data_type * data = rml_enkf_data_safe_cast( module_data ); - int nrobs = matrix_get_rows( S ); // Num obs - int ens_size = matrix_get_columns( S ); // N - double nsc = 1/sqrt(ens_size-1); // Scale factor - matrix_type * Cd = matrix_alloc( nrobs, nrobs ); // Cov(E), where E = measurement perturbations? - - - // Empirical error covar. R is left unused. Investigate? - enkf_linalg_Covariance(Cd ,E ,nsc, nrobs); // Cd = SampCov(E) (including (N-1) normalization) - matrix_inv(Cd); // In-place inversion - - rml_enkf_log_open(data->rml_log , data->iteration_nr); - fprintf(stdout,"\nIter %d --> %d", data->iteration_nr, data->iteration_nr + 1); - - - if (data->iteration_nr == 0) { - // IF ITERATION 0 - rml_enkf_updateA_iter0(data , A , S , R , dObs , E , D , Cd); - data->iteration_nr++; - } else { - // IF ITERATION 1, 2, ... - int nrmin = util_int_min( ens_size , nrobs); // Min(p,N) - matrix_type * Ud = matrix_alloc( nrobs , nrmin ); // Left singular vectors. */ - matrix_type * VdT = matrix_alloc( nrmin , ens_size ); // Right singular vectors. */ - double * Wd = util_calloc( nrmin , sizeof * Wd ); // Singular values, vector - matrix_type * Skm = matrix_alloc(ens_size,ens_size); // Mismatch - Sk_new = enkf_linalg_data_mismatch(D,Cd,Skm); // Skm = D'*inv(Cd)*D; Sk_new = trace(Skm)/N - Std_new = matrix_diag_std(Skm,Sk_new); // Standard deviation of mismatches. - - - // Lambda = Normalized data mismatch (rounded) - if (rml_enkf_config_get_lambda_recalculate( data->config )) - data->lambda = pow(10 , floor(log10(Sk_new / (2*nrobs))) ); - - // Accept/Reject update? Lambda calculation. - { - bool mismatch_reduced = false; - bool std_reduced = false; - - if (Sk_new < data->Sk) - mismatch_reduced = true; - - if (Std_new <= data->Std) - std_reduced = true; - - rml_enkf_write_iter_info(data, data->Sk , Sk_new, Std_new); - - if (mismatch_reduced) { - /* - Stop check: if ( (1- (Sk_new/data->Sk)) < .0001) // check convergence ** model change norm has to be added in this!! - */ - - // Reduce Lambda - if (std_reduced) - data->lambda = data->lambda * rml_enkf_config_get_lambda_decrease_factor( data->config ); - - rml_enkf_common_store_state(data->previous_state , A , data->ens_mask ); - - data->Sk = Sk_new; - data->Std=Std_new; - data->iteration_nr++; - } else { - // Increase lambda - data->lambda = data->lambda * rml_enkf_config_get_lambda_increase_factor( data->config ); - // A = data->previous_state - rml_enkf_common_recover_state( data->previous_state , A , data->ens_mask ); - } - } - - // Update dependant on data mismatch (delta m_1) - rml_enkf_initA__(data , A , S , Cd , E , D , Ud , Wd , VdT); - - // Update dependant on prior mismatch (delta m_2) - if (rml_enkf_config_get_use_prior(data->config)) { - rml_enkf_init_Csc( data ); - rml_enkf_init2__(data , A , Wd , VdT); - } - - // Free - matrix_free(Skm); - matrix_free( Ud ); - matrix_free( VdT ); - free( Wd ); - } - - { - double lambda_min = rml_enkf_config_get_lambda_min( data->config ); - if (data->lambda < lambda_min) - data->lambda = lambda_min; - } - - - rml_enkf_log_close( data->rml_log ); - matrix_free(Cd); -} - - - -void rml_enkf_init_update(void * arg, const bool_vector_type * ens_mask, const matrix_type * S, const matrix_type * R, const matrix_type * dObs, const matrix_type * E, const matrix_type * D ) { - rml_enkf_data_type * module_data = rml_enkf_data_safe_cast( arg ); - - if (module_data->ens_mask) - bool_vector_free( module_data->ens_mask ); - - module_data->ens_mask = bool_vector_alloc_copy( ens_mask ); -} - - - - - - - -//********************************************** -// Set / Get basic types -//********************************************** -bool rml_enkf_set_int( void * arg , const char * var_name , int value) { - rml_enkf_data_type * module_data = rml_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , ENKF_NCOMP_KEY_) == 0) - rml_enkf_config_set_subspace_dimension(module_data->config , value); - else if (strcmp( var_name , ITER_KEY) == 0) - rml_enkf_set_iteration_nr( module_data , value ); - else - name_recognized = false; - - return name_recognized; - } -} - -int rml_enkf_get_int( const void * arg, const char * var_name) { - const rml_enkf_data_type * module_data = rml_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , ITER_KEY) == 0) - return module_data->iteration_nr; - else - return -1; - } -} - -bool rml_enkf_set_bool( void * arg , const char * var_name , bool value) { - rml_enkf_data_type * module_data = rml_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , USE_PRIOR_KEY) == 0) - rml_enkf_config_set_use_prior( module_data->config , value); - else if (strcmp( var_name , CLEAR_LOG_KEY) == 0) - rml_enkf_log_set_clear_log( module_data->rml_log , value ); - else if (strcmp( var_name , LAMBDA_RECALCULATE_KEY) == 0) - rml_enkf_config_set_lambda_recalculate( module_data->config , value ); - else - name_recognized = false; - - return name_recognized; - } -} - -bool rml_enkf_get_bool( const void * arg, const char * var_name) { - const rml_enkf_data_type * module_data = rml_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , USE_PRIOR_KEY) == 0) - return rml_enkf_config_get_use_prior( module_data->config ); - else if (strcmp(var_name , CLEAR_LOG_KEY) == 0) - return rml_enkf_log_get_clear_log( module_data->rml_log ); - else if (strcmp(var_name , LAMBDA_RECALCULATE_KEY) == 0) - return rml_enkf_config_get_lambda_recalculate( module_data->config ); - else - return false; - } -} - -bool rml_enkf_set_double( void * arg , const char * var_name , double value) { - rml_enkf_data_type * module_data = rml_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , ENKF_TRUNCATION_KEY_) == 0) - rml_enkf_config_set_truncation( module_data->config , value ); - else if (strcmp( var_name , LAMBDA_INCREASE_FACTOR_KEY) == 0) - rml_enkf_config_set_lambda_increase_factor( module_data->config , value ); - else if (strcmp( var_name , LAMBDA_REDUCE_FACTOR_KEY) == 0) - rml_enkf_config_set_lambda_decrease_factor( module_data->config , value ); - else if (strcmp( var_name , LAMBDA0_KEY) == 0) - rml_enkf_config_set_lambda0( module_data->config , value ); - else if (strcmp( var_name , LAMBDA_MIN_KEY) == 0) - rml_enkf_config_set_lambda_min( module_data->config , value ); - else - name_recognized = false; - - return name_recognized; - } -} - -double rml_enkf_get_double( const void * arg, const char * var_name) { - const rml_enkf_data_type * module_data = rml_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , LAMBDA_REDUCE_FACTOR_KEY) == 0) - return rml_enkf_config_get_lambda_decrease_factor(module_data->config); - - if (strcmp(var_name , LAMBDA_INCREASE_FACTOR_KEY) == 0) - return rml_enkf_config_get_lambda_increase_factor(module_data->config); - - if (strcmp(var_name , LAMBDA0_KEY) == 0) - return rml_enkf_config_get_lambda0(module_data->config); - - if (strcmp(var_name , LAMBDA_MIN_KEY) == 0) - return rml_enkf_config_get_lambda_min(module_data->config); - - if (strcmp(var_name , ENKF_TRUNCATION_KEY_) == 0) - return rml_enkf_config_get_truncation( module_data->config ); - - return -1; - } -} - - -bool rml_enkf_set_string( void * arg , const char * var_name , const char * value) { - rml_enkf_data_type * module_data = rml_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , LOG_FILE_KEY) == 0) - rml_enkf_log_set_log_file( module_data->rml_log , value ); - else - name_recognized = false; - - return name_recognized; - } -} - -long rml_enkf_get_options( void * arg , long flag ) { - rml_enkf_data_type * module_data = rml_enkf_data_safe_cast( arg ); - { - return rml_enkf_config_get_option_flags( module_data->config ); - } -} - -bool rml_enkf_has_var( const void * arg, const char * var_name) { - { - if (strcmp(var_name , ITER_KEY) == 0) - return true; - else if (strcmp(var_name , USE_PRIOR_KEY) == 0) - return true; - else if (strcmp(var_name , LAMBDA_INCREASE_FACTOR_KEY) == 0) - return true; - else if (strcmp(var_name , LAMBDA_REDUCE_FACTOR_KEY) == 0) - return true; - else if (strcmp(var_name , LAMBDA0_KEY) == 0) - return true; - else if (strcmp(var_name , LAMBDA_MIN_KEY) == 0) - return true; - else if (strcmp(var_name , LAMBDA_RECALCULATE_KEY) == 0) - return true; - else if (strcmp(var_name , ENKF_TRUNCATION_KEY_) == 0) - return true; - else if (strcmp(var_name , LOG_FILE_KEY) == 0) - return true; - else if (strcmp(var_name , CLEAR_LOG_KEY) == 0) - return true; - else - return false; - } -} - -void * rml_enkf_get_ptr( const void * arg , const char * var_name ) { - const rml_enkf_data_type * module_data = rml_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , LOG_FILE_KEY) == 0) - return (void *) rml_enkf_log_get_log_file( module_data->rml_log ); - else - return NULL; - } -} - - - - - - -//********************************************** -// Symbol table -//********************************************** -#ifdef INTERNAL_LINK -#define LINK_NAME RML_ENKF -#else -#define LINK_NAME EXTERNAL_MODULE_SYMBOL -#endif - - -analysis_table_type LINK_NAME = { - .name = "RML_ENKF", - .alloc = rml_enkf_data_alloc, - .freef = rml_enkf_data_free, - .set_int = rml_enkf_set_int , - .set_double = rml_enkf_set_double , - .set_bool = rml_enkf_set_bool, - .set_string = rml_enkf_set_string, - .get_options = rml_enkf_get_options , - .initX = NULL, - .updateA = rml_enkf_updateA , - .init_update = rml_enkf_init_update , - .complete_update = NULL, - .has_var = rml_enkf_has_var, - .get_int = rml_enkf_get_int, - .get_double = rml_enkf_get_double, - .get_bool = rml_enkf_get_bool, - .get_ptr = rml_enkf_get_ptr, -}; - diff --git a/ThirdParty/Ert/libanalysis/modules/rml_enkf_common.c b/ThirdParty/Ert/libanalysis/modules/rml_enkf_common.c deleted file mode 100644 index fdc541bfbc..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/rml_enkf_common.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rml_enkf.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - - -// Explanation -// zzz_enkf_common_store_state( state , A ,ens_mask) assigns A to state. RESIZES state to rows(A)-by-LEN(ens_mask) -// zzz_enkf_common_recover_state(state , A ,ens_mask) assigns state to A. RESIZES A to rows(state)-by-SUM(ens_mask) - - -void rml_enkf_common_store_state( matrix_type * state , const matrix_type * A , const bool_vector_type * ens_mask ) { - matrix_resize( state , matrix_get_rows( A ) , bool_vector_size( ens_mask ) , false); - { - const int ens_size = bool_vector_size( ens_mask ); - int active_index = 0; - for (int iens = 0; iens < ens_size; iens++) { - if (bool_vector_iget( ens_mask , iens )) { - matrix_copy_column( state , A , iens , active_index ); - active_index++; - } else - matrix_set_const_column( state , iens , 0); - } - } -} - - - -void rml_enkf_common_recover_state( const matrix_type * state , matrix_type * A , const bool_vector_type * ens_mask ) { - const int ens_size = bool_vector_size( ens_mask ); - const int active_size = bool_vector_count_equal( ens_mask , true ); - const int rows = matrix_get_rows( state ); - - matrix_resize( A , rows , active_size , false ); - { - int active_index = 0; - for (int iens = 0; iens < ens_size; iens++) { - if (bool_vector_iget( ens_mask , iens )) { - matrix_copy_column( A , state , active_index , iens ); - active_index++; - } - } - } -} - - - -// Scale rows by the entries in the vector Csc -void rml_enkf_common_scaleA(matrix_type *A , const double * Csc, bool invert ){ - int nrows = matrix_get_rows(A); - if (invert) { - for (int i=0; i< nrows ; i++) { - double sc= 1/Csc[i]; - matrix_scale_row(A, i, sc); - } - } else { - for (int i=0; i< nrows ; i++) { - double sc= Csc[i]; - matrix_scale_row(A, i, sc); - } - } -} diff --git a/ThirdParty/Ert/libanalysis/modules/rml_enkf_common.h b/ThirdParty/Ert/libanalysis/modules/rml_enkf_common.h deleted file mode 100644 index f288b56419..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/rml_enkf_common.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef ERT_RML_ENKF_COMMON_H -#define ERT_RML_ENKF_COMMON_H - -#include - -#include -#include -#include - - -void rml_enkf_common_store_state( matrix_type * state , const matrix_type * A , const bool_vector_type * ens_mask ); -void rml_enkf_common_recover_state( const matrix_type * state , matrix_type * A , const bool_vector_type * ens_mask ); -void rml_enkf_common_scaleA(matrix_type *A , const double * Csc, bool invert ); - -#endif diff --git a/ThirdParty/Ert/libanalysis/modules/rml_enkf_config.c b/ThirdParty/Ert/libanalysis/modules/rml_enkf_config.c deleted file mode 100644 index 6e9ff18287..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/rml_enkf_config.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'rml_enkf_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include - -#include -#include - -#include - - -#define INVALID_SUBSPACE_DIMENSION -1 -#define INVALID_TRUNCATION -1 - -#define DEFAULT_SUBSPACE_DIMENSION INVALID_SUBSPACE_DIMENSION -#define DEFAULT_USE_PRIOR true - -#define DEFAULT_LAMBDA_INCREASE_FACTOR 4 -#define DEFAULT_LAMBDA_REDUCE_FACTOR 0.1 -#define DEFAULT_LAMBDA0 -1 -#define DEFAULT_LAMBDA_MIN 0.01 -#define DEFAULT_LAMBDA_RECALCULATE false - - - -#define RML_ENKF_CONFIG_TYPE_ID 61400061 - -struct rml_enkf_config_struct { - UTIL_TYPE_ID_DECLARATION; - double truncation; // Controlled by config key: ENKF_TRUNCATION_KEY - int subspace_dimension; // Controlled by config key: ENKF_NCOMP_KEY (-1: use Truncation instead) - long option_flags; - bool use_prior; // Use exact/approximate scheme? Approximate scheme drops the "prior" term in the LM step. - - - double lambda0; - double lambda_min; - double lambda_decrease_factor; - double lambda_increase_factor; - bool lambda_recalculate; -}; - - - - - - - -rml_enkf_config_type * rml_enkf_config_alloc() { - rml_enkf_config_type * config = util_malloc( sizeof * config ); - UTIL_TYPE_ID_INIT( config , RML_ENKF_CONFIG_TYPE_ID ); - - rml_enkf_config_set_truncation( config , DEFAULT_ENKF_TRUNCATION_); - rml_enkf_config_set_subspace_dimension( config , DEFAULT_SUBSPACE_DIMENSION); - rml_enkf_config_set_use_prior( config , DEFAULT_USE_PRIOR ); - rml_enkf_config_set_option_flags( config , ANALYSIS_NEED_ED + ANALYSIS_UPDATE_A + ANALYSIS_ITERABLE + ANALYSIS_SCALE_DATA); - - rml_enkf_config_set_lambda_min( config , DEFAULT_LAMBDA_MIN ); - rml_enkf_config_set_lambda0( config , DEFAULT_LAMBDA0 ); - rml_enkf_config_set_lambda_decrease_factor( config , DEFAULT_LAMBDA_REDUCE_FACTOR ); - rml_enkf_config_set_lambda_increase_factor( config , DEFAULT_LAMBDA_INCREASE_FACTOR ); - rml_enkf_config_set_lambda_recalculate( config , DEFAULT_LAMBDA_RECALCULATE ); - - return config; -} - - -bool rml_enkf_config_get_use_prior( const rml_enkf_config_type * config ) { - return config->use_prior; -} - -void rml_enkf_config_set_use_prior( rml_enkf_config_type * config , bool use_prior) { - config->use_prior = use_prior; -} - - -double rml_enkf_config_get_truncation( rml_enkf_config_type * config ) { - return config->truncation; -} - -void rml_enkf_config_set_truncation( rml_enkf_config_type * config , double truncation) { - config->truncation = truncation; - if (truncation > 0.0) - config->subspace_dimension = INVALID_SUBSPACE_DIMENSION; -} - -int rml_enkf_config_get_subspace_dimension( rml_enkf_config_type * config ) { - return config->subspace_dimension; -} - -void rml_enkf_config_set_subspace_dimension( rml_enkf_config_type * config , int subspace_dimension) { - config->subspace_dimension = subspace_dimension; - if (subspace_dimension > 0) - config->truncation = INVALID_TRUNCATION; -} - -void rml_enkf_config_set_option_flags( rml_enkf_config_type * config , long flags) { - config->option_flags = flags; -} - -long rml_enkf_config_get_option_flags( const rml_enkf_config_type * config ) { - return config->option_flags; -} - -double rml_enkf_config_get_lambda0( rml_enkf_config_type * config ) { - return config->lambda0; -} - -void rml_enkf_config_set_lambda0( rml_enkf_config_type * config , double lambda0) { - config->lambda0 = lambda0; -} - - -double rml_enkf_config_get_lambda_min( rml_enkf_config_type * config ) { - return config->lambda_min; -} - -void rml_enkf_config_set_lambda_min( rml_enkf_config_type * config , double lambda_min) { - config->lambda_min = lambda_min; -} - - -double rml_enkf_config_get_lambda_increase_factor( rml_enkf_config_type * config ) { - return config->lambda_increase_factor; -} - -void rml_enkf_config_set_lambda_increase_factor( rml_enkf_config_type * config , double lambda_increase_factor) { - config->lambda_increase_factor = lambda_increase_factor; -} - -double rml_enkf_config_get_lambda_decrease_factor( rml_enkf_config_type * config ) { - return config->lambda_decrease_factor; -} - -void rml_enkf_config_set_lambda_decrease_factor( rml_enkf_config_type * config , double lambda_decrease_factor) { - config->lambda_decrease_factor = lambda_decrease_factor; -} - - -bool rml_enkf_config_get_lambda_recalculate( const rml_enkf_config_type * config ) { - return config->lambda_recalculate; -} - -void rml_enkf_config_set_lambda_recalculate( rml_enkf_config_type * config , bool lambda_recalculate) { - config->lambda_recalculate = lambda_recalculate; -} - - -void rml_enkf_config_free(rml_enkf_config_type * config) { - free( config ); -} diff --git a/ThirdParty/Ert/libanalysis/modules/rml_enkf_config.h b/ThirdParty/Ert/libanalysis/modules/rml_enkf_config.h deleted file mode 100644 index 8173b9f7e6..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/rml_enkf_config.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'rml_enkf_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef RML_ENKF_CONFIG_H -#define RML_ENKF_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - - -typedef struct rml_enkf_config_struct rml_enkf_config_type; - - - rml_enkf_config_type * rml_enkf_config_alloc(); - void rml_enkf_config_free(rml_enkf_config_type * config); - - int rml_enkf_config_get_subspace_dimension( rml_enkf_config_type * config ); - void rml_enkf_config_set_subspace_dimension( rml_enkf_config_type * config , int subspace_dimension); - - double rml_enkf_config_get_truncation( rml_enkf_config_type * config ); - void rml_enkf_config_set_truncation( rml_enkf_config_type * config , double truncation); - - bool rml_enkf_config_get_use_prior( const rml_enkf_config_type * config ); - void rml_enkf_config_set_use_prior( rml_enkf_config_type * config , bool use_prior); - - void rml_enkf_config_set_option_flags( rml_enkf_config_type * config , long flags); - long rml_enkf_config_get_option_flags( const rml_enkf_config_type * config ); - - double rml_enkf_config_get_lambda0( rml_enkf_config_type * config ); - void rml_enkf_config_set_lambda0( rml_enkf_config_type * config , double lambda0); - - double rml_enkf_config_get_lambda_min( rml_enkf_config_type * config ); - void rml_enkf_config_set_lambda_min( rml_enkf_config_type * config , double lambda_min); - - double rml_enkf_config_get_lambda_increase_factor( rml_enkf_config_type * config ); - void rml_enkf_config_set_lambda_increase_factor( rml_enkf_config_type * config , double lambda_increase_factor); - - double rml_enkf_config_get_lambda_decrease_factor( rml_enkf_config_type * config ); - void rml_enkf_config_set_lambda_decrease_factor( rml_enkf_config_type * config , double lambda_decrease_factor); - - bool rml_enkf_config_get_lambda_recalculate( const rml_enkf_config_type * config ); - void rml_enkf_config_set_lambda_recalculate( rml_enkf_config_type * config , bool lambda_recalculate); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libanalysis/modules/rml_enkf_log.c b/ThirdParty/Ert/libanalysis/modules/rml_enkf_log.c deleted file mode 100644 index 108c3734c5..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/rml_enkf_log.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'rml_enkf_log.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include - -#include - -#include - -#define DEFAULT_LOG_FILE "rml_enkf.out" -#define DEFAULT_CLEAR_LOG true - -struct rml_enkf_log_struct { - bool clear_log; - char * log_file; - FILE * log_stream; -}; - - -rml_enkf_log_type * rml_enkf_log_alloc() { - rml_enkf_log_type * rml_log = util_malloc( sizeof * rml_log ); - rml_log->log_file = NULL; - rml_log->log_stream = NULL; - rml_enkf_log_set_clear_log( rml_log , DEFAULT_CLEAR_LOG ); - - rml_enkf_log_set_log_file( rml_log, DEFAULT_LOG_FILE ); - return rml_log; -} - -bool rml_enkf_log_get_clear_log( const rml_enkf_log_type * data ) { - return data->clear_log; -} - -void rml_enkf_log_set_clear_log( rml_enkf_log_type * data , bool clear_log) { - data->clear_log = clear_log; -} - -void rml_enkf_log_set_log_file( rml_enkf_log_type * data , const char * log_file ) { - data->log_file = util_realloc_string_copy( data->log_file , log_file ); -} - -const char * rml_enkf_log_get_log_file( const rml_enkf_log_type * data) { - return data->log_file; -} - - -void rml_enkf_log_free(rml_enkf_log_type * rml_log) { - rml_enkf_log_close( rml_log ); - util_safe_free( rml_log->log_file ); - free( rml_log ); -} - - -void rml_enkf_log_open( rml_enkf_log_type * rml_log , int iteration_nr ) { - if (rml_log->log_file) { - if ( iteration_nr == 0) { - - if (rml_log->clear_log) - rml_log->log_stream = util_mkdir_fopen( rml_log->log_file , "w"); - else - rml_log->log_stream = util_mkdir_fopen( rml_log->log_file , "a"); - - } else - rml_log->log_stream = util_fopen( rml_log->log_file , "a"); - } -} - - -bool rml_enkf_log_is_open( const rml_enkf_log_type * rml_log ) { - if (rml_log->log_stream) - return true; - else - return false; -} - - -void rml_enkf_log_close( rml_enkf_log_type * rml_log ) { - if (rml_log->log_stream) - fclose( rml_log->log_stream ); - - rml_log->log_stream = NULL; -} - - -void rml_enkf_log_line( rml_enkf_log_type * rml_log , const char * fmt , ...) { - if (rml_log->log_stream) { - va_list ap; - va_start(ap , fmt); - vfprintf( rml_log->log_stream , fmt , ap ); - va_end( ap ); - } -} - diff --git a/ThirdParty/Ert/libanalysis/modules/rml_enkf_log.h b/ThirdParty/Ert/libanalysis/modules/rml_enkf_log.h deleted file mode 100644 index 2c61d655e7..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/rml_enkf_log.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'rml_enkf_log.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef RML_ENKF_LOG_H -#define RML_ENKF_LOG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - - typedef struct rml_enkf_log_struct rml_enkf_log_type; - - rml_enkf_log_type * rml_enkf_log_alloc(); - void rml_enkf_log_free(rml_enkf_log_type * rml_log); - bool rml_enkf_log_get_clear_log( const rml_enkf_log_type * data ); - void rml_enkf_log_set_clear_log( rml_enkf_log_type * data , bool clear_log); - void rml_enkf_log_set_log_file( rml_enkf_log_type * data , const char * log_file ); - const char * rml_enkf_log_get_log_file( const rml_enkf_log_type * data); - void rml_enkf_log_open( rml_enkf_log_type * rml_log , int iteration_nr ); - void rml_enkf_log_close( rml_enkf_log_type * rml_log ); - void rml_enkf_log_line( rml_enkf_log_type * rml_log , const char * fmt , ...); - bool rml_enkf_log_is_open( const rml_enkf_log_type * rml_log ); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/ThirdParty/Ert/libanalysis/modules/std_enkf_debug.c b/ThirdParty/Ert/libanalysis/modules/std_enkf_debug.c deleted file mode 100644 index 8ae6a8b1b7..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/std_enkf_debug.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - This file is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define PREFIX_KEY "PREFIX" -#define DEFAULT_PREFIX "debug" - -/* - A random 'magic' integer id which is used for run-time type checking - of the input data. -*/ -#define STD_ENKF_DEBUG_TYPE_ID 269923 - -typedef struct std_enkf_debug_data_struct std_enkf_debug_data_type; - -struct std_enkf_debug_data_struct { - UTIL_TYPE_ID_DECLARATION; - std_enkf_data_type * std_data; - char * prefix; - int update_count; -}; - - -static UTIL_SAFE_CAST_FUNCTION_CONST( std_enkf_debug_data , STD_ENKF_DEBUG_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION( std_enkf_debug_data , STD_ENKF_DEBUG_TYPE_ID ) - - -void std_enkf_debug_data_set_prefix( std_enkf_debug_data_type * data , const char * prefix ) { - data->prefix = util_realloc_string_copy( data->prefix , prefix ); -} - - -void * std_enkf_debug_data_alloc( rng_type * rng) { - std_enkf_debug_data_type * data = util_malloc( sizeof * data ); - UTIL_TYPE_ID_INIT( data , STD_ENKF_DEBUG_TYPE_ID ); - data->std_data = std_enkf_data_alloc( rng ); - - data->update_count = 0; - data->prefix = NULL; - std_enkf_debug_data_set_prefix( data , DEFAULT_PREFIX ); - return data; -} - - -void std_enkf_debug_data_free( void * arg ) { - std_enkf_debug_data_type * data = std_enkf_debug_data_safe_cast( arg ); - std_enkf_data_free( data->std_data ); - free( data ); -} - -void std_enkf_debug_save_matrix( const matrix_type * m , const char * path , const char * file, bool transpose) { - char * filename = util_alloc_filename( path , file , NULL ); - - if (transpose) { - matrix_type * mt = matrix_alloc_transpose( m ); - matrix_dump_csv(mt,filename); - matrix_free( mt ); - } else - matrix_dump_csv(m , filename); - - - free( filename ); -} - - - -void std_enkf_debug_initX(void * module_data , - matrix_type * X , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D) { - - std_enkf_debug_data_type * data = std_enkf_debug_data_safe_cast( module_data ); - char * debug_path = util_alloc_sprintf( "%s/%d" , data->prefix , data->update_count ); - std_enkf_data_type * std_data = data->std_data; - util_make_path( debug_path ); - std_enkf_debug_save_matrix( A , debug_path , "prior_ert.csv" , true); - - std_enkf_debug_save_matrix( S , debug_path , "S.csv" , true); - std_enkf_debug_save_matrix( S , debug_path , "simResponses.csv" , true); - - std_enkf_debug_save_matrix( E , debug_path , "E.csv" , true); - std_enkf_debug_save_matrix( E , debug_path , "measurementErrors.csv" , true); - - std_enkf_debug_save_matrix( R , debug_path , "R.csv" , true); - std_enkf_debug_save_matrix( D , debug_path , "D.csv" , true); - { - matrix_type * value = matrix_alloc_sub_copy( dObs , 0 , 0 , matrix_get_rows( dObs ) , 1 ); - matrix_type * std = matrix_alloc_sub_copy( dObs , 0 , 1 , matrix_get_rows( dObs ) , 1 ); - - std_enkf_debug_save_matrix( value , debug_path , "observations.csv", true); - std_enkf_debug_save_matrix( std , debug_path , "observations_std.csv", true); - - matrix_free( value ); - matrix_free( std ); - } - std_enkf_initX( std_data , X , A , S , R , dObs , E , D ); - { - matrix_type * posterior = matrix_alloc_matmul( A , X ); - std_enkf_debug_save_matrix( posterior , debug_path , "posterior_ert.csv" , true); - matrix_free( posterior ); - } - - data->update_count++; -} - - - - - - - -bool std_enkf_debug_set_double( void * arg , const char * var_name , double value) { - std_enkf_debug_data_type * module_data = std_enkf_debug_data_safe_cast( arg ); - return std_enkf_set_double( module_data->std_data , var_name , value ); -} - - -bool std_enkf_debug_set_int( void * arg , const char * var_name , int value) { - std_enkf_debug_data_type * module_data = std_enkf_debug_data_safe_cast( arg ); - return std_enkf_set_int( module_data->std_data , var_name , value ); -} - - -bool std_enkf_debug_set_bool( void * arg , const char * var_name , bool value) { - std_enkf_debug_data_type * module_data = std_enkf_debug_data_safe_cast( arg ); - return std_enkf_set_bool( module_data->std_data , var_name , value ); -} - - -bool std_enkf_debug_set_string( void * arg , const char * var_name , const char * value) { - std_enkf_debug_data_type * module_data = std_enkf_debug_data_safe_cast( arg ); - if (strcmp(var_name, PREFIX_KEY) == 0) { - std_enkf_debug_data_set_prefix( module_data , value ); - return true; - } else - return false; -} - - - -long std_enkf_debug_get_options( void * arg , long flag ) { - const std_enkf_debug_data_type * module_data = std_enkf_debug_data_safe_cast_const( arg ); - long options = std_enkf_get_options( module_data->std_data , flag ); - options |= ANALYSIS_USE_A; - return options; -} - - -bool std_enkf_debug_has_var( const void * arg, const char * var_name) { - if (strcmp(var_name , PREFIX_KEY) == 0) - return true; - else { - const std_enkf_debug_data_type * module_data = std_enkf_debug_data_safe_cast_const( arg ); - return std_enkf_has_var( module_data->std_data , var_name ); - } -} - - -double std_enkf_debug_get_double( const void * arg, const char * var_name) { - const std_enkf_debug_data_type * module_data = std_enkf_debug_data_safe_cast_const( arg ); - return std_enkf_get_double( module_data->std_data , var_name ); -} - -int std_enkf_debug_get_int( const void * arg, const char * var_name) { - const std_enkf_debug_data_type * module_data = std_enkf_debug_data_safe_cast_const( arg ); - return std_enkf_get_int( module_data->std_data , var_name ); -} - - -bool std_enkf_debug_get_bool( const void * arg, const char * var_name) { - const std_enkf_debug_data_type * module_data = std_enkf_debug_data_safe_cast_const( arg ); - return std_enkf_get_bool( module_data->std_data , var_name ); -} - - -void * std_enkf_debug_get_ptr( const void * arg, const char * var_name) { - const std_enkf_debug_data_type * module_data = std_enkf_debug_data_safe_cast_const( arg ); - if (strcmp( var_name , PREFIX_KEY) == 0) - return (void *) module_data->prefix; - else - return NULL; -} - - - -#ifdef INTERNAL_LINK -#define LINK_NAME STD_ENKF_DEBUG -#else -#define LINK_NAME EXTERNAL_MODULE_SYMBOL -#endif - - -analysis_table_type LINK_NAME = { - .name = "STD_ENKF_DEBUG_DEBUG", - .alloc = std_enkf_debug_data_alloc, - .freef = std_enkf_debug_data_free, - .set_int = std_enkf_debug_set_int , - .set_double = std_enkf_debug_set_double , - .set_bool = std_enkf_debug_set_bool, - .set_string = std_enkf_debug_set_string, - .get_options = std_enkf_debug_get_options , - .initX = std_enkf_debug_initX , - .updateA = NULL, - .init_update = NULL, - .complete_update = NULL, - .has_var = std_enkf_debug_has_var, - .get_int = std_enkf_debug_get_int, - .get_double = std_enkf_debug_get_double, - .get_bool = std_enkf_debug_get_bool, - .get_ptr = std_enkf_debug_get_ptr -}; - diff --git a/ThirdParty/Ert/libanalysis/modules/tests/CMakeLists.txt b/ThirdParty/Ert/libanalysis/modules/tests/CMakeLists.txt deleted file mode 100644 index 6463497ffa..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/tests/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_executable(analysis_rml_enkf_common analysis_rml_enkf_common.c ../rml_enkf_common.c) -target_link_libraries( analysis_rml_enkf_common analysis util test_util ) - -add_test( analysis_rml_enkf_common ${EXECUTABLE_OUTPUT_PATH}/analysis_rml_enkf_common ) - diff --git a/ThirdParty/Ert/libanalysis/modules/tests/analysis_rml_enkf_common.c b/ThirdParty/Ert/libanalysis/modules/tests/analysis_rml_enkf_common.c deleted file mode 100644 index 355eeaca1f..0000000000 --- a/ThirdParty/Ert/libanalysis/modules/tests/analysis_rml_enkf_common.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'analysis_rml_common.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include - - - -void test_store_recover_state() { - rng_type * rng = rng_alloc( MZRAN , INIT_DEFAULT ); - int ens_size = 10; - int active_size = 8; - int rows = 100; - matrix_type * state = matrix_alloc(1,1); - bool_vector_type * ens_mask = bool_vector_alloc(ens_size , false); - matrix_type * A = matrix_alloc( rows , active_size); - matrix_type * A2 = matrix_alloc( rows, active_size ); - matrix_type * A3 = matrix_alloc( 1,1 ); - - for (int i=0; i < active_size; i++) - bool_vector_iset( ens_mask , i + 1 , true ); - - matrix_random_init(A , rng); - rml_enkf_common_store_state( state , A , ens_mask ); - - test_assert_int_equal( matrix_get_rows( state ) , rows ); - test_assert_int_equal( matrix_get_columns( state ) , ens_size ); - - { - int g; - int a = 0; - for (g=0; g < ens_size; g++) { - if (bool_vector_iget( ens_mask , g )) { - test_assert_true( matrix_columns_equal( state , g , A , a )); - a++; - } - } - } - - rml_enkf_common_recover_state( state , A2 , ens_mask); - rml_enkf_common_recover_state( state , A3 , ens_mask); - test_assert_true( matrix_equal( A , A2 )); - test_assert_true( matrix_equal( A , A3 )); - - bool_vector_free( ens_mask ); - matrix_free( state ); - matrix_free( A ); -} - - - - - -void test_scaleA() { - const int N = 10; - matrix_type * m1 = matrix_alloc(N , N); - matrix_type * m2 = matrix_alloc(N , N); - double * csc = util_calloc( N , sizeof * csc ); - rng_type * rng = rng_alloc( MZRAN , INIT_DEFAULT ); - - matrix_random_init( m1 , rng ); - matrix_assign(m2 , m1); - test_assert_true( matrix_equal(m1 , m2)); - - { - for (int i=0; i < N; i++) - csc[i] = (i + 2); - } - rml_enkf_common_scaleA( m1 , csc , false ); - { - int row,col; - for (row = 0; row < N; row++) { - for (col=0; col < N; col++) { - double v1 = matrix_iget(m1 , row , col); - double v2 = matrix_iget(m2 , row , col); - - test_assert_double_equal( v1 , v2 * csc[row] ); - } - } - } - rml_enkf_common_scaleA( m2 , csc , false ); - test_assert_true( matrix_equal(m1 , m2)); - - rml_enkf_common_scaleA( m2 , csc , true ); - { - int row,col; - for (row = 0; row < N; row++) { - for (col=0; col < N; col++) { - double v1 = matrix_iget(m1 , row , col); - double v2 = matrix_iget(m2 , row , col); - - test_assert_double_equal( v1 , v2 * csc[row] ); - } - } - } - rml_enkf_common_scaleA( m1 , csc , true ); - test_assert_true( matrix_equal(m1 , m2)); - - - rng_free( rng ); - matrix_free(m1); - matrix_free(m2); - free( csc ); -} - - - -int main(int argc , char ** argv) { - test_store_recover_state(); - test_scaleA(); - exit(0); -} - diff --git a/ThirdParty/Ert/libanalysis/script/CMakeLists.txt b/ThirdParty/Ert/libanalysis/script/CMakeLists.txt deleted file mode 100644 index ce8e9028fb..0000000000 --- a/ThirdParty/Ert/libanalysis/script/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set (destination ${CMAKE_INSTALL_PREFIX}/bin) - -install(PROGRAMS ert_module DESTINATION ${destination}) - -if (INSTALL_GROUP) - install(CODE "EXECUTE_PROCESS(COMMAND chgrp ${INSTALL_GROUP} ${destination}/ert_module)") - install(CODE "EXECUTE_PROCESS(COMMAND chmod g+w ${destination}/ert_module)") -endif() diff --git a/ThirdParty/Ert/libanalysis/script/ert_module b/ThirdParty/Ert/libanalysis/script/ert_module deleted file mode 100644 index 57a4d34683..0000000000 --- a/ThirdParty/Ert/libanalysis/script/ert_module +++ /dev/null @@ -1,239 +0,0 @@ -#!/usr/bin/env python -import sys -import os -import os.path -from optparse import OptionParser - -ert_root = os.path.realpath( os.path.join(os.path.dirname( os.path.realpath( os.path.abspath( __file__))) , "../") ) - -#----------------------------------------------------------------- - -default_lib_list = ["analysis" , "ert_util"] -default_define_list = ["HAVE_PTHREAD" , "COMPILER_GCC"] - - -CFLAGS = "-std=gnu99 -O2 -Wall -fpic -g" -LDFLAGS_list = ["-shared"] -CC = "gcc" -LD = CC - -#----------------------------------------------------------------- - - -c_file = 0 -header_file = 1 -object_file = 2 -other = 3 - -file_types = {".o" : object_file , - ".h" : header_file , - ".c" : c_file } - -def base_name(file): - (name,ext) = os.path.split( file ) - return name - - -def file_type( file ): - name,ext = os.path.splitext( file ) - return file_types.get( ext , other ) - - -def object_file_name( file ): - (name,ext) = os.path.splitext( file ) - return "%s.o" % name - - -def make_LDFLAGS( use_rpath , lib_path_list): - if use_rpath: - LDFLAGS_list.append("-Wl,--enable-new-dtags") - for path in lib_path_list: - LDFLAGS_list.append("-Wl,-rpath,%s" % path) - LDFLAGS_list.append("-Wl,-soname,") - - return " ".join(LDFLAGS_list) - - -def make_XFLAG( X , def_list ): - FLAG = "" - for d in def_list: - FLAG += "-%s%s " % (X , d) - return FLAG - - -def compile_file( file , IFLAG , DFLAG , verbose): - target = object_file_name( file ) - if os.path.exists( target ): - os.unlink( target ) - - cmd = "%s %s %s %s -c %s -o %s" % (CC , CFLAGS , IFLAG , DFLAG , file , target) - if verbose: - print "Compiling: %s" % cmd - os.system( cmd ) - if os.path.exists( target ): - return target - else: - sys.exit("Compile cmd:%s failed" % cmd) - - -def link( soname , filename , object_list , LDFLAGS , LFLAG , lFLAG , verbose): - object_string = "" - for obj in object_list: - object_string += "%s " % obj - - cmd = "%s %s%s -o %s %s %s %s" % ( LD , LDFLAGS , soname , filename , object_string , LFLAG , lFLAG) - if verbose: - print "Linking : %s" % cmd - if os.path.exists( filename ): - os.unlink( filename ) - os.system(cmd) - if os.path.exists( filename ): - return True - else: - return False - - -usage = """ -The ert_module script is a small convenience script to -compile C source code into an analysis module which can -be loaded by ert. The script is controlled by commandline -arguments: - - 1. The first argument should be the name of the module - you are creating, an extension .so will be appended. - - 2. List the source files you want to include, the - files should have extension .c. In addition you can - include object files which have been compiled by - other means, the object files should have - extension .o - - 3. Optionally you can pass -I and -D options which are - passed to the compiler; and -l and -L options which - are passed to the linker. - -Example: - - ert_module my_module my_src1.c my_src2.c f90_object1.o f90_object2.o -I/path -DFAST=Yes -L/path/to/lib -lfm -lz - -Will create a module 'my_module' based on the src files my_src1.c -and my_src2.c; in addition the object files f90_object1.o and -f90_object2.o will be included in the final module. - ------------------------------------------------------------------ - -To compile the module code you will typically need the include files -and libraries from an existing ert installation. By default the -ert_module script will locate the ert installation based on the -location of the script, but you can pass the option: - - --ert-root=/path/where/ert/is/installed - -The --ert-root option should point to a directory containing the -lib64/ and include/ directories of a binary etr distribution. In -addition to --ert-root you can use the normal -L/path/to/lib option to -send in additional link path arguments. - -By default the path to shared libraries will not be embedded in the -resulting module, but by passing the option --use-rpath you can tell -the script to embed these paths in the final shared object. - ------------------------------------------------------------------ - -Options summary: - - -L/path/to/lib: Include the path /path/to/lib in the linker path - - -llib1 : Link with the library lib1 - - -I/include : Include the path /include in the compiler include path. - - --ert-root=/path/to/ert : Use this is as root for ert headers - and libraries. [Default: inferred from location of script] - - --use-rpath : Embed library paths in shared objects. Default off. - - --exclude-ert: Do not use any ert default libraries or headers - - -Default flags: - -Compile: %s %s %s -Link: %s %s %s -""" % (CC, - make_XFLAG( "I" , ["./" , "%s/include" % ert_root]) , - make_XFLAG( "D" , default_define_list) , - LD , - make_XFLAG("L" , ["%s/lib64" % ert_root]) , - make_XFLAG("l" , default_lib_list)) - -parser = OptionParser( usage ) -parser.add_option("--ert-root" , dest="ert_root" , action="store") -parser.add_option("-I" , dest = "include_path_list", action = "append" , default = []) -parser.add_option("-D" , dest = "define_list" , action = "append" , default = []) -parser.add_option("-L" , dest = "lib_path_list" , action = "append" , default = []) -parser.add_option("-l" , dest = "lib_list" , action = "append" , default = []) -parser.add_option("--exclude-ert" , dest = "exclude_ert" , action="store_true" , default = False) -parser.add_option("--use-rpath" , dest="use_rpath" , action="store_true" , default = False) -parser.add_option("--silent" , dest="silent" , action="store_true" , default = False) - -(options , args) = parser.parse_args() -if len(args) == 0: - sys.exit( usage ) - -if options.ert_root: - ert_root = options.ert_root - -if options.exclude_ert: - default_include_path_list = ["./"] - default_lib_path_list = [] - default_lib_list = [] -else: - default_include_path_list = ["./" , "%s/include" % ert_root] - default_lib_path_list = ["%s/lib64" % ert_root] - default_lib_list = default_lib_list - - -# What is supplied as commandline options should take presedence, this -# implies that it should be first OR last on the commandline. -include_path_list = options.include_path_list + default_include_path_list -define_list = default_define_list + options.define_list -lib_list = options.lib_list + default_lib_list -lib_path_list = options.lib_path_list + default_lib_path_list - - -verbose = not options.silent -LDFLAGS = make_LDFLAGS( options.use_rpath , lib_path_list) -input_name = args[0] -(path , tmp ) = os.path.split( input_name ) -(module , ext) = os.path.splitext( tmp ) - -soname = "%s.so" % module -if path: - filename = "%s/%s.so" % (path , module) - if not os.path.exists( path ): - os.makedirs( path ) -else: - filename = "%s.so" % module - -#----------------------------------------------------------------- - -IFLAG = make_XFLAG( "I" , include_path_list ) -DFLAG = make_XFLAG( "D" , define_list ) -LFLAG = make_XFLAG( "L" , lib_path_list ) -lFLAG = make_XFLAG( "l" , lib_list ) - -object_list = [] -for arg in args[1:]: - if file_type( arg ) == c_file: - object_list.append( compile_file( arg , IFLAG , DFLAG , verbose) ) - elif file_type( arg ) == object_file: - object_list.append( arg ) - else: - print "** Warning: ignoring file:%s" % arg - - -if link( soname , filename , object_list , LDFLAGS , LFLAG , lFLAG , verbose): - sys.exit() -else: - sys.exit("Creating library failed") diff --git a/ThirdParty/Ert/libanalysis/src/CMakeLists.txt b/ThirdParty/Ert/libanalysis/src/CMakeLists.txt deleted file mode 100644 index 76c2586960..0000000000 --- a/ThirdParty/Ert/libanalysis/src/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -# Common libanalysis library -set( source_files analysis_module.c enkf_linalg.c std_enkf.c sqrt_enkf.c cv_enkf.c bootstrap_enkf.c null_enkf.c fwd_step_enkf.c fwd_step_log.c module_data_block.c module_data_block_vector.c module_obs_block.c module_obs_block_vector.c module_info.c) -set( header_files analysis_module.h enkf_linalg.h analysis_table.h std_enkf.h fwd_step_enkf.h fwd_step_log.h module_data_block.h module_data_block_vector.h module_obs_block.h module_obs_block_vector.h module_info.h) -add_library( analysis SHARED ${source_files} ) -set_target_properties( analysis PROPERTIES COMPILE_DEFINITIONS INTERNAL_LINK) -set_target_properties( analysis PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR} ) - -target_link_libraries( analysis ert_util ) -target_link_libraries( analysis dl ) - -if (USE_RUNPATH) - add_runpath( analysis ) -endif() - - -#----------------------------------------------------------------- - -if (ERT_USE_OPENMP) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OpenMP_SHARED_LINKER_FLAGS}") -endif() - - -if (INSTALL_ERT) - install(TARGETS analysis DESTINATION ${CMAKE_INSTALL_LIBDIR}) - #install(TARGETS rml_enkf DESTINATION ${CMAKE_INSTALL_LIBDIR}) - foreach(header ${header_files}) - install(FILES ../include/ert/analysis/${header} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/ert/analysis) - endforeach() -endif() - diff --git a/ThirdParty/Ert/libanalysis/src/analysis_module.c b/ThirdParty/Ert/libanalysis/src/analysis_module.c deleted file mode 100644 index 59aec768a0..0000000000 --- a/ThirdParty/Ert/libanalysis/src/analysis_module.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'analysis_module.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#define ANALYSIS_MODULE_TYPE_ID 6610123 - -struct analysis_module_struct { - UTIL_TYPE_ID_DECLARATION; - void * lib_handle; - void * module_data; - char * symbol_table; - char * lib_name; - - analysis_free_ftype * freef; - analysis_alloc_ftype * alloc; - analysis_initX_ftype * initX; - analysis_updateA_ftype * updateA; - analysis_init_update_ftype * init_update; - analysis_complete_update_ftype * complete_update; - - analysis_get_options_ftype * get_options; - analysis_set_int_ftype * set_int; - analysis_set_double_ftype * set_double; - analysis_set_bool_ftype * set_bool; - analysis_set_string_ftype * set_string; - - analysis_has_var_ftype * has_var; - analysis_get_int_ftype * get_int; - analysis_get_double_ftype * get_double; - analysis_get_bool_ftype * get_bool; - analysis_get_ptr_ftype * get_ptr; - - bool internal; - char * user_name; /* String used to identify this module for the user; not used in - the linking process. */ -}; - - - -static analysis_module_type * analysis_module_alloc_empty( const char * symbol_table , const char * lib_name) { - analysis_module_type * module = util_malloc( sizeof * module ); - UTIL_TYPE_ID_INIT( module , ANALYSIS_MODULE_TYPE_ID ); - - module->lib_handle = NULL; - module->initX = NULL; - module->updateA = NULL; - module->set_int = NULL; - module->set_bool = NULL; - module->set_double = NULL; - module->set_string = NULL; - module->module_data = NULL; - module->init_update = NULL; - module->complete_update = NULL; - module->has_var = NULL; - module->get_int = NULL; - module->get_double = NULL; - module->get_bool = NULL; - module->get_ptr = NULL; - module->alloc = NULL; - - module->user_name = NULL; - module->symbol_table = util_alloc_string_copy( symbol_table ); - module->lib_name = util_alloc_string_copy( lib_name ); - - return module; -} - - -static bool analysis_module_internal_check( analysis_module_type * module ) { - if (!module->user_name) - fprintf(stderr,"Invalid module loaded from lib:%s / symbol_table:%s - name not set\n", module->lib_name , module->symbol_table); - - return true; -} - - -static analysis_module_type * analysis_module_alloc__( rng_type * rng , - const analysis_table_type * table , - const char * symbol_table , - const char * lib_name , - void * lib_handle ) { - - analysis_module_type * module = analysis_module_alloc_empty( symbol_table , lib_name ); - - module->lib_handle = lib_handle; - module->initX = table->initX; - module->updateA = table->updateA; - module->init_update = table->init_update; - module->complete_update = table->complete_update; - module->set_int = table->set_int; - module->set_double = table->set_double; - module->set_string = table->set_string; - module->set_bool = table->set_bool; - module->alloc = table->alloc; - module->freef = table->freef; - module->get_options = table->get_options; - module->has_var = table->has_var; - module->get_int = table->get_int; - module->get_double = table->get_double; - module->get_bool = table->get_bool; - module->get_ptr = table->get_ptr; - analysis_module_set_name( module , table->name ); - - if (module->alloc) - module->module_data = module->alloc( rng ); - - if (!analysis_module_internal_check( module )) { - fprintf(stderr,"** Warning loading module: %s failed - internal inconsistency\n", module->user_name); - analysis_module_free( module ); - module = NULL; - } - - return module; -} - - - - - -static analysis_module_type * analysis_module_alloc( rng_type * rng , - const char * libname , - const char * table_name , - bool verbose, - analysis_module_load_status_enum * load_status) { - analysis_module_type * module = NULL; - void * lib_handle = dlopen( libname , RTLD_NOW ); - if (lib_handle != NULL) { - analysis_table_type * analysis_table = (analysis_table_type *) dlsym( lib_handle , table_name ); - if (analysis_table != NULL) { - *load_status = LOAD_OK; - module = analysis_module_alloc__( rng , analysis_table , table_name , libname , lib_handle ); - } else { - *load_status = LOAD_SYMBOL_TABLE_NOT_FOUND; - if (verbose) - fprintf(stderr , "Failed to load symbol table:%s Error:%s \n",table_name , dlerror()); - } - - if (module == NULL) - dlclose( lib_handle ); - } else { - *load_status = DLOPEN_FAILURE; - if (verbose) - fprintf(stderr , "Failed to load library:%s Error:%s \n",libname , dlerror()); - } - - if (module != NULL) { - if (libname == NULL) - module->internal = true; - else - module->internal = false; - } - - return module; -} - -analysis_module_type * analysis_module_alloc_internal__( rng_type * rng , const char * symbol_table , bool verbose , analysis_module_load_status_enum * load_status) { - return analysis_module_alloc( rng , NULL , symbol_table , verbose , load_status); -} - -analysis_module_type * analysis_module_alloc_internal( rng_type * rng , const char * symbol_table ) { - analysis_module_load_status_enum load_status; - return analysis_module_alloc_internal__( rng , symbol_table , true , &load_status); -} - - -analysis_module_type * analysis_module_alloc_external__(rng_type * rng , const char * lib_name , bool verbose , analysis_module_load_status_enum * load_status) { - return analysis_module_alloc( rng , lib_name , EXTERNAL_MODULE_NAME , verbose , load_status); -} - - -analysis_module_type * analysis_module_alloc_external( rng_type * rng , const char * lib_name) { - analysis_module_load_status_enum load_status; - return analysis_module_alloc_external__( rng , lib_name , true , &load_status); -} - -/*****************************************************************/ - -const char * analysis_module_get_name( const analysis_module_type * module ) { - return module->user_name; -} - -void analysis_module_set_name( analysis_module_type * module , const char * name) { - module->user_name = util_realloc_string_copy( module->user_name , name ); -} - - -const char * analysis_module_get_table_name( const analysis_module_type * module) { - return module->symbol_table; -} - -const char * analysis_module_get_lib_name( const analysis_module_type * module) { - return module->lib_name; -} - -bool analysis_module_internal( const analysis_module_type * module ) { - return module->internal; -} - -/*****************************************************************/ - -static UTIL_SAFE_CAST_FUNCTION( analysis_module , ANALYSIS_MODULE_TYPE_ID ) -UTIL_IS_INSTANCE_FUNCTION( analysis_module , ANALYSIS_MODULE_TYPE_ID ) - - -void analysis_module_free( analysis_module_type * module ) { - if (module->freef != NULL) - module->freef( module->module_data ); - - util_safe_free( module->lib_name ); - free( module->user_name ); - free( module->symbol_table ); - dlclose( module->lib_handle ); - free( module ); -} - - -void analysis_module_free__( void * arg) { - analysis_module_type * module = analysis_module_safe_cast( arg ); - analysis_module_free( module ); -} - -/*****************************************************************/ -/* Update functions */ - - -void analysis_module_initX(analysis_module_type * module , - matrix_type * X , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D ) { - - - module->initX(module->module_data , X , A , S , R , dObs , E , D ); -} - - -void analysis_module_updateA(analysis_module_type * module , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D , - const module_info_type* module_info) { - - module->updateA(module->module_data , A , S , R , dObs , E , D, module_info); -} - - - - -void analysis_module_init_update( analysis_module_type * module , - const bool_vector_type * ens_mask , - const matrix_type * S , - const matrix_type * R , - const matrix_type * dObs , - const matrix_type * E , - const matrix_type * D ) { - if (module->init_update != NULL) - module->init_update( module->module_data , ens_mask , S , R , dObs , E , D); -} - - -void analysis_module_complete_update( analysis_module_type * module ) { - if (module->complete_update != NULL) - module->complete_update( module->module_data ); -} - -/*****************************************************************/ - - -static bool analysis_module_set_int(analysis_module_type * module , const char * flag , int value) { - if (module->set_int != NULL) - return module->set_int( module->module_data , flag , value ); - else - return false; -} - -static bool analysis_module_set_double(analysis_module_type * module , const char * var , double value) { - if (module->set_double != NULL) - return module->set_double( module->module_data , var , value ); - else - return false; -} - - -static bool analysis_module_set_bool(analysis_module_type * module , const char * var , bool value) { - if (module->set_bool != NULL) - return module->set_bool( module->module_data , var , value ); - else - return false; -} - - -static bool analysis_module_set_string(analysis_module_type * module , const char * var , const char * value) { - if (module->set_string != NULL) - return module->set_string( module->module_data , var , value ); - else - return false; -} - - - -/* - The input value typically comes from the configuration system and - is in terms of a string, irrespective of the fundamental type of - the underlying parameter. The algorithm for setting the parameter - tries datatypes as follows: integer - double - string. - - For the numeric datatypes the algorithm is two step: - - 1. Try the conversion string -> numeric. - 2. Try calling the analysis_module_set_xxx() function. - - Observe that this implies that the same variable name can NOT be - used for different variable types. -*/ - -bool analysis_module_set_var( analysis_module_type * module , const char * var_name , const char * string_value ) { - bool set_ok = false; - { - int int_value; - - if (util_sscanf_int( string_value , &int_value )) - set_ok = analysis_module_set_int( module , var_name , int_value ); - - - if (set_ok) - return true; - } - - { - double double_value; - if (util_sscanf_double( string_value , &double_value )) - set_ok = analysis_module_set_double( module , var_name , double_value ); - - if (set_ok) - return true; - } - - { - bool bool_value; - if (util_sscanf_bool( string_value , &bool_value)) - set_ok = analysis_module_set_bool( module , var_name , bool_value ); - - if (set_ok) - return true; - } - - - set_ok = analysis_module_set_string( module , var_name , string_value ); - if (!set_ok) - fprintf(stderr,"** Warning: failed to set %s=%s for analysis module:%s\n", var_name , string_value , module->user_name); - - return set_ok; -} - - -bool analysis_module_check_option( const analysis_module_type * module , long flag) { - if ((flag & module->get_options( module->module_data , flag )) == flag) - return true; - else - return false; -} - - -bool analysis_module_has_var( const analysis_module_type * module , const char * var) { - if (module->has_var) - return module->has_var( module->module_data , var ); - else - return false; -} - - -int analysis_module_get_int( const analysis_module_type * module , const char * var) { - if (analysis_module_has_var( module , var )) { - if (module->get_int != NULL) - return module->get_int( module->module_data , var ); - else - util_exit("%s: Tried to get integer variable:%s from module:%s - get_int() method not implemented for this module\n" , __func__ , var , module->user_name); - } else - util_exit("%s: Tried to get integer variable:%s from module:%s - module does not support this variable \n" , __func__ , var , module->user_name); - - return 0; -} - - -bool analysis_module_get_bool( const analysis_module_type * module , const char * var) { - if (analysis_module_has_var( module , var )) { - if (module->get_bool != NULL) - return module->get_bool( module->module_data , var ); - else - util_exit("%s: Tried to get bool variable:%s from module:%s - get_int() method not implemented for this module\n" , __func__ , var , module->user_name); - } else - util_exit("%s: Tried to get bool variable:%s from module:%s - module does not support this variable \n" , __func__ , var , module->user_name); - - return false; -} - - -double analysis_module_get_double( const analysis_module_type * module , const char * var) { - if (analysis_module_has_var( module , var )) { - if (module->get_double != NULL) - return module->get_double( module->module_data , var ); - else - util_exit("%s: Tried to get double variable:%s from module:%s - get_double() method not implemented for this module\n" , __func__ , var , module->user_name); - } else - util_exit("%s: Tried to get double variable:%s from module:%s - module does not support this variable \n" , __func__ , var , module->user_name); - - return 0; -} - - -void * analysis_module_get_ptr( const analysis_module_type * module , const char * var) { - if (analysis_module_has_var( module , var )) { - if (module->get_double != NULL) - return module->get_ptr( module->module_data , var ); - else - util_exit("%s: Tried to get pointer variable:%s from module:%s - get_ptr() method not implemented for this module\n" , __func__ , var , module->user_name); - } else - util_exit("%s: Tried to get pointer variable:%s from module:%s - module does not support this variable \n" , __func__ , var , module->user_name); - - return NULL; -} - - -/*****************************************************************/ - -const char * analysis_module_flag_enum_iget( int index, int * value) { - return util_enum_iget( index , ANALYSIS_MODULE_FLAG_ENUM_SIZE , (const util_enum_element_type []) { ANALYSIS_MODULE_FLAG_ENUM_DEFS }, value); -} - diff --git a/ThirdParty/Ert/libanalysis/src/bootstrap_enkf.c b/ThirdParty/Ert/libanalysis/src/bootstrap_enkf.c deleted file mode 100644 index 29c7980b53..0000000000 --- a/ThirdParty/Ert/libanalysis/src/bootstrap_enkf.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'bootstrap_enkf.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -#define BOOTSTRAP_ENKF_TYPE_ID 741223 - -#define INVALID_SUBSPACE_DIMENSION -1 -#define INVALID_TRUNCATION -1 -#define DEFAULT_TRUNCATION 0.95 -#define DEFAULT_NCOMP INVALID_SUBSPACE_DIMENSION - -#define DEFAULT_DO_CV false -#define DEFAULT_NFOLDS 10 -#define NFOLDS_KEY "BOOTSTRAP_NFOLDS" - - -typedef struct { - UTIL_TYPE_ID_DECLARATION; - std_enkf_data_type * std_enkf_data; - cv_enkf_data_type * cv_enkf_data; - rng_type * rng; - long option_flags; - bool doCV; -} bootstrap_enkf_data_type; - - -static UTIL_SAFE_CAST_FUNCTION( bootstrap_enkf_data , BOOTSTRAP_ENKF_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION_CONST( bootstrap_enkf_data , BOOTSTRAP_ENKF_TYPE_ID ) - - -void bootstrap_enkf_set_doCV( bootstrap_enkf_data_type * data , bool doCV) { - data->doCV = doCV; -} - - - -void bootstrap_enkf_set_truncation( bootstrap_enkf_data_type * boot_data , double truncation ) { - std_enkf_set_truncation( boot_data->std_enkf_data , truncation ); - cv_enkf_set_truncation( boot_data->cv_enkf_data , truncation ); -} - - -void bootstrap_enkf_set_subspace_dimension( bootstrap_enkf_data_type * boot_data , int ncomp) { - std_enkf_set_subspace_dimension( boot_data->std_enkf_data , ncomp ); - cv_enkf_set_subspace_dimension( boot_data->cv_enkf_data , ncomp ); -} - - -void * bootstrap_enkf_data_alloc( rng_type * rng ) { - bootstrap_enkf_data_type * boot_data = util_malloc( sizeof * boot_data ); - UTIL_TYPE_ID_INIT( boot_data , BOOTSTRAP_ENKF_TYPE_ID ); - - boot_data->std_enkf_data = std_enkf_data_alloc( NULL ); - boot_data->cv_enkf_data = cv_enkf_data_alloc( rng ); - - boot_data->rng = rng; - bootstrap_enkf_set_truncation( boot_data , DEFAULT_TRUNCATION ); - bootstrap_enkf_set_subspace_dimension( boot_data , DEFAULT_NCOMP ); - bootstrap_enkf_set_doCV( boot_data , DEFAULT_DO_CV); - boot_data->option_flags = ANALYSIS_NEED_ED + ANALYSIS_UPDATE_A + ANALYSIS_SCALE_DATA; - return boot_data; -} - - - - - -void bootstrap_enkf_data_free( void * arg ) { - bootstrap_enkf_data_type * boot_data = bootstrap_enkf_data_safe_cast( arg ); - { - std_enkf_data_free( boot_data->std_enkf_data ); - cv_enkf_data_free( boot_data->cv_enkf_data ); - } - free( boot_data ); -} - - -static int ** alloc_iens_resample( rng_type * rng , int ens_size ) { - int ** iens_resample; - int iens; - - iens_resample = util_calloc( ens_size , sizeof * iens_resample ); - for (iens = 0; iens < ens_size; iens++) - iens_resample[iens] = util_calloc( ens_size , sizeof( ** iens_resample ) ); - - { - int i,j; - for (i=0; i < ens_size; i++) - for (j=0; j < ens_size; j++) - iens_resample[i][j] = rng_get_int( rng , ens_size ); - } - return iens_resample; -} - - -static void free_iens_resample( int ** iens_resample, int ens_size ) { - for (int i=0; i < ens_size; i++) - free( iens_resample[i] ); - free( iens_resample ); -} - - - -void bootstrap_enkf_updateA(void * module_data , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D , - const module_info_type* module_info) { - - bootstrap_enkf_data_type * bootstrap_data = bootstrap_enkf_data_safe_cast( module_data ); - { - const int num_cpu_threads = 4; - int ens_size = matrix_get_columns( A ); - matrix_type * X = matrix_alloc( ens_size , ens_size ); - matrix_type * A0 = matrix_alloc_copy( A ); - matrix_type * S_resampled = matrix_alloc_copy( S ); - matrix_type * A_resampled = matrix_alloc( matrix_get_rows(A0) , matrix_get_columns( A0 )); - int ** iens_resample = alloc_iens_resample( bootstrap_data->rng , ens_size ); - { - int ensemble_members_loop; - for ( ensemble_members_loop = 0; ensemble_members_loop < ens_size; ensemble_members_loop++) { - int unique_bootstrap_components; - int ensemble_counter; - /* Resample A and meas_data. Here we are careful to resample the working copy.*/ - { - { - int_vector_type * bootstrap_components = int_vector_alloc( ens_size , 0); - for (ensemble_counter = 0; ensemble_counter < ens_size; ensemble_counter++) { - int random_column = iens_resample[ ensemble_members_loop][ensemble_counter]; - int_vector_iset( bootstrap_components , ensemble_counter , random_column ); - matrix_copy_column( A_resampled , A0 , ensemble_counter , random_column ); - matrix_copy_column( S_resampled , S , ensemble_counter , random_column ); - } - int_vector_select_unique( bootstrap_components ); - unique_bootstrap_components = int_vector_size( bootstrap_components ); - int_vector_free( bootstrap_components ); - } - - if (bootstrap_data->doCV) { - const bool_vector_type * ens_mask = NULL; - cv_enkf_init_update( bootstrap_data->cv_enkf_data , ens_mask , S_resampled , R , dObs , E , D); - cv_enkf_initX( bootstrap_data->cv_enkf_data , X , A_resampled , S_resampled , R , dObs , E , D); - } else - std_enkf_initX(bootstrap_data->std_enkf_data , X , NULL , S_resampled,R, dObs, E,D ); - - - matrix_inplace_matmul_mt1( A_resampled , X , num_cpu_threads ); - matrix_inplace_add( A_resampled , A0 ); - matrix_copy_column( A , A_resampled, ensemble_members_loop, ensemble_members_loop); - - } - } - } - - - free_iens_resample( iens_resample , ens_size); - matrix_free( X ); - matrix_free( S_resampled ); - matrix_free( A_resampled ); - matrix_free( A0 ); - } -} - - - - - - -long bootstrap_enkf_get_options( void * arg , long flag) { - bootstrap_enkf_data_type * bootstrap_data = bootstrap_enkf_data_safe_cast( arg ); - { - return bootstrap_data->option_flags; - } -} - - -bool bootstrap_enkf_set_double( void * arg , const char * var_name , double value) { - bootstrap_enkf_data_type * bootstrap_data = bootstrap_enkf_data_safe_cast( arg ); - { - if (std_enkf_set_double( bootstrap_data->std_enkf_data , var_name , value )) - return true; - else { - return false; - } - } -} - - -bool bootstrap_enkf_set_int( void * arg , const char * var_name , int value) { - bootstrap_enkf_data_type * bootstrap_data = bootstrap_enkf_data_safe_cast( arg ); - { - if (std_enkf_set_int( bootstrap_data->std_enkf_data , var_name , value )) - return true; - else { - return false; - } - } -} - - -bool bootstrap_enkf_set_bool( void * arg , const char * var_name , bool value) { - bootstrap_enkf_data_type * bootstrap_data = bootstrap_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , "CV" ) == 0) - bootstrap_data->doCV = value; - else - name_recognized = false; - - return name_recognized; - } -} - - -bool bootstrap_enkf_has_var( const void * arg, const char * var_name) { - const bootstrap_enkf_data_type * module_data = bootstrap_enkf_data_safe_cast_const( arg ); - { - return std_enkf_has_var(module_data->std_enkf_data, var_name); - } -} - -double bootstrap_enkf_get_double( const void * arg, const char * var_name) { - const bootstrap_enkf_data_type * module_data = bootstrap_enkf_data_safe_cast_const( arg ); - { - return std_enkf_get_double( module_data->std_enkf_data , var_name); - } -} - -int bootstrap_enkf_get_int( const void * arg, const char * var_name) { - const bootstrap_enkf_data_type * module_data = bootstrap_enkf_data_safe_cast_const( arg ); - { - return std_enkf_get_int( module_data->std_enkf_data , var_name); - } -} - - - - -#ifdef INTERNAL_LINK -#define LINK_NAME BOOTSTRAP_ENKF -#else -#define LINK_NAME EXTERNAL_MODULE_SYMBOL -#endif - - -analysis_table_type LINK_NAME = { - .name = "BOOTSTRAP_ENKF", - .alloc = bootstrap_enkf_data_alloc, - .freef = bootstrap_enkf_data_free, - .set_int = bootstrap_enkf_set_int , - .set_double = bootstrap_enkf_set_double , - .set_bool = bootstrap_enkf_set_bool , - .set_string = NULL , - .get_options = bootstrap_enkf_get_options , - .initX = NULL, - .updateA = bootstrap_enkf_updateA, - .init_update = NULL, - .complete_update = NULL, - .has_var = bootstrap_enkf_has_var, - .get_int = bootstrap_enkf_get_int, - .get_double = bootstrap_enkf_get_double, - .get_bool = NULL, - .get_ptr = NULL, -}; diff --git a/ThirdParty/Ert/libanalysis/src/cv_enkf.c b/ThirdParty/Ert/libanalysis/src/cv_enkf.c deleted file mode 100644 index b00574c83d..0000000000 --- a/ThirdParty/Ert/libanalysis/src/cv_enkf.c +++ /dev/null @@ -1,721 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'cv_enkf.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define CV_ENKF_TYPE_ID 765523 - -#define INVALID_SUBSPACE_DIMENSION -1 -#define INVALID_TRUNCATION -1 -#define DEFAULT_SUBSPACE_DIMENSION INVALID_SUBSPACE_DIMENSION - -#define DEFAULT_NFOLDS 10 -#define DEFAULT_PEN_PRESS false -#define NFOLDS_KEY "CV_NFOLDS" -#define CV_PEN_PRESS_KEY "CV_PEN_PRESS" - - - - -struct cv_enkf_data_struct { - UTIL_TYPE_ID_DECLARATION; - matrix_type * Z; - matrix_type * Rp; - matrix_type * Dp; - rng_type * rng; - double truncation; - int nfolds; - int subspace_dimension; // ENKF_NCOMP_KEY (-1: use Truncation instead) - long option_flags; - bool penalised_press; -}; - - - -static UTIL_SAFE_CAST_FUNCTION( cv_enkf_data , CV_ENKF_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION_CONST( cv_enkf_data , CV_ENKF_TYPE_ID ) - - -void cv_enkf_set_truncation( cv_enkf_data_type * data , double truncation ) { - data->truncation = truncation; - if (truncation > 0.0) - data->subspace_dimension = INVALID_SUBSPACE_DIMENSION; -} - - -void cv_enkf_set_subspace_dimension( cv_enkf_data_type * data , int subspace_dimension) { - data->subspace_dimension = subspace_dimension; - if (subspace_dimension > 0) - data->truncation = INVALID_TRUNCATION; -} - - -void cv_enkf_set_nfolds( cv_enkf_data_type * data , int nfolds ) { - data->nfolds = nfolds; -} - -void cv_enkf_set_pen_press( cv_enkf_data_type * data , bool value ) { - data->penalised_press = value; -} - - -void * cv_enkf_data_alloc( rng_type * rng ) { - cv_enkf_data_type * data = util_malloc( sizeof * data); - UTIL_TYPE_ID_INIT( data , CV_ENKF_TYPE_ID ); - - data->Z = NULL; - data->Rp = NULL; - data->Dp = NULL; - data->rng = rng; - - data->penalised_press = DEFAULT_PEN_PRESS; - data->option_flags = ANALYSIS_NEED_ED + ANALYSIS_USE_A + ANALYSIS_SCALE_DATA; - data->nfolds = DEFAULT_NFOLDS; - cv_enkf_set_truncation( data , DEFAULT_ENKF_TRUNCATION_ ); - - return data; -} - - - -void cv_enkf_data_free( void * arg ) { - cv_enkf_data_type * cv_data = cv_enkf_data_safe_cast( arg ); - { - matrix_safe_free( cv_data->Z ); - matrix_safe_free( cv_data->Rp ); - matrix_safe_free( cv_data->Dp ); - } - free( cv_data ); -} - - - - - - -void cv_enkf_init_update( void * arg , - const bool_vector_type * ens_mask , - const matrix_type * S , - const matrix_type * R , - const matrix_type * dObs , - const matrix_type * E , - const matrix_type * D ) { - - cv_enkf_data_type * cv_data = cv_enkf_data_safe_cast( arg ); - { - int i, j; - const int nrobs = matrix_get_rows( S ); - const int nrens = matrix_get_columns( S ); - const int nrmin = util_int_min( nrobs , nrens ); - - cv_data->Z = matrix_alloc( nrmin , nrens ); - cv_data->Rp = matrix_alloc( nrmin , nrmin ); - cv_data->Dp = matrix_alloc( nrmin , nrens ); - - /* - Compute SVD(S) - */ - matrix_type * U0 = matrix_alloc( nrobs , nrmin ); /* Left singular vectors. */ - matrix_type * V0T = matrix_alloc( nrmin , nrens ); /* Right singular vectors. */ - - double * inv_sig0 = util_calloc( nrmin , sizeof * inv_sig0 ); - double * sig0 = inv_sig0; - - printf("Computing svd using truncation %0.4f\n",cv_data->truncation); - - enkf_linalg_svdS(S , cv_data->truncation , cv_data->subspace_dimension , DGESVD_MIN_RETURN , inv_sig0 , U0 , V0T); - - /* Need to use the original non-inverted singular values. */ - for(i = 0; i < nrmin; i++) - if ( inv_sig0[i] > 0 ) - sig0[i] = 1.0 / inv_sig0[i]; - - /* - Compute the actual principal components, Z = sig0 * VOT - NOTE: Z contains potentially alot of redundant zeros, but - we do not care about this for now - */ - - for(i = 0; i < nrmin; i++) - for(j = 0; j < nrens; j++) - matrix_iset( cv_data->Z , i , j , sig0[i] * matrix_iget( V0T , i , j ) ); - - /* Also compute Rp */ - { - matrix_type * X0 = matrix_alloc( nrmin , matrix_get_rows( R )); - matrix_dgemm(X0 , U0 , R , true , false , 1.0 , 0.0); /* X0 = U0^T * R */ - matrix_dgemm(cv_data->Rp , X0 , U0 , false , false , 1.0 , 0.0); /* Rp = X0 * U0 */ - matrix_free(X0); - } - - /*We also need to compute the reduced "Innovation matrix" Dp = U0' * D */ - matrix_dgemm(cv_data->Dp , U0 , D , true , false , 1.0 , 0.0); - - - free(inv_sig0); - matrix_free(U0); - matrix_free(V0T); - - /* - 2: Diagonalize the S matrix; singular vectors etc. needed later in the local CV: - (V0T = transposed right singular vectors of S, Z = scaled principal components, - eig = scaled, inverted singular vectors, U0 = left singular vectors of S - eig = inv(I+Lambda1),(Eq.14.30, and 14.29, Evensen, 2007, respectively) - */ - } -} - - - -/*Function that computes the PRESS for different subspace dimensions using - m-fold CV - INPUT : - A : State-Vector ensemble matrix - Z : Ensemble matrix of principal components - Rp : Reduced order Observation error matrix - indexTrain: index of training ensemble - indexTest: index of test ensemble - nTest : number of members in the training ensemble - nTrain . number of members in the test ensemble - foldIndex: integer specifying which "cv-fold" we are considering - - OUTPUT: - cvErr : UPDATED MATRIX OF PRESS VALUES - -*/ - -static void cv_enkf_get_cv_error_prin_comp( cv_enkf_data_type * cv_data , - matrix_type * cvErr , - const matrix_type * A , - const int * indexTest, - const int * indexTrain , - const int nTest , - const int nTrain , - const int foldIndex, - const int maxP) { - /* - We need to predict ATest(p), for p = 1,...,nens -1, based on the estimated regression model: - AHatTest(p) = A[:,indexTrain] * Z[1:p,indexTrain]'* inv( Z[1:p,indexTrain] * Z[1:p,indexTrain]' + (nens-1) * Rp[1:p,1:p] ) * Z[1:p,indexTest]; - */ - - - const int nx = matrix_get_rows( A ); - matrix_type * AHat = matrix_alloc(nx , nTest ); - matrix_type * ATrain = matrix_alloc( nx , nTrain ); - - int p,i,j; - - - /* Copy elements*/ - for (i = 0; i < nx; i++) - for (j = 0; j < nTrain; j++) - matrix_iset(ATrain , i , j , matrix_iget( A , i , indexTrain[j])); - - - for (p = 0; p < maxP; p++) { - matrix_type * ZpTrain = matrix_alloc( p + 1, nTrain ); - matrix_type *SigDp = matrix_alloc( p + 1 , p + 1); - - - for (i = 0; i <= p ; i++) - for (j = 0; j < nTrain; j++) - matrix_iset(ZpTrain , i , j , matrix_iget(cv_data->Z , i , indexTrain[j])); - - /* SigDp = ZpTrain * ZpTrain' */ - matrix_dgemm( SigDp , ZpTrain , ZpTrain, false , true , 1.0, 0.0); - - /* SigDp += (nTrain - 1) * Rp */ - for(i = 0; i <= p; i++) - for( j = 0; j <= p; j++) - matrix_iadd( SigDp , i , j , (nTrain - 1) * matrix_iget(cv_data->Rp, i, j)); - - - /* Invert the covariance matrix for the principal components */ - { - int inv_ok = matrix_inv( SigDp ); - if ( inv_ok != 0 ) - util_abort("%s: inversion of covariance matrix for the principal components failed for subspace dimension p = %d\n - aborting \n",__func__,p+1); - } - - - { - matrix_type * W = matrix_alloc(p + 1 , nTest ); - matrix_type * W2 = matrix_alloc(nTrain , nTest ); - - /* W = inv(SigDp) * ZTest */ - for (i = 0; i <= p; i++) { - for (j = 0; j < nTest; j++) { - double ksum = 0.0; - for (int k = 0; k <= p; k++) - ksum += matrix_iget(SigDp , i , k) * matrix_iget(cv_data->Z , k , indexTest[j]); - - matrix_iset(W , i , j , ksum); - } - } - - /* W2 = ZpTrain' * W */ - matrix_dgemm( W2 , ZpTrain , W , true , false , 1.0 , 0.0); - - /* Estimate the state-vector */ - matrix_matmul( AHat , ATrain , W2 ); - - matrix_free( W2 ); - matrix_free( W ); - } - - - /*Compute Press Statistic: */ - { - double R2Sum = 0; - - for (i = 0; i < nx; i++) { - for (j = 0; j < nTest; j++) { - double tmp = matrix_iget(A , i , indexTest[j]) - matrix_iget(AHat , i , j); - R2Sum += tmp * tmp; - } - } - matrix_iset( cvErr , p , foldIndex , R2Sum ); - } - - - - matrix_free( ZpTrain ); - matrix_free( SigDp ); - } /*end for p */ - - matrix_free( AHat ); - matrix_free( ATrain ); -} - - - - - - -int cv_enkf_get_optimal_numb_comp(cv_enkf_data_type * cv_data , - const matrix_type * cvErr , - const int maxP ) { - - - double * cvMean = util_calloc( maxP , sizeof * cvMean ); - double * cvStd = util_calloc( maxP , sizeof * cvStd ); - int optP; - - { - for (int p = 0; p < maxP; p++ ){ - double err_sum = 0; - for (int folds = 0; folds < cv_data->nfolds; folds++ ) - err_sum += matrix_iget( cvErr , p, folds ); - - cvMean[p] = err_sum / cv_data->nfolds; - } - - for ( int p = 0; p < maxP; p++){ - double err_sum2 = 0; - for ( int folds = 0; folds < cv_data->nfolds; folds++) - err_sum2 += pow( matrix_iget( cvErr , p , folds ) - cvMean[p] , 2); - - cvStd[p] = sqrt( err_sum2 / (cv_data->nfolds - 1) ); - } - } - - { - double minErr = cvMean[0]; - int i; - optP = 1; - - printf("PRESS:\n"); - printf("%f\n",cvMean[0]); - for (i = 1; i < maxP; i++) { - printf("%f\n",cvMean[i]); - if ((cvMean[i] < minErr) && (cvMean[i] > 0.0)) { - minErr = cvMean[i]; - optP = i+1; - } - } - - - - - if (cv_data->penalised_press) { - for ( i = 0; i < optP; i++){ - if( cvMean[i] - cvStd[i] <= minErr ){ - optP = i+1; - break; - } - } - } - } - - free( cvStd ); - free( cvMean ); - return optP; -} - - - - - - -/* Function that performs cross-validation to find the optimal subspace dimension, */ - - -static int get_optimal_principal_components( cv_enkf_data_type * cv_data , - const matrix_type * A) { - - - const int nrens = matrix_get_columns( cv_data->Z ); - const int nrmin = matrix_get_rows( cv_data->Z ); - - - - matrix_type * cvError; - int * randperms = util_calloc( nrens , sizeof * randperms); - - int maxP = nrmin; - int optP; - - - /* We only want to search the non-zero eigenvalues */ - for (int i = 0; i < nrmin; i++) { - if (matrix_iget(cv_data->Z,i,1) == 0.0) { - maxP = i; - break; - } - } - - if (maxP > nrmin) - maxP = nrmin - 1; // <- Change by Joakim; using nrmin here will load to out - // bounds access oc cv_data->Z at line 460. - - - - - if ( nrens < cv_data->nfolds ) - util_abort("%s: number of ensemble members %d need to be larger than the number of cv-folds - aborting \n", - __func__, - nrens, - cv_data->nfolds); - - for (int i=0; i < nrens; i++) - randperms[i] = i; - - rng_shuffle_int( cv_data->rng , randperms , nrens ); - - cvError = matrix_alloc( maxP , cv_data->nfolds ); - { - int ntest, ntrain, k,j,i; - int * indexTest = util_calloc( nrens , sizeof * indexTest ); - int * indexTrain = util_calloc( nrens , sizeof * indexTrain ); - for (i = 0; i < cv_data->nfolds; i++) { - ntest = 0; - ntrain = 0; - k = i; - /*extract members for the training and test ensembles */ - for (j = 0; j < nrens; j++) { - if (j == k) { - indexTest[ntest] = randperms[j]; - k += cv_data->nfolds; - ntest++; - } else { - indexTrain[ntrain] = randperms[j]; - ntrain++; - } - } - - /*Perform CV for each subspace dimension p */ - cv_enkf_get_cv_error_prin_comp( cv_data , cvError , A , indexTest , indexTrain, ntest, ntrain , i , maxP); - } - free( indexTest ); - free( indexTrain ); - } - - - /* find optimal truncation value for the cv-scheme */ - optP = cv_enkf_get_optimal_numb_comp( cv_data , cvError , maxP); - - matrix_free( cvError ); - free( randperms ); - return optP; -} - - - -/*NB! HERE WE COUNT optP from 0,1,2,... */ -static void getW_prin_comp(cv_enkf_data_type * cv_data , matrix_type *W , const int optP) { - - int i, j; - double tmp2; - int nrens = matrix_get_columns( cv_data->Z ); - - /* Finally, compute W = Z(1:p,:)' * inv(Z(1:p,:) * Z(1:p,:)' + (n -1) * Rp) */ - matrix_type *Zp = matrix_alloc( optP, nrens ); - matrix_type *SigZp = matrix_alloc( optP ,optP); - - // This loop will fail with i to large whcn accessing cv_data->Z - // if we do not limit maxP to nrmin - 1? - for (i = 0; i < optP ; i++) - for (j = 0; j < nrens; j++) - matrix_iset_safe(Zp , i , j , matrix_iget_safe(cv_data->Z , i ,j)); - - // Matrix copy_block should be used in stead of the double (i,j) loop; - // however that failed because the cv_data->Z matrix had one row too few? - // matrix_copy_block( Zp , 0 , 0 , optP , nrens , cv_data->Z , 0 , 0 ); - - /*Compute SigZp = Zp * Zp' */ - matrix_dgemm( SigZp , Zp , Zp, false , true , 1.0, 0.0); - - /*Add (ntrain-1) * Rp*/ - for(i = 0; i < optP; i++) { - for( j = 0; j < optP; j++) { - tmp2 = matrix_iget(SigZp , i , j) + (nrens - 1) * matrix_iget(cv_data->Rp, i, j); - matrix_iset( SigZp , i , j , tmp2 ); - } - } - - - /* Invert the covariance matrix for the principal components */ - int inv_ok = matrix_inv( SigZp ); - - /*Check if the inversion went ok */ - if ( inv_ok != 0 ) - util_abort("%s: inversion of covariance matrix for the principal components failed for subspace dimension p = %d\n - aborting \n",__func__,optP); - - - - - /*Compute W = Zp' * inv(SigZp) */ - matrix_dgemm( W , Zp , SigZp , true , false , 1.0 , 0.0); - - matrix_free( Zp ); - matrix_free( SigZp ); -} - - - - -void cv_enkf_initX(void * module_data , - matrix_type * X , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D) { - - - cv_enkf_data_type * cv_data = cv_enkf_data_safe_cast( module_data ); - printf("Running CV\n"); - { - int optP; - int ens_size = matrix_get_columns( S ); - - /* Get the optimal number of principal components - where p is found minimizing the PRESS statistic */ - - { - matrix_type * workA = matrix_alloc_copy( A ); - matrix_subtract_row_mean( workA ); - optP = get_optimal_principal_components(cv_data , workA ); - printf("Optimal subspace dimension found %d\n",optP); - matrix_free( workA ); - } - - { - matrix_type * W = matrix_alloc(ens_size , optP); - - /* Compute W = Z(1:p,:)' * inv(Z(1:p,:) * Z(1:p,:)' + (ens_size-1) * Rp(1:p,1:p))*/ - getW_prin_comp( cv_data , W , optP); - - /*Compute the actual X5 matrix: */ - /*Compute X5 = W * Dp (The hard way) */ - for( int i = 0; i < ens_size; i++) { - for( int j = 0; j < ens_size; j++) { - double tmp = 0.0; - - for( int k = 0; k < optP; k++) - tmp += matrix_iget( W , i , k) * matrix_iget( cv_data->Dp , k , j); - - matrix_iset(X , i , j ,tmp); - } - matrix_iadd( X , i , i , 1.0); /* X5 = I + X5 */ - } - - matrix_free( W ); - } - } -} - - - -void cv_enkf_complete_update( void * arg ) { - cv_enkf_data_type * cv_data = cv_enkf_data_safe_cast( arg ); - { - matrix_free( cv_data->Z ); - matrix_free( cv_data->Rp ); - matrix_free( cv_data->Dp ); - - cv_data->Z = NULL; - cv_data->Rp = NULL; - cv_data->Dp = NULL; - } -} - - - -bool cv_enkf_set_double( void * arg , const char * var_name , double value) { - cv_enkf_data_type * module_data = cv_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , ENKF_TRUNCATION_KEY_) == 0) - cv_enkf_set_truncation( module_data , value ); - else - name_recognized = false; - - return name_recognized; - } -} - - -bool cv_enkf_set_int( void * arg , const char * var_name , int value) { - cv_enkf_data_type * module_data = cv_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , ENKF_NCOMP_KEY_) == 0) - cv_enkf_set_subspace_dimension( module_data , value ); - else if (strcmp( var_name , NFOLDS_KEY) == 0) - cv_enkf_set_nfolds( module_data , value); - else - name_recognized = false; - - return name_recognized; - } -} - - -bool cv_enkf_set_bool( void * arg , const char * var_name , bool value) { - cv_enkf_data_type * module_data = cv_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - if (strcmp( var_name , CV_PEN_PRESS_KEY) == 0) - cv_enkf_set_pen_press( module_data , value ); - else - name_recognized = false; - - return name_recognized; - } -} - - -long cv_enkf_get_options( void * arg , long flag) { - cv_enkf_data_type * cv_data = cv_enkf_data_safe_cast( arg ); - { - return cv_data->option_flags; - } -} - -bool cv_enkf_has_var( const void * arg, const char * var_name) { - { - if (strcmp(var_name , ENKF_NCOMP_KEY_) == 0) - return true; - else if (strcmp(var_name , ENKF_TRUNCATION_KEY_) == 0) - return true; - else if (strcmp(var_name , NFOLDS_KEY) == 0) - return true; - else if (strcmp(var_name , CV_PEN_PRESS_KEY) == 0) - return true; - else - return false; - } -} - -double cv_enkf_get_double( const void * arg, const char * var_name) { - const cv_enkf_data_type * module_data = cv_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , ENKF_TRUNCATION_KEY_) == 0) - return module_data->truncation; - else - return -1; - } -} - -int cv_enkf_get_int( const void * arg, const char * var_name) { - const cv_enkf_data_type * module_data = cv_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , ENKF_NCOMP_KEY_) == 0) - return module_data->subspace_dimension; - else if (strcmp(var_name , NFOLDS_KEY) == 0) - return module_data->nfolds; - else - return -1; - } -} - -bool cv_enkf_get_bool( const void * arg, const char * var_name) { - const cv_enkf_data_type * module_data = cv_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , CV_PEN_PRESS_KEY) == 0) - return module_data->penalised_press; - else - return false; - } -} - - -#ifdef INTERNAL_LINK -#define LINK_NAME CV_ENKF -#else -#define LINK_NAME EXTERNAL_MODULE_SYMBOL -#endif - - -analysis_table_type LINK_NAME = { - .name = "CV_ENKF", - .alloc = cv_enkf_data_alloc, - .freef = cv_enkf_data_free, - .set_int = cv_enkf_set_int , - .set_double = cv_enkf_set_double , - .set_bool = cv_enkf_set_bool , - .set_string = NULL , - .get_options = cv_enkf_get_options , - .initX = cv_enkf_initX , - .updateA = NULL, - .init_update = cv_enkf_init_update , - .complete_update = cv_enkf_complete_update , - .has_var = cv_enkf_has_var, - .get_int = cv_enkf_get_int, - .get_double = cv_enkf_get_double, - .get_bool = cv_enkf_get_bool, - .get_ptr = NULL, -}; diff --git a/ThirdParty/Ert/libanalysis/src/enkf_linalg.c b/ThirdParty/Ert/libanalysis/src/enkf_linalg.c deleted file mode 100644 index b3caf21637..0000000000 --- a/ThirdParty/Ert/libanalysis/src/enkf_linalg.c +++ /dev/null @@ -1,860 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include - -#include - -void enkf_linalg_genX3(matrix_type * X3 , const matrix_type * W , const matrix_type * D , const double * eig) { - const int nrobs = matrix_get_rows( D ); - const int nrens = matrix_get_columns( D ); - const int nrmin = util_int_min( nrobs , nrens ); - int i,j; - matrix_type * X1 = matrix_alloc(nrmin , nrobs); - matrix_type * X2 = matrix_alloc(nrmin , nrens); - - /* X1 = (I + Lambda1)^(-1) * W'*/ - for (i=0; i < nrmin; i++) - for (j=0; j < nrobs; j++) - matrix_iset(X1 , i , j , eig[i] * matrix_iget(W , j , i)); - - matrix_matmul(X2 , X1 , D); /* X2 = X1 * D (Eq. 14.31) */ - matrix_matmul(X3 , W , X2); /* X3 = W * X2 = X1 * X2 (Eq. 14.31) */ - - matrix_free( X1 ); - matrix_free( X2 ); -} - - -void enkf_linalg_genX2(matrix_type * X2 , const matrix_type * S , const matrix_type * W , const double * eig) { - const int nrens = matrix_get_columns( S ); - const int idim = matrix_get_rows( X2 ); - matrix_dgemm(X2 , W , S , true , false , 1.0 , 0.0); - { - int i,j; - for (j=0; j < nrens; j++) - for (i=0; i < idim; i++) - matrix_imul(X2 , i,j , sqrt(eig[i])); - } -} - - - -/** - This function calculates the svd of the input matrix S. The number - of significant singular values to retain can either be forced to a - fixed number, or a cutoff on small singular values can be - used. This behaviour is regulated by the @ncomp and @truncation - parameters: - - ncomp > 0 , truncation < 0: Use ncomp parameters. - ncomp < 0 , truncation > 0: Truncate at level 'truncation'. - - The singular values are returned in the inv_sig0 vector; the values - we retain are inverted and the remaining elements in are explicitly - set to zero. - - The left-hand singular vectors are returned in the matrix - U0. Depending on the value of the flag @store_V0T the right hand - singular vectors are stored in the V0T matrix, or just - discarded. If you do not intend to use the right hand vectors at - all, i.e. store_V0T == DGESVD_NONE, the V0T matrix will not be - accessed. - - The input S matrix should have been shifted to zero mean prior to - calling this function. -*/ - - - -/*This function is similar to enkf_linalg_svdS but it returns the eigen values without its inverse and also give the matrices truncated U VT and Sig0*/ - -// Trunc.SVD(S) = U0 * Sig0 * V0T -int enkf_linalg_svd_truncation(const matrix_type * S , - double truncation , - int ncomp , - dgesvd_vector_enum store_V0T , - double * sig0, - matrix_type * U0 , - matrix_type * V0T) { - - int num_significant = -1; - int nrows = matrix_get_rows(S); - int ncolumns= matrix_get_columns(S); - - if (((truncation > 0) && (ncomp < 0)) || - ((truncation < 0) && (ncomp > 0))) { - - int num_singular_values = util_int_min( matrix_get_rows( S ) , matrix_get_columns( S )); - { - matrix_type * workS = matrix_alloc_copy( S ); - matrix_dgesvd(DGESVD_MIN_RETURN , store_V0T , workS , sig0 , U0 , V0T); - matrix_free( workS ); - } - int i; - - if (ncomp > 0) - num_significant = ncomp; - else { - double total_sigma2 = 0; - for (i=0; i < num_singular_values; i++) - total_sigma2 += sig0[i]; - - /* - Determine the number of singular values by enforcing that - less than a fraction @truncation of the total variance be - accounted for. - */ - num_significant = 0; - { - double running_sigma2 = 0; - for (i=0; i < num_singular_values; i++) { - if (running_sigma2 / total_sigma2 < truncation) { /* Include one more singular value ? */ - num_significant++; - running_sigma2 += sig0[i]; - } else - break; - } - } - } - if (num_significant > 0) { - matrix_resize(U0 , nrows , num_significant , true); - matrix_resize(V0T , num_significant , ncolumns , true); - } else - util_abort("%s: zero significant singular values\n",__func__); - } - else - util_abort("%s: truncation:%g ncomp:%d - invalid ambigous input.\n",__func__ , truncation , ncomp ); - - return num_significant; -} - - -static int enkf_linalg_num_significant(int num_singular_values , const double * sig0 , double truncation ) { - int num_significant = 0; - double total_sigma2 = 0; - for (int i=0; i < num_singular_values; i++) - total_sigma2 += sig0[i] * sig0[i]; - - /* - Determine the number of singular values by enforcing that - less than a fraction @truncation of the total variance be - accounted for. - */ - { - double running_sigma2 = 0; - for (int i=0; i < num_singular_values; i++) { - if (running_sigma2 / total_sigma2 < truncation) { /* Include one more singular value ? */ - num_significant++; - running_sigma2 += sig0[i] * sig0[i]; - } else - break; - } - } - - return num_significant; -} - - -int enkf_linalg_svdS(const matrix_type * S , - double truncation , - int ncomp , - dgesvd_vector_enum store_V0T , - double * inv_sig0, - matrix_type * U0 , - matrix_type * V0T) { - - double * sig0 = inv_sig0; - int num_significant = 0; - - - if (((truncation > 0) && (ncomp < 0)) || - ((truncation < 0) && (ncomp > 0))) { - int num_singular_values = util_int_min( matrix_get_rows( S ) , matrix_get_columns( S )); - { - matrix_type * workS = matrix_alloc_copy( S ); - matrix_dgesvd(DGESVD_MIN_RETURN , store_V0T , workS , sig0 , U0 , V0T); - matrix_free( workS ); - } - - if (ncomp > 0) - num_significant = ncomp; - else - num_significant = enkf_linalg_num_significant( num_singular_values , sig0 , truncation ); - - { - int i; - /* Inverting the significant singular values */ - for (i = 0; i < num_significant; i++) - inv_sig0[i] = 1.0 / sig0[i]; - - /* Explicitly setting the insignificant singular values to zero. */ - for (i=num_significant; i < num_singular_values; i++) - inv_sig0[i] = 0; - } - } else - - util_abort("%s: truncation:%g ncomp:%d - invalid ambigous input.\n",__func__ , truncation , ncomp ); - - return num_significant; -} - - -int enkf_linalg_num_PC(const matrix_type * S , double truncation ) { - int num_singular_values = util_int_min( matrix_get_rows( S ) , matrix_get_columns( S )); - int num_significant; - double * sig0 = util_calloc( num_singular_values , sizeof * sig0); - - { - matrix_type * workS = matrix_alloc_copy( S ); - matrix_dgesvd(DGESVD_NONE , DGESVD_NONE , workS , sig0 , NULL , NULL); - matrix_free( workS ); - } - - num_significant = enkf_linalg_num_significant( num_singular_values , sig0 , truncation ); - free( sig0 ); - return num_significant; -} - - - -/* -**************************************************************************************************** - Routine computes X1 and eig corresponding to Eqs 14.54-14.55 - Geir Evensen -*/ -void enkf_linalg_lowrankE(const matrix_type * S , /* (nrobs x nrens) */ - const matrix_type * E , /* (nrobs x nrens) */ - matrix_type * W , /* (nrobs x nrmin) Corresponding to X1 from Eqs. 14.54-14.55 */ - double * eig , /* (nrmin) Corresponding to 1 / (1 + Lambda1^2) (14.54) */ - double truncation , - int ncomp) { - - - const int nrobs = matrix_get_rows( S ); - const int nrens = matrix_get_columns( S ); - const int nrmin = util_int_min( nrobs , nrens ); - - matrix_type * U0 = matrix_alloc( nrobs , nrmin ); - double * inv_sig0 = util_calloc( nrmin , sizeof * inv_sig0); - matrix_type * X0 = matrix_alloc( nrmin , nrens ); - - - matrix_type * U1 = matrix_alloc( nrmin , nrmin ); - double * sig1 = util_calloc( nrmin , sizeof * sig1); - - int i ,j; - - -/* Compute SVD of S=HA` -> U0, invsig0=sig0^(-1) */ - enkf_linalg_svdS(S , truncation , ncomp , DGESVD_NONE , inv_sig0, U0 , NULL); - -/* X0(nrmin x nrens) = Sigma0^(+) * U0'* E (14.51) */ - matrix_dgemm(X0 , U0 , E , true , false , 1.0 , 0.0); /* X0 = U0^T * E (14.51) */ - - -/* Multiply X0 with sig0^(-1) from left X0 = S^(-1) * X0 */ - for (j=0; j < matrix_get_columns( X0 ) ; j++) - for (i=0; i < matrix_get_rows( X0 ); i++) - matrix_imul(X0 , i , j , inv_sig0[j]); - - -/* Compute SVD of X0-> U1*eig*V1 14.52 */ - matrix_dgesvd(DGESVD_MIN_RETURN , DGESVD_NONE, X0 , sig1, U1 , NULL); - - /* Lambda1 = 1/(I + Lambda^2) in 14.56 */ - for (i=0; i < nrmin; i++) - eig[i] = 1.0 / (1.0 + sig1[i]*sig1[i]); - - -/* Compute sig0^+ U1 (14:55) */ - for (j=0; j < nrmin; j++) - for (i=0; i < nrmin; i++) - matrix_imul(U1 , i , j , inv_sig0[i]); - - -/* Compute X1 = W = U0 * (U1=sig0^+ U1) = U0 * Sigma0^(+') * U1 (14:55) */ - matrix_matmul(W , U0 , U1); - - - matrix_free( X0 ); - matrix_free( U0 ); - util_safe_free( inv_sig0 ); - - matrix_free( U1 ); - util_safe_free( sig1 ); - -} - - - - -void enkf_linalg_Cee(matrix_type * B, int nrens , const matrix_type * R , const matrix_type * U0 , const double * inv_sig0) { - const int nrmin = matrix_get_rows( B ); - { - matrix_type * X0 = matrix_alloc( nrmin , matrix_get_rows( R )); - matrix_dgemm(X0 , U0 , R , true , false , 1.0 , 0.0); /* X0 = U0^T * R */ - matrix_dgemm(B , X0 , U0 , false , false , 1.0 , 0.0); /* B = X0 * U0 */ - matrix_free( X0 ); - } - - { - int i ,j; - - /* Funny code ?? - Multiply B with S^(-1)from left and right - BHat = S^(-1) * B * S^(-1) - */ - for (j=0; j < matrix_get_columns( B ) ; j++) - for (i=0; i < matrix_get_rows( B ); i++) - matrix_imul(B , i , j , inv_sig0[i]); - - for (j=0; j < matrix_get_columns( B ) ; j++) - for (i=0; i < matrix_get_rows( B ); i++) - matrix_imul(B , i , j , inv_sig0[j]); - } - - matrix_scale(B , nrens - 1.0); -} - - - - -void enkf_linalg_lowrankCinv__(const matrix_type * S , - const matrix_type * R , - matrix_type * V0T , - matrix_type * Z, - double * eig , - matrix_type * U0, - double truncation, - int ncomp) { - - const int nrobs = matrix_get_rows( S ); - const int nrens = matrix_get_columns( S ); - const int nrmin = util_int_min( nrobs , nrens ); - - double * inv_sig0 = util_calloc( nrmin , sizeof * inv_sig0); - - if (V0T != NULL) - enkf_linalg_svdS(S , truncation , ncomp , DGESVD_MIN_RETURN , inv_sig0 , U0 , V0T ); - else - enkf_linalg_svdS(S , truncation , ncomp , DGESVD_NONE , inv_sig0, U0 , NULL); - - { - matrix_type * B = matrix_alloc( nrmin , nrmin ); - enkf_linalg_Cee( B , nrens , R , U0 , inv_sig0); /* B = Xo = (N-1) * Sigma0^(+) * U0'* Cee * U0 * Sigma0^(+') (14.26)*/ - matrix_dgesvd(DGESVD_MIN_RETURN , DGESVD_NONE, B , eig, Z , NULL); - matrix_free( B ); - } - - { - int i,j; - /* Lambda1 = (I + Lambda)^(-1) */ - - for (i=0; i < nrmin; i++) - eig[i] = 1.0 / (1 + eig[i]); - - for (j=0; j < nrmin; j++) - for (i=0; i < nrmin; i++) - matrix_imul(Z , i , j , inv_sig0[i]); /* Z2 = Sigma0^(+) * Z; */ - } - util_safe_free( inv_sig0 ); -} - - -void enkf_linalg_lowrankCinv(const matrix_type * S , - const matrix_type * R , - matrix_type * W , /* Corresponding to X1 from Eq. 14.29 */ - double * eig , /* Corresponding to 1 / (1 + Lambda_1) (14.29) */ - double truncation , - int ncomp) { - - const int nrobs = matrix_get_rows( S ); - const int nrens = matrix_get_columns( S ); - const int nrmin = util_int_min( nrobs , nrens ); - - matrix_type * U0 = matrix_alloc( nrobs , nrmin ); - matrix_type * Z = matrix_alloc( nrmin , nrmin ); - - enkf_linalg_lowrankCinv__( S , R , NULL , Z , eig , U0 , truncation , ncomp); - matrix_matmul(W , U0 , Z); /* X1 = W = U0 * Z2 = U0 * Sigma0^(+') * Z */ - - matrix_free( U0 ); - matrix_free( Z ); -} - - -void enkf_linalg_meanX5(const matrix_type * S , - const matrix_type * W , - const double * eig , - const matrix_type * dObs, - matrix_type * X5) { - - - const int nrens = matrix_get_columns( S ); - const int nrobs = matrix_get_rows( S ); - const int nrmin = util_int_min( nrobs , nrens ); - double * work = util_calloc( (2 * nrmin + nrobs + nrens) , sizeof * work ); - matrix_type * innov = enkf_linalg_alloc_innov( dObs , S ); - { - double * y1 = &work[0]; - double * y2 = &work[nrmin]; - double * y3 = &work[2*nrmin]; - double * y4 = &work[2*nrmin + nrobs]; - - if (nrobs == 1) { - /* Is this special casing necessary ??? */ - y1[0] = matrix_iget(W , 0,0) * matrix_iget( innov , 0 , 0); - y2[0] = eig[0] * y1[0]; - y3[0] = matrix_iget(W , 0, 0) *y2[0]; - for (int iens = 0; iens < nrens; iens++) - y4[iens] = y3[0] * matrix_iget(S , 0, iens); - } else { - matrix_dgemv(W , matrix_get_data( innov ) , y1 , true , 1.0, 0.0); /* y1 = Trans(W) * innov */ - for (int i= 0; i < nrmin; i++) - y2[i] = eig[i] * y1[i]; /* y2 = eig * y1 */ - matrix_dgemv(W , y2 , y3 , false , 1.0 , 0.0); /* y3 = W * y2; */ - matrix_dgemv(S , y3 , y4 , true , 1.0 , 0.0); /* y4 = Trans(S) * y3 */ - } - - for (int iens = 0; iens < nrens; iens++) - matrix_set_column(X5 , y4 , iens ); - - matrix_shift(X5 , 1.0/nrens); - } - free( work ); - matrix_free( innov ); -} - - - -void enkf_linalg_X5sqrt(matrix_type * X2 , matrix_type * X5 , const matrix_type * randrot, int nrobs) { - const int nrens = matrix_get_columns( X5 ); - const int nrmin = util_int_min( nrobs , nrens ); - matrix_type * VT = matrix_alloc( nrens , nrens ); - double * sig = util_calloc( nrmin , sizeof * sig ); - double * isig = util_calloc( nrmin , sizeof * sig ); - - matrix_dgesvd(DGESVD_NONE , DGESVD_ALL , X2 , sig , NULL , VT); - { - matrix_type * X3 = matrix_alloc( nrens , nrens ); - matrix_type * X33 = matrix_alloc( nrens , nrens ); - matrix_type * X4 = matrix_alloc( nrens , nrens ); - matrix_type * IenN = matrix_alloc( nrens , nrens ); - int i,j; - for (i = 0; i < nrmin; i++) - isig[i] = sqrt( util_double_max( 1.0 - sig[i]*sig[i] ,0.0)); - - for (j = 0; j < nrens; j++) - for (i = 0; i < nrens; i++) - matrix_iset(X3 , i , j , matrix_iget(VT , j , i)); - - for (j=0; j< nrmin; j++) - matrix_scale_column(X3 , j , isig[j]); - - matrix_dgemm(X33 , X3 , VT , false , false , 1.0 , 0.0); /* X33 = X3 * VT */ - if (randrot != NULL) - matrix_dgemm(X4 , X33 , randrot , false, false , 1.0 , 0.0); /* X4 = X33 * Randrot */ - else - matrix_assign(X4 , X33); - - matrix_set(IenN , -1.0/ nrens); - for (i = 0; i < nrens; i++) - matrix_iadd(IenN , i , i , 1.0); - - matrix_dgemm(X5 , IenN , X4 , false , false , 1.0 , 1.0); /* X5 = IenN * X4 + X5 */ - - matrix_free( X3 ); - matrix_free( X33 ); - matrix_free( X4 ); - matrix_free( IenN ); - } - - free(sig); - free(isig); - matrix_free( VT ); -} - - -matrix_type * enkf_linalg_alloc_innov( const matrix_type * dObs , const matrix_type * S) { - matrix_type * innov = matrix_alloc_copy( dObs ); - - for (int iobs =0; iobs < matrix_get_row_sum( dObs , iobs); iobs++) - matrix_isub( innov , iobs , 0 , matrix_get_row_sum( S , iobs )); - - return innov; -} - - -void enkf_linalg_init_stdX( matrix_type * X , const matrix_type * S , const matrix_type * D , - const matrix_type * W , const double * eig , bool bootstrap) { - - int nrobs = matrix_get_rows( W ); - int ens_size = matrix_get_rows( X ); - - matrix_type * X3 = matrix_alloc(nrobs , ens_size); - enkf_linalg_genX3(X3 , W , D , eig ); /* X2 = diag(eig) * W' * D (Eq. 14.31, Evensen (2007)) */ - /* X3 = W * X2 = X1 * X2 (Eq. 14.31, Evensen (2007)) */ - - matrix_dgemm( X , S , X3 , true , false , 1.0 , 0.0); /* X = S' * X3 */ - if (!bootstrap) { - for (int i = 0; i < ens_size ; i++) - matrix_iadd( X , i , i , 1.0); /*X = I + X */ - } - - matrix_free( X3 ); -} - - - -void enkf_linalg_init_sqrtX(matrix_type * X5 , - const matrix_type * S , - const matrix_type * randrot , - const matrix_type * innov , - const matrix_type * W , - const double * eig , - bool bootstrap) { - - const int nrobs = matrix_get_rows( S ); - const int nrens = matrix_get_columns( S ); - const int nrmin = util_int_min( nrobs , nrens ); - - matrix_type * X2 = matrix_alloc(nrmin , nrens); - - if (bootstrap) - util_exit("%s: Sorry bootstrap support not fully implemented for SQRT scheme\n",__func__); - - enkf_linalg_meanX5( S , W , eig , innov , X5 ); - enkf_linalg_genX2(X2 , S , W , eig); - enkf_linalg_X5sqrt(X2 , X5 , randrot , nrobs); - - matrix_free( X2 ); -} - -/*****************************************************************/ - - - - - -/** - This routine generates a real orthogonal random matrix. - The algorithm is the one by - Francesco Mezzadri (2007), How to generate random matrices from the classical - compact groups, Notices of the AMS, Vol. 54, pp 592-604. - 1. First a matrix with independent random normal numbers are simulated. - 2. Then the QR decomposition is computed, and Q will then be a random orthogonal matrix. - 3. The diagonal elements of R are extracted and we construct the diagonal matrix X(j,j)=R(j,j)/|R(j,j)| - 4. An updated Q'=Q X is computed, and this is now a random orthogonal matrix with a Haar measure. - - The implementation is a plain reimplementation/copy of the old m_randrot.f90 function. -*/ - - - -/** - NB: This should rather use the implementation in m_mean_preserving_rotation.f90. -*/ - -void enkf_linalg_set_randrot( matrix_type * Q , rng_type * rng) { - int ens_size = matrix_get_rows( Q ); - double * tau = util_calloc( ens_size , sizeof * tau ); - int * sign = util_calloc( ens_size , sizeof * sign); - - for (int i = 0; i < ens_size; i++) - for (int j = 0; j < ens_size; j++) - matrix_iset(Q , i , j , rng_std_normal( rng )); - - matrix_dgeqrf( Q , tau ); /* QR factorization */ - for (int i=0; i < ens_size; i++) { - double Qii = matrix_iget( Q , i,i); - sign[i] = Qii / abs(Qii); - } - - matrix_dorgqr( Q , tau , ens_size ); - for (int i = 0; i < ens_size; i++) { - if (sign[i] < 0) - matrix_scale_column( Q , i , -1 ); - } - - free( sign ); - free( tau ); -} - - - - -/** - Generates the mean preserving random rotation for the EnKF SQRT algorithm - using the algorithm from Sakov 2006-07. I.e, generate rotation Up such that - Up*Up^T=I and Up*1=1 (all rows have sum = 1) see eq 17. - From eq 18, Up=B * Upb * B^T - B is a random orthonormal basis with the elements in the first column equals 1/sqrt(nrens) - - Upb = | 1 0 | - | 0 U | - - where U is an arbitrary orthonormal matrix of dim nrens-1 x nrens-1 (eq. 19) -*/ - -matrix_type * enkf_linalg_alloc_mp_randrot(int ens_size , rng_type * rng) { - matrix_type * Up = matrix_alloc( ens_size , ens_size ); /* The return value. */ - { - matrix_type * B = matrix_alloc( ens_size , ens_size ); - matrix_type * Upb = matrix_alloc( ens_size , ens_size ); - matrix_type * U = matrix_alloc_shared(Upb , 1 , 1 , ens_size - 1, ens_size - 1); - - - { - int k,j; - matrix_type * R = matrix_alloc( ens_size , ens_size ); - matrix_random_init( B , rng); /* B is filled up with U(0,1) numbers. */ - matrix_set_const_column( B , 1.0 / sqrt( ens_size ) , 0 ); - - /* modified_gram_schmidt is used to create the orthonormal basis in B.*/ - for (k=0; k < ens_size; k++) { - double Rkk = sqrt( matrix_column_column_dot_product( B , k , B , k)); - matrix_iset(R , k , k , Rkk); - matrix_scale_column(B , k , 1.0/Rkk); - for (j=k+1; j < ens_size; j++) { - double Rkj = matrix_column_column_dot_product(B , k , B , j); - matrix_iset(R , k , j , Rkj); - { - int i; - for (i=0; i < ens_size; i++) { - double Bij = matrix_iget(B , i , j); - double Bik = matrix_iget(B , i , k); - matrix_iset(B , i , j , Bij - Bik * Rkj); - } - } - } - } - matrix_free( R ); - } - - enkf_linalg_set_randrot( U , rng ); - matrix_iset( Upb , 0 , 0 , 1); - - - { - matrix_type * Q = matrix_alloc( ens_size , ens_size ); - matrix_dgemm( Q , B , Upb , false , false , 1, 0); /* Q = B * Ubp */ - matrix_dgemm( Up , Q , B , false , true , 1, 0); /* Up = Q * T(B) */ - matrix_free( Q ); - } - - matrix_free( B ); - matrix_free( Upb ); - matrix_free( U ); - } - - return Up; -} - - -/*****************************************************************/ - -/** - Checking that the sum through one row in the X matrix equals - @target_sum. @target_sum will be 1 normally, and zero if we are doing - bootstrap. -*/ - -void enkf_linalg_checkX(const matrix_type * X , bool bootstrap) { - matrix_assert_finite( X ); - { - int target_sum; - if (bootstrap) - target_sum = 0; - else - target_sum = 1; - - for (int icol = 0; icol < matrix_get_columns( X ); icol++) { - double col_sum = matrix_get_column_sum(X , icol); - if (fabs(col_sum - target_sum) > 0.0001) - util_abort("%s: something is seriously broken. col:%d col_sum = %g != %g - ABORTING\n",__func__ , icol , col_sum , target_sum); - } - } -} - - -/*****************************************************************/ - -int enkf_linalg_get_PC( const matrix_type * S0, - const matrix_type * dObs , - double truncation, - int ncomp, - matrix_type * PC, - matrix_type * PC_obs, - double_vector_type * singular_values) { - - const int nrobs = matrix_get_rows( S0 ); - const int nrens = matrix_get_columns( S0 ); - const int nrmin = util_int_min( nrobs , nrens ); - - matrix_type * U0 = matrix_alloc( nrobs , nrens ); - matrix_type * S = matrix_alloc_copy( S0 ); - double * inv_sig0; - int num_PC; - - double_vector_iset( singular_values , nrmin - 1 , 0 ); - matrix_subtract_row_mean( S ); - ncomp = util_int_min( ncomp , nrmin ); - inv_sig0 = double_vector_get_ptr( singular_values ); - { - matrix_type * S_mean = matrix_alloc( nrobs , 1 ); - num_PC = enkf_linalg_svdS(S , truncation , ncomp, DGESVD_NONE , inv_sig0 , U0 , NULL); - - matrix_assign( S , S0); // The svd routine will overwrite S - we therefor must pick it up again from S0. - matrix_subtract_and_store_row_mean( S , S_mean); - - /* Multiply with inverted singular values. */ - matrix_resize( U0 , nrobs , num_PC , true); - for (int i=0; i < num_PC; i++) - matrix_imul_col( U0 , i , inv_sig0[i] ); - - /* The simulated components / projections */ - { - matrix_resize( PC , num_PC , nrens , false ); - matrix_dgemm( PC , U0 , S , true , false , 1.0 , 0.0 ); - } - - - /* The observer projections. */ - { - matrix_scale( S_mean , -1.0); - matrix_inplace_add_column( S_mean , dObs , 0 , 0 ); - matrix_resize( PC_obs , num_PC , 1 , false ); - matrix_dgemm( PC_obs , U0 , S_mean , true , false , 1.0 , 0.0 ); - } - - for (int i=0; i < double_vector_size( singular_values ); i++) - inv_sig0[i] = 1.0 / inv_sig0[i]; - - matrix_free( S_mean ); - } - matrix_free( S ); - matrix_free( U0 ); - - return num_PC; -} - - - -void enkf_linalg_rml_enkfX1(matrix_type *X1, matrix_type *Udr, matrix_type *D, matrix_type *R) -{ - /* - This routine computes X1 for RML_EnKF module as X1 = Ud(T)*Cd(-1/2)*D -- D= (dk-do) - here the negative sign cancels with one needed in X3 matrix computation - */ - matrix_type * tmp = matrix_alloc(matrix_get_columns(Udr),matrix_get_rows(R)); - - matrix_matmul_with_transpose( tmp, Udr, R, true, false); - matrix_matmul( X1 , tmp, D); - - matrix_free(tmp); -} - - - -void enkf_linalg_rml_enkfX2(matrix_type *X2 , double *Wdr , matrix_type * X1 , double a , int nsign) -{ - /* - This routine computes X2 for RML_EnKF module as X2 = ((a*Ipd)+Wd^2)^-1 * X1 - Since a+Ipd & Wd are diagonal in nature the computation is reduced to array operations - */ - - for (int i=0; i< nsign ; i++) { - double scale_factor = 1 / (a + (Wdr[i]*Wdr[i])); - matrix_scale_row(X1 , i , scale_factor); - } - matrix_assign(X2,X1); - -} - - -void enkf_linalg_rml_enkfX3(matrix_type *X3, matrix_type *VdTr, double *Wdr, matrix_type *X2, int nsign) -{ - /* - This routine computes X3 for RML_EnKF module as X3 = Vd *Wd*X2 - */ - - printf("\nWd: "); - matrix_type *tmp = matrix_alloc_copy(VdTr); - for (int i=0; i< nsign ; i++) { - printf("%5.2f ", Wdr[i]); - matrix_scale_row(tmp, i, Wdr[i]); - } - printf("\n\n"); - - matrix_matmul_with_transpose( X3 , tmp , X2 , true, false); - matrix_free(tmp); -} - - - - -double enkf_linalg_data_mismatch(matrix_type *D , matrix_type *R , matrix_type *Sk) -{ - matrix_type * tmp = matrix_alloc (matrix_get_columns(D), matrix_get_columns(R)); - double mismatch; - matrix_matmul_with_transpose(tmp, D, R,true, false); // tmp = D' * R, i.e. N-by-p - matrix_matmul(Sk, tmp, D); // Sk = D' * R * D - // Calculate the mismatch - mismatch = matrix_trace(Sk)/(matrix_get_columns(D)); - - return mismatch; -} - -// Cd = SampCov(E) (including (N-1) normalization) -void enkf_linalg_Covariance(matrix_type *Cd, const matrix_type *E, double nsc ,int nrobs) -{ - matrix_matmul_with_transpose(Cd, E, E,false,true); - for (int i=0; i< nrobs; i++) { - for (int j=0;j< nrobs; j++) { - if (i!=j) - matrix_iset(Cd, i, j, 0.0); - } - } - nsc = nsc*nsc; - matrix_scale(Cd,nsc); -} - - - -// Scale columns (not rows!) of Um by entries in diagonal Wm -void enkf_linalg_rml_enkfAm(matrix_type * Um, const double * Wm,int nsign1){ - for (int i=0; i< nsign1 ; i++) { - double sc = 1 / Wm[i]; - matrix_scale_column(Um, i, sc); - } -} - - - - -void enkf_linalg_rml_enkfX7(matrix_type * X7, matrix_type * VdT, double * Wdr, double a, matrix_type * X6){ - - int nsign = matrix_get_rows(VdT); - int ens_size = matrix_get_columns(VdT); - matrix_type *tmp1 = matrix_alloc_copy(VdT); - matrix_type *tmp2 = matrix_alloc(ens_size,ens_size); - - - for (int i=0; i < nsign ; i++) { - double scale_factor = 1 / ( a + (Wdr[i]*Wdr[i])); - matrix_scale_row( tmp1 , i , scale_factor); - } - - - matrix_matmul_with_transpose(tmp2, tmp1, VdT, true, false); - matrix_matmul(X7, tmp2, X6); - matrix_free(tmp1); - matrix_free(tmp2); -} - - diff --git a/ThirdParty/Ert/libanalysis/src/fwd_step_enkf.c b/ThirdParty/Ert/libanalysis/src/fwd_step_enkf.c deleted file mode 100644 index 6f41935d56..0000000000 --- a/ThirdParty/Ert/libanalysis/src/fwd_step_enkf.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - copyright (C) 2011 Statoil ASA, Norway. - - The file 'fwd_step_enkf.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#if defined(_OPENMP) -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define FWD_STEP_ENKF_TYPE_ID 765524 - -#define DEFAULT_NFOLDS 5 -#define DEFAULT_R2_LIMIT 0.99 -#define DEFAULT_NUM_THREADS -1 - -#define NFOLDS_KEY "CV_NFOLDS" -#define R2_LIMIT_KEY "FWD_STEP_R2_LIMIT" -#define DEFAULT_VERBOSE false -#define VERBOSE_KEY "VERBOSE" -#define NUM_THREADS_KEY "NUM_THREADS" -#define LOG_FILE_KEY "LOG_FILE" -#define CLEAR_LOG_KEY "CLEAR_LOG" - - -struct fwd_step_enkf_data_struct { - UTIL_TYPE_ID_DECLARATION; - stepwise_type * stepwise_data; - rng_type * rng; - int nfolds; - long option_flags; - double r2_limit; - bool verbose; - int num_threads; - fwd_step_log_type * fwd_step_log; -}; - - -static UTIL_SAFE_CAST_FUNCTION_CONST( fwd_step_enkf_data , FWD_STEP_ENKF_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION( fwd_step_enkf_data , FWD_STEP_ENKF_TYPE_ID ) - - -void fwd_step_enkf_set_nfolds( fwd_step_enkf_data_type * data , int nfolds ) { - data->nfolds = nfolds; -} - -void fwd_step_enkf_set_r2_limit( fwd_step_enkf_data_type * data , double limit ) { - data->r2_limit = limit; -} - -void fwd_step_enkf_set_verbose( fwd_step_enkf_data_type * data , bool verbose ) { - data->verbose = verbose; -} - -void fwd_step_enkf_set_num_threads( fwd_step_enkf_data_type * data , int threads ) { - data->num_threads = threads; -} - - -void * fwd_step_enkf_data_alloc( rng_type * rng ) { - fwd_step_enkf_data_type * data = util_malloc( sizeof * data ); - UTIL_TYPE_ID_INIT( data , FWD_STEP_ENKF_TYPE_ID ); - - data->stepwise_data = NULL; - data->rng = rng; - data->nfolds = DEFAULT_NFOLDS; - data->r2_limit = DEFAULT_R2_LIMIT; - data->option_flags = ANALYSIS_NEED_ED + ANALYSIS_UPDATE_A + ANALYSIS_SCALE_DATA; - data->verbose = DEFAULT_VERBOSE; - data->num_threads = DEFAULT_NUM_THREADS; - data->fwd_step_log = fwd_step_log_alloc(); - return data; -} - -void fwd_step_enkf_data_free( void * arg ) { - fwd_step_enkf_data_type * fwd_step_data = fwd_step_enkf_data_safe_cast( arg ); - { - - if (fwd_step_data != NULL) { - if (fwd_step_data->stepwise_data != NULL) { - stepwise_free( fwd_step_data->stepwise_data ); - } - } - } - fwd_step_log_free( fwd_step_data->fwd_step_log ); - free( fwd_step_data ); -} - - -//********************************************** -// Log-file related stuff -//********************************************** - - -static void fwd_step_enkf_write_log_header( fwd_step_enkf_data_type * fwd_step_data, const char * ministep_name, const int nx, const int nd, const int ens_size) { - const char * format = "%-25s%-25s%-25s%-25s\n"; - const char * column1 = "Parameter(ActiveIndex)"; - const char * column2 = "GlobalIndex"; - const char * column3 = "NumAttached"; - const char * column4 = "AttachedObs(ActiveIndex)[Percentage sensitivity]"; - int nfolds = fwd_step_data->nfolds; - int num_threads = fwd_step_data->num_threads; - double r2_limit = fwd_step_data->r2_limit; - - if (fwd_step_log_is_open( fwd_step_data->fwd_step_log )) { - fwd_step_log_line(fwd_step_data->fwd_step_log, "===============================================================================================================================\n"); - fwd_step_log_line(fwd_step_data->fwd_step_log, "Ministep : %s\n",ministep_name); - fwd_step_log_line(fwd_step_data->fwd_step_log, "Total number of parameters : %d\n",nx); - fwd_step_log_line(fwd_step_data->fwd_step_log, "Total number of observations: %d\n",nd); - fwd_step_log_line(fwd_step_data->fwd_step_log, "Number of ensembles : %d\n",ens_size); - fwd_step_log_line(fwd_step_data->fwd_step_log, "CV folds : %d\n",nfolds); - fwd_step_log_line(fwd_step_data->fwd_step_log, "Relative R2 tolerance : %f\n",r2_limit); - fwd_step_log_line(fwd_step_data->fwd_step_log, "===============================================================================================================================\n"); - fwd_step_log_line(fwd_step_data->fwd_step_log, format, column1, column2, column3, column4); - fwd_step_log_line(fwd_step_data->fwd_step_log, "===============================================================================================================================\n"); - } - - printf("===============================================================================================================================\n"); - printf("Ministep : %s\n",ministep_name); - printf("Total number of parameters : %d\n",nx); - printf("Total number of observations: %d\n",nd); - printf("Number of ensembles : %d\n",ens_size); - printf("CV folds : %d\n",nfolds); - printf("Number of threads : %d\n",num_threads); - printf("Relative R2 tolerance : %f\n",r2_limit); - printf("===============================================================================================================================\n"); - printf(format, column1, column2, column3, column4); - printf("===============================================================================================================================\n"); -} - -static void fwd_step_enkf_write_iter_info( fwd_step_enkf_data_type * data , stepwise_type * stepwise, const char* key, const int data_active_index, const int global_index, const module_info_type * module_info ) { - - const char * format = "%-25s%-25d%-25d"; - int n_active = stepwise_get_n_active( stepwise); - bool_vector_type * active_set = stepwise_get_active_set(stepwise); - bool has_log = fwd_step_log_is_open( data->fwd_step_log ); - module_obs_block_vector_type * module_obs_block_vector = module_info_get_obs_block_vector(module_info); - char * loc_key = util_alloc_string_copy(key); - char * data_active_index_str = util_alloc_sprintf( "(%d)" , data_active_index ); - char * cat = util_strcat_realloc(loc_key , data_active_index_str ); - if (has_log) - fwd_step_log_line( data->fwd_step_log , format, cat, global_index, n_active); - - printf(format, cat, global_index,n_active); - - const double sum_beta = stepwise_get_sum_beta(stepwise); - int obs_active_index = 0; - stringlist_type * obs_list = stringlist_alloc_new( ); - double_vector_type * r_list = double_vector_alloc(0, 0); - - const char * format1 = "%s(%d)[%.1f] "; - for (int ivar = 0; ivar < bool_vector_size( active_set); ivar++) { - if (!bool_vector_iget( active_set , ivar)) - continue; - - const module_obs_block_type * module_obs_block = module_obs_block_vector_search_module_obs_block(module_obs_block_vector, ivar); - const int* active_indices = module_obs_block_get_active_indices(module_obs_block); - bool all_active = active_indices == NULL; /* Inactive are not present in D */ - int row_start = module_obs_block_get_row_start(module_obs_block); - int row_end = module_obs_block_get_row_end(module_obs_block); - const char* obs_key = module_obs_block_get_key(module_obs_block); - const double var_beta = stepwise_iget_beta(stepwise, ivar); - const double var_beta_percent = 100.0 * fabs(var_beta) / sum_beta; - - int local_index = 0; - for (int i = row_start; i < row_end; i++) { - if (i == ivar){ - if (all_active) - obs_active_index = local_index; - else - obs_active_index = active_indices[local_index]; - break; - } - local_index ++; - } - - char * obs_list_entry = util_alloc_sprintf(format1 , obs_key, obs_active_index,var_beta_percent); - stringlist_append_copy(obs_list, obs_list_entry); - double_vector_append(r_list, var_beta_percent); - free( obs_list_entry ); - } - - { - /* Sorting with respect to sensitivity */ - perm_vector_type * sort_perm = double_vector_alloc_rsort_perm(r_list); - for (int i = 0; i < stringlist_get_size( obs_list); i++) { - const char * obs_list_entry = stringlist_iget(obs_list, perm_vector_iget(sort_perm, i)); - if (has_log) - fwd_step_log_line( data->fwd_step_log , "%s", obs_list_entry); - - printf("%s", obs_list_entry); - } - perm_vector_free(sort_perm); - } - - - - if (has_log) - fwd_step_log_line( data->fwd_step_log , "\n"); - - printf("\n"); - - stringlist_free(obs_list); - util_safe_free(data_active_index_str); - util_safe_free(cat); -} - -/*Main function: */ -void fwd_step_enkf_updateA(void * module_data , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D , - const module_info_type* module_info) { - - - - fwd_step_enkf_data_type * fwd_step_data = fwd_step_enkf_data_safe_cast( module_data ); - fwd_step_log_open(fwd_step_data->fwd_step_log); - module_data_block_vector_type * data_block_vector = module_info_get_data_block_vector(module_info); - printf("Running Forward Stepwise regression:\n"); - { - - int ens_size = matrix_get_columns( S ); - int nx = matrix_get_rows( A ); - int nd = matrix_get_rows( S ); - int nfolds = fwd_step_data->nfolds; - double r2_limit = fwd_step_data->r2_limit; - bool verbose = fwd_step_data->verbose; - int num_kw = module_data_block_vector_get_size(data_block_vector); - -#if defined(_OPENMP) - #pragma omp parallel - #pragma omp master - if (fwd_step_data->num_threads == DEFAULT_NUM_THREADS) - fwd_step_data->num_threads = omp_get_num_threads(); -#else - fwd_step_data->num_threads = 1; -#endif - - if ( ens_size <= nfolds) - util_abort("%s: The number of ensembles must be larger than the CV fold - aborting\n", __func__); - - - { - - matrix_type * St = matrix_alloc( ens_size , nd ); - matrix_type * Et = matrix_alloc( ens_size , nd ); - - /*workS = S' */ - matrix_subtract_row_mean( S ); /* Shift away the mean */ - St = matrix_alloc_transpose( S ); - Et = matrix_alloc_transpose( E ); - - matrix_type * di = matrix_alloc( 1 , nd ); - - if (verbose){ - char * ministep_name = module_info_get_ministep_name(module_info); - fwd_step_enkf_write_log_header(fwd_step_data, ministep_name, nx, nd, ens_size); - } - - int kw,i; - - /* This is to avoid a global-to-block search function since the number of parameters could be very large*/ - int_vector_type * kw_list = int_vector_alloc(nx, -1); - int_vector_type * local_index_list = int_vector_alloc(nx, -1); - for (kw = 0; kw < num_kw; kw++) { - module_data_block_type * data_block = module_data_block_vector_iget_module_data_block(data_block_vector, kw); - int row_start = module_data_block_get_row_start(data_block); - int row_end = module_data_block_get_row_end(data_block); - for (i = row_start; i < row_end; i++) { - int_vector_iset(kw_list, i, kw); - int_vector_iset(local_index_list, i, i - row_start); - } - } - - - // ============================================= - #pragma omp parallel for schedule(dynamic, 1) num_threads(fwd_step_data->num_threads) - for (i = 0; i < nx; i++) { - int kw_ind = int_vector_iget(kw_list, i); - module_data_block_type * data_block = module_data_block_vector_iget_module_data_block(data_block_vector, kw_ind); - const char * key = module_data_block_get_key(data_block); - const int* active_indices = module_data_block_get_active_indices(data_block); - int active_index = 0; - bool all_active = active_indices == NULL; /* Inactive are not present in A */ - stepwise_type * stepwise_data = stepwise_alloc1(ens_size, nd , fwd_step_data->rng, St, Et); - - /*Update values of y */ - /*Start of the actual update */ - matrix_type * y = matrix_alloc( ens_size , 1 ); - - for (int j = 0; j < ens_size; j++) { - matrix_iset(y , j , 0 , matrix_iget( A, i , j ) ); - } - - stepwise_set_Y0( stepwise_data , y ); - - stepwise_estimate(stepwise_data , r2_limit , nfolds ); - - /*manipulate A directly*/ - for (int j = 0; j < ens_size; j++) { - for (int k = 0; k < nd; k++) { - matrix_iset(di , 0 , k , matrix_iget( D , k , j ) ); - } - double aij = matrix_iget( A , i , j ); - double xHat = stepwise_eval(stepwise_data , di ); - matrix_iset(A , i , j , aij + xHat); - } - - if (verbose){ - int loc_ind = int_vector_iget(local_index_list, i ); - if (all_active) - active_index = loc_ind; - else - active_index = active_indices[loc_ind]; - - fwd_step_enkf_write_iter_info(fwd_step_data, stepwise_data, key, active_index, i, module_info); - - } - - stepwise_free( stepwise_data ); - } - - if (verbose) - printf("===============================================================================================================================\n"); - - printf("Done with stepwise regression enkf\n"); - - - matrix_free( di ); - int_vector_free(kw_list); - int_vector_free(local_index_list); - } - - - - } - - fwd_step_log_close( fwd_step_data->fwd_step_log ); -} - - - - - - -bool fwd_step_enkf_set_double( void * arg , const char * var_name , double value) { - fwd_step_enkf_data_type * module_data = fwd_step_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , R2_LIMIT_KEY ) == 0) - fwd_step_enkf_set_r2_limit( module_data , value ); - else - name_recognized = false; - - return name_recognized; - } -} - - -bool fwd_step_enkf_set_int( void * arg , const char * var_name , int value) { - fwd_step_enkf_data_type * module_data = fwd_step_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - - if (strcmp( var_name , NFOLDS_KEY) == 0) - fwd_step_enkf_set_nfolds( module_data , value); /*Set number of CV folds */ - else if (strcmp( var_name , NUM_THREADS_KEY) == 0) - fwd_step_enkf_set_num_threads( module_data , value); /*Set number of OMP threads */ - else - name_recognized = false; - - return name_recognized; - } -} - -bool fwd_step_enkf_set_bool( void * arg , const char * var_name , bool value) { - fwd_step_enkf_data_type * module_data = fwd_step_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - /*Set verbose */ - if (strcmp( var_name , VERBOSE_KEY) == 0) - fwd_step_enkf_set_verbose( module_data , value); - else if (strcmp( var_name , CLEAR_LOG_KEY) == 0) - fwd_step_log_set_clear_log( module_data->fwd_step_log , value ); - else - name_recognized = false; - - return name_recognized; - } -} - -bool fwd_step_enkf_set_string( void * arg , const char * var_name , const char * value) { - fwd_step_enkf_data_type * module_data = fwd_step_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , LOG_FILE_KEY) == 0) - fwd_step_log_set_log_file( module_data->fwd_step_log , value ); - else - name_recognized = false; - - return name_recognized; - } -} - -long fwd_step_enkf_get_options( void * arg , long flag) { - fwd_step_enkf_data_type * fwd_step_data = fwd_step_enkf_data_safe_cast( arg ); - { - return fwd_step_data->option_flags; - } -} - -bool fwd_step_enkf_has_var( const void * arg, const char * var_name) { - { - if (strcmp(var_name , NFOLDS_KEY) == 0) - return true; - else if (strcmp(var_name , R2_LIMIT_KEY ) == 0) - return true; - else if (strcmp(var_name , VERBOSE_KEY ) == 0) - return true; - else if (strcmp(var_name , LOG_FILE_KEY) == 0) - return true; - else if (strcmp(var_name , CLEAR_LOG_KEY) == 0) - return true; - else if (strcmp(var_name , NUM_THREADS_KEY) == 0) - return true; - else - return false; - } -} - -double fwd_step_enkf_get_double( const void * arg, const char * var_name) { - const fwd_step_enkf_data_type * module_data = fwd_step_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , R2_LIMIT_KEY ) == 0) - return module_data->r2_limit; - else - return -1; - } -} - -int fwd_step_enkf_get_int( const void * arg, const char * var_name) { - const fwd_step_enkf_data_type * module_data = fwd_step_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , NFOLDS_KEY) == 0) - return module_data->nfolds; - if (strcmp(var_name , NUM_THREADS_KEY) == 0) - return module_data->num_threads; - else - return -1; - } -} - -bool fwd_step_enkf_get_bool( const void * arg, const char * var_name) { - const fwd_step_enkf_data_type * module_data = fwd_step_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , VERBOSE_KEY) == 0) - return module_data->verbose; - else if (strcmp(var_name , CLEAR_LOG_KEY) == 0) - return fwd_step_log_get_clear_log( module_data->fwd_step_log ); - else - return false; - } -} - -void * fwd_step_enkf_get_ptr( const void * arg , const char * var_name ) { - const fwd_step_enkf_data_type * module_data = fwd_step_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , LOG_FILE_KEY) == 0) - return (void *) fwd_step_log_get_log_file( module_data->fwd_step_log ); - else - return NULL; - } -} - - - - - -#ifdef INTERNAL_LINK -#define LINK_NAME FWD_STEP_ENKF -#else -#define LINK_NAME EXTERNAL_MODULE_SYMBOL -#endif - - -analysis_table_type LINK_NAME = { - .name = "FWD_STEP_ENKF", - .alloc = fwd_step_enkf_data_alloc, - .freef = fwd_step_enkf_data_free, - .set_int = fwd_step_enkf_set_int , - .set_double = fwd_step_enkf_set_double , - .set_bool = fwd_step_enkf_set_bool , - .set_string = fwd_step_enkf_set_string , - .get_options = fwd_step_enkf_get_options , - .initX = NULL , - .updateA = fwd_step_enkf_updateA, - .init_update = NULL , - .complete_update = NULL , - .has_var = fwd_step_enkf_has_var, - .get_int = fwd_step_enkf_get_int , - .get_double = fwd_step_enkf_get_double , - .get_bool = fwd_step_enkf_get_bool , - .get_ptr = fwd_step_enkf_get_ptr -}; - - diff --git a/ThirdParty/Ert/libanalysis/src/fwd_step_log.c b/ThirdParty/Ert/libanalysis/src/fwd_step_log.c deleted file mode 100644 index d8c585e9a6..0000000000 --- a/ThirdParty/Ert/libanalysis/src/fwd_step_log.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'fwd_step_log.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include - -#include - -#include - -#define DEFAULT_LOG_FILE "fwd_step.out" -#define DEFAULT_CLEAR_LOG false - -struct fwd_step_log_struct { - bool clear_log; - char * log_file; - FILE * log_stream; -}; - - -fwd_step_log_type * fwd_step_log_alloc() { - fwd_step_log_type * fwd_step_log = util_malloc( sizeof * fwd_step_log ); - fwd_step_log->log_file = NULL; - fwd_step_log->log_stream = NULL; - fwd_step_log_set_log_file( fwd_step_log , DEFAULT_LOG_FILE); - fwd_step_log_set_clear_log( fwd_step_log , DEFAULT_CLEAR_LOG ); - return fwd_step_log; -} - -bool fwd_step_log_get_clear_log( const fwd_step_log_type * data ) { - return data->clear_log; -} - -void fwd_step_log_set_clear_log( fwd_step_log_type * data , bool clear_log) { - data->clear_log = clear_log; -} - -void fwd_step_log_set_log_file( fwd_step_log_type * data , const char * log_file ) { - data->log_file = util_realloc_string_copy( data->log_file , log_file ); -} - -const char * fwd_step_log_get_log_file( const fwd_step_log_type * data) { - return data->log_file; -} - - -void fwd_step_log_free(fwd_step_log_type * fwd_step_log) { - fwd_step_log_close( fwd_step_log ); - util_safe_free( fwd_step_log->log_file ); - free( fwd_step_log ); -} - - -void fwd_step_log_open( fwd_step_log_type * fwd_step_log ) { - if (fwd_step_log->log_file) { - if (fwd_step_log->clear_log) - fwd_step_log->log_stream = util_mkdir_fopen( fwd_step_log->log_file , "w"); - else - fwd_step_log->log_stream = util_mkdir_fopen( fwd_step_log->log_file , "a"); - } -} - - -bool fwd_step_log_is_open( const fwd_step_log_type * fwd_step_log ) { - if (fwd_step_log->log_stream) - return true; - else - return false; -} - - -void fwd_step_log_close( fwd_step_log_type * fwd_step_log ) { - if (fwd_step_log->log_stream) - fclose( fwd_step_log->log_stream ); - - fwd_step_log->log_stream = NULL; -} - - -void fwd_step_log_line( fwd_step_log_type * fwd_step_log , const char * fmt , ...) { - if (fwd_step_log->log_stream) { - va_list ap; - va_start(ap , fmt); - vfprintf( fwd_step_log->log_stream , fmt , ap ); - va_end( ap ); - } -} - - diff --git a/ThirdParty/Ert/libanalysis/src/module_data_block.c b/ThirdParty/Ert/libanalysis/src/module_data_block.c deleted file mode 100644 index ebe9d34c23..0000000000 --- a/ThirdParty/Ert/libanalysis/src/module_data_block.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'module_data_block.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include - -#include -#include - -#include - -#define MODULE_DATA_BLOCK_TYPE_ID 73217801 -static UTIL_SAFE_CAST_FUNCTION( module_data_block , MODULE_DATA_BLOCK_TYPE_ID); -UTIL_IS_INSTANCE_FUNCTION( module_data_block , MODULE_DATA_BLOCK_TYPE_ID) - -module_data_block_type * module_data_block_alloc( const char * key, const int * index_list , const int row_start, const int n_active) { - module_data_block_type * module_data_block = util_malloc( sizeof * module_data_block ); - UTIL_TYPE_ID_INIT( module_data_block , MODULE_DATA_BLOCK_TYPE_ID ); - module_data_block->key = util_alloc_string_copy( key ); - module_data_block->index_list = index_list; - module_data_block->A_row_start = row_start; - module_data_block->n_active = n_active; - return module_data_block; -} - - -const char * module_data_block_get_key(const module_data_block_type * module_data_block){ - return module_data_block->key; -} - -const int module_data_block_get_row_start(const module_data_block_type * module_data_block){ - return module_data_block->A_row_start; -} - -const int module_data_block_get_row_end(const module_data_block_type * module_data_block){ - return module_data_block->A_row_start + module_data_block->n_active; -} - -const int * module_data_block_get_active_indices(const module_data_block_type * module_data_block ){ - return module_data_block->index_list; -} - -void module_data_block_free( module_data_block_type * module_data_block ) { - util_safe_free(module_data_block->key); - free( module_data_block ); -} - -void module_data_block_free__( void * arg ) { - module_data_block_type * data_block = module_data_block_safe_cast( arg ); - module_data_block_free( data_block ); -} diff --git a/ThirdParty/Ert/libanalysis/src/module_data_block_vector.c b/ThirdParty/Ert/libanalysis/src/module_data_block_vector.c deleted file mode 100644 index 33ff3a86cc..0000000000 --- a/ThirdParty/Ert/libanalysis/src/module_data_block_vector.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'module_data_block_vector.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include - -#include -#include - -#define MODULE_DATA_BLOCK_VECTOR_TYPE_ID 732178012 - -struct module_data_block_vector_struct { - UTIL_TYPE_ID_DECLARATION; - vector_type * data_block_vector; -}; - -UTIL_IS_INSTANCE_FUNCTION( module_data_block_vector , MODULE_DATA_BLOCK_VECTOR_TYPE_ID) - -module_data_block_vector_type * module_data_block_vector_alloc( ) { - module_data_block_vector_type * module_data_block_vector = util_malloc( sizeof * module_data_block_vector ); - UTIL_TYPE_ID_INIT( module_data_block_vector , MODULE_DATA_BLOCK_VECTOR_TYPE_ID ); - module_data_block_vector->data_block_vector = vector_alloc_new(); - return module_data_block_vector; -} - - -void module_data_block_vector_free( module_data_block_vector_type * module_data_block_vector ) { - vector_free( module_data_block_vector->data_block_vector ); - free( module_data_block_vector ); -} - -void module_data_block_vector_add_data_block( module_data_block_vector_type * module_data_block_vector , const module_data_block_type * data_block) { - vector_append_owned_ref(module_data_block_vector->data_block_vector, data_block , module_data_block_free__); -} - - -module_data_block_type * module_data_block_vector_iget_module_data_block(const module_data_block_vector_type * module_data_block_vector, int index){ - return vector_iget(module_data_block_vector->data_block_vector, index); -} - -int module_data_block_vector_get_size(const module_data_block_vector_type * module_data_block_vector){ - return vector_get_size(module_data_block_vector->data_block_vector); -} - - diff --git a/ThirdParty/Ert/libanalysis/src/module_info.c b/ThirdParty/Ert/libanalysis/src/module_info.c deleted file mode 100644 index 969df3792a..0000000000 --- a/ThirdParty/Ert/libanalysis/src/module_info.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'module_info.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include - -#include - -#define MODULE_INFO_TYPE_ID 73780123 - -struct module_info_struct { - UTIL_TYPE_ID_DECLARATION; - char * ministep_name; - module_data_block_vector_type * data_block_vector; - module_obs_block_vector_type * obs_block_vector; -}; - -UTIL_IS_INSTANCE_FUNCTION( module_info , MODULE_INFO_TYPE_ID) - -module_info_type * module_info_alloc( const char* ministep_name ) { - module_info_type * module_info = util_malloc( sizeof * module_info ); - UTIL_TYPE_ID_INIT( module_info , MODULE_INFO_TYPE_ID ); - module_info->ministep_name = util_alloc_string_copy( ministep_name ); - module_info->data_block_vector = module_data_block_vector_alloc(); - module_info->obs_block_vector = module_obs_block_vector_alloc(); - return module_info; -} - - -void module_info_free( module_info_type * module_info ) { - util_safe_free(module_info->ministep_name); - module_data_block_vector_free( module_info->data_block_vector ); - module_obs_block_vector_free( module_info->obs_block_vector ); - free( module_info ); -} - -module_data_block_vector_type * module_info_get_data_block_vector(const module_info_type * module_info){ - return module_info->data_block_vector; -} - -module_obs_block_vector_type * module_info_get_obs_block_vector(const module_info_type * module_info){ - return module_info->obs_block_vector; -} - -char * module_info_get_ministep_name(const module_info_type * module_info){ - return module_info->ministep_name; -} diff --git a/ThirdParty/Ert/libanalysis/src/module_obs_block.c b/ThirdParty/Ert/libanalysis/src/module_obs_block.c deleted file mode 100644 index 7960919528..0000000000 --- a/ThirdParty/Ert/libanalysis/src/module_obs_block.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'module_obs_block.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include - -#include -#include - -#include - -#define MODULE_OBS_BLOCK_TYPE_ID 73217901 -static UTIL_SAFE_CAST_FUNCTION( module_obs_block , MODULE_OBS_BLOCK_TYPE_ID); -UTIL_IS_INSTANCE_FUNCTION( module_obs_block , MODULE_OBS_BLOCK_TYPE_ID) - -module_obs_block_type * module_obs_block_alloc( const char * key, const int * index_list, const int row_start, const int n_active) { - module_obs_block_type * module_obs_block = util_malloc( sizeof * module_obs_block ); - UTIL_TYPE_ID_INIT( module_obs_block , MODULE_OBS_BLOCK_TYPE_ID ); - module_obs_block->key = util_alloc_string_copy( key ); - module_obs_block->index_list = index_list; - module_obs_block->D_row_start = row_start; - module_obs_block->n_active = n_active; - return module_obs_block; -} - - -const char * module_obs_block_get_key(const module_obs_block_type * module_obs_block){ - return module_obs_block->key; -} - -const int module_obs_block_get_row_start(const module_obs_block_type * module_obs_block){ - return module_obs_block->D_row_start; -} - -const int module_obs_block_get_row_end(const module_obs_block_type * module_obs_block){ - return module_obs_block->D_row_start + module_obs_block->n_active; -} - -const int * module_obs_block_get_active_indices(const module_obs_block_type * module_obs_block ){ - return module_obs_block->index_list; -} - -void module_obs_block_free( module_obs_block_type * module_obs_block ) { - util_safe_free(module_obs_block->key); - free( module_obs_block ); -} - -void module_obs_block_free__( void * arg ) { - module_obs_block_type * obs_block = module_obs_block_safe_cast( arg ); - module_obs_block_free( obs_block ); -} diff --git a/ThirdParty/Ert/libanalysis/src/module_obs_block_vector.c b/ThirdParty/Ert/libanalysis/src/module_obs_block_vector.c deleted file mode 100644 index dc076d0523..0000000000 --- a/ThirdParty/Ert/libanalysis/src/module_obs_block_vector.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'module_obs_block_vector.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include - -#include -#include - -#define MODULE_OBS_BLOCK_VECTOR_TYPE_ID 732188012 - -struct module_obs_block_vector_struct { - UTIL_TYPE_ID_DECLARATION; - vector_type * obs_block_vector; -}; - -UTIL_IS_INSTANCE_FUNCTION( module_obs_block_vector , MODULE_OBS_BLOCK_VECTOR_TYPE_ID) - -module_obs_block_vector_type * module_obs_block_vector_alloc() { - module_obs_block_vector_type * module_obs_block_vector = util_malloc( sizeof * module_obs_block_vector ); - UTIL_TYPE_ID_INIT( module_obs_block_vector , MODULE_OBS_BLOCK_VECTOR_TYPE_ID ); - module_obs_block_vector->obs_block_vector = vector_alloc_new(); - return module_obs_block_vector; -} - - -void module_obs_block_vector_free( module_obs_block_vector_type * module_obs_block_vector ) { - vector_free( module_obs_block_vector->obs_block_vector ); - free( module_obs_block_vector ); -} - -void module_obs_block_vector_add_obs_block( module_obs_block_vector_type * module_obs_block_vector , module_obs_block_type * obs_block) { - vector_append_owned_ref(module_obs_block_vector->obs_block_vector, obs_block , module_obs_block_free__); -} - - -module_obs_block_type * module_obs_block_vector_iget_module_obs_block(const module_obs_block_vector_type * module_obs_block_vector, int block_index){ - return vector_iget(module_obs_block_vector->obs_block_vector, block_index); -} - -const module_obs_block_type * module_obs_block_vector_search_module_obs_block(const module_obs_block_vector_type * module_obs_block_vector, int global_index){ - /* This function maps from a global index to an observation information block. Will return NULL if block is not found */ - int block_nr = 0; - while (true) { - if (block_nr >= module_obs_block_vector_get_size( module_obs_block_vector )) - break; - - module_obs_block_type * module_obs_block = module_obs_block_vector_iget_module_obs_block (module_obs_block_vector, block_nr); - int row_start = module_obs_block_get_row_start(module_obs_block); - int row_end = module_obs_block_get_row_end(module_obs_block); - if (global_index >= row_start && global_index < row_end) - return module_obs_block; - - block_nr++; - } - return NULL; -} - -int module_obs_block_vector_get_size(const module_obs_block_vector_type * module_obs_block_vector){ - return vector_get_size(module_obs_block_vector->obs_block_vector); -} - - diff --git a/ThirdParty/Ert/libanalysis/src/modules.txt b/ThirdParty/Ert/libanalysis/src/modules.txt deleted file mode 100644 index 906a777b9c..0000000000 --- a/ThirdParty/Ert/libanalysis/src/modules.txt +++ /dev/null @@ -1,212 +0,0 @@ -Overview --------- -The ERT application has evolved into a quite complex beast. Originally -the actual EnKF algorithm was located very deep down in the code, and -changes to the EnKF algorithm required detailed knowledge about the -enkf_node objects, the datatype for measurements and observations, -serialisation and so on. Quite complex and fragile stuff. - -To facilitate easier development and testing of new update schemes the -core EnKF update step has been factored out as analysis modules, which -are called from the enkf_main scope. The update functions in the -module get ordinary matrices as input, and do not need to know -anything about the internals of the ERT application. - -The modules can either be built in, or you can compile your own module -as a shared library and load it runtime. Apart from the initial -loading internal modules and external modules are treated 100% -identically. - - -How modules work ----------------- -The modules are instances of the object type analysis_module_type, and -the enkf_main layer interacts with the module through the -analyis_module instance. The most important part of the -analysis_module type is a list of function pointers to functions which -"actually do the work". In addition to some functions for setting -internal module variables the most core functions are: - - init_update() - initX() - updateA() - complete_update() - -Of these functions a module should have ONLY ONE of initX() and -updateA(); the initX() function will initialize an X matrix which is -then subsequently used to update the ensemble matrix A. Alternatively -the updateA() function should will directly manipulate the A matrix. - -The init_update() and complete_update() functions are optional, they -can be used to avoid repeated initialization calculations. These -functions interact quite closely with the scheme used for local -analysis; so you should understand that in detail before deciding -whether it is worthwile to implement init_update() and -complete_update() functions. - - -Loading modules ---------------- - -The loading of modules is based on the dlopen() function to open a -shared a library and map it into the adress space of the current -process, and then the dlsym() function to locate a symbol table which -is a list of function pointers. The only difference between internal -and external modules is in the arguments passed to the dlopen() and -dlsym() function calls: - - Loading internal modules - ------------------------ - Internal modules means modules which have been compiled into the - libanalyis library, i.e. they are already part of the ERT - executable, however before we have "loaded" these modules we have - no way to access them. The current executable is loaded by - passing NULL as argument to dlopen(). - - When dlopen() has succeded we must use dlsym() to get a handle to - the symbol table. The symbol table is essentially a global - variable in the ERT adress space, and must have a unique name for - each module. - - - Loading external modules - ------------------------ - External modules are ordinary shared libraries. To load an external - module the name of the shared library must be given to the dlopen() - function, normal rules for runtime loading of dynamic libraries - apply - i.e. the shared library must be in a location where the - dynamic linker can find it. The name of module should be a - filename, including the .so extension. undo - - When dlopen() has succeded we must use dlsym() to get a handle to - the symbol table; when the module loading is hidden behind a - dlopen() call we have essentially created a module namespace, and - the symbol tables from the different modules can have the same - name. For convenience we assume that the symbol table is given by - the name defined by the symbol EXTERNAL_MODULE_TABLE in - analysis_module.h. - -In practice all of is handled by the functions: - - analysis_module_type * analysis_module_alloc_internal( ); - analysis_module_type * analysis_module_alloc_external( ); - -symbol_table ------------- - -Interacting with modules ------------------------- -The modules can implement four different functions to set a scalar -value. The four functions have signature: - - bool set_int (void * module_data, const char * var_name , int value) - bool set_double( void * module_data , const char * var_name , double value) - bool set_bool( void * module_data , const char * var_name , bool value ) - bool set_string( void * module_data , const char * var_name , const char * value ) - -Common for all these functions is: - - 1. It is not necessary to implement these functions; if you know - that the module has no internal integer variables which should be - user-modifiable you can just set the set_int function pointer to - NULL. - - 2. If the module recognizes the variable name and actually sets an - internal variable it should return true, otherwise return false. - - 3. The set_xxx() functions are called from the wrapper function - analysis_module_set_var(); when calling the wrapper function the - value variable is a string which we try to convert to int, double - and bool respectively and then cascade through the functions in - the order listed above. This involves two things: - - a) A module has an internal variable namespace which is shared - among all variable types. - - b) If the string value argument is incorrectly formatted, - i.e. an integer is passed as "12x" the correct low level - function will not be called. - -The method to get information out from the module is much more -limited. Each module should contain an internal variable: - - long option_flags; - -And when instantiating the module data you should initialize the -option_flags variable by adding together the relevant option flags -from analysis_module.h. The enkf_main_UPDATE() method which invokes -the module functions will inspect the option_flags to see which -variables to pass to the module, and which module functions to invoke, -so this must be correct. - -Example -------- -The module/file std_enkf.c is commented quite heavily to serve as an -example. - ---------------------------------------------------------------------- - -With the analysis modules we have essentially got a three layer -design: - - 1. The ert core layer which creates/loads a list of analysis_module - instances. - - 2. analysis_module instances are a thing layer which: - - a) Hold on to specific analysis implementations like e.g. the - std_enkf implementation on one side. - - b) Present a uniform module interface to the ert layer on the - 'other side'. - - 3. Specific analysis module implementations like the std_enkf. - - -In fine ASCII art: - . - +----------------------+ . +---------------------------+ - | Analysis module | . | Implementation std_enkf | - +----------------------+ . +---------------------------+ - | | /------> | std_enkf_alloc() | - ----------------------> | | / . | std_enkf_free() | - / | X |o--------> | std_enkf_get_options() | - / | | \ . | std_enkf_initX() | - +------------------------------------------+ / | | \------> | std_enkf_set_int() | - | The ert core layer; in particular | / | | . | std_enkf_set_double() | - | the following functions: | / +----------------------+ . +---------------------------+ - | - analysis_config_load_external_module() |o . - | - analysis_config_load_internal_module() | \ +----------------------+ . +---------------------------+ - | - enkf_main_module_update() | \ | Analysis module | . | Implementation sqrt_enkf | - +------------------------------------------+ \ +----------------------+ . +---------------------------+ - \ | | /------> | sqrt_enkf_alloc() | - \ | | / . | sqrt_enkf_free() | - \---------------------> | |o--------> | sqrt_enkf_get_options() | - \ | X | \ . | sqrt_enkf_initX() | - \ | | \------> | sqrt_enkf_set_int() | - \ | | . | sqrt_enkf_set_double() | - \ +----------------------+ . +---------------------------+ - \ . - In the ert core layer the \ +----------------------+ . +---------------------------+ - different analysis module \ | Analysis module | . | Implementation cv_enkf | - instances are collected in \ +----------------------+ . +---------------------------+ - a hash table, and all function \ | | /------> | cv_enkf_alloc() | - invocations go through the \ | | / . | cv_enkf_free() | - functions in the analysis_module -----------> | |o--------> | cv_enkf_get_options() | - layer. | X | \ . | cv_enkf_initX() | - | | \------> | cv_enkf_set_int() | - | | . | cv_enkf_set_double() | - +----------------------+ . +---------------------------+ - . - . - . - . - . - The links between the analysis - modules and the std_enkf, sqrt_enkf - and cv_enkf implementations are - in terms of function pointers. These - links are established runtime, and - the vertical dotted line represents - an opaque wall which ert core layer - can not see through. diff --git a/ThirdParty/Ert/libanalysis/src/null_enkf.c b/ThirdParty/Ert/libanalysis/src/null_enkf.c deleted file mode 100644 index 295ab53ada..0000000000 --- a/ThirdParty/Ert/libanalysis/src/null_enkf.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'null_enkf.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - - - - -void null_enkf_initX(void * module_data , - matrix_type * X , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D) { - - matrix_diag_set_scalar( X , 1.0 ); - -} - - -long null_enkf_get_options( void * arg , long flag ) { - return 0L; -} - - - -/** - gcc -fpic -c -I?? - gcc -shared -o -*/ - - - -#ifdef INTERNAL_LINK -#define LINK_NAME NULL_ENKF -#else -#define LINK_NAME EXTERNAL_MODULE_SYMBOL -#endif - -analysis_table_type LINK_NAME = { - .name = "NULL_ENKF", - .alloc = NULL , - .freef = NULL , - .set_int = NULL , - .set_double = NULL , - .set_bool = NULL , - .set_string = NULL , - .get_options = null_enkf_get_options, - .initX = null_enkf_initX , - .updateA = NULL, - .init_update = NULL, - .complete_update = NULL, - .has_var = NULL, - .get_int = NULL, - .get_double = NULL, - .get_ptr = NULL, -}; - diff --git a/ThirdParty/Ert/libanalysis/src/sqrt_enkf.c b/ThirdParty/Ert/libanalysis/src/sqrt_enkf.c deleted file mode 100644 index 082a57bc29..0000000000 --- a/ThirdParty/Ert/libanalysis/src/sqrt_enkf.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sqrt_enkf.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - - -/* - The sqrt_enkf module performs a EnKF update based on the square root - scheme. Observe that this module shares quite a lot of - implementation with the std_enkf module. -*/ - -#define SQRT_ENKF_TYPE_ID 268823 - -typedef struct { - UTIL_TYPE_ID_DECLARATION; - std_enkf_data_type * std_data; - matrix_type * randrot; - rng_type * rng; - long options; -} sqrt_enkf_data_type; - - -static UTIL_SAFE_CAST_FUNCTION( sqrt_enkf_data , SQRT_ENKF_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION_CONST( sqrt_enkf_data , SQRT_ENKF_TYPE_ID ) - - -void * sqrt_enkf_data_alloc( rng_type * rng ) { - sqrt_enkf_data_type * data = util_malloc( sizeof * data ); - UTIL_TYPE_ID_INIT( data , SQRT_ENKF_TYPE_ID ); - - data->std_data = std_enkf_data_alloc( rng ); - data->randrot = NULL; - data->rng = rng; - data->options = ANALYSIS_SCALE_DATA; - - return data; -} - - - -void sqrt_enkf_data_free( void * data ) { - sqrt_enkf_data_type * module_data = sqrt_enkf_data_safe_cast( data ); - { - std_enkf_data_free( module_data->std_data ); - free( module_data ); - } -} - - - -bool sqrt_enkf_set_double( void * arg , const char * var_name , double value) { - sqrt_enkf_data_type * module_data = sqrt_enkf_data_safe_cast( arg ); - { - if (std_enkf_set_double( module_data->std_data , var_name , value )) - return true; - else { - /* Could in principle set sqrt specific variables here. */ - return false; - } - } -} - - -bool sqrt_enkf_set_int( void * arg , const char * var_name , int value) { - sqrt_enkf_data_type * module_data = sqrt_enkf_data_safe_cast( arg ); - { - if (std_enkf_set_int( module_data->std_data , var_name , value )) - return true; - else { - /* Could in principle set sqrt specific variables here. */ - return false; - } - } -} - - - - - -void sqrt_enkf_initX(void * module_data , - matrix_type * X , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type *D ) { - - sqrt_enkf_data_type * data = sqrt_enkf_data_safe_cast( module_data ); - { - int ncomp = std_enkf_get_subspace_dimension( data->std_data ); - double truncation = std_enkf_get_truncation( data->std_data ); - int nrobs = matrix_get_rows( S ); - int ens_size = matrix_get_columns( S ); - int nrmin = util_int_min( ens_size , nrobs); - matrix_type * W = matrix_alloc(nrobs , nrmin); - double * eig = util_calloc( nrmin , sizeof * eig ); - - matrix_subtract_row_mean( S ); /* Shift away the mean */ - enkf_linalg_lowrankCinv( S , R , W , eig , truncation , ncomp); - enkf_linalg_init_sqrtX( X , S , data->randrot , dObs , W , eig , false); - matrix_free( W ); - free( eig ); - - enkf_linalg_checkX( X , false ); - } -} - - -long sqrt_enkf_get_options( void * arg , long flag ) { - sqrt_enkf_data_type * module_data = sqrt_enkf_data_safe_cast( arg ); - { - return module_data->options; - } -} - - - -// Called from analysis_module.c: analysis_module_init_update() -void sqrt_enkf_init_update( void * arg , - const bool_vector_type * ens_mask, - const matrix_type * S , - const matrix_type * R , - const matrix_type * dObs , - const matrix_type * E , - const matrix_type * D ) { - - sqrt_enkf_data_type * sqrt_data = sqrt_enkf_data_safe_cast( arg ); - { - int ens_size = matrix_get_columns( S ); - sqrt_data->randrot = enkf_linalg_alloc_mp_randrot( ens_size , sqrt_data->rng ); - } -} - - -void sqrt_enkf_complete_update( void * arg ) { - sqrt_enkf_data_type * sqrt_data = sqrt_enkf_data_safe_cast( arg ); - { - matrix_free( sqrt_data->randrot ); - sqrt_data->randrot = NULL; - } -} - -bool sqrt_enkf_has_var( const void * arg, const char * var_name) { - const sqrt_enkf_data_type * module_data = sqrt_enkf_data_safe_cast_const( arg ); - { - return std_enkf_has_var(module_data->std_data, var_name); - } -} - -double sqrt_enkf_get_double( const void * arg, const char * var_name) { - const sqrt_enkf_data_type * module_data = sqrt_enkf_data_safe_cast_const( arg ); - { - return std_enkf_get_double( module_data->std_data , var_name); - } -} - -int sqrt_enkf_get_int( const void * arg, const char * var_name) { - const sqrt_enkf_data_type * module_data = sqrt_enkf_data_safe_cast_const( arg ); - { - return std_enkf_get_int( module_data->std_data , var_name); - } -} - - - -/*****************************************************************/ - -#ifdef INTERNAL_LINK -#define LINK_NAME SQRT_ENKF -#else -#define LINK_NAME EXTERNAL_MODULE_SYMBOL -#endif - - - -analysis_table_type LINK_NAME = { - .name = "SQRT_ENKF", - .alloc = sqrt_enkf_data_alloc, - .freef = sqrt_enkf_data_free, - .set_int = sqrt_enkf_set_int , - .set_double = sqrt_enkf_set_double , - .set_bool = NULL , - .set_string = NULL , - .initX = sqrt_enkf_initX , - .updateA = NULL, - .init_update = sqrt_enkf_init_update, - .complete_update = sqrt_enkf_complete_update, - .get_options = sqrt_enkf_get_options, - .has_var = sqrt_enkf_has_var, - .get_int = sqrt_enkf_get_int, - .get_double = sqrt_enkf_get_double, - .get_bool = NULL, - .get_ptr = NULL -}; - diff --git a/ThirdParty/Ert/libanalysis/src/std_enkf.c b/ThirdParty/Ert/libanalysis/src/std_enkf.c deleted file mode 100644 index 52ed793e1f..0000000000 --- a/ThirdParty/Ert/libanalysis/src/std_enkf.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'std_enkf.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - - -/* - A random 'magic' integer id which is used for run-time type checking - of the input data. -*/ -#define STD_ENKF_TYPE_ID 261123 - - - -/* - Observe that only one of the settings subspace_dimension and - truncation can be valid at a time; otherwise the svd routine will - fail. This implies that the set_truncation() and - set_subspace_dimension() routines will set one variable, AND - INVALIDATE THE OTHER. For most situations this will be OK, but if - you have repeated calls to both of these functions the end result - might be a surprise. -*/ -#define INVALID_SUBSPACE_DIMENSION -1 -#define INVALID_TRUNCATION -1 -#define DEFAULT_SUBSPACE_DIMENSION INVALID_SUBSPACE_DIMENSION -#define DEFAULT_USE_EE false -#define DEFAULT_USE_GE false -#define DEFAULT_ANALYSIS_SCALE_DATA true - - - - - -/* - The configuration data used by the std_enkf module is contained in a - std_enkf_data_struct instance. The data type used for the std_enkf - module is quite simple; with only a few scalar variables, but there - are essentially no limits to what you can pack into such a datatype. - - All the functions in the module have a void pointer as the first - argument, this will immediately be casted to a std_enkf_data_type - instance, to get some type safety the UTIL_TYPE_ID system should be - used (see documentation in util.h) - - The data structure holding the data for your analysis module should - be created and initialized by a constructor, which should be - registered with the '.alloc' element of the analysis table; in the - same manner the desctruction of this data should be handled by a - destructor or free() function registered with the .freef field of - the analysis table. -*/ - - - - -struct std_enkf_data_struct { - UTIL_TYPE_ID_DECLARATION; - double truncation; // Controlled by config key: ENKF_TRUNCATION_KEY - int subspace_dimension; // Controlled by config key: ENKF_NCOMP_KEY (-1: use Truncation instead) - long option_flags; - bool use_EE; - bool use_GE; - bool analysis_scale_data; -}; - -static UTIL_SAFE_CAST_FUNCTION_CONST( std_enkf_data , STD_ENKF_TYPE_ID ) - - -/* - This is a macro which will expand to generate a function: - - std_enkf_data_type * std_enkf_data_safe_cast( void * arg ) {} - - which is used for runtime type checking of all the functions which - accept a void pointer as first argument. -*/ -static UTIL_SAFE_CAST_FUNCTION( std_enkf_data , STD_ENKF_TYPE_ID ) - - -double std_enkf_get_truncation( std_enkf_data_type * data ) { - return data->truncation; -} - -int std_enkf_get_subspace_dimension( std_enkf_data_type * data ) { - return data->subspace_dimension; -} - -void std_enkf_set_truncation( std_enkf_data_type * data , double truncation ) { - data->truncation = truncation; - if (truncation > 0.0) - data->subspace_dimension = INVALID_SUBSPACE_DIMENSION; -} - -void std_enkf_set_subspace_dimension( std_enkf_data_type * data , int subspace_dimension) { - data->subspace_dimension = subspace_dimension; - if (subspace_dimension > 0) - data->truncation = INVALID_TRUNCATION; -} - - - -void * std_enkf_data_alloc( rng_type * rng) { - std_enkf_data_type * data = util_malloc( sizeof * data ); - UTIL_TYPE_ID_INIT( data , STD_ENKF_TYPE_ID ); - - std_enkf_set_truncation( data , DEFAULT_ENKF_TRUNCATION_ ); - std_enkf_set_subspace_dimension( data , DEFAULT_SUBSPACE_DIMENSION ); - data->option_flags = ANALYSIS_NEED_ED; - data->use_EE = DEFAULT_USE_EE; - data->use_GE = DEFAULT_USE_GE; - data->analysis_scale_data = DEFAULT_ANALYSIS_SCALE_DATA; - return data; -} - - -void std_enkf_data_free( void * data ) { - free( data ); -} - - - - -static void std_enkf_initX__( matrix_type * X , - matrix_type * S , - matrix_type * R , - matrix_type * E , - matrix_type * D , - double truncation, - int ncomp, - bool bootstrap , - bool use_EE , - bool use_GE) { - - int nrobs = matrix_get_rows( S ); - int ens_size = matrix_get_columns( S ); - int nrmin = util_int_min( ens_size , nrobs); - - matrix_type * W = matrix_alloc(nrobs , nrmin); - double * eig = util_calloc( nrmin , sizeof * eig); - - matrix_subtract_row_mean( S ); /* Shift away the mean */ - - if (use_EE) { - if (use_GE) { - enkf_linalg_lowrankE( S , E , W , eig , truncation , ncomp); - } - else { - matrix_type * Et = matrix_alloc_transpose( E ); - matrix_type * Cee = matrix_alloc_matmul( E , Et ); - matrix_scale( Cee , 1.0 / (ens_size - 1)); - - enkf_linalg_lowrankCinv( S , Cee , W , eig , truncation , ncomp); - - matrix_free( Et ); - matrix_free( Cee ); - } - - } - else { - enkf_linalg_lowrankCinv( S , R , W , eig , truncation , ncomp); - } - - enkf_linalg_init_stdX( X , S , D , W , eig , bootstrap); - - matrix_free( W ); - free( eig ); - enkf_linalg_checkX( X , bootstrap ); -} - - - - - -void std_enkf_initX(void * module_data , - matrix_type * X , - matrix_type * A , - matrix_type * S , - matrix_type * R , - matrix_type * dObs , - matrix_type * E , - matrix_type * D) { - - - std_enkf_data_type * data = std_enkf_data_safe_cast( module_data ); - { - int ncomp = data->subspace_dimension; - double truncation = data->truncation; - - std_enkf_initX__(X,S,R,E,D,truncation,ncomp,false,data->use_EE,data->use_GE); - } -} - - - - - - - -bool std_enkf_set_double( void * arg , const char * var_name , double value) { - std_enkf_data_type * module_data = std_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , ENKF_TRUNCATION_KEY_) == 0) - std_enkf_set_truncation( module_data , value ); - else - name_recognized = false; - - return name_recognized; - } -} - - -bool std_enkf_set_int( void * arg , const char * var_name , int value) { - std_enkf_data_type * module_data = std_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , ENKF_NCOMP_KEY_) == 0) - std_enkf_set_subspace_dimension( module_data , value ); - else - name_recognized = false; - - return name_recognized; - } -} - - -bool std_enkf_set_bool( void * arg , const char * var_name , bool value) { - std_enkf_data_type * module_data = std_enkf_data_safe_cast( arg ); - { - bool name_recognized = true; - - if (strcmp( var_name , USE_EE_KEY_) == 0) - module_data->use_EE = value; - else if (strcmp( var_name , USE_GE_KEY_) == 0) - module_data->use_GE = value; - else if (strcmp( var_name , ANALYSIS_SCALE_DATA_KEY_) == 0) - module_data->analysis_scale_data = value; - else - name_recognized = false; - - return name_recognized; - } -} - - - -long std_enkf_get_options( void * arg , long flag ) { - std_enkf_data_type * module_data = std_enkf_data_safe_cast( arg ); - int scale_option = (module_data->analysis_scale_data) ? ANALYSIS_SCALE_DATA : 0; - return module_data->option_flags + scale_option; -} - -bool std_enkf_has_var( const void * arg, const char * var_name) { - { - if (strcmp(var_name , ENKF_NCOMP_KEY_) == 0) - return true; - else if (strcmp(var_name , ENKF_TRUNCATION_KEY_) == 0) - return true; - else if (strcmp(var_name , USE_EE_KEY_) == 0) - return true; - else if (strcmp(var_name , USE_GE_KEY_) == 0) - return true; - else if (strcmp(var_name , ANALYSIS_SCALE_DATA_KEY_) == 0) - return true; - else - return false; - } -} - -double std_enkf_get_double( const void * arg, const char * var_name) { - const std_enkf_data_type * module_data = std_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , ENKF_TRUNCATION_KEY_) == 0) - return module_data->truncation; - else - return -1; - } -} - -int std_enkf_get_int( const void * arg, const char * var_name) { - const std_enkf_data_type * module_data = std_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , ENKF_NCOMP_KEY_) == 0) - return module_data->subspace_dimension; - else - return -1; - } -} - - -bool std_enkf_get_bool( const void * arg, const char * var_name) { - const std_enkf_data_type * module_data = std_enkf_data_safe_cast_const( arg ); - { - if (strcmp(var_name , USE_EE_KEY_) == 0) - return module_data->use_EE; - else if (strcmp(var_name , USE_GE_KEY_) == 0) - return module_data->use_GE; - else if (strcmp(var_name , ANALYSIS_SCALE_DATA_KEY_) == 0) - return module_data->analysis_scale_data; - else - return false; - } -} - - -/** - gcc -fpic -c -I?? - gcc -shared -o -*/ - - -#ifdef INTERNAL_LINK -#define LINK_NAME STD_ENKF -#else -#define LINK_NAME EXTERNAL_MODULE_SYMBOL -#endif - - -analysis_table_type LINK_NAME = { - .name = "STD_ENKF", - .alloc = std_enkf_data_alloc, - .freef = std_enkf_data_free, - .set_int = std_enkf_set_int , - .set_double = std_enkf_set_double , - .set_bool = std_enkf_set_bool, - .set_string = NULL , - .get_options = std_enkf_get_options , - .initX = std_enkf_initX , - .updateA = NULL, - .init_update = NULL, - .complete_update = NULL, - .has_var = std_enkf_has_var, - .get_int = std_enkf_get_int, - .get_double = std_enkf_get_double, - .get_bool = std_enkf_get_bool, - .get_ptr = NULL, -}; - diff --git a/ThirdParty/Ert/libanalysis/tests/CMakeLists.txt b/ThirdParty/Ert/libanalysis/tests/CMakeLists.txt deleted file mode 100644 index ff75b8e0d0..0000000000 --- a/ThirdParty/Ert/libanalysis/tests/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -ert_module_name( VAR_RML rml_enkf ${LIBRARY_OUTPUT_PATH} ) - -add_executable(analysis_test_external_module analysis_test_external_module.c ) -target_link_libraries( analysis_test_external_module analysis util test_util ) - -add_test( analysis_module_rml ${EXECUTABLE_OUTPUT_PATH}/analysis_test_external_module "RML_ENKF" ${VAR_RML} 41 - ITER:45 - USE_PRIOR:False - LAMBDA_REDUCE:0.10 - LAMBDA_INCREASE:2.5 - ENKF_TRUNCATION:0.77 - LAMBDA0:0.25 - LAMBDA_MIN:0.01 - LOG_FILE:LogFile.txt - CLEAR_LOG:True - LAMBDA_RECALCULATE:True ) - - -add_executable( analysis_test_module_info analysis_test_module_info.c ) -target_link_libraries( analysis_test_module_info analysis util test_util) -add_test( analysis_test_module_info ${EXECUTABLE_OUTPUT_PATH}/analysis_test_module_info ) diff --git a/ThirdParty/Ert/libanalysis/tests/analysis_test_external_module.c b/ThirdParty/Ert/libanalysis/tests/analysis_test_external_module.c deleted file mode 100644 index 01f5a661f8..0000000000 --- a/ThirdParty/Ert/libanalysis/tests/analysis_test_external_module.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'analysis_test_external_module.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include -#include - -#include - - - -void test_set_get(analysis_module_type * module , const char * var_value) { - char * var , *string_value; - util_binary_split_string( var_value , ":" , false , &var , &string_value); - - if (var && string_value) { - printf("Testing variable:%s \n",var); - while (true) { - int int_value; - double double_value; - bool bool_value; - test_assert_true(analysis_module_has_var( module , var )); - - if (util_sscanf_int( string_value , &int_value)) { - test_assert_true(analysis_module_set_var( module , var , string_value )); - test_assert_int_equal( int_value , analysis_module_get_int( module , var )); - break; - } - - if (util_sscanf_double( string_value , &double_value)) { - test_assert_true(analysis_module_set_var( module , var , string_value )); - test_assert_double_equal( double_value , analysis_module_get_double( module , var )); - break; - } - - if (util_sscanf_bool( string_value , &bool_value)) { - test_assert_true(analysis_module_set_var( module , var , string_value )); - test_assert_bool_equal( bool_value , analysis_module_get_bool( module , var )); - break; - } - - - test_assert_true(analysis_module_set_var( module , var , string_value )); - test_assert_string_equal( string_value , (const char *) analysis_module_get_ptr( module , var )); - break; - } - } else { - fprintf(stderr,"Invalid test input data: %s -> could not split in var:value\n" , var_value); - exit(1); - } -} - - - -void load_module( rng_type * rng , const char * user_name , const char * lib_name, const char * options_str , int nvar , const char ** var_list) { - long flags = strtol(options_str , NULL , 10); - analysis_module_type * analysis_module = analysis_module_alloc_external(rng , lib_name); - - printf("Loading:%s \n" , lib_name); - test_assert_string_equal( EXTERNAL_MODULE_NAME , analysis_module_get_table_name(analysis_module)); - if (util_is_abs_path(lib_name)) - test_assert_string_equal( lib_name , analysis_module_get_lib_name(analysis_module)); - - test_assert_true( analysis_module_is_instance( analysis_module)); - { - for (int i=0; i < nvar; i++) - test_set_get( analysis_module , var_list[i] ); - } - test_assert_false( analysis_module_has_var(analysis_module , "DoesNotHaveThisVariable")); - - test_assert_true( analysis_module_check_option( analysis_module , flags)); - flags += 1; - test_assert_false( analysis_module_check_option( analysis_module , flags)); - analysis_module_free( analysis_module); -} - - -int main(int argc , char ** argv) { - const char * user_name = argv[1]; - const char * lib_name = argv[2]; - const char * options_str = argv[3]; - int nvar = argc - 4; - rng_type * rng = rng_alloc( MZRAN , INIT_DEFAULT); - - load_module(rng , user_name , lib_name , options_str , nvar , (const char **) &argv[4]); - rng_free( rng ); - - exit(0); -} diff --git a/ThirdParty/Ert/libanalysis/tests/analysis_test_module_info.c b/ThirdParty/Ert/libanalysis/tests/analysis_test_module_info.c deleted file mode 100644 index 6924263441..0000000000 --- a/ThirdParty/Ert/libanalysis/tests/analysis_test_module_info.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'analysis_test_module_info.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include - - -int main(int argc , char ** argv) { - - const char* ministep_name = "SOME MINISTEP"; - module_info_type * module_info = module_info_alloc( ministep_name ); - test_assert_true( module_info_is_instance( module_info )); - - module_data_block_vector_type * module_data_block_vector = module_info_get_data_block_vector(module_info); - test_assert_true( module_data_block_vector_is_instance( module_data_block_vector )); - - module_obs_block_vector_type * module_obs_block_vector = module_info_get_obs_block_vector(module_info); - test_assert_true( module_obs_block_vector_is_instance( module_obs_block_vector )); - - int index_list[1] = { 1 }; - module_data_block_type * module_data_block = module_data_block_alloc( "PARAMETER", &index_list[0], 0, 1 ); - test_assert_true( module_data_block_is_instance( module_data_block )); - module_data_block_vector_add_data_block(module_data_block_vector, module_data_block); - - - module_obs_block_type * module_obs_block = module_obs_block_alloc( "OBS", &index_list[0], 0, 1 ); - test_assert_true( module_obs_block_is_instance( module_obs_block )); - module_obs_block_vector_add_obs_block(module_obs_block_vector, module_obs_block); - - module_info_free( module_info ); - exit(0); -} - - diff --git a/ThirdParty/Ert/libconfig/CMakeLists.txt b/ThirdParty/Ert/libconfig/CMakeLists.txt deleted file mode 100644 index 6d8bd6b946..0000000000 --- a/ThirdParty/Ert/libconfig/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_subdirectory( src ) -if (BUILD_TESTS) - add_subdirectory( tests ) -endif() diff --git a/ThirdParty/Ert/libconfig/applications/conf_test.c b/ThirdParty/Ert/libconfig/applications/conf_test.c deleted file mode 100644 index 31aa43222f..0000000000 --- a/ThirdParty/Ert/libconfig/applications/conf_test.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'conf_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -int main() -{ - const char * enkf_conf_help = "The main enkf conf shall contain neccessary infomation to run the enkf."; - conf_class_type * enkf_conf_class = conf_class_alloc_empty("ENKF_conf", true, false, enkf_conf_help); - conf_class_set_help(enkf_conf_class, enkf_conf_help); - - /** Create and insert HISTORY_OBSERVATION class. */ - { - const char * help_class_history_observation = "The class HISTORY_OBSERVATION is used to condition on a time series from the production history. The name of the an instance is used to define the item to condition on, and should be in summary.x syntax. E.g., creating a HISTORY_OBSERVATION instance with name GOPR:P4 conditions on GOPR for group P4."; - conf_class_type * history_observation_class = conf_class_alloc_empty("HISTORY_OBSERVATION", false, false, help_class_history_observation); - conf_class_set_help(history_observation_class, help_class_history_observation); - - - const char * help_item_spec_error_mode = "The string ERROR_MODE gives the error mode for the observation."; - conf_item_spec_type * item_spec_error_mode = conf_item_spec_alloc("ERROR_MODE", true, DT_STR, help_item_spec_error_mode); - conf_item_spec_set_help(item_spec_error_mode, help_item_spec_error_mode); - - conf_item_spec_add_restriction(item_spec_error_mode, "rel"); - conf_item_spec_add_restriction(item_spec_error_mode, "abs"); - conf_item_spec_add_restriction(item_spec_error_mode, "relmin"); - - conf_item_spec_set_default_value(item_spec_error_mode, "rel"); - - - const char * help_item_spec_error = "The positive floating number ERROR gives the standard deviation (abs) or the relative uncertainty (rel/relmin) of the observations."; - conf_item_spec_type * item_spec_error = conf_item_spec_alloc("ERROR", true, DT_POSFLOAT, help_item_spec_error); - conf_item_spec_set_default_value(item_spec_error, "0.10"); - conf_item_spec_set_help(item_spec_error, help_item_spec_error); - - const char * help_item_spec_error_min = "The positive floating point number ERROR_MIN gives the minimum value for the standard deviation of the observation when relmin is used."; - conf_item_spec_type * item_spec_error_min = conf_item_spec_alloc("ERROR_MIN", true, DT_POSFLOAT, help_item_spec_error_min); - conf_item_spec_set_default_value(item_spec_error_min, "0.10"); - conf_item_spec_set_help(item_spec_error_min, help_item_spec_error_min); - - - conf_class_insert_owned_item_spec(history_observation_class, item_spec_error_mode); - conf_class_insert_owned_item_spec(history_observation_class, item_spec_error); - conf_class_insert_owned_item_spec(history_observation_class, item_spec_error_min); - - conf_class_insert_owned_sub_class(enkf_conf_class, history_observation_class); - } - - - - /** Create and insert SUMMARY_OBSERVATION class. */ - { - const char * help_class_summary_observation = "The class SUMMARY_OBSERVATION can be used to condition on any observation whos simulated value is written to the summary file."; - conf_class_type * summary_observation_class = conf_class_alloc_empty("SUMMARY_OBSERVATION", false, false, help_class_summary_observation); - conf_class_set_help(summary_observation_class, help_class_summary_observation); - - const char * help_item_spec_value = "The floating point number VALUE gives the observed value."; - conf_item_spec_type * item_spec_value = conf_item_spec_alloc("VALUE", true, DT_FLOAT, help_item_spec_value); - conf_item_spec_set_help(item_spec_value, help_item_spec_value); - - - const char * help_item_spec_error = "The positive floating point number ERROR is the standard deviation of the observed value."; - conf_item_spec_type * item_spec_error = conf_item_spec_alloc("ERROR", true, DT_POSFLOAT, help_item_spec_error); - conf_item_spec_set_help(item_spec_error, help_item_spec_error); - - const char * help_item_spec_date = "The DATE item gives the date of the observation. Format is dd/mm/yyyy."; - conf_item_spec_type * item_spec_date = conf_item_spec_alloc("DATE", false, DT_DATE, help_item_spec_date); - conf_item_spec_set_help(item_spec_date, help_item_spec_date); - - const char * help_item_spec_days = "The DAYS item gives the observation time as days after simulation start."; - conf_item_spec_type * item_spec_days = conf_item_spec_alloc("DAYS", false, DT_POSFLOAT, help_item_spec_days); - conf_item_spec_set_help(item_spec_days, help_item_spec_days); - - const char * help_item_spec_restart = "The RESTART item gives the observation time as the ECLIPSE restart nr."; - conf_item_spec_type * item_spec_restart = conf_item_spec_alloc("RESTART", false, DT_POSINT, help_item_spec_restart); - conf_item_spec_set_help(item_spec_restart, help_item_spec_restart); - - const char * help_item_spec_sumkey = "The string SUMMARY_KEY is used to look up the simulated value in the summary file. It has the same format as the summary.x program, e.g. WOPR:P4"; - conf_item_spec_type * item_spec_sumkey = conf_item_spec_alloc("KEY", true, DT_STR, help_item_spec_sumkey); - conf_item_spec_set_help(item_spec_sumkey, help_item_spec_sumkey); - - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_value); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_error); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_date); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_days); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_restart); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_sumkey); - - /** Create a mutex on DATE, DAYS and RESTART. */ - conf_item_mutex_type * time_mutex = conf_class_new_item_mutex(summary_observation_class , true , false); - - conf_item_mutex_add_item_spec(time_mutex, item_spec_date); - conf_item_mutex_add_item_spec(time_mutex, item_spec_days); - conf_item_mutex_add_item_spec(time_mutex, item_spec_restart); - - - - - conf_class_insert_owned_sub_class(enkf_conf_class, summary_observation_class); - } - - - - /** Create and insert BLOCK_OBSERVATION class. */ - { - const char * help_class_block_observation = "The class BLOCK_OBSERVATION can be used to condition on an observation whos simulated values are block/cell values of a field, e.g. RFT tests."; - conf_class_type * block_observation_class = conf_class_alloc_empty("BLOCK_OBSERVATION", false, false, help_class_block_observation); - conf_class_set_help(block_observation_class, help_class_block_observation); - - const char * help_item_spec_field = "The item FIELD gives the observed field. E.g., ECLIPSE fields such as PRESSURE, SGAS or any user defined fields such as PORO or PERMX."; - conf_item_spec_type * item_spec_field = conf_item_spec_alloc("FIELD", true, DT_STR, help_item_spec_field); - conf_item_spec_set_help(item_spec_field, help_item_spec_field); - - const char * help_item_spec_date = "The DATE item gives the date of the observation. Format is dd/mm/yyyy."; - conf_item_spec_type * item_spec_date = conf_item_spec_alloc("DATE", true, DT_DATE, help_item_spec_date); - conf_item_spec_set_help(item_spec_date, help_item_spec_date); - - conf_class_insert_owned_item_spec(block_observation_class, item_spec_field); - conf_class_insert_owned_item_spec(block_observation_class, item_spec_date); - - /** Create and insert the sub class OBS. */ - { - const char * help_class_obs = "The class OBS is used to specify a single observed point."; - conf_class_type * obs_class = conf_class_alloc_empty("OBS", true, true , help_class_obs); - conf_class_set_help(obs_class, help_class_obs); - - const char * help_item_i = "The item I gives the I index of the block observation."; - conf_item_spec_type * item_spec_i = conf_item_spec_alloc("I", true, DT_POSINT, help_item_i); - conf_item_spec_set_help(item_spec_i, help_item_i); - - const char * help_item_j = "The item J gives the J index of the block observation."; - conf_item_spec_type * item_spec_j = conf_item_spec_alloc("J", true, DT_POSINT, help_item_j); - conf_item_spec_set_help(item_spec_j, help_item_j); - - const char * help_item_k = "The item K gives the K index of the block observation."; - conf_item_spec_type * item_spec_k = conf_item_spec_alloc("K", true, DT_POSINT, help_item_k); - conf_item_spec_set_help(item_spec_k, help_item_k); - - const char * help_item_spec_value = "The floating point number VALUE gives the observed value."; - conf_item_spec_type * item_spec_value = conf_item_spec_alloc("VALUE", true, DT_FLOAT, help_item_spec_value); - conf_item_spec_set_help(item_spec_value, help_item_spec_value); - - const char * help_item_spec_error = "The positive floating point number ERROR is the standard deviation of the observed value."; - conf_item_spec_type * item_spec_error = conf_item_spec_alloc("ERROR", true, DT_POSFLOAT, help_item_spec_error); - conf_item_spec_set_help(item_spec_error, help_item_spec_error); - - conf_class_insert_owned_item_spec(obs_class, item_spec_i); - conf_class_insert_owned_item_spec(obs_class, item_spec_j); - conf_class_insert_owned_item_spec(obs_class, item_spec_k); - conf_class_insert_owned_item_spec(obs_class, item_spec_value); - conf_class_insert_owned_item_spec(obs_class, item_spec_error); - - conf_class_insert_owned_sub_class(block_observation_class, obs_class); - } - - conf_class_insert_owned_sub_class(enkf_conf_class, block_observation_class); - } - - - - /** Try to create an instance of the enkf_conf_class. */ - - conf_instance_type * enkf_conf = conf_instance_alloc_from_file(enkf_conf_class, "enkf_conf", "testcase/test.txt"); - conf_instance_type * enkf_conf2 = conf_instance_alloc_from_file(enkf_conf_class, "enkf_conf2", "testcase/test2.txt"); - - /** Validate enkf_conf_class. */ - - conf_instance_validate(enkf_conf); - conf_instance_validate(enkf_conf2); - - /** Overload. */ - conf_instance_overload(enkf_conf, enkf_conf2); - - - /** Print the name of the HISTORY_OBSERVATION instances. */ - { - stringlist_type * history_observations = conf_instance_alloc_list_of_sub_instances_of_class_by_name(enkf_conf, "HISTORY_OBSERVATION"); - - int num_history_observations = stringlist_get_size(history_observations); - - for(int obs_nr = 0; obs_nr < num_history_observations ; obs_nr++) - { - printf("%2i. %s\n", obs_nr, stringlist_iget(history_observations, obs_nr)); - const conf_instance_type * sched_obs = conf_instance_get_sub_instance_ref(enkf_conf, stringlist_iget(history_observations, obs_nr)); - double error = conf_instance_get_item_value_double(sched_obs, "ERROR"); - printf(" std.dev : %f\n", error); - } - - stringlist_free(history_observations); - } - - - /** Clean up. */ - - conf_instance_free(enkf_conf); - conf_instance_free(enkf_conf2); - conf_class_free(enkf_conf_class); - -} diff --git a/ThirdParty/Ert/libconfig/applications/config_test.c b/ThirdParty/Ert/libconfig/applications/config_test.c deleted file mode 100644 index 7a2a14ff77..0000000000 --- a/ThirdParty/Ert/libconfig/applications/config_test.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'config_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - - -int main(void) { - const char * config_file = "config_test_input"; - config_parser_type * config = config_alloc(); - config_schema_item_type * item; - - item = config_add_schema_item(config , "KEY1" , true , true); - item = config_add_schema_item(config , "KEY2" , true , false); - config_schema_item_set_argc_minmax(item , 1 , 4 , 4 , (const config_item_types [4]) {CONFIG_EXECUTABLE , CONFIG_EXISTING_FILE , CONFIG_BOOLEAN , CONFIG_BOOLEAN}); - - - item = config_add_schema_item(config , "FATHER" , false , false); - { - stringlist_type * children = stringlist_alloc_argv_ref( (const char *[2]) {"CHILD1" , "CHILD2"} , 2); - config_schema_item_set_required_children(item , children); - stringlist_free(children); - } - item = config_add_schema_item(config , "CHILD1" , false , false); - config_schema_item_set_argc_minmax(item , 1 , 1 , 1 , (const config_item_types [1]) {CONFIG_INT}); - - config_parse(config , config_file , "--" , "INCLUDE" , NULL , true, true); - - - - { - stringlist_type * sl = config_alloc_complete_stringlist(config , "KEY1"); - char * s = stringlist_alloc_joined_string(sl , "|"); - printf("KEY1 -> \"%s\" \n",s); - printf("CONFIG_IGET:%s\n" , config_iget(config , "KEY2" , 0 , 0)); - free(s); - stringlist_free(sl); - } - - - config_free(config); -} diff --git a/ThirdParty/Ert/libconfig/include/ert/config/conf.h b/ThirdParty/Ert/libconfig/include/ert/config/conf.h deleted file mode 100644 index aad3e275ab..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/conf.h +++ /dev/null @@ -1,354 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'conf.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CONF_H -#define ERT_CONF_H - -/* libconfig: lightweight configuration parser - * - * - * - * Introduction - * - * This library provides a lightweight configuration parser for the - * enkf application. The goal of the library is to provide the - * developer with a tool for rapid specification of configuration - * files, automatic checking of user provided configuration files - * and typed access to configuration items. - * - * - * - * A Simple Example - * - * Let us consider a simple example of user provided configuration - * file that can be used with the parser: - * - * - * res_sim FrontSim2007 - * { - * executable = /bin/frontsim2007; - * version = 2007; - * - * run_host bgo179lin - * { - * hostname = bgo179lin.nho.hydro.com; - * num_jobs = 4; - * }; - * }; - * - * - * Note that the newlines are not neccessary. In the example above, - * the user has provided an instance of the class "res_sim" with name - * FrontSim2007. Further, the user has set the items executable and version. - * He has also provided a instance of the sub class "run_host" with name - * bgo179lin and allocated 4 jobs to this machine. - * - * - * - * Structure - * - * The system is built around four basic objects: - * - * - Class definitions. - * - Item specifications. - * - Instances of classes. - * - Instances of item specifications, i.e. items. - * - * The relationship between the objects is as follows : - * - * - Class: - * . Can have contain both classes and item specifications. - * . Can not contain items or class instances. - * - * - Item specifications: - * . Can not contain any of the other objects. - * - * - Instances of classes: - * . Can contain class instances and items. - * - * - Items: - * . Can not contain any of the other objects. - * - * - * - * General Use - * - * The parser is designed to be used in the following way: - * - * - The developer creates the classes and item specifications needed. - * - Using the library and the classes, user provided configuration - * files are read and validated. - * - If the validation fails, the developer can choose to exit. - * - Using the library, the devloper has typed access to all - * information provided by the user. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include - -#include - - - -typedef struct conf_class_struct conf_class_type; -typedef struct conf_instance_struct conf_instance_type; -typedef struct conf_item_spec_struct conf_item_spec_type; -typedef struct conf_item_struct conf_item_type; -typedef struct conf_item_mutex_struct conf_item_mutex_type; - - -/** D E F A U L T A L L O C / F R E E F U N C T I O N S */ - - - -conf_class_type * conf_class_alloc_empty( - const char * class_name, - bool require_instance, - bool singleton, - const char * help); - -void conf_class_free( - conf_class_type * conf_class); - -void conf_class_free__( - void * conf_class); - - - -conf_instance_type * conf_instance_alloc_default( - const conf_class_type * conf_class, - const char * name); - -conf_instance_type * conf_instance_copyc( - const conf_instance_type * conf_instance); - -void conf_instance_free( - conf_instance_type * conf_instance); - -void conf_instance_free__( - void * conf_instance); - - - -conf_item_spec_type * conf_item_spec_alloc( - char * name, - bool required_set, - dt_enum dt, - const char * help); - -void conf_item_spec_free( - conf_item_spec_type * conf_item_spec); - -void conf_item_spec_free__( - void * conf_item_spec); - - - -conf_item_type * conf_item_alloc( - const conf_item_spec_type * conf_item_spec, - const char * value); - -conf_item_type * conf_item_copyc( - const conf_item_type * conf_item); - -void conf_item_free( - conf_item_type * conf_item); - -void conf_item_free__( - void * conf_item); - - - -void conf_item_mutex_free( - conf_item_mutex_type * conf_item_mutex); - -void conf_item_mutex_free__( - void * conf_item_mutex); - - - -/** M A N I P U L A T O R S , I N S E R T I O N */ - - - -void conf_class_insert_owned_sub_class( - conf_class_type * conf_class, - conf_class_type * sub_conf_class); - -void conf_class_insert_owned_item_spec( - conf_class_type * conf_class, - conf_item_spec_type * item_spec); - -void conf_instance_insert_owned_sub_instance( - conf_instance_type * conf_instance, - conf_instance_type * sub_conf_instance); - -void conf_instance_insert_owned_item( - conf_instance_type * conf_instance, - conf_item_type * conf_item); - -void conf_instance_insert_item( - conf_instance_type * conf_instance, - const char * item_name, - const char * value); - -void conf_instance_overload( - conf_instance_type * conf_instance_target, - const conf_instance_type * conf_instance_source); - -conf_item_mutex_type * conf_class_new_item_mutex( - conf_class_type * conf_class, - bool require_one, - bool inverse); - -void conf_item_mutex_add_item_spec( - conf_item_mutex_type * conf_item_mutex, - const conf_item_spec_type * conf_item_spec); - - - -/** M A N I P U L A T O R S , C L A S S A N D I T E M S P E C I F I C A T I O N */ - - - -void conf_class_set_help( - conf_class_type * conf_class, - const char * help); - - - -void conf_item_spec_add_restriction( - conf_item_spec_type * conf_item_spec, - const char * restriction); - -void conf_item_spec_set_default_value( - conf_item_spec_type * conf_item_spec, - const char * default_value); - -void conf_item_spec_set_help( - conf_item_spec_type * conf_item_spec, - const char * help); - - - -/** A C C E S S O R S */ - - - -bool conf_class_has_item_spec( - const conf_class_type * conf_class, - const char * item_name); - -bool conf_class_has_sub_class( - const conf_class_type * conf_class, - const char * sub_class_name); - -const conf_item_spec_type * conf_class_get_item_spec_ref( - const conf_class_type * conf_class, - const char * item_name); - -const conf_class_type * conf_class_get_sub_class_ref( - const conf_class_type * conf_class, - const char * sub_class_name); - - - -const char * conf_instance_get_name_ref( - const conf_instance_type * conf_instance); - -bool conf_instance_is_of_class( - const conf_instance_type * conf_instance, - const char * class_name); - -bool conf_instance_has_item( - const conf_instance_type * conf_instance, - const char * item_name); - -bool conf_instance_has_sub_instance( - const conf_instance_type * conf_instance, - const char * sub_instance_name); - -const conf_instance_type * conf_instance_get_sub_instance_ref( - const conf_instance_type * conf_instance, - const char * sub_instance_name); - -stringlist_type * conf_instance_alloc_list_of_sub_instances_of_class( - const conf_instance_type * conf_instance, - const conf_class_type * conf_class); - -stringlist_type * conf_instance_alloc_list_of_sub_instances_of_class_by_name( - const conf_instance_type * conf_instance, - const char * sub_class_name); - -const conf_class_type * conf_instance_get_class_ref( - const conf_instance_type * conf_instance); - -const char * conf_instance_get_class_name_ref( - const conf_instance_type * conf_instance); - -const char * conf_instance_get_item_value_ref( - const conf_instance_type * conf_instance, - const char * item_name); - -/** If the dt supports it, these functions will parse the item - value to the requested types. - - NOTE: - If the dt does not support it, or the conf_instance - does not have the item, the functions will abort your program. -*/ -int conf_instance_get_item_value_int( - const conf_instance_type * conf_instance, - const char * item_name); - -double conf_instance_get_item_value_double( - const conf_instance_type * conf_instance, - const char * item_name); - -time_t conf_instance_get_item_value_time_t( - const conf_instance_type * conf_instance, - const char * item_name); - -/** V A L I D A T O R S */ - - - -bool conf_instance_validate( - const conf_instance_type * conf_instance); - - - -/** A L L O C F R O M F I L E */ - - -conf_instance_type * conf_instance_alloc_from_file( - const conf_class_type * conf_class, - const char * name, - const char * file_name); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libconfig/include/ert/config/conf_data.h b/ThirdParty/Ert/libconfig/include/ert/config/conf_data.h deleted file mode 100644 index 96f3c79377..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/conf_data.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'conf_data.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CONF_DATA_H -#define ERT_CONF_DATA_H -#include -#include - -typedef enum { - DT_STR, - DT_INT, - DT_POSINT, - DT_FLOAT, - DT_POSFLOAT, - DT_FILE, - DT_EXEC, - DT_FOLDER, - DT_DATE - } dt_enum; - -dt_enum conf_data_get_dt_from_string( - const char * str); - -bool conf_data_string_is_dt( - const char * str); - -const char * conf_data_get_dt_name_ref( - dt_enum dt); - -bool conf_data_validate_string_as_dt_value( - dt_enum dt, - const char * str); - -int conf_data_get_int_from_string( - dt_enum dt, - const char * str); - -double conf_data_get_double_from_string( - dt_enum dt, - const char * str); - -time_t conf_data_get_time_t_from_string( - dt_enum dt, - const char * str); - -#endif diff --git a/ThirdParty/Ert/libconfig/include/ert/config/conf_util.h b/ThirdParty/Ert/libconfig/include/ert/config/conf_util.h deleted file mode 100644 index 9fbc5dfb93..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/conf_util.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'conf_util.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CONF_UTIL_H -#define ERT_CONF_UTIL_H - -char * conf_util_fscanf_alloc_token_buffer( const char * file_name ); - -char * conf_util_alloc_next_token( char ** buffer_position ); - -#endif diff --git a/ThirdParty/Ert/libconfig/include/ert/config/config_content.h b/ThirdParty/Ert/libconfig/include/ert/config/config_content.h deleted file mode 100644 index dc86388407..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/config_content.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'config_content.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_CONFIG_CONTENT_H -#define ERT_CONFIG_CONTENT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include -#include -#include -#include - -typedef struct config_content_struct config_content_type; - - - config_content_type * config_content_alloc(const char * filename); - void config_content_free( config_content_type * content ); - void config_content_set_valid( config_content_type * content); - bool config_content_is_valid( const config_content_type * content ); - bool config_content_has_item( const config_content_type * content , const char * key); - void config_content_add_item( config_content_type * content , const config_schema_item_type * schema_item , const config_path_elm_type * path_elm); - config_content_item_type * config_content_get_item( const config_content_type * content , const char * key); - void config_content_add_node( config_content_type * content , config_content_node_type * content_node ); - config_error_type * config_content_get_errors( const config_content_type * content); - - const char * config_content_iget( const config_content_type * content , const char * key , int occurence , int index); - int config_content_iget_as_int( const config_content_type * content , const char * key , int occurence , int index); - bool config_content_iget_as_bool( const config_content_type * content , const char * key , int occurence , int index); - double config_content_iget_as_double( const config_content_type * content , const char * key , int occurence , int index); - const char * config_content_iget_as_path( const config_content_type * content , const char * key , int occurence , int index); - const char * config_content_safe_iget(const config_content_type * content , const char *kw, int occurence , int index); - int config_content_get_occurences(const config_content_type * content, const char * kw); - - bool config_content_get_value_as_bool(const config_content_type * config , const char * kw); - int config_content_get_value_as_int(const config_content_type * config , const char * kw); - double config_content_get_value_as_double(const config_content_type * config , const char * kw); - const char * config_content_get_value_as_path( const config_content_type * config , const char * kw); - const char * config_content_get_value_as_abspath( const config_content_type * config , const char * kw); - const char * config_content_get_value_as_relpath( const config_content_type * config , const char * kw); - const char * config_content_get_value(const config_content_type * config , const char * kw); - char * config_content_alloc_joined_string(const config_content_type * content , const char * kw, const char * sep); - stringlist_type * config_content_alloc_complete_stringlist(const config_content_type * content , const char * kw); - const stringlist_type * config_content_iget_stringlist_ref(const config_content_type * content , const char * kw, int occurence); - config_content_node_type * config_content_get_value_node( const config_content_type * content , const char * kw); - void config_content_add_define( config_content_type * content , const char * key , const char * value ); - subst_list_type * config_content_get_define_list( config_content_type * content ); - const char * config_content_get_config_file( const config_content_type * content , bool abs_path ); - int config_content_get_size(const config_content_type * content); - const config_content_node_type * config_content_iget_node( const config_content_type * content , int index); - bool config_content_add_file( config_content_type * content , const char * config_file); - config_root_path_type * config_content_get_invoke_path( config_content_type * content ); - config_path_elm_type * config_content_add_path_elm( config_content_type * content , const char * path ); - void config_content_pop_path_stack( config_content_type * content ); - const stringlist_type * config_content_get_warnings( const config_content_type * content); - - UTIL_IS_INSTANCE_HEADER( config_content ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libconfig/include/ert/config/config_content_item.h b/ThirdParty/Ert/libconfig/include/ert/config/config_content_item.h deleted file mode 100644 index 40b843ff93..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/config_content_item.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_content_item.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_CONFIG_CONTENT_ITEM_H -#define ERT_CONFIG_CONTENT_ITEM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include -#include -#include -#include - -typedef struct config_content_item_struct config_content_item_type; - - int config_content_item_get_size(const config_content_item_type * item); - config_content_node_type * config_content_item_get_last_node(const config_content_item_type * item); - config_content_node_type * config_content_item_iget_node(const config_content_item_type * item , int index); - const config_content_node_type * config_content_item_get_last_node_const(const config_content_item_type * item); - const config_content_node_type * config_content_item_iget_node_const(const config_content_item_type * item , int index); - char * config_content_item_ialloc_joined_string(const config_content_item_type * item , const char * sep , int occurence); - char * config_content_item_alloc_joined_string(const config_content_item_type * item , const char * sep); - const stringlist_type * config_content_item_iget_stringlist_ref(const config_content_item_type * item, int occurence); - const stringlist_type * config_content_item_get_stringlist_ref(const config_content_item_type * item); - stringlist_type * config_content_item_alloc_complete_stringlist(const config_content_item_type * item, bool copy); - stringlist_type * config_content_item_alloc_stringlist(const config_content_item_type * item, bool copy); - hash_type * config_content_item_alloc_hash(const config_content_item_type * item , bool copy); - const char * config_content_item_iget(const config_content_item_type * item , int occurence , int index); - bool config_content_item_iget_as_bool(const config_content_item_type * item, int occurence , int index); - int config_content_item_iget_as_int(const config_content_item_type * item, int occurence , int index); - double config_content_item_iget_as_double(const config_content_item_type * item, int occurence , int index); - void config_content_item_clear( config_content_item_type * item ); - void config_content_item_free( config_content_item_type * item ); - void config_content_item_free__( void * arg ); - config_content_item_type * config_content_item_alloc( const config_schema_item_type * schema , const config_path_elm_type * path_elm); - void config_content_item_validate(const config_content_item_type * item, config_error_type * error); - config_content_node_type * config_content_item_alloc_node( const config_content_item_type * item , const config_path_elm_type * path_elm); - const config_schema_item_type * config_content_item_get_schema( const config_content_item_type * item ); - const config_path_elm_type * config_content_item_get_path_elm( const config_content_item_type * item ); - - UTIL_IS_INSTANCE_HEADER( config_content_item ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libconfig/include/ert/config/config_content_node.h b/ThirdParty/Ert/libconfig/include/ert/config/config_content_node.h deleted file mode 100644 index 954777c430..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/config_content_node.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_content_node.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_CONFIG_CONTENT_NODE_H -#define ERT_CONFIG_CONTENT_NODE_H - -#ifdef __cplusplus -define extern "C" { -#endif - -#include - -#include -#include - -typedef struct config_content_node_struct config_content_node_type; - - config_item_types config_content_node_iget_type( const config_content_node_type * node , int index); - config_content_node_type * config_content_node_alloc( const config_schema_item_type * schema , const config_path_elm_type * cwd); - void config_content_node_add_value(config_content_node_type * node , const char * value); - void config_content_node_set(config_content_node_type * node , const stringlist_type * token_list); - char * config_content_node_alloc_joined_string(const config_content_node_type * node, const char * sep); - void config_content_node_free(config_content_node_type * node); - void config_content_node_free__(void * arg); - const char * config_content_node_get_full_string( config_content_node_type * node , const char * sep ); - const char * config_content_node_iget(const config_content_node_type * node , int index); - bool config_content_node_iget_as_bool(const config_content_node_type * node , int index); - int config_content_node_iget_as_int(const config_content_node_type * node , int index); - double config_content_node_iget_as_double(const config_content_node_type * node , int index); - const char * config_content_node_iget_as_path(config_content_node_type * node , int index); - const char * config_content_node_iget_as_abspath( config_content_node_type * node , int index); - const char * config_content_node_iget_as_relpath( config_content_node_type * node , int index); - time_t config_content_node_iget_as_isodate(const config_content_node_type * node , int index); - const stringlist_type * config_content_node_get_stringlist( const config_content_node_type * node ); - const char * config_content_node_safe_iget(const config_content_node_type * node , int index); - int config_content_node_get_size( const config_content_node_type * node ); - const char * config_content_node_get_kw( const config_content_node_type * node ); - void config_content_node_assert_key_value( const config_content_node_type * node ); - const config_path_elm_type * config_content_node_get_path_elm( const config_content_node_type * node ); - void config_content_node_init_opt_hash( const config_content_node_type * node , hash_type * opt_hash , int elm_offset); - void config_content_node_fprintf( const config_content_node_type * node , FILE * stream ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libconfig/include/ert/config/config_error.h b/ThirdParty/Ert/libconfig/include/ert/config/config_error.h deleted file mode 100644 index d634a2859d..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/config_error.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_error.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CONFIG_ERROR_H -#define ERT_CONFIG_ERROR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -typedef struct config_error_struct config_error_type; - - - config_error_type * config_error_alloc(); - config_error_type * config_error_alloc_copy( const config_error_type * src_error); - void config_error_free(config_error_type * error); - const char * config_error_iget(const config_error_type * error , int index); - void config_error_add( config_error_type * error , char * new_error ); - void config_error_clear( config_error_type * error ); - int config_error_count( const config_error_type * error ); - void config_error_fprintf( const config_error_type * error , bool add_count , FILE * stream ); - bool config_error_equal( const config_error_type * error1 , const config_error_type * error2); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libconfig/include/ert/config/config_parser.h b/ThirdParty/Ert/libconfig/include/ert/config/config_parser.h deleted file mode 100644 index 52f77bef65..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/config_parser.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CONFIG_H -#define ERT_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#define ECL_COM_KW "--" -#define ENKF_COM_KW "--" - - - - - -typedef struct config_parser_struct config_parser_type; - - - void config_free(config_parser_type *); - config_parser_type * config_alloc( ); - char ** config_alloc_active_list(const config_parser_type * , int * ); - config_content_type * config_parse(config_parser_type * config, const char * filename, const char * comment_string, const char * include_kw, const char * define_kw, const hash_type * pre_defined_kw_map, config_schema_unrecognized_enum unrecognized_behaviour , bool validate); - bool config_has_schema_item(const config_parser_type * config , const char * kw); - -/*****************************************************************/ - - config_schema_item_type * config_get_schema_item(const config_parser_type *, const char *); - bool config_item_set(const config_parser_type * , const char * ); - void config_add_alias(config_parser_type * , const char * , const char * ); - void config_install_message(config_parser_type * , const char * , const char * ); - const char * config_safe_get(const config_parser_type * , const char *); - char * config_alloc_joined_string(const config_parser_type * , const char * , const char * ); - - void config_add_define( config_parser_type * config , const char * key , const char * value ); - - /* - bool config_schema_item_is_set(const config_schema_item_type * ); - void config_schema_item_set_argc_minmax(config_schema_item_type * , int , int , int type_map_size , const config_item_types * ); - void config_schema_item_set_common_selection_set(config_schema_item_type * , int argc , const char ** argv); - void config_schema_item_set_indexed_selection_set(config_schema_item_type * item , int , int , const char ** ); - void config_schema_item_set_required_children(config_schema_item_type * , stringlist_type * ); - void config_schema_item_set_required_children_on_value(config_schema_item_type * , const char * , stringlist_type * ); - void config_schema_item_add_required_children(config_schema_item_type * item , const char * child_key); - */ - - config_schema_item_type * config_add_schema_item(config_parser_type * config, - const char * kw, - bool required); - - - stringlist_type * config_alloc_complete_stringlist(const config_parser_type * , const char * ); - stringlist_type * config_alloc_stringlist(const config_parser_type * config , const char * ); - hash_type * config_alloc_hash(const config_parser_type * , const char * ); - const stringlist_type * config_iget_stringlist_ref(const config_parser_type * , const char * , int ); - - int config_get_occurences(const config_parser_type * , const char * ); - int config_get_occurence_size( const config_parser_type * config , const char * kw , int occurence); - - bool config_has_content_item( const config_parser_type * config , const char * input_kw); - config_content_item_type * config_get_content_item( const config_parser_type * config , const char * input_kw); - config_schema_item_type * config_add_key_value( config_parser_type * config , const char * key , bool required , config_item_types item_type); -; - const char * config_get_value_as_relpath( const config_parser_type * config , const char * kw); - const char * config_get_value_as_path( const config_parser_type * config , const char * kw); - const char * config_get_value(const config_parser_type * config , const char * kw); - - const subst_list_type * config_get_define_list( const config_parser_type * config); - int config_get_schema_size( const config_parser_type * config ); - config_content_node_type * config_get_value_node( const config_parser_type * config , const char * kw); - void config_parser_deprecate(config_parser_type * config , const char * kw, const char * msg); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libconfig/include/ert/config/config_path_elm.h b/ThirdParty/Ert/libconfig/include/ert/config/config_path_elm.h deleted file mode 100644 index 7a50066d0a..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/config_path_elm.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'config_path_elm.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CONFIG_PATH_ELM_H -#define ERT_CONFIG_PATH_ELM_H - -#ifdef __cplusplus -extern "C" -#endif - -#include - -typedef struct config_path_elm_struct config_path_elm_type; - -void config_path_elm_free( config_path_elm_type * path_elm ); -void config_path_elm_free__( void * arg ); -config_path_elm_type * config_path_elm_alloc( const config_root_path_type * root_path , const char * path); -const char * config_path_elm_get_abspath( const config_path_elm_type * path_elm ); -const char * config_path_elm_get_relpath( const config_path_elm_type * path_elm ); -const config_root_path_type * config_path_elm_get_rootpath( const config_path_elm_type * path_elm ); -char * config_path_elm_alloc_abspath(const config_path_elm_type * path_elm , const char * input_path); -char * config_path_elm_alloc_relpath(const config_path_elm_type * path_elm , const char * input_path); -char * config_path_elm_alloc_path(const config_path_elm_type * path_elm , const char * input_path); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libconfig/include/ert/config/config_root_path.h b/ThirdParty/Ert/libconfig/include/ert/config/config_root_path.h deleted file mode 100644 index 723b64ed25..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/config_root_path.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'config_root_path.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CONFIG_ROOT_PATH_H -#define ERT_CONFIG_ROOT_PATH_H - -#ifdef __cplusplus -extern "C" -#endif - - -typedef struct config_root_path_struct config_root_path_type; - -void config_root_path_free( config_root_path_type * root_path ); -config_root_path_type * config_root_path_alloc( const char * input_path ); -void config_root_path_printf( const config_root_path_type * root_path ); -const char * config_root_path_get_input_path( const config_root_path_type * root_path ); -const char * config_root_path_get_rel_path( const config_root_path_type * root_path ); -const char * config_root_path_get_abs_path( const config_root_path_type * root_path ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libconfig/include/ert/config/config_schema_item.h b/ThirdParty/Ert/libconfig/include/ert/config/config_schema_item.h deleted file mode 100644 index 695f2cfef7..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/config_schema_item.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_schema_item.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_CONFIG_SCHEMA_ITEM_H -#define ERT_CONFIG_SCHEMA_ITEM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include - -/** - Types used for validation of config items. -*/ -typedef enum { - CONFIG_STRING = 1, - CONFIG_INT = 2, - CONFIG_FLOAT = 4, - CONFIG_PATH = 8, - CONFIG_EXISTING_PATH = 16, - CONFIG_BOOL = 32, - CONFIG_CONFIG = 64, - CONFIG_BYTESIZE = 128, - CONFIG_EXECUTABLE = 256, - CONFIG_ISODATE = 512, - CONFIG_INVALID = 1024 -} config_item_types; - - -typedef enum { - CONFIG_UNRECOGNIZED_IGNORE = 0, - CONFIG_UNRECOGNIZED_WARN = 1, - CONFIG_UNRECOGNIZED_ERROR = 2 -} config_schema_unrecognized_enum; - - - -#define CONFIG_DEFAULT_ARG_MIN -1 -#define CONFIG_DEFAULT_ARG_MAX -1 - - - - typedef struct config_schema_item_struct config_schema_item_type; - - - config_schema_item_type * config_schema_item_alloc(const char * kw , bool required); - bool config_schema_item_validate_set(const config_schema_item_type * item , - stringlist_type * token_list , - const char * config_file, - const config_path_elm_type * path_elm, - config_error_type * error_list); - - void config_schema_item_free( config_schema_item_type * item); - void config_schema_item_free__ (void * void_item); - - void config_schema_item_set_required_children_on_value(config_schema_item_type * item , const char * value , stringlist_type * child_list); - void config_schema_item_set_common_selection_set(config_schema_item_type * item , int argc , const char ** argv); - void config_schema_item_set_indexed_selection_set(config_schema_item_type * item , int index , int argc , const char ** argv); - void config_schema_item_add_indexed_alternative(config_schema_item_type * item , int index , const char * value); - void config_schema_item_set_required_children(config_schema_item_type * item , stringlist_type * stringlist); - void config_schema_item_add_required_children(config_schema_item_type * item , const char * child_key); - void config_schema_item_set_envvar_expansion( config_schema_item_type * item , bool expand_envvar ); - void config_schema_item_set_argc_minmax(config_schema_item_type * item , - int argc_min , - int argc_max); - void config_schema_item_assure_type(const config_schema_item_type * item , int index , int type_mask); - - int config_schema_item_num_required_children(const config_schema_item_type * item); - const char * config_schema_item_iget_required_child( const config_schema_item_type * item , int index); - const char * config_schema_item_get_kw( const config_schema_item_type * item ); - bool config_schema_item_required( const config_schema_item_type * item ); - bool config_schema_item_expand_envvar( const config_schema_item_type * item ); - void config_schema_item_get_argc( const config_schema_item_type * item , int *argc_min , int *argc_max); - bool config_schema_item_has_required_children_value( const config_schema_item_type * item ); - stringlist_type * config_schema_item_get_required_children_value(const config_schema_item_type * item , const char * value); - - void config_schema_item_iset_type( config_schema_item_type * item , int index , config_item_types type); - config_item_types config_schema_item_iget_type(const config_schema_item_type * item , int index ); - void config_schema_item_set_default_type( config_schema_item_type * item , config_item_types type); - bool config_schema_item_is_deprecated( const config_schema_item_type * item); - const char * config_schema_item_get_deprecate_msg( const config_schema_item_type * item); - void config_schema_item_set_deprecated( config_schema_item_type * item , const char * msg); - bool config_schema_item_valid_string(config_item_types value_type , const char * value); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libconfig/include/ert/config/config_settings.h b/ThirdParty/Ert/libconfig/include/ert/config/config_settings.h deleted file mode 100644 index cde4938332..0000000000 --- a/ThirdParty/Ert/libconfig/include/ert/config/config_settings.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (C) 2017 Statoil ASA, Norway. - - The file 'config_settings.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CONFIG_SETTINGS_H -#define ERT_CONFIG_SETTINGS_H - -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include - -#include -#include -#include - -typedef struct config_settings_struct config_settings_type; - -config_settings_type * config_settings_alloc( const char * root_key ); -void config_settings_free( config_settings_type * settings); -bool config_settings_has_key( const config_settings_type * settings , const char * key); -config_item_types config_settings_get_value_type( const config_settings_type * config_settings , const char * key); -bool config_settings_set_value( const config_settings_type * config_settings , const char * key, const char * value); -void config_settings_init_parser( const config_settings_type * config_settings, config_parser_type * config , bool required); -void config_settings_init_parser__( const char * root_key , config_parser_type * config , bool required); -void config_settings_apply(config_settings_type * config_settings , const config_content_type * config ); -stringlist_type * config_settings_alloc_keys( const config_settings_type * config_settings ); - -bool config_settings_add_setting(config_settings_type * settings , const char* key, config_item_types value_type , const char* initial_value); -void config_settings_add_int_setting(config_settings_type * settings , const char* key, int initial_value); -void config_settings_add_double_setting(config_settings_type * settings , const char* key, double initial_value); -void config_settings_add_string_setting(config_settings_type * settings , const char* key, const char * initial_value); -void config_settings_add_bool_setting(config_settings_type * settings , const char* key, bool initial_value); - - -const char * config_settings_get_value( const config_settings_type * config_settings , const char * key); -const char * config_settings_get_string_value( const config_settings_type * config_settings , const char * key); -int config_settings_get_int_value( const config_settings_type * config_settings , const char * key); -bool config_settings_get_bool_value( const config_settings_type * config_settings , const char * key); -double config_settings_get_double_value( const config_settings_type * config_settings , const char * key); - -bool config_settings_set_value( const config_settings_type * config_settings , const char * key, const char * value); -bool config_settings_set_int_value( const config_settings_type * config_settings , const char * key, int value); -bool config_settings_set_double_value( const config_settings_type * config_settings , const char * key, double value); -bool config_settings_set_bool_value( const config_settings_type * config_settings , const char * key, bool value); -bool config_settings_set_string_value( const config_settings_type * config_settings , const char * key, const char * value); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libconfig/src/CMakeLists.txt b/ThirdParty/Ert/libconfig/src/CMakeLists.txt deleted file mode 100644 index 8d60cec151..0000000000 --- a/ThirdParty/Ert/libconfig/src/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -set( source_files config_parser.c config_content.c config_error.c config_schema_item.c config_content_item.c config_content_node.c config_root_path.c config_path_elm.c conf.c conf_util.c conf_data.c config_settings.c) -set( header_files config_parser.h config_content.h config_error.h config_schema_item.h config_content_item.h config_content_node.h config_root_path.h config_path_elm.h conf.h conf_data.h config_settings.h) - -add_library( config ${LIBRARY_TYPE} ${source_files} ) -set_target_properties( config PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR} ) - -target_link_libraries( config ert_util ) -if (USE_RUNPATH) - add_runpath( config ) -endif() - -if (INSTALL_ERT) - install(TARGETS config DESTINATION ${CMAKE_INSTALL_LIBDIR}) - foreach(header ${header_files}) - install(FILES ../include/ert/config/${header} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/ert/config) - endforeach() -endif() diff --git a/ThirdParty/Ert/libconfig/src/conf.c b/ThirdParty/Ert/libconfig/src/conf.c deleted file mode 100644 index 7ec931c97e..0000000000 --- a/ThirdParty/Ert/libconfig/src/conf.c +++ /dev/null @@ -1,1569 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'conf.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include -#include - -#include -#include - - - -/** S T R U C T D E F I N I T I O N S */ - - - -struct conf_class_struct -{ - const conf_class_type * super_class; /** Can be NULL. */ - char * class_name; - char * help; /** Can be NULL if not given. */ - bool require_instance; - bool singleton; - - hash_type * sub_classes; /** conf_class_types */ - hash_type * item_specs; /** conf_item_spec_types */ - vector_type * item_mutexes; /** item_mutex_types */ -}; - - - -struct conf_instance_struct -{ - const conf_class_type * conf_class; - char * name; - - hash_type * sub_instances; /** conf_instance_types */ - hash_type * items; /** conf_item_types */ -}; - - - -struct conf_item_spec_struct -{ - const conf_class_type * super_class; /** NULL if not inserted into a class. */ - char * name; - bool required_set; /** Require the item to take a valid value. */ - char * default_value; /** Can be NULL if not given. */ - dt_enum dt; /** Data type. See conf_data.* */ - set_type * restriction; /** If non-empty, allowable values. */ - char * help; /** Can be NULL if not given. */ -}; - - - -struct conf_item_struct -{ - const conf_item_spec_type * conf_item_spec; - char * value; -}; - - - -struct conf_item_mutex_struct -{ - const conf_class_type * super_class; - bool require_one; - bool inverse; /* if inverse == true the 'mutex' implements: if A then ALSO B, C and D. */ - hash_type * item_spec_refs; -}; - - - -/** D E F A U L T A L L O C / F R E E F U N C T I O N S */ - - - -conf_class_type * conf_class_alloc_empty( - const char * class_name, - bool require_instance, - bool singleton, - const char * help) -{ - assert(class_name != NULL); - - conf_class_type * conf_class = util_malloc(sizeof *conf_class); - - conf_class->super_class = NULL; - conf_class->class_name = util_alloc_string_copy(class_name); - conf_class->help = NULL; - conf_class->require_instance = require_instance; - conf_class->singleton = singleton; - conf_class->sub_classes = hash_alloc(); - conf_class->item_specs = hash_alloc(); - conf_class->item_mutexes = vector_alloc_new(); - - - conf_class_set_help( conf_class , help ); - return conf_class; -} - - - -void conf_class_free( - conf_class_type * conf_class) -{ - free(conf_class->class_name); - util_safe_free(conf_class->help); - hash_free(conf_class->sub_classes); - hash_free(conf_class->item_specs); - vector_free(conf_class->item_mutexes); - free(conf_class); -} - - - -void conf_class_free__( - void * conf_class) -{ - conf_class_free( (conf_class_type *) conf_class); -} - - - -conf_instance_type * conf_instance_alloc_default( - const conf_class_type * conf_class, - const char * name) -{ - assert(conf_class != NULL); - assert(name != NULL); - - conf_instance_type * conf_instance = util_malloc(sizeof * conf_instance); - - conf_instance->conf_class = conf_class; - conf_instance->name = util_alloc_string_copy(name); - conf_instance->sub_instances = hash_alloc(); - conf_instance->items = hash_alloc(); - - { - /** Insert items that have a default value in their specs. */ - int num_item_specs = hash_get_size(conf_class->item_specs); - char ** item_spec_keys = hash_alloc_keylist(conf_class->item_specs); - - for(int item_spec_nr = 0; item_spec_nr < num_item_specs; item_spec_nr++) - { - const char * item_spec_name = item_spec_keys[item_spec_nr]; - const conf_item_spec_type * conf_item_spec = hash_get(conf_class->item_specs, item_spec_name); - if(conf_item_spec->default_value != NULL) - { - conf_item_type * conf_item = conf_item_alloc(conf_item_spec, conf_item_spec->default_value); - conf_instance_insert_owned_item(conf_instance, conf_item); - } - } - - util_free_stringlist(item_spec_keys, num_item_specs); - } - - return conf_instance; -} - - - -static -void conf_instance_copy_items( - conf_instance_type * conf_instance_target, - const conf_instance_type * conf_instance_source) -{ - int num_items = hash_get_size(conf_instance_source->items); - char ** item_keys = hash_alloc_keylist(conf_instance_source->items); - - for(int item_nr = 0; item_nr < num_items; item_nr++) - { - const char * item_name = item_keys[item_nr]; - const conf_item_type * conf_item = hash_get(conf_instance_source->items, item_name); - conf_item_type * conf_item_copy = conf_item_copyc(conf_item); - conf_instance_insert_owned_item(conf_instance_target, conf_item_copy); - } - - util_free_stringlist(item_keys, num_items); -} - - - -static -void conf_instance_copy_sub_instances( - conf_instance_type * conf_instance_target, - const conf_instance_type * conf_instance_source) -{ - int num_sub_instances = hash_get_size(conf_instance_source->sub_instances); - char ** sub_instance_keys = hash_alloc_keylist(conf_instance_source->sub_instances); - - for(int sub_nr = 0; sub_nr < num_sub_instances; sub_nr++) - { - const char * sub_name = sub_instance_keys[sub_nr]; - const conf_instance_type * sub_conf_instance = hash_get(conf_instance_source->sub_instances, sub_name); - conf_instance_type * sub_conf_instance_copy = conf_instance_copyc(sub_conf_instance); - conf_instance_insert_owned_sub_instance(conf_instance_target, sub_conf_instance_copy); - } - - util_free_stringlist(sub_instance_keys, num_sub_instances); -} - - - -conf_instance_type * conf_instance_copyc( - const conf_instance_type * conf_instance) -{ - conf_instance_type * conf_instance_copy = util_malloc(sizeof * conf_instance_copy); - - conf_instance_copy->conf_class = conf_instance->conf_class; - conf_instance_copy->name = util_alloc_string_copy(conf_instance->name); - conf_instance_copy->sub_instances = hash_alloc(); - conf_instance_copy->items = hash_alloc(); - - conf_instance_copy_items( conf_instance_copy, conf_instance); - conf_instance_copy_sub_instances(conf_instance_copy, conf_instance); - - return conf_instance_copy; -} - - - -void conf_instance_free( - conf_instance_type * conf_instance) -{ - free(conf_instance->name); - hash_free(conf_instance->sub_instances); - hash_free(conf_instance->items); - free(conf_instance); -} - - - -void conf_instance_free__( - void * conf_instance) -{ - conf_instance_free( (conf_instance_type *) conf_instance); -} - - - -conf_item_spec_type * conf_item_spec_alloc( - char * name, - bool required_set, - dt_enum dt, - const char * help) -{ - assert(name != NULL); - - conf_item_spec_type * conf_item_spec = util_malloc(sizeof * conf_item_spec); - - conf_item_spec->super_class = NULL; - conf_item_spec->name = util_alloc_string_copy(name); - conf_item_spec->required_set = required_set; - conf_item_spec->dt = dt; - conf_item_spec->default_value = NULL; - conf_item_spec->restriction = set_alloc_empty(); - conf_item_spec->help = NULL; - conf_item_spec_set_help( conf_item_spec , help ); - return conf_item_spec; -} - - - -void conf_item_spec_free( - conf_item_spec_type * conf_item_spec) -{ - free(conf_item_spec->name); - util_safe_free(conf_item_spec->default_value); - util_safe_free(conf_item_spec->help); - set_free(conf_item_spec->restriction); - free(conf_item_spec); -} - - - -void conf_item_spec_free__( - void * conf_item_spec) -{ - conf_item_spec_free( (conf_item_spec_type *) conf_item_spec); -} - - - -conf_item_type * conf_item_alloc( - const conf_item_spec_type * conf_item_spec, - const char * value) -{ - conf_item_type * conf_item = util_malloc(sizeof * conf_item); - - assert(conf_item_spec != NULL); - assert(value != NULL); - - conf_item->conf_item_spec = conf_item_spec; - conf_item->value = util_alloc_string_copy(value); - - return conf_item; -} - - - -conf_item_type * conf_item_copyc( - const conf_item_type * conf_item) -{ - return conf_item_alloc(conf_item->conf_item_spec, conf_item->value); -} - - - -void conf_item_free( - conf_item_type * conf_item) -{ - free(conf_item->value); - free(conf_item); -} - - - -void conf_item_free__( - void * conf_item) -{ - conf_item_free( (conf_item_type *) conf_item); -} - - - -static -conf_item_mutex_type * conf_item_mutex_alloc( - const conf_class_type * super_class, - bool require_one, - bool inverse) -{ - conf_item_mutex_type * conf_item_mutex = util_malloc(sizeof * conf_item_mutex); - - conf_item_mutex->super_class = super_class; - conf_item_mutex->require_one = require_one; - conf_item_mutex->inverse = inverse; - conf_item_mutex->item_spec_refs = hash_alloc(); - - return conf_item_mutex; -} - - - -void conf_item_mutex_free( - conf_item_mutex_type * conf_item_mutex) -{ - hash_free(conf_item_mutex->item_spec_refs); - free(conf_item_mutex); -} - - - -void conf_item_mutex_free__( - void * conf_item_mutex) -{ - conf_item_mutex_free( (conf_item_mutex_type *) conf_item_mutex); -} - - - - - - -/** M A N I P U L A T O R S , I N S E R T I O N */ - - - -static -bool conf_class_has_super_class( - const conf_class_type * conf_class, - const conf_class_type * super_class) -{ - assert(conf_class != NULL); - assert(super_class != NULL); - - const conf_class_type * parent = conf_class->super_class; - - while(parent != NULL) - { - if(parent == super_class) - return true; - else - parent = parent->super_class; - } - return false; -} - - - -void conf_class_insert_owned_sub_class( - conf_class_type * conf_class, - conf_class_type * sub_conf_class) -{ - assert(conf_class != NULL); - assert(sub_conf_class != NULL); - - /** Abort if conf_class already has an item with the same name. */ - if(hash_has_key(conf_class->item_specs, sub_conf_class->class_name)) - util_abort("%s: Internal error. conf class already has an item with name \"%s\".\n", - __func__, sub_conf_class->class_name); - - /** Abort if sub_conf_class is equal to conf_class. */ - if(sub_conf_class == conf_class) - util_abort("%s: Internal error. Trying to make a class it's own super class.\n", __func__); - - /** Abort if sub_conf_class is a super class to conf_class. */ - if(conf_class_has_super_class(conf_class, sub_conf_class)) - util_abort("%s: Internal error. Trying to make a class it's own super class .\n", __func__); - - /** Abort if sub_conf_class already has a super class. */ - if(sub_conf_class->super_class != NULL) - util_abort("%s: Internal error. Inserted class already has a super class.\n", __func__); - - hash_insert_hash_owned_ref(conf_class->sub_classes, sub_conf_class->class_name, - sub_conf_class, conf_class_free__); - - sub_conf_class->super_class = conf_class; -} - - - -void conf_class_insert_owned_item_spec( - conf_class_type * conf_class, - conf_item_spec_type * item_spec) -{ - assert(conf_class != NULL); - assert(item_spec != NULL); - - - /** Abort if item_spec already has a super class. */ - if(item_spec->super_class != NULL) - util_abort("%s: Internal error: item is already assigned to another class.\n", __func__); - - - /** Abort if the class has a sub class with the same name.. */ - if(hash_has_key(conf_class->sub_classes, item_spec->name)) - util_abort("%s: Internal error. conf class already has a sub class with name \"%s\".\n", __func__, item_spec->name); - - - hash_insert_hash_owned_ref(conf_class->item_specs, item_spec->name, - item_spec, conf_item_spec_free__); - - item_spec->super_class = conf_class; -} - - - -conf_item_mutex_type * conf_class_new_item_mutex(conf_class_type * conf_class , bool require_one , bool inverse) -{ - assert(conf_class != NULL); - conf_item_mutex_type * mutex = conf_item_mutex_alloc( conf_class , require_one , inverse); - vector_append_owned_ref(conf_class->item_mutexes, mutex, conf_item_mutex_free__); - return mutex; -} - - - -void conf_instance_insert_owned_sub_instance( - conf_instance_type * conf_instance, - conf_instance_type * sub_conf_instance) -{ - assert(conf_instance != NULL); - assert(sub_conf_instance != NULL); - - /** Abort if the instance is of unknown type. */ - if(sub_conf_instance->conf_class->super_class != conf_instance->conf_class) - util_abort("%s: Internal error. Trying to insert instance of unknown type.\n", __func__); - - - /** Check if the instance's class is singleton. If so, remove the old instance. */ - if(sub_conf_instance->conf_class->singleton) - { - stringlist_type * instances = conf_instance_alloc_list_of_sub_instances_of_class(conf_instance, - sub_conf_instance->conf_class); - int num_instances = stringlist_get_size(instances); - - for(int i = 0; i < num_instances; i++) - { - const char * key = stringlist_iget(instances, i); - printf("WARNING: Class \"%s\" is of singleton type. Overwriting instance \"%s\" with \"%s\".\n", - sub_conf_instance->conf_class->class_name, key, sub_conf_instance->name); - hash_del(conf_instance->sub_instances, key); - } - - stringlist_free(instances); - } - - - /** Warn if the sub_instance already exists and is overwritten. */ - if(hash_has_key(conf_instance->sub_instances, sub_conf_instance->name)) - { - printf("WARNING: Overwriting instance \"%s\" of class \"%s\" in instance \"%s\" of class \"%s\"\n", - sub_conf_instance->name, conf_instance_get_class_name_ref(sub_conf_instance), - conf_instance->name, conf_instance_get_class_name_ref(conf_instance)); - } - - hash_insert_hash_owned_ref(conf_instance->sub_instances, - sub_conf_instance->name, - sub_conf_instance, - conf_instance_free__); -} - - - -void conf_instance_insert_owned_item( - conf_instance_type * conf_instance, - conf_item_type * conf_item) -{ - assert(conf_instance != NULL); - assert(conf_item != NULL); - - const char * item_name = conf_item->conf_item_spec->name; - - /** Check that the inserted item is of known type. */ - { - const hash_type * item_spec_hash = conf_instance->conf_class->item_specs; - const conf_item_spec_type * conf_item_spec = hash_get(item_spec_hash, item_name); - if(conf_item_spec != conf_item->conf_item_spec) - util_abort("%s: Internal error.\n", __func__); - } - - hash_insert_hash_owned_ref(conf_instance->items, item_name, conf_item, conf_item_free__); -} - - - -void conf_instance_insert_item( - conf_instance_type * conf_instance, - const char * item_name, - const char * value) -{ - assert(conf_instance != NULL); - assert(item_name != NULL); - assert(value != NULL); - - conf_item_type * conf_item; - const conf_class_type * conf_class = conf_instance->conf_class; - const conf_item_spec_type * conf_item_spec; - - if(!conf_class_has_item_spec(conf_class, item_name)) - util_abort("%s: Internal error. Unkown item \"%s\" in class \"%s\".\n", - __func__, item_name, conf_instance->conf_class->class_name); - - conf_item_spec = conf_class_get_item_spec_ref(conf_class, item_name); - - conf_item = conf_item_alloc(conf_item_spec, value); - conf_instance_insert_owned_item(conf_instance, conf_item); -} - - - -void conf_instance_overload( - conf_instance_type * conf_instance_target, - const conf_instance_type * conf_instance_source) -{ - assert(conf_instance_target != NULL); - assert(conf_instance_source != NULL); - - if(conf_instance_target->conf_class != conf_instance_source->conf_class) - util_abort("%s: Internal error. Invalid overloading.\n", __func__); - - conf_instance_copy_items( conf_instance_target, conf_instance_source); - conf_instance_copy_sub_instances(conf_instance_target, conf_instance_source); -} - - - -void conf_item_mutex_add_item_spec( - conf_item_mutex_type * conf_item_mutex, - const conf_item_spec_type * conf_item_spec) -{ - - if(conf_item_mutex->super_class != NULL) - { - const conf_class_type * conf_class = conf_item_mutex->super_class; - const char * item_key = conf_item_spec->name; - - if(!hash_has_key(conf_class->item_specs, item_key)) - { - util_abort("%s: Internal error. Trying to insert a mutex on item \"%s\", which class \"%s\" does not have.\n", - __func__, item_key, conf_class->class_name); - } - else - { - const conf_item_spec_type * conf_item_spec_class = hash_get(conf_class->item_specs, item_key); - if(conf_item_spec_class != conf_item_spec) - { - util_abort("Internal error. Trying to insert a mutex on item \"%s\", which class \"%s\" has a different implementation of.\n", - __func__, item_key, conf_class->class_name); - } - } - } - - if(conf_item_mutex->require_one && conf_item_spec->required_set) - util_abort("%s: Trying to add item \"%s\" to a mutex, but it is required set!\n", - __func__, conf_item_spec->name); - - hash_insert_ref(conf_item_mutex->item_spec_refs, conf_item_spec->name, conf_item_spec); -} - - - -/** M A N I P U L A T O R S , C L A S S A N D I T E M S P E C I F I C A T I O N */ - - - -void conf_class_set_help( - conf_class_type * conf_class, - const char * help) -{ - conf_class->help = util_realloc_string_copy(conf_class->help , help); -} - - - -void conf_item_spec_add_restriction( - conf_item_spec_type * conf_item_spec, - const char * restriction) -{ - set_add_key(conf_item_spec->restriction, restriction); -} - - - -void conf_item_spec_set_default_value( - conf_item_spec_type * conf_item_spec, - const char * default_value) -{ - if(conf_item_spec->default_value != NULL) - free(conf_item_spec->default_value); - if(default_value != NULL) - conf_item_spec->default_value = util_alloc_string_copy(default_value); - else - conf_item_spec->default_value = NULL; -} - - - -void conf_item_spec_set_help( - conf_item_spec_type * conf_item_spec, - const char * help) -{ - conf_item_spec->help = util_realloc_string_copy( conf_item_spec->help , help); -} - - - - -/** A C C E S S O R S */ - - - -bool conf_class_has_item_spec( - const conf_class_type * conf_class, - const char * item_name) -{ - if(!hash_has_key(conf_class->item_specs, item_name)) - return false; - else - return true; -} - - - -bool conf_class_has_sub_class( - const conf_class_type * conf_class, - const char * sub_class_name) -{ - if(!hash_has_key(conf_class->sub_classes, sub_class_name)) - return false; - else - return true; -} - - - -const conf_item_spec_type * conf_class_get_item_spec_ref( - const conf_class_type * conf_class, - const char * item_name) -{ - if(!hash_has_key(conf_class->item_specs, item_name)) - util_abort("%s: Internal error.\n", __func__); - - return hash_get(conf_class->item_specs, item_name); -} - - - -const conf_class_type * conf_class_get_sub_class_ref( - const conf_class_type * conf_class, - const char * sub_class_name) -{ - if(!hash_has_key(conf_class->sub_classes, sub_class_name)) - util_abort("%s: Internal error.\n", __func__); - - return hash_get(conf_class->sub_classes, sub_class_name); -} - - - -const char * conf_instance_get_name_ref( - const conf_instance_type * conf_instance) -{ - return conf_instance->name; -} - - - -bool conf_instance_is_of_class( - const conf_instance_type * conf_instance, - const char * class_name) -{ - if(strcmp(conf_instance->conf_class->class_name, class_name) == 0) - return true; - else - return false; -} - - - -bool conf_instance_has_item( - const conf_instance_type * conf_instance, - const char * item_name) -{ - if(!hash_has_key(conf_instance->items, item_name)) - return false; - else - return true; -} - - - -bool conf_instance_has_sub_instance( - const conf_instance_type * conf_instance, - const char * sub_instance_name) -{ - if(!hash_has_key(conf_instance->sub_instances, sub_instance_name)) - return false; - else - return true; -} - - - -const conf_instance_type * conf_instance_get_sub_instance_ref( - const conf_instance_type * conf_instance, - const char * sub_instance_name) -{ - if(!hash_has_key(conf_instance->sub_instances, sub_instance_name)) - { - util_abort("%s: Instance %s of type %s has no sub instance named %s.\n", - __func__, conf_instance->name, - conf_instance->conf_class->class_name, - sub_instance_name); - } - return hash_get(conf_instance->sub_instances, sub_instance_name); -} - - - -stringlist_type * conf_instance_alloc_list_of_sub_instances_of_class( - const conf_instance_type * conf_instance, - const conf_class_type * conf_class) -{ - stringlist_type * instances = stringlist_alloc_new(); - int num_sub_instances = hash_get_size(conf_instance->sub_instances); - char ** sub_instance_keys = hash_alloc_keylist(conf_instance->sub_instances); - - for(int key_nr = 0; key_nr < num_sub_instances; key_nr++) - { - const conf_instance_type * sub_instance = hash_get(conf_instance->sub_instances, - sub_instance_keys[key_nr]); - - const conf_class_type * sub_instance_class = sub_instance->conf_class; - - if(sub_instance_class == conf_class) - stringlist_append_copy(instances, sub_instance_keys[key_nr]); - } - - util_free_stringlist(sub_instance_keys, num_sub_instances); - - return instances; -} - - - -stringlist_type * conf_instance_alloc_list_of_sub_instances_of_class_by_name( - const conf_instance_type * conf_instance, - const char * sub_class_name) -{ - if(!conf_class_has_sub_class(conf_instance->conf_class, sub_class_name)) - util_abort("%s: Instance \"%s\" is of class \"%s\" which has no sub class with name \"%s\"\n", - conf_instance->name, conf_instance->conf_class->class_name, sub_class_name); - - const conf_class_type * conf_class = conf_class_get_sub_class_ref(conf_instance->conf_class, sub_class_name); - - return conf_instance_alloc_list_of_sub_instances_of_class(conf_instance, conf_class); -} - - - -const conf_class_type * conf_instance_get_class_ref( - const conf_instance_type * conf_instance) -{ - return conf_instance->conf_class; -} - - - -const char * conf_instance_get_class_name_ref( - const conf_instance_type * conf_instance) -{ - return conf_instance->conf_class->class_name; -} - - - -const char * conf_instance_get_item_value_ref( - const conf_instance_type * conf_instance, - const char * item_name) -{ - if(!hash_has_key(conf_instance->items, item_name)) - { - util_abort("%s: Instance %s of type %s has no item %s.\n", - __func__, conf_instance->name, - conf_instance->conf_class->class_name, - item_name); - } - const conf_item_type * conf_item = hash_get(conf_instance->items, item_name); - return conf_item->value; -} - - - -/** If the dt supports it, this function shall return the item value as an int. - If the dt does not support it, the function will abort. -*/ -int conf_instance_get_item_value_int( - const conf_instance_type * conf_instance, - const char * item_name) -{ - if(!hash_has_key(conf_instance->items, item_name)) - util_abort("%s: Instance %s of type %s has no item %s.\n", - __func__, conf_instance->name, - conf_instance->conf_class->class_name, - item_name); - - const conf_item_type * conf_item = hash_get(conf_instance->items, item_name); - const conf_item_spec_type * conf_item_spec = conf_item->conf_item_spec; - - return conf_data_get_int_from_string(conf_item_spec->dt, conf_item->value); -} - - - -/** If the dt supports it, this function shall return the item value as a double. - If the dt does not support it, the function will abort. -*/ -double conf_instance_get_item_value_double( - const conf_instance_type * conf_instance, - const char * item_name) -{ - if(!hash_has_key(conf_instance->items, item_name)) - util_abort("%s: Instance %s of type %s has no item %s.\n", - __func__, conf_instance->name, - conf_instance->conf_class->class_name, - item_name); - - const conf_item_type * conf_item = hash_get(conf_instance->items, item_name); - const conf_item_spec_type * conf_item_spec = conf_item->conf_item_spec; - - return conf_data_get_double_from_string(conf_item_spec->dt, conf_item->value); -} - - - -/** If the dt supports it, this function shall return the item value as a time_t. - If the dt does not support it, the function will abort. -*/ -time_t conf_instance_get_item_value_time_t( - const conf_instance_type * conf_instance, - const char * item_name) -{ - if(!hash_has_key(conf_instance->items, item_name)) - util_abort("%s: Instance %s of type %s has no item %s.\n", - __func__, conf_instance->name, - conf_instance->conf_class->class_name, - item_name); - - const conf_item_type * conf_item = hash_get(conf_instance->items, item_name); - const conf_item_spec_type * conf_item_spec = conf_item->conf_item_spec; - - return conf_data_get_time_t_from_string(conf_item_spec->dt, conf_item->value); -} - - - - - -/** V A L I D A T O R S */ - - - -static -void conf_item_spec_printf_help( - const conf_item_spec_type * conf_item_spec) -{ - assert(conf_item_spec->super_class != NULL); - int num_restrictions = set_get_size(conf_item_spec->restriction); - - printf("\n Help on item \"%s\" in class \"%s\":\n\n", - conf_item_spec->name, conf_item_spec->super_class->class_name); - printf(" - Data type : %s\n\n", conf_data_get_dt_name_ref(conf_item_spec->dt)); - if(conf_item_spec->default_value != NULL) - printf(" - Default value: %s\n\n", conf_item_spec->default_value); - if(conf_item_spec->help != NULL) - printf(" - %s\n", conf_item_spec->help); - - if(num_restrictions > 0) - { - printf("\n The item \"%s\" is restricted to the following values:\n\n", - conf_item_spec->name); - char ** restriction_keys = set_alloc_keylist(conf_item_spec->restriction); - - for(int key_nr = 0; key_nr < num_restrictions; key_nr++) - { - printf(" %i. %s\n", key_nr + 1, restriction_keys[key_nr]); - } - - util_free_stringlist(restriction_keys, num_restrictions); - } - printf("\n"); -} - - - -static -void conf_class_printf_help( - const conf_class_type * conf_class) -{ - /** TODO Should print info on the required sub classes and items. */ - - if(conf_class->help != NULL) - { - if(conf_class->super_class != NULL) - printf("\n Help on class \"%s\" with super class \"%s\":\n\n", - conf_class->class_name, conf_class->super_class->class_name); - else - printf("\n Help on class \"%s\":\n\n", - conf_class->class_name); - - printf(" %s\n", conf_class->help); - } - printf("\n"); -} - - - -static -bool conf_item_validate( - const conf_item_type * conf_item) -{ - assert(conf_item != NULL); - - bool ok = true; - const conf_item_spec_type * conf_item_spec = conf_item->conf_item_spec; - int num_restrictions = set_get_size(conf_item_spec->restriction); - - if(!conf_data_validate_string_as_dt_value(conf_item_spec->dt, conf_item->value)) - { - ok = false; - printf("ERROR: Failed to validate \"%s\" as a %s for item \"%s\".\n", - conf_item->value, conf_data_get_dt_name_ref(conf_item_spec->dt), - conf_item_spec->name); - } - - if(num_restrictions > 0 && ok) - { - char ** restriction_keys = set_alloc_keylist(conf_item_spec->restriction); - - /** Legacy work-around when removing the vector supprt. */ - const int num_tokens = 1; - const char ** tokens = (const char **) &conf_item->value; - - for(int token_nr = 0; token_nr < num_tokens; token_nr++) - { - bool valid = false; - - for(int key_nr = 0; key_nr < num_restrictions; key_nr++) - { - if(strcmp(tokens[token_nr], restriction_keys[key_nr]) == 0) - valid = true; - } - - if(valid == false) - { - ok = false; - printf("ERROR: Failed to validate \"%s\" as a valid value for item \"%s\".\n", - conf_item->value, conf_item_spec->name); - } - } - util_free_stringlist(restriction_keys, num_restrictions); - } - - if(!ok) - conf_item_spec_printf_help(conf_item_spec); - - - return ok; -} - - - -static -bool conf_instance_has_required_items( - const conf_instance_type * conf_instance) -{ - bool ok = true; - const conf_class_type * conf_class = conf_instance->conf_class; - - int num_item_specs = hash_get_size(conf_class->item_specs); - char ** item_spec_keys = hash_alloc_keylist(conf_class->item_specs); - - for(int item_spec_nr = 0; item_spec_nr < num_item_specs; item_spec_nr++) - { - const char * item_spec_name = item_spec_keys[item_spec_nr]; - const conf_item_spec_type * conf_item_spec = hash_get(conf_class->item_specs, item_spec_name); - if(conf_item_spec->required_set) - { - if(!hash_has_key(conf_instance->items, item_spec_name)) - { - ok = false; - printf("ERROR: Missing item \"%s\" in instance \"%s\" of class \"%s\"\n", - item_spec_name, conf_instance->name, conf_instance->conf_class->class_name); - conf_item_spec_printf_help(conf_item_spec); - } - } - } - - util_free_stringlist(item_spec_keys, num_item_specs); - - return ok; -} - - - -static -bool conf_instance_has_valid_items( - const conf_instance_type * conf_instance) -{ - bool ok = true; - - int num_items = hash_get_size(conf_instance->items); - char ** item_keys = hash_alloc_keylist(conf_instance->items); - - for(int item_nr = 0; item_nr < num_items; item_nr++) - { - const conf_item_type * conf_item = hash_get(conf_instance->items, item_keys[item_nr]); - if(!conf_item_validate(conf_item)) - ok = false; - } - - util_free_stringlist(item_keys, num_items); - - return ok; -} - - -static -bool conf_instance_check_item_mutex( - const conf_instance_type * conf_instance, - const conf_item_mutex_type * conf_item_mutex) -{ - bool ok = true; - int num_items_set = 0; - set_type * items_set = set_alloc_empty(); - int num_items = hash_get_size(conf_item_mutex->item_spec_refs); - char ** item_keys = hash_alloc_keylist(conf_item_mutex->item_spec_refs); - - for(int item_nr = 0; item_nr < num_items; item_nr++) - { - const char * item_key = item_keys[item_nr]; - if(conf_instance_has_item(conf_instance, item_key)) - { - set_add_key(items_set, item_key); - } - } - - num_items_set = set_get_size(items_set); - - if (conf_item_mutex->inverse) - { - /** This is an inverse mutex - all (or none) items should be set. */ - if (!((num_items_set == 0) || (num_items_set == num_items))) - { - ok = false; - char ** items_set_keys = set_alloc_keylist(items_set); - printf("ERROR: Failed to validate mutal inclusion in instance \"%s\" of class \"%s\".\n\n", - conf_instance->name, conf_instance->conf_class->class_name); - printf(" When using one or more of the following items, all must be set:\n"); - for(int item_nr = 0; item_nr < num_items; item_nr++) - printf(" %i : %s\n", item_nr, item_keys[item_nr]); - printf("\n"); - printf(" However, only the following items were set:\n"); - for(int item_nr = 0; item_nr < num_items_set; item_nr++) - printf(" %i : %s\n", item_nr, items_set_keys[item_nr]); - printf("\n"); - - util_free_stringlist(items_set_keys, num_items_set); - } - } - else - { - if(num_items_set > 1) - { - ok = false; - char ** items_set_keys = set_alloc_keylist(items_set); - - printf("ERROR: Failed to validate mutex in instance \"%s\" of class \"%s\".\n\n", - conf_instance->name, conf_instance->conf_class->class_name); - printf(" Only one of the following items may be set:\n"); - for(int item_nr = 0; item_nr < num_items; item_nr++) - printf(" %i : %s\n", item_nr, item_keys[item_nr]); - - printf("\n"); - printf(" However, all the following items were set:\n"); - for(int item_nr = 0; item_nr < num_items_set; item_nr++) - printf(" %i : %s\n", item_nr, items_set_keys[item_nr]); - printf("\n"); - - util_free_stringlist(items_set_keys, num_items_set); - } - } - - if(num_items_set == 0 && conf_item_mutex->require_one && num_items > 0) - { - ok = false; - printf("ERROR: Failed to validate mutex in instance \"%s\" of class \"%s\".\n\n", - conf_instance->name, conf_instance->conf_class->class_name); - printf(" One of the following items MUST be set:\n"); - for(int item_nr = 0; item_nr < num_items; item_nr++) - printf(" %i : %s\n", item_nr, item_keys[item_nr]); - printf("\n"); - } - - util_free_stringlist(item_keys, num_items); - set_free(items_set); - - return ok; -} - - - -static -bool conf_instance_has_valid_mutexes( - const conf_instance_type * conf_instance) -{ - bool ok = true; - const conf_class_type * conf_class = conf_instance->conf_class; - const vector_type * item_mutexes = conf_class->item_mutexes; - int num_mutexes = vector_get_size(item_mutexes); - - for(int mutex_nr = 0; mutex_nr < num_mutexes; mutex_nr++) - { - const conf_item_mutex_type * conf_item_mutex = vector_iget( item_mutexes, mutex_nr ); - if(!conf_instance_check_item_mutex(conf_instance, conf_item_mutex)) - ok = false; - } - - return ok; -} - -static bool __instance_has_sub_instance_of_type( - const conf_class_type * __conf_class, int num_sub_instances, conf_class_type ** class_signatures) -{ - for(int sub_instance_nr = 0; sub_instance_nr < num_sub_instances; sub_instance_nr++) - { - if(class_signatures[sub_instance_nr] == __conf_class) - return true; - } - return false; -} - -static -bool conf_instance_has_required_sub_instances( - const conf_instance_type * conf_instance) -{ - /** U G L Y B U G L Y U G L Y B U G LY U G L Y B U G LY U G L Y B U G LY */ - /** This function is really ugly. It could be smoother if set_type supported size_t's. */ - /** U G L Y B U G L Y U G L Y B U G LY U G L Y B U G LY U G L Y B U G LY */ - - bool ok = true; - - - /** This first part is just concerned with creating the function __instance_has_sub_instance_of_type. */ - int num_sub_instances = hash_get_size(conf_instance->sub_instances); - conf_class_type ** class_signatures = util_calloc(num_sub_instances , sizeof * class_signatures); - { - char ** sub_instance_keys = hash_alloc_keylist(conf_instance->sub_instances); - for(int sub_instance_nr = 0; sub_instance_nr < num_sub_instances; sub_instance_nr++) - { - const char * sub_instance_name = sub_instance_keys[sub_instance_nr]; - const conf_instance_type * sub_conf_instance = hash_get(conf_instance->sub_instances, sub_instance_name); - class_signatures[sub_instance_nr] = (conf_class_type *) sub_conf_instance->conf_class; - } - util_free_stringlist(sub_instance_keys, num_sub_instances); - } - - - - - - - /** OK, we now check that the sub classes that have require_instance true have at least one instance. */ - { - const conf_class_type * conf_class = conf_instance->conf_class; - int num_sub_classes = hash_get_size(conf_class->sub_classes); - char ** sub_class_keys = hash_alloc_keylist(conf_class->sub_classes); - - for(int sub_class_nr = 0; sub_class_nr < num_sub_classes; sub_class_nr ++) - { - const char * sub_class_name = sub_class_keys[sub_class_nr]; - const conf_class_type * sub_conf_class = hash_get(conf_class->sub_classes, sub_class_name); - if(sub_conf_class->require_instance) - { - if(!__instance_has_sub_instance_of_type(sub_conf_class, num_sub_instances, class_signatures)) - { - printf("ERROR: Missing required instance of sub class \"%s\" in instance \"%s\" of class \"%s\".\n", - sub_conf_class->class_name, conf_instance->name, conf_instance->conf_class->class_name); - conf_class_printf_help(sub_conf_class); - ok = false; - } - } - } - - util_free_stringlist(sub_class_keys, num_sub_classes); - } - - free(class_signatures); - - return ok; -} - - - -static -bool conf_instance_validate_sub_instances( - const conf_instance_type * conf_instance) -{ - bool ok = true; - - int num_sub_instances = hash_get_size(conf_instance->sub_instances); - char ** sub_instance_keys = hash_alloc_keylist(conf_instance->sub_instances); - - for(int sub_instance_nr = 0; sub_instance_nr < num_sub_instances; sub_instance_nr++) - { - const char * sub_instances_key = sub_instance_keys[sub_instance_nr]; - const conf_instance_type * sub_conf_instance = hash_get(conf_instance->sub_instances, sub_instances_key); - if(!conf_instance_validate(sub_conf_instance)) - ok = false; - } - - util_free_stringlist(sub_instance_keys, num_sub_instances); - - return ok; -} - - - -bool conf_instance_validate( - const conf_instance_type * conf_instance) -{ - bool ok = true; - - if(conf_instance == NULL) - { - printf("%s: Trying to dereference NULL pointer.\n", __func__); - return false; - } - - if(!conf_instance_has_required_items(conf_instance)) - ok = false; - - if(!conf_instance_has_valid_mutexes(conf_instance)) - ok = false; - - if(!conf_instance_has_valid_items(conf_instance)) - ok = false; - - if(!conf_instance_has_required_sub_instances(conf_instance)) - ok = false; - - if(!conf_instance_validate_sub_instances(conf_instance)) - ok = false; - - return ok; -} - - - -/** A L L O C F R O M F I L E */ - - - -static -void conf_instance_parser_add_item( - conf_instance_type * conf_instance, - const char * item_name, - char ** buffer_pos) -{ - char * token_assign; - char * token_value; - char * token_end; - - char * buffer_pos_loc = *buffer_pos; - - token_assign = conf_util_alloc_next_token(&buffer_pos_loc); - if(token_assign == NULL) - { - /** This will fail. Give up. */ - printf("WARNING: Unexpected EOF after \"%s\". Giving up on this item.\n\n", item_name); - return; - } - else if(strcmp(token_assign, "=") != 0) - { - /** This will fail. Give up. */ - printf("WARNING: Unexpected \"%s\" after \"%s\". Giving up on this item.\n\n", token_assign, item_name); - free(token_assign); - *buffer_pos = buffer_pos_loc; - return; - } - - token_value = conf_util_alloc_next_token(&buffer_pos_loc); - if(token_value == NULL) - { - /** This will fail. Give up. */ - printf("WARNING: Unexpected EOF after \"%s = \". Giving up on this item.\n\n", item_name); - free(token_assign); - return; - } - else - conf_instance_insert_item(conf_instance, item_name, token_value); - - *buffer_pos = buffer_pos_loc; - - token_end = conf_util_alloc_next_token(&buffer_pos_loc); - if(token_end == NULL) - { - /** We've already alloc'd the token. Print a warning to the user. */ - printf("WARNING: Unexpected EOF after \"%s = %s \".\n\n", item_name, token_value); - free(token_assign); - free(token_value); - return; - } - else if(strcmp(token_end, ";") != 0) - { - printf("WARNING: Unexpected \"%s\" after \"%s = %s \". Probably a missing \";\".\n\n", - token_end, item_name, token_value); - } - else - { - *buffer_pos = buffer_pos_loc; - } - - free(token_assign); - free(token_value); - free(token_end); -} - - - -static -void conf_instance_parser_skip_unknown_class( - char ** buffer_pos) -{ - int depth_in_unkown_class = 1; - char * token = conf_util_alloc_next_token(buffer_pos); - - while(token != NULL) - { - if(strcmp(token, "{") == 0) - depth_in_unkown_class++; - else if(strcmp(token, "}") == 0) - depth_in_unkown_class--; - - printf("WARNING: Skipping token \"%s\" in unknown class.\n", token); - free(token); - if(depth_in_unkown_class == 0) - break; - else - token = conf_util_alloc_next_token(buffer_pos); - } -} - - - -static -void conf_instance_add_data_from_token_buffer( - conf_instance_type * conf_instance, - char ** buffer_pos, - bool allow_inclusion, - bool is_root) -{ - const conf_class_type * conf_class = conf_instance->conf_class; - char * token = conf_util_alloc_next_token(buffer_pos); - - bool scope_start_set = false; - bool scope_end_set = false; - - while(token != NULL) - { - if(conf_class_has_item_spec(conf_class, token) && (scope_start_set || is_root)) - conf_instance_parser_add_item(conf_instance, token, buffer_pos); - else if(conf_class_has_sub_class(conf_class, token) && (scope_start_set || is_root)) - { - char * name = conf_util_alloc_next_token(buffer_pos); - const conf_class_type * sub_conf_class = conf_class_get_sub_class_ref(conf_class, token); - if(name != NULL) - { - conf_instance_type * sub_conf_instance = conf_instance_alloc_default(sub_conf_class, name); - free(name); - conf_instance_insert_owned_sub_instance(conf_instance, sub_conf_instance); - conf_instance_add_data_from_token_buffer(sub_conf_instance, buffer_pos, allow_inclusion, false); - } - else - printf("WARNING: Unexpected EOF after \"%s\".\n\n", token); - } - else if(strcmp(token, "}") == 0) - { - if(scope_start_set) - { - scope_end_set = true; - free(token); - break; - } - else - printf("WARNING: Skipping unexpected token \"%s\".\n\n", token); - } - else if(strcmp(token, "{") == 0) - { - if(!scope_start_set && !is_root) - scope_start_set = true; - else - conf_instance_parser_skip_unknown_class(buffer_pos); - } - else if(strcmp(token, ";") == 0) - { - if(!scope_start_set) - { - free(token); - break; - } - else - printf("WARNING: Skipping unexpected token \"%s\".\n\n", token); - } - else if(strcmp(token, "include") == 0) - { - char * file_name = conf_util_alloc_next_token(buffer_pos); - char * buffer_pos_lookahead = *buffer_pos; - char * token_end; - - if(file_name == NULL) - { - printf("WARNING: Unexpected EOF after \"%s\".\n\n", token); - free(token); - break; - } - else if(!allow_inclusion) - { - printf("WARNING: No support for nested inclusion. Skipping file \"%s\".\n\n", file_name); - } - else - { - char * buffer_new = conf_util_fscanf_alloc_token_buffer(file_name); - char * buffer_pos_new = buffer_new; - - conf_instance_add_data_from_token_buffer(conf_instance, &buffer_pos_new, false, true); - - free(buffer_new); - } - - /** Check that the filename is followed by a ; */ - token_end = conf_util_alloc_next_token(&buffer_pos_lookahead); - if(token_end == NULL) - { - printf("WARNING: Unexpected EOF after inclusion of file \"%s\".\n\n", file_name); - free(token); - free(file_name); - break; - } - else if(strcmp(token_end, ";") != 0) - { - printf("WARNING: Unexpected \"%s\" after inclusion of file \"%s\". Probably a missing \";\".\n\n", - token_end, file_name); - } - else - { - *buffer_pos = buffer_pos_lookahead; - } - free(token_end); - free(file_name); - } - else - { - printf("WARNING: Skipping unexpected token \"%s\".\n\n", token); - } - - free(token); - token = conf_util_alloc_next_token(buffer_pos); - } - - - if(scope_end_set) - { - token = conf_util_alloc_next_token(buffer_pos); - if(token == NULL) - { - printf("WARNING: Unexpected EOF. Missing terminating \";\".\n"); - } - else if(strcmp(token, ";") != 0) - { - printf("WARNING: Missing terminating \";\" at the end of \"%s\".\n", conf_instance->name); - free(token); - } - else - free(token); - } -} - - - -conf_instance_type * conf_instance_alloc_from_file( - const conf_class_type * conf_class, - const char * name, - const char * file_name) -{ - conf_instance_type * conf_instance = conf_instance_alloc_default(conf_class, name); - - char * buffer = conf_util_fscanf_alloc_token_buffer(file_name); - char * buffer_pos = buffer; - - conf_instance_add_data_from_token_buffer(conf_instance, &buffer_pos, true, true); - - free(buffer); - - return conf_instance; -} - - diff --git a/ThirdParty/Ert/libconfig/src/conf_data.c b/ThirdParty/Ert/libconfig/src/conf_data.c deleted file mode 100644 index eb0867c6d2..0000000000 --- a/ThirdParty/Ert/libconfig/src/conf_data.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'conf_data.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include - -#include - - - -#define DT_STR_STRING "string" -#define DT_INT_STRING "integer" -#define DT_POSINT_STRING "positive integer" -#define DT_FLOAT_STRING "floating point number" -#define DT_POSFLOAT_STRING "positive floating foint number" -#define DT_FILE_STRING "file" -#define DT_EXEC_STRING "executable" -#define DT_FOLDER_STRING "folder" -#define DT_DATE_STRING "date" - - - -#define RETURN_TYPE_IF_MATCH(STRING,TYPE) if(strcmp(STRING, TYPE ##_STRING) == 0){ return TYPE;} -dt_enum conf_data_get_dt_from_string( - const char * str) -{ - RETURN_TYPE_IF_MATCH(str, DT_STR); - RETURN_TYPE_IF_MATCH(str, DT_INT); - RETURN_TYPE_IF_MATCH(str, DT_POSINT); - RETURN_TYPE_IF_MATCH(str, DT_FLOAT); - RETURN_TYPE_IF_MATCH(str, DT_POSFLOAT); - RETURN_TYPE_IF_MATCH(str, DT_FILE); - RETURN_TYPE_IF_MATCH(str, DT_EXEC); - RETURN_TYPE_IF_MATCH(str, DT_FOLDER); - RETURN_TYPE_IF_MATCH(str, DT_DATE); - - util_abort("%s: Data type \"%s\" is unkown.\n", __func__, str); - return 0; -} -#undef RETURN_TYPE_IF_MATCH - - - -bool conf_data_string_is_dt( - const char * str) -{ - if( !strcmp(str, DT_STR_STRING )) return true; - else if(!strcmp(str, DT_INT_STRING )) return true; - else if(!strcmp(str, DT_POSINT_STRING )) return true; - else if(!strcmp(str, DT_FLOAT_STRING )) return true; - else if(!strcmp(str, DT_POSFLOAT_STRING )) return true; - else if(!strcmp(str, DT_FILE_STRING )) return true; - else if(!strcmp(str, DT_EXEC_STRING )) return true; - else if(!strcmp(str, DT_FOLDER_STRING )) return true; - else if(!strcmp(str, DT_DATE_STRING )) return true; - else return false; -} - - - -const char * conf_data_get_dt_name_ref( - dt_enum dt) -{ - switch(dt) - { - case(DT_STR): - return DT_STR_STRING; - case(DT_INT): - return DT_INT_STRING; - case(DT_POSINT): - return DT_POSINT_STRING; - case(DT_FLOAT): - return DT_FLOAT_STRING; - case(DT_POSFLOAT): - return DT_POSFLOAT_STRING; - case(DT_FILE): - return DT_FILE_STRING; - case(DT_EXEC): - return DT_EXEC_STRING; - case(DT_FOLDER): - return DT_FOLDER_STRING; - case(DT_DATE): - return DT_DATE_STRING; - default: - util_abort("%s: Internal error.\n", __func__); - return ""; - } -} - - - -bool conf_data_validate_string_as_dt_value( - dt_enum dt, - const char * str) -{ - if(str == NULL) - return false; - - switch(dt) - { - case(DT_STR): - return true; - case(DT_INT): - return util_sscanf_int(str, NULL); - case(DT_POSINT): - { - int val; - bool ok = util_sscanf_int(str, &val); - if(!ok) - return false; - else - return val > 0; - } - case(DT_FLOAT): - return util_sscanf_double(str, NULL); - case(DT_POSFLOAT): - { - double val; - bool ok = util_sscanf_double(str, &val); - if(!ok) - return false; - else - return val >= 0.0; - } - case(DT_FILE): - { - return util_file_exists(str); - } - case(DT_EXEC): - { - bool ok; - char * exec = util_alloc_PATH_executable(str); - ok = exec != NULL; - free(exec); - return ok; - } - case(DT_FOLDER): - { - return util_is_directory(str); - } - case(DT_DATE): - { - time_t date; - return util_sscanf_date_utc(str, &date); - } - default: - util_abort("%s: Internal error.\n", __func__); - } - return true; -} - - - - - -int conf_data_get_int_from_string( - dt_enum dt, - const char * str) -{ - int value = 0; - bool ok = true; - - switch(dt) - { - case(DT_INT): - ok = util_sscanf_int(str, &value); - break; - case(DT_POSINT): - ok = util_sscanf_int(str, &value); - break; - default: - ok = false; - } - - if(!ok) - util_abort("%s: Can not get an int from \"%s\".\n", - __func__, str); - - return value; -} - - - -double conf_data_get_double_from_string( - dt_enum dt, - const char * str) -{ - double value = 0; - bool ok = true; - - switch(dt) - { - case(DT_INT): - ok = util_sscanf_double(str, &value); - break; - case(DT_POSINT): - ok = util_sscanf_double(str, &value); - break; - case(DT_FLOAT): - ok = util_sscanf_double(str, &value); - break; - case(DT_POSFLOAT): - ok = util_sscanf_double(str, &value); - break; - default: - ok = false; - } - - if(!ok) - util_abort("%s: Can not get a double from \"%s\".\n", - __func__, str); - - return value; -} - - - -time_t conf_data_get_time_t_from_string( - dt_enum dt, - const char * str) -{ - time_t value = 0; - bool ok = true; - - switch(dt) - { - case(DT_DATE): - ok = util_sscanf_date_utc(str, &value); - break; - default: - ok = false; - } - - if(!ok) - util_abort("%s: Can not get a time_t from \"%s\".\n", - __func__, str); - return value; -} - - - diff --git a/ThirdParty/Ert/libconfig/src/conf_util.c b/ThirdParty/Ert/libconfig/src/conf_util.c deleted file mode 100644 index f634b784ad..0000000000 --- a/ThirdParty/Ert/libconfig/src/conf_util.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'conf_util.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include - -#include - - -/* - This function creates a string buffer from a file. Furthermore, if the strings in pad_keys are found in the buffer, - they are padded with a space before and after. - - I.e., if the file contains - - key=value - - and "=" is in pad_keys, then the buffer will read - - key = value -*/ -static -char * __conf_util_fscanf_alloc_token_buffer( - const char * file, - const char * comment, - int num_pad_keys, - const char ** pad_keys) -{ - char * buffer_wrk = basic_parser_fread_alloc_file_content( file , NULL /* quote_set */ , NULL /* delete_set */ , "--" /* Comment start*/ , "\n" /* Comment end */); - char ** padded_keys = util_calloc(num_pad_keys , sizeof * padded_keys); - for(int key_nr = 0; key_nr < num_pad_keys; key_nr++) - { - assert(pad_keys[key_nr] != NULL); - - int key_len = strlen(pad_keys[key_nr]); - padded_keys[key_nr] = util_calloc((key_len + 3) , sizeof * padded_keys[key_nr]); - padded_keys[key_nr][0] = ' '; - for(int i=0; i 0) - found = true; - else if(len_token == 0 && !quoted) - return NULL; - else if(len_token == 0 && quoted) - *buff_pos += 1; - } - - char * token = util_calloc( (len_token + 1) , sizeof * token); - memmove(token, *buff_pos, len_token); - token[len_token] = '\0'; - *buff_pos += len_token; - - if(quoted) - *buff_pos += 1; - - return token; -} diff --git a/ThirdParty/Ert/libconfig/src/config_content.c b/ThirdParty/Ert/libconfig/src/config_content.c deleted file mode 100644 index d218dbfd43..0000000000 --- a/ThirdParty/Ert/libconfig/src/config_content.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'config_content.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -#define CONFIG_CONTENT_TYPE_ID 6612520 - -struct config_content_struct { - UTIL_TYPE_ID_DECLARATION; - set_type * parsed_files; /* A set of config files whcih have been parsed - to protect against circular includes. */ - vector_type * nodes; - hash_type * items; - config_error_type * parse_errors; - stringlist_type * warnings; - subst_list_type * define_list; - char * config_file; - char * abs_path; - - config_root_path_type * invoke_path; - vector_type * path_elm_storage; - vector_type * path_elm_stack; - bool valid; -}; - - -UTIL_IS_INSTANCE_FUNCTION( config_content , CONFIG_CONTENT_TYPE_ID ) - -config_content_type * config_content_alloc(const char * filename) { - config_content_type * content = util_malloc( sizeof * content ); - UTIL_TYPE_ID_INIT( content , CONFIG_CONTENT_TYPE_ID ); - content->valid = false; - content->items = hash_alloc(); - content->nodes = vector_alloc_new(); - content->parse_errors = config_error_alloc(); - content->define_list = subst_list_alloc( NULL ); - content->parsed_files = set_alloc_empty(); - content->warnings = stringlist_alloc_new(); - - content->path_elm_storage = vector_alloc_new(); - content->path_elm_stack = vector_alloc_new(); - - content->config_file = util_alloc_string_copy( filename ); - content->abs_path = util_alloc_abs_path( filename ); - { - char * path = util_split_alloc_dirname( filename ); - content->invoke_path = config_root_path_alloc( NULL ); - free( path ); - } - - - return content; -} - - -bool config_content_has_item( const config_content_type * content , const char * key) { - return hash_has_key( content->items , key ); -} - - -config_content_item_type * config_content_get_item( const config_content_type * content , const char * key) { - return hash_get( content->items , key ); -} - - -void config_content_add_item( config_content_type * content , const config_schema_item_type * schema_item , const config_path_elm_type * path_elm) { - - const char * kw = config_schema_item_get_kw( schema_item ); - config_content_item_type * content_item = config_content_item_alloc( schema_item , path_elm ); - hash_insert_hash_owned_ref( content->items , kw , content_item , config_content_item_free__ ); - - if (config_schema_item_is_deprecated(schema_item)) - stringlist_append_copy( content->warnings , config_schema_item_get_deprecate_msg(schema_item)); -} - -void config_content_add_node( config_content_type * content , config_content_node_type * content_node ) { - vector_append_ref( content->nodes , content_node ); -} - - -void config_content_set_valid( config_content_type * content) { - content->valid = true; -} - -bool config_content_is_valid( const config_content_type * content ) { - return content->valid; -} - - -config_error_type * config_content_get_errors( const config_content_type * content) { - return content->parse_errors; -} - - -const stringlist_type * config_content_get_warnings( const config_content_type * content) { - return content->warnings; -} - - - -void config_content_free( config_content_type * content ) { - stringlist_free( content->warnings ); - vector_free( content->nodes ); - vector_free( content->path_elm_stack ); - vector_free( content->path_elm_storage ); - hash_free( content->items ); - config_error_free( content->parse_errors ); - subst_list_free( content->define_list ); - util_safe_free( content->config_file ); - util_safe_free( content->abs_path ); - set_free( content->parsed_files ); - if (content->invoke_path != NULL) - config_root_path_free( content->invoke_path ); - - free( content ); -} - -bool config_content_add_file( config_content_type * content , const char * config_file) { - return set_add_key( content->parsed_files , config_file); -} - -config_root_path_type * config_content_get_invoke_path( config_content_type * content ) { - return content->invoke_path; -} - - - - - -/*****************************************************************/ - -/* - Here comes some xxx_get() functions - many of them will fail if - the item has not been added in the right way (this is to ensure that - the xxx_get() request is unambigous. -*/ - - -/** - This function can be used to get the value of a config - parameter. But to ensure that the get is unambigous we set the - following requirements to the item corresponding to 'kw': - - * argc_minmax has been set to 1,1 - - If this is not the case - we die. -*/ - -/** - Assume we installed a key 'KEY' which occurs three times in the final - config file: - - KEY 1 2 3 - KEY 11 22 33 - KEY 111 222 333 - - - Now when accessing these values the occurence variable will - correspond to the linenumber, and the index will index along a line: - - config_iget_as_int( config , "KEY" , 0 , 2) => 3 - config_iget_as_int( config , "KEY" , 2 , 1) => 222 -*/ - -const char * config_content_iget( const config_content_type * content , const char * key , int occurence , int index) { - config_content_item_type * item = config_content_get_item(content , key); - return config_content_item_iget(item , occurence , index); -} - - -int config_content_iget_as_int( const config_content_type * content , const char * key , int occurence , int index) { - config_content_item_type * item = config_content_get_item(content , key); - return config_content_item_iget_as_int(item , occurence , index); -} - - -bool config_content_iget_as_bool( const config_content_type * content , const char * key , int occurence , int index) { - config_content_item_type * item = config_content_get_item(content , key); - return config_content_item_iget_as_bool(item , occurence , index); -} - - -double config_content_iget_as_double( const config_content_type * content , const char * key , int occurence , int index) { - config_content_item_type * item = config_content_get_item(content , key); - return config_content_item_iget_as_double(item , occurence , index); -} - -const char * config_content_iget_as_path( const config_content_type * content , const char * key , int occurence , int index) { - config_content_item_type * item = config_content_get_item(content , key); - config_content_node_type * node = config_content_item_iget_node( item , index ); - return config_content_node_iget_as_path(node , index); -} - - -/** - This function will return NULL is the item has not been set, - however it must be installed with config_add_schema_item(). -*/ - -const char * config_content_safe_iget(const config_content_type * content , const char *kw, int occurence , int index) { - const char * value = NULL; - - if (config_content_has_item( content , kw )) { - config_content_item_type * item = config_content_get_item(content , kw); - if (occurence < config_content_item_get_size( item )) { - config_content_node_type * node = config_content_item_iget_node( item , occurence ); - value = config_content_node_safe_iget( node , index ); - } - } - return value; -} - - -/** - Return the number of times a keyword has been set - dies on unknown - 'kw'. If the append_arg attribute has been set to false the - function will return 0 or 1 irrespective of how many times the item - has been set in the config file. -*/ - - -int config_content_get_occurences(const config_content_type * content, const char * kw) { - if (config_content_has_item( content , kw )) - return config_content_item_get_size( config_content_get_item(content , kw) ); - else - return 0; -} - - - -const config_content_node_type * config_content_iget_node( const config_content_type * content , int index) { - const config_content_node_type * node = vector_iget_const(content->nodes , index ); - return node; -} - - -int config_content_get_size(const config_content_type * content) { - return vector_get_size( content->nodes ); -} - -/*****************************************************************/ -/* All the get_value functions will operate on the last item which has - been set with a particular key value. So assuming the config file - looks like: - - KEY VALUE1 - KEY VALUE2 OPTIONAL - KEY 100 VALUE3 OPTIONAL ERROR - - these functions will all operate on the last line in the config file: - - KEY 100 VALUE3 OPTIONAL ERROR -*/ - - - -static config_content_node_type * config_content_get_value_node__( const config_content_type * config , const char * kw) { - config_content_node_type * node = config_content_get_value_node( config , kw ); - if (node == NULL) - util_abort("Tried to get value node from unset kw:%s \n",__func__ , kw ); - - return node; -} - -config_content_node_type * config_content_get_value_node( const config_content_type * content , const char * kw) { - config_content_item_type * item = config_content_get_item(content , kw); - config_content_node_type * node = config_content_item_get_last_node( item ); - config_content_node_assert_key_value( node ); - return node; -} - - -bool config_content_get_value_as_bool(const config_content_type * config , const char * kw) { - config_content_node_type * node = config_content_get_value_node__( config , kw ); - return config_content_node_iget_as_bool(node , 0); -} - -int config_content_get_value_as_int(const config_content_type * config , const char * kw) { - config_content_node_type * node = config_content_get_value_node__( config , kw ); - return config_content_node_iget_as_int(node , 0); -} - -double config_content_get_value_as_double(const config_content_type * config , const char * kw) { - config_content_node_type * node = config_content_get_value_node__( config , kw ); - return config_content_node_iget_as_double(node , 0); -} - -const char * config_content_get_value_as_path( const config_content_type * config , const char * kw) { - config_content_node_type * node = config_content_get_value_node__( config , kw ); - return config_content_node_iget_as_path(node , 0); -} - -const char * config_content_get_value_as_abspath( const config_content_type * config , const char * kw) { - config_content_node_type * node = config_content_get_value_node__( config , kw ); - return config_content_node_iget_as_abspath(node , 0); -} - -const char * config_content_get_value_as_relpath( const config_content_type * config , const char * kw) { - config_content_node_type * node = config_content_get_value_node__( config , kw ); - return config_content_node_iget_as_relpath(node , 0); -} - - -const char * config_content_get_value(const config_content_type * config , const char * kw) { - config_content_node_type * node = config_content_get_value_node__( config , kw ); - return config_content_node_iget(node , 0); -} - -/*****************************************************************/ - -char * config_content_alloc_joined_string(const config_content_type * content , const char * kw, const char * sep) { - config_content_item_type * item = config_content_get_item(content , kw); - return config_content_item_alloc_joined_string(item , sep); -} - - -/** - This function allocates a new stringlist containing *ALL* the - arguements for an item. With reference to the illustrated example at - the top the function call: - - config_alloc_complete_strtinglist(config , "KEY1"); - - would produce the list: ("ARG1" "ARG2" "ARG2" "VERBOSE"), i.e. the - arguments for the various occurences of "KEY1" are collapsed to one - stringlist. -*/ - - -stringlist_type * config_content_alloc_complete_stringlist(const config_content_type * content , const char * kw) { - bool copy = true; - config_content_item_type * item = config_content_get_item(content , kw); - return config_content_item_alloc_complete_stringlist(item , copy); -} - - - -const stringlist_type * config_content_iget_stringlist_ref(const config_content_type * content , const char * kw, int occurence) { - config_content_item_type * item = config_content_get_item(content , kw); - - return config_content_item_iget_stringlist_ref(item , occurence); -} - -void config_content_add_define( config_content_type * content , const char * key , const char * value ) { - subst_list_append_copy( content->define_list , key , value , NULL ); -} - -subst_list_type * config_content_get_define_list( config_content_type * content ) { - return content->define_list; -} - - -/*****************************************************************/ - - - - -const char * config_content_get_config_file( const config_content_type * content , bool abs_path ) { - if (abs_path) - return content->abs_path; - else - return content->config_file; -} - - -config_path_elm_type * config_content_add_path_elm( config_content_type * content , const char * path ) { - const config_path_elm_type * current_path_elm; - - if (vector_get_size( content->path_elm_stack ) == 0) - current_path_elm = NULL; - else - current_path_elm = vector_get_last_const(content->path_elm_stack); - - { - config_path_elm_type * new_path_elm; - - { - char * rel_path = NULL; - config_root_path_type * invoke_path = config_content_get_invoke_path( content ); - if (path != NULL) { - if (current_path_elm == NULL) - rel_path = util_alloc_rel_path( config_root_path_get_abs_path(invoke_path) , path); - else - rel_path = config_path_elm_alloc_relpath( current_path_elm , path ); - } - new_path_elm = config_path_elm_alloc( invoke_path , rel_path ); - util_safe_free( rel_path ); - } - vector_append_owned_ref( content->path_elm_storage , new_path_elm , config_path_elm_free__); - vector_append_ref( content->path_elm_stack , new_path_elm ); - return new_path_elm; - } -} - -void config_content_pop_path_stack( config_content_type * content ) { - vector_pop_back( content->path_elm_stack ); -} diff --git a/ThirdParty/Ert/libconfig/src/config_content_item.c b/ThirdParty/Ert/libconfig/src/config_content_item.c deleted file mode 100644 index b6d4873f30..0000000000 --- a/ThirdParty/Ert/libconfig/src/config_content_item.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_content_item.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -#define CONFIG_CONTENT_ITEM_ID 8876752 -struct config_content_item_struct { - UTIL_TYPE_ID_DECLARATION; - const config_schema_item_type * schema; - vector_type * nodes; - const config_path_elm_type * path_elm; -}; - - - - - - - - -/*****************************************************************/ - -/** - This function counts the number of times a config item has been - set. Referring again to the example at the top: - - config_content_item_get_occurences( "KEY1" ) - - will return 2. -*/ - - - -int config_content_item_get_size(const config_content_item_type * item) { - return vector_get_size( item->nodes ); -} - - -config_content_node_type * config_content_item_get_last_node(const config_content_item_type * item) { - return vector_get_last( item->nodes ); -} - -config_content_node_type * config_content_item_iget_node(const config_content_item_type * item , int index) { - return vector_iget( item->nodes , index ); -} - -const config_content_node_type * config_content_item_get_last_node_const(const config_content_item_type * item) { - return vector_get_last( item->nodes ); -} - -const config_content_node_type * config_content_item_iget_node_const(const config_content_item_type * item , int index) { - return vector_iget( item->nodes , index ); -} - - -char * config_content_item_ialloc_joined_string(const config_content_item_type * item , const char * sep , int occurence) { - const config_content_node_type * node = config_content_item_iget_node(item , occurence); - return config_content_node_alloc_joined_string(node , sep); -} - - - -char * config_content_item_alloc_joined_string(const config_content_item_type * item , const char * sep) { - const int occurences = config_content_item_get_size( item ); - char * joined_string = NULL; - - for (int i =0; i < occurences ; i++) { - char * element = config_content_item_ialloc_joined_string(item , sep , i); - joined_string = util_strcat_realloc( joined_string , element); - if (i < (occurences - 1)) - joined_string = util_strcat_realloc( joined_string , sep ); - free( element ); - } - - return joined_string; -} - -const stringlist_type * config_content_item_iget_stringlist_ref(const config_content_item_type * item, int occurence) { - const config_content_node_type * node = config_content_item_iget_node(item , occurence); - return config_content_node_get_stringlist( node ); -} - - -const stringlist_type * config_content_item_get_stringlist_ref(const config_content_item_type * item) { - const config_content_node_type * node = config_content_item_get_last_node( item ); - return config_content_node_get_stringlist( node ); -} - - -/** - If copy == false - the stringlist will break down when/if the - config object is freed - your call. -*/ - -stringlist_type * config_content_item_alloc_complete_stringlist(const config_content_item_type * item, bool copy) { - int inode; - stringlist_type * stringlist = stringlist_alloc_new(); - for (inode = 0; inode < vector_get_size( item->nodes ); inode++) { - const config_content_node_type * node = config_content_item_iget_node(item , inode); - const stringlist_type * src_list = config_content_node_get_stringlist( node ); - - if (copy) - stringlist_append_stringlist_copy( stringlist , src_list ); - else - stringlist_append_stringlist_ref( stringlist , src_list ); - - } - - return stringlist; -} - - -/** - If copy == false - the stringlist will break down when/if the - config object is freed - your call. -*/ - -stringlist_type * config_content_item_alloc_stringlist(const config_content_item_type * item, bool copy) { - const config_content_node_type * node = config_content_item_get_last_node( item ); - stringlist_type * stringlist = stringlist_alloc_new(); - const stringlist_type * src_list = config_content_node_get_stringlist( node ); - - if (copy) - stringlist_append_stringlist_copy( stringlist , src_list ); - else - stringlist_append_stringlist_ref( stringlist , src_list ); - - return stringlist; -} - - -/** - If copy == false - the hash will break down when/if the - config object is freed - your call. -*/ - -hash_type * config_content_item_alloc_hash(const config_content_item_type * item , bool copy) { - hash_type * hash = hash_alloc(); - if (item != NULL) { - int inode; - for (inode = 0; inode < vector_get_size( item->nodes ); inode++) { - const config_content_node_type * node = config_content_item_iget_node(item , inode); - const stringlist_type * src_list = config_content_node_get_stringlist( node ); - const char * key = stringlist_iget(src_list , 0); - const char * value = stringlist_iget(src_list , 1); - - if (copy) { - hash_insert_hash_owned_ref(hash , - key , - util_alloc_string_copy(value) , - free); - } else - hash_insert_ref(hash , key , value ); - - } - } - return hash; -} - - -/******************************************************************/ - - - - -const char * config_content_item_iget(const config_content_item_type * item , int occurence , int index) { - const config_content_node_type * node = config_content_item_iget_node(item , occurence); - const stringlist_type * src_list = config_content_node_get_stringlist( node ); - return stringlist_iget( src_list , index ); -} - -bool config_content_item_iget_as_bool(const config_content_item_type * item, int occurence , int index) { - bool value; - config_schema_item_assure_type(item->schema , index , CONFIG_BOOL); - util_sscanf_bool( config_content_item_iget(item , occurence ,index) , &value ); - return value; -} - - - - -int config_content_item_iget_as_int(const config_content_item_type * item, int occurence , int index) { - int value; - config_schema_item_assure_type(item->schema , index , CONFIG_INT); - util_sscanf_int( config_content_item_iget(item , occurence , index) , &value ); - return value; -} - - -double config_content_item_iget_as_double(const config_content_item_type * item, int occurence , int index) { - double value; - config_schema_item_assure_type(item->schema , index , CONFIG_FLOAT); - util_sscanf_double( config_content_item_iget(item , occurence , index) , &value ); - return value; -} - - -/** - Used to reset an item is the special string 'CLEAR_STRING' - is found as the only argument: - - OPTION V1 - OPTION V2 V3 V4 - OPTION __RESET__ - OPTION V6 - - In this case OPTION will get the value 'V6'. The example given - above is a bit contrived; this option is designed for situations - where several config files are parsed serially; and the user can - not/will not update the first. -*/ - -void config_content_item_clear( config_content_item_type * item ) { - vector_clear( item->nodes ); -} - - - -void config_content_item_free( config_content_item_type * item ) { - vector_free( item->nodes ); - free(item); -} - - - -UTIL_SAFE_CAST_FUNCTION( config_content_item , CONFIG_CONTENT_ITEM_ID) -UTIL_IS_INSTANCE_FUNCTION( config_content_item , CONFIG_CONTENT_ITEM_ID) - - -void config_content_item_free__( void * arg ) { - config_content_item_type * content_item = config_content_item_safe_cast( arg ); - config_content_item_free( content_item ); -} - - -config_content_item_type * config_content_item_alloc( const config_schema_item_type * schema , const config_path_elm_type * path_elm) { - config_content_item_type * content_item = util_malloc( sizeof * content_item ); - UTIL_TYPE_ID_INIT( content_item , CONFIG_CONTENT_ITEM_ID ); - content_item->schema = schema; - content_item->nodes = vector_alloc_new(); - content_item->path_elm = path_elm; - return content_item; -} - - - - - -config_content_node_type * config_content_item_alloc_node( const config_content_item_type * item , const config_path_elm_type * path_elm) { - config_content_node_type * node = config_content_node_alloc( item->schema , path_elm ); - vector_append_owned_ref( item->nodes , node , config_content_node_free__); - return node; -} - - - -const config_schema_item_type * config_content_item_get_schema( const config_content_item_type * item ) { - return item->schema; -} - - - - -const config_path_elm_type * config_content_item_get_path_elm( const config_content_item_type * item ) { - return item->path_elm; -} diff --git a/ThirdParty/Ert/libconfig/src/config_content_node.c b/ThirdParty/Ert/libconfig/src/config_content_node.c deleted file mode 100644 index ba9673cb93..0000000000 --- a/ThirdParty/Ert/libconfig/src/config_content_node.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_content_node.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include -#include - -#include -#include -#include - - -#define CONFIG_CONTENT_NODE_ID 6752887 -struct config_content_node_struct { - UTIL_TYPE_ID_DECLARATION; - const config_schema_item_type * schema; - stringlist_type * stringlist; /* The values which have been set. */ - const config_path_elm_type * cwd; - stringlist_type * string_storage; -}; - - -static UTIL_SAFE_CAST_FUNCTION( config_content_node , CONFIG_CONTENT_NODE_ID ) - - - -config_content_node_type * config_content_node_alloc( const config_schema_item_type * schema , const config_path_elm_type * cwd) { - config_content_node_type * node = util_malloc(sizeof * node ); - UTIL_TYPE_ID_INIT( node , CONFIG_CONTENT_NODE_ID ); - node->stringlist = stringlist_alloc_new(); - node->cwd = cwd; - node->schema = schema; - node->string_storage = NULL; - return node; -} - - -void config_content_node_add_value(config_content_node_type * node , const char * value) { - stringlist_append_copy( node->stringlist , value); -} - - -void config_content_node_set(config_content_node_type * node , const stringlist_type * token_list) { - int argc = stringlist_get_size( token_list ) - 1; - for (int iarg=0; iarg < argc; iarg++) - config_content_node_add_value( node , stringlist_iget( token_list , iarg + 1)); -} - - - -char * config_content_node_alloc_joined_string(const config_content_node_type * node, const char * sep) { - return stringlist_alloc_joined_string(node->stringlist , sep); -} - - - -void config_content_node_free(config_content_node_type * node) { - stringlist_free(node->stringlist); - if (node->string_storage != NULL) - stringlist_free( node->string_storage ); - free(node); -} - - - -void config_content_node_free__(void * arg) { - config_content_node_type * node = config_content_node_safe_cast( arg ); - config_content_node_free( node ); -} - -static void config_content_node_push_string( config_content_node_type * node , char * string) { - if (node->string_storage == NULL) - node->string_storage = stringlist_alloc_new( ); - - stringlist_append_owned_ref( node->string_storage , string ); -} - -const char * config_content_node_get_full_string( config_content_node_type * node , const char * sep ) { - char * full_string = stringlist_alloc_joined_string(node->stringlist , sep); - config_content_node_push_string( node , full_string ); - return full_string; -} - -const char * config_content_node_iget(const config_content_node_type * node , int index) { - return stringlist_iget( node->stringlist , index ); -} - - -const char * config_content_node_safe_iget(const config_content_node_type * node , int index) { - if (index >= stringlist_get_size( node->stringlist )) - return NULL; - else - return stringlist_iget( node->stringlist , index ); -} - - -config_item_types config_content_node_iget_type( const config_content_node_type * node , int index) { - return config_schema_item_iget_type( node->schema , index ); -} - - -time_t config_content_node_iget_as_isodate(const config_content_node_type * node , int index) { - time_t value; - config_schema_item_assure_type(node->schema , index , CONFIG_ISODATE); - util_sscanf_isodate( config_content_node_iget(node , index) , &value ); - return value; -} - - -bool config_content_node_iget_as_bool(const config_content_node_type * node , int index) { - bool value; - config_schema_item_assure_type(node->schema , index , CONFIG_BOOL); - util_sscanf_bool( config_content_node_iget(node , index) , &value ); - return value; -} - - -int config_content_node_iget_as_int(const config_content_node_type * node , int index) { - int value; - config_schema_item_assure_type(node->schema , index , CONFIG_INT); - util_sscanf_int( config_content_node_iget(node , index) , &value ); - return value; -} - - - -double config_content_node_iget_as_double(const config_content_node_type * node , int index) { - double value; - config_schema_item_assure_type(node->schema , index , CONFIG_FLOAT + CONFIG_INT); - util_sscanf_double( config_content_node_iget(node , index) , &value ); - return value; -} - - - - -const char * config_content_node_iget_as_path(config_content_node_type * node , int index) { - config_schema_item_assure_type(node->schema , index , CONFIG_PATH + CONFIG_EXISTING_PATH); - { - const char * config_value = config_content_node_iget(node , index); - char * path_value = config_path_elm_alloc_path( node->cwd , config_value ); - config_content_node_push_string( node , path_value ); - - return path_value; - } -} - - -const char * config_content_node_iget_as_abspath( config_content_node_type * node , int index) { - config_schema_item_assure_type(node->schema , index , CONFIG_PATH + CONFIG_EXISTING_PATH); - { - const char * config_value = config_content_node_iget(node , index); - char * path_value = config_path_elm_alloc_abspath( node->cwd , config_value ); - config_content_node_push_string( node , path_value ); - - return path_value; - } -} - - -const char * config_content_node_iget_as_relpath( config_content_node_type * node , int index) { - config_schema_item_assure_type(node->schema , index , CONFIG_PATH + CONFIG_EXISTING_PATH); - { - const char * config_value = config_content_node_iget(node , index); - char * path_value = config_path_elm_alloc_relpath( node->cwd , config_value ); - config_content_node_push_string( node , path_value ); - - return path_value; - } -} - - -const stringlist_type * config_content_node_get_stringlist( const config_content_node_type * node ) { - return node->stringlist; -} - - -const char * config_content_node_get_kw( const config_content_node_type * node ) { - return config_schema_item_get_kw( node->schema ); -} - - - - -int config_content_node_get_size( const config_content_node_type * node ) { - return stringlist_get_size( node->stringlist ); -} - - -void config_content_node_assert_key_value( const config_content_node_type * node ) { - int argc_min , argc_max; - config_schema_item_get_argc( node->schema , &argc_min , &argc_max); - - if (!((argc_min == 1) && (argc_min == 1))) - util_abort("%s: item:%s before calling config_get_value() functions *without* index you must set argc_min == argc_max = 1 \n",__func__ , config_schema_item_get_kw( node->schema )); -} - - -const config_path_elm_type * config_content_node_get_path_elm( const config_content_node_type * node ) { - return node->cwd; -} - -/** - The node should contain elements of the type: - - KEY1:VALUE1 KEY2:Value2 XX Key3:Val3 Ignored - - Which will be inserted in the opt_hash dictionary as : {"KEY1" : - "VALUE1" , ... } Elements which do not conform to this syntax are - ignored. -*/ - - -void config_content_node_init_opt_hash( const config_content_node_type * node , hash_type * opt_hash , int elm_offset) { - int i; - for (i = elm_offset; i < config_content_node_get_size( node ); i++) - hash_add_option( opt_hash , config_content_node_iget( node , i )); -} - - -void config_content_node_fprintf( const config_content_node_type * node , FILE * stream ) { - fprintf(stream , "%s: {" , config_schema_item_get_kw( node->schema )); - stringlist_fprintf( node->stringlist , ", " , stream ); - fprintf(stream , "}\n"); -} diff --git a/ThirdParty/Ert/libconfig/src/config_error.c b/ThirdParty/Ert/libconfig/src/config_error.c deleted file mode 100644 index 9924e94b62..0000000000 --- a/ThirdParty/Ert/libconfig/src/config_error.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_error.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include -#include - -#include - -struct config_error_struct { - stringlist_type * error_list; -}; - - - -config_error_type * config_error_alloc() { - config_error_type * error = util_malloc( sizeof * error ); - error->error_list = stringlist_alloc_new(); - return error; -} - - -config_error_type * config_error_alloc_copy( const config_error_type * src_error) { - config_error_type * config_error = config_error_alloc(); - stringlist_deep_copy( config_error->error_list , src_error->error_list ); - return config_error; -} - - -bool config_error_equal( const config_error_type * error1 , const config_error_type * error2) { - return stringlist_equal( error1->error_list , error2->error_list ); -} - -void config_error_free( config_error_type * error ) { - stringlist_free( error->error_list ); - free( error ); -} - - - -void config_error_add( config_error_type * error , char * new_error) { - stringlist_append_copy( error->error_list , new_error ); -} - - - -void config_error_clear( config_error_type * error ) { - stringlist_clear( error->error_list ); -} - - -int config_error_count( const config_error_type * error ) { - return stringlist_get_size( error->error_list ); -} - - -const char * config_error_iget( const config_error_type * error , int index) { - return stringlist_iget( error->error_list , index ); -} - - -void config_error_fprintf( const config_error_type * error , bool add_count , FILE * stream ) { - int error_nr; - - for (error_nr = 0; error_nr < stringlist_get_size( error->error_list ); error_nr++) { - if (add_count) - fprintf(stream , " %02d: " , error_nr); - - fprintf( stream , "%s\n" , stringlist_iget( error->error_list , error_nr)); - } -} diff --git a/ThirdParty/Ert/libconfig/src/config_get.c b/ThirdParty/Ert/libconfig/src/config_get.c deleted file mode 100644 index ea331b7c06..0000000000 --- a/ThirdParty/Ert/libconfig/src/config_get.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_get.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -/*****************************************************************/ -/* All the functions in this block will operate on the last item - which has been set with a particular key value. So assuming the - config file looks like: - - KEY VALUE1 - KEY VALUE2 OPTIONAL - KEY 100 VALUE3 OPTIONAL ERROR - - these functions will all operate on the last line in the config file: - - KEY 100 VALUE3 OPTIONAL ERROR -*/ - - -/*config_content_node_type * config_get_value_node( const config_parser_type * config , const char * kw) { - config_content_item_type * item = config_get_content_item(config , kw); - if (item != NULL) { - config_content_node_type * node = config_content_item_get_last_node( item ); - config_content_node_assert_key_value( node ); - return node; - } else - return NULL; // Will return NULL on unset keywords - must check NULL return value?! -} - -static config_content_node_type * config_get_value_node__( const config_parser_type * config , const char * kw) { - config_content_node_type * node = config_get_value_node( config , kw ); - if (node == NULL) - util_abort("Tried to get value node from unset kw:%s \n",__func__ , kw ); - - return node; -} - -bool config_get_value_as_bool(const config_parser_type * config , const char * kw) { - config_content_node_type * node = config_get_value_node__( config , kw ); - return config_content_node_iget_as_bool(node , 0); -} - -int config_get_value_as_int(const config_parser_type * config , const char * kw) { - config_content_node_type * node = config_get_value_node__( config , kw ); - return config_content_node_iget_as_int(node , 0); -} - -double config_get_value_as_double(const config_parser_type * config , const char * kw) { - config_content_node_type * node = config_get_value_node__( config , kw ); - return config_content_node_iget_as_double(node , 0); -} - -const char * config_get_value_as_path( const config_parser_type * config , const char * kw) { - config_content_node_type * node = config_get_value_node__( config , kw ); - return config_content_node_iget_as_path(node , 0); -} - -const char * config_get_value_as_abspath( const config_parser_type * config , const char * kw) { - config_content_node_type * node = config_get_value_node__( config , kw ); - return config_content_node_iget_as_abspath(node , 0); -} - -const char * config_get_value_as_relpath( const config_parser_type * config , const char * kw) { - config_content_node_type * node = config_get_value_node__( config , kw ); - return config_content_node_iget_as_relpath(node , 0); -} - - -const char * config_get_value(const config_parser_type * config , const char * kw) { - config_content_node_type * node = config_get_value_node__( config , kw ); - return config_content_node_iget(node , 0); -} -*/ - -/*****************************************************************/ - - - - - - -int config_get_schema_size( const config_parser_type * config ) { - return hash_get_size( config->schema_items ); -} - - - - diff --git a/ThirdParty/Ert/libconfig/src/config_parser.c b/ThirdParty/Ert/libconfig/src/config_parser.c deleted file mode 100644 index 10be6237d2..0000000000 --- a/ThirdParty/Ert/libconfig/src/config_parser.c +++ /dev/null @@ -1,719 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define CLEAR_STRING "__RESET__" - - - -/** -Structure to parse configuration files of this type: - -KEYWORD1 ARG2 ARG2 ARG3 -KEYWORD2 ARG1-2 -.... -KEYWORDN ARG1 ARG2 - -A keyword can occure many times. - -*/ - - - -/** - - - ============================= - | config_type object | - | | - | Contains 'all' the | - | configuration information.| - | | - ============================= - | | - | \________________________ - | \ - KEY1 KEY2 - | | - \|/ \|/ - ========================= ========================= - | config_item object | | config_item object | - | | | | - | Indexed by a keyword | | Indexed by a keyword | - | which is the first | | which is the first | - | string in the | | string in the | - | config file. | | config file. | - | | | | - ========================= ========================= - | | | - | | | - \|/ \|/ \|/ -============================ ============================ ============================ -| config_item_node object | | config_item_node object | | config_item_node object | -| | | | | | -| Only containing the | | Only containing the | | Only containing the | -| stringlist object | | stringlist object | | stringlist object | -| directly parsed from the | | directly parsed from the | | directly parsed from the | -| file. | | file. | | file. | -|--------------------------| |--------------------------| |--------------------------| -| ARG1 ARG2 ARG3 | | VERBOSE | | DEBUG | -============================ ============================ ============================ - - -The example illustrated above would correspond to the following config -file (invariant under line-permutations): - -KEY1 ARG1 ARG2 ARG3 -KEY1 VERBOSE -KEY2 DEBUG - - -Example config file(2): - -OUTFILE filename -INPUT filename -OPTIONS store -OPTIONS verbose -OPTIONS optimize cache=1 - -In this case the whole config object will contain three items, -corresponding to the keywords OUTFILE, INPUT and OPTIONS. The two -first will again only contain one node each, whereas the OPTIONS item -will contain three nodes, corresponding to the three times the keyword -"OPTIONS" appear in the config file. -*/ - - - - - - - - - - - -struct config_parser_struct { - hash_type * schema_items; - hash_type * messages; /* Can print a (warning) message when a keyword is encountered. */ -}; - - - - - - - - - - - - - - - - - - -/* - The last argument (config_file) is only used for printing - informative error messages, and can be NULL. The config_cwd is - essential if we are looking up a filename, otherwise it can be NULL. - - Returns a string with an error description, or NULL if the supplied - arguments were OK. The string is allocated here, but is assumed that - calling scope will free it. -*/ - -static config_content_node_type * config_content_item_set_arg__(subst_list_type * define_list , - config_error_type * parse_errors , - config_content_item_type * item , - stringlist_type * token_list , - const config_path_elm_type * path_elm , - const char * config_file ) { - - config_content_node_type * new_node = NULL; - int argc = stringlist_get_size( token_list ) - 1; - - if (argc == 1 && (strcmp(stringlist_iget(token_list , 1) , CLEAR_STRING) == 0)) { - config_content_item_clear(item); - } else { - const config_schema_item_type * schema_item = config_content_item_get_schema( item ); - - /* Filtering based on DEFINE statements */ - if (subst_list_get_size( define_list ) > 0) { - int iarg; - for (iarg = 0; iarg < argc; iarg++) { - char * filtered_copy = subst_list_alloc_filtered_string( define_list , stringlist_iget(token_list , iarg + 1)); - stringlist_iset_owned_ref( token_list , iarg + 1 , filtered_copy); - } - } - - - /* Filtering based on environment variables */ - if (config_schema_item_expand_envvar( schema_item )) { - int iarg; - for (iarg = 0; iarg < argc; iarg++) { - int env_offset = 0; - while (true) { - char * env_var = util_isscanf_alloc_envvar( stringlist_iget(token_list , iarg + 1) , env_offset ); - if (env_var == NULL) - break; - - { - const char * env_value = getenv( &env_var[1] ); - if (env_value != NULL) { - char * new_value = util_string_replace_alloc( stringlist_iget( token_list , iarg + 1 ) , env_var , env_value ); - stringlist_iset_owned_ref( token_list , iarg + 1 , new_value ); - } else { - env_offset += 1; - fprintf(stderr,"** Warning: environment variable: %s is not defined \n", env_var); - } - } - - free( env_var ); - } - } - } - - { - if (config_schema_item_validate_set(schema_item , token_list , config_file, path_elm , parse_errors)) { - new_node = config_content_item_alloc_node( item , config_content_item_get_path_elm( item )); - config_content_node_set(new_node , token_list); - } - } - } - return new_node; -} - - - - - -/*****************************************************************/ - - - -config_parser_type * config_alloc() { - config_parser_type *config = util_malloc(sizeof * config ); - config->schema_items = hash_alloc(); - config->messages = hash_alloc(); - return config; -} - - - - - - - - - - -void config_free(config_parser_type * config) { - - hash_free(config->schema_items); - hash_free(config->messages); - - free(config); -} - - - -static void config_insert_schema_item(config_parser_type * config , const char * kw , const config_schema_item_type * item , bool ref) { - if (ref) - hash_insert_ref(config->schema_items , kw , item); - else - hash_insert_hash_owned_ref(config->schema_items , kw , item , config_schema_item_free__); -} - - -/** - This function allocates a simple item with all values - defaulted. The item is added to the config object, and a pointer is - returned to the calling scope. If you want to change the properties - of the item you can do that with config_schema_item_set_xxxx() functions - from the calling scope. -*/ - - -config_schema_item_type * config_add_schema_item(config_parser_type * config , - const char * kw, - bool required) { - - config_schema_item_type * item = config_schema_item_alloc( kw , required ); - config_insert_schema_item(config , kw , item , false); - return item; -} - - - -/** - This is a minor wrapper for adding an item with the properties. - - 1. It has argc_minmax = {1,1} - - The value can than be extracted with config_get_value() and - config_get_value_as_xxxx functions. -*/ - -config_schema_item_type * config_add_key_value( config_parser_type * config , const char * key , bool required , config_item_types item_type) { - config_schema_item_type * item = config_add_schema_item( config , key , required ); - config_schema_item_set_argc_minmax( item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , item_type ); - return item; -} - - - -bool config_has_schema_item(const config_parser_type * config , const char * kw) { - return hash_has_key(config->schema_items , kw); -} - - -config_schema_item_type * config_get_schema_item(const config_parser_type * config , const char * kw) { - return hash_get(config->schema_items , kw); -} - -/* - Due to the possibility of aliases we must go through the canonical - keyword which is internalized in the schema_item. -*/ - - - - - - - - - -static void config_validate_content_item(const config_parser_type * config , config_content_type * content , const config_content_item_type * item) { - const config_schema_item_type * schema_item = config_content_item_get_schema( item ); - const char * schema_kw = config_schema_item_get_kw( schema_item ); - - { - int i; - for (i = 0; i < config_schema_item_num_required_children(schema_item); i++) { - const char * required_child = config_schema_item_iget_required_child( schema_item , i ); - if (!config_content_has_item(content , required_child)) { - char * error_message = util_alloc_sprintf("When:%s is set - you also must set:%s.",schema_kw , required_child); - config_error_add( config_content_get_errors( content ) , error_message ); - free( error_message ); - } - } - - if (config_schema_item_has_required_children_value( schema_item )) { - int inode; - for (inode = 0; inode < config_content_item_get_size(item); inode++) { - config_content_node_type * node = config_content_item_iget_node(item , inode); - const stringlist_type * values = config_content_node_get_stringlist( node ); - int is; - - for (is = 0; is < stringlist_get_size(values); is++) { - const char * value = stringlist_iget(values , is); - stringlist_type * required_children = config_schema_item_get_required_children_value( schema_item , value ); - - if (required_children != NULL) { - int ic; - for (ic = 0; ic < stringlist_get_size( required_children ); ic++) { - const char * req_child = stringlist_iget( required_children , ic ); - if (!config_content_has_item(content , req_child )) { - char * error_message = util_alloc_sprintf("When:%s is set to:%s - you also must set:%s.",schema_kw , value , req_child ); - config_error_add( config_content_get_errors( content ) , error_message ); - free( error_message ); - } - } - } - } - } - } - } -} - - - -static void config_validate(config_parser_type * config, config_content_type * content , const char * filename) { - int size = hash_get_size(config->schema_items); - char ** key_list = hash_alloc_keylist(config->schema_items); - int ikey; - for (ikey = 0; ikey < size; ikey++) { - const config_schema_item_type * schema_item = config_get_schema_item( config , key_list[ikey]); - const char * content_key = config_schema_item_get_kw( schema_item ); - if (config_content_has_item( content , content_key)) { - const config_content_item_type * item = config_content_get_item(content , content_key); - config_validate_content_item(config , content , item ); - } else { - if (config_schema_item_required( schema_item)) { /* The item is not set ... */ - char * error_message = util_alloc_sprintf("Item:%s must be set - parsing:%s",content_key , config_content_get_config_file( content , true )); - config_error_add( config_content_get_errors( content ) , error_message ); - free( error_message ); - } - } - } - util_free_stringlist(key_list , size); -} - - - - - - - -/** - This function parses the config file 'filename', and updated the - internal state of the config object as parsing proceeds. If - comment_string != NULL everything following 'comment_string' on a - line is discarded. - - include_kw is a string identifier for an include functionality, if - an include is encountered, the included file is parsed immediately - (through a recursive call to config_parse__). if include_kw == NULL, - include files are not supported. - - Observe that use of include, relative paths and all that shit is - quite tricky. The following is currently implemented: - - 1. The front_end function will split the path to the config file - in a path_name component and a file component. - - 2. Recursive calls to config_parse__() will keep control of the - parsers notion of cwd (note that the real OS'wise cwd never - changes), and every item is tagged with the config_cwd - currently active. - - 3. When an item has been entered with type CONFIG_FILE / - CONFIG_DIRECTORY / CONFIG_EXECUTABLE - the item is updated to - reflect to be relative (iff it is relative in the first place) - to the path of the root config file. - - These are not strict rules - it is possible to get other things to - work as well, but the problem is that it very quickly becomes - dependant on 'arbitrariness' in the parsing configuration. - - validate: whether we should validate when complete, that should - typically only be done at the last parsing. - - - define_kw: This a string which can serve as a "#define" for the - parsing. The define_kw keyword should have two arguments - a key - and a value. If the define_kw is present all __subsequent__ - occurences of 'key' are replaced with 'value'. alloc_new_key - is an optinal function (can be NULL) which is used to alloc a new - key, i.e. add leading and trailing 'magic' characters. - - - Example: - -------- - - char * add_angular_brackets(const char * key) { - char * new_key = util_alloc_sprintf("<%s>" , key); - } - - - - config_parse(... , "myDEF" , add_angular_brackets , ...) - - - Config file: - ------------- - myDEF Name BJARNE - myDEF sexual-pref Dogs - ... - ... - PERSON 28 - ... - ------------ - - After parsing we will have an entry: "NAME" , "Bjarne" , "28" , "Dogs". - - The key-value pairs internalized during the config parsing are NOT - returned to the calling scope in any way. -*/ - - -static void config_parse__(config_parser_type * config , - config_content_type * content , - path_stack_type * path_stack , - const char * config_input , - const char * comment_string , - const char * include_kw , - const char * define_kw , - config_schema_unrecognized_enum unrecognized, - bool validate) { - - /* Guard against circular includes. */ - { - char * abs_filename = util_alloc_realpath(config_input); - if (!config_content_add_file( content , abs_filename )) - util_exit("%s: file:%s already parsed - circular include ? \n",__func__ , abs_filename); - free( abs_filename ); - } - config_path_elm_type * current_path_elm; - - char * config_file; - { - /* Extract the path component of the current input file and chdir() */ - char * config_path; - { - char * config_base; - char * config_ext; - util_alloc_file_components( config_input , &config_path , &config_base , &config_ext); - config_file = util_alloc_filename( NULL , config_base , config_ext ); - free( config_base ); - util_safe_free( config_ext ); - } - current_path_elm = config_content_add_path_elm( content , config_path ); - path_stack_push_cwd( path_stack ); - if (config_path != NULL) { - util_chdir( config_path ); - free( config_path ); - } - } - - - { - const char * comment_end = comment_string ? "\n" : NULL; - basic_parser_type * parser = basic_parser_alloc(" \t" , "\"", NULL , NULL , comment_string , comment_end); - FILE * stream = util_fopen(config_file , "r"); - bool at_eof = false; - - while (!at_eof) { - int active_tokens; - stringlist_type * token_list; - char *line_buffer; - - - line_buffer = util_fscanf_alloc_line(stream , &at_eof); - if (line_buffer != NULL) { - token_list = basic_parser_tokenize_buffer(parser , line_buffer , true); - active_tokens = stringlist_get_size( token_list ); - - /* - util_split_string(line_buffer , " \t" , &tokens , &token_list); - active_tokens = tokens; - for (i = 0; i < tokens; i++) { - char * comment_ptr = NULL; - if(comment_string != NULL) - comment_ptr = strstr(token_list[i] , comment_string); - - if (comment_ptr != NULL) { - if (comment_ptr == token_list[i]) - active_tokens = i; - else - active_tokens = i + 1; - break; - } - } - */ - - if (active_tokens > 0) { - const char * kw = stringlist_iget( token_list , 0 ); - - /*Treating the include keyword. */ - if (include_kw != NULL && (strcmp(include_kw , kw) == 0)) { - if (active_tokens != 2) - util_abort("%s: keyword:%s must have exactly one argument. \n",__func__ ,include_kw); - { - const char *include_file = stringlist_iget( token_list , 1); - if (util_file_exists( include_file )) - config_parse__(config , content , path_stack , include_file , comment_string , include_kw , define_kw , unrecognized, false); /* Recursive call */ - else { - char * error_message = util_alloc_sprintf("%s file:%s not found" , include_kw , include_file); - config_error_add( config_content_get_errors( content ) , error_message ); - free( error_message ); - } - } - } else if ((define_kw != NULL) && (strcmp(define_kw , kw) == 0)) { - /* Treating the define keyword. */ - if (active_tokens < 3) - util_abort("%s: keyword:%s must have exactly one (or more) arguments. \n",__func__ , define_kw); - { - char * key = util_alloc_string_copy( stringlist_iget(token_list ,1) ); - char * value = stringlist_alloc_joined_substring( token_list , 2 , active_tokens , " "); - - { - char * filtered_value = subst_list_alloc_filtered_string( config_content_get_define_list( content ) , value); - config_content_add_define( content , key , filtered_value ); - free( filtered_value ); - } - free(key); - free(value); - } - } else { - if (hash_has_key(config->messages , kw)) - printf("%s \n", (const char *) hash_get(config->messages , kw)); - - if (!config_has_schema_item(config , kw)) { - if (unrecognized == CONFIG_UNRECOGNIZED_WARN) - fprintf(stderr,"** Warning keyword:%s not recognized when parsing:%s --- \n" , kw , config_input); - else if (unrecognized == CONFIG_UNRECOGNIZED_ERROR) { - char * error_message = util_alloc_sprintf("Keyword:%s is not recognized" , kw); - config_error_add( config_content_get_errors( content ) , error_message ); - free( error_message ); - } - } - - if (config_has_schema_item(config , kw)) { - config_schema_item_type * schema_item = config_get_schema_item( config , kw ); - char * config_cwd; - util_alloc_file_components( config_file , &config_cwd , NULL , NULL ); - - if (!config_content_has_item( content , kw )) - config_content_add_item( content , schema_item , current_path_elm); - - - { - subst_list_type * define_list = config_content_get_define_list( content ); - config_content_item_type * content_item = config_content_get_item( content , config_schema_item_get_kw( schema_item ) ); - config_content_node_type * new_node = config_content_item_set_arg__(define_list , config_content_get_errors( content ) , content_item , token_list , current_path_elm , config_file ); - if (new_node) - config_content_add_node( content , new_node ); - - } - } - } - } - stringlist_free(token_list); - free(line_buffer); - } - } - if (validate) - config_validate(config , content , config_file); - fclose(stream); - basic_parser_free( parser ); - } - free(config_file); - path_stack_pop( path_stack ); - config_content_pop_path_stack( content ); -} - - - - - - - - - - - - -config_content_type * config_parse(config_parser_type * config , - const char * filename, - const char * comment_string , - const char * include_kw , - const char * define_kw , - const hash_type * pre_defined_kw_map, - config_schema_unrecognized_enum unrecognized_behaviour, - bool validate) { - - config_content_type * content = config_content_alloc( filename ); - - if(pre_defined_kw_map != NULL) { - hash_iter_type * keys = hash_iter_alloc(pre_defined_kw_map); - - while(!hash_iter_is_complete(keys)) { - const char * key = hash_iter_get_next_key(keys); - const char * value = hash_get(pre_defined_kw_map, key); - config_content_add_define( content , key , value ); - } - - hash_iter_free(keys); - } - - - if (util_file_readable( filename )) { - path_stack_type * path_stack = path_stack_alloc(); - config_parse__(config , content , path_stack , filename , comment_string , include_kw , define_kw , unrecognized_behaviour , validate); - path_stack_free( path_stack ); - } else { - char * error_message = util_alloc_sprintf("Could not open file:%s for parsing" , filename); - config_error_add( config_content_get_errors( content ) , error_message ); - free( error_message ); - } - - if (config_error_count( config_content_get_errors( content ) ) == 0) - config_content_set_valid( content ); - - return content; -} - - - - -/*****************************************************************/ - - - - -/** - This function adds an alias to an existing item; so that the - value+++ of an item can be referred to by two different names. -*/ - - -void config_add_alias(config_parser_type * config , const char * src , const char * alias) { - if (config_has_schema_item(config , src)) { - config_schema_item_type * item = config_get_schema_item(config , src); - config_insert_schema_item(config , alias , item , true); - } else - util_abort("%s: item:%s not recognized \n",__func__ , src); -} - - - -void config_install_message(config_parser_type * config , const char * kw, const char * message) { - hash_insert_hash_owned_ref(config->messages , kw , util_alloc_string_copy(message) , free); -} - - -void config_parser_deprecate(config_parser_type * config , const char * kw, const char * msg) { - if (config_has_schema_item(config , kw)) { - config_schema_item_type * item = config_get_schema_item(config , kw); - config_schema_item_set_deprecated(item , msg); - } else - util_abort("%s: item:%s not recognized \n",__func__ , kw); -} - - -#include "config_get.c" - - diff --git a/ThirdParty/Ert/libconfig/src/config_path_elm.c b/ThirdParty/Ert/libconfig/src/config_path_elm.c deleted file mode 100644 index ca0f8dfbe3..0000000000 --- a/ThirdParty/Ert/libconfig/src/config_path_elm.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'config_path_elm.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#define CONFIG_PATH_ELM_TYPE_ID 7100063 - -struct config_path_elm_struct { - UTIL_TYPE_ID_DECLARATION; - char * abs_path; // This will always be absolute - char * rel_path; // This will always be relative to the root path. - const config_root_path_type * root_path; -}; - -static UTIL_SAFE_CAST_FUNCTION( config_path_elm , CONFIG_PATH_ELM_TYPE_ID ) - - -config_path_elm_type * config_path_elm_alloc( const config_root_path_type * root_path , const char * path) { - if (root_path != NULL) { - config_path_elm_type * path_elm = util_malloc( sizeof * path_elm ); - UTIL_TYPE_ID_INIT(path_elm , CONFIG_PATH_ELM_TYPE_ID); - path_elm->root_path = root_path; - if (path == NULL) { - path_elm->rel_path = NULL; - path_elm->abs_path = util_alloc_string_copy( config_root_path_get_abs_path(root_path) ); - } else { - if (util_is_abs_path( path )) { - path_elm->abs_path = util_alloc_string_copy( path ); - path_elm->rel_path = util_alloc_rel_path( config_root_path_get_abs_path(root_path) , path ); - } else { - { - char * tmp_abs_path = util_alloc_filename( config_root_path_get_abs_path(root_path) , path , NULL ); - path_elm->abs_path = util_alloc_abs_path( tmp_abs_path ); - free( tmp_abs_path ); - } - path_elm->rel_path = util_alloc_string_copy( path ); - } - } - return path_elm; - } else { - util_abort("%s: root_path input argument == NULL - invalid \n",__func__); - return NULL; - } -} - - - - -void config_path_elm_free( config_path_elm_type * path_elm ) { - util_safe_free( path_elm->rel_path ); - util_safe_free( path_elm->abs_path ); - free( path_elm ); -} - - - -void config_path_elm_free__( void * arg ) { - config_path_elm_type * path_elm = config_path_elm_safe_cast( arg ); - config_path_elm_free( path_elm ); -} - -const config_root_path_type * config_path_elm_get_rootpath( const config_path_elm_type * path_elm ) { - return path_elm->root_path; -} - -const char * config_path_elm_get_relpath( const config_path_elm_type * path_elm ) { - return path_elm->rel_path; -} - -const char * config_path_elm_get_abspath( const config_path_elm_type * path_elm ) { - return path_elm->abs_path; -} - - -/*****************************************************************/ - - -char * config_path_elm_alloc_path(const config_path_elm_type * path_elm , const char * path) { - if (util_is_abs_path( path )) - return util_alloc_string_copy( path ); - else { - /* This will be relative or absolute depending on the relative/absolute - status of the root_path. */ - const char * input_root = config_root_path_get_input_path( path_elm->root_path ); - if (input_root == NULL) - return util_alloc_filename( path_elm->rel_path , path , NULL); - else - return util_alloc_joined_string( (const char *[3]) { input_root , path_elm->rel_path , path } , 3 , UTIL_PATH_SEP_STRING ); - } -} - - -char * config_path_elm_alloc_relpath(const config_path_elm_type * path_elm , const char * input_path) { - if (util_is_abs_path( input_path )) - return util_alloc_rel_path( config_root_path_get_rel_path( path_elm->root_path ) , input_path); - else { - char * abs_path = config_path_elm_alloc_abspath( path_elm , input_path ); - char * rel_path = util_alloc_rel_path( config_root_path_get_abs_path( path_elm->root_path ) , abs_path ); - free( abs_path ); - return rel_path; - } -} - - -char * config_path_elm_alloc_abspath(const config_path_elm_type * path_elm , const char * input_path) { - if (util_is_abs_path( input_path )) - return util_alloc_string_copy( input_path ); - else { - char * abs_path1 = util_alloc_filename( path_elm->abs_path , input_path , NULL ); - char * abs_path = util_alloc_realpath__( abs_path1 ); // The util_alloc_realpath__() will work also for nonexsting paths - free( abs_path1 ); - return abs_path; - } -} diff --git a/ThirdParty/Ert/libconfig/src/config_root_path.c b/ThirdParty/Ert/libconfig/src/config_root_path.c deleted file mode 100644 index ba251bbc6f..0000000000 --- a/ThirdParty/Ert/libconfig/src/config_root_path.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'config_root_path.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include - -#include - -#include - -struct config_root_path_struct { - char * input_path; - char * abs_path; - char * rel_path; -}; - - -/** - Input must be an existing directory, which will be used as the - root; or NULL in which case cwd will be used as root. The input - directory can be both realtive or absolute. -*/ - -config_root_path_type * config_root_path_alloc( const char * input_path ) { - if (input_path == NULL || util_is_directory( input_path )) { - config_root_path_type * root_path = util_malloc( sizeof * root_path ); - { - char * cwd = util_alloc_cwd(); - - root_path->input_path = util_alloc_string_copy( input_path ); - if (input_path == NULL) { - root_path->rel_path = NULL; - root_path->abs_path = util_alloc_string_copy( cwd ); - } else { - if (util_is_abs_path( input_path )) { - root_path->abs_path = util_alloc_string_copy( input_path ); - root_path->rel_path = util_alloc_rel_path( cwd , root_path->abs_path); - } else { - root_path->rel_path = util_alloc_string_copy( input_path ); - { - char * abs_path = util_alloc_filename( cwd , input_path , NULL ); - root_path->abs_path = util_alloc_realpath( abs_path ); - free( abs_path ); - } - } - } - free( cwd ); - } - return root_path; - } else - return NULL; -} - - -void config_root_path_free( config_root_path_type * root_path ) { - util_safe_free( root_path->rel_path ); - util_safe_free( root_path->abs_path ); - util_safe_free( root_path->input_path ); - free( root_path ); -} - -const char * config_root_path_get_input_path( const config_root_path_type * root_path ) { - return root_path->input_path; -} - - -const char * config_root_path_get_rel_path( const config_root_path_type * root_path ) { - return root_path->rel_path; -} - - -const char * config_root_path_get_abs_path( const config_root_path_type * root_path ) { - return root_path->abs_path; -} - - -void config_root_path_printf( const config_root_path_type * root_path ) { - printf("input_path : %s \n" , root_path->input_path); - printf("abs_path : %s \n" , root_path->abs_path); - printf("rel_path : %s \n" , root_path->rel_path); -} - - diff --git a/ThirdParty/Ert/libconfig/src/config_schema_item.c b/ThirdParty/Ert/libconfig/src/config_schema_item.c deleted file mode 100644 index 897d360fd5..0000000000 --- a/ThirdParty/Ert/libconfig/src/config_schema_item.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_schema_item.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -typedef struct validate_struct validate_type; - -/** - This is a 'support-struct' holding various pieces of information - needed during the validation process. Observe the following about - validation: - - 1. It is atomic, in the sense that if you try to an item like this: - - KW ARG1 ARG2 ARG3 - - where ARG1 and ARG2 are valid, whereas there is something wrong - with ARG3, NOTHING IS SET. - - 2. Validation is a two-step process, the first step is run when an - item is parsed. This includes checking: - - o The number of argument. - o That the arguments have the right type. - o That the values match the selection set. - - The second validation step is done when the pasing is complete, - in this pass we check dependencies - i.e. required_children and - required_children_on_value. - - - Observe that nothing has-to be set in this struct. There are some dependencies: - - 1. Only _one_ of common_selection_set and indexed_selection_set - can be set. - - 2. If setting indexed_selection_set or type_map, you MUST set - argc_max first. -*/ - - -struct validate_struct { - int argc_min; /* The minimum number of arguments: -1 means no lower limit. */ - int argc_max; /* The maximum number of arguments: -1 means no upper limit. */ - set_type * common_selection_set; /* A selection set which will apply uniformly to all the arguments. */ - int_vector_type * type_map; /* A list of types for the items. Set along with argc_minmax(); */ - stringlist_type * required_children; /* A list of item's which must also be set (if this item is set). (can be NULL) */ - hash_type * required_children_value; /* A list of item's which must also be set - depending on the value of this item. (can be NULL) (This one is complex). */ - vector_type * indexed_selection_set; /* A vector of set_type instances which will apply for specific (indexed) arguments. */ -}; - - - - - -#define CONFIG_SCHEMA_ITEM_ID 6751 -struct config_schema_item_struct { - UTIL_TYPE_ID_DECLARATION; - char * kw; /* The kw which identifies this item */ - - - bool required_set; - stringlist_type * required_children; /* A list of item's which must also be set (if this item is set). (can be NULL) */ - hash_type * required_children_value; /* A list of item's which must also be set - depending on the value of this item. (can be NULL) */ - validate_type * validate; /* Information need during validation. */ - bool expand_envvar; /* Should environment variables like $HOME be expanded?*/ - bool deprecated; - char * deprecate_msg; -}; - - -/*****************************************************************/ - - -/*****************************************************************/ -static void validate_set_default_type( validate_type * validate , config_item_types item_type) { - int_vector_set_default(validate->type_map , item_type); -} - -static validate_type * validate_alloc() { - validate_type * validate = util_malloc(sizeof * validate ); - validate->argc_min = CONFIG_DEFAULT_ARG_MIN; - validate->argc_max = CONFIG_DEFAULT_ARG_MAX; - validate->common_selection_set = NULL; - validate->indexed_selection_set = vector_alloc_new(); - validate->required_children = NULL; - validate->required_children_value = NULL; - validate->type_map = int_vector_alloc(0 , 0); - validate_set_default_type( validate , CONFIG_STRING ); - return validate; -} - - -static void validate_free(validate_type * validate) { - if (validate->common_selection_set != NULL) set_free(validate->common_selection_set); - - vector_free( validate->indexed_selection_set ); - int_vector_free( validate->type_map ); - if (validate->required_children != NULL) stringlist_free(validate->required_children); - if (validate->required_children_value != NULL) hash_free(validate->required_children_value); - free(validate); -} - - -static void validate_iset_type( validate_type * validate , int index , config_item_types type) { - int_vector_iset( validate->type_map , index , type); -} - - -static config_item_types validate_iget_type( const validate_type * validate , int index) { - return int_vector_safe_iget( validate->type_map , index ); -} - - -static void validate_set_argc_minmax(validate_type * validate , int argc_min , int argc_max) { - if (validate->argc_min != CONFIG_DEFAULT_ARG_MIN) - util_abort("%s: sorry - current implementation does not allow repeated calls to: %s \n",__func__ , __func__); - - if (argc_min == CONFIG_DEFAULT_ARG_MIN) - argc_min = 0; - - validate->argc_min = argc_min; - validate->argc_max = argc_max; - - if ((argc_max != CONFIG_DEFAULT_ARG_MAX) && (argc_max < argc_min)) - util_abort("%s invalid arg min/max values. argc_min:%d argc_max:%d \n",__func__ , argc_min , argc_max); - - { - int internal_type_size = 0; /* Should end up in the range [argc_min,argc_max] */ - - if (argc_max > 0) - internal_type_size = argc_max; - else - internal_type_size = argc_min; - } - -} - - - -static void validate_set_common_selection_set(validate_type * validate , int argc , const char ** argv) { - if (validate->common_selection_set != NULL) - set_free(validate->common_selection_set); - validate->common_selection_set = set_alloc( argc , argv ); -} - - -static set_type * validate_iget_selection_set( validate_type * validate , int index) { - return vector_safe_iget( validate->indexed_selection_set , index); -} - -static void validate_add_indexed_alternative(validate_type * validate , int index , const char * value) { - set_type * set = validate_iget_selection_set( validate , index ); - - if (!set) { - vector_safe_iset_owned_ref( validate->indexed_selection_set , index , set_alloc(0,NULL) , set_free__ ); - set = vector_safe_iget( validate->indexed_selection_set , index); - } - - set_add_key( set , value ); -} - - - -static void validate_set_indexed_selection_set(validate_type * validate , int index , int argc , const char ** argv) { - - if (validate->indexed_selection_set == NULL) - util_abort("%s: must call xxx_set_argc_minmax() first - aborting \n",__func__); - - if (index >= validate->argc_min) - util_abort("%s: When not not setting argc_max selection set can only be applied to indices up to argc_min\n",__func__); - - vector_safe_iset_owned_ref( validate->indexed_selection_set , index , set_alloc(argc,argv) , set_free__ ); -} - - -/*****************************************************************/ - - -static UTIL_SAFE_CAST_FUNCTION( config_schema_item , CONFIG_SCHEMA_ITEM_ID) - -void config_schema_item_assure_type(const config_schema_item_type * item , int index , int type_mask) { - bool OK = false; - - if (int_vector_safe_iget( item->validate->type_map , index) & type_mask) - OK = true; - - if (!OK) - util_abort("%s: failed - wrong installed type \n" , __func__); -} - - -config_schema_item_type * config_schema_item_alloc(const char * kw , bool required) { - config_schema_item_type * item = util_malloc(sizeof * item ); - UTIL_TYPE_ID_INIT( item , CONFIG_SCHEMA_ITEM_ID); - item->kw = util_alloc_string_copy(kw); - - item->required_set = required; - item->deprecated = false; - item->deprecate_msg = NULL; - item->required_children = NULL; - item->required_children_value = NULL; - item->expand_envvar = true; /* Default is to expand $VAR expressions; can be turned off with - config_schema_item_set_envvar_expansion( item , false ); */ - item->validate = validate_alloc(); - return item; -} - - - -static char * __alloc_relocated__(const config_path_elm_type * path_elm , const char * value) { - char * file; - - if (util_is_abs_path(value)) - file = util_alloc_string_copy( value ); - else - file = util_alloc_filename(config_path_elm_get_relpath( path_elm ) , value , NULL); - - return file; -} - -bool config_schema_item_valid_string(config_item_types value_type , const char * value) -{ - switch(value_type) { - case(CONFIG_ISODATE): - return util_sscanf_isodate( value , NULL ); - break; - case(CONFIG_INT): - return util_sscanf_int( value , NULL ); - break; - case(CONFIG_FLOAT): - return util_sscanf_double( value , NULL ); - break; - case(CONFIG_BOOL): - return util_sscanf_bool( value , NULL ); - break; - case(CONFIG_BYTESIZE): - return util_sscanf_bytesize( value , NULL); - break; - default: - return true; - } -} - - -bool config_schema_item_validate_set(const config_schema_item_type * item , stringlist_type * token_list , const char * config_file, const config_path_elm_type * path_elm , config_error_type * error_list) { - bool OK = true; - int argc = stringlist_get_size( token_list ) - 1; - if (item->validate->argc_min >= 0) { - if (argc < item->validate->argc_min) { - OK = false; - { - char * error_message; - if (config_file != NULL) - error_message = util_alloc_sprintf("Error when parsing config_file:\"%s\" Keyword:%s must have at least %d arguments.",config_file , item->kw , item->validate->argc_min); - else - error_message = util_alloc_sprintf("Error:: Keyword:%s must have at least %d arguments.",item->kw , item->validate->argc_min); - - config_error_add( error_list , error_message ); - } - } - } - - if (item->validate->argc_max >= 0) { - if (argc > item->validate->argc_max) { - OK = false; - { - char * error_message; - - if (config_file != NULL) - error_message = util_alloc_sprintf("Error when parsing config_file:\"%s\" Keyword:%s must have maximum %d arguments.",config_file , item->kw , item->validate->argc_max); - else - error_message = util_alloc_sprintf("Error:: Keyword:%s must have maximum %d arguments.",item->kw , item->validate->argc_max); - - config_error_add( error_list , error_message ); - } - } - } - - /* - OK - now we have verified that the number of arguments is correct. Then - we start actually looking at the values. - */ - if (OK) { - /* Validating selection set - first common, then indexed */ - if (item->validate->common_selection_set) { - for (int iarg = 0; iarg < argc; iarg++) { - if (!set_has_key(item->validate->common_selection_set , stringlist_iget( token_list , iarg + 1))) { - config_error_add( error_list , util_alloc_sprintf("%s: is not a valid value for: %s.",stringlist_iget( token_list , iarg + 1) , item->kw)); - OK = false; - } - } - } else if (item->validate->indexed_selection_set != NULL) { - for (int iarg = 0; iarg < argc; iarg++) { - if ((item->validate->argc_max > 0) || (iarg < item->validate->argc_min)) { /* Without this test we might go out of range on the indexed selection set. */ - const set_type * selection_set = validate_iget_selection_set( item->validate , iarg); - if (selection_set) { - if (!set_has_key( selection_set, stringlist_iget( token_list , iarg + 1))) { - config_error_add( error_list , util_alloc_sprintf("%s: is not a valid value for item %d of \'%s\'.",stringlist_iget( token_list , iarg + 1) , iarg + 1 , item->kw)); - OK = false; - } - } - } - } - } - - /* - Observe that the following code might rewrite the content of - argv for arguments referring to path locations. - */ - - - /* Validate the TYPE of the various argumnents */ - { - for (int iarg = 0; iarg < argc; iarg++) { - const char * value = stringlist_iget(token_list , iarg + 1); - switch (validate_iget_type( item->validate , iarg)) { - case(CONFIG_STRING): /* This never fails ... */ - break; - case(CONFIG_ISODATE): - if (!util_sscanf_isodate( value , NULL )) - config_error_add( error_list , util_alloc_sprintf("Failed to parse:%s as an ISO date: YYYY-MM-DD.",value)); - break; - case(CONFIG_INT): - if (!util_sscanf_int( value , NULL )) - config_error_add( error_list , util_alloc_sprintf("Failed to parse:%s as an integer.",value)); - break; - case(CONFIG_FLOAT): - if (!util_sscanf_double( value , NULL )) { - config_error_add( error_list , util_alloc_sprintf("Failed to parse:%s as a floating point number.", value)); - OK = false; - } - break; - case(CONFIG_PATH): - // As long as we do not reuqire the path to exist it is just a string. - break; - case(CONFIG_EXISTING_PATH): - { - char * path = config_path_elm_alloc_abspath( path_elm , value ); - if (!util_entry_exists(path)) { - config_error_add( error_list , util_alloc_sprintf("Can not find entry %s in %s ",value , config_path_elm_get_relpath( path_elm) )); - OK = false; - } - free( path ); - } - break; - case(CONFIG_EXECUTABLE): - { - /* - 1. If the supplied value is an abolute path - do nothing. - 2. If the supplied is _not_ an absolute path: - - a. Try if the relocated exists - then use that. - b. Else - try if the util_alloc_PATH_executable() exists. - */ - if (!util_is_abs_path( value )) { - char * relocated = __alloc_relocated__(path_elm , value); - char * path_exe = util_alloc_PATH_executable( value ); - - if (util_file_exists(relocated)) { - if (util_is_executable(relocated)) - stringlist_iset_copy( token_list , iarg , relocated); - } else if (path_exe != NULL) - stringlist_iset_copy( token_list , iarg , path_exe); - else - config_error_add( error_list , util_alloc_sprintf("Could not locate executable:%s ", value)); - - free(relocated); - util_safe_free(path_exe); - } else { - if (!util_is_executable( value )) - config_error_add( error_list , util_alloc_sprintf("Could not locate executable:%s ", value)); - } - } - break; - case(CONFIG_BOOL): - if (!util_sscanf_bool( value , NULL )) { - config_error_add( error_list , util_alloc_sprintf("Failed to parse:%s as a boolean.", value)); - OK = false; - } - break; - case(CONFIG_BYTESIZE): - if (!util_sscanf_bytesize( value , NULL)) { - config_error_add( error_list , util_alloc_sprintf("Failed to parse:\"%s\" as number of bytes." , value)); - OK = false; - } - break; - default: - util_abort("%s: config_item_type:%d not recognized \n",__func__ , validate_iget_type(item->validate , iarg)); - } - } - } - } - return OK; -} - - -void config_schema_item_free( config_schema_item_type * item) { - free(item->kw); - free( item->deprecate_msg ); - if (item->required_children != NULL) stringlist_free(item->required_children); - if (item->required_children_value != NULL) hash_free(item->required_children_value); - validate_free(item->validate); - free(item); -} - - -void config_schema_item_free__ (void * void_item) { - config_schema_item_type * item = config_schema_item_safe_cast( void_item ); - config_schema_item_free( item ); -} - - - -void config_schema_item_set_required_children_on_value(config_schema_item_type * item , const char * value , stringlist_type * child_list) { - if (item->required_children_value == NULL) - item->required_children_value = hash_alloc(); - hash_insert_hash_owned_ref( item->required_children_value , value , stringlist_alloc_deep_copy(child_list) , stringlist_free__); -} - - - -/** - This function is used to set the minimum and maximum number of - arguments for an item. In addition you can pass in a pointer to an - array of config_schema_item_types values which will be used for validation - of the input. This vector must be argc_max elements long; it can be - NULL. -*/ - - -void config_schema_item_set_argc_minmax(config_schema_item_type * item , - int argc_min , - int argc_max) { - - validate_set_argc_minmax(item->validate , argc_min , argc_max); - -} - -void config_schema_item_iset_type( config_schema_item_type * item , int index , config_item_types type) { - validate_iset_type( item->validate , index , type ); -} - -void config_schema_item_set_default_type( config_schema_item_type * item , config_item_types type) { - validate_set_default_type( item->validate , type ); -} - - -config_item_types config_schema_item_iget_type(const config_schema_item_type * item , int index ) { - return validate_iget_type( item->validate , index ); -} - - - - -void config_schema_item_set_envvar_expansion( config_schema_item_type * item , bool expand_envvar ) { - item->expand_envvar = expand_envvar; -} - - - -void config_schema_item_set_common_selection_set(config_schema_item_type * item , int argc , const char ** argv) { - validate_set_common_selection_set(item->validate , argc , argv); -} - -void config_schema_item_set_indexed_selection_set(config_schema_item_type * item , int index , int argc , const char ** argv) { - validate_set_indexed_selection_set(item->validate , index , argc , argv); -} - -void config_schema_item_add_indexed_alternative(config_schema_item_type * item , int index , const char * value) { - validate_add_indexed_alternative(item->validate , index , value); -} - - - -void config_schema_item_set_required_children(config_schema_item_type * item , stringlist_type * stringlist) { - item->required_children = stringlist_alloc_deep_copy(stringlist); -} - -void config_schema_item_add_required_children(config_schema_item_type * item , const char * child_key) { - if (item->required_children == NULL) - item->required_children = stringlist_alloc_new(); - - stringlist_append_copy( item->required_children , child_key ); -} - - -int config_schema_item_num_required_children(const config_schema_item_type * item) { - if (item->required_children == NULL) - return 0; - else - return stringlist_get_size( item->required_children ); -} - - -const char * config_schema_item_iget_required_child( const config_schema_item_type * item , int index) { - return stringlist_iget( item->required_children , index ); -} - - -const char * config_schema_item_get_kw( const config_schema_item_type * item ) { - return item->kw; -} - - -bool config_schema_item_required( const config_schema_item_type * item ) { - return item->required_set; -} - - -bool config_schema_item_expand_envvar( const config_schema_item_type * item ) { - return item->expand_envvar; -} - - -void config_schema_item_get_argc( const config_schema_item_type * item , int *argc_min , int *argc_max) { - *argc_min = item->validate->argc_min; - *argc_max = item->validate->argc_max; -} - - - -bool config_schema_item_has_required_children_value( const config_schema_item_type * item ) { - if (item->required_children_value == NULL) - return false; - else - return true; -} - - - -stringlist_type * config_schema_item_get_required_children_value(const config_schema_item_type * item , const char * value) { - return hash_safe_get( item->required_children_value , value ); -} - -bool config_schema_item_is_deprecated( const config_schema_item_type * item) { - return item->deprecated; -} - -const char * config_schema_item_get_deprecate_msg( const config_schema_item_type * item) { - return item->deprecate_msg; -} - -void config_schema_item_set_deprecated( config_schema_item_type * item , const char * msg) { - item->deprecated = true; - item->deprecate_msg = util_realloc_string_copy(item->deprecate_msg, msg); -} - - -/*****************************************************************/ -/* Small functions to support enum introspection. */ - diff --git a/ThirdParty/Ert/libconfig/src/config_settings.c b/ThirdParty/Ert/libconfig/src/config_settings.c deleted file mode 100644 index ef9c175251..0000000000 --- a/ThirdParty/Ert/libconfig/src/config_settings.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - Copyright (C) 2017 Statoil ASA, Norway. - - The file 'config_settings.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include -#include -#include - -#include -#include - - -#define CONFIG_SETTINGS_TYPE_ID 68621527 -#define SETTING_NODE_TYPE_ID 76254096 - - -struct config_settings_struct { - UTIL_TYPE_ID_DECLARATION; - char * root_key; - hash_type * settings; -}; - -/*****************************************************************/ - -typedef struct setting_node_struct setting_node_type; - -struct setting_node_struct { - UTIL_TYPE_ID_DECLARATION; - config_item_types value_type; - char * key; - char * string_value; -}; - -static void setting_node_assert_type( const setting_node_type * node , config_item_types expected_type) { - if (node->value_type != expected_type) - util_abort("%s: internal error. Asked for type:%d is of type:%d \n",__func__ , expected_type , node->value_type); -} - -UTIL_SAFE_CAST_FUNCTION( setting_node , SETTING_NODE_TYPE_ID ) - -static setting_node_type * setting_node_alloc( const char * key, config_item_types value_type, const char * initial_value) { - if (!config_schema_item_valid_string( value_type , initial_value)) - return NULL; - - { - setting_node_type * node = util_malloc( sizeof * node ); - UTIL_TYPE_ID_INIT( node , SETTING_NODE_TYPE_ID ); - node->value_type = value_type; - node->string_value = util_alloc_string_copy( initial_value ); - node->key = util_alloc_string_copy( key ); - return node; - } -} - - -static void setting_node_free( setting_node_type * node ) { - free( node->key ); - free( node->string_value ); - free( node ); -} - - -static void setting_node_free__( void * arg ) { - setting_node_type * node = setting_node_safe_cast( arg ); - setting_node_free( node ); -} - - -static bool setting_node_set_value( setting_node_type * node, const char * value) { - if (config_schema_item_valid_string(node->value_type , value)) { - node->string_value = util_realloc_string_copy( node->string_value , value ); - return true; - } else - return false; -} - - -static void setting_node_set_string_value( setting_node_type * node, const char * value) { - setting_node_assert_type( node , CONFIG_STRING ); - setting_node_set_value( node , value ); -} - - -static void setting_node_set_int_value( setting_node_type * node, int value) { - setting_node_assert_type( node , CONFIG_INT ); - { - char * string_value = util_alloc_sprintf("%d" , value); - setting_node_set_value( node , string_value ); - free( string_value ); - } -} - -static void setting_node_set_double_value( setting_node_type * node, double value) { - setting_node_assert_type( node , CONFIG_FLOAT ); - { - char * string_value = util_alloc_sprintf("%g" , value); - setting_node_set_value( node , string_value ); - free( string_value ); - } -} - - -static void setting_node_set_bool_value( setting_node_type * node, bool value) { - bool bool_value; - setting_node_assert_type( node , CONFIG_BOOL ); - if (value) - setting_node_set_value( node , "True"); - else - setting_node_set_value( node , "False"); -} - - -static const char * setting_node_get_value( const setting_node_type * node) { - return node->string_value; -} - - -static const char * setting_node_get_string_value( const setting_node_type * node) { - setting_node_assert_type( node , CONFIG_STRING ); - return node->string_value; -} - -static int setting_node_get_int_value( const setting_node_type * node) { - setting_node_assert_type( node , CONFIG_INT ); - return strtol( node->string_value , NULL , 10 ); -} - -static double setting_node_get_double_value( const setting_node_type * node) { - setting_node_assert_type( node , CONFIG_FLOAT ); - return strtod( node->string_value , NULL ); -} - - -static bool setting_node_get_bool_value( const setting_node_type * node) { - bool bool_value; - setting_node_assert_type( node , CONFIG_BOOL ); - util_sscanf_bool( node->string_value , &bool_value ); - return bool_value; -} - - - - -/*****************************************************************/ - -config_settings_type * config_settings_alloc( const char * root_key ) { - config_settings_type * settings = util_malloc( sizeof * settings ); - settings->root_key = util_alloc_string_copy( root_key ); - settings->settings = hash_alloc(); - return settings; -} - - -void config_settings_free( config_settings_type * settings) { - free( settings->root_key ); - hash_free( settings->settings ); - free( settings ); -} - - - -bool config_settings_add_setting(config_settings_type * settings , const char* key, config_item_types value_type , const char* initial_value) { - setting_node_type * node = setting_node_alloc( key , value_type , initial_value); - if (node) { - hash_insert_hash_owned_ref( settings->settings , key , node , setting_node_free__ ); - return true; - } else - return false; -} - - -void config_settings_add_bool_setting(config_settings_type * settings , const char* key, bool initial_value) { - if (initial_value) - config_settings_add_setting( settings , key , CONFIG_BOOL , "True"); - else - config_settings_add_setting( settings , key , CONFIG_BOOL , "False"); -} - - -void config_settings_add_int_setting(config_settings_type * settings , const char* key, int initial_value) { - char * string_value = util_alloc_sprintf("%d" , initial_value); - config_settings_add_setting( settings , key , CONFIG_INT , string_value); - free( string_value ); -} - - -void config_settings_add_double_setting(config_settings_type * settings , const char* key, double initial_value) { - char * string_value = util_alloc_sprintf("%g" , initial_value); - config_settings_add_setting( settings , key , CONFIG_FLOAT , string_value); - free( string_value ); -} - - -void config_settings_add_string_setting(config_settings_type * settings , const char* key, const char * initial_value) { - config_settings_add_setting( settings , key , CONFIG_STRING , initial_value); -} - - - - -bool config_settings_has_key( const config_settings_type * settings , const char * key) { - return hash_has_key( settings->settings , key ); -} - -static setting_node_type * config_settings_get_node( const config_settings_type * config_settings, const char * key){ - return hash_get( config_settings->settings , key ); -} - - -const char * config_settings_get_value( const config_settings_type * config_settings , const char * key) { - setting_node_type * node = config_settings_get_node( config_settings , key ); - return setting_node_get_value( node ); -} - -const char * config_settings_get_string_value( const config_settings_type * config_settings , const char * key) { - setting_node_type * node = config_settings_get_node( config_settings , key ); - return setting_node_get_string_value( node ); -} - -double config_settings_get_double_value( const config_settings_type * config_settings , const char * key) { - setting_node_type * node = config_settings_get_node( config_settings , key ); - return setting_node_get_double_value( node ); -} - -int config_settings_get_int_value( const config_settings_type * config_settings , const char * key) { - setting_node_type * node = config_settings_get_node( config_settings , key ); - return setting_node_get_int_value( node ); -} - - -bool config_settings_get_bool_value( const config_settings_type * config_settings , const char * key) { - setting_node_type * node = config_settings_get_node( config_settings , key ); - return setting_node_get_bool_value( node ); -} - -config_item_types config_settings_get_value_type( const config_settings_type * config_settings , const char * key) { - setting_node_type * node = config_settings_get_node( config_settings , key ); - return node->value_type; -} - - -bool config_settings_set_value( const config_settings_type * config_settings , const char * key, const char * value) { - if (config_settings_has_key( config_settings , key )) { - setting_node_type * node = config_settings_get_node( config_settings , key ); - return setting_node_set_value( node, value ); - } - - return false; -} - - -bool config_settings_set_int_value( const config_settings_type * config_settings , const char * key, int value) { - if (config_settings_has_key( config_settings , key )) { - setting_node_type * node = config_settings_get_node( config_settings , key ); - setting_node_set_int_value( node, value ); - return true; - } - - return false; -} - - -bool config_settings_set_double_value( const config_settings_type * config_settings , const char * key, double value) { - if (config_settings_has_key( config_settings , key )) { - setting_node_type * node = config_settings_get_node( config_settings , key ); - setting_node_set_double_value( node, value ); - return true; - } - - return false; -} - - -bool config_settings_set_bool_value( const config_settings_type * config_settings , const char * key, bool value) { - if (config_settings_has_key( config_settings , key )) { - setting_node_type * node = config_settings_get_node( config_settings , key ); - setting_node_set_bool_value( node, value ); - return true; - } - - return false; -} - - -bool config_settings_set_string_value( const config_settings_type * config_settings , const char * key, const char * value) { - if (config_settings_has_key( config_settings , key )) { - setting_node_type * node = config_settings_get_node( config_settings , key ); - setting_node_set_string_value( node, value ); - return true; - } - - return false; -} - - - - -void config_settings_init_parser__( const char * root_key , config_parser_type * config , bool required) { - config_schema_item_type * item = config_add_schema_item(config, root_key , required); - config_schema_item_set_argc_minmax(item, 2, 2); -} - - - -void config_settings_init_parser( const config_settings_type * config_settings, config_parser_type * config , bool required) { - config_settings_init_parser__( config_settings->root_key , config , required ); -} - - -void config_settings_apply(config_settings_type * config_settings , const config_content_type * config ) { - for (int i = 0; i < config_content_get_occurences(config, config_settings->root_key); i++) { - const stringlist_type * tokens = config_content_iget_stringlist_ref(config, config_settings->root_key , i); - const char * setting = stringlist_iget(tokens, 0); - const char * value = stringlist_iget(tokens, 1); - - bool set_ok = config_settings_set_value( config_settings , setting , value ); - if (!set_ok) - fprintf(stderr," ** Warning: failed to apply CONFIG_SETTING %s=%s \n",setting,value); - } -} - - -stringlist_type * config_settings_alloc_keys( const config_settings_type * config_settings ) { - return hash_alloc_stringlist(config_settings->settings); -} diff --git a/ThirdParty/Ert/libconfig/src/testcase/test.txt b/ThirdParty/Ert/libconfig/src/testcase/test.txt deleted file mode 100644 index 075a883f95..0000000000 --- a/ThirdParty/Ert/libconfig/src/testcase/test.txt +++ /dev/null @@ -1,76 +0,0 @@ --- Dette er en OK kommentar. - - - - - -" " -HISTORY_OBSERVATION C-17:WOPR -{ - ERROR = 0.10; - ERROR_MODE = "rel"; - ERROR_MIN = 0.10; -}; - - - -HISTORY_OBSERVATION C-17:WGOR; -HISTORY_OBSERVATION C-17:WWCT; - - - - -SUMMARY_OBSERVATION SEP_TEST_2006 -{ - VALUE = 1; - ERROR = 0.1; --- DATE = 22/10/2006; --- DAYS = 100; - RESTART = 10; - KEY = GOPR:G4; -}; - - - -SUMMARY_OBSERVATION SEP_TEST_2007 -{ - VALUE = 1; - ERROR = 0.1; - RESTART = 10; - KEY = GOPR:G4; -}; - - - -BLOCK_OBSERVATION RFT_2005 -{ - DATE = 22/10/2005; - - OBS P1 { I=1; J=1; K=1; VALUE=10; ERROR=1;}; - OBS P2 { I=2; J=1; K=1; VALUE=10; ERROR=1;}; - OBS P3 { I=3; J=1; K=1; VALUE=10; ERROR=1;}; - OBS P4 { I=4; J=1; K=1; VALUE=10; ERROR=1;}; - OBS P5 { I=5; J=1; K=1; VALUE=10; ERROR=1;}; - OBS P6 { I=6; J=1; K=1; VALUE=10; ERROR=1;}; - OBS P7 { I=7; J=1; K=1; VALUE=10; ERROR=1;}; - OBS P8 { I=8; J=1; K=1; VALUE=10; ERROR=1;}; - OBS P9 { I=9; J=1; K=1; VALUE=10; ERROR=1;}; - OBS P10 { I=10; J=1; K=1; VALUE=10; ERROR=1;}; - OBS P11 { I=11; J=1; K=1; VALUE=10; ERROR=1;}; - OBS P12 { I=12; J=1; K=1; VALUE=10; ERROR=1;}; - - - FIELD = SWAT; -}; - -INTVEC = -[ -0 -1 -2 -3 -]; - -DOUBLEVEC = [0.1, 0.2, 10.1, 3.14]; - -SINGLETON svada; diff --git a/ThirdParty/Ert/libconfig/src/testcase/test2.txt b/ThirdParty/Ert/libconfig/src/testcase/test2.txt deleted file mode 100644 index b0f1e1a668..0000000000 --- a/ThirdParty/Ert/libconfig/src/testcase/test2.txt +++ /dev/null @@ -1,9 +0,0 @@ --- Dette er en OK kommentar. - - -HISTORY_OBSERVATION C-18:WOPR -{ - ERROR = 0.10; - ERROR_MODE = "rel"; - ERROR_MIN = 0.10; -}; diff --git a/ThirdParty/Ert/libconfig/tests/CMakeLists.txt b/ThirdParty/Ert/libconfig/tests/CMakeLists.txt deleted file mode 100644 index 456b59144b..0000000000 --- a/ThirdParty/Ert/libconfig/tests/CMakeLists.txt +++ /dev/null @@ -1,61 +0,0 @@ -add_executable( config_append_test config_append_test.c ) -target_link_libraries( config_append_test config test_util ) - -add_executable( config_node_test config_node_test.c ) -target_link_libraries( config_node_test config test_util ) - -add_executable( config_typeOK config_typeOK.c ) -target_link_libraries( config_typeOK config test_util ) - -add_executable( config_typeFail config_typeFail.c ) -target_link_libraries( config_typeFail config test_util ) - -add_executable( config_path_elm config_path_elm.c ) -target_link_libraries( config_path_elm config test_util ) - -add_executable( config_root_path config_root_path.c ) -target_link_libraries( config_root_path config test_util ) - -add_executable( config_include_test config_include_test.c) -target_link_libraries( config_include_test config test_util ) - -add_executable( config_content_node config_content_node.c) -target_link_libraries( config_content_node config test_util ) - -add_executable( config_content_item config_content_item.c) -target_link_libraries( config_content_item config test_util ) - -add_executable( config_argc config_argc.c) -target_link_libraries( config_argc config test_util ) - -add_executable( config_define config_define.c) -target_link_libraries( config_define config test_util ) - -add_executable( config_error config_error.c) -target_link_libraries( config_error config test_util ) -add_test( config_error ${EXECUTABLE_OUTPUT_PATH}/config_error ) - -add_executable( config_content config_content.c) -target_link_libraries( config_content config test_util ) -add_test( config_content ${EXECUTABLE_OUTPUT_PATH}/config_content ) - - -add_executable( config_config config_config.c) -target_link_libraries( config_config config test_util ) -add_test( config_config ${EXECUTABLE_OUTPUT_PATH}/config_config ) - -add_executable( config_schema_item config_schema_item.c) -target_link_libraries( config_schema_item config test_util ) -add_test( config_schema_item ${EXECUTABLE_OUTPUT_PATH}/config_schema_item ) - -add_test( config_typeOK ${EXECUTABLE_OUTPUT_PATH}/config_typeOK ${CMAKE_CURRENT_SOURCE_DIR}/data/type_testOK ) -add_test( config_typeFail ${EXECUTABLE_OUTPUT_PATH}/config_typeFail ${CMAKE_CURRENT_SOURCE_DIR}/data/type_testFail ) -add_test( config_append_test ${EXECUTABLE_OUTPUT_PATH}/config_append_test ${CMAKE_CURRENT_SOURCE_DIR}/data/append_test ) -add_test( config_node_test ${EXECUTABLE_OUTPUT_PATH}/config_node_test ${CMAKE_CURRENT_SOURCE_DIR}/data/append_test ) -add_test( config_define ${EXECUTABLE_OUTPUT_PATH}/config_define ${CMAKE_CURRENT_SOURCE_DIR}/data/define_test ) -add_test( config_path_elm ${EXECUTABLE_OUTPUT_PATH}/config_path_elm ) -add_test( config_content_node ${EXECUTABLE_OUTPUT_PATH}/config_content_node ) -add_test( config_content_item ${EXECUTABLE_OUTPUT_PATH}/config_content_item ${CMAKE_CURRENT_SOURCE_DIR}/data/content_item_test) -add_test( config_include_test ${EXECUTABLE_OUTPUT_PATH}/config_include_test ${CMAKE_CURRENT_SOURCE_DIR}/data include_test ) -add_test( config_root_path ${EXECUTABLE_OUTPUT_PATH}/config_root_path ${CMAKE_CURRENT_SOURCE_DIR}/data ) -add_test( config_argc ${EXECUTABLE_OUTPUT_PATH}/config_argc ${CMAKE_CURRENT_SOURCE_DIR}/data/argc_OK ${CMAKE_CURRENT_SOURCE_DIR}/data/argc_less ${CMAKE_CURRENT_SOURCE_DIR}/data/argc_more) diff --git a/ThirdParty/Ert/libconfig/tests/config_append_test.c b/ThirdParty/Ert/libconfig/tests/config_append_test.c deleted file mode 100644 index 4c89d18853..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_append_test.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_append_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include - -#include -#include - - - - -int main(int argc , char ** argv) { - const char * config_file = argv[1]; - config_parser_type * config = config_alloc(); - config_schema_item_type * item = config_add_schema_item(config , "APPEND" , false ); - config_schema_item_set_argc_minmax( item , 1 , 1); - - { - config_content_type * content = config_parse(config , config_file , "--" , NULL , NULL , NULL , false , true ); - test_assert_true(config_content_is_instance( content )); - test_assert_true(config_content_is_valid( content )); - test_assert_int_equal( config_content_get_occurences( content , "APPEND" ) , 3); - - { - const char * value = config_content_get_value( content , "APPEND"); - test_assert_string_equal( value , "VALUE3"); - } - - config_content_free( content ); - } - - { - config_content_type * content = config_parse( config , "DoesNotExist" , "--" , NULL , NULL , NULL , false , true); - test_assert_false( config_content_is_valid( content )); - config_content_free( content ); - } - exit(0); -} diff --git a/ThirdParty/Ert/libconfig/tests/config_argc.c b/ThirdParty/Ert/libconfig/tests/config_argc.c deleted file mode 100644 index 067023672e..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_argc.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'config_argc.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -void install_SIGNALS(void) { - signal(SIGSEGV , util_abort_signal); /* Segmentation violation, i.e. overwriting memory ... */ - signal(SIGINT , util_abort_signal); /* Control C */ - signal(SIGTERM , util_abort_signal); /* If killing the program with SIGTERM (the default kill signal) you will get a backtrace. - Killing with SIGKILL (-9) will not give a backtrace.*/ -} - - - -int main(int argc , char ** argv) { - install_SIGNALS(); - { - const char * argc_OK = argv[1]; - const char * argc_less = argv[2]; - const char * argc_more = argv[3]; - - config_parser_type * config = config_alloc(); - config_schema_item_type * schema_item = config_add_schema_item( config , "ITEM" , false ); - config_schema_item_set_argc_minmax( schema_item , 2 , 2 ); - - { - config_content_type * content = config_parse( config , argc_OK , "--" , NULL , NULL , NULL , CONFIG_UNRECOGNIZED_ERROR , true); - test_assert_true( config_content_is_instance( content )); - test_assert_true(config_content_is_valid( content )); - config_content_free( content ); - } - - { - config_content_type * content = config_parse( config , argc_less , "--" , NULL , NULL , NULL , CONFIG_UNRECOGNIZED_ERROR , true); - test_assert_true( config_content_is_instance( content )); - test_assert_false( config_content_is_valid( content )); - - { - const config_error_type * config_error = config_content_get_errors( content ); - const char * error_msg = "Error when parsing config_file:\"argc_less\" Keyword:ITEM must have at least 2 arguments."; - - test_assert_int_equal( config_error_count( config_error ) , 1); - test_assert_string_equal( config_error_iget( config_error , 0 ) , error_msg); - } - config_content_free( content ); - } - - { - config_content_type * content = config_parse( config , argc_more , "--" , NULL , NULL , NULL , CONFIG_UNRECOGNIZED_ERROR , true); - test_assert_true( config_content_is_instance( content )); - test_assert_false( config_content_is_valid( content )); - { - const config_error_type * config_error = config_content_get_errors( content ); - const char * error_msg = "Error when parsing config_file:\"argc_more\" Keyword:ITEM must have maximum 2 arguments."; - - test_assert_int_equal( config_error_count( config_error ) , 1); - test_assert_string_equal( config_error_iget( config_error , 0 ) , error_msg); - } - config_content_free( content ); - } - - config_free( config ); - exit(0); - } -} diff --git a/ThirdParty/Ert/libconfig/tests/config_config.c b/ThirdParty/Ert/libconfig/tests/config_config.c deleted file mode 100644 index 8d10c89cf5..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_config.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'config_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include - -#include -#include - - -int main(int argc , char ** argv) { - config_parser_type * config = config_alloc(); - config_add_schema_item( config , "KEYWORD" , false ); - config_free( config ); - exit(0); -} - diff --git a/ThirdParty/Ert/libconfig/tests/config_content.c b/ThirdParty/Ert/libconfig/tests/config_content.c deleted file mode 100644 index 4caa608d12..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_content.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'config_content.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include - - -void test_create() { - config_content_type * content = config_content_alloc( "filename" ); - test_assert_true( config_content_is_instance( content ) ); - config_content_free( content ); -} - - - - - - -int main( int argc , char ** argv) { - test_create(); -} diff --git a/ThirdParty/Ert/libconfig/tests/config_content_item.c b/ThirdParty/Ert/libconfig/tests/config_content_item.c deleted file mode 100644 index 0b8ab1aa41..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_content_item.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'config_content_item.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - - -int main(int argc , char ** argv) { - const char * config_file = argv[1]; - config_parser_type * config = config_alloc(); - - config_add_schema_item( config , "SET" , true ); - config_add_schema_item( config , "NOTSET" , false ); - - { - config_content_type * content = config_parse( config , config_file , "--" , "INCLUDE" , NULL , NULL , CONFIG_UNRECOGNIZED_IGNORE , true ); - test_assert_true( config_content_is_instance( content )); - test_assert_true(config_content_is_valid( content )); - - test_assert_true( config_content_has_item( content , "SET" )); - test_assert_false( config_content_has_item( content , "NOTSET" ) ); - test_assert_false( config_content_has_item( content , "UNKNOWN" ) ); - - test_assert_true( config_has_schema_item( config , "SET" )); - test_assert_true( config_has_schema_item( config , "NOTSET" )); - test_assert_false( config_has_schema_item( config , "UNKNOWN" )); - - config_content_free( content ); - } - - exit(0); -} - diff --git a/ThirdParty/Ert/libconfig/tests/config_content_node.c b/ThirdParty/Ert/libconfig/tests/config_content_node.c deleted file mode 100644 index f7289f60de..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_content_node.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'config_content_node.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - - -int main(int argc , char ** argv) { - config_schema_item_type * schema = config_schema_item_alloc("TEST" , true); - config_root_path_type * root_path = config_root_path_alloc( NULL ); - config_path_elm_type * cwd = config_path_elm_alloc( root_path , NULL ); - { - config_content_node_type * node = config_content_node_alloc( schema , cwd ); - config_content_node_add_value( node , "KEY1:VALUE1" ); - config_content_node_add_value( node , "KEY2:VALUE2" ); - config_content_node_add_value( node , "KEY3:VALUE3" ); - config_content_node_add_value( node , "KEYVALUE" ); - - test_assert_int_equal( config_content_node_get_size( node ) , 4 ); - test_assert_string_equal( config_content_node_iget( node , 0 ) , "KEY1:VALUE1" ); - test_assert_string_equal( config_content_node_iget( node , 2 ) , "KEY3:VALUE3" ); - - test_assert_string_equal( config_content_node_get_full_string( node , ",") , "KEY1:VALUE1,KEY2:VALUE2,KEY3:VALUE3,KEYVALUE"); - - { - hash_type * opt_hash = hash_alloc( ); - { - config_content_node_init_opt_hash( node , opt_hash , 0 ); - test_assert_int_equal( hash_get_size( opt_hash ) , 3 ); - test_assert_string_equal( hash_get( opt_hash , "KEY1" ) , "VALUE1" ); - test_assert_string_equal( hash_get( opt_hash , "KEY3" ) , "VALUE3" ); - } - - hash_clear( opt_hash ); - test_assert_int_equal( hash_get_size( opt_hash ) , 0 ); - config_content_node_init_opt_hash( node , opt_hash , 1 ); - test_assert_int_equal( hash_get_size( opt_hash ) , 2 ); - test_assert_string_equal( hash_get( opt_hash , "KEY2" ) , "VALUE2" ); - test_assert_string_equal( hash_get( opt_hash , "KEY3" ) , "VALUE3" ); - test_assert_false( hash_has_key( opt_hash , "KEY1" ) ); - test_assert_false( hash_has_key( opt_hash , "KEYVALUE" ) ); - hash_free( opt_hash ); - } - - - config_content_node_free( node ); - } - config_path_elm_free( cwd ); - config_root_path_free( root_path ); - config_schema_item_free( schema ); - exit(0); -} - diff --git a/ThirdParty/Ert/libconfig/tests/config_define.c b/ThirdParty/Ert/libconfig/tests/config_define.c deleted file mode 100644 index 386ab0c655..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_define.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'config_define.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -void test_define(config_parser_type * config , const char * config_file) { - hash_type * pre_defined_kw_map = hash_alloc(); - hash_insert_string(pre_defined_kw_map, "", "TEST_VALUE"); - config_content_type * content = config_parse( config , config_file , NULL , NULL , "DEFINE" , pre_defined_kw_map , CONFIG_UNRECOGNIZED_IGNORE , true ); - hash_free(pre_defined_kw_map); - test_assert_true( config_content_is_instance( content )); - test_assert_true(config_content_is_valid( content )); - { - const subst_list_type * define_list = config_content_get_define_list( content ); - test_assert_true( subst_list_has_key( define_list , "VAR1")); - test_assert_true( subst_list_has_key( define_list , "VAR2")); - test_assert_true( subst_list_has_key( define_list , "VARX")); - test_assert_true( subst_list_has_key( define_list , "")); - test_assert_false( subst_list_has_key( define_list , "VARY")); - - - test_assert_string_equal( subst_list_get_value( define_list , "VAR1") , "100"); - test_assert_string_equal( subst_list_get_value( define_list , "VAR2") , "10"); - test_assert_string_equal( subst_list_get_value( define_list , "VARX") , "1"); - test_assert_string_equal( subst_list_get_value( define_list , "") , "TEST_VALUE"); - } - - config_content_free( content ); -} - - - -config_parser_type * config_create_schema() { - config_parser_type * config = config_alloc(); - - config_add_schema_item( config , "SET" , true ); - config_add_schema_item( config , "NOTSET" , false ); - - return config; -} - - -int main(int argc , char ** argv) { - util_install_signals(); - { - const char * config_file = argv[1]; - config_parser_type * config = config_create_schema(); - - test_define( config , config_file ); - - config_free( config ); - exit(0); - } -} - diff --git a/ThirdParty/Ert/libconfig/tests/config_error.c b/ThirdParty/Ert/libconfig/tests/config_error.c deleted file mode 100644 index 5312d937d9..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_error.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_error.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include - -#include - -int main(int argc , char ** argv) { - config_error_type * config_error = config_error_alloc(); - - { - config_error_type * error_copy = config_error_alloc_copy( config_error ); - - test_assert_true( config_error_equal( config_error , error_copy )); - test_assert_ptr_not_equal( config_error , error_copy ); - - config_error_free( error_copy ); - } - - config_error_free( config_error ); - exit(0); -} - diff --git a/ThirdParty/Ert/libconfig/tests/config_include_test.c b/ThirdParty/Ert/libconfig/tests/config_include_test.c deleted file mode 100644 index 593a34af5b..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_include_test.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_include_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -void parse_test(config_parser_type * config , - const char * root_path , // The new working directory - the test will start by chdir() here. - const char * config_file ) { // The config_file, either as an absolute path - or relative from root_path - -#ifdef ERT_LINUX - const char * path0 = "PATH0"; - const char * path1 = "path/PATH1"; - const char * path2 = "path/PATH2"; - const char * path3 = "path/subpath/PATH3"; - const char * path4 = "path/subpath/subsubpath/PATH4"; -#endif - - - char * config_path, *config_rel_path,*config_abs_path; - path_stack_type * path_stack = path_stack_alloc(); - - util_alloc_file_components( config_file , &config_path , NULL , NULL); - path_stack_push( path_stack , NULL ); - if (root_path != NULL) - util_chdir( root_path ); - - config_abs_path = util_alloc_abs_path( config_path ); - config_rel_path = util_alloc_rel_path( NULL , config_abs_path); - - { - config_content_type * content = config_parse( config , config_file , "--" , "INCLUDE" , NULL , NULL , CONFIG_UNRECOGNIZED_IGNORE , true ); - if (config_content_is_valid( content )) { - - char * relpath0 = util_alloc_filename( config_rel_path , path0, NULL); - char * relpath1 = util_alloc_filename( config_rel_path , path1, NULL); - char * relpath2 = util_alloc_filename( config_rel_path , path2, NULL); - char * relpath3 = util_alloc_filename( config_rel_path , path3, NULL); - char * relpath4 = util_alloc_filename( config_rel_path , path4, NULL); - - char * abspath0 = util_alloc_filename( config_abs_path , path0, NULL); - char * abspath1 = util_alloc_filename( config_abs_path , path1, NULL); - char * abspath2 = util_alloc_filename( config_abs_path , path2, NULL); - char * abspath3 = util_alloc_filename( config_abs_path , path3, NULL); - char * abspath4 = util_alloc_filename( config_abs_path , path4, NULL); - - test_assert_string_equal(config_content_get_value_as_relpath(content , "PATH0") , relpath0 ); - test_assert_string_equal(config_content_get_value_as_relpath(content , "PATH1") , relpath1 ); - test_assert_string_equal(config_content_get_value_as_relpath(content , "PATH2") , relpath2 ); - test_assert_string_equal(config_content_get_value_as_relpath(content , "PATH3") , relpath3 ); - test_assert_string_equal(config_content_get_value_as_relpath(content , "PATH4") , relpath4 ); - - test_assert_string_equal(config_content_get_value_as_abspath(content , "PATH0") , abspath0 ); - test_assert_string_equal(config_content_get_value_as_abspath(content , "PATH1") , abspath1 ); - test_assert_string_equal(config_content_get_value_as_abspath(content , "PATH2") , abspath2 ); - test_assert_string_equal(config_content_get_value_as_abspath(content , "PATH3") , abspath3 ); - test_assert_string_equal(config_content_get_value_as_abspath(content , "PATH4") , abspath4 ); - - } else { - const config_error_type * error = config_content_get_errors( content ); - config_error_fprintf( error , true , stdout ); - test_error_exit("Hmm - parsing %s failed \n", config_file ); - } - config_content_free( content ); - } - path_stack_pop( path_stack ); -} - - -int main(int argc , char ** argv) { - const char * abs_path = argv[1]; - const char * config_file = argv[2]; - char * abs_config_file = util_alloc_filename( abs_path , config_file , NULL); - config_parser_type * config = config_alloc(); - - { - config_schema_item_type * schema_item; - - schema_item = config_add_schema_item( config , "PATH0" , true ); - config_schema_item_set_argc_minmax( schema_item , 1 , 1 ); - config_schema_item_iset_type( schema_item , 0 , CONFIG_PATH ); - - schema_item = config_add_schema_item( config , "PATH1" , true ); - config_schema_item_set_argc_minmax( schema_item , 1 , 1 ); - config_schema_item_iset_type( schema_item , 0 , CONFIG_PATH ); - - schema_item = config_add_schema_item( config , "PATH2" , true ); - config_schema_item_set_argc_minmax( schema_item , 1 , 1 ); - config_schema_item_iset_type( schema_item , 0 , CONFIG_PATH ); - - schema_item = config_add_schema_item( config , "PATH3" , true ); - config_schema_item_set_argc_minmax( schema_item , 1 , 1 ); - config_schema_item_iset_type( schema_item , 0 , CONFIG_PATH ); - - schema_item = config_add_schema_item( config , "PATH4" , true ); - config_schema_item_set_argc_minmax( schema_item , 1 , 1 ); - config_schema_item_iset_type( schema_item , 0 , CONFIG_PATH ); - } - - parse_test( config , abs_path , config_file ); - parse_test( config , abs_path , abs_config_file ); - parse_test( config , NULL , abs_config_file ); - parse_test( config , "../../" , abs_config_file ); - - config_free( config ); - exit(0); -} - - - - diff --git a/ThirdParty/Ert/libconfig/tests/config_node_test.c b/ThirdParty/Ert/libconfig/tests/config_node_test.c deleted file mode 100644 index 7f18c4fd7e..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_node_test.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_node_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include -#include - - - -int main(int argc , char ** argv) { - const char * config_file = argv[1]; - config_parser_type * config = config_alloc(); - { - config_schema_item_type * item = config_add_schema_item(config , "APPEND" , false ); - config_schema_item_set_argc_minmax( item , 1 , 1); - } - config_add_schema_item(config , "NEXT" , false ); - - config_content_type * content = config_parse(config , config_file , "--" , NULL , NULL , NULL , false , true ); - - if (config_content_is_valid( content )) { - if (config_content_get_size( content ) == 4) { - const config_content_node_type * node0 = config_content_iget_node( content , 0 ); - if (strcmp( config_content_node_get_kw( node0 ) , "APPEND") == 0) { - if (config_content_node_get_size(node0) == 1) { - const config_content_node_type * node3 = config_content_iget_node( content , 3 ); - if (strcmp( config_content_node_get_kw( node3 ) , "NEXT") == 0) { - if (config_content_node_get_size(node3) == 2) { - config_content_free( content ); - exit(0); - } else printf("Size error node3\n"); - } else printf("kw error node3 \n"); - } else printf("Size error node0\n"); - } else printf("kw error node0 kw:%s \n", config_content_node_get_kw( node0 )); - } else printf("Size error \n"); - } else printf("Parse error"); - - config_content_free( content ); - exit(1); -} - diff --git a/ThirdParty/Ert/libconfig/tests/config_path_elm.c b/ThirdParty/Ert/libconfig/tests/config_path_elm.c deleted file mode 100644 index e6b4ea50f1..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_path_elm.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_path_elm.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -int main(int argc , char ** argv) { -#ifdef ERT_LINUX - const char * rel_path = "rel/path"; - const char * rel_true = "rel/path/XXX"; - const char * path_true1 = "rel/path/XXX"; - - -#endif - test_work_area_type * work_area = test_work_area_alloc( "config_path_elm" ); - const char * root = test_work_area_get_cwd( work_area ); - char * abs_path = util_alloc_filename( root , "rel/path" , NULL); - char * abs_true = util_alloc_filename( root , "rel/path/XXX" , NULL); - char * path_true2 = util_alloc_filename( root , "rel/path/XXX" , NULL); - - util_chdir( test_work_area_get_original_cwd( work_area )); - config_root_path_type * root_path = config_root_path_alloc( root ); - { - config_path_elm_type * path_elm = config_path_elm_alloc( root_path , rel_path ); - - test_assert_string_equal( config_path_elm_get_relpath( path_elm ) , rel_path ); - test_assert_string_equal( config_path_elm_get_abspath( path_elm ) , abs_path ); - - test_assert_string_equal( config_path_elm_alloc_relpath( path_elm , "XXX" ) , rel_true); - test_assert_string_equal( config_path_elm_alloc_abspath( path_elm , "XXX" ) , abs_true); - test_assert_string_equal( config_path_elm_alloc_path( path_elm , "XXX" ) , path_true2 ); - - - config_path_elm_free( path_elm ); - } - { - config_path_elm_type * path_elm = config_path_elm_alloc( root_path , abs_path ); - - test_assert_string_equal( config_path_elm_get_relpath( path_elm ) , rel_path ); - test_assert_string_equal( config_path_elm_get_abspath( path_elm ) , abs_path ); - - test_assert_string_equal( config_path_elm_alloc_relpath( path_elm , "XXX" ) , rel_true); - test_assert_string_equal( config_path_elm_alloc_abspath( path_elm , "XXX" ) , abs_true); - test_assert_string_equal( config_path_elm_alloc_path( path_elm , "XXX" ) , path_true2 ); - - config_path_elm_free( path_elm ); - } - config_root_path_free( root_path ); - - util_chdir( root ); - root_path = config_root_path_alloc( NULL ); - { - config_path_elm_type * path_elm = config_path_elm_alloc( root_path , rel_path ); - - test_assert_string_equal( config_path_elm_get_relpath( path_elm ) , rel_path ); - test_assert_string_equal( config_path_elm_get_abspath( path_elm ) , abs_path ); - - test_assert_string_equal( config_path_elm_alloc_relpath( path_elm , "XXX" ) , rel_true); - test_assert_string_equal( config_path_elm_alloc_abspath( path_elm , "XXX" ) , abs_true); - test_assert_string_equal( config_path_elm_alloc_path( path_elm , "XXX" ) , path_true1 ); - - - config_path_elm_free( path_elm ); - } - - exit(0); -} - diff --git a/ThirdParty/Ert/libconfig/tests/config_root_path.c b/ThirdParty/Ert/libconfig/tests/config_root_path.c deleted file mode 100644 index 60bbe9be69..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_root_path.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'config_root_path.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - -#include -#include - -#include -#include - - -int main(int argc , char ** argv) { - char * cwd = util_alloc_cwd(); - - { - config_root_path_type * root_path = config_root_path_alloc( NULL ); - - if (!test_check_string_equal( config_root_path_get_abs_path( root_path ) , cwd )) - test_error_exit("abs:path:%s expeceted:%s \n",config_root_path_get_abs_path( root_path ) , cwd ); - - if (!test_check_string_equal( config_root_path_get_input_path( root_path ) , NULL )) - test_error_exit("input:path:%s expeceted:%s \n",config_root_path_get_input_path( root_path ) , NULL ); - - if (!test_check_string_equal( config_root_path_get_rel_path( root_path ) , NULL )) - test_error_exit("rel:path:%s expeceted:%s \n",config_root_path_get_rel_path( root_path ) , NULL ); - - - config_root_path_free( root_path ); - } - - - { - config_root_path_type * root_path = config_root_path_alloc( "/does/not/exist" ); - if (root_path != NULL) - test_error_exit("Created root_path instance for not-existing input \n"); - } - - - - { - const char * input_path = argv[1]; - char * cwd = util_alloc_cwd(); - char * rel_path = util_alloc_rel_path( cwd , input_path ); - - config_root_path_type * root_path1 = config_root_path_alloc( input_path ); - config_root_path_type * root_path2 = config_root_path_alloc( rel_path ); - - if (!test_check_string_equal( config_root_path_get_rel_path( root_path1 ) , config_root_path_get_rel_path( root_path2 ))) - test_error_exit("Rel: %s != %s \n",config_root_path_get_rel_path( root_path1 ) , config_root_path_get_rel_path( root_path2)); - - if (!test_check_string_equal( config_root_path_get_abs_path( root_path1 ) , config_root_path_get_abs_path( root_path2 ))) - test_error_exit("Abs: %s != %s \n",config_root_path_get_abs_path( root_path1 ) , config_root_path_get_abs_path( root_path2 )); - - config_root_path_free( root_path1 ); - config_root_path_free( root_path2 ); - } - - - exit(0); -} - diff --git a/ThirdParty/Ert/libconfig/tests/config_schema_item.c b/ThirdParty/Ert/libconfig/tests/config_schema_item.c deleted file mode 100644 index 69dc55238c..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_schema_item.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'config_schema_item.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include - -#include - - - -int main(int argc , char ** argv) { - config_schema_item_type * schema_item = config_schema_item_alloc( "KW" , false ); - - test_assert_int_equal( config_schema_item_iget_type( schema_item , 1 ) , CONFIG_STRING ); - test_assert_int_equal( config_schema_item_iget_type( schema_item , 2 ) , CONFIG_STRING ); - - config_schema_item_iset_type( schema_item , 0 , CONFIG_INT ); - config_schema_item_iset_type( schema_item , 5 , CONFIG_BOOL ); - - - test_assert_int_equal( config_schema_item_iget_type( schema_item , 0 ) , CONFIG_INT ); - test_assert_int_equal( config_schema_item_iget_type( schema_item , 1 ) , CONFIG_STRING ); - test_assert_int_equal( config_schema_item_iget_type( schema_item , 2 ) , CONFIG_STRING ); - test_assert_int_equal( config_schema_item_iget_type( schema_item , 5 ) , CONFIG_BOOL ); - - config_schema_item_set_default_type( schema_item , CONFIG_FLOAT ); - test_assert_int_equal( config_schema_item_iget_type( schema_item , 7 ) , CONFIG_FLOAT ); - - config_schema_item_free( schema_item ); - exit(0); -} - diff --git a/ThirdParty/Ert/libconfig/tests/config_typeFail.c b/ThirdParty/Ert/libconfig/tests/config_typeFail.c deleted file mode 100644 index c3a113adf7..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_typeFail.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_parser_typeFail.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include - -#include -#include -#include - - -void error(char * msg) { - fprintf(stderr , msg); - exit(1); -} - - -int main(int argc , char ** argv) { - const char * config_file = argv[1]; - config_parser_type * config = config_alloc(); - { - config_schema_item_type * item = config_add_schema_item(config , "TYPES_KEY" , false ); - config_schema_item_set_argc_minmax( item , 4 , 4 ); - config_schema_item_iset_type( item , 0 , CONFIG_INT ); - config_schema_item_iset_type( item , 1 , CONFIG_FLOAT ); - config_schema_item_iset_type( item , 2 , CONFIG_BOOL ); - - item = config_add_schema_item( config , "SHORT_KEY" , false ); - config_schema_item_set_argc_minmax( item , 1 , 1 ); - - item = config_add_schema_item( config , "LONG_KEY" , false ); - config_schema_item_set_argc_minmax( item , 3 , CONFIG_DEFAULT_ARG_MAX); - } - - { - config_content_type * content = config_parse(config , config_file , "--" , NULL , NULL , NULL , false , true ); - - if (config_content_is_valid( content )) { - error("Parse error\n"); - } else { - const config_error_type * cerror = config_content_get_errors( content ); - if (config_error_count( cerror ) > 0) { - int i; - for (i=0; i < config_error_count( cerror ); i++) { - printf("Error %d: %s \n",i , config_error_iget( cerror , i )); - } - } - test_assert_int_equal( 5 , config_error_count( cerror )); - } - config_content_free( content ); - } - printf("OK \n"); - exit(0); -} - diff --git a/ThirdParty/Ert/libconfig/tests/config_typeOK.c b/ThirdParty/Ert/libconfig/tests/config_typeOK.c deleted file mode 100644 index e68c4e929c..0000000000 --- a/ThirdParty/Ert/libconfig/tests/config_typeOK.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'config_parser_typeOK.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include -#include -#include - - - - -int main(int argc , char ** argv) { - const char * config_file = argv[1]; - config_parser_type * config = config_alloc(); - { - config_schema_item_type * item = config_add_schema_item(config , "TYPE_KEY" , false ); - config_schema_item_set_argc_minmax( item , 4 , 4 ); - config_schema_item_iset_type( item , 0 , CONFIG_INT ); - config_schema_item_iset_type( item , 1 , CONFIG_FLOAT ); - config_schema_item_iset_type( item , 2 , CONFIG_BOOL ); - - item = config_add_schema_item( config , "SHORT_KEY" , false ); - config_schema_item_set_argc_minmax( item , 1 , 1 ); - - item = config_add_schema_item( config , "LONG_KEY" , false ); - config_schema_item_set_argc_minmax( item , 3 , CONFIG_DEFAULT_ARG_MAX ); - } - { - config_content_type * content = config_parse(config , config_file , "--" , NULL , NULL , NULL , false , true ); - test_assert_true( config_content_is_valid( content )); - config_content_free( content ); - } - - - exit(0); -} - diff --git a/ThirdParty/Ert/libconfig/tests/data/append_test b/ThirdParty/Ert/libconfig/tests/data/append_test deleted file mode 100644 index 8af962aaa2..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/append_test +++ /dev/null @@ -1,4 +0,0 @@ -APPEND VALUE1 -APPEND VALUE2 -APPEND VALUE3 -NEXT VALUE4 VALUE5 \ No newline at end of file diff --git a/ThirdParty/Ert/libconfig/tests/data/argc_OK b/ThirdParty/Ert/libconfig/tests/data/argc_OK deleted file mode 100644 index 771501c380..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/argc_OK +++ /dev/null @@ -1 +0,0 @@ -ITEM Arg1 Arg2 diff --git a/ThirdParty/Ert/libconfig/tests/data/argc_less b/ThirdParty/Ert/libconfig/tests/data/argc_less deleted file mode 100644 index 26c79f150b..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/argc_less +++ /dev/null @@ -1 +0,0 @@ -ITEM Arg1 diff --git a/ThirdParty/Ert/libconfig/tests/data/argc_more b/ThirdParty/Ert/libconfig/tests/data/argc_more deleted file mode 100644 index bd026bbdc4..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/argc_more +++ /dev/null @@ -1,2 +0,0 @@ -ITEM Arg1 ARG2 Arg3 - diff --git a/ThirdParty/Ert/libconfig/tests/data/content_item_test b/ThirdParty/Ert/libconfig/tests/data/content_item_test deleted file mode 100644 index 403ef6ae3e..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/content_item_test +++ /dev/null @@ -1 +0,0 @@ -SET SetValue diff --git a/ThirdParty/Ert/libconfig/tests/data/define_test b/ThirdParty/Ert/libconfig/tests/data/define_test deleted file mode 100644 index 6976c4853f..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/define_test +++ /dev/null @@ -1,5 +0,0 @@ -DEFINE VAR1 100 -DEFINE VAR2 10 -DEFINE VARX 1 - -SET VAR1 100 diff --git a/ThirdParty/Ert/libconfig/tests/data/include_test b/ThirdParty/Ert/libconfig/tests/data/include_test deleted file mode 100644 index 9717f9dcaf..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/include_test +++ /dev/null @@ -1,3 +0,0 @@ -PATH0 PATH0 -INCLUDE path/include1 -INCLUDE path/subpath/include2 \ No newline at end of file diff --git a/ThirdParty/Ert/libconfig/tests/data/path/include1 b/ThirdParty/Ert/libconfig/tests/data/path/include1 deleted file mode 100644 index 24c1ce46d0..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/path/include1 +++ /dev/null @@ -1,5 +0,0 @@ -PATH1 PATH1 -PATH2 PATH2 - -INCLUDE subpath/include3 -INCLUDE subpath/subsubpath/include4 \ No newline at end of file diff --git a/ThirdParty/Ert/libconfig/tests/data/path/subpath/include2 b/ThirdParty/Ert/libconfig/tests/data/path/subpath/include2 deleted file mode 100644 index df203e9835..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/path/subpath/include2 +++ /dev/null @@ -1 +0,0 @@ -PATH2 PATH2 \ No newline at end of file diff --git a/ThirdParty/Ert/libconfig/tests/data/path/subpath/include3 b/ThirdParty/Ert/libconfig/tests/data/path/subpath/include3 deleted file mode 100644 index 85a8dae08a..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/path/subpath/include3 +++ /dev/null @@ -1 +0,0 @@ -PATH3 PATH3 \ No newline at end of file diff --git a/ThirdParty/Ert/libconfig/tests/data/path/subpath/subsubpath/include4 b/ThirdParty/Ert/libconfig/tests/data/path/subpath/subsubpath/include4 deleted file mode 100644 index 9bb116f3a4..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/path/subpath/subsubpath/include4 +++ /dev/null @@ -1 +0,0 @@ -PATH4 PATH4 \ No newline at end of file diff --git a/ThirdParty/Ert/libconfig/tests/data/type_testFail b/ThirdParty/Ert/libconfig/tests/data/type_testFail deleted file mode 100644 index f54ebe9a10..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/type_testFail +++ /dev/null @@ -1,6 +0,0 @@ -TYPES_KEY 100 0.75 rue String -TYPES_KEY 100 0.75 True String -TYPES_KEY 100 0.75X True String -TYPES_KEY 100X 0.75 True String -SHORT_KEY 100 100 -LONG_KEY 100 100 diff --git a/ThirdParty/Ert/libconfig/tests/data/type_testOK b/ThirdParty/Ert/libconfig/tests/data/type_testOK deleted file mode 100644 index 7801b99a58..0000000000 --- a/ThirdParty/Ert/libconfig/tests/data/type_testOK +++ /dev/null @@ -1,4 +0,0 @@ -TYPES_KEY 100 0.75 True String -SHORT_KEY 100 -LONG_KEY 100 100 100 -LONG_KEY asc asc asc asc asc asc as asc sac asc sac sca sca sa sac \ No newline at end of file diff --git a/ThirdParty/Ert/libecl/applications/ecl_pack.c b/ThirdParty/Ert/libecl/applications/ecl_pack.c index 0dacd92249..34ae853cda 100644 --- a/ThirdParty/Ert/libecl/applications/ecl_pack.c +++ b/ThirdParty/Ert/libecl/applications/ecl_pack.c @@ -25,6 +25,7 @@ #include #include #include +#include @@ -67,7 +68,7 @@ int main(int argc, char ** argv) { if (target_type == ECL_UNIFIED_RESTART_FILE) { int dummy; - seqnum_kw = ecl_kw_alloc_new("SEQNUM" , 1 , ECL_INT_TYPE , &dummy); + seqnum_kw = ecl_kw_alloc_new("SEQNUM" , 1 , ECL_INT , &dummy); } { diff --git a/ThirdParty/Ert/libecl/applications/grdecl_grid.c b/ThirdParty/Ert/libecl/applications/grdecl_grid.c index e510ff8e45..f961118ef6 100644 --- a/ThirdParty/Ert/libecl/applications/grdecl_grid.c +++ b/ThirdParty/Ert/libecl/applications/grdecl_grid.c @@ -28,10 +28,10 @@ int main(int argc , char ** argv) { FILE * stream = util_fopen( argv[1] , "r"); - ecl_kw_type * gridhead_kw = ecl_kw_fscanf_alloc_grdecl_dynamic__( stream , SPECGRID_KW , false , ECL_INT_TYPE ); - ecl_kw_type * zcorn_kw = ecl_kw_fscanf_alloc_grdecl_dynamic( stream , ZCORN_KW , ECL_FLOAT_TYPE ); - ecl_kw_type * coord_kw = ecl_kw_fscanf_alloc_grdecl_dynamic( stream , COORD_KW , ECL_FLOAT_TYPE ); - ecl_kw_type * actnum_kw = ecl_kw_fscanf_alloc_grdecl_dynamic( stream , ACTNUM_KW , ECL_INT_TYPE ); + ecl_kw_type * gridhead_kw = ecl_kw_fscanf_alloc_grdecl_dynamic__( stream , SPECGRID_KW , false , ECL_INT ); + ecl_kw_type * zcorn_kw = ecl_kw_fscanf_alloc_grdecl_dynamic( stream , ZCORN_KW , ECL_FLOAT ); + ecl_kw_type * coord_kw = ecl_kw_fscanf_alloc_grdecl_dynamic( stream , COORD_KW , ECL_FLOAT ); + ecl_kw_type * actnum_kw = ecl_kw_fscanf_alloc_grdecl_dynamic( stream , ACTNUM_KW , ECL_INT ); { int nx = ecl_kw_iget_int( gridhead_kw , SPECGRID_NX_INDEX ); diff --git a/ThirdParty/Ert/libecl/applications/grdecl_test.c b/ThirdParty/Ert/libecl/applications/grdecl_test.c index a503f515b0..8e73a7db4c 100644 --- a/ThirdParty/Ert/libecl/applications/grdecl_test.c +++ b/ThirdParty/Ert/libecl/applications/grdecl_test.c @@ -32,7 +32,7 @@ int main(int argc , char ** argv) { while (true) { ecl_kw_type * grdecl_kw; timer_start( timer ); - grdecl_kw = ecl_kw_fscanf_alloc_current_grdecl( stream , ECL_FLOAT_TYPE ); + grdecl_kw = ecl_kw_fscanf_alloc_current_grdecl( stream , ECL_FLOAT ); timer_stop( timer ); if (grdecl_kw != NULL) { diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file.h index c0c1a682ff..d7186ada55 100644 --- a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file.h +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file.h @@ -32,6 +32,7 @@ extern "C" { #include #include #include +#include @@ -76,11 +77,11 @@ extern "C" { ecl_file_kw_type * ecl_file_iget_file_kw( const ecl_file_type * file , int global_index); ecl_file_kw_type * ecl_file_iget_named_file_kw( const ecl_file_type * file , const char * kw, int ith); ecl_kw_type * ecl_file_iget_kw( const ecl_file_type * file , int global_index); - ecl_type_enum ecl_file_iget_type( const ecl_file_type * file , int global_index); + ecl_data_type ecl_file_iget_data_type( const ecl_file_type * file , int global_index); int ecl_file_iget_size( const ecl_file_type * file , int global_index); const char * ecl_file_iget_header( const ecl_file_type * file , int global_index); ecl_kw_type * ecl_file_iget_named_kw( const ecl_file_type * file , const char * kw, int ith); - ecl_type_enum ecl_file_iget_named_type( const ecl_file_type * file , const char * kw , int ith); + ecl_data_type ecl_file_iget_named_data_type( const ecl_file_type * file , const char * kw , int ith); int ecl_file_iget_named_size( const ecl_file_type * file , const char * kw , int ith); void ecl_file_indexed_read(const ecl_file_type * file , const char * kw, int index, const int_vector_type * index_map, char* buffer); diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file_kw.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file_kw.h index 9965354171..bfd6b5e8e5 100644 --- a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file_kw.h +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file_kw.h @@ -45,7 +45,7 @@ typedef struct inv_map_struct inv_map_type; ecl_file_kw_type * ecl_file_kw_alloc_copy( const ecl_file_kw_type * src ); const char * ecl_file_kw_get_header( const ecl_file_kw_type * file_kw ); int ecl_file_kw_get_size( const ecl_file_kw_type * file_kw ); - ecl_type_enum ecl_file_kw_get_type( const ecl_file_kw_type * file_kw); + ecl_data_type ecl_file_kw_get_data_type(const ecl_file_kw_type *); offset_type ecl_file_kw_get_offset(const ecl_file_kw_type * file_kw); bool ecl_file_kw_ptr_eq( const ecl_file_kw_type * file_kw , const ecl_kw_type * ecl_kw); void ecl_file_kw_replace_kw( ecl_file_kw_type * file_kw , fortio_type * target , ecl_kw_type * new_kw ); diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file_view.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file_view.h index e44d332919..8e363158da 100644 --- a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file_view.h +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_file_view.h @@ -25,6 +25,7 @@ #include #include +#include #ifdef __cplusplus @@ -63,11 +64,11 @@ typedef struct ecl_file_view_struct ecl_file_view_type; const char * ecl_file_view_iget_distinct_kw( const ecl_file_view_type * ecl_file_view , int index); int ecl_file_view_get_num_distinct_kw( const ecl_file_view_type * ecl_file_view ); int ecl_file_view_get_size( const ecl_file_view_type * ecl_file_view ); - ecl_type_enum ecl_file_view_iget_type( const ecl_file_view_type * ecl_file_view , int index); + ecl_data_type ecl_file_view_iget_data_type( const ecl_file_view_type * ecl_file_view , int index); int ecl_file_view_iget_size( const ecl_file_view_type * ecl_file_view , int index); const char * ecl_file_view_iget_header( const ecl_file_view_type * ecl_file_view , int index); ecl_kw_type * ecl_file_view_iget_named_kw( const ecl_file_view_type * ecl_file_view , const char * kw, int ith); - ecl_type_enum ecl_file_view_iget_named_type( const ecl_file_view_type * ecl_file_view , const char * kw , int ith); + ecl_data_type ecl_file_view_iget_named_data_type( const ecl_file_view_type * ecl_file_view , const char * kw , int ith); int ecl_file_view_iget_named_size( const ecl_file_view_type * ecl_file_view , const char * kw , int ith); void ecl_file_view_replace_kw( ecl_file_view_type * ecl_file_view , ecl_kw_type * old_kw , ecl_kw_type * new_kw , bool insert_copy); bool ecl_file_view_load_all( ecl_file_view_type * ecl_file_view ); diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_grid.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_grid.h index af5e23fe39..fdea668183 100644 --- a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_grid.h +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_grid.h @@ -32,6 +32,9 @@ extern "C" { #include #include +#define ECL_GRID_COORD_SIZE(nx,ny) (((nx) + 1) * ((ny) + 1) * 6) +#define ECL_GRID_ZCORN_SIZE(nx,ny,nz) (((nx) * (ny) * (nz) * 8)) + #define ECL_GRID_GLOBAL_GRID "Global" // used as key in hash tables over grids. #define ECL_GRID_MAINGRID_LGR_NR 0 @@ -46,6 +49,8 @@ extern "C" { ecl_coarse_cell_type * ecl_grid_get_cell_coarse_group1( const ecl_grid_type * ecl_grid , int global_index); ecl_coarse_cell_type * ecl_grid_get_cell_coarse_group3( const ecl_grid_type * ecl_grid , int i , int j , int k); + int ecl_grid_get_cell_twist1( const ecl_grid_type * ecl_grid, int global_index ); + int ecl_grid_get_cell_twist3( const ecl_grid_type * ecl_grid, int i , int j , int k); void ecl_grid_get_column_property(const ecl_grid_type * ecl_grid , const ecl_kw_type * ecl_kw , int i , int j, double_vector_type * column); int ecl_grid_get_global_index_from_xy_top( const ecl_grid_type * ecl_grid , double x , double y); @@ -84,6 +89,7 @@ extern "C" { bool ecl_grid_cell_contains1(const ecl_grid_type * grid , int global_index , double x , double y , double z); bool ecl_grid_cell_contains3(const ecl_grid_type * grid , int i , int j ,int k , double x , double y , double z); int ecl_grid_get_global_index_from_xyz(ecl_grid_type * grid , double x , double y , double z , int start_index); + bool ecl_grid_get_ijk_from_xyz(ecl_grid_type * grid , double x , double y , double z , int start_index, int *i, int *j, int *k ); bool ecl_grid_get_ij_from_xy( const ecl_grid_type * grid , double x , double y , int k , int* i, int* j); const char * ecl_grid_get_name( const ecl_grid_type * ); int ecl_grid_get_active_index3(const ecl_grid_type * ecl_grid , int i , int j , int k); @@ -130,9 +136,14 @@ extern "C" { void ecl_grid_get_ijk1(const ecl_grid_type * , int global_index , int *, int * , int *); void ecl_grid_get_ijk1A(const ecl_grid_type * , int active_index, int *, int * , int *); void ecl_grid_get_ijk_from_active_index(const ecl_grid_type *, int , int *, int * , int * ); + void ecl_grid_get_xyz3(const ecl_grid_type * , int , int , int , double * , double * , double *); void ecl_grid_get_xyz1(const ecl_grid_type * grid , int global_index , double *xpos , double *ypos , double *zpos); void ecl_grid_get_xyz1A(const ecl_grid_type * grid , int active_index , double *xpos , double *ypos , double *zpos); + + bool ecl_grid_get_xyz_inside1(const ecl_grid_type * grid , int global_index , double *xpos , double *ypos , double *zpos); + bool ecl_grid_get_xyz_inside3(const ecl_grid_type * grid , int i , int j , int k , double *xpos , double *ypos , double *zpos); + int ecl_grid_get_global_size( const ecl_grid_type * ecl_grid ); bool ecl_grid_compare(const ecl_grid_type * g1 , const ecl_grid_type * g2 , bool include_lgr, bool include_nnc , bool verbose); int ecl_grid_get_active_size( const ecl_grid_type * ecl_grid ); @@ -205,6 +216,7 @@ extern "C" { void ecl_grid_fprintf_grdecl( ecl_grid_type * grid , FILE * stream ); void ecl_grid_fprintf_grdecl2( ecl_grid_type * grid , FILE * stream , ert_ecl_unit_enum output_unit); + int ecl_grid_zcorn_index__(int nx, int ny , int i, int j , int k , int c); int ecl_grid_zcorn_index(const ecl_grid_type * grid , int i, int j , int k , int c); ecl_grid_type * ecl_grid_alloc_EGRID(const char * grid_file, bool apply_mapaxes ); ecl_grid_type * ecl_grid_alloc_GRID(const char * grid_file, bool apply_mapaxes ); diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw.h index 25accc5926..eca17750c8 100644 --- a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw.h +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw.h @@ -31,6 +31,7 @@ extern "C" { #include #include +#include UTIL_IS_INSTANCE_HEADER(ecl_kw); @@ -55,13 +56,24 @@ extern "C" { #define ECL_KW_MAX_SIZE INT_MAX +/* + Character data in ECLIPSE files comes as an array of fixed-length + string. Each of these strings is 8 characters long. The type name, + i.e. 'REAL', 'INTE', ... , come as 4 character strings. +*/ +#define ECL_KW_HEADER_DATA_SIZE ECL_STRING8_LENGTH + ECL_TYPE_LENGTH + 4 +#define ECL_KW_HEADER_FORTIO_SIZE ECL_KW_HEADER_DATA_SIZE + 8 + + + int ecl_kw_first_different( const ecl_kw_type * kw1 , const ecl_kw_type * kw2 , int offset, double abs_epsilon , double rel_epsilon); size_t ecl_kw_fortio_size( const ecl_kw_type * ecl_kw ); void * ecl_kw_get_ptr(const ecl_kw_type *ecl_kw); void ecl_kw_set_data_ptr(ecl_kw_type * ecl_kw , void * data); void ecl_kw_fwrite_data(const ecl_kw_type *_ecl_kw , fortio_type *fortio); bool ecl_kw_fread_realloc_data(ecl_kw_type *ecl_kw, fortio_type *fortio); - ecl_type_enum ecl_kw_get_type(const ecl_kw_type *); + ecl_data_type ecl_kw_get_data_type(const ecl_kw_type *); + size_t ecl_kw_get_sizeof_ctype(const ecl_kw_type *); const char * ecl_kw_get_header8(const ecl_kw_type *); const char * ecl_kw_get_header(const ecl_kw_type * ecl_kw ); ecl_kw_type * ecl_kw_alloc_empty(void); @@ -78,7 +90,7 @@ extern "C" { void ecl_kw_fread(ecl_kw_type * , fortio_type * ); ecl_kw_type * ecl_kw_fread_alloc(fortio_type *); void ecl_kw_free_data(ecl_kw_type *); - void ecl_kw_fread_indexed_data(fortio_type * fortio, offset_type data_offset, ecl_type_enum ecl_type, int element_count, const int_vector_type* index_map, char* buffer); + void ecl_kw_fread_indexed_data(fortio_type * fortio, offset_type data_offset, ecl_data_type, int element_count, const int_vector_type* index_map, char* buffer); void ecl_kw_free(ecl_kw_type *); void ecl_kw_free__(void *); ecl_kw_type * ecl_kw_alloc_copy (const ecl_kw_type *); @@ -103,11 +115,11 @@ extern "C" { void * ecl_kw_iget_ptr(const ecl_kw_type *, int); int ecl_kw_get_size(const ecl_kw_type *); bool ecl_kw_ichar_eq(const ecl_kw_type *, int , const char *); - ecl_kw_type * ecl_kw_alloc( const char * header , int size , ecl_type_enum ecl_type ); - ecl_kw_type * ecl_kw_alloc_new(const char * , int , ecl_type_enum , const void * ); - ecl_kw_type * ecl_kw_alloc_new_shared(const char * , int , ecl_type_enum , void * ); - void ecl_kw_fwrite_param(const char * , bool , const char * , ecl_type_enum , int , void * ); - void ecl_kw_fwrite_param_fortio(fortio_type *, const char * , ecl_type_enum , int , void * ); + ecl_kw_type * ecl_kw_alloc( const char * header , int size , ecl_data_type ); + ecl_kw_type * ecl_kw_alloc_new(const char * , int , ecl_data_type , const void * ); + ecl_kw_type * ecl_kw_alloc_new_shared(const char * , int , ecl_data_type , void * ); + void ecl_kw_fwrite_param(const char * , bool , const char * , ecl_data_type , int , void * ); + void ecl_kw_fwrite_param_fortio(fortio_type *, const char * , ecl_data_type , int , void * ); void ecl_kw_summarize(const ecl_kw_type * ecl_kw); void ecl_kw_fread_double_param(const char * , bool , double *); float ecl_kw_iget_as_float(const ecl_kw_type * ecl_kw , int i); @@ -123,7 +135,7 @@ extern "C" { bool ecl_kw_block_equal( const ecl_kw_type * ecl_kw1 , const ecl_kw_type * ecl_kw2 , int cmp_elements); bool ecl_kw_data_equal( const ecl_kw_type * ecl_kw , const void * data); bool ecl_kw_content_equal( const ecl_kw_type * ecl_kw1 , const ecl_kw_type * ecl_kw2); - bool ecl_kw_fskip_data__( ecl_type_enum ecl_type , int size , fortio_type * fortio); + bool ecl_kw_fskip_data__( ecl_data_type, int, fortio_type *); bool ecl_kw_fskip_data(ecl_kw_type *ecl_kw, fortio_type *fortio); bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio); void ecl_kw_fskip_header( fortio_type * fortio); diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw_grdecl.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw_grdecl.h index 8174a1e5ea..6c5afabcb1 100644 --- a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw_grdecl.h +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw_grdecl.h @@ -32,17 +32,17 @@ extern "C" { bool ecl_kw_grdecl_fseek_kw(const char * , bool , FILE * ); - ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_dynamic__( FILE * stream , const char * kw , bool strict , ecl_type_enum ecl_type); - ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_dynamic( FILE * stream , const char * kw , ecl_type_enum ecl_type); + ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_dynamic__( FILE * stream , const char * kw , bool strict , ecl_data_type ); + ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_dynamic( FILE * stream , const char * kw , ecl_data_type); - ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_data__(FILE * stream , bool strict , int size, ecl_type_enum ecl_type ); - ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_data( FILE * stream , int size , ecl_type_enum ecl_type); + ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_data__(FILE * stream , bool strict , int size, ecl_data_type data_type ); + ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_data( FILE * stream , int size , ecl_data_type data_type); - ecl_kw_type * ecl_kw_fscanf_alloc_grdecl__(FILE * stream, const char * kw , bool strict , int size, ecl_type_enum ecl_type); - ecl_kw_type * ecl_kw_fscanf_alloc_grdecl(FILE * stream , const char * kw, int size, ecl_type_enum ecl_type); + ecl_kw_type * ecl_kw_fscanf_alloc_grdecl__(FILE * stream, const char * kw , bool strict , int size, ecl_data_type data_type); + ecl_kw_type * ecl_kw_fscanf_alloc_grdecl(FILE * stream , const char * kw, int size, ecl_data_type data_type); - ecl_kw_type * ecl_kw_fscanf_alloc_current_grdecl__( FILE * stream , bool strict , ecl_type_enum ecl_type); - ecl_kw_type * ecl_kw_fscanf_alloc_current_grdecl( FILE * stream , ecl_type_enum ecl_type); + ecl_kw_type * ecl_kw_fscanf_alloc_current_grdecl__( FILE * stream , bool strict , ecl_data_type data_type); + ecl_kw_type * ecl_kw_fscanf_alloc_current_grdecl( FILE * stream , ecl_data_type data_type); bool ecl_kw_grdecl_fseek_next_kw( FILE * stream ); char * ecl_kw_grdecl_alloc_next_header( FILE * stream ); diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_nnc_geometry.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_nnc_geometry.h new file mode 100644 index 0000000000..743d45f33a --- /dev/null +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_nnc_geometry.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2017 Statoil ASA, Norway. + + The file 'ecl_nnc_geometry.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 at + for more details. +*/ + +#ifndef ERT_NNC_GEOMETRY_H +#define ERT_NNC_GEOMETRY_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +typedef struct ecl_nnc_geometry_struct ecl_nnc_geometry_type; +typedef struct ecl_nnc_pair_struct ecl_nnc_pair_type; + +struct ecl_nnc_pair_struct { + int grid_nr1; + int global_index1; + int grid_nr2; + int global_index2; + + int input_index; /* corresponds to the input ordering of this nnc */ +}; + +UTIL_IS_INSTANCE_HEADER( ecl_nnc_geometry); +void ecl_nnc_geometry_free( ecl_nnc_geometry_type * nnc_geo); +ecl_nnc_geometry_type * ecl_nnc_geometry_alloc( const ecl_grid_type * grid ); +int ecl_nnc_geometry_size( const ecl_nnc_geometry_type * nnc_geo ); +const ecl_nnc_pair_type * ecl_nnc_geometry_iget( const ecl_nnc_geometry_type * nnc_geo , int index); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_type.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_type.h new file mode 100644 index 0000000000..8ae1597916 --- /dev/null +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_type.h @@ -0,0 +1,150 @@ +/* + Copyright (C) 2017 Statoil ASA, Norway. + + The file 'ecl_type.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 at + for more details. +*/ + +#ifndef ERT_ECL_TYPE_H +#define ERT_ECL_TYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + The type of an eclipse keyword is carried by a struct + ecl_type_struct which contains a type enum, and the size in bytes of + one such element. These structs are for the most part handled with + value semantics, and created with macros ECL_INT, ECL_FLOAT and so + on. + + The macros in C use designated initializers, whereas the C++ macros + use a constructor, for this reason this file has two slightly + different code paths for C and C++. +*/ + + +typedef enum { + ECL_CHAR_TYPE = 0, + ECL_FLOAT_TYPE = 1, + ECL_DOUBLE_TYPE = 2, + ECL_INT_TYPE = 3, + ECL_BOOL_TYPE = 4, + ECL_MESS_TYPE = 5, + ECL_C010_TYPE = 6 // See comment immediately above about the limited support of this type. +} ecl_type_enum; + +#define ECL_TYPE_ENUM_DEFS {.value = 0 , .name = "ECL_CHAR_TYPE"}, \ +{.value = 1 , .name = "ECL_FLOAT_TYPE"} , \ +{.value = 2 , .name = "ECL_DOUBLE_TYPE"}, \ +{.value = 3 , .name = "ECL_INT_TYPE"}, \ +{.value = 4 , .name = "ECL_BOOL_TYPE"}, \ +{.value = 5 , .name = "ECL_MESS_TYPE"} + +#define ECL_TYPE_ENUM_SIZE 6 + +/* + Character data in ECLIPSE files comes as an array of fixed-length + string. Each of these strings is 8 characters long. The type name, + i.e. 'REAL', 'INTE', ... , come as 4 character strings. +*/ + +#define ECL_STRING8_LENGTH 8 // 'Normal' 8 characters 'CHAR' type. +#define ECL_STRING10_LENGTH 10 // 'Normal' 8 characters 'CHAR' type. +#define ECL_TYPE_LENGTH 4 + + +#ifdef __cplusplus +} +#endif + + +#ifdef __cplusplus + +struct ecl_type_struct { + const ecl_type_enum type; + const size_t element_size; + + ecl_type_struct( ecl_type_enum t, size_t es) : + type( t ), + element_size( es ) + {} +}; + +#define ECL_INT ecl_data_type( ECL_INT_TYPE, sizeof(int)) +#define ECL_FLOAT ecl_data_type( ECL_FLOAT_TYPE, sizeof(float)) +#define ECL_DOUBLE ecl_data_type( ECL_DOUBLE_TYPE, sizeof(double)) +#define ECL_BOOL ecl_data_type( ECL_BOOL_TYPE, sizeof(int)) +#define ECL_CHAR ecl_data_type( ECL_CHAR_TYPE, ECL_STRING8_LENGTH + 1) +#define ECL_MESS ecl_data_type( ECL_MESS_TYPE, 0) +#define ECL_C010 ecl_data_type( ECL_C010_TYPE . ECL_STRING10_LENGTH + 1) + +#else + +struct ecl_type_struct { + const ecl_type_enum type; + const size_t element_size; +}; + +#define ECL_CHAR (ecl_data_type) {.type = ECL_CHAR_TYPE, .element_size = ECL_STRING8_LENGTH + 1} +#define ECL_INT (ecl_data_type) {.type = ECL_INT_TYPE, .element_size = sizeof(int)} +#define ECL_FLOAT (ecl_data_type) {.type = ECL_FLOAT_TYPE, .element_size = sizeof(float)} +#define ECL_DOUBLE (ecl_data_type) {.type = ECL_DOUBLE_TYPE, .element_size = sizeof(double)} +#define ECL_BOOL (ecl_data_type) {.type = ECL_BOOL_TYPE, .element_size = sizeof(int)} +#define ECL_MESS (ecl_data_type) {.type = ECL_MESS_TYPE, .element_size = 0} +#define ECL_C010 (ecl_data_type) {.type = ECL_C010_TYPE, .element_size = ECL_STRING10_LENGTH + 1} + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ecl_type_struct ecl_data_type; + + + +ecl_data_type ecl_type_create_from_name(const char *); +ecl_data_type ecl_type_create(const ecl_type_enum, const size_t); +ecl_data_type ecl_type_create_from_type(const ecl_type_enum); + +ecl_type_enum ecl_type_get_type(const ecl_data_type); +const char * ecl_type_get_name(const ecl_data_type); + +int ecl_type_get_sizeof_ctype(const ecl_data_type); +int ecl_type_get_sizeof_ctype_fortio(const ecl_data_type); + +bool ecl_type_is_equal(const ecl_data_type, const ecl_data_type); + +bool ecl_type_is_numeric(const ecl_data_type); +bool ecl_type_is_char(const ecl_data_type); +bool ecl_type_is_int(const ecl_data_type); +bool ecl_type_is_float(const ecl_data_type); +bool ecl_type_is_double(const ecl_data_type); +bool ecl_type_is_mess(const ecl_data_type); +bool ecl_type_is_bool(const ecl_data_type); +bool ecl_type_is_C010(const ecl_data_type); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_util.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_util.h index f7aeabc996..67cca9cde2 100644 --- a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_util.h +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_util.h @@ -27,6 +27,7 @@ extern "C" { #include #include #include +#include typedef enum { ECL_OTHER_FILE = 0 , @@ -55,68 +56,6 @@ typedef enum { ECL_OTHER_FILE = 0 , ECL_BINARY_NON_UNIFIED = 4, ECL_FORMATTED_NON_UNIFIED = 8} ecl_storage_enum; -/* - Character data in ECLIPSE files comes as an array of fixed-length - string. Each of these strings is 8 characters long. The type name, - i.e. 'REAL', 'INTE', ... , come as 4 character strings. -*/ - -#define ECL_STRING10_LENGTH 10 // Initial guess that the type C010 type is a10 character string. -#define ECL_STRING8_LENGTH 8 -#define ECL_TYPE_LENGTH 4 -#define ECL_KW_HEADER_DATA_SIZE ECL_STRING8_LENGTH + ECL_TYPE_LENGTH + 4 -#define ECL_KW_HEADER_FORTIO_SIZE ECL_KW_HEADER_DATA_SIZE + 8 - -/*****************************************************************/ -/* - Observe that these type identidiers are (ab)used in both the rms and - ert/enkf libraries in situations where ECLIPSE is not at all involved. - - Regarding the type ECL_C010_TYPE: In an SMSPEC file generated by IX - there was a keyword with header: - - NAMES 316 C010 - - i.e. the type identifier was the string 'C010'. Have not found any - further documentation of that type, but assuming it is a 10 - character long string the file loads ok. The ECL_C010_TYPE is - implemented on a very loose basis it is not clear if the - ten-character-long-string implementation makes sense, or if that - just happened to work for the one example we have encountered so - far. For this reason the support for this keyword type is very - limited: - - - keywords of this type are not propertly internalized; they are - just cleanly skipped by ecl_kw/ecl_file implementation when - loading a file. - - - it is not possible to instantiate a keyword of this type with - ecl_kw_alloc( ). - - - The type is not exported to Python. -*/ - -typedef enum { - ECL_CHAR_TYPE = 0, - ECL_FLOAT_TYPE = 1, - ECL_DOUBLE_TYPE = 2, - ECL_INT_TYPE = 3, - ECL_BOOL_TYPE = 4, - ECL_MESS_TYPE = 5, - ECL_C010_TYPE = 6 // See comment immediately above about the limited support of this type. -} ecl_type_enum; - -#define ECL_TYPE_ENUM_DEFS {.value = 0 , .name = "ECL_CHAR_TYPE"}, \ -{.value = 1 , .name = "ECL_FLOAT_TYPE"} , \ -{.value = 2 , .name = "ECL_DOUBLE_TYPE"}, \ -{.value = 3 , .name = "ECL_INT_TYPE"}, \ -{.value = 4 , .name = "ECL_BOOL_TYPE"}, \ -{.value = 5 , .name = "ECL_MESS_TYPE"} - -#define ECL_TYPE_ENUM_SIZE 6 - - - /* The libecl library has been built and tested 99.5% with ECLIPSE100 as context, but in thye gravity code there is some very limited @@ -173,10 +112,6 @@ typedef enum { #define ECL_COMMENT_CHAR '-' // Need to consecutive to make an ECLIPSE comment #define ECL_DATA_TERMINATION "/" -int ecl_util_get_sizeof_ctype_fortio(ecl_type_enum ecl_type); -int ecl_util_get_sizeof_ctype(ecl_type_enum ); -ecl_type_enum ecl_util_get_type_from_name( const char * type_name ); -const char * ecl_util_get_type_name( ecl_type_enum ecl_type ); /*****************************************************************/ bool ecl_util_unified_file(const char *filename); @@ -187,7 +122,7 @@ ecl_file_enum ecl_util_get_file_type(const char * , bool * , int * ); ecl_file_enum ecl_util_inspect_extension(const char * ext , bool *_fmt_file, int * _report_nr); char * ecl_util_alloc_filename(const char * /* path */, const char * /* base */, ecl_file_enum , bool /* fmt_file */ , int /*report_nr*/); char * ecl_util_alloc_exfilename(const char * /* path */, const char * /* base */, ecl_file_enum , bool /* fmt_file */ , int /*report_nr*/); -void ecl_util_memcpy_typed_data(void *, const void * , ecl_type_enum , ecl_type_enum , int ); +void ecl_util_memcpy_typed_data(void *, const void * , ecl_data_type , ecl_data_type , int ); void ecl_util_escape_kw(char * kw); bool ecl_util_alloc_summary_files(const char * , const char * , const char * , char ** , stringlist_type * ); void ecl_util_alloc_summary_data_files(const char * path , const char * base , bool fmt_file , stringlist_type * filelist); diff --git a/ThirdParty/Ert/libecl/src/CMakeLists.txt b/ThirdParty/Ert/libecl/src/CMakeLists.txt index 3c3994b174..d59c9baf95 100644 --- a/ThirdParty/Ert/libecl/src/CMakeLists.txt +++ b/ThirdParty/Ert/libecl/src/CMakeLists.txt @@ -2,85 +2,90 @@ include_directories( ext ) file(GLOB ext_source "ext/*.c" ) file(GLOB ext_header "ext/*.h" ) -set( source_files - ecl_rsthead.c - ecl_sum_tstep.c - ecl_rst_file.c - ecl_init_file.c - ecl_grid_cache.c - smspec_node.c - ecl_kw_grdecl.c +set( source_files + ecl_rsthead.c + ecl_sum_tstep.c + ecl_rst_file.c + ecl_init_file.c + ecl_grid_cache.c + smspec_node.c + ecl_kw_grdecl.c ecl_file_kw.c - ecl_file_view.c - ecl_grav.c - ecl_grav_calc.c - ecl_smspec.c - ecl_sum_data.c - ecl_util.c - ecl_kw.c + ecl_file_view.c + ecl_grav.c + ecl_grav_calc.c + ecl_smspec.c + ecl_sum_data.c + ecl_util.c + ecl_kw.c ecl_sum.c ecl_sum_vector.c - fortio.c - ecl_rft_file.c - ecl_rft_node.c - ecl_rft_cell.c - ecl_grid.c - ecl_coarse_cell.c - ecl_box.c - ecl_io_config.c - ecl_file.c - ecl_region.c - ecl_subsidence.c - ecl_grid_dims.c - grid_dims.c - nnc_info.c - ecl_grav_common.c - nnc_vector.c - ecl_nnc_export.c + fortio.c + ecl_rft_file.c + ecl_rft_node.c + ecl_rft_cell.c + ecl_grid.c + ecl_coarse_cell.c + ecl_box.c + ecl_io_config.c + ecl_file.c + ecl_region.c + ecl_subsidence.c + ecl_grid_dims.c + grid_dims.c + nnc_info.c + ecl_grav_common.c + nnc_vector.c + ecl_nnc_export.c + ecl_nnc_geometry.c layer.c fault_block_layer.c + ecl_type.c + ecl_type_python.c ${ext_source}) -set( header_files - ecl_rsthead.h - ecl_sum_tstep.h - ecl_rst_file.h - ecl_init_file.h - smspec_node.h - ecl_grid_cache.h - ecl_kw_grdecl.h - ecl_file_kw.h - ecl_grav.h - ecl_grav_calc.h - ecl_endian_flip.h - ecl_smspec.h - ecl_sum_data.h - ecl_util.h - ecl_kw.h +set( header_files + ecl_rsthead.h + ecl_sum_tstep.h + ecl_rst_file.h + ecl_init_file.h + smspec_node.h + ecl_grid_cache.h + ecl_kw_grdecl.h + ecl_file_kw.h + ecl_grav.h + ecl_grav_calc.h + ecl_endian_flip.h + ecl_smspec.h + ecl_sum_data.h + ecl_util.h + ecl_kw.h ecl_sum.h ecl_sum_vector.h - fortio.h - ecl_rft_file.h - ecl_rft_node.h - ecl_rft_cell.h - ecl_box.h - ecl_coarse_cell.h - ecl_grid.h - ecl_io_config.h + fortio.h + ecl_rft_file.h + ecl_rft_node.h + ecl_rft_cell.h + ecl_box.h + ecl_coarse_cell.h + ecl_grid.h + ecl_io_config.h ecl_file.h - ecl_file_view.h - ecl_region.h - ecl_kw_magic.h - ecl_subsidence.h - ecl_grid_dims.h - grid_dims.h - nnc_info.h - nnc_vector.h - ecl_grav_common.h - ecl_nnc_export.h + ecl_file_view.h + ecl_region.h + ecl_kw_magic.h + ecl_subsidence.h + ecl_grid_dims.h + grid_dims.h + nnc_info.h + nnc_vector.h + ecl_grav_common.h + ecl_nnc_export.h + ecl_nnc_geometry.h layer.h fault_block.h fault_block_layer.h + ecl_type.h ${ext_header}) if (ERT_USE_OPENMP) @@ -98,7 +103,7 @@ endif() target_link_libraries( ecl ert_geometry ert_util ) #----------------------------------------------------------------- -if (INSTALL_ERT) +if (INSTALL_ERT) install(TARGETS ecl DESTINATION ${CMAKE_INSTALL_LIBDIR}) foreach(header ${header_files}) install(FILES ../include/ert/ecl/${header} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/ert/ecl) diff --git a/ThirdParty/Ert/libecl/src/ecl_file.c b/ThirdParty/Ert/libecl/src/ecl_file.c index 0559f1d796..064cb0d027 100644 --- a/ThirdParty/Ert/libecl/src/ecl_file.c +++ b/ThirdParty/Ert/libecl/src/ecl_file.c @@ -36,6 +36,7 @@ #include #include #include +#include /** This file implements functionality to load an ECLIPSE file in @@ -418,8 +419,8 @@ ecl_kw_type * ecl_file_iget_kw( const ecl_file_type * file , int global_index) { return ecl_file_view_iget_kw( file->active_view , global_index); } -ecl_type_enum ecl_file_iget_type( const ecl_file_type * file , int global_index) { - return ecl_file_view_iget_type( file->active_view , global_index); +ecl_data_type ecl_file_iget_data_type( const ecl_file_type * file , int global_index) { + return ecl_file_view_iget_data_type( file->active_view , global_index); } int ecl_file_iget_size( const ecl_file_type * file , int global_index) { @@ -446,8 +447,8 @@ void ecl_file_indexed_read(const ecl_file_type * file , const char * kw, int ind ecl_file_view_index_fload_kw(file->active_view, kw, index, index_map, buffer); } -ecl_type_enum ecl_file_iget_named_type( const ecl_file_type * file , const char * kw , int ith) { - return ecl_file_view_iget_named_type( file->active_view , kw , ith ); +ecl_data_type ecl_file_iget_named_data_type( const ecl_file_type * file , const char * kw , int ith) { + return ecl_file_view_iget_named_data_type( file->active_view , kw , ith ); } int ecl_file_iget_named_size( const ecl_file_type * file , const char * kw , int ith) { @@ -515,7 +516,7 @@ static bool ecl_file_scan( ecl_file_type * ecl_file ) { bool scan_ok = false; fortio_fseek( ecl_file->fortio , 0 , SEEK_SET ); { - ecl_kw_type * work_kw = ecl_kw_alloc_new("WORK-KW" , 0 , ECL_INT_TYPE , NULL); + ecl_kw_type * work_kw = ecl_kw_alloc_new("WORK-KW" , 0 , ECL_INT , NULL); while (true) { if (fortio_read_at_eof(ecl_file->fortio)) { diff --git a/ThirdParty/Ert/libecl/src/ecl_file_kw.c b/ThirdParty/Ert/libecl/src/ecl_file_kw.c index 64e106589a..4a137974c2 100644 --- a/ThirdParty/Ert/libecl/src/ecl_file_kw.c +++ b/ThirdParty/Ert/libecl/src/ecl_file_kw.c @@ -57,7 +57,7 @@ struct inv_map_struct { struct ecl_file_kw_struct { UTIL_TYPE_ID_DECLARATION; offset_type file_offset; - ecl_type_enum ecl_type; + ecl_data_type data_type; int kw_size; char * header; ecl_kw_type * kw; @@ -135,13 +135,13 @@ UTIL_IS_INSTANCE_FUNCTION( ecl_file_kw , ECL_FILE_KW_TYPE_ID ) -static ecl_file_kw_type * ecl_file_kw_alloc__( const char * header , ecl_type_enum ecl_type , int size , offset_type offset) { +static ecl_file_kw_type * ecl_file_kw_alloc__( const char * header , ecl_data_type data_type , int size , offset_type offset) { ecl_file_kw_type * file_kw = util_malloc( sizeof * file_kw ); UTIL_TYPE_ID_INIT( file_kw , ECL_FILE_KW_TYPE_ID ); file_kw->header = util_alloc_string_copy( header ); + memcpy(&file_kw->data_type, &data_type, sizeof data_type); file_kw->kw_size = size; - file_kw->ecl_type = ecl_type; file_kw->file_offset = offset; file_kw->kw = NULL; @@ -161,7 +161,7 @@ static ecl_file_kw_type * ecl_file_kw_alloc__( const char * header , ecl_type_en */ ecl_file_kw_type * ecl_file_kw_alloc( const ecl_kw_type * ecl_kw , offset_type offset ) { - return ecl_file_kw_alloc__( ecl_kw_get_header( ecl_kw ) , ecl_kw_get_type( ecl_kw ) , ecl_kw_get_size( ecl_kw ) , offset ); + return ecl_file_kw_alloc__( ecl_kw_get_header( ecl_kw ) , ecl_kw_get_data_type( ecl_kw ) , ecl_kw_get_size( ecl_kw ) , offset ); } @@ -169,7 +169,7 @@ ecl_file_kw_type * ecl_file_kw_alloc( const ecl_kw_type * ecl_kw , offset_type o Does NOT copy the kw pointer which must be reloaded. */ ecl_file_kw_type * ecl_file_kw_alloc_copy( const ecl_file_kw_type * src ) { - return ecl_file_kw_alloc__( src->header , src->ecl_type , src->kw_size , src->file_offset ); + return ecl_file_kw_alloc__( src->header , ecl_file_kw_get_data_type(src) , src->kw_size , src->file_offset ); } @@ -193,7 +193,10 @@ void ecl_file_kw_free__( void * arg ) { static void ecl_file_kw_assert_kw( const ecl_file_kw_type * file_kw ) { - if (file_kw->ecl_type != ecl_kw_get_type( file_kw->kw )) + if(!ecl_type_is_equal( + ecl_file_kw_get_data_type(file_kw), + ecl_kw_get_data_type(file_kw->kw) + )) util_abort("%s: type mismatch between header and file.\n",__func__); if (file_kw->kw_size != ecl_kw_get_size( file_kw->kw )) @@ -265,18 +268,20 @@ bool ecl_file_kw_ptr_eq( const ecl_file_kw_type * file_kw , const ecl_kw_type * void ecl_file_kw_replace_kw( ecl_file_kw_type * file_kw , fortio_type * target , ecl_kw_type * new_kw ) { - if ((file_kw->ecl_type == ecl_kw_get_type( new_kw )) && - (file_kw->kw_size == ecl_kw_get_size( new_kw ))) { + if (!ecl_type_is_equal( + ecl_file_kw_get_data_type(file_kw), + ecl_kw_get_data_type(new_kw) + )) + util_abort("%s: sorry type mismatch between in-file keyword and new keyword \n",__func__); + if((file_kw->kw_size == ecl_kw_get_size( new_kw ))) + util_abort("%s: sorry size mismatch between in-file keyword and new keyword \n",__func__); - if (file_kw->kw != NULL) - ecl_kw_free( file_kw->kw ); + if (file_kw->kw != NULL) + ecl_kw_free( file_kw->kw ); - file_kw->kw = new_kw; - fortio_fseek( target , file_kw->file_offset , SEEK_SET ); - ecl_kw_fwrite( file_kw->kw , target ); - - } else - util_abort("%s: sorry size/type mismatch between in-file keyword and new keyword \n",__func__); + file_kw->kw = new_kw; + fortio_fseek( target , file_kw->file_offset , SEEK_SET ); + ecl_kw_fwrite( file_kw->kw , target ); } @@ -289,8 +294,8 @@ int ecl_file_kw_get_size( const ecl_file_kw_type * file_kw ) { return file_kw->kw_size; } -ecl_type_enum ecl_file_kw_get_type( const ecl_file_kw_type * file_kw) { - return file_kw->ecl_type; +ecl_data_type ecl_file_kw_get_data_type(const ecl_file_kw_type * file_kw) { + return file_kw->data_type; } offset_type ecl_file_kw_get_offset(const ecl_file_kw_type * file_kw) { @@ -298,7 +303,7 @@ offset_type ecl_file_kw_get_offset(const ecl_file_kw_type * file_kw) { } bool ecl_file_kw_fskip_data( const ecl_file_kw_type * file_kw , fortio_type * fortio) { - return ecl_kw_fskip_data__( file_kw->ecl_type , file_kw->kw_size , fortio ); + return ecl_kw_fskip_data__( ecl_file_kw_get_data_type(file_kw) , file_kw->kw_size , fortio ); } diff --git a/ThirdParty/Ert/libecl/src/ecl_file_view.c b/ThirdParty/Ert/libecl/src/ecl_file_view.c index 38f6921270..5f74d3f1ce 100644 --- a/ThirdParty/Ert/libecl/src/ecl_file_view.c +++ b/ThirdParty/Ert/libecl/src/ecl_file_view.c @@ -27,6 +27,7 @@ #include #include #include +#include struct ecl_file_view_struct { @@ -166,10 +167,10 @@ void ecl_file_view_index_fload_kw(const ecl_file_view_type * ecl_file_view, cons if (fortio_assert_stream_open( ecl_file_view->fortio )) { offset_type offset = ecl_file_kw_get_offset(file_kw); - ecl_type_enum ecl_type = ecl_file_kw_get_type(file_kw); + ecl_data_type data_type = ecl_file_kw_get_data_type(file_kw); int element_count = ecl_file_kw_get_size(file_kw); - ecl_kw_fread_indexed_data(ecl_file_view->fortio, offset + ECL_KW_HEADER_FORTIO_SIZE, ecl_type, element_count, index_map, buffer); + ecl_kw_fread_indexed_data(ecl_file_view->fortio, offset + ECL_KW_HEADER_FORTIO_SIZE, data_type, element_count, index_map, buffer); } } @@ -204,9 +205,9 @@ int ecl_file_view_get_size( const ecl_file_view_type * ecl_file_view ) { } -ecl_type_enum ecl_file_view_iget_type( const ecl_file_view_type * ecl_file_view , int index) { +ecl_data_type ecl_file_view_iget_data_type( const ecl_file_view_type * ecl_file_view , int index) { ecl_file_kw_type * file_kw = ecl_file_view_iget_file_kw( ecl_file_view , index ); - return ecl_file_kw_get_type( file_kw ); + return ecl_file_kw_get_data_type( file_kw ); } int ecl_file_view_iget_size( const ecl_file_view_type * ecl_file_view , int index) { @@ -235,9 +236,9 @@ ecl_kw_type * ecl_file_view_iget_named_kw( const ecl_file_view_type * ecl_file_v return ecl_kw; } -ecl_type_enum ecl_file_view_iget_named_type( const ecl_file_view_type * ecl_file_view , const char * kw , int ith) { +ecl_data_type ecl_file_view_iget_named_data_type( const ecl_file_view_type * ecl_file_view , const char * kw , int ith) { ecl_file_kw_type * file_kw = ecl_file_view_iget_named_file_kw( ecl_file_view , kw, ith); - return ecl_file_kw_get_type( file_kw ); + return ecl_file_kw_get_data_type( file_kw ); } int ecl_file_view_iget_named_size( const ecl_file_view_type * ecl_file_view , const char * kw , int ith) { @@ -360,7 +361,7 @@ void ecl_file_view_fprintf_kw_list(const ecl_file_view_type * ecl_file_view , FI fprintf(stream , "%-8s %7d:%s\n", ecl_file_kw_get_header( file_kw ) , ecl_file_kw_get_size( file_kw ) , - ecl_util_get_type_name( ecl_file_kw_get_type( file_kw ))); + ecl_type_get_name( ecl_file_kw_get_data_type( file_kw ))); } } diff --git a/ThirdParty/Ert/libecl/src/ecl_grid.c b/ThirdParty/Ert/libecl/src/ecl_grid.c index d0eff2fd99..5f9004ceee 100644 --- a/ThirdParty/Ert/libecl/src/ecl_grid.c +++ b/ThirdParty/Ert/libecl/src/ecl_grid.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -492,45 +493,55 @@ Warning: The main author of this code suspects that the coordinate system can be right-handed as well, giving a z axis which will increase 'towards the sky'; the safest is probaly to check this explicitly if it matters for the case at hand. + +Method 0 corresponds to a tetrahedron decomposition which will split +the lower layer along the 1-2 diagonal and the upper layer along the +4-7 diagonal, method 1 corresponds to the alternative decomposition +which splits the lower face along the 0-3 diagnoal and the upper face +along the 5-6 diagonal. */ -static const int tetrahedron_permutations[2][12][3] = {{{0,1,2}, + +static const int tetrahedron_permutations[2][12][3] = {{ + // K- + {0,1,2}, {3,2,1}, - {0,4,1}, - {5,1,4}, + // J+ + {6,2,7}, + {3,7,2}, + // I- {0,2,4}, {6,4,2}, - {3,7,2}, - {6,2,7}, + // I+ {3,1,7}, {5,7,1}, + // J- + {0,4,1}, + {5,1,4}, + // K+ {5,4,7}, - {6,7,4}}, - {{1,5,3}, + {6,7,4} + }, + { + // K- {1,3,0}, - {1,0,5}, {2,0,3}, - {2,6,0}, + // J+ {2,3,6}, - {4,5,0}, - {4,6,5}, + {7,6,3}, + // I- + {2,6,0}, {4,0,6}, - {7,5,6}, + // I+ {7,3,5}, - {7,6,3}}}; - - - - - - - -static const int bounding_planes[6][3] = {{0,1,2}, - {0,2,4}, - {0,4,1}, - {4,6,5}, - {2,3,6}, - {1,5,3}}; + {1,5,3}, + // J- + {1,0,5}, + {4,5,0}, + // K+ + {7,5,6}, + {4,6,5} + }}; @@ -605,37 +616,6 @@ static double point_dot_product( const point_type * v1 , const point_type * v2) return v1->x*v2->x + v1->y*v2->y + v1->z*v2->z; } -static bool point_equal( const point_type *p1 , const point_type * p2) { - return (memcmp( p1 , p2 , sizeof * p1 ) == 0); -} - -/** - This function calculates the (signed) distance from point 'p' to - the plane specifed by the plane vector 'n' and the point - 'plane_point' which is part of the plane. -*/ - -static double point_plane_distance(const point_type * p , const point_type * n , const point_type * plane_point) { - point_type diff = *p; - point_inplace_sub( &diff, plane_point ); - return point_dot_product( n, &diff ); -} - -static void point_normal_vector(point_type * n, const point_type * p0, const point_type * p1 , const point_type * p2) { - point_type v1 = *p1; - point_type v2 = *p2; - - point_inplace_sub( &v1, p0 ); - point_inplace_sub( &v2, p0 ); - - point_vector_cross( n, &v1, &v2 ); -} - -static double point3_plane_distance(const point_type * p0 , const point_type * p1 , const point_type * p2 , const point_type * x) { - point_type n; - point_normal_vector( &n , p0 , p1 , p2 ); - return point_plane_distance( x , &n , p0 ) / sqrt( n.x*n.x + n.y*n.y + n.z*n.z); -} static void point_compare( const point_type *p1 , const point_type * p2, bool * equal) { const double tolerance = 0.001; @@ -1066,6 +1046,21 @@ static void ecl_cell_taint_cell( ecl_cell_type * cell ) { } + +static int ecl_cell_get_twist( const ecl_cell_type * cell ) { + int twist_count = 0; + + for (int c = 0; c < 4; c++) { + const point_type * p1 = &cell->corner_list[c]; + const point_type * p2 = &cell->corner_list[c + 4]; + if ((p2->z - p1->z) < 0) + twist_count += 1; + } + return twist_count; +} + + + /*****************************************************************/ @@ -1113,6 +1108,7 @@ static void ecl_cell_set_center( ecl_cell_type * cell) { } + static void ecl_cell_assert_center( ecl_cell_type * cell) { if (!GET_CELL_FLAG(cell , CELL_FLAG_CENTER)) ecl_cell_set_center( cell ); @@ -1230,6 +1226,35 @@ static inline double tetrahedron_volume6( tetrahedron_type tet ) { return tet.p0.x*bxc.x + tet.p0.y*bxc.y + tet.p0.z*bxc.z; } +/* + Returns true if and only if the point p is inside the tetrahedron tet. +*/ +static bool tetrahedron_contains(tetrahedron_type tet, const point_type p) { + const double epsilon = 1e-9; + double tetra_volume = fabs(tetrahedron_volume6(tet)); + + if(tetra_volume < epsilon) + return false; + + // Decomposes tetrahedron into 4 new tetrahedrons + point_type tetra_points[4] = {tet.p0, tet.p1, tet.p2, tet.p3}; + double decomposition_volume = 0; + for(int i = 0; i < 4; ++i) { + const point_type tmp = tetra_points[i]; + tetra_points[i] = p; + + // Compute volum of decomposition tetrahedron + tetrahedron_type dec_tet; + dec_tet.p0 = tetra_points[0]; dec_tet.p1 = tetra_points[1]; + dec_tet.p2 = tetra_points[2]; dec_tet.p3 = tetra_points[3]; + decomposition_volume += fabs(tetrahedron_volume6(dec_tet)); + + tetra_points[i] = tmp; + } + + return (fabs(tetra_volume - decomposition_volume) < epsilon); +} + /* * This function used to account for a significant amount of execution time * when used in opm-parser and has been optimised significantly. This means @@ -1340,6 +1365,52 @@ static bool triangle_contains(const point_type *p0 , const point_type * p1 , con } } +static double parallelogram_area3d(const point_type * p0, const point_type * p1, const point_type * p2) { + point_type a = *p1; + point_type b = *p2; + point_inplace_sub(&a, p0); + point_inplace_sub(&b, p0); + + point_type c; + point_vector_cross(&c, &a, &b); + return sqrt(point_dot_product(&c, &c)); +} + +/* + * Returns true if and only if point p is contained in the triangle denoted by + * p0, p1 and p2. Note that if the triangle is a line, the function will still + * return true if the point lies on the line segment. + */ +static bool triangle_contains3d(const point_type *p0 , const point_type * p1 , const point_type *p2 , const point_type *p) { + double epsilon = 1e-10; + double vt = parallelogram_area3d(p0, p1, p2); + + double v1 = parallelogram_area3d(p0, p1, p); + double v2 = parallelogram_area3d(p0, p2, p); + double v3 = parallelogram_area3d(p1, p2, p); + + // p0, p1, p2 represents a line segment and + // p lies on the line this segment represents + if(vt < epsilon && fabs(v1+v2+v3) < epsilon) { + double x_min = util_double_min(p0->x, util_double_min(p1->x, p2->x)); + double x_max = util_double_max(p0->x, util_double_max(p1->x, p2->x)); + + double y_min = util_double_min(p0->y, util_double_min(p1->y, p2->y)); + double y_max = util_double_max(p0->y, util_double_max(p1->y, p2->y)); + + double z_min = util_double_min(p0->z, util_double_min(p1->z, p2->z)); + double z_max = util_double_max(p0->z, util_double_max(p1->z, p2->z)); + + return ( + x_min-epsilon <= p->x && p->x <= x_max+epsilon && + y_min-epsilon <= p->y && p->y <= y_max+epsilon && + z_min-epsilon <= p->z && p->z <= z_max+epsilon + ); + } + + return (fabs( vt - (v1 + v2 + v3 )) < epsilon); +} + @@ -2153,10 +2224,7 @@ static void ecl_grid_set_lgr_name_GRID(ecl_grid_type * lgr_grid , const ecl_file the zcorn vector. */ -int ecl_grid_zcorn_index(const ecl_grid_type * grid , int i, int j , int k , int c) { - int nx = grid->nx; - int ny = grid->ny; - +int ecl_grid_zcorn_index__(int nx, int ny , int i, int j , int k , int c) { int zcorn_index = k*8*nx*ny + j*4*nx + 2*i; if ((c % 2) == 1) zcorn_index += 1; @@ -2173,6 +2241,9 @@ int ecl_grid_zcorn_index(const ecl_grid_type * grid , int i, int j , int k , int return zcorn_index; } +int ecl_grid_zcorn_index(const ecl_grid_type * grid , int i, int j , int k , int c) { + return ecl_grid_zcorn_index__( grid->nx, grid->ny , i , j , k , c ); +} static void ecl_grid_init_GRDECL_data_jslice(ecl_grid_type * ecl_grid , const float * zcorn , const float * coord , const int * actnum, const int * corsnum , int j) { @@ -2274,7 +2345,7 @@ static ecl_grid_type * ecl_grid_alloc_GRDECL_data__(ecl_grid_type * global_grid if (corsnum != NULL) ecl_grid->coarsening_active = true; - ecl_grid->coord_kw = ecl_kw_alloc_new("COORD" , 6*(nx + 1) * (ny + 1) , ECL_FLOAT_TYPE , coord ); + ecl_grid->coord_kw = ecl_kw_alloc_new("COORD" , 6*(nx + 1) * (ny + 1) , ECL_FLOAT , coord ); ecl_grid_init_GRDECL_data( ecl_grid , zcorn , coord , actnum , corsnum); ecl_grid_init_coarse_cells( ecl_grid ); @@ -2652,9 +2723,16 @@ static void ecl_grid_init_nnc(ecl_grid_type * main_grid, ecl_file_type * ecl_fil int num_nnchead_kw = ecl_file_get_num_named_kw( ecl_file , NNCHEAD_KW ); int i; - if(num_nnchead_kw > 0 && main_grid->eclipse_version == 2015){ - return; //Eclipse 2015 has an error with nnc. - } + /* + NB: There is a bug in Eclipse version 2015.1, for MPI runs with + six or more processors (I think ...) the NNC datastructures + are in an internally inconsistent state; and will lead to a + hard crash. The issue has been fixed in version 2015.2, but + unfortunately it is not possible to test for micro version. + + if(num_nnchead_kw > 0 && main_grid->eclipse_version == 2015) + return; + */ for (i = 0; i < num_nnchead_kw; i++) { ecl_file_view_type * lgr_view = ecl_file_alloc_global_blockview(ecl_file , NNCHEAD_KW , i); @@ -3750,143 +3828,268 @@ bool ecl_grid_compare(const ecl_grid_type * g1 , const ecl_grid_type * g2 , bool /*****************************************************************/ -bool ecl_grid_cell_contains_xyz1( const ecl_grid_type * ecl_grid , int global_index , double x , double y , double z) { - const double min_volume = 1e-9; - point_type p; - ecl_cell_type * cell = ecl_grid_get_cell( ecl_grid , global_index ); +typedef enum {NOT_ON_FACE, BELONGS_TO_CELL, BELONGS_TO_OTHER} face_status_enum; - point_set( &p , x , y , z); - /* - 1. first check if the point z value is below the deepest point of - the cell, or above the shallowest => return false. - - 2. should do similar fast checks in x/y direction. - - 3. full geometric verification. - */ - if (GET_CELL_FLAG(cell , CELL_FLAG_TAINTED)) +/* + Returns whether the given point is contained within the minimal cube + encapsulating the cell that has all faces parallel to a coordinate plane. +*/ +static bool ecl_grid_cube_contains(const ecl_cell_type * cell, const point_type * p) { + if (p->z < ecl_cell_min_z( cell )) return false; - if (p.z < ecl_cell_min_z( cell )) + if (p->z > ecl_cell_max_z( cell )) return false; - if (p.z > ecl_cell_max_z( cell )) + if (p->x < ecl_cell_min_x( cell )) return false; - if (p.x < ecl_cell_min_x( cell )) + if (p->x > ecl_cell_max_x( cell )) return false; - if (p.x > ecl_cell_max_x( cell )) + if (p->y < ecl_cell_min_y( cell )) return false; - if (p.y < ecl_cell_min_y( cell )) + if (p->y > ecl_cell_max_y( cell )) return false; - if (p.y > ecl_cell_max_y( cell )) - return false; + return true; +} - { - int i,j,k; - ecl_grid_get_ijk1( ecl_grid , global_index , &i , &j , &k); - ecl_cell_assert_center( cell ); +/* + Returns true if and only if p is on plane "plane" of cell when decomposed by "method". +*/ +static bool ecl_grid_on_plane(const ecl_cell_type * cell, const int method, + const int plane, const point_type * p) { + const point_type * p0 = &cell->corner_list[ tetrahedron_permutations[method][plane][0] ]; + const point_type * p1 = &cell->corner_list[ tetrahedron_permutations[method][plane][1] ]; + const point_type * p2 = &cell->corner_list[ tetrahedron_permutations[method][plane][2] ]; + return triangle_contains3d(p0, p1, p2, p); +} - /* - Special case checks for the corner points. - */ - if (point_equal( &p , &cell->corner_list[0])) - return true; +/* + Returns true if and only if p is on one of the cells faces and + "belongs" to this cell. This is done such that every point is contained in at most + one point. - if (point_equal( &p , &cell->corner_list[1] )) { - if (i == (ecl_grid->nx - 1)) - return true; - else + Known caveats when using this function: + - if a point is on the surface of a/many cells, but for all of these cells + the point is contained on two opposite sides of the cell. Imagine a cake + being cut as a cake should be cut. To which of the slices does the center + point of the cake belong? This is a somewhat obscure situation and it is + not possible to circumvent by only considering the grid cell by cell. + - if there is a fault and this cell is on the border of the grid. + - if a cells projection to the xy-plane is concave, this method might give + false positives. + + Note: The correctness of this function relies *HEAVILY* on the permutation of the + tetrahedrons in the decompositions. +*/ +static face_status_enum ecl_grid_on_cell_face(const ecl_cell_type * cell, const int method, + const point_type * p, + const bool max_i, const bool max_j, const bool max_k) { + + int k_minus = 0, j_pluss = 1, i_minus = 2, i_pluss = 3, j_minus = 4, k_pluss = 5; + bool on[6]; + for(int i = 0; i < 6; ++i) { + on[i] = ( + ecl_grid_on_plane(cell, method, 2*i, p) || + ecl_grid_on_plane(cell, method, 2*i+1, p) + ); + } + + // Not on any of the cell sides + if(!on[k_minus] && !on[k_pluss] && !on[j_pluss] && !on[j_minus] && !on[i_minus] && !on[i_pluss]) + return NOT_ON_FACE; + + // Handles side collapses, i.e. the point is contained on opposite sides. + // Cell passes on the responsibility if not on border of grid. + bool i_collapse = (on[i_minus] && on[i_pluss]); + bool j_collapse = (on[j_minus] && on[j_pluss]); + bool k_collapse = (on[k_minus] && on[k_pluss]); + + for(int i = 0; i < 6; ++i) + on[i] &= (!i_collapse || max_i) && (!j_collapse || max_j) && (!k_collapse || max_k); + + on[i_minus] &= !on[i_pluss]; + on[j_minus] &= !on[j_pluss]; + on[k_minus] &= !on[k_pluss]; + + // Removed from all sides + if(!on[k_minus] && !on[k_pluss] && !on[j_pluss] && !on[j_minus] && !on[i_minus] && !on[i_pluss]) + return BELONGS_TO_OTHER; + + // Not on any of the lower priority sides + if(!on[k_pluss] && !on[j_pluss] && !on[i_pluss]) + return BELONGS_TO_CELL; + + // Contained in cell due to border conditions + // NOTE: One should read X <= Y as X "implies" Y + if((on[i_pluss] <= max_i) && (on[j_pluss] <= max_j) && (on[k_pluss] <= max_k)) + return BELONGS_TO_CELL; + + return BELONGS_TO_OTHER; +} + +/* + Returns true if and only if the tetrahedron defined by p0, p1, p2, p3 + contains p. + + The sole purpose of this functions is to make concave_cell_contains + more readable. +*/ +static bool tetrahedron_by_points_contains(const point_type * p0, + const point_type * p1, + const point_type * p2, + const point_type * p3, + const point_type * p) { + + tetrahedron_type pro_tet; + pro_tet.p0 = *p0; + pro_tet.p1 = *p1; + pro_tet.p2 = *p2; + pro_tet.p3 = *p3; + + return tetrahedron_contains(pro_tet, *p); +} + +static bool tetrahedron_positive_volume(const point_type * p0, + const point_type * p1, + const point_type * p2, + const point_type * p3) { + + tetrahedron_type pro_tet; + pro_tet.p0 = *p0; + pro_tet.p1 = *p1; + pro_tet.p2 = *p2; + pro_tet.p3 = *p3; + + return tetrahedron_volume6(pro_tet) >= 0; +} + +/* + Returns true if and only if the cell "cell" decomposed by "method" contains the point "p". + This is done by decomposing the cell into 5 tetrahedrons according to the decomposition + method for the faces. + + Assumes the cell to not be self-intersecting! + + Note: This function relies *HEAVILY* on the permutation of tetrahedron_permutations. +*/ +static bool concave_cell_contains( const ecl_cell_type * cell, int method, const point_type * p) { + + const point_type * dia[2][2] = { + { + &cell->corner_list[tetrahedron_permutations[method][0][1]], + &cell->corner_list[tetrahedron_permutations[method][0][2]] + }, + { + &cell->corner_list[tetrahedron_permutations[method][10][1]], + &cell->corner_list[tetrahedron_permutations[method][10][2]] + } + }; + + const point_type * extra[2][2] = { + { + &cell->corner_list[tetrahedron_permutations[method][0][0]], + &cell->corner_list[tetrahedron_permutations[method][1][0]] + }, + { + &cell->corner_list[tetrahedron_permutations[method][10][0]], + &cell->corner_list[tetrahedron_permutations[method][11][0]] + } + }; + + // Test for containment in cell core + bool contained = tetrahedron_by_points_contains(dia[0][0], dia[1][0], dia[0][1], dia[1][1], p); + + // Test for containment in protrusions + for(int i = 0; i < 2; ++i) { + if(tetrahedron_by_points_contains(dia[i][0], dia[i][1], dia[(i+1)%2][0], extra[i][0], p)) { + contained = true; + + bool on_inner_faces = false; + on_inner_faces |= triangle_contains3d(dia[i][0], dia[(i+1)%2][0], extra[i][0], p); + on_inner_faces |= triangle_contains3d(dia[i][1], dia[(i+1)%2][0], extra[i][0], p); + + if(!on_inner_faces && !tetrahedron_positive_volume(dia[i][0], dia[i][1], dia[(i+1)%2][0], extra[i][0])) return false; } - if (point_equal( &p , &cell->corner_list[2])) { - if (j == (ecl_grid->ny - 1)) - return true; - else - return false; - } + if(tetrahedron_by_points_contains(dia[i][0], dia[(i+1)%2][1], dia[i][1], extra[i][1], p)) { + contained = true; - if (point_equal( &p , &cell->corner_list[3])) { - if ((j == (ecl_grid->ny - 1)) && - (i == (ecl_grid->nx - 1))) - return true; - else - return false; - } + bool on_inner_faces = false; + on_inner_faces |= triangle_contains3d(dia[i][0], dia[(i+1)%2][1], extra[i][1], p); + on_inner_faces |= triangle_contains3d(dia[i][1], dia[(i+1)%2][1], extra[i][1], p); - if (point_equal( &p , &cell->corner_list[4])) { - if (k == (ecl_grid->nz - 1)) - return true; - else - return false; - } - - if (point_equal( &p , &cell->corner_list[5] )) { - if ((i == (ecl_grid->nx - 1)) && - (k == (ecl_grid->nz - 1))) - return true; - else - return false; - } - - if (point_equal( &p , &cell->corner_list[6] )) { - if ((j == (ecl_grid->ny - 1)) && - (k == (ecl_grid->nz - 1))) - return true; - else - return false; - } - - if (point_equal( &p , &cell->corner_list[7] )) { - if ((i == (ecl_grid->nx - 1)) && - (j == (ecl_grid->ny - 1)) && - (k == (ecl_grid->nz - 1))) - return true; - else - return false; - } - - { - double sign = 1.0; - int plane_nr = 0; - double signed_volume = ecl_cell_get_signed_volume( cell ); - if (fabs(signed_volume) > min_volume) { - point_type * p0; - point_type * p1; - point_type * p2; - - if (signed_volume < 0) - sign = -1; - { - while (true) { - p0 = &cell->corner_list[ bounding_planes[plane_nr][0] ]; - p1 = &cell->corner_list[ bounding_planes[plane_nr][1] ]; - p2 = &cell->corner_list[ bounding_planes[plane_nr][2] ]; - - if (point_equal(p0, p1) || point_equal(p0,p2) || point_equal(p1,p2)) - return false; - - if (sign * point3_plane_distance(p0 , p1 , p2 , &p ) < 0) - return false; - - plane_nr++; - if (plane_nr == 6) - return true; - } - } - } else + if(!on_inner_faces && !tetrahedron_positive_volume(dia[i][0], dia[(i+1)%2][1], dia[i][1], extra[i][1])) return false; } } + + return contained; } -bool ecl_grid_cell_contains_xyz3( const ecl_grid_type * ecl_grid , int i , int j , int k, double x , double y , double z) { - int global_index = ecl_grid_get_global_index3( ecl_grid , i , j , k ); - return ecl_grid_cell_contains_xyz1( ecl_grid , global_index , x ,y , z); +/* + Observe the following quirks with this functions: + + - It is quite simple to create a cell where the center point is + actually *not* inside the cell - that might come as a surprise! + + - Cells with nonzero twist are completely discarded from the search, + if the point (x,y,z) "should" have been found on the inside of a + twisted cell the algorithm will incorrectly return false; a + warning will be printed on stderr if a cell is discarded due to + twist. + + - See the documentation of ecl_grid_on_cell_face for caveats regarding + containtment of points of cell faces. +*/ +bool ecl_grid_cell_contains_xyz3( const ecl_grid_type * ecl_grid , int i, int j , int k, double x , double y , double z) { + point_type p; + ecl_cell_type * cell = ecl_grid_get_cell( ecl_grid , ecl_grid_get_global_index3( ecl_grid , i, j , k )); + point_set( &p , x , y , z); + int method = (i + j + k) % 2; // Chooses the approperiate decomposition method for the cell + + if (GET_CELL_FLAG(cell , CELL_FLAG_TAINTED)) + return false; + + // Pruning + if (!ecl_grid_cube_contains(cell, &p)) + return false; + + // Checks if point is on one of the faces of the cell, and if so whether it + // "belongs" to this cell. + bool max_i = (i == ecl_grid->nx-1); + bool max_j = (j == ecl_grid->ny-1); + bool max_k = (k == ecl_grid->nz-1); + face_status_enum face_status = ecl_grid_on_cell_face(cell, method, &p, max_i, max_j, max_k); + + if(face_status != NOT_ON_FACE) { + // Since we might get false positives in the case when the cells + // projections to the xy-plane is concave, we still check whether + // the point is contained in the cell if it face_status is + // BELONGS_TO_CELL. + if(face_status == BELONGS_TO_OTHER) + return false; + } + + // Twisted cells + if (ecl_cell_get_twist(cell) > 0) { + fprintf(stderr, "** Warning: Point (%g,%g,%g) is in vicinity of twisted cell: (%d,%d,%d) - function:%s might be mistaken.\n", x,y,z,i,j,k, __func__); + return false; + } + + // We now check whether the point is strictly inside the cell + return concave_cell_contains(cell, method, &p); +} + + +bool ecl_grid_cell_contains_xyz1( const ecl_grid_type * ecl_grid , int global_index, double x , double y , double z) { + int i,j,k; + ecl_grid_get_ijk1( ecl_grid , global_index , &i , &j , &k); + return ecl_grid_cell_contains_xyz3( ecl_grid , i,j,k,x ,y , z); } /** @@ -4036,6 +4239,15 @@ int ecl_grid_get_global_index_from_xyz(ecl_grid_type * grid , double x , double return -1; } +bool ecl_grid_get_ijk_from_xyz(ecl_grid_type * grid , double x , double y , double z , int start_index, int *i, int *j, int *k ) { + int g = ecl_grid_get_global_index_from_xyz(grid, x, y, z, start_index); + if (g < 0) + return false; + + ecl_grid_get_ijk1( grid , g , i,j,k); + return true; +} + static bool ecl_grid_sublayer_contanins_xy__(const ecl_grid_type * grid , double x , double y , int k , int i1 , int i2 , int j1 , int j2, geo_polygon_type * polygon) { int i,j; @@ -4430,11 +4642,14 @@ void ecl_grid_get_ijk1A(const ecl_grid_type *ecl_grid , int active_index , int * /******************************************************************/ /* Functions to get the 'true' (i.e. UTM or whatever) position (x,y,z). + + The cell center is calculated as the plain average of the eight + corner positions, it is quite simple to construct cells where this + average position is on the outside of the cell - hence there is no + guarantee that the (x,y,z) position returned from this function + actually is on the inside of the cell. */ -/* - ijk are C-based zero offset. -*/ void ecl_grid_get_xyz1(const ecl_grid_type * grid , int global_index , double *xpos , double *ypos , double *zpos) { ecl_cell_type * cell = ecl_grid_get_cell( grid , global_index); @@ -4448,6 +4663,7 @@ void ecl_grid_get_xyz1(const ecl_grid_type * grid , int global_index , double *x + void ecl_grid_get_xyz3(const ecl_grid_type * grid , int i, int j , int k, double *xpos , double *ypos , double *zpos) { const int global_index = ecl_grid_get_global_index__(grid , i , j , k ); ecl_grid_get_xyz1( grid , global_index , xpos , ypos , zpos); @@ -4455,8 +4671,6 @@ void ecl_grid_get_xyz3(const ecl_grid_type * grid , int i, int j , int k, double - - /** This function will return (by reference) the x,y,z values of corner nr 'corner_nr' in cell 'global_index'. See the documentation of @@ -5044,7 +5258,31 @@ bool ecl_grid_cell_regular3( const ecl_grid_type * ecl_grid, int i,int j,int k) return ecl_grid_cell_regular1( ecl_grid , global_index ); } +/* + The function ecl_grid_get_cell_twist() is an attempt to measure how + twisted or deformed a cell is. For a 'normal' cell the corners + [0..3] will z value <= the corners [4..7]. This function will count + the number of times the z value from the [4..7] is lower than the + corresponding z value from the [0..3] layer. + The purpose of the function is to detect twisted cells before + embarking on cell contains calculation. The current + ecl_cell_contains_xyz( ) implementation will fail badly for twisted + cells. + + If the function return 4 you probably have an inverted z-axis! +*/ + +int ecl_grid_get_cell_twist1( const ecl_grid_type * ecl_grid, int global_index ) { + ecl_cell_type * cell = ecl_grid_get_cell( ecl_grid , global_index ); + return ecl_cell_get_twist( cell ); +} + + +int ecl_grid_get_cell_twist3(const ecl_grid_type * ecl_grid, int i, int j , int k) { + int global_index = ecl_grid_get_global_index3( ecl_grid , i , j , k); + return ecl_grid_get_cell_twist1( ecl_grid , global_index ); +} double ecl_grid_get_cell_volume1( const ecl_grid_type * ecl_grid, int global_index ) { @@ -5152,8 +5390,8 @@ static int ecl_grid_get_property_index__(const ecl_grid_type * ecl_grid , const static bool ecl_grid_get_property__(const ecl_grid_type * ecl_grid , const ecl_kw_type * ecl_kw , int i , int j , int k, void * value) { - ecl_type_enum ecl_type = ecl_kw_get_type( ecl_kw ); - if ((ecl_type == ECL_FLOAT_TYPE) || (ecl_type == ECL_INT_TYPE) || (ecl_type == ECL_DOUBLE_TYPE)) { + ecl_data_type data_type = ecl_kw_get_data_type( ecl_kw ); + if (ecl_type_is_numeric(data_type)) { int lookup_index = ecl_grid_get_property_index__( ecl_grid , ecl_kw , i , j , k ); if (lookup_index >= 0) { @@ -5163,15 +5401,15 @@ static bool ecl_grid_get_property__(const ecl_grid_type * ecl_grid , const ecl_k return false; } else { - util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_util_get_type_name( ecl_type ) , __func__); + util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_type_get_name( data_type ) , __func__); return false; } } double ecl_grid_get_double_property(const ecl_grid_type * ecl_grid , const ecl_kw_type * ecl_kw , int i , int j , int k) { - ecl_type_enum ecl_type = ecl_kw_get_type( ecl_kw ); - if (ecl_type == ECL_DOUBLE_TYPE) { + ecl_data_type data_type = ecl_kw_get_data_type( ecl_kw ); + if (ecl_type_is_double(data_type)) { double value; if (ecl_grid_get_property__( ecl_grid , ecl_kw , i , j , k , &value)) return value; @@ -5185,8 +5423,8 @@ double ecl_grid_get_double_property(const ecl_grid_type * ecl_grid , const ecl_k int ecl_grid_get_int_property(const ecl_grid_type * ecl_grid , const ecl_kw_type * ecl_kw , int i , int j , int k) { - ecl_type_enum ecl_type = ecl_kw_get_type( ecl_kw ); - if (ecl_type == ECL_INT_TYPE) { + ecl_data_type data_type = ecl_kw_get_data_type( ecl_kw ); + if (ecl_type_is_int(data_type)) { int value; if (ecl_grid_get_property__( ecl_grid , ecl_kw , i , j , k , &value)) @@ -5202,8 +5440,8 @@ int ecl_grid_get_int_property(const ecl_grid_type * ecl_grid , const ecl_kw_type float ecl_grid_get_float_property(const ecl_grid_type * ecl_grid , const ecl_kw_type * ecl_kw , int i , int j , int k) { - ecl_type_enum ecl_type = ecl_kw_get_type( ecl_kw ); - if (ecl_type == ECL_FLOAT_TYPE) { + ecl_data_type data_type = ecl_kw_get_data_type( ecl_kw ); + if (ecl_type_is_float(data_type)) { float value; if (ecl_grid_get_property__( ecl_grid , ecl_kw , i , j , k , &value)) @@ -5218,8 +5456,8 @@ float ecl_grid_get_float_property(const ecl_grid_type * ecl_grid , const ecl_kw_ } double ecl_grid_get_property(const ecl_grid_type * ecl_grid , const ecl_kw_type * ecl_kw , int i , int j , int k) { - ecl_type_enum ecl_type = ecl_kw_get_type( ecl_kw ); - if ((ecl_type == ECL_FLOAT_TYPE) || (ecl_type == ECL_INT_TYPE) || (ecl_type == ECL_DOUBLE_TYPE)) { + ecl_data_type data_type = ecl_kw_get_data_type( ecl_kw ); + if (ecl_type_is_numeric(data_type)) { int lookup_index = ecl_grid_get_property_index__( ecl_grid , ecl_kw , i , j , k ); if (lookup_index >= 0) @@ -5228,7 +5466,7 @@ double ecl_grid_get_property(const ecl_grid_type * ecl_grid , const ecl_kw_type return -1; /* Tried to lookup an inactive cell. */ } else { - util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_util_get_type_name( ecl_type ) , __func__); + util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_type_get_name( data_type ) , __func__); return -1; } } @@ -5252,8 +5490,8 @@ double ecl_grid_get_property(const ecl_grid_type * ecl_grid , const ecl_kw_type void ecl_grid_get_column_property(const ecl_grid_type * ecl_grid , const ecl_kw_type * ecl_kw , int i , int j, double_vector_type * column) { - ecl_type_enum ecl_type = ecl_kw_get_type( ecl_kw ); - if ((ecl_type == ECL_FLOAT_TYPE) || (ecl_type == ECL_INT_TYPE) || (ecl_type == ECL_DOUBLE_TYPE)) { + ecl_data_type data_type = ecl_kw_get_data_type(ecl_kw); + if (ecl_type_is_numeric(data_type)) { int kw_size = ecl_kw_get_size( ecl_kw ); bool use_global_index = false; @@ -5279,7 +5517,7 @@ void ecl_grid_get_column_property(const ecl_grid_type * ecl_grid , const ecl_kw_ } } } else - util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_util_get_type_name( ecl_type ) , __func__); + util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_type_get_name( data_type ) , __func__); } @@ -5316,7 +5554,7 @@ void ecl_grid_get_column_property(const ecl_grid_type * ecl_grid , const ecl_kw_ int ecl_grid_get_region_cells(const ecl_grid_type * ecl_grid , const ecl_kw_type * region_kw , int region_value , bool active_only, bool export_active_index , int_vector_type * index_list) { int cells_found = 0; if (ecl_kw_get_size( region_kw ) == ecl_grid->size) { - if (ecl_kw_get_type( region_kw ) == ECL_INT_TYPE) { + if (ecl_type_is_int(ecl_kw_get_data_type( region_kw ))) { const int * region_ptr = ecl_kw_iget_ptr( region_kw , 0); int_vector_reset( index_list ); @@ -5359,7 +5597,7 @@ void ecl_grid_grdecl_fprintf_kw( const ecl_grid_type * ecl_grid , const ecl_kw_t float float_default; int int_default; int bool_default; - ecl_type_enum ecl_type = ecl_kw_get_type( ecl_kw ); + ecl_type_enum ecl_type = ecl_type_get_type(ecl_kw_get_data_type( ecl_kw )); if (ecl_type == ECL_FLOAT_TYPE) { float_default = (float) double_default; @@ -5575,11 +5813,11 @@ static const float * ecl_grid_get_mapaxes( const ecl_grid_type * grid ) { } static ecl_kw_type * ecl_grid_alloc_mapaxes_kw( const float * mapaxes ) { - return ecl_kw_alloc_new( MAPAXES_KW , 6 , ECL_FLOAT_TYPE , mapaxes); + return ecl_kw_alloc_new( MAPAXES_KW , 6 , ECL_FLOAT , mapaxes); } static ecl_kw_type * ecl_grid_alloc_mapunits_kw( ert_ecl_unit_enum output_unit ) { - ecl_kw_type * mapunits_kw = ecl_kw_alloc( MAPUNITS_KW , 1 , ECL_CHAR_TYPE); + ecl_kw_type * mapunits_kw = ecl_kw_alloc( MAPUNITS_KW , 1 , ECL_CHAR); if (output_unit == ECL_FIELD_UNITS) ecl_kw_iset_string8( mapunits_kw , 0 , "FEET" ); @@ -5594,7 +5832,7 @@ static ecl_kw_type * ecl_grid_alloc_mapunits_kw( ert_ecl_unit_enum output_unit ) } static ecl_kw_type * ecl_grid_alloc_gridunits_kw( ert_ecl_unit_enum output_unit ) { - ecl_kw_type * gridunits_kw = ecl_kw_alloc( GRIDUNIT_KW , 2 , ECL_CHAR_TYPE); + ecl_kw_type * gridunits_kw = ecl_kw_alloc( GRIDUNIT_KW , 2 , ECL_CHAR); if (output_unit == ECL_FIELD_UNITS) ecl_kw_iset_string8( gridunits_kw , 0 , "FEET" ); @@ -5666,14 +5904,14 @@ static void ecl_grid_fwrite_main_GRID_headers( const ecl_grid_type * ecl_grid , static void ecl_grid_fwrite_GRID__( const ecl_grid_type * grid , int coords_size , fortio_type * fortio, ert_ecl_unit_enum output_unit) { if (grid->parent_grid != NULL) { - ecl_kw_type * lgr_kw = ecl_kw_alloc(LGR_KW , 1 , ECL_CHAR_TYPE ); + ecl_kw_type * lgr_kw = ecl_kw_alloc(LGR_KW , 1 , ECL_CHAR); ecl_kw_iset_string8( lgr_kw , 0 , grid->name ); ecl_kw_fwrite( lgr_kw , fortio ); ecl_kw_free( lgr_kw ); } { - ecl_kw_type * dimens_kw = ecl_kw_alloc(DIMENS_KW , 3 , ECL_INT_TYPE ); + ecl_kw_type * dimens_kw = ecl_kw_alloc(DIMENS_KW , 3 , ECL_INT); ecl_kw_iset_int( dimens_kw , 0 , grid->nx ); ecl_kw_iset_int( dimens_kw , 1 , grid->ny ); if (grid->dualp_flag == FILEHEAD_SINGLE_POROSITY) @@ -5689,15 +5927,15 @@ static void ecl_grid_fwrite_GRID__( const ecl_grid_type * grid , int coords_size ecl_grid_fwrite_main_GRID_headers( grid , fortio , output_unit); { - ecl_kw_type * radial_kw = ecl_kw_alloc( RADIAL_KW , 1 , ECL_CHAR_TYPE); + ecl_kw_type * radial_kw = ecl_kw_alloc( RADIAL_KW , 1 , ECL_CHAR); ecl_kw_iset_string8( radial_kw , 0 , "FALSE" ); ecl_kw_fwrite( radial_kw , fortio ); ecl_kw_free( radial_kw ); } { - ecl_kw_type * coords_kw = ecl_kw_alloc( COORDS_KW , coords_size , ECL_INT_TYPE ); - ecl_kw_type * corners_kw = ecl_kw_alloc( CORNERS_KW , 24 , ECL_FLOAT_TYPE ); + ecl_kw_type * coords_kw = ecl_kw_alloc( COORDS_KW , coords_size , ECL_INT); + ecl_kw_type * corners_kw = ecl_kw_alloc( CORNERS_KW , 24 , ECL_FLOAT); int i,j,k; for (k=0; k < grid->nz; k++) { for (j=0; j < grid->ny; j++) { @@ -5781,7 +6019,7 @@ static void ecl_grid_fwrite_main_EGRID_header( const ecl_grid_type * grid , fort const float * mapaxes = ecl_grid_get_mapaxes( grid ); { - ecl_kw_type * filehead_kw = ecl_kw_alloc( FILEHEAD_KW , 100 , ECL_INT_TYPE ); + ecl_kw_type * filehead_kw = ecl_kw_alloc( FILEHEAD_KW , 100 , ECL_INT); ecl_kw_scalar_set_int( filehead_kw , 0 ); ecl_kw_iset_int( filehead_kw , FILEHEAD_VERSION_INDEX , EGRID_VERSION ); @@ -5970,21 +6208,19 @@ void ecl_grid_init_coord_data_double( const ecl_grid_type * grid , double * coor float * ecl_grid_alloc_coord_data( const ecl_grid_type * grid ) { - float * coord = util_calloc( (grid->nx + 1) * (grid->ny + 1) * 6 , sizeof * coord ); + float * coord = util_calloc( ecl_grid_get_coord_size(grid) , sizeof * coord ); ecl_grid_init_coord_data( grid , coord ); return coord; } void ecl_grid_assert_coord_kw( ecl_grid_type * grid ) { if (grid->coord_kw == NULL) { - grid->coord_kw = ecl_kw_alloc( COORD_KW , (grid->nx + 1) * (grid->ny + 1) * 6 , ECL_FLOAT_TYPE ); + grid->coord_kw = ecl_kw_alloc( COORD_KW , ecl_grid_get_coord_size( grid ) , ECL_FLOAT); ecl_grid_init_coord_data( grid , ecl_kw_get_void_ptr( grid->coord_kw )); } } -int ecl_grid_get_coord_size( const ecl_grid_type * ecl_grid) { - return (ecl_grid->nx + 1) * (ecl_grid->ny + 1) * 6; -} + @@ -6050,14 +6286,19 @@ float * ecl_grid_alloc_zcorn_data( const ecl_grid_type * grid ) { ecl_kw_type * ecl_grid_alloc_zcorn_kw( const ecl_grid_type * grid ) { - ecl_kw_type * zcorn_kw = ecl_kw_alloc( ZCORN_KW , 8 * grid->size , ECL_FLOAT_TYPE ); + ecl_kw_type * zcorn_kw = ecl_kw_alloc( ZCORN_KW , 8 * grid->size , ECL_FLOAT); ecl_grid_init_zcorn_data( grid , ecl_kw_get_void_ptr( zcorn_kw )); return zcorn_kw; } +int ecl_grid_get_coord_size( const ecl_grid_type * grid) { + return ECL_GRID_COORD_SIZE( grid->nx , grid->ny ); +} + + int ecl_grid_get_zcorn_size( const ecl_grid_type * grid ) { - return 8 * grid->size; + return ECL_GRID_ZCORN_SIZE( grid->nx , grid->ny, grid->nz ); } /*****************************************************************/ @@ -6109,7 +6350,7 @@ int * ecl_grid_alloc_actnum_data( const ecl_grid_type * grid ) { ecl_kw_type * ecl_grid_alloc_actnum_kw( const ecl_grid_type * grid ) { - ecl_kw_type * actnum_kw = ecl_kw_alloc( ACTNUM_KW , grid->size , ECL_INT_TYPE ); + ecl_kw_type * actnum_kw = ecl_kw_alloc( ACTNUM_KW , grid->size , ECL_INT); ecl_grid_init_actnum_data( grid , ecl_kw_get_void_ptr( actnum_kw )); return actnum_kw; } @@ -6163,7 +6404,7 @@ int * ecl_grid_alloc_hostnum_data( const ecl_grid_type * grid ) { ecl_kw_type * ecl_grid_alloc_hostnum_kw( const ecl_grid_type * grid ) { - ecl_kw_type * hostnum_kw = ecl_kw_alloc( HOSTNUM_KW , grid->size , ECL_INT_TYPE ); + ecl_kw_type * hostnum_kw = ecl_kw_alloc( HOSTNUM_KW , grid->size , ECL_INT); ecl_grid_init_hostnum_data( grid , ecl_kw_get_void_ptr( hostnum_kw )); return hostnum_kw; } @@ -6186,7 +6427,7 @@ int * ecl_grid_alloc_corsnum_data( const ecl_grid_type * grid ) { ecl_kw_type * ecl_grid_alloc_corsnum_kw( const ecl_grid_type * grid ) { - ecl_kw_type * corsnum_kw = ecl_kw_alloc( CORSNUM_KW , grid->size , ECL_INT_TYPE ); + ecl_kw_type * corsnum_kw = ecl_kw_alloc( CORSNUM_KW , grid->size , ECL_INT); ecl_grid_init_corsnum_data( grid , ecl_kw_get_void_ptr( corsnum_kw )); return corsnum_kw; } @@ -6195,7 +6436,7 @@ ecl_kw_type * ecl_grid_alloc_corsnum_kw( const ecl_grid_type * grid ) { ecl_kw_type * ecl_grid_alloc_gridhead_kw( int nx, int ny , int nz , int grid_nr) { - ecl_kw_type * gridhead_kw = ecl_kw_alloc( GRIDHEAD_KW , GRIDHEAD_SIZE , ECL_INT_TYPE ); + ecl_kw_type * gridhead_kw = ecl_kw_alloc( GRIDHEAD_KW , GRIDHEAD_SIZE , ECL_INT); ecl_kw_scalar_set_int( gridhead_kw , 0 ); ecl_kw_iset_int( gridhead_kw , GRIDHEAD_TYPE_INDEX , GRIDHEAD_GRIDTYPE_CORNERPOINT ); ecl_kw_iset_int( gridhead_kw , GRIDHEAD_NX_INDEX , nx); @@ -6244,9 +6485,9 @@ static void ecl_grid_fwrite_self_nnc( const ecl_grid_type * grid , fortio_type } { int num_nnc = int_vector_size( g1 ); - ecl_kw_type * nnc1_kw = ecl_kw_alloc_new_shared( NNC1_KW , num_nnc , ECL_INT_TYPE , int_vector_get_ptr( g1 )); - ecl_kw_type * nnc2_kw = ecl_kw_alloc_new_shared( NNC2_KW , num_nnc , ECL_INT_TYPE , int_vector_get_ptr( g2 )); - ecl_kw_type * nnchead_kw = ecl_kw_alloc( NNCHEAD_KW , NNCHEAD_SIZE , ECL_INT_TYPE ); + ecl_kw_type * nnc1_kw = ecl_kw_alloc_new_shared( NNC1_KW , num_nnc , ECL_INT , int_vector_get_ptr( g1 )); + ecl_kw_type * nnc2_kw = ecl_kw_alloc_new_shared( NNC2_KW , num_nnc , ECL_INT , int_vector_get_ptr( g2 )); + ecl_kw_type * nnchead_kw = ecl_kw_alloc( NNCHEAD_KW , NNCHEAD_SIZE , ECL_INT); ecl_kw_scalar_set_int( nnchead_kw , 0 ); ecl_kw_iset_int( nnchead_kw , NNCHEAD_NUMNNC_INDEX , num_nnc ); @@ -6276,14 +6517,14 @@ static void ecl_grid_fwrite_EGRID__( ecl_grid_type * grid , fortio_type * fortio ecl_grid_fwrite_main_EGRID_header( grid , fortio , output_unit ); } else { { - ecl_kw_type * lgr_kw = ecl_kw_alloc(LGR_KW , 1 , ECL_CHAR_TYPE ); + ecl_kw_type * lgr_kw = ecl_kw_alloc(LGR_KW , 1 , ECL_CHAR); ecl_kw_iset_string8( lgr_kw , 0 , grid->name ); ecl_kw_fwrite( lgr_kw , fortio ); ecl_kw_free( lgr_kw ); } { - ecl_kw_type * lgr_parent_kw = ecl_kw_alloc(LGR_PARENT_KW , 1 , ECL_CHAR_TYPE ); + ecl_kw_type * lgr_parent_kw = ecl_kw_alloc(LGR_PARENT_KW , 1 , ECL_CHAR); if (grid->parent_name != NULL) ecl_kw_iset_string8( lgr_parent_kw , 0 , grid->parent_name ); else @@ -6329,14 +6570,14 @@ static void ecl_grid_fwrite_EGRID__( ecl_grid_type * grid , fortio_type * fortio } { - ecl_kw_type * endgrid_kw = ecl_kw_alloc( ENDGRID_KW , 0 , ECL_INT_TYPE ); + ecl_kw_type * endgrid_kw = ecl_kw_alloc( ENDGRID_KW , 0 , ECL_INT); ecl_kw_fwrite( endgrid_kw , fortio ); ecl_kw_free( endgrid_kw ); } } if (is_lgr) { - ecl_kw_type * endlgr_kw = ecl_kw_alloc( ENDLGR_KW , 0 , ECL_INT_TYPE ); + ecl_kw_type * endlgr_kw = ecl_kw_alloc( ENDLGR_KW , 0 , ECL_INT); ecl_kw_fwrite( endlgr_kw , fortio ); ecl_kw_free( endlgr_kw ); } @@ -6380,7 +6621,7 @@ void ecl_grid_fwrite_EGRID( ecl_grid_type * grid , const char * filename, bool o void ecl_grid_fwrite_depth( const ecl_grid_type * grid , fortio_type * init_file , ert_ecl_unit_enum output_unit) { - ecl_kw_type * depth_kw = ecl_kw_alloc("DEPTH" , ecl_grid_get_nactive(grid) , ECL_FLOAT_TYPE ); + ecl_kw_type * depth_kw = ecl_kw_alloc("DEPTH" , ecl_grid_get_nactive(grid) , ECL_FLOAT); { float * depth_ptr = ecl_kw_get_ptr(depth_kw); for (int i = 0; i < ecl_grid_get_nactive( grid ); i++) @@ -6393,9 +6634,9 @@ void ecl_grid_fwrite_depth( const ecl_grid_type * grid , fortio_type * init_file void ecl_grid_fwrite_dims( const ecl_grid_type * grid , fortio_type * init_file, ert_ecl_unit_enum output_unit) { - ecl_kw_type * dx = ecl_kw_alloc("DX" , ecl_grid_get_nactive(grid) , ECL_FLOAT_TYPE ); - ecl_kw_type * dy = ecl_kw_alloc("DY" , ecl_grid_get_nactive(grid) , ECL_FLOAT_TYPE ); - ecl_kw_type * dz = ecl_kw_alloc("DZ" , ecl_grid_get_nactive(grid) , ECL_FLOAT_TYPE ); + ecl_kw_type * dx = ecl_kw_alloc("DX" , ecl_grid_get_nactive(grid) , ECL_FLOAT); + ecl_kw_type * dy = ecl_kw_alloc("DY" , ecl_grid_get_nactive(grid) , ECL_FLOAT); + ecl_kw_type * dz = ecl_kw_alloc("DZ" , ecl_grid_get_nactive(grid) , ECL_FLOAT); { { float * dx_ptr = ecl_kw_get_ptr(dx); @@ -6548,7 +6789,7 @@ int ecl_grid_get_num_nnc( const ecl_grid_type * grid ) { static ecl_kw_type * ecl_grid_alloc_volume_kw_active( const ecl_grid_type * grid) { - ecl_kw_type * volume_kw = ecl_kw_alloc("VOLUME" , ecl_grid_get_active_size(grid) , ECL_DOUBLE_TYPE); + ecl_kw_type * volume_kw = ecl_kw_alloc("VOLUME" , ecl_grid_get_active_size(grid) , ECL_DOUBLE); { double * volume_data = ecl_kw_get_ptr( volume_kw ); int active_index; @@ -6562,7 +6803,7 @@ static ecl_kw_type * ecl_grid_alloc_volume_kw_active( const ecl_grid_type * grid static ecl_kw_type * ecl_grid_alloc_volume_kw_global( const ecl_grid_type * grid) { - ecl_kw_type * volume_kw = ecl_kw_alloc("VOLUME" , ecl_grid_get_global_size(grid) , ECL_DOUBLE_TYPE); + ecl_kw_type * volume_kw = ecl_kw_alloc("VOLUME" , ecl_grid_get_global_size(grid) , ECL_DOUBLE); { double * volume_data = ecl_kw_get_ptr( volume_kw ); int global_index; diff --git a/ThirdParty/Ert/libecl/src/ecl_init_file.c b/ThirdParty/Ert/libecl/src/ecl_init_file.c index 6f50bbaaa4..eb20dc8674 100644 --- a/ThirdParty/Ert/libecl/src/ecl_init_file.c +++ b/ThirdParty/Ert/libecl/src/ecl_init_file.c @@ -38,9 +38,10 @@ #include #include #include +#include static ecl_kw_type * ecl_init_file_alloc_INTEHEAD( const ecl_grid_type * ecl_grid , ert_ecl_unit_enum unit_system, int phases, time_t start_date , int simulator) { - ecl_kw_type * intehead_kw = ecl_kw_alloc( INTEHEAD_KW , INTEHEAD_INIT_SIZE , ECL_INT_TYPE ); + ecl_kw_type * intehead_kw = ecl_kw_alloc( INTEHEAD_KW , INTEHEAD_INIT_SIZE , ECL_INT ); ecl_kw_scalar_set_int( intehead_kw , 0 ); ecl_kw_iset_int( intehead_kw , INTEHEAD_UNIT_INDEX , unit_system ); @@ -89,7 +90,7 @@ static ecl_kw_type * ecl_init_file_alloc_LOGIHEAD( int simulator ) { bool scale_gas_PC_at_max_sat = false; - ecl_kw_type * logihead_kw = ecl_kw_alloc( LOGIHEAD_KW , LOGIHEAD_INIT_SIZE , ECL_BOOL_TYPE ); + ecl_kw_type * logihead_kw = ecl_kw_alloc( LOGIHEAD_KW , LOGIHEAD_INIT_SIZE , ECL_BOOL ); ecl_kw_scalar_set_bool( logihead_kw , false ); @@ -120,7 +121,7 @@ static ecl_kw_type * ecl_init_file_alloc_LOGIHEAD( int simulator ) { static ecl_kw_type * ecl_init_file_alloc_DOUBHEAD( ) { - ecl_kw_type * doubhead_kw = ecl_kw_alloc( DOUBHEAD_KW , DOUBHEAD_INIT_SIZE , ECL_DOUBLE_TYPE ); + ecl_kw_type * doubhead_kw = ecl_kw_alloc( DOUBHEAD_KW , DOUBHEAD_INIT_SIZE , ECL_DOUBLE ); ecl_kw_scalar_set_double( doubhead_kw , 0); @@ -147,7 +148,7 @@ static ecl_kw_type * ecl_init_file_alloc_DOUBHEAD( ) { static void ecl_init_file_fwrite_poro( fortio_type * fortio , const ecl_grid_type * ecl_grid , const ecl_kw_type * poro ) { { - ecl_kw_type * porv = ecl_kw_alloc( PORV_KW , ecl_grid_get_global_size( ecl_grid ) , ECL_FLOAT_TYPE); + ecl_kw_type * porv = ecl_kw_alloc( PORV_KW , ecl_grid_get_global_size( ecl_grid ) , ECL_FLOAT); int global_index; bool global_poro = (ecl_kw_get_size( poro ) == ecl_grid_get_global_size( ecl_grid )) ? true : false; for ( global_index = 0; global_index < ecl_grid_get_global_size( ecl_grid ); global_index++) { diff --git a/ThirdParty/Ert/libecl/src/ecl_kw.c b/ThirdParty/Ert/libecl/src/ecl_kw.c index a23c841a65..d7ebf1ef87 100644 --- a/ThirdParty/Ert/libecl/src/ecl_kw.c +++ b/ThirdParty/Ert/libecl/src/ecl_kw.c @@ -27,9 +27,9 @@ #include #include -#include #include #include +#include #define ECL_KW_TYPE_ID 6111098 @@ -41,8 +41,7 @@ struct ecl_kw_struct { UTIL_TYPE_ID_DECLARATION; int size; - int sizeof_ctype; - ecl_type_enum ecl_type; + ecl_data_type data_type; char * header8; /* Header which is right padded with ' ' to become exactly 8 characters long. Should only be used internally.*/ char * header; /* Header which is trimmed to no-space. */ char * data; /* The actual data vector. */ @@ -159,9 +158,11 @@ UTIL_IS_INSTANCE_FUNCTION(ecl_kw , ECL_KW_TYPE_ID ) #define BOOL_FALSE_CHAR 'F' +ecl_type_enum ecl_kw_get_type(const ecl_kw_type *); +void ecl_kw_set_data_type(ecl_kw_type * ecl_kw, ecl_data_type data_type); -static const char * get_read_fmt( ecl_type_enum ecl_type ) { - switch(ecl_type) { +static const char * get_read_fmt(const ecl_data_type data_type ) { + switch(ecl_type_get_type(data_type)) { case(ECL_CHAR_TYPE): return READ_FMT_CHAR; break; @@ -184,14 +185,14 @@ static const char * get_read_fmt( ecl_type_enum ecl_type ) { return READ_FMT_MESS; break; default: - util_abort("%s: invalid ecl_type:%d \n",__func__ , ecl_type); + util_abort("%s: invalid ecl_type:%d \n",__func__ , ecl_type_get_type(data_type)); return NULL; } } -const char * ecl_kw_get_write_fmt( ecl_type_enum ecl_type ) { - switch(ecl_type) { +static const char * ecl_kw_get_write_fmt(const ecl_data_type data_type) { + switch(ecl_type_get_type(data_type)) { case(ECL_CHAR_TYPE): return WRITE_FMT_CHAR; break; @@ -214,27 +215,27 @@ const char * ecl_kw_get_write_fmt( ecl_type_enum ecl_type ) { return WRITE_FMT_MESS; break; default: - util_abort("%s: invalid ecl_type:%d \n",__func__ , ecl_type); + util_abort("%s: invalid ecl_type:%d \n",__func__ , ecl_type_get_type(data_type)); return NULL; } } -static int get_blocksize( ecl_type_enum ecl_type ) { - if (ecl_type == ECL_CHAR_TYPE) +static int get_blocksize( ecl_data_type data_type ) { + if (ecl_type_is_char(data_type)) return BLOCKSIZE_CHAR; - if (ecl_type == ECL_MESS_TYPE) + if (ecl_type_is_mess(data_type)) return BLOCKSIZE_CHAR; - if (ecl_type == ECL_C010_TYPE) + if (ecl_type_is_C010(data_type)) return BLOCKSIZE_C010; - return BLOCKSIZE_NUMERIC; + return BLOCKSIZE_NUMERIC; } -static int get_columns( ecl_type_enum ecl_type ) { - switch(ecl_type) { +static int get_columns(const ecl_data_type data_type) { + switch(ecl_type_get_type(data_type)) { case(ECL_CHAR_TYPE): return COLUMNS_CHAR; break; @@ -254,7 +255,7 @@ static int get_columns( ecl_type_enum ecl_type ) { return COLUMNS_MESSAGE; break; default: - util_abort("%s: invalid ecl_type:%d \n",__func__ , ecl_type); + util_abort("%s: invalid ecl_type:%d \n",__func__ , ecl_type_get_type(data_type)); return -1; } } @@ -271,8 +272,8 @@ static void ecl_kw_assert_index(const ecl_kw_type *ecl_kw , int index, const cha static void ecl_kw_endian_convert_data(ecl_kw_type *ecl_kw) { - if (ecl_kw->ecl_type != ECL_CHAR_TYPE && ecl_kw->ecl_type != ECL_MESS_TYPE) - util_endian_flip_vector(ecl_kw->data , ecl_kw->sizeof_ctype , ecl_kw->size); + if (ecl_type_is_numeric(ecl_kw->data_type) || ecl_type_is_bool(ecl_kw->data_type)) + util_endian_flip_vector(ecl_kw->data , ecl_kw_get_sizeof_ctype(ecl_kw) , ecl_kw->size); } @@ -294,35 +295,35 @@ bool ecl_kw_name_equal( const ecl_kw_type * ecl_kw , const char * name) { void ecl_kw_get_memcpy_data(const ecl_kw_type *ecl_kw , void *target) { - memcpy(target , ecl_kw->data , ecl_kw->size * ecl_kw->sizeof_ctype); + memcpy(target , ecl_kw->data , ecl_kw->size * ecl_kw_get_sizeof_ctype(ecl_kw)); } void ecl_kw_get_memcpy_int_data(const ecl_kw_type *ecl_kw , int * target) { - if (ecl_kw->ecl_type == ECL_INT_TYPE) + if (ecl_type_is_int(ecl_kw->data_type)) ecl_kw_get_memcpy_data( ecl_kw , target ); } void ecl_kw_get_memcpy_float_data(const ecl_kw_type *ecl_kw , float *target) { - if (ecl_kw->ecl_type == ECL_FLOAT_TYPE) + if (ecl_type_is_float(ecl_kw->data_type)) ecl_kw_get_memcpy_data( ecl_kw , target ); } void ecl_kw_get_memcpy_double_data(const ecl_kw_type *ecl_kw , double *target) { -if (ecl_kw->ecl_type == ECL_DOUBLE_TYPE) +if (ecl_type_is_double(ecl_kw->data_type)) ecl_kw_get_memcpy_data( ecl_kw , target ); } /** Allocates a untyped buffer with exactly the same content as the ecl_kw instances data. */ void * ecl_kw_alloc_data_copy(const ecl_kw_type * ecl_kw) { - void * buffer = util_alloc_copy( ecl_kw->data , ecl_kw->size * ecl_kw->sizeof_ctype ); + void * buffer = util_alloc_copy( ecl_kw->data , ecl_kw->size * ecl_kw_get_sizeof_ctype(ecl_kw) ); return buffer; } void ecl_kw_set_memcpy_data(ecl_kw_type *ecl_kw , const void *src) { if (src != NULL) - memcpy(ecl_kw->data , src , ecl_kw->size * ecl_kw->sizeof_ctype); + memcpy(ecl_kw->data , src , ecl_kw->size * ecl_kw_get_sizeof_ctype(ecl_kw)); } @@ -358,14 +359,8 @@ bool ecl_kw_ichar_eq(const ecl_kw_type *ecl_kw , int i , const char *value) { bool ecl_kw_size_and_type_equal( const ecl_kw_type *ecl_kw1 , const ecl_kw_type * ecl_kw2 ) { - bool equal = true; - - if (ecl_kw1->size != ecl_kw2->size) - equal = false; - else if (ecl_kw1->ecl_type != ecl_kw2->ecl_type) - equal = false; - - return equal; + return (ecl_kw1->size == ecl_kw2->size && + ecl_type_is_equal(ecl_kw1->data_type, ecl_kw2->data_type)); } @@ -381,7 +376,7 @@ bool ecl_kw_header_eq(const ecl_kw_type *ecl_kw1 , const ecl_kw_type * ecl_kw2) } static bool ecl_kw_data_equal__( const ecl_kw_type * ecl_kw , const void * data , int cmp_elements) { - int cmp = memcmp( ecl_kw->data , data , cmp_elements * ecl_kw->sizeof_ctype); + int cmp = memcmp( ecl_kw->data , data , cmp_elements * ecl_kw_get_sizeof_ctype(ecl_kw)); if (cmp == 0) return true; else @@ -455,22 +450,15 @@ ECL_KW_NUMERIC_CMP( double ) */ bool ecl_kw_numeric_equal(const ecl_kw_type *ecl_kw1, const ecl_kw_type *ecl_kw2 , double abs_diff , double rel_diff) { - bool equal = true; - if ( ecl_kw1->ecl_type != ecl_kw2->ecl_type) - equal = false; + if(!ecl_kw_size_and_type_equal(ecl_kw1, ecl_kw2)) + return false; - if ( ecl_kw1->size != ecl_kw2->size) - equal = false; - - if (equal) { - if (ecl_kw1->ecl_type == ECL_FLOAT_TYPE) - equal = ecl_kw_numeric_equal_float( ecl_kw1 , ecl_kw2 , abs_diff , rel_diff ); - else if (ecl_kw1->ecl_type == ECL_DOUBLE_TYPE) - equal = ecl_kw_numeric_equal_double( ecl_kw1 , ecl_kw2 , abs_diff , rel_diff ); - else - equal = ecl_kw_data_equal( ecl_kw1 , ecl_kw2->data ); - } - return equal; + if (ecl_type_is_float(ecl_kw1->data_type)) + return ecl_kw_numeric_equal_float( ecl_kw1 , ecl_kw2 , abs_diff , rel_diff ); + else if (ecl_type_is_double(ecl_kw1->data_type)) + return ecl_kw_numeric_equal_double( ecl_kw1 , ecl_kw2 , abs_diff , rel_diff ); + else + return ecl_kw_data_equal( ecl_kw1 , ecl_kw2->data ); } @@ -498,9 +486,8 @@ static void ecl_kw_set_shared_ref(ecl_kw_type * ecl_kw , void *data_ptr) { -static void ecl_kw_initialize(ecl_kw_type * ecl_kw , const char *header , int size , ecl_type_enum ecl_type) { - ecl_kw->ecl_type = ecl_type; - ecl_kw->sizeof_ctype = ecl_util_get_sizeof_ctype(ecl_kw->ecl_type); +static void ecl_kw_initialize(ecl_kw_type * ecl_kw , const char *header , int size , ecl_data_type data_type) { + ecl_kw_set_data_type(ecl_kw, data_type); if (strlen(header) > ECL_STRING8_LENGTH) util_abort("%s: Fatal error: ecl_header_name:%s is longer than eight characters - aborting \n",__func__,header); @@ -509,11 +496,11 @@ static void ecl_kw_initialize(ecl_kw_type * ecl_kw , const char *header , int s } static size_t ecl_kw_fortio_data_size( const ecl_kw_type * ecl_kw) { - const int blocksize = get_blocksize( ecl_kw->ecl_type ); + const int blocksize = get_blocksize( ecl_kw->data_type ); const int num_blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1); return num_blocks * (4 + 4) + // Fortran fluff for each block - ecl_kw->size * ecl_util_get_sizeof_ctype_fortio( ecl_kw->ecl_type ); // Actual data + ecl_kw->size * ecl_type_get_sizeof_ctype_fortio( ecl_kw->data_type ); // Actual data } @@ -534,10 +521,10 @@ size_t ecl_kw_fortio_size( const ecl_kw_type * ecl_kw ) { /** The data is copied from the input argument to the ecl_kw; data can be NULL. */ -ecl_kw_type * ecl_kw_alloc_new(const char * header , int size, ecl_type_enum ecl_type , const void * data) { +ecl_kw_type * ecl_kw_alloc_new(const char * header , int size, ecl_data_type data_type , const void * data) { ecl_kw_type *ecl_kw; ecl_kw = ecl_kw_alloc_empty(); - ecl_kw_initialize(ecl_kw , header , size , ecl_type); + ecl_kw_initialize(ecl_kw , header , size , data_type); if (data != NULL) { ecl_kw_alloc_data(ecl_kw); ecl_kw_set_memcpy_data(ecl_kw , data); @@ -547,14 +534,14 @@ ecl_kw_type * ecl_kw_alloc_new(const char * header , int size, ecl_type_enum ec -ecl_kw_type * ecl_kw_alloc( const char * header , int size , ecl_type_enum ecl_type ) { - if (ecl_type == ECL_C010_TYPE) +ecl_kw_type * ecl_kw_alloc( const char * header , int size , ecl_data_type data_type ) { + if (ecl_type_is_C010(data_type)) return NULL; { ecl_kw_type *ecl_kw; ecl_kw = ecl_kw_alloc_empty(); - ecl_kw_initialize(ecl_kw , header , size , ecl_type); + ecl_kw_initialize(ecl_kw , header , size , data_type); ecl_kw_alloc_data(ecl_kw); return ecl_kw; @@ -563,10 +550,10 @@ ecl_kw_type * ecl_kw_alloc( const char * header , int size , ecl_type_enum ecl_t -ecl_kw_type * ecl_kw_alloc_new_shared(const char * header , int size, ecl_type_enum ecl_type , void * data) { +ecl_kw_type * ecl_kw_alloc_new_shared(const char * header , int size, ecl_data_type data_type , void * data) { ecl_kw_type *ecl_kw; ecl_kw = ecl_kw_alloc_empty(); - ecl_kw_initialize(ecl_kw , header , size , ecl_type); + ecl_kw_initialize(ecl_kw , header , size , data_type); ecl_kw_set_shared_ref(ecl_kw , data); return ecl_kw; } @@ -582,7 +569,6 @@ ecl_kw_type * ecl_kw_alloc_empty() { ecl_kw->data = NULL; ecl_kw->shared_data = false; ecl_kw->size = 0; - ecl_kw->sizeof_ctype = 0; UTIL_TYPE_ID_INIT(ecl_kw , ECL_KW_TYPE_ID); @@ -604,19 +590,17 @@ void ecl_kw_free__(void *void_ecl_kw) { void ecl_kw_memcpy_data( ecl_kw_type * target , const ecl_kw_type * src) { - if (!ecl_kw_assert_binary( target , src )) + if (!ecl_kw_size_and_type_equal( target , src )) util_abort("%s: type/size mismatch \n",__func__); - memcpy(target->data , src->data , target->size * target->sizeof_ctype); + memcpy(target->data , src->data , target->size * ecl_kw_get_sizeof_ctype(target)); } void ecl_kw_memcpy(ecl_kw_type *target, const ecl_kw_type *src) { target->size = src->size; - target->sizeof_ctype = src->sizeof_ctype; - target->ecl_type = src->ecl_type; - + ecl_kw_set_data_type(target, src->data_type); ecl_kw_set_header_name( target , src->header ); ecl_kw_alloc_data(target); @@ -664,7 +648,7 @@ ecl_kw_type * ecl_kw_alloc_slice_copy( const ecl_kw_type * src, int index1, int } if (new_size > 0) { new_kw = ecl_kw_alloc_empty(); - ecl_kw_initialize(new_kw , src->header , new_size , src->ecl_type); + ecl_kw_initialize(new_kw , src->header , new_size , src->data_type); ecl_kw_alloc_data(new_kw); /* 2: Copy over the elements. */ @@ -673,7 +657,7 @@ ecl_kw_type * ecl_kw_alloc_slice_copy( const ecl_kw_type * src, int index1, int int target_index = 0; const char * src_ptr = src->data; char * new_ptr = new_kw->data; - int sizeof_ctype = new_kw->sizeof_ctype; + int sizeof_ctype = ecl_kw_get_sizeof_ctype(new_kw); while ( src_index < index2 ) { memcpy( &new_ptr[ target_index * sizeof_ctype ] , &src_ptr[ src_index * sizeof_ctype ] , sizeof_ctype ); @@ -694,8 +678,8 @@ void ecl_kw_resize( ecl_kw_type * ecl_kw, int new_size) { util_abort("%s: trying to allocate data for ecl_kw object which has been declared with shared storage - aborting \n",__func__); if (new_size != ecl_kw->size) { - size_t old_byte_size = ecl_kw->size * ecl_kw->sizeof_ctype; - size_t new_byte_size = new_size * ecl_kw->sizeof_ctype; + size_t old_byte_size = ecl_kw->size * ecl_kw_get_sizeof_ctype(ecl_kw); + size_t new_byte_size = new_size * ecl_kw_get_sizeof_ctype(ecl_kw); ecl_kw->data = util_realloc(ecl_kw->data , new_byte_size ); if (new_byte_size > old_byte_size) { @@ -727,7 +711,7 @@ ecl_kw_type * ecl_kw_alloc_sub_copy( const ecl_kw_type * src, const char * new_k { void * src_data = ecl_kw_iget_ptr( src , offset ); - return ecl_kw_alloc_new( new_kw , count , src->ecl_type , src_data ); + return ecl_kw_alloc_new( new_kw , count , src->data_type , src_data ); } } @@ -739,18 +723,18 @@ const void * ecl_kw_copyc__(const void * void_kw) { static void * ecl_kw_iget_ptr_static(const ecl_kw_type *ecl_kw , int i) { ecl_kw_assert_index(ecl_kw , i , __func__); - return &ecl_kw->data[i * ecl_kw->sizeof_ctype]; + return &ecl_kw->data[i * ecl_kw_get_sizeof_ctype(ecl_kw)]; } static void ecl_kw_iget_static(const ecl_kw_type *ecl_kw , int i , void *iptr) { - memcpy(iptr , ecl_kw_iget_ptr_static(ecl_kw , i) , ecl_kw->sizeof_ctype); + memcpy(iptr , ecl_kw_iget_ptr_static(ecl_kw , i) , ecl_kw_get_sizeof_ctype(ecl_kw)); } static void ecl_kw_iset_static(ecl_kw_type *ecl_kw , int i , const void *iptr) { ecl_kw_assert_index(ecl_kw , i , __func__); - memcpy(&ecl_kw->data[i * ecl_kw->sizeof_ctype] , iptr, ecl_kw->sizeof_ctype); + memcpy(&ecl_kw->data[i * ecl_kw_get_sizeof_ctype(ecl_kw)] , iptr, ecl_kw_get_sizeof_ctype(ecl_kw)); } @@ -764,11 +748,11 @@ void ecl_kw_iget(const ecl_kw_type *ecl_kw , int i , void *iptr) { float and int. */ double ecl_kw_iget_as_double(const ecl_kw_type * ecl_kw , int index) { - if (ecl_kw->ecl_type == ECL_FLOAT_TYPE) + if (ecl_type_is_float(ecl_kw->data_type)) return ecl_kw_iget_float( ecl_kw , index); /* Here the compiler will silently insert a float -> double conversion. */ - else if (ecl_kw->ecl_type == ECL_DOUBLE_TYPE) + else if (ecl_type_is_double(ecl_kw->data_type)) return ecl_kw_iget_double( ecl_kw, index); - else if (ecl_kw->ecl_type == ECL_INT_TYPE) + else if (ecl_type_is_int(ecl_kw->data_type)) return ecl_kw_iget_int( ecl_kw, index); /* */ else { util_abort("%s: can not be converted to double - no data for you! \n",__func__); @@ -781,9 +765,9 @@ double ecl_kw_iget_as_double(const ecl_kw_type * ecl_kw , int index) { */ float ecl_kw_iget_as_float(const ecl_kw_type * ecl_kw , int i) { - if (ecl_kw->ecl_type == ECL_FLOAT_TYPE) + if (ecl_type_is_float(ecl_kw->data_type)) return ecl_kw_iget_float( ecl_kw , i); - else if (ecl_kw->ecl_type == ECL_DOUBLE_TYPE) + else if (ecl_type_is_double(ecl_kw->data_type)) return (float) ecl_kw_iget_double( ecl_kw, i); else { util_abort("%s: can not be converted to float - no data for you! \n",__func__); @@ -1091,10 +1075,10 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { const char null_char = '\0'; bool fmt_file = fortio_fmt_file( fortio ); if (ecl_kw->size > 0) { - const int blocksize = get_blocksize( ecl_kw->ecl_type ); + const int blocksize = get_blocksize( ecl_kw->data_type ); if (fmt_file) { const int blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1); - const char * read_fmt = get_read_fmt( ecl_kw->ecl_type ); + const char * read_fmt = get_read_fmt( ecl_kw->data_type ); FILE * stream = fortio_get_FILE(fortio); int offset = 0; int index = 0; @@ -1102,7 +1086,7 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { for (ib = 0; ib < blocks; ib++) { int read_elm = util_int_min((ib + 1) * blocksize , ecl_kw->size) - ib * blocksize; for (ir = 0; ir < read_elm; ir++) { - switch(ecl_kw->ecl_type) { + switch(ecl_kw_get_type(ecl_kw)) { case(ECL_CHAR_TYPE): ecl_kw_fscanf_qstring(&ecl_kw->data[offset] , read_fmt , 8, stream); break; @@ -1110,7 +1094,7 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { { int iread = fscanf(stream , read_fmt , (int *) &ecl_kw->data[offset]); if (iread != 1) - util_abort("%s: after reading %d values reading of keyword:%s from:%s failed - aborting \n",__func__ , offset / ecl_kw->sizeof_ctype , ecl_kw->header8 , fortio_filename_ref(fortio)); + util_abort("%s: after reading %d values reading of keyword:%s from:%s failed - aborting \n",__func__ , offset / ecl_kw_get_sizeof_ctype(ecl_kw) , ecl_kw->header8 , fortio_filename_ref(fortio)); } break; case(ECL_FLOAT_TYPE): @@ -1118,7 +1102,7 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { int iread = fscanf(stream , read_fmt , (float *) &ecl_kw->data[offset]); if (iread != 1) { util_abort("%s: after reading %d values reading of keyword:%s from:%s failed - aborting \n",__func__ , - offset / ecl_kw->sizeof_ctype , + offset / ecl_kw_get_sizeof_ctype(ecl_kw) , ecl_kw->header8 , fortio_filename_ref(fortio)); } @@ -1148,9 +1132,9 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { ecl_kw_fscanf_qstring(&ecl_kw->data[offset] , read_fmt , 8 , stream); break; default: - util_abort("%s: Internal error: internal eclipse_type: %d not recognized - aborting \n",__func__ , ecl_kw->ecl_type); + util_abort("%s: Internal error: internal eclipse_type: %d not recognized - aborting \n",__func__ , ecl_kw_get_type(ecl_kw)); } - offset += ecl_kw->sizeof_ctype; + offset += ecl_kw_get_sizeof_ctype(ecl_kw); index++; } } @@ -1160,7 +1144,7 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { return true; } else { bool read_ok = true; - if (ecl_kw->ecl_type == ECL_CHAR_TYPE || ecl_kw->ecl_type == ECL_MESS_TYPE) { + if (ecl_type_is_char(ecl_kw->data_type) || ecl_type_is_mess(ecl_kw->data_type)) { const int blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1); int ib = 0; while (true) { @@ -1174,8 +1158,8 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { if (record_size >= 0) { int ir; for (ir = 0; ir < read_elm; ir++) { - util_fread( &ecl_kw->data[(ib * blocksize + ir) * ecl_kw->sizeof_ctype] , 1 , ECL_STRING8_LENGTH , stream , __func__); - ecl_kw->data[(ib * blocksize + ir) * ecl_kw->sizeof_ctype + ECL_STRING8_LENGTH] = null_char; + util_fread( &ecl_kw->data[(ib * blocksize + ir) * ecl_kw_get_sizeof_ctype(ecl_kw)] , 1 , ECL_STRING8_LENGTH , stream , __func__); + ecl_kw->data[(ib * blocksize + ir) * ecl_kw_get_sizeof_ctype(ecl_kw) + ECL_STRING8_LENGTH] = null_char; } read_ok = fortio_complete_read(fortio , record_size); } else @@ -1193,7 +1177,7 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { This function handles the fuc***g blocks transparently at a low level. */ - read_ok = fortio_fread_buffer(fortio , ecl_kw->data , ecl_kw->size * ecl_kw->sizeof_ctype); + read_ok = fortio_fread_buffer(fortio , ecl_kw->data , ecl_kw->size * ecl_kw_get_sizeof_ctype(ecl_kw)); if (read_ok && ECL_ENDIAN_FLIP) ecl_kw_endian_convert_data(ecl_kw); } @@ -1205,13 +1189,13 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { } -void ecl_kw_fread_indexed_data(fortio_type * fortio, offset_type data_offset, ecl_type_enum ecl_type, int element_count, const int_vector_type* index_map, char* buffer) { - const int block_size = get_blocksize( ecl_type ); +void ecl_kw_fread_indexed_data(fortio_type * fortio, offset_type data_offset, ecl_data_type data_type, int element_count, const int_vector_type* index_map, char* buffer) { + const int block_size = get_blocksize(data_type); FILE *stream = fortio_get_FILE( fortio ); int index; - int element_size = ecl_util_get_sizeof_ctype(ecl_type); + int element_size = ecl_type_get_sizeof_ctype(data_type); - if(ecl_type == ECL_CHAR_TYPE || ecl_type == ECL_MESS_TYPE) { + if(ecl_type_is_char(data_type) || ecl_type_is_mess(data_type)) { element_size = ECL_STRING8_LENGTH; } @@ -1243,26 +1227,26 @@ bool ecl_kw_fread_realloc_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { Static method without a class instance. */ -bool ecl_kw_fskip_data__( ecl_type_enum ecl_type , const int element_count , fortio_type * fortio) { +bool ecl_kw_fskip_data__( ecl_data_type data_type , const int element_count , fortio_type * fortio) { bool fmt_file = fortio_fmt_file(fortio); bool skip_ok = true; if (element_count > 0) { if (fmt_file) { /* Formatted skipping actually involves reading the data - nice ??? */ ecl_kw_type * tmp_kw = ecl_kw_alloc_empty( ); - ecl_kw_initialize( tmp_kw , "WORK" , element_count , ecl_type ); + ecl_kw_initialize( tmp_kw , "WORK" , element_count , data_type ); ecl_kw_alloc_data(tmp_kw); ecl_kw_fread_data(tmp_kw , fortio); ecl_kw_free( tmp_kw ); } else { - const int blocksize = get_blocksize( ecl_type ); + const int blocksize = get_blocksize( data_type ); const int block_count = element_count / blocksize + (element_count % blocksize == 0 ? 0 : 1); - int element_size = ecl_util_get_sizeof_ctype(ecl_type ); - if(ecl_type == ECL_CHAR_TYPE) + int element_size = ecl_type_get_sizeof_ctype(data_type); + if(ecl_type_is_char(data_type)) element_size = ECL_STRING8_LENGTH; - if(ecl_type == ECL_C010_TYPE) + if(ecl_type_is_C010(data_type)) element_size = ECL_STRING10_LENGTH; skip_ok = fortio_data_fskip(fortio, element_size, element_count, block_count); @@ -1273,7 +1257,7 @@ bool ecl_kw_fskip_data__( ecl_type_enum ecl_type , const int element_count , for bool ecl_kw_fskip_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { - return ecl_kw_fskip_data__( ecl_kw->ecl_type , ecl_kw->size , fortio ); + return ecl_kw_fskip_data__( ecl_kw_get_data_type(ecl_kw) , ecl_kw->size , fortio ); } @@ -1341,10 +1325,10 @@ ecl_read_status_enum ecl_kw_fread_header(ecl_kw_type *ecl_kw , fortio_type * for } if (OK) { - ecl_type_enum ecl_type = ecl_util_get_type_from_name( ecl_type_str ); - ecl_kw_initialize( ecl_kw , header , size , ecl_type); + ecl_data_type data_type = ecl_type_create_from_name( ecl_type_str ); + ecl_kw_initialize( ecl_kw , header , size , data_type); - if (ecl_type == ECL_C010_TYPE) + if (ecl_type_is_C010(data_type)) return ECL_KW_READ_SKIP; return ECL_KW_READ_OK; @@ -1456,7 +1440,7 @@ void ecl_kw_alloc_data(ecl_kw_type *ecl_kw) { util_abort("%s: trying to allocate data for ecl_kw object which has been declared with shared storage - aborting \n",__func__); { - size_t byte_size = ecl_kw->size * ecl_kw->sizeof_ctype; + size_t byte_size = ecl_kw->size * ecl_kw_get_sizeof_ctype(ecl_kw); ecl_kw->data = util_realloc(ecl_kw->data , byte_size ); memset(ecl_kw->data , 0 , byte_size); } @@ -1483,6 +1467,9 @@ void ecl_kw_set_header_name(ecl_kw_type * ecl_kw , const char * header) { } +void ecl_kw_set_data_type(ecl_kw_type * ecl_kw, ecl_data_type data_type) { + memcpy(&ecl_kw->data_type, &data_type, sizeof data_type); +} bool ecl_kw_fread_realloc(ecl_kw_type *ecl_kw , fortio_type *fortio) { @@ -1533,13 +1520,13 @@ static void ecl_kw_fwrite_data_unformatted( ecl_kw_type * ecl_kw , fortio_type * ecl_kw_endian_convert_data(ecl_kw); { - const int blocksize = get_blocksize( ecl_kw->ecl_type ); + const int blocksize = get_blocksize( ecl_kw->data_type ); const int num_blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1); int block_nr; for (block_nr = 0; block_nr < num_blocks; block_nr++) { int this_blocksize = util_int_min((block_nr + 1)*blocksize , ecl_kw->size) - block_nr*blocksize; - if (ecl_kw->ecl_type == ECL_CHAR_TYPE || ecl_kw->ecl_type == ECL_MESS_TYPE) { + if (ecl_type_is_char(ecl_kw->data_type) || ecl_type_is_mess(ecl_kw->data_type)) { /* Due to the terminating \0 characters there is not a continous file/memory mapping - the \0 characters arel @@ -1550,11 +1537,11 @@ static void ecl_kw_fwrite_data_unformatted( ecl_kw_type * ecl_kw , fortio_type * int i; fortio_init_write(fortio , record_size ); for (i = 0; i < this_blocksize; i++) - fwrite(&ecl_kw->data[(block_nr * blocksize + i) * ecl_kw->sizeof_ctype] , 1 , ECL_STRING8_LENGTH , stream); + fwrite(&ecl_kw->data[(block_nr * blocksize + i) * ecl_kw_get_sizeof_ctype(ecl_kw)] , 1 , ECL_STRING8_LENGTH , stream); fortio_complete_write(fortio , record_size); } else { - int record_size = this_blocksize * ecl_kw->sizeof_ctype; /* The total size in bytes of the record written by the fortio layer. */ - fortio_fwrite_record(fortio , &ecl_kw->data[block_nr * blocksize * ecl_kw->sizeof_ctype] , record_size); + int record_size = this_blocksize * ecl_kw_get_sizeof_ctype(ecl_kw); /* The total size in bytes of the record written by the fortio layer. */ + fortio_fwrite_record(fortio , &ecl_kw->data[block_nr * blocksize * ecl_kw_get_sizeof_ctype(ecl_kw)] , record_size); } } } @@ -1606,9 +1593,9 @@ static void ecl_kw_fwrite_data_formatted( ecl_kw_type * ecl_kw , fortio_type * f { FILE * stream = fortio_get_FILE( fortio ); - const int blocksize = get_blocksize( ecl_kw->ecl_type ); - const int columns = get_columns( ecl_kw->ecl_type ); - const char * write_fmt = ecl_kw_get_write_fmt( ecl_kw->ecl_type ); + const int blocksize = get_blocksize( ecl_kw->data_type ); + const int columns = get_columns( ecl_kw->data_type ); + const char * write_fmt = ecl_kw_get_write_fmt( ecl_kw->data_type ); const int num_blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1); int block_nr; @@ -1622,7 +1609,7 @@ static void ecl_kw_fwrite_data_formatted( ecl_kw_type * ecl_kw , fortio_type * f for (col_nr =0; col_nr < num_columns; col_nr++) { int data_index = block_nr * blocksize + line_nr * columns + col_nr; void * data_ptr = ecl_kw_iget_ptr_static( ecl_kw , data_index ); - switch (ecl_kw->ecl_type) { + switch (ecl_kw_get_type(ecl_kw)) { case(ECL_CHAR_TYPE): fprintf(stream , write_fmt , data_ptr); break; @@ -1684,7 +1671,7 @@ void ecl_kw_fwrite_header(const ecl_kw_type *ecl_kw , fortio_type *fortio) { FILE *stream = fortio_get_FILE(fortio); bool fmt_file = fortio_fmt_file(fortio); if (fmt_file) - fprintf(stream , WRITE_HEADER_FMT , ecl_kw->header8 , ecl_kw->size , ecl_util_get_type_name( ecl_kw->ecl_type )); + fprintf(stream , WRITE_HEADER_FMT , ecl_kw->header8 , ecl_kw->size , ecl_type_get_name( ecl_kw->data_type )); else { int size = ecl_kw->size; if (ECL_ENDIAN_FLIP) @@ -1694,7 +1681,7 @@ void ecl_kw_fwrite_header(const ecl_kw_type *ecl_kw , fortio_type *fortio) { fwrite(ecl_kw->header8 , sizeof(char) , ECL_STRING8_LENGTH , stream); fwrite(&size , sizeof(int) , 1 , stream); - fwrite(ecl_util_get_type_name( ecl_kw->ecl_type ) , sizeof(char) , ECL_TYPE_LENGTH , stream); + fwrite(ecl_type_get_name( ecl_kw->data_type ) , sizeof(char) , ECL_TYPE_LENGTH , stream); fortio_complete_write(fortio , ECL_KW_HEADER_DATA_SIZE); @@ -1724,7 +1711,17 @@ int ecl_kw_get_size(const ecl_kw_type * ecl_kw) { return ecl_kw->size; } -ecl_type_enum ecl_kw_get_type(const ecl_kw_type * ecl_kw) { return ecl_kw->ecl_type; } +ecl_type_enum ecl_kw_get_type(const ecl_kw_type * ecl_kw) { + return ecl_type_get_type(ecl_kw->data_type); +} + +ecl_data_type ecl_kw_get_data_type(const ecl_kw_type * ecl_kw) { + return ecl_kw->data_type; +} + +size_t ecl_kw_get_sizeof_ctype(const ecl_kw_type * ecl_kw) { + return ecl_type_get_sizeof_ctype(ecl_kw->data_type); +} /******************************************************************/ @@ -1734,37 +1731,39 @@ ecl_kw_type * ecl_kw_buffer_alloc(buffer_type * buffer) { const char * header = buffer_fread_string( buffer ); int size = buffer_fread_int( buffer ); ecl_type_enum ecl_type = buffer_fread_int( buffer ); - { - ecl_kw_type * ecl_kw = ecl_kw_alloc_empty(); - ecl_kw_initialize( ecl_kw , header , size , ecl_type ); - ecl_kw_alloc_data(ecl_kw); - buffer_fread(buffer , ecl_kw->data , ecl_kw->sizeof_ctype , ecl_kw->size); - return ecl_kw; - } + size_t element_size = buffer_fread_int( buffer ); + + ecl_data_type data_type = ecl_type_create(ecl_type, element_size); + ecl_kw_type * ecl_kw = ecl_kw_alloc_empty(); + ecl_kw_initialize( ecl_kw , header , size , data_type ); + ecl_kw_alloc_data(ecl_kw); + buffer_fread(buffer , ecl_kw->data , ecl_kw_get_sizeof_ctype(ecl_kw) , ecl_kw->size); + return ecl_kw; } void ecl_kw_buffer_store(const ecl_kw_type * ecl_kw , buffer_type * buffer) { buffer_fwrite_string( buffer , ecl_kw->header8 ); buffer_fwrite_int( buffer , ecl_kw->size ); - buffer_fwrite_int( buffer , ecl_kw->ecl_type ); - buffer_fwrite( buffer , ecl_kw->data , ecl_kw->sizeof_ctype , ecl_kw->size); + buffer_fwrite_int( buffer , ecl_type_get_type(ecl_kw->data_type) ); + buffer_fwrite_int( buffer , ecl_type_get_sizeof_ctype(ecl_kw->data_type)); + buffer_fwrite( buffer , ecl_kw->data , ecl_kw_get_sizeof_ctype(ecl_kw) , ecl_kw->size); } -void ecl_kw_fwrite_param_fortio(fortio_type * fortio, const char * header , ecl_type_enum ecl_type , int size, void * data) { - ecl_kw_type * ecl_kw = ecl_kw_alloc_new_shared(header , size , ecl_type , data); +void ecl_kw_fwrite_param_fortio(fortio_type * fortio, const char * header , ecl_data_type data_type , int size, void * data) { + ecl_kw_type * ecl_kw = ecl_kw_alloc_new_shared(header , size , data_type , data); ecl_kw_fwrite(ecl_kw , fortio); ecl_kw_free(ecl_kw); } -void ecl_kw_fwrite_param(const char * filename , bool fmt_file , const char * header , ecl_type_enum ecl_type , int size, void * data) { +void ecl_kw_fwrite_param(const char * filename , bool fmt_file , const char * header , ecl_data_type data_type , int size, void * data) { fortio_type * fortio = fortio_open_writer(filename , fmt_file , ECL_ENDIAN_FLIP); - ecl_kw_fwrite_param_fortio(fortio , header , ecl_type , size , data); + ecl_kw_fwrite_param_fortio(fortio , header , data_type , size , data); fortio_fclose(fortio); } @@ -1772,14 +1771,14 @@ void ecl_kw_fwrite_param(const char * filename , bool fmt_file , const char * he void ecl_kw_get_data_as_double(const ecl_kw_type * ecl_kw , double * double_data) { - if (ecl_kw->ecl_type == ECL_DOUBLE_TYPE) + if (ecl_type_is_double(ecl_kw->data_type)) // Direct memcpy - no conversion ecl_kw_get_memcpy_data(ecl_kw , double_data); else { - if (ecl_kw->ecl_type == ECL_FLOAT_TYPE) { + if (ecl_type_is_float(ecl_kw->data_type)) { const float * float_data = (const float *) ecl_kw->data; util_float_to_double(double_data , float_data , ecl_kw->size); - } else if (ecl_kw->ecl_type == ECL_INT_TYPE) { + } else if (ecl_type_is_int(ecl_kw->data_type)) { const int * int_data = (const int *) ecl_kw->data; int i; for (i=0; i < ecl_kw->size; i++) @@ -1795,14 +1794,14 @@ void ecl_kw_get_data_as_double(const ecl_kw_type * ecl_kw , double * double_data void ecl_kw_get_data_as_float(const ecl_kw_type * ecl_kw , float * float_data) { - if (ecl_kw->ecl_type == ECL_FLOAT_TYPE) + if (ecl_type_is_float(ecl_kw->data_type)) // Direct memcpy - no conversion ecl_kw_get_memcpy_data(ecl_kw , float_data); else { - if (ecl_kw->ecl_type == ECL_DOUBLE_TYPE) { + if (ecl_type_is_double(ecl_kw->data_type)) { const double * double_data = (const double *) ecl_kw->data; util_double_to_float(float_data , double_data , ecl_kw->size); - } else if (ecl_kw->ecl_type == ECL_INT_TYPE) { + } else if (ecl_type_is_int(ecl_kw->data_type)) { const int * int_data = (const int *) ecl_kw->data; int i; for (i=0; i < ecl_kw->size; i++) @@ -1838,13 +1837,13 @@ ecl_kw_type * ecl_kw_alloc_scatter_copy( const ecl_kw_type * src_kw , int target float default_float = 0; int default_bool = ECL_BOOL_FALSE_INT; const char * default_char = ""; - ecl_kw_type * new_kw = ecl_kw_alloc( src_kw->header , target_size , src_kw->ecl_type ); + ecl_kw_type * new_kw = ecl_kw_alloc( src_kw->header , target_size , src_kw->data_type ); if (def_value != NULL) ecl_kw_scalar_set__( new_kw , def_value ); else { /** Initialize with defaults .*/ - switch (src_kw->ecl_type) { + switch (ecl_kw_get_type(src_kw)) { case(ECL_INT_TYPE): ecl_kw_scalar_set__( new_kw , &default_int ); break; @@ -1861,12 +1860,12 @@ ecl_kw_type * ecl_kw_alloc_scatter_copy( const ecl_kw_type * src_kw , int target ecl_kw_scalar_set__( new_kw , default_char ); break; default: - util_abort("%s: unsupported type:%d \n", __func__ , src_kw->ecl_type); + util_abort("%s: unsupported type:%d \n", __func__ , ecl_kw_get_type(src_kw)); } } { - int sizeof_ctype = ecl_util_get_sizeof_ctype( src_kw->ecl_type ); + int sizeof_ctype = ecl_type_get_sizeof_ctype( src_kw->data_type ); int i; for( i =0; i < src_kw->size; i++) { int target_index = mapping[i]; @@ -1895,7 +1894,7 @@ void ecl_kw_fread_double_param(const char * filename , bool fmt_file , double * void ecl_kw_summarize(const ecl_kw_type * ecl_kw) { printf("%8s %10d:%4s \n",ecl_kw_get_header8(ecl_kw), ecl_kw_get_size(ecl_kw), - ecl_util_get_type_name( ecl_kw->ecl_type)); + ecl_type_get_name( ecl_kw->data_type)); } @@ -1906,7 +1905,7 @@ void ecl_kw_summarize(const ecl_kw_type * ecl_kw) { #define ECL_KW_SCALAR_SET_TYPED( ctype , ECL_TYPE ) \ void ecl_kw_scalar_set_ ## ctype( ecl_kw_type * ecl_kw , ctype value){ \ - if (ecl_kw->ecl_type == ECL_TYPE) { \ + if (ecl_kw_get_type(ecl_kw) == ECL_TYPE) { \ ctype * data = ecl_kw_get_data_ref(ecl_kw); \ int i; \ for (i=0;i < ecl_kw->size; i++) \ @@ -1952,7 +1951,7 @@ void ecl_kw_scalar_set_float_or_double( ecl_kw_type * ecl_kw , double value ) { Untyped - low level alternative. */ void ecl_kw_scalar_set__(ecl_kw_type * ecl_kw , const void * value) { - int sizeof_ctype = ecl_util_get_sizeof_ctype( ecl_kw->ecl_type ); + int sizeof_ctype = ecl_type_get_sizeof_ctype( ecl_kw->data_type ); int i; for (i=0;i < ecl_kw->size; i++) memcpy( &ecl_kw->data[ i * sizeof_ctype ] , value , sizeof_ctype); @@ -1965,12 +1964,12 @@ void ecl_kw_scalar_set__(ecl_kw_type * ecl_kw , const void * value) { void ecl_kw_alloc_double_data(ecl_kw_type * ecl_kw , double * values) { ecl_kw_alloc_data(ecl_kw); - memcpy(ecl_kw->data , values , ecl_kw->size * ecl_kw->sizeof_ctype); + memcpy(ecl_kw->data , values , ecl_kw->size * ecl_kw_get_sizeof_ctype(ecl_kw)); } void ecl_kw_alloc_float_data(ecl_kw_type * ecl_kw , float * values) { ecl_kw_alloc_data(ecl_kw); - memcpy(ecl_kw->data , values , ecl_kw->size * ecl_kw->sizeof_ctype); + memcpy(ecl_kw->data , values , ecl_kw->size * ecl_kw_get_sizeof_ctype(ecl_kw)); } /*****************************************************************/ @@ -2034,40 +2033,17 @@ void ecl_kw_shift_float_or_double( ecl_kw_type * ecl_kw , double shift_value ) { util_abort("%s: wrong type \n",__func__); } - - -bool ecl_kw_assert_numeric( const ecl_kw_type * kw ) { - if ((kw->ecl_type == ECL_INT_TYPE) || (kw->ecl_type == ECL_FLOAT_TYPE) || (kw->ecl_type == ECL_DOUBLE_TYPE)) - return true; - else - return false; -} - - -bool ecl_kw_assert_binary( const ecl_kw_type * kw1, const ecl_kw_type * kw2) { - if (kw1->size != kw2->size) - return false; /* Size mismatch */ - if (kw1->ecl_type != kw2->ecl_type) - return false; /* Type mismatch */ - - return true; -} - - -bool ecl_kw_assert_binary_numeric( const ecl_kw_type * kw1, const ecl_kw_type * kw2) { - if (!ecl_kw_assert_binary( kw1 , kw2)) - return false; - else - return ecl_kw_assert_numeric( kw1 ); +bool ecl_kw_size_and_numeric_type_equal( const ecl_kw_type * kw1, const ecl_kw_type * kw2) { + return ecl_kw_size_and_type_equal(kw1, kw2) && ecl_type_is_numeric(kw1->data_type); } #define ECL_KW_ASSERT_TYPED_BINARY_OP( ctype , ECL_TYPE ) \ bool ecl_kw_assert_binary_ ## ctype( const ecl_kw_type * kw1 , const ecl_kw_type * kw2) { \ - if (!ecl_kw_assert_binary_numeric( kw1 , kw2)) \ + if (!ecl_kw_size_and_numeric_type_equal( kw1 , kw2)) \ return false; \ - if (kw1->ecl_type != ECL_TYPE) \ + if (ecl_kw_get_type(kw1) != ECL_TYPE) \ return false; /* Type mismatch */ \ return true; \ } @@ -2079,12 +2055,12 @@ ECL_KW_ASSERT_TYPED_BINARY_OP( double , ECL_DOUBLE_TYPE ) void ecl_kw_copy_indexed( ecl_kw_type * target_kw , const int_vector_type * index_set , const ecl_kw_type * src_kw) { - if (!ecl_kw_assert_binary( target_kw , src_kw )) + if (!ecl_kw_size_and_type_equal( target_kw , src_kw )) util_abort("%s: type/size mismatch\n",__func__); { char * target_data = ecl_kw_get_data_ref( target_kw ); const char * src_data = ecl_kw_get_data_ref( src_kw ); - int sizeof_ctype = ecl_util_get_sizeof_ctype(target_kw->ecl_type); + int sizeof_ctype = ecl_type_get_sizeof_ctype(target_kw->data_type); int set_size = int_vector_size( index_set ); const int * index_data = int_vector_get_const_ptr( index_set ); int i; @@ -2133,7 +2109,7 @@ void ecl_kw_inplace_add_indexed( ecl_kw_type * target_kw , const int_vector_type ecl_kw_inplace_add_indexed_int( target_kw , index_set , add_kw ); break; default: - util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_util_get_type_name( type )); + util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2171,7 +2147,7 @@ void ecl_kw_inplace_add( ecl_kw_type * target_kw , const ecl_kw_type * add_kw) { ecl_kw_inplace_add_int( target_kw , add_kw ); break; default: - util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_util_get_type_name( type )); + util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2210,7 +2186,7 @@ void ecl_kw_inplace_sub( ecl_kw_type * target_kw , const ecl_kw_type * sub_kw) { ecl_kw_inplace_sub_int( target_kw , sub_kw ); break; default: - util_abort("%s: inplace sub not implemented for type:%s \n",__func__ , ecl_util_get_type_name( type )); + util_abort("%s: inplace sub not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2250,7 +2226,7 @@ void ecl_kw_inplace_sub_indexed( ecl_kw_type * target_kw , const int_vector_type ecl_kw_inplace_sub_indexed_int( target_kw , index_set , sub_kw ); break; default: - util_abort("%s: inplace sub not implemented for type:%s \n",__func__ , ecl_util_get_type_name( type )); + util_abort("%s: inplace sub not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2285,7 +2261,7 @@ void ecl_kw_inplace_abs( ecl_kw_type * kw ) { ecl_kw_inplace_abs_int( kw ); break; default: - util_abort("%s: inplace abs not implemented for type:%s \n",__func__ , ecl_util_get_type_name( type )); + util_abort("%s: inplace abs not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(kw) )); } } @@ -2322,7 +2298,7 @@ void ecl_kw_inplace_mul( ecl_kw_type * target_kw , const ecl_kw_type * mul_kw) { ecl_kw_inplace_mul_int( target_kw , mul_kw ); break; default: - util_abort("%s: inplace mul not implemented for type:%s \n",__func__ , ecl_util_get_type_name( type )); + util_abort("%s: inplace mul not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2362,7 +2338,7 @@ void ecl_kw_inplace_mul_indexed( ecl_kw_type * target_kw , const int_vector_type ecl_kw_inplace_mul_indexed_int( target_kw , index_set , mul_kw ); break; default: - util_abort("%s: inplace mul not implemented for type:%s \n",__func__ , ecl_util_get_type_name( type )); + util_abort("%s: inplace mul not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2400,7 +2376,7 @@ void ecl_kw_inplace_div( ecl_kw_type * target_kw , const ecl_kw_type * div_kw) { ecl_kw_inplace_div_int( target_kw , div_kw ); break; default: - util_abort("%s: inplace div not implemented for type:%s \n",__func__ , ecl_util_get_type_name( type )); + util_abort("%s: inplace div not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2441,7 +2417,7 @@ void ecl_kw_inplace_div_indexed( ecl_kw_type * target_kw , const int_vector_type ecl_kw_inplace_div_indexed_int( target_kw , index_set , div_kw ); break; default: - util_abort("%s: inplace div not implemented for type:%s \n",__func__ , ecl_util_get_type_name( type )); + util_abort("%s: inplace div not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2496,7 +2472,7 @@ void ecl_kw_inplace_update_file(const ecl_kw_type * ecl_kw , const char * filena ecl_kw_fread_header(file_kw , fortio); fortio_fseek( fortio , current_pos , SEEK_SET ); - if (!((file_kw->size == ecl_kw->size) && (file_kw->ecl_type == ecl_kw->ecl_type))) + if (!ecl_kw_size_and_type_equal(ecl_kw, file_kw)) util_abort("%s: header mismatch when trying to update:%s in %s \n",__func__ , ecl_kw_get_header8(ecl_kw) , filename); ecl_kw_free(file_kw); } @@ -2544,14 +2520,14 @@ bool ecl_kw_is_kw_file(fortio_type * fortio) { int i; \ for (i=1; i < ecl_kw_get_size(ecl_kw); i++) \ util_update_ ## type ## _max_min(data[i] , &max , &min); \ - memcpy(_max , &max , ecl_kw->sizeof_ctype); \ - memcpy(_min , &min , ecl_kw->sizeof_ctype); \ + memcpy(_max , &max , ecl_kw_get_sizeof_ctype(ecl_kw)); \ + memcpy(_min , &min , ecl_kw_get_sizeof_ctype(ecl_kw)); \ } void ecl_kw_max_min(const ecl_kw_type * ecl_kw , void * _max , void *_min) { - switch (ecl_kw->ecl_type) { + switch (ecl_kw_get_type(ecl_kw)) { case(ECL_FLOAT_TYPE): KW_MAX_MIN(float); break; @@ -2609,20 +2585,20 @@ ECL_KW_MIN( double ) -#define KW_SUM(type) \ -{ \ - type * data = ecl_kw_get_data_ref(ecl_kw); \ - type sum = 0; \ - int i; \ - for (i=0; i < ecl_kw_get_size(ecl_kw); i++) \ - sum += data[i]; \ - memcpy(_sum , &sum , ecl_kw->sizeof_ctype); \ +#define KW_SUM(type) \ +{ \ + type * data = ecl_kw_get_data_ref(ecl_kw); \ + type sum = 0; \ + int i; \ + for (i=0; i < ecl_kw_get_size(ecl_kw); i++) \ + sum += data[i]; \ + memcpy(_sum , &sum , ecl_kw_get_sizeof_ctype(ecl_kw)); \ } void ecl_kw_element_sum(const ecl_kw_type * ecl_kw , void * _sum) { - switch (ecl_kw->ecl_type) { + switch (ecl_kw_get_type(ecl_kw)) { case(ECL_FLOAT_TYPE): KW_SUM(float); break; @@ -2644,18 +2620,18 @@ double ecl_kw_element_sum_float( const ecl_kw_type * ecl_kw ) { double double_sum; void * sum_ptr = NULL; - if (ecl_kw->ecl_type == ECL_DOUBLE_TYPE) + if (ecl_type_is_double(ecl_kw->data_type)) sum_ptr = &double_sum; - else if (ecl_kw->ecl_type == ECL_FLOAT_TYPE) + else if (ecl_type_is_float(ecl_kw->data_type)) sum_ptr = &float_sum; else util_abort("%s: invalid type: \n",__func__); ecl_kw_element_sum( ecl_kw , sum_ptr ); - if (ecl_kw->ecl_type == ECL_DOUBLE_TYPE) + if (ecl_type_is_double(ecl_kw->data_type)) return double_sum; - else if (ecl_kw->ecl_type == ECL_FLOAT_TYPE) + else if (ecl_type_is_float(ecl_kw->data_type)) return float_sum; else return 0; @@ -2700,20 +2676,20 @@ static void ecl_kw_fprintf_data_bool( const ecl_kw_type * ecl_kw , const char * static void ecl_kw_fprintf_data_char( const ecl_kw_type * ecl_kw , const char * fmt , FILE * stream) { int i; for (i=0; i < ecl_kw->size; i++) - fprintf(stream , fmt , &ecl_kw->data[ i * ecl_kw->sizeof_ctype]); + fprintf(stream , fmt , &ecl_kw->data[ i * ecl_kw_get_sizeof_ctype(ecl_kw)]); } void ecl_kw_fprintf_data( const ecl_kw_type * ecl_kw , const char * fmt , FILE * stream) { - if (ecl_kw->ecl_type == ECL_DOUBLE_TYPE) + if (ecl_type_is_double(ecl_kw->data_type)) ecl_kw_fprintf_data_double( ecl_kw , fmt , stream ); - else if (ecl_kw->ecl_type == ECL_FLOAT_TYPE) + else if (ecl_type_is_float(ecl_kw->data_type)) ecl_kw_fprintf_data_float( ecl_kw , fmt , stream ); - else if (ecl_kw->ecl_type == ECL_INT_TYPE) + else if (ecl_type_is_int(ecl_kw->data_type)) ecl_kw_fprintf_data_int( ecl_kw , fmt , stream ); - else if (ecl_kw->ecl_type == ECL_BOOL_TYPE) + else if (ecl_type_is_bool(ecl_kw->data_type)) ecl_kw_fprintf_data_bool( ecl_kw , fmt , stream ); - else if (ecl_kw->ecl_type == ECL_CHAR_TYPE) + else if (ecl_type_is_char(ecl_kw->data_type)) ecl_kw_fprintf_data_char( ecl_kw , fmt , stream ); } @@ -2727,8 +2703,8 @@ static bool ecl_kw_elm_equal_numeric__( const ecl_kw_type * ecl_kw1 , const ecl_ static bool ecl_kw_elm_equal__( const ecl_kw_type * ecl_kw1 , const ecl_kw_type * ecl_kw2 , int offset) { - size_t data_offset = ecl_kw1->sizeof_ctype * offset; - int cmp = memcmp( &ecl_kw1->data[ data_offset ] , &ecl_kw2->data[ data_offset ] , ecl_kw1->sizeof_ctype); + size_t data_offset = ecl_kw_get_sizeof_ctype(ecl_kw1) * offset; + int cmp = memcmp( &ecl_kw1->data[ data_offset ] , &ecl_kw2->data[ data_offset ] , ecl_kw_get_sizeof_ctype(ecl_kw1)); if (cmp == 0) return true; else @@ -2767,5 +2743,4 @@ int ecl_kw_first_different( const ecl_kw_type * ecl_kw1 , const ecl_kw_type * ec } } - #include "ecl_kw_functions.c" diff --git a/ThirdParty/Ert/libecl/src/ecl_kw_grdecl.c b/ThirdParty/Ert/libecl/src/ecl_kw_grdecl.c index 42fb0711fc..9140a295c1 100644 --- a/ThirdParty/Ert/libecl/src/ecl_kw_grdecl.c +++ b/ThirdParty/Ert/libecl/src/ecl_kw_grdecl.c @@ -22,6 +22,7 @@ #include #include +#include #include @@ -41,7 +42,7 @@ formatted numbers it is in general impossible to determine whether the underlying datatype should be integer, float or double. Therefor all the file-reading routines here expect an - ecl_type_enum variable as input. + ecl_data_type as input. 2. The files can have comment sections; even in the data block. @@ -333,13 +334,13 @@ static void iset_range( char * data , int data_offset , int sizeof_ctype , void Observe that no-spaces-are-allowed-around-the-* */ -static char * fscanf_alloc_grdecl_data( const char * header , bool strict , ecl_type_enum ecl_type , int * kw_size , FILE * stream ) { +static char * fscanf_alloc_grdecl_data( const char * header , bool strict , ecl_data_type data_type , int * kw_size , FILE * stream ) { char newline = '\n'; bool atEOF = false; int init_size = 32; int buffer_size = 64; int data_index = 0; - int sizeof_ctype = ecl_util_get_sizeof_ctype( ecl_type ); + int sizeof_ctype = ecl_type_get_sizeof_ctype( data_type ); int data_size = init_size; char * buffer = util_calloc( (buffer_size + 1) , sizeof * buffer ); char * data = util_calloc( sizeof_ctype * data_size , sizeof * data ); @@ -369,7 +370,7 @@ static char * fscanf_alloc_grdecl_data( const char * header , bool strict , ecl_ void * value_ptr = NULL; bool char_input = false; - if (ecl_type == ECL_INT_TYPE) { + if (ecl_type_is_int(data_type)) { int value; if (sscanf(buffer , "%d*%d" , &multiplier , &value) == 2) @@ -383,7 +384,7 @@ static char * fscanf_alloc_grdecl_data( const char * header , bool strict , ecl_ } value_ptr = &value; - } else if (ecl_type == ECL_FLOAT_TYPE) { + } else if (ecl_type_is_float(data_type)) { float value; if (sscanf(buffer , "%d*%g" , &multiplier , &value) == 2) @@ -397,7 +398,7 @@ static char * fscanf_alloc_grdecl_data( const char * header , bool strict , ecl_ } value_ptr = &value; - } else if (ecl_type == ECL_DOUBLE_TYPE) { + } else if (ecl_type_is_double(data_type)) { double value; if (sscanf(buffer , "%d*%lg" , &multiplier , &value) == 2) @@ -412,7 +413,7 @@ static char * fscanf_alloc_grdecl_data( const char * header , bool strict , ecl_ value_ptr = &value; } else - util_abort("%s: sorry type:%s not supported \n",__func__ , ecl_util_get_type_name(ecl_type)); + util_abort("%s: sorry type:%s not supported \n",__func__ , ecl_type_get_name(data_type)); /* Removing this warning on user request: @@ -515,9 +516,8 @@ static char * fscanf_alloc_grdecl_data( const char * header , bool strict , ecl_ if there is something wrong it can be difficult to detect. */ - -static ecl_kw_type * __ecl_kw_fscanf_alloc_grdecl__(FILE * stream , const char * header , bool strict , int size , ecl_type_enum ecl_type) { - if (! (ecl_type == ECL_FLOAT_TYPE || ecl_type == ECL_INT_TYPE || ecl_type == ECL_DOUBLE_TYPE)) +static ecl_kw_type * __ecl_kw_fscanf_alloc_grdecl__(FILE * stream , const char * header , bool strict , int size , ecl_data_type data_type) { + if (!ecl_type_is_numeric(data_type)) util_abort("%s: sorry only types FLOAT, INT and DOUBLE supported\n",__func__); if (header != NULL) @@ -528,7 +528,7 @@ static ecl_kw_type * __ecl_kw_fscanf_alloc_grdecl__(FILE * stream , const char * char file_header[9]; if (fscanf(stream , "%s" , file_header) == 1) { int kw_size; - char * data = fscanf_alloc_grdecl_data( file_header , strict , ecl_type , &kw_size , stream ); + char * data = fscanf_alloc_grdecl_data( file_header , strict , data_type , &kw_size , stream ); // Verify size if (size > 0) @@ -539,7 +539,7 @@ static ecl_kw_type * __ecl_kw_fscanf_alloc_grdecl__(FILE * stream , const char * } { - ecl_kw_type * ecl_kw = ecl_kw_alloc_new( file_header , kw_size , ecl_type , NULL ); + ecl_kw_type * ecl_kw = ecl_kw_alloc_new( file_header , kw_size , data_type , NULL ); ecl_kw_set_data_ptr( ecl_kw , data ); return ecl_kw; } @@ -569,14 +569,14 @@ static ecl_kw_type * __ecl_kw_fscanf_alloc_grdecl__(FILE * stream , const char * /*****************************************************************/ -ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_data__(FILE * stream , bool strict , int size , ecl_type_enum ecl_type) { - return __ecl_kw_fscanf_alloc_grdecl__( stream , NULL , strict , size , ecl_type ); +ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_data__(FILE * stream , bool strict , int size , ecl_data_type data_type) { + return __ecl_kw_fscanf_alloc_grdecl__( stream , NULL , strict , size , data_type ); } -ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_data(FILE * stream , int size , ecl_type_enum ecl_type) { +ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_data(FILE * stream , int size , ecl_data_type data_type) { bool strict = true; - return ecl_kw_fscanf_alloc_grdecl_data__( stream , strict , size , ecl_type ); + return ecl_kw_fscanf_alloc_grdecl_data__( stream , strict , size , data_type ); } /*****************************************************************/ @@ -591,13 +591,13 @@ ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_data(FILE * stream , int size , ecl_typ the whole keyword is loaded, and then return. */ -ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_dynamic__( FILE * stream , const char * kw , bool strict , ecl_type_enum ecl_type) { - return __ecl_kw_fscanf_alloc_grdecl__( stream , kw , strict , 0 , ecl_type ); +ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_dynamic__( FILE * stream , const char * kw , bool strict , ecl_data_type data_type) { + return __ecl_kw_fscanf_alloc_grdecl__( stream , kw , strict , 0 , data_type ); } -ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_dynamic( FILE * stream , const char * kw , ecl_type_enum ecl_type) { +ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_dynamic( FILE * stream , const char * kw , ecl_data_type data_type) { bool strict = true; - return ecl_kw_fscanf_alloc_grdecl_dynamic__( stream , kw , strict , ecl_type ); + return ecl_kw_fscanf_alloc_grdecl_dynamic__( stream , kw , strict , data_type ); } /*****************************************************************/ @@ -615,14 +615,14 @@ ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_dynamic( FILE * stream , const char * k size == 0. */ -ecl_kw_type * ecl_kw_fscanf_alloc_grdecl__( FILE * stream , const char * kw , bool strict , int size , ecl_type_enum ecl_type) { - return __ecl_kw_fscanf_alloc_grdecl__( stream , kw , strict , size , ecl_type ); +ecl_kw_type * ecl_kw_fscanf_alloc_grdecl__( FILE * stream , const char * kw , bool strict , int size , ecl_data_type data_type) { + return __ecl_kw_fscanf_alloc_grdecl__( stream , kw , strict , size , data_type ); } -ecl_kw_type * ecl_kw_fscanf_alloc_grdecl( FILE * stream , const char * kw , int size , ecl_type_enum ecl_type) { +ecl_kw_type * ecl_kw_fscanf_alloc_grdecl( FILE * stream , const char * kw , int size , ecl_data_type data_type) { bool strict = true; - return ecl_kw_fscanf_alloc_grdecl__( stream , kw , strict , size , ecl_type ); + return ecl_kw_fscanf_alloc_grdecl__( stream , kw , strict , size , data_type ); } /*****************************************************************/ @@ -636,14 +636,14 @@ ecl_kw_type * ecl_kw_fscanf_alloc_grdecl( FILE * stream , const char * kw , int input file is well formatted. */ -ecl_kw_type * ecl_kw_fscanf_alloc_current_grdecl__( FILE * stream , bool strict , ecl_type_enum ecl_type) { - return __ecl_kw_fscanf_alloc_grdecl__( stream , NULL , strict , 0 , ecl_type ); +ecl_kw_type * ecl_kw_fscanf_alloc_current_grdecl__( FILE * stream , bool strict , ecl_data_type data_type) { + return __ecl_kw_fscanf_alloc_grdecl__( stream , NULL , strict , 0 , data_type ); } -ecl_kw_type * ecl_kw_fscanf_alloc_current_grdecl( FILE * stream , ecl_type_enum ecl_type) { +ecl_kw_type * ecl_kw_fscanf_alloc_current_grdecl( FILE * stream , ecl_data_type data_type) { bool strict = true; - return ecl_kw_fscanf_alloc_current_grdecl__( stream , strict , ecl_type ); + return ecl_kw_fscanf_alloc_current_grdecl__( stream , strict , data_type ); } @@ -676,4 +676,3 @@ void ecl_kw_fprintf_grdecl__(const ecl_kw_type * ecl_kw , const char * special_h void ecl_kw_fprintf_grdecl(const ecl_kw_type * ecl_kw , FILE * stream) { ecl_kw_fprintf_grdecl__(ecl_kw , NULL , stream ); } - diff --git a/ThirdParty/Ert/libecl/src/ecl_nnc_geometry.c b/ThirdParty/Ert/libecl/src/ecl_nnc_geometry.c new file mode 100644 index 0000000000..378112cced --- /dev/null +++ b/ThirdParty/Ert/libecl/src/ecl_nnc_geometry.c @@ -0,0 +1,126 @@ +/* + Copyright (c) 2017 statoil asa, norway. + + The file 'ecl_nnc_geometry.c' is part of ert - ensemble based reservoir tool. + + ERT 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. + + ERT 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 at + for more details. +*/ + +#include + +#include + +#define ECL_NNC_GEOMETRY_TYPE_ID 6124343 + +struct ecl_nnc_geometry_struct { + UTIL_TYPE_ID_DECLARATION; + struct_vector_type * data; +}; + + +UTIL_IS_INSTANCE_FUNCTION( ecl_nnc_geometry, ECL_NNC_GEOMETRY_TYPE_ID ) + + +int ecl_nnc_geometry_size( const ecl_nnc_geometry_type * nnc_geo ) { + return struct_vector_get_size( nnc_geo->data ); +} + +/* + Will go through the grid and add links for all NNC connections in + the grid. The endpoints of an NNC are defined by the tuple: + + (grid_nr, global_index), + + and a NNC link is defined by a pair of such connections, linking + cells (grid_nr1, global_index1) and (grid_nr2, global_index2). +*/ + +static void ecl_nnc_geometry_add_pairs( const ecl_nnc_geometry_type * nnc_geo , const ecl_grid_type * grid ) { + int lgr_nr1 = ecl_grid_get_lgr_nr( grid ); + const ecl_grid_type * global_grid = ecl_grid_get_global_grid( grid ); + + if (!global_grid) + global_grid = grid; + + + for (int global_index1 = 0; global_index1 < ecl_grid_get_global_size( grid ); global_index1++) { + const nnc_info_type * nnc_info = ecl_grid_get_cell_nnc_info1( grid , global_index1 ); + if (!nnc_info) + continue; + + for (int lgr_index2 = 0; lgr_index2 < nnc_info_get_size( nnc_info ); lgr_index2++) { + const nnc_vector_type * nnc_vector = nnc_info_iget_vector( nnc_info , lgr_index2 ); + const int_vector_type * grid2_index_list = nnc_vector_get_grid_index_list( nnc_vector ); + const int_vector_type * nnc_index_list = nnc_vector_get_nnc_index_list( nnc_vector ); + int lgr_nr2 = nnc_vector_get_lgr_nr( nnc_vector ); + + for (int index2 = 0; index2 < nnc_vector_get_size( nnc_vector ); index2++) { + ecl_nnc_pair_type pair = {.grid_nr1 = lgr_nr1, + .global_index1 = global_index1, + .grid_nr2 = lgr_nr2, + .global_index2 = int_vector_iget( grid2_index_list , index2 ), + .input_index = int_vector_iget( nnc_index_list, index2 )}; + + struct_vector_append( nnc_geo->data , &pair); + } + } + } +} + + +static int ecl_nnc_cmp(const void * _nnc1 , const void * _nnc2) { + const ecl_nnc_pair_type * nnc1 = (const ecl_nnc_pair_type * ) _nnc1; + const ecl_nnc_pair_type * nnc2 = (const ecl_nnc_pair_type * ) _nnc2; + + if (nnc1->grid_nr1 != nnc2->grid_nr1) + return nnc1->grid_nr1 - nnc2->grid_nr1; + + if (nnc1->grid_nr2 != nnc2->grid_nr2) + return nnc1->grid_nr2 - nnc2->grid_nr2; + + if (nnc1->global_index1 != nnc2->global_index1) + return nnc1->global_index1 - nnc2->global_index1; + + if (nnc1->global_index2 != nnc2->global_index2) + return nnc1->global_index2 - nnc2->global_index2; + + return 0; +} + + + +ecl_nnc_geometry_type * ecl_nnc_geometry_alloc( const ecl_grid_type * grid ) { + ecl_nnc_geometry_type * nnc_geo = util_malloc( sizeof * nnc_geo ); + UTIL_TYPE_ID_INIT( nnc_geo , ECL_NNC_GEOMETRY_TYPE_ID ); + nnc_geo->data = struct_vector_alloc( sizeof( struct ecl_nnc_pair_struct )); + + ecl_nnc_geometry_add_pairs( nnc_geo , grid ); + for (int lgr_index = 0; lgr_index < ecl_grid_get_num_lgr(grid); lgr_index++) { + ecl_grid_type * igrid = ecl_grid_iget_lgr( grid , lgr_index ); + ecl_nnc_geometry_add_pairs( nnc_geo, igrid ); + } + struct_vector_sort( nnc_geo->data , ecl_nnc_cmp ); + return nnc_geo; +} + + +void ecl_nnc_geometry_free( ecl_nnc_geometry_type * nnc_geo) { + struct_vector_free( nnc_geo->data ); + free( nnc_geo ); +} + + +const ecl_nnc_pair_type * ecl_nnc_geometry_iget( const ecl_nnc_geometry_type * nnc_geo , int index) { + return struct_vector_iget_ptr( nnc_geo->data , index ); + +} diff --git a/ThirdParty/Ert/libecl/src/ecl_region.c b/ThirdParty/Ert/libecl/src/ecl_region.c index 88e2b8372e..ca1a2faeb7 100644 --- a/ThirdParty/Ert/libecl/src/ecl_region.c +++ b/ThirdParty/Ert/libecl/src/ecl_region.c @@ -306,7 +306,7 @@ void ecl_region_deselect_cell( ecl_region_type * region , int i , int j , int k) static void ecl_region_select_equal__( ecl_region_type * region , const ecl_kw_type * ecl_kw, int value , bool select) { bool global_kw; ecl_region_assert_kw( region , ecl_kw , &global_kw); - if (ecl_kw_get_type( ecl_kw ) != ECL_INT_TYPE) + if (!ecl_type_is_int(ecl_kw_get_data_type( ecl_kw ))) util_abort("%s: sorry - select by equality is only supported for integer keywords \n",__func__); { const int * kw_data = ecl_kw_get_int_ptr( ecl_kw ); @@ -344,7 +344,7 @@ void ecl_region_deselect_equal( ecl_region_type * region , const ecl_kw_type * e static void ecl_region_select_bool_equal__( ecl_region_type * region , const ecl_kw_type * ecl_kw, bool value , bool select) { bool global_kw; ecl_region_assert_kw( region , ecl_kw , &global_kw); - if (ecl_kw_get_type( ecl_kw ) != ECL_BOOL_TYPE) + if (!ecl_type_is_bool(ecl_kw_get_data_type( ecl_kw ))) util_abort("%s: sorry - select by equality is only supported for boolean keywords \n",__func__); { if (global_kw) { @@ -392,7 +392,7 @@ void ecl_region_deselect_false( ecl_region_type * region , const ecl_kw_type * e static void ecl_region_select_in_interval__( ecl_region_type * region , const ecl_kw_type * ecl_kw, float min_value , float max_value , bool select) { bool global_kw; ecl_region_assert_kw( region , ecl_kw , &global_kw); - if (ecl_kw_get_type( ecl_kw ) != ECL_FLOAT_TYPE) + if (!ecl_type_is_float(ecl_kw_get_data_type( ecl_kw ))) util_abort("%s: sorry - select by in_interval is only supported for float keywords \n",__func__); { const float * kw_data = ecl_kw_get_float_ptr( ecl_kw ); @@ -439,13 +439,13 @@ void ecl_region_deselect_in_interval( ecl_region_type * region , const ecl_kw_ty */ static void ecl_region_select_with_limit__( ecl_region_type * region , const ecl_kw_type * ecl_kw, float limit , bool select_less , bool select) { bool global_kw; - ecl_type_enum ecl_type = ecl_kw_get_type( ecl_kw ); + ecl_data_type data_type = ecl_kw_get_data_type( ecl_kw ); ecl_region_assert_kw( region , ecl_kw , &global_kw); - if (!((ecl_type == ECL_FLOAT_TYPE) || (ecl_type == ECL_INT_TYPE) || (ecl_type == ECL_DOUBLE_TYPE))) + if (!ecl_type_is_numeric(data_type)) util_abort("%s: sorry - select by in_interval is only supported for float and integer keywords \n",__func__); { - if (ecl_type == ECL_FLOAT_TYPE) { + if (ecl_type_is_float(data_type)) { const float * kw_data = ecl_kw_get_float_ptr( ecl_kw ); float float_limit = limit; if (global_kw) { @@ -475,7 +475,7 @@ static void ecl_region_select_with_limit__( ecl_region_type * region , const ecl } } } - } else if (ecl_type == ECL_INT_TYPE) { + } else if (ecl_type_is_int(data_type)) { const int * kw_data = ecl_kw_get_int_ptr( ecl_kw ); int int_limit = (int) limit; if (global_kw) { @@ -505,7 +505,7 @@ static void ecl_region_select_with_limit__( ecl_region_type * region , const ecl } } } - } else if (ecl_type == ECL_DOUBLE_TYPE) { + } else if (ecl_type_is_double(data_type)) { const double * kw_data = ecl_kw_get_double_ptr( ecl_kw ); double double_limit = (double) limit; if (global_kw) { @@ -566,11 +566,10 @@ void ecl_region_deselect_larger( ecl_region_type * ecl_region , const ecl_kw_typ static void ecl_region_cmp_select__( ecl_region_type * region , const ecl_kw_type * kw1 , const ecl_kw_type * kw2 , bool select_less , bool select) { bool global_kw; ecl_region_assert_kw( region , kw1 , &global_kw); - if (ecl_kw_get_type( kw1 ) != ECL_FLOAT_TYPE) + if (!ecl_type_is_float(ecl_kw_get_data_type( kw1 ))) util_abort("%s: sorry - select by cmp() is only supported for float keywords \n",__func__); { - if ((ecl_kw_get_size( kw1 ) == ecl_kw_get_size( kw2 )) && - (ecl_kw_get_type( kw1 ) == ecl_kw_get_type( kw2 ))) { + if (ecl_kw_size_and_type_equal(kw1, kw2)) { const float * kw1_data = ecl_kw_get_float_ptr( kw1 ); const float * kw2_data = ecl_kw_get_float_ptr( kw2 ); diff --git a/ThirdParty/Ert/libecl/src/ecl_rft_node.c b/ThirdParty/Ert/libecl/src/ecl_rft_node.c index 5ab5508b3e..72cf1b33d2 100644 --- a/ThirdParty/Ert/libecl/src/ecl_rft_node.c +++ b/ThirdParty/Ert/libecl/src/ecl_rft_node.c @@ -34,6 +34,7 @@ #include #include #include +#include /** @@ -537,14 +538,14 @@ void ecl_rft_node_fwrite(const ecl_rft_node_type * rft_node, fortio_type * forti util_abort("%s: sorry - only writing of simple RFT is currently implemented",__func__); { - ecl_kw_type * time = ecl_kw_alloc(TIME_KW, 1, ECL_FLOAT_TYPE); + ecl_kw_type * time = ecl_kw_alloc(TIME_KW, 1, ECL_FLOAT); ecl_kw_iset_float(time, 0, ecl_rft_node_get_days(rft_node)); ecl_kw_fwrite(time, fortio); ecl_kw_free(time); } { - ecl_kw_type * datevalue = ecl_kw_alloc(DATE_KW, 3, ECL_INT_TYPE); + ecl_kw_type * datevalue = ecl_kw_alloc(DATE_KW, 3, ECL_INT); time_t date = ecl_rft_node_get_date(rft_node); int day; int month; @@ -558,7 +559,7 @@ void ecl_rft_node_fwrite(const ecl_rft_node_type * rft_node, fortio_type * forti } { - ecl_kw_type * welletc = ecl_kw_alloc(WELLETC_KW, 16, ECL_CHAR_TYPE); + ecl_kw_type * welletc = ecl_kw_alloc(WELLETC_KW, 16, ECL_CHAR); ecl_rft_enum type = ecl_rft_node_get_type(rft_node); ecl_kw_iset_string8(welletc, 1, ecl_rft_node_get_well_name(rft_node)); @@ -577,14 +578,14 @@ void ecl_rft_node_fwrite(const ecl_rft_node_type * rft_node, fortio_type * forti { int size_cells = ecl_rft_node_get_size(rft_node); - ecl_kw_type * conipos = ecl_kw_alloc(CONIPOS_KW, size_cells, ECL_INT_TYPE); - ecl_kw_type * conjpos = ecl_kw_alloc(CONJPOS_KW, size_cells, ECL_INT_TYPE); - ecl_kw_type * conkpos = ecl_kw_alloc(CONKPOS_KW, size_cells, ECL_INT_TYPE); - ecl_kw_type * hostgrid = ecl_kw_alloc(HOSTGRID_KW, size_cells, ECL_CHAR_TYPE); - ecl_kw_type * depth = ecl_kw_alloc(DEPTH_KW, size_cells, ECL_FLOAT_TYPE); - ecl_kw_type * pressure = ecl_kw_alloc(PRESSURE_KW, size_cells, ECL_FLOAT_TYPE); - ecl_kw_type * swat = ecl_kw_alloc(SWAT_KW, size_cells, ECL_FLOAT_TYPE); - ecl_kw_type * sgas = ecl_kw_alloc(SGAS_KW, size_cells, ECL_FLOAT_TYPE); + ecl_kw_type * conipos = ecl_kw_alloc(CONIPOS_KW, size_cells, ECL_INT); + ecl_kw_type * conjpos = ecl_kw_alloc(CONJPOS_KW, size_cells, ECL_INT); + ecl_kw_type * conkpos = ecl_kw_alloc(CONKPOS_KW, size_cells, ECL_INT); + ecl_kw_type * hostgrid = ecl_kw_alloc(HOSTGRID_KW, size_cells, ECL_CHAR); + ecl_kw_type * depth = ecl_kw_alloc(DEPTH_KW, size_cells, ECL_FLOAT); + ecl_kw_type * pressure = ecl_kw_alloc(PRESSURE_KW, size_cells, ECL_FLOAT); + ecl_kw_type * swat = ecl_kw_alloc(SWAT_KW, size_cells, ECL_FLOAT); + ecl_kw_type * sgas = ecl_kw_alloc(SGAS_KW, size_cells, ECL_FLOAT); int i; for(i =0;i #include #include +#include struct ecl_rst_file_struct { fortio_type * fortio; @@ -101,7 +102,7 @@ ecl_rst_file_type * ecl_rst_file_open_write_seek( const char * filename , int re fortio_fseek( rst_file->fortio , 0 , SEEK_SET ); { - ecl_kw_type * work_kw = ecl_kw_alloc_new("WORK-KW" , 0 , ECL_INT_TYPE , NULL); + ecl_kw_type * work_kw = ecl_kw_alloc_new("WORK-KW" , 0 , ECL_INT, NULL); while (true) { offset_type current_offset = fortio_ftell( rst_file->fortio ); @@ -157,20 +158,20 @@ void ecl_rst_file_close( ecl_rst_file_type * rst_file ) { /*****************************************************************/ static void ecl_rst_file_fwrite_SEQNUM( ecl_rst_file_type * rst_file , int seqnum ) { - ecl_kw_type * seqnum_kw = ecl_kw_alloc( SEQNUM_KW , 1 , ECL_INT_TYPE ); + ecl_kw_type * seqnum_kw = ecl_kw_alloc( SEQNUM_KW , 1 , ECL_INT ); ecl_kw_iset_int( seqnum_kw , 0 , seqnum ); ecl_kw_fwrite( seqnum_kw , rst_file->fortio ); ecl_kw_free( seqnum_kw ); } void ecl_rst_file_start_solution( ecl_rst_file_type * rst_file ) { - ecl_kw_type * startsol_kw = ecl_kw_alloc( STARTSOL_KW , 0 , ECL_MESS_TYPE ); + ecl_kw_type * startsol_kw = ecl_kw_alloc( STARTSOL_KW , 0 , ECL_MESS ); ecl_kw_fwrite( startsol_kw , rst_file->fortio ); ecl_kw_free( startsol_kw ); } void ecl_rst_file_end_solution( ecl_rst_file_type * rst_file ) { - ecl_kw_type * endsol_kw = ecl_kw_alloc( ENDSOL_KW , 0 , ECL_MESS_TYPE ); + ecl_kw_type * endsol_kw = ecl_kw_alloc( ENDSOL_KW , 0 , ECL_MESS ); ecl_kw_fwrite( endsol_kw , rst_file->fortio ); ecl_kw_free( endsol_kw ); } @@ -180,7 +181,7 @@ void ecl_rst_file_end_solution( ecl_rst_file_type * rst_file ) { static ecl_kw_type * ecl_rst_file_alloc_INTEHEAD( ecl_rst_file_type * rst_file, ecl_rsthead_type * rsthead, int simulator ) { - ecl_kw_type * intehead_kw = ecl_kw_alloc( INTEHEAD_KW , INTEHEAD_RESTART_SIZE , ECL_INT_TYPE ); + ecl_kw_type * intehead_kw = ecl_kw_alloc( INTEHEAD_KW , INTEHEAD_RESTART_SIZE , ECL_INT ); ecl_kw_scalar_set_int( intehead_kw , 0 ); ecl_kw_iset_int( intehead_kw , INTEHEAD_UNIT_INDEX , rsthead->unit_system ); @@ -230,7 +231,7 @@ static ecl_kw_type * ecl_rst_file_alloc_LOGIHEAD( int simulator ) { bool radial_grid_ECLIPSE100 = false; bool radial_grid_ECLIPSE300 = false; - ecl_kw_type * logihead_kw = ecl_kw_alloc( LOGIHEAD_KW , LOGIHEAD_RESTART_SIZE , ECL_BOOL_TYPE ); + ecl_kw_type * logihead_kw = ecl_kw_alloc( LOGIHEAD_KW , LOGIHEAD_RESTART_SIZE , ECL_BOOL ); ecl_kw_scalar_set_bool( logihead_kw , false ); @@ -245,7 +246,7 @@ static ecl_kw_type * ecl_rst_file_alloc_LOGIHEAD( int simulator ) { static ecl_kw_type * ecl_rst_file_alloc_DOUBHEAD( ecl_rst_file_type * rst_file , double days) { - ecl_kw_type * doubhead_kw = ecl_kw_alloc( DOUBHEAD_KW , DOUBHEAD_RESTART_SIZE , ECL_DOUBLE_TYPE ); + ecl_kw_type * doubhead_kw = ecl_kw_alloc( DOUBHEAD_KW , DOUBHEAD_RESTART_SIZE , ECL_DOUBLE ); ecl_kw_scalar_set_double( doubhead_kw , 0); ecl_kw_iset_double( doubhead_kw , DOUBHEAD_DAYS_INDEX , days ); diff --git a/ThirdParty/Ert/libecl/src/ecl_rsthead.c b/ThirdParty/Ert/libecl/src/ecl_rsthead.c index e382cc18de..52ad95436d 100644 --- a/ThirdParty/Ert/libecl/src/ecl_rsthead.c +++ b/ThirdParty/Ert/libecl/src/ecl_rsthead.c @@ -88,8 +88,7 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ // The only derived quantity rsthead->sim_time = rsthead_date( rsthead->day , rsthead->month , rsthead->year ); } - if (doubhead_kw) - rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); + rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); if (logihead_kw) rsthead->dualp = ecl_kw_iget_bool( logihead_kw , LOGIHEAD_DUALP_INDEX); @@ -110,15 +109,12 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ ecl_rsthead_type * ecl_rsthead_alloc( const ecl_file_view_type * rst_view, int report_step) { const ecl_kw_type * intehead_kw = ecl_file_view_iget_named_kw( rst_view , INTEHEAD_KW , 0); - const ecl_kw_type * doubhead_kw = NULL; + const ecl_kw_type * doubhead_kw = ecl_file_view_iget_named_kw( rst_view , DOUBHEAD_KW , 0); const ecl_kw_type * logihead_kw = NULL; if (ecl_file_view_has_kw(rst_view, LOGIHEAD_KW)) logihead_kw = ecl_file_view_iget_named_kw( rst_view , LOGIHEAD_KW , 0); - if (ecl_file_view_has_kw(rst_view, DOUBHEAD_KW)) - doubhead_kw = ecl_file_view_iget_named_kw(rst_view, DOUBHEAD_KW, 0); - if (ecl_file_view_has_kw( rst_view , SEQNUM_KW)) { const ecl_kw_type * seqnum_kw = ecl_file_view_iget_named_kw( rst_view , SEQNUM_KW , 0); report_step = ecl_kw_iget_int( seqnum_kw , 0); diff --git a/ThirdParty/Ert/libecl/src/ecl_smspec.c b/ThirdParty/Ert/libecl/src/ecl_smspec.c index ed6490484a..ae64dde627 100644 --- a/ThirdParty/Ert/libecl/src/ecl_smspec.c +++ b/ThirdParty/Ert/libecl/src/ecl_smspec.c @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef HAVE_FNMATCH #include @@ -344,7 +345,7 @@ void ecl_smspec_lock( ecl_smspec_type * smspec ) { static void ecl_smspec_fortio_fwrite( const ecl_smspec_type * smspec , fortio_type * fortio) { int num_nodes = ecl_smspec_num_nodes( smspec ); { - ecl_kw_type * restart_kw = ecl_kw_alloc( RESTART_KW , SUMMARY_RESTART_SIZE , ECL_CHAR_TYPE ); + ecl_kw_type * restart_kw = ecl_kw_alloc( RESTART_KW , SUMMARY_RESTART_SIZE , ECL_CHAR ); int i; for (i=0; i < SUMMARY_RESTART_SIZE; i++) ecl_kw_iset_string8( restart_kw , i , ""); @@ -353,7 +354,7 @@ static void ecl_smspec_fortio_fwrite( const ecl_smspec_type * smspec , fortio_ty ecl_kw_free( restart_kw ); } { - ecl_kw_type * dimens_kw = ecl_kw_alloc( DIMENS_KW , DIMENS_SIZE , ECL_INT_TYPE ); + ecl_kw_type * dimens_kw = ecl_kw_alloc( DIMENS_KW , DIMENS_SIZE , ECL_INT ); ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_SIZE_INDEX , num_nodes ); ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_NX_INDEX , smspec->grid_dims[0] ); ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_NY_INDEX , smspec->grid_dims[1] ); @@ -369,13 +370,13 @@ static void ecl_smspec_fortio_fwrite( const ecl_smspec_type * smspec , fortio_ty { - ecl_kw_type * keywords_kw = ecl_kw_alloc( KEYWORDS_KW , num_nodes , ECL_CHAR_TYPE ); - ecl_kw_type * wgnames_kw = ecl_kw_alloc( WGNAMES_KW , num_nodes , ECL_CHAR_TYPE ); - ecl_kw_type * units_kw = ecl_kw_alloc( UNITS_KW , num_nodes , ECL_CHAR_TYPE ); + ecl_kw_type * keywords_kw = ecl_kw_alloc( KEYWORDS_KW , num_nodes , ECL_CHAR ); + ecl_kw_type * wgnames_kw = ecl_kw_alloc( WGNAMES_KW , num_nodes , ECL_CHAR ); + ecl_kw_type * units_kw = ecl_kw_alloc( UNITS_KW , num_nodes , ECL_CHAR ); ecl_kw_type * nums_kw = NULL; if (smspec->need_nums) - nums_kw = ecl_kw_alloc( NUMS_KW , num_nodes , ECL_INT_TYPE); + nums_kw = ecl_kw_alloc( NUMS_KW , num_nodes , ECL_INT); { int i; for (i=0; i < ecl_smspec_num_nodes( smspec ); i++) { @@ -435,7 +436,7 @@ static void ecl_smspec_fortio_fwrite( const ecl_smspec_type * smspec , fortio_ty } { - ecl_kw_type * startdat_kw = ecl_kw_alloc( STARTDAT_KW , STARTDAT_SIZE , ECL_INT_TYPE ); + ecl_kw_type * startdat_kw = ecl_kw_alloc( STARTDAT_KW , STARTDAT_SIZE , ECL_INT ); int day,month,year; ecl_util_set_date_values( smspec->sim_start_time , &day, &month , &year); diff --git a/ThirdParty/Ert/libecl/src/ecl_subsidence.c b/ThirdParty/Ert/libecl/src/ecl_subsidence.c index 9b3f30b893..4fe053f6f9 100644 --- a/ThirdParty/Ert/libecl/src/ecl_subsidence.c +++ b/ThirdParty/Ert/libecl/src/ecl_subsidence.c @@ -179,9 +179,9 @@ static double ecl_subsidence_survey_eval_geertsma( const ecl_subsidence_survey_t for (int index = 0; index < size; index++) { if (monitor_survey) { - weight[index] = - scale_factor * cell_volume[index] * (monitor_survey->pressure[index] - base_survey->pressure[index]); + weight[index] = scale_factor * cell_volume[index] * (base_survey->pressure[index] - monitor_survey->pressure[index]); } else { - weight[index] = - scale_factor * cell_volume[index] * (base_survey->pressure[index] ); + weight[index] = scale_factor * cell_volume[index] * (base_survey->pressure[index] ); } } diff --git a/ThirdParty/Ert/libecl/src/ecl_sum_data.c b/ThirdParty/Ert/libecl/src/ecl_sum_data.c index cad70f8c14..c8871fb84d 100644 --- a/ThirdParty/Ert/libecl/src/ecl_sum_data.c +++ b/ThirdParty/Ert/libecl/src/ecl_sum_data.c @@ -324,7 +324,7 @@ ecl_sum_data_type * ecl_sum_data_alloc_writer( ecl_smspec_type * smspec ) { static void ecl_sum_data_fwrite_report__( const ecl_sum_data_type * data , int report_step , fortio_type * fortio) { { - ecl_kw_type * seqhdr_kw = ecl_kw_alloc( SEQHDR_KW , SEQHDR_SIZE , ECL_INT_TYPE ); + ecl_kw_type * seqhdr_kw = ecl_kw_alloc( SEQHDR_KW , SEQHDR_SIZE , ECL_INT ); ecl_kw_iset_int( seqhdr_kw , 0 , 0 ); ecl_kw_fwrite( seqhdr_kw , fortio ); ecl_kw_free( seqhdr_kw ); diff --git a/ThirdParty/Ert/libecl/src/ecl_sum_tstep.c b/ThirdParty/Ert/libecl/src/ecl_sum_tstep.c index cd209fbe46..8228400d02 100644 --- a/ThirdParty/Ert/libecl/src/ecl_sum_tstep.c +++ b/ThirdParty/Ert/libecl/src/ecl_sum_tstep.c @@ -26,6 +26,7 @@ #include #include #include +#include #define ECL_SUM_TSTEP_ID 88631 @@ -270,7 +271,7 @@ int ecl_sum_tstep_get_ministep(const ecl_sum_tstep_type * ministep) { void ecl_sum_tstep_fwrite( const ecl_sum_tstep_type * ministep , const int_vector_type * index_map , fortio_type * fortio) { { - ecl_kw_type * ministep_kw = ecl_kw_alloc( MINISTEP_KW , 1 , ECL_INT_TYPE ); + ecl_kw_type * ministep_kw = ecl_kw_alloc( MINISTEP_KW , 1 , ECL_INT ); ecl_kw_iset_int( ministep_kw , 0 , ministep->ministep ); ecl_kw_fwrite( ministep_kw , fortio ); ecl_kw_free( ministep_kw ); @@ -278,7 +279,7 @@ void ecl_sum_tstep_fwrite( const ecl_sum_tstep_type * ministep , const int_vecto { int compact_size = int_vector_size( index_map ); - ecl_kw_type * params_kw = ecl_kw_alloc( PARAMS_KW , compact_size , ECL_FLOAT_TYPE ); + ecl_kw_type * params_kw = ecl_kw_alloc( PARAMS_KW , compact_size , ECL_FLOAT ); const int * index = int_vector_get_ptr( index_map ); float * data = ecl_kw_get_ptr( params_kw ); diff --git a/ThirdParty/Ert/libecl/src/ecl_type.c b/ThirdParty/Ert/libecl/src/ecl_type.c new file mode 100644 index 0000000000..efb79e29d7 --- /dev/null +++ b/ThirdParty/Ert/libecl/src/ecl_type.c @@ -0,0 +1,172 @@ +/* + Copyright (C) 2017 Statoil ASA, Norway. + + The file 'ecl_type.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 at + for more details. +*/ + +#include +#include + +#include +#include + +/*****************************************************************/ +/* The string names for the different ECLIPSE low-level + types. +*/ +#define ECL_TYPE_NAME_CHAR "CHAR" +#define ECL_TYPE_NAME_C010 "C010" +#define ECL_TYPE_NAME_FLOAT "REAL" +#define ECL_TYPE_NAME_INT "INTE" +#define ECL_TYPE_NAME_DOUBLE "DOUB" +#define ECL_TYPE_NAME_BOOL "LOGI" +#define ECL_TYPE_NAME_MESSAGE "MESS" + + +ecl_data_type ecl_type_create(const ecl_type_enum type, const size_t element_size) { + ecl_data_type ecl_type = ecl_type_create_from_type(type); + + if(ecl_type.element_size != element_size) + util_abort( + "%s: element_size mismatch for type %d, was: %d, expected: %d\n", + __func__, type, element_size, ecl_type.element_size); + + return ecl_type; +} + +ecl_data_type ecl_type_create_from_type(const ecl_type_enum type) { + switch(type) { + case(ECL_CHAR_TYPE): + return ECL_CHAR; + case(ECL_INT_TYPE): + return ECL_INT; + case(ECL_FLOAT_TYPE): + return ECL_FLOAT; + case(ECL_DOUBLE_TYPE): + return ECL_DOUBLE; + case(ECL_BOOL_TYPE): + return ECL_BOOL; + case(ECL_MESS_TYPE): + return ECL_MESS; + case(ECL_C010_TYPE): + return ECL_C010; + default: + util_abort("%s: invalid ecl_type: %d\n", __func__, type); + return ECL_INT; /* Dummy */ + } +} + +ecl_type_enum ecl_type_get_type(const ecl_data_type ecl_type) { + return ecl_type.type; +} + +size_t ecl_type_get_element_size(const ecl_data_type ecl_type) { + return ecl_type.element_size; +} + +const char * ecl_type_get_name(const ecl_data_type ecl_type) { + switch (ecl_type.type) { + case(ECL_CHAR_TYPE): + return ECL_TYPE_NAME_CHAR ; + case(ECL_C010_TYPE): + return ECL_TYPE_NAME_C010; + case(ECL_FLOAT_TYPE): + return ECL_TYPE_NAME_FLOAT; + case(ECL_DOUBLE_TYPE): + return ECL_TYPE_NAME_DOUBLE; + case(ECL_INT_TYPE): + return ECL_TYPE_NAME_INT; + case(ECL_BOOL_TYPE): + return ECL_TYPE_NAME_BOOL; + case(ECL_MESS_TYPE): + return ECL_TYPE_NAME_MESSAGE; + default: + util_abort("Internal error in %s - internal eclipse_type: %d not recognized - aborting \n",__func__ , ecl_type.type); + return NULL; /* Dummy */ + } +} + +ecl_data_type ecl_type_create_from_name( const char * type_name ) { + if (strncmp( type_name , ECL_TYPE_NAME_FLOAT , ECL_TYPE_LENGTH) == 0) + return ECL_FLOAT; + else if (strncmp( type_name , ECL_TYPE_NAME_INT , ECL_TYPE_LENGTH) == 0) + return ECL_INT; + else if (strncmp( type_name , ECL_TYPE_NAME_DOUBLE , ECL_TYPE_LENGTH) == 0) + return ECL_DOUBLE; + else if (strncmp( type_name , ECL_TYPE_NAME_CHAR , ECL_TYPE_LENGTH) == 0) + return ECL_CHAR; + else if (strncmp( type_name , ECL_TYPE_NAME_C010 , ECL_TYPE_LENGTH) == 0) + return ECL_C010; + else if (strncmp( type_name , ECL_TYPE_NAME_MESSAGE , ECL_TYPE_LENGTH) == 0) + return ECL_MESS; + else if (strncmp( type_name , ECL_TYPE_NAME_BOOL , ECL_TYPE_LENGTH) == 0) + return ECL_BOOL; + else { + util_abort("%s: unrecognized type name:%s \n",__func__ , type_name); + return ECL_INT; /* Dummy */ + } +} + + +int ecl_type_get_sizeof_ctype_fortio(const ecl_data_type ecl_type) { + if(ecl_type_is_char(ecl_type) || ecl_type_is_C010(ecl_type)) + return ecl_type.element_size - 1; + else + return ecl_type_get_sizeof_ctype(ecl_type); +} + +int ecl_type_get_sizeof_ctype(const ecl_data_type ecl_type) { + return ecl_type.element_size; +} + +bool ecl_type_is_numeric(const ecl_data_type ecl_type) { + return (ecl_type_is_int(ecl_type) || + ecl_type_is_float(ecl_type) || + ecl_type_is_double(ecl_type)); +} + +bool ecl_type_is_equal(const ecl_data_type ecl_type1, + const ecl_data_type ecl_type2) { + return (ecl_type1.type == ecl_type2.type && + ecl_type1.element_size == ecl_type2.element_size); +} + +bool ecl_type_is_char(const ecl_data_type ecl_type) { + return (ecl_type.type == ECL_CHAR_TYPE); +} + +bool ecl_type_is_int(const ecl_data_type ecl_type) { + return (ecl_type.type == ECL_INT_TYPE); +} + +bool ecl_type_is_float(const ecl_data_type ecl_type) { + return (ecl_type.type == ECL_FLOAT_TYPE); +} + +bool ecl_type_is_double(const ecl_data_type ecl_type) { + return (ecl_type.type == ECL_DOUBLE_TYPE); +} + +bool ecl_type_is_mess(const ecl_data_type ecl_type) { + return (ecl_type.type == ECL_MESS_TYPE); +} + +bool ecl_type_is_bool(const ecl_data_type ecl_type) { + return (ecl_type.type == ECL_BOOL_TYPE); +} + +bool ecl_type_is_C010(const ecl_data_type ecl_type) { + return (ecl_type.type == ECL_C010_TYPE); +} diff --git a/ThirdParty/Ert/libecl/src/ecl_type_python.c b/ThirdParty/Ert/libecl/src/ecl_type_python.c new file mode 100644 index 0000000000..2ad25981d0 --- /dev/null +++ b/ThirdParty/Ert/libecl/src/ecl_type_python.c @@ -0,0 +1,108 @@ +#include +#include +#include + +/** + * + * Functions only to be used by the *PYTHON* prototype for EclDataType + * + */ +ecl_data_type * ecl_type_alloc_copy_python(const ecl_data_type * src_type) { + ecl_data_type * data_type = util_malloc(sizeof * src_type); + memcpy(data_type, src_type, sizeof * data_type); + return data_type; +} + +ecl_data_type * ecl_type_alloc_python(const ecl_type_enum type, const size_t element_size) { + ecl_data_type src_type = ecl_type_create(type, element_size); + return ecl_type_alloc_copy_python(&src_type); +} + +ecl_data_type * ecl_type_alloc_from_type_python(const ecl_type_enum type) { + ecl_data_type src_type = ecl_type_create_from_type(type); + return ecl_type_alloc_copy_python(&src_type); +} + +ecl_data_type * ecl_type_alloc_from_name_python(const char * name) { + ecl_data_type src_type = ecl_type_create_from_name(name); + return ecl_type_alloc_copy_python(&src_type); +} + +void ecl_type_free_python(ecl_data_type * data_type) { + free(data_type); +} + +ecl_type_enum ecl_type_get_type_python(const ecl_data_type * ecl_type) { + return ecl_type_get_type(*ecl_type); +} + +const char * ecl_type_get_name_python(const ecl_data_type * ecl_type) { + return ecl_type_get_name(*ecl_type); +} + +int ecl_type_get_sizeof_ctype_fortio_python(const ecl_data_type * ecl_type) { + return ecl_type_get_sizeof_ctype_fortio(*ecl_type); +} + +int ecl_type_get_sizeof_ctype_python(const ecl_data_type * ecl_type) { + return ecl_type_get_sizeof_ctype(*ecl_type); +} + +bool ecl_type_is_numeric_python(const ecl_data_type * ecl_type) { + return ecl_type_is_numeric(*ecl_type); +} + +bool ecl_type_is_equal_python(const ecl_data_type * ecl_type1, + const ecl_data_type * ecl_type2) { + return ecl_type_is_equal(*ecl_type1, *ecl_type2); +} + +bool ecl_type_is_char_python(const ecl_data_type * ecl_type) { + return ecl_type_is_char(*ecl_type); +} + +bool ecl_type_is_int_python(const ecl_data_type * ecl_type) { + return ecl_type_is_int(*ecl_type); +} + +bool ecl_type_is_float_python(const ecl_data_type * ecl_type) { + return ecl_type_is_float(*ecl_type); +} + +bool ecl_type_is_double_python(const ecl_data_type * ecl_type) { + return ecl_type_is_double(*ecl_type); +} + +bool ecl_type_is_mess_python(const ecl_data_type * ecl_type) { + return ecl_type_is_mess(*ecl_type); +} + +bool ecl_type_is_bool_python(const ecl_data_type * ecl_type) { + return ecl_type_is_bool(*ecl_type); +} + +bool ecl_type_is_C010_python(const ecl_data_type * ecl_type) { + return ecl_type_is_C010(*ecl_type); +} + +/** + * + * Functions for the EclKw prototype + * + */ +ecl_kw_type * ecl_kw_fscanf_alloc_grdecl_dynamic_python( FILE * stream , const char * kw , bool strict , const ecl_data_type * data_type) { + return ecl_kw_fscanf_alloc_grdecl_dynamic__( stream , kw , strict, *data_type ); +} + +ecl_kw_type * ecl_kw_alloc_python( const char * header , int size , const ecl_data_type * data_type ) { + return ecl_kw_alloc(header, size, *data_type); +} + +ecl_data_type * ecl_kw_get_data_type_python( const ecl_kw_type * ecl_kw ) { + ecl_data_type data_type = ecl_kw_get_data_type(ecl_kw); + return ecl_type_alloc_copy_python(&data_type); +} + +void ecl_kw_fread_indexed_data_python(fortio_type * fortio, offset_type data_offset, const ecl_data_type * data_type, int element_count, const int_vector_type* index_map, char* buffer) { + return ecl_kw_fread_indexed_data(fortio, data_offset, *data_type, element_count, index_map, buffer); +} diff --git a/ThirdParty/Ert/libecl/src/ecl_util.c b/ThirdParty/Ert/libecl/src/ecl_util.c index 4b2e4c6842..6e11822ffb 100644 --- a/ThirdParty/Ert/libecl/src/ecl_util.c +++ b/ThirdParty/Ert/libecl/src/ecl_util.c @@ -30,6 +30,7 @@ #include #include +#include /*****************************************************************/ @@ -106,121 +107,6 @@ const char * ecl_util_get_phase_name( ecl_phase_enum phase ) { } - - - -const char * ecl_util_get_type_name( ecl_type_enum ecl_type ) { - switch (ecl_type) { - case(ECL_CHAR_TYPE): - return ECL_TYPE_NAME_CHAR ; - break; - case(ECL_C010_TYPE): - return ECL_TYPE_NAME_C010; - break; - case(ECL_FLOAT_TYPE): - return ECL_TYPE_NAME_FLOAT; - break; - case(ECL_DOUBLE_TYPE): - return ECL_TYPE_NAME_DOUBLE; - break; - case(ECL_INT_TYPE): - return ECL_TYPE_NAME_INT; - break; - case(ECL_BOOL_TYPE): - return ECL_TYPE_NAME_BOOL; - break; - case(ECL_MESS_TYPE): - return ECL_TYPE_NAME_MESSAGE; - break; - default: - util_abort("Internal error in %s - internal eclipse_type: %d not recognized - aborting \n",__func__ , ecl_type); - } - return NULL; /* Dummy */ -} - - -ecl_type_enum ecl_util_get_type_from_name( const char * type_name ) { - ecl_type_enum ecl_type; - - if (strncmp( type_name , ECL_TYPE_NAME_FLOAT , ECL_TYPE_LENGTH) == 0) - ecl_type = ECL_FLOAT_TYPE; - else if (strncmp( type_name , ECL_TYPE_NAME_INT , ECL_TYPE_LENGTH) == 0) - ecl_type = ECL_INT_TYPE; - else if (strncmp( type_name , ECL_TYPE_NAME_DOUBLE , ECL_TYPE_LENGTH) == 0) - ecl_type = ECL_DOUBLE_TYPE; - else if (strncmp( type_name , ECL_TYPE_NAME_CHAR , ECL_TYPE_LENGTH) == 0) - ecl_type = ECL_CHAR_TYPE; - else if (strncmp( type_name , ECL_TYPE_NAME_C010 , ECL_TYPE_LENGTH) == 0) - ecl_type = ECL_C010_TYPE; - else if (strncmp( type_name , ECL_TYPE_NAME_MESSAGE , ECL_TYPE_LENGTH) == 0) - ecl_type = ECL_MESS_TYPE; - else if (strncmp( type_name , ECL_TYPE_NAME_BOOL , ECL_TYPE_LENGTH) == 0) - ecl_type = ECL_BOOL_TYPE; - else { - util_abort("%s: unrecognized type name:%s \n",__func__ , type_name); - ecl_type = -1; /* Dummy */ - } - return ecl_type; -} - - -int ecl_util_get_sizeof_ctype_fortio(ecl_type_enum ecl_type) { - int size = ecl_util_get_sizeof_ctype ( ecl_type ); - if (ecl_type == ECL_CHAR_TYPE) - size = ECL_STRING8_LENGTH * sizeof(char); - - if (ecl_type == ECL_C010_TYPE) - size = ECL_STRING10_LENGTH * sizeof(char); - - return size; -} - -int ecl_util_get_sizeof_ctype(ecl_type_enum ecl_type) { - int sizeof_ctype = -1; - switch (ecl_type) { - case(ECL_CHAR_TYPE): - /* - One element of character data is a string section of 8 - characters + \0. Observe that the return value here - corresponds to the size requirements of ECL_CHAR_TYPE instance - in memory; on disk the trailing \0 is not stored. - */ - sizeof_ctype = (ECL_STRING8_LENGTH + 1) * sizeof(char); - break; - case(ECL_C010_TYPE): - /* - One element of character data is a string section of 8 - characters + \0. Observe that the return value here - corresponds to the size requirements of ECL_CHAR_TYPE instance - in memory; on disk the trailing \0 is not stored. - */ - sizeof_ctype = (ECL_STRING10_LENGTH + 1) * sizeof(char); - break; - case(ECL_FLOAT_TYPE): - sizeof_ctype = sizeof(float); - break; - case(ECL_DOUBLE_TYPE): - sizeof_ctype = sizeof(double); - break; - case(ECL_INT_TYPE): - sizeof_ctype = sizeof(int); - break; - case(ECL_BOOL_TYPE): - sizeof_ctype = sizeof(int); // The ECL_BOOL_TYPE type is internally implemented as an integer - and not a bool. - break; - case(ECL_MESS_TYPE): - sizeof_ctype = sizeof(char); - break; - default: - util_abort("Internal error in %s - internal eclipse_type: %d not recognized - aborting \n",__func__ , ecl_type); - } - return sizeof_ctype; -} - - - - - /*****************************************************************/ @@ -741,7 +627,7 @@ bool ecl_util_fmt_file(const char *filename , bool * __fmt_file) { int report_nr; ecl_file_enum file_type; bool status = true; - bool fmt_file; + bool fmt_file = 0; if (util_file_exists(filename)) { file_type = ecl_util_get_file_type(filename , &fmt_file , &report_nr); @@ -774,17 +660,17 @@ bool ecl_util_fmt_file(const char *filename , bool * __fmt_file) { appropriate numerical conversion is applied. */ -void ecl_util_memcpy_typed_data(void *_target_data , const void * _src_data , ecl_type_enum target_type , ecl_type_enum src_type, int size) { +void ecl_util_memcpy_typed_data(void *_target_data , const void * _src_data , ecl_data_type target_type , ecl_data_type src_type, int size) { int i; - if (target_type == src_type) - memcpy(_target_data , _src_data , size * ecl_util_get_sizeof_ctype(src_type)); + if (ecl_type_is_equal(target_type, src_type)) + memcpy(_target_data , _src_data , size * ecl_type_get_sizeof_ctype(src_type)); else { - switch (target_type) { + switch (ecl_type_get_type(target_type)) { case(ECL_DOUBLE_TYPE): { double * target_data = (double *) _target_data; - switch(src_type) { + switch(ecl_type_get_type(src_type)) { case(ECL_FLOAT_TYPE): util_float_to_double(target_data , (const float *) _src_data , size); break; @@ -800,7 +686,7 @@ void ecl_util_memcpy_typed_data(void *_target_data , const void * _src_data , ec case(ECL_FLOAT_TYPE): { float * target_data = (float *) _target_data; - switch(src_type) { + switch(ecl_type_get_type(src_type)) { case(ECL_FLOAT_TYPE): util_double_to_float(target_data , (const double *) _src_data , size); break; @@ -814,7 +700,7 @@ void ecl_util_memcpy_typed_data(void *_target_data , const void * _src_data , ec break; } default: - util_abort("%s con not convert %d -> %d \n",__func__ , src_type , target_type); + util_abort("%s con not convert %s -> %s \n",__func__ , ecl_type_get_name(src_type) , ecl_type_get_name(target_type)); } } } diff --git a/ThirdParty/Ert/libecl/src/fault_block_layer.c b/ThirdParty/Ert/libecl/src/fault_block_layer.c index 0c458eb470..87c899f118 100644 --- a/ThirdParty/Ert/libecl/src/fault_block_layer.c +++ b/ThirdParty/Ert/libecl/src/fault_block_layer.c @@ -130,7 +130,7 @@ bool fault_block_layer_scan_kw( fault_block_layer_type * layer , const ecl_kw_ty if (ecl_kw_get_size( fault_block_kw) != ecl_grid_get_global_size(layer->grid)) return false; - else if (ecl_kw_get_type( fault_block_kw ) != ECL_INT_TYPE) + else if (!ecl_type_is_int(ecl_kw_get_data_type( fault_block_kw ))) return false; else { int i,j; @@ -171,7 +171,7 @@ bool fault_block_layer_scan_kw( fault_block_layer_type * layer , const ecl_kw_ty bool fault_block_layer_load_kw( fault_block_layer_type * layer , const ecl_kw_type * fault_block_kw) { if (ecl_kw_get_size( fault_block_kw) != ecl_grid_get_global_size(layer->grid)) return false; - else if (ecl_kw_get_type( fault_block_kw ) != ECL_INT_TYPE) + else if (!ecl_type_is_int(ecl_kw_get_data_type( fault_block_kw ))) return false; else { int i,j; @@ -316,7 +316,7 @@ void fault_block_layer_insert_block_content( fault_block_layer_type * layer , co bool fault_block_layer_export( const fault_block_layer_type * layer , ecl_kw_type * faultblock_kw) { - if ((ecl_kw_get_type( faultblock_kw ) == ECL_INT_TYPE) && (ecl_kw_get_size( faultblock_kw ) == ecl_grid_get_global_size( layer->grid ))) { + if (ecl_type_is_int(ecl_kw_get_data_type( faultblock_kw )) && (ecl_kw_get_size( faultblock_kw ) == ecl_grid_get_global_size( layer->grid ))) { int i,j; for (j=0; j < ecl_grid_get_ny( layer->grid ); j++) { diff --git a/ThirdParty/Ert/libecl/tests/CMakeLists.txt b/ThirdParty/Ert/libecl/tests/CMakeLists.txt index edad35ed31..62aa9a50c2 100644 --- a/ThirdParty/Ert/libecl/tests/CMakeLists.txt +++ b/ThirdParty/Ert/libecl/tests/CMakeLists.txt @@ -1,4 +1,9 @@ if (BUILD_TESTS) + + # Common test binary used in both the Statoil internal tests and the open tests. + add_executable( ecl_grid_cell_contains ecl_grid_cell_contains.c ) + target_link_libraries( ecl_grid_cell_contains ecl ) + include( tests.cmake ) if (STATOIL_TESTDATA_ROOT) include (statoil_tests.cmake) diff --git a/ThirdParty/Ert/libecl/tests/ecl_alloc_cpgrid.c b/ThirdParty/Ert/libecl/tests/ecl_alloc_cpgrid.c new file mode 100644 index 0000000000..e9417f887b --- /dev/null +++ b/ThirdParty/Ert/libecl/tests/ecl_alloc_cpgrid.c @@ -0,0 +1,112 @@ +/* + Copyright (C) 2017 Statoil ASA, Norway. + + The file 'ecl_alloc_cpgrid.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 at + for more details. +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include + + +void test_grid(int nx, int ny, int nz) { + ecl_kw_type * coord_kw = ecl_kw_alloc( COORD_KW , ECL_GRID_COORD_SIZE( nx , ny ) , ECL_FLOAT ); + ecl_kw_type * zcorn_kw = ecl_kw_alloc( ZCORN_KW , ECL_GRID_ZCORN_SIZE( nx , ny , nz) , ECL_FLOAT ); + int i,j,k; + double a = 1.0; + for (j= 0; j < ny; j++) { + for (i = 0; i < nx; i++) { + int offset = 6*(i + j*nx); + ecl_kw_iset_float( coord_kw , offset , a*i); + ecl_kw_iset_float( coord_kw , offset + 1, a*j); + ecl_kw_iset_float( coord_kw , offset + 2, -1); + + ecl_kw_iset_float( coord_kw , offset + 3, a*i); + ecl_kw_iset_float( coord_kw , offset + 4, a*j); + ecl_kw_iset_float( coord_kw , offset + 5, -1); + + for (k=0; k < nz; k++) { + for (int c = 0; c < 4; c++) { + int zi1 = ecl_grid_zcorn_index__( nx , ny , i , j , k , c); + int zi2 = ecl_grid_zcorn_index__( nx , ny , i , j , k , c + 4); + + double z1 = k*a; + double z2 = (k + 1) * a; + + ecl_kw_iset_float( zcorn_kw , zi1 , z1 ); + ecl_kw_iset_float( zcorn_kw , zi2 , z2 ); + } + } + } + } + + + { + ecl_grid_type * grid = ecl_grid_alloc_GRDECL_kw( nx,ny,nz, zcorn_kw , coord_kw , NULL, NULL ); + test_assert_int_equal( ecl_grid_get_cell_twist3( grid , 0,0,0) , 0 ); + ecl_grid_free( grid ); + } + + + { + int zi1 = ecl_grid_zcorn_index__( nx , ny , 0 , 0 , 0 , 0); + int zi2 = ecl_grid_zcorn_index__( nx , ny , 0 , 0 , 0 , 4); + + double z1 = 0; + double z2 = -0.25; + + ecl_kw_iset_float( zcorn_kw , zi1 , z1 ); + ecl_kw_iset_float( zcorn_kw , zi2 , z2 ); + + { + ecl_grid_type * grid = ecl_grid_alloc_GRDECL_kw( nx,ny,nz, zcorn_kw , coord_kw , NULL, NULL ); + test_assert_int_equal( ecl_grid_get_cell_twist3( grid , 0,0,0) , 1 ); + ecl_grid_free( grid ); + } + + zi1 = ecl_grid_zcorn_index__( nx , ny , 0 , 0 , 0 , 3); + zi2 = ecl_grid_zcorn_index__( nx , ny , 0 , 0 , 0 , 7); + + ecl_kw_iset_float( zcorn_kw , zi1 , z1 ); + ecl_kw_iset_float( zcorn_kw , zi2 , z2 ); + + { + ecl_grid_type * grid = ecl_grid_alloc_GRDECL_kw( nx,ny,nz, zcorn_kw , coord_kw , NULL, NULL ); + test_assert_int_equal( ecl_grid_get_cell_twist3( grid , 0,0,0) , 2 ); + ecl_grid_free( grid ); + } + } + + + ecl_kw_free( coord_kw ); + ecl_kw_free( zcorn_kw ); +} + + +int main(int argc , char ** argv) { + int nx = 10; + int ny = 7; + int nz = 8; + + test_grid( nx,ny,nz ); + + exit(0); +} diff --git a/ThirdParty/Ert/libecl/tests/ecl_fault_block_layer.c b/ThirdParty/Ert/libecl/tests/ecl_fault_block_layer.c index 08917065df..37e0184688 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_fault_block_layer.c +++ b/ThirdParty/Ert/libecl/tests/ecl_fault_block_layer.c @@ -26,6 +26,7 @@ #include #include #include +#include @@ -62,7 +63,7 @@ void test_create( const ecl_grid_type * grid , ecl_kw_type * fault_block_kw) { void test_create_invalid( const ecl_grid_type * grid ) { - ecl_kw_type * fault_blk_kw = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( grid ) - 1, ECL_INT_TYPE ); + ecl_kw_type * fault_blk_kw = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( grid ) - 1, ECL_INT); test_assert_NULL( fault_block_layer_alloc( grid , 7 )); @@ -105,9 +106,9 @@ void test_trace_edge( const ecl_grid_type * grid) { void test_export( const ecl_grid_type * grid) { fault_block_layer_type * layer = fault_block_layer_alloc( grid , 0 ); - ecl_kw_type * ecl_kw1 = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( grid ) , ECL_INT_TYPE ); - ecl_kw_type * ecl_kw2 = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( grid ) + 1 , ECL_INT_TYPE ); - ecl_kw_type * ecl_kw3 = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( grid ) , ECL_FLOAT_TYPE ); + ecl_kw_type * ecl_kw1 = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( grid ) , ECL_INT); + ecl_kw_type * ecl_kw2 = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( grid ) + 1 , ECL_INT); + ecl_kw_type * ecl_kw3 = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( grid ) , ECL_FLOAT); fault_block_type * block = fault_block_layer_add_block( layer , 10 ); fault_block_add_cell( block , 0 , 0 ); @@ -141,7 +142,7 @@ void test_neighbours( const ecl_grid_type * grid) { const int k = 0; fault_block_layer_type * layer = fault_block_layer_alloc( grid , k ); geo_polygon_collection_type * polylines = geo_polygon_collection_alloc(); - ecl_kw_type * ecl_kw = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( grid ) , ECL_INT_TYPE ); + ecl_kw_type * ecl_kw = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( grid ) , ECL_INT); ecl_kw_iset_int( ecl_kw , 0 , 1); ecl_kw_iset_int( ecl_kw , ecl_grid_get_global_index3( grid , 3,3,k) , 2); @@ -181,7 +182,7 @@ void test_neighbours( const ecl_grid_type * grid) { int main(int argc , char ** argv) { ecl_grid_type * ecl_grid = ecl_grid_alloc_rectangular( 9 , 9 , 2 , 1 , 1 , 1 , NULL ); - ecl_kw_type * fault_blk_kw = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( ecl_grid ) , ECL_INT_TYPE ); + ecl_kw_type * fault_blk_kw = ecl_kw_alloc("FAULTBLK" , ecl_grid_get_global_size( ecl_grid ) , ECL_INT); test_create( ecl_grid , fault_blk_kw ); test_create_invalid( ecl_grid ); diff --git a/ThirdParty/Ert/libecl/tests/ecl_fault_block_layer_statoil.c b/ThirdParty/Ert/libecl/tests/ecl_fault_block_layer_statoil.c index c14b094090..9fc2581572 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_fault_block_layer_statoil.c +++ b/ThirdParty/Ert/libecl/tests/ecl_fault_block_layer_statoil.c @@ -74,7 +74,7 @@ int main(int argc , char ** argv) { ecl_kw_type * fault_blk_kw; { FILE * stream = util_fopen( fault_blk_file , "r"); - fault_blk_kw = ecl_kw_fscanf_alloc_grdecl( stream , "FAULTBLK" , ecl_grid_get_global_size( ecl_grid ) , ECL_INT_TYPE); + fault_blk_kw = ecl_kw_fscanf_alloc_grdecl( stream , "FAULTBLK" , ecl_grid_get_global_size( ecl_grid ) , ECL_INT); fclose( stream ); } diff --git a/ThirdParty/Ert/libecl/tests/ecl_fortio.c b/ThirdParty/Ert/libecl/tests/ecl_fortio.c index d675c9f2a3..c722d49abd 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_fortio.c +++ b/ThirdParty/Ert/libecl/tests/ecl_fortio.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff --git a/ThirdParty/Ert/libecl/tests/ecl_grid_cell_contains.c b/ThirdParty/Ert/libecl/tests/ecl_grid_cell_contains.c index fe9b17a2fe..b2aa88e501 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_grid_cell_contains.c +++ b/ThirdParty/Ert/libecl/tests/ecl_grid_cell_contains.c @@ -1,29 +1,70 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. - + Copyright (C) 2014 Statoil ASA, Norway. + The file 'ecl_grid_cell_contains.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. + + ERT 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. + + ERT 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 at + for more details. */ #include #include +#include #include #include +bool get_test_point1(const ecl_grid_type * grid , int global_index, double *_xpos , double *_ypos , double *_zpos) { + const int corners[4] = {1,2,5,6}; + double xpos = 0; + double ypos = 0; + double zpos = 0; + const double min_volume = 1e-8; + + if (fabs(ecl_grid_get_cell_volume1( grid , global_index )) <= min_volume) + return false; + + if (ecl_grid_get_cell_twist1( grid , global_index ) > 0) + return false; + + if (!ecl_grid_cell_regular1( grid , global_index )) + return false; + + + for (int ci = 0; ci < 4; ci++) { + int corner = corners[ci]; + double x,y,z; + ecl_grid_get_cell_corner_xyz1( grid , global_index, corner , &x, &y , &z); + xpos += x; + ypos += y; + zpos += z; + } + + *_xpos = xpos * 0.25; + *_ypos = ypos * 0.25; + *_zpos = zpos * 0.25; + + return ecl_grid_cell_contains_xyz1(grid, global_index, *_xpos, *_ypos, *_zpos); +} + + +bool get_test_point3(const ecl_grid_type * grid , int i , int j ,int k, double *_xpos , double *_ypos , double *_zpos) { + const int global_index = ecl_grid_get_global_index3(grid , i , j , k ); + return get_test_point1( grid , global_index , _xpos , _ypos , _zpos); +} + + void test_grid_covering( const ecl_grid_type * grid) { const int nx = ecl_grid_get_nx( grid ); const int ny = ecl_grid_get_ny( grid ); @@ -44,12 +85,12 @@ void test_grid_covering( const ecl_grid_type * grid) { test_assert_true( p1[ 1 ] == p2[ 1 ] ); test_assert_true( p1[ 2 ] == p2[ 2 ] ); } - - + + for (int l=0; l < 4; l++) { ecl_grid_get_cell_corner_xyz1( grid , g1 , l, &p1[0], &p1[1], &p1[2] ); ecl_grid_get_cell_corner_xyz1( grid , g1 , l + 4 , &p2[0], &p2[1], &p2[2] ); - + test_assert_true( p2[2] >= p1[2] ); } } @@ -59,53 +100,54 @@ void test_grid_covering( const ecl_grid_type * grid) { -void test_contains_count( const ecl_grid_type * grid ) { - int error_count = 0; +void assert_contains( const ecl_grid_type * grid , int i , int j , int k , double x , double y , double z) { + if (!ecl_grid_cell_contains_xyz3( grid , i,j,k , x,y, z )) + fprintf(stderr," Point: (%g,%g,%g) not found in cell: (%d,%d,%d) \n",x,y,z,i,j,k); + + test_assert_true( ecl_grid_cell_contains_xyz3( grid , i,j,k , x,y, z )); +} + + +void test_contains( const ecl_grid_type * grid ) { const int nx = ecl_grid_get_nx( grid ); const int ny = ecl_grid_get_ny( grid ); const int nz = ecl_grid_get_nz( grid ); for (int k=0; k < nz; k++) { - printf("k: %d/%d \n", k , nz - 1); for (int j=0; j < ny; j++) { for (int i=0; i < nx; i++) { - double x,y,z; - ecl_grid_get_xyz3( grid , i,j,k , &x,&y,&z); - { - int i2,j2,k2; - int contains_count = 0; - int kmin = util_int_max( 0 , k - 1 ); - int kmax = util_int_min( nz , k + 1 ); - - int jmin = util_int_max( 0 , j - 1 ); - int jmax = util_int_min( ny , j + 1 ); + if (!ecl_grid_get_cell_twist3( grid , i,j,k) == 0) { + double x,y,z; + if (get_test_point3( grid , i,j,k , &x,&y,&z)) { + assert_contains( grid , i , j , k , x , y , z); + { + int i2,j2,k2; + int kmin = util_int_max( 0 , k - 1 ); + int kmax = util_int_min( nz , k + 1 ); - int imin = util_int_max( 0 , i - 1 ); - int imax = util_int_min( nx , i + 1 ); - + int jmin = util_int_max( 0 , j - 1 ); + int jmax = util_int_min( ny , j + 1 ); - for (k2 = kmin; k2 < kmax; k2++) { - for (j2 = jmin; j2 < jmax; j2++) { - for (i2 = imin; i2 < imax; i2++) { - if (ecl_grid_cell_contains_xyz3( grid , i2,j2,k2 , x,y, z )) { - contains_count++; + int imin = util_int_max( 0 , i - 1 ); + int imax = util_int_min( nx , i + 1 ); + + + for (k2 = kmin; k2 < kmax; k2++) { + for (j2 = jmin; j2 < jmax; j2++) { + for (i2 = imin; i2 < imax; i2++) { + if ( (i != i2) && (j != j2 ) && (k != k2)) { + if (ecl_grid_get_cell_twist3( grid , i2,j2,k2) == 0) + test_assert_false( ecl_grid_cell_contains_xyz3( grid , i2,j2,k2 , x,y, z ) ); + } + } } } } } - - if (contains_count != 1) { - if (contains_count > 1) - error_count += 1; - else - if (ecl_grid_cell_regular3( grid , i,j,k)) - error_count += 1; - } } } } } - test_assert_int_equal( error_count , 0 ); } @@ -115,91 +157,30 @@ void test_find( ecl_grid_type * grid ) { int find_count = 100; int delta = util_int_max(1 , ecl_grid_get_global_size( grid ) / find_count); for (init_index = 0; init_index < ecl_grid_get_global_size( grid ); init_index += delta) { - printf("find index:%d \n",init_index / delta); - if (!ecl_grid_cell_invalid1(grid , init_index) && ecl_grid_cell_regular1( grid , init_index) ) { + if (ecl_grid_get_cell_twist1( grid , init_index ) == 0) { double x,y,z; int find_index; int start_index = 0; - - ecl_grid_get_xyz1( grid , init_index , &x,&y,&z); - find_index = ecl_grid_get_global_index_from_xyz(grid , x, y , z , start_index ); - test_assert_int_equal(init_index , find_index ); + + if (get_test_point1( grid , init_index , &x,&y,&z)) { + find_index = ecl_grid_get_global_index_from_xyz(grid , x, y , z , start_index ); + if (init_index != find_index) { + int i1,j1,k1,i2,j2,k2; + + ecl_grid_get_ijk1( grid , init_index , &i1,&j1,&k1); + ecl_grid_get_ijk1( grid , find_index , &i2,&j2,&k2); + printf(" point: %14.7f %14.7f %14.7f \n",x,y,z); + printf(" Regular: %d / %d \n",ecl_grid_cell_regular3(grid , i1,j1,k1) , ecl_grid_cell_regular3(grid , i2,j2,k2)); + printf(" init: contains(%7d) : %d (%d,%d,%d) V:%g \n",init_index , ecl_grid_cell_contains_xyz1( grid , init_index ,x , y , z), i1+1,j1+1,k1+1, ecl_grid_get_cell_volume1( grid , init_index)); + printf("ERROR: find: contains(%7d) : %d (%d,%d,%d) V:%g \n\n",find_index , ecl_grid_cell_contains_xyz1( grid , find_index ,x , y , z), i2+1,j2+1,k2+1,ecl_grid_get_cell_volume1( grid , find_index)); + test_assert_int_equal(init_index , find_index ); + } + } } } } -// /* -// Will indeed answer yes when asked if it contains it's own center. -// */ -// test_assert_true( ecl_grid_cell_contains_xyz1( grid , init_index , x,y,z) ); -// -// if (1) -// { -// int start_index = 0; -// -// if (find_index != init_index) { -// int init_ijk[3]; -// int find_ijk[3]; -// -// ecl_grid_get_ijk1( grid , find_index , &find_ijk[0] , &find_ijk[1] , &find_ijk[2]); -// ecl_grid_get_ijk1( grid , init_index , &init_ijk[0] , &init_ijk[1] , &init_ijk[2]); -// -// printf("ijk: %d:(%2d,%2d,%2d) -> %d:(%2d,%2d,%2d) \n",init_index , init_ijk[0] , init_ijk[1] , init_ijk[2] , find_index , find_ijk[0] , find_ijk[1], find_ijk[2]); -// global_error += 1; -// } -// -// if (0) { -// //if (find_index != init_index) { -// int init_ijk[3]; -// int find_ijk[3]; -// -// ecl_grid_get_ijk1( grid , find_index , &find_ijk[0] , &find_ijk[1] , &find_ijk[2]); -// ecl_grid_get_ijk1( grid , init_index , &init_ijk[0] , &init_ijk[1] , &init_ijk[2]); -// -// { -// printf("ijk: (%2d,%2d,%2d) -> (%2d,%2d,%2d) \n",init_ijk[0] , init_ijk[1] , init_ijk[2] , find_ijk[0] , find_ijk[1], find_ijk[2]); -// -// if (0) { -// printf(" ecl_grid_cell_contains_xyz3(%d,%d,%d) : %d Volume:%g \n",init_ijk[0] , init_ijk[1], init_ijk[2] , -// ecl_grid_cell_contains_xyz3( grid , init_ijk[0] , init_ijk[1], init_ijk[2] , x , y , z ), -// ecl_grid_get_cell_volume1( grid , init_index)); -// -// printf(" ecl_grid_cell_contains_xyz3(%d,%d,%d) : %d Volume:%g \n",find_ijk[0] , find_ijk[1], find_ijk[2] , -// ecl_grid_cell_contains_xyz3( grid , find_ijk[0] , find_ijk[1], find_ijk[2] , x , y , z ), -// ecl_grid_get_cell_volume1( grid , find_index)); -// } -// -// { -// int find_index2 = ecl_grid_get_global_index_from_xyz(grid , x, y , z , init_index ); -// printf("find_index2:%d \n",find_index2); -// } -// -// printf("init_index:%d find_index:%d \n",init_index , find_index); -// if (find_index >= 0) -// printf("Vrengte: %d\n",ecl_grid_cell_inside_out1( grid , find_index)); -// printf("Vrengte: %d\n",ecl_grid_cell_inside_out1( grid , init_index)); -// -// { -// bool init_cell_inside_out = ecl_grid_cell_inside_out1( grid , init_index); -// bool find_cell_inside_out = false; -// -// if (find_index >= 0) -// find_cell_inside_out = ecl_grid_cell_inside_out1( grid , find_index ); -// else -// test_assert_int_not_equal( -1 , find_index ); -// -// if (find_cell_inside_out == init_cell_inside_out) { -// if (init_cell_inside_out == false) -// test_assert_int_equal( init_index , find_index ); -// } -// } -// } -// } -// } -// } -// } -//} void test_corners() { @@ -225,7 +206,7 @@ void test_corners() { ecl_grid_get_cell_corner_xyz3( grid , 0, 0, 0 , i , &x , &y , &z); test_assert_int_not_equal( 0 , ecl_grid_get_global_index_from_xyz( grid , x,y,z,0)); } - + // Corner 1 ecl_grid_get_cell_corner_xyz3(grid , 2,0,0,1 , &x,&y,&z); test_assert_int_equal( ecl_grid_get_global_index3( grid , 2,0,0 ) , ecl_grid_get_global_index_from_xyz( grid , x,y,z,0)); @@ -254,7 +235,7 @@ void test_corners() { ecl_grid_get_cell_corner_xyz3(grid , 2,2,2,7 , &x,&y,&z); test_assert_int_equal( ecl_grid_get_global_index3( grid , 2,2,2 ) , ecl_grid_get_global_index_from_xyz( grid , x,y,z,0)); } - + ecl_grid_free( grid ); } @@ -265,19 +246,17 @@ void test_corners() { int main(int argc , char ** argv) { ecl_grid_type * grid; - int case_nr; util_install_signals(); - util_sscanf_int( argv[1] , &case_nr ); - if (argc == 2) { + if (argc == 1) { grid = ecl_grid_alloc_rectangular(6,6,6,1,2,3,NULL); } else - grid = ecl_grid_alloc( argv[2] ); - + grid = ecl_grid_alloc( argv[1] ); + test_grid_covering( grid ); - test_contains_count( grid ); - + test_contains( grid ); + test_find(grid); test_corners(); diff --git a/ThirdParty/Ert/libecl/tests/ecl_grid_cell_contains_wellpath.c b/ThirdParty/Ert/libecl/tests/ecl_grid_cell_contains_wellpath.c new file mode 100644 index 0000000000..0afc83b1c1 --- /dev/null +++ b/ThirdParty/Ert/libecl/tests/ecl_grid_cell_contains_wellpath.c @@ -0,0 +1,101 @@ +/* + Copyright (C) 2017 Statoil ASA, Norway. + + The file 'ecl_grid_cell_contains_wellpath.c' is part of ERT - + Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 at + for more details. +*/ + +#include +#include +#include + +#include +#include +#include + + +typedef struct { + double x; + double y; + double z; + + int g; + int i; + int j; + int k; + + bool skip; +} point_type; + + + +vector_type * load_expected( const ecl_grid_type * grid, const char * filename ) { + FILE * stream = util_fopen( filename , "r"); + vector_type * expected = vector_alloc_new(); + + while (true) { + double x,y,z; + int i,j,k,skip; + + if (fscanf( stream , "%lg %lg %lg %d %d %d %d" , &x,&y,&z,&i,&j,&k,&skip) == 7) { + point_type * p = util_malloc( sizeof * p ); + p->x = x; + p->y = y; + p->z = z; + + p->i = i-1; + p->j = j-1; + p->k = k-1; + p->skip = skip; + p->g = ecl_grid_get_global_index3(grid, p->i, p->j, p->k); + vector_append_owned_ref( expected, p , free ); + } else + break; + } + + fclose( stream ); + test_assert_int_equal( 10 , vector_get_size( expected )); + return expected; +} + + + +int main(int argc , char ** argv) { + util_install_signals(); + { + ecl_grid_type * grid = ecl_grid_alloc( argv[1] ); + vector_type * expected = load_expected( grid, argv[2] ); + + for (int c=0; c < vector_get_size( expected ); c++) { + const point_type * p = vector_iget_const( expected , c ); + int g = ecl_grid_get_global_index_from_xyz(grid , p->x, p->y , p->z , 0 ); + if (g != ecl_grid_get_global_index3(grid, p->i,p->j, p->k)) { + int i,j,k; + ecl_grid_get_ijk1(grid, g, &i, &j, &k); + fprintf(stderr,"point:%d (%g,%g,%g), Simulated: %d:(%d,%d,%d) Expected: %d:(%d,%d,%d) contains:%d\n", + c , p->x, p->y, p->z, g, i,j,k, p->g, p->i, p->j, p->k, ecl_grid_cell_contains_xyz1( grid, p->g , p->x , p->y, p->z)); + } + if (!p->skip) + test_assert_int_equal( g , ecl_grid_get_global_index3(grid, p->i,p->j, p->k)); + else { + if ( g != ecl_grid_get_global_index3(grid, p->i,p->j, p->k)) + fprintf(stderr," ** Skipping failed test for point:%d \n",c); + } + } + ecl_grid_free( grid ); + vector_free( expected ); + } + exit(0); +} diff --git a/ThirdParty/Ert/libecl/tests/ecl_grid_corner.c b/ThirdParty/Ert/libecl/tests/ecl_grid_corner.c index eb98690b22..b4adf52270 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_grid_corner.c +++ b/ThirdParty/Ert/libecl/tests/ecl_grid_corner.c @@ -19,7 +19,6 @@ #include #include -#include #include diff --git a/ThirdParty/Ert/libecl/tests/ecl_init_file.c b/ThirdParty/Ert/libecl/tests/ecl_init_file.c index 12493ce49b..0e3d3978d8 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_init_file.c +++ b/ThirdParty/Ert/libecl/tests/ecl_init_file.c @@ -28,6 +28,7 @@ #include #include #include +#include void test_write_header() { @@ -48,7 +49,7 @@ void test_write_header() { // Write poro with global size. { fortio_type * f = fortio_open_writer( "FOO1.INIT" , false , ECL_ENDIAN_FLIP ); - ecl_kw_type * poro = ecl_kw_alloc( "PORO" , ecl_grid_get_global_size( ecl_grid ) , ECL_FLOAT_TYPE ); + ecl_kw_type * poro = ecl_kw_alloc( "PORO" , ecl_grid_get_global_size( ecl_grid ) , ECL_FLOAT); ecl_kw_scalar_set_float( poro , 0.10 ); ecl_init_file_fwrite_header( f , ecl_grid , poro , ECL_FIELD_UNITS, 7 , start_time ); ecl_kw_free( poro ); @@ -59,7 +60,7 @@ void test_write_header() { // Write poro with nactive size. { fortio_type * f = fortio_open_writer( "FOO2.INIT" , false , ECL_ENDIAN_FLIP ); - ecl_kw_type * poro = ecl_kw_alloc( "PORO" , ecl_grid_get_global_size( ecl_grid ) , ECL_FLOAT_TYPE ); + ecl_kw_type * poro = ecl_kw_alloc( "PORO" , ecl_grid_get_global_size( ecl_grid ) , ECL_FLOAT); ecl_kw_scalar_set_float( poro , 0.10 ); ecl_init_file_fwrite_header( f , ecl_grid , poro , ECL_FIELD_UNITS, 7 , start_time ); ecl_kw_free( poro ); diff --git a/ThirdParty/Ert/libecl/tests/ecl_kw_cmp_string.c b/ThirdParty/Ert/libecl/tests/ecl_kw_cmp_string.c index 934a931654..c12009dbc5 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_kw_cmp_string.c +++ b/ThirdParty/Ert/libecl/tests/ecl_kw_cmp_string.c @@ -21,11 +21,12 @@ #include #include +#include void test_cmp_string() { - ecl_kw_type * ecl_kw = ecl_kw_alloc( "HEADER" , 1 , ECL_CHAR_TYPE ); + ecl_kw_type * ecl_kw = ecl_kw_alloc( "HEADER" , 1 , ECL_CHAR); ecl_kw_iset_string8( ecl_kw , 0 , "ABCD"); diff --git a/ThirdParty/Ert/libecl/tests/ecl_kw_equal.c b/ThirdParty/Ert/libecl/tests/ecl_kw_equal.c index 4ec147e84e..3e00c26c3e 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_kw_equal.c +++ b/ThirdParty/Ert/libecl/tests/ecl_kw_equal.c @@ -21,10 +21,11 @@ #include #include #include +#include int main(int argc , char ** argv) { - ecl_kw_type * ecl_kw1 = ecl_kw_alloc( "KW" , 10 , ECL_INT_TYPE ); + ecl_kw_type * ecl_kw1 = ecl_kw_alloc( "KW" , 10 , ECL_INT ); int data[10]; int i; for (i=0; i < 10; i++) { @@ -49,8 +50,8 @@ int main(int argc , char ** argv) { } { - ecl_kw_type * ecl_ikw = ecl_kw_alloc_new_shared( "KW" , 10 , ECL_INT_TYPE , data); - ecl_kw_type * ecl_fkw = ecl_kw_alloc_new_shared( "KW" , 10 , ECL_FLOAT_TYPE , data); + ecl_kw_type * ecl_ikw = ecl_kw_alloc_new_shared( "KW" , 10 , ECL_INT , data); + ecl_kw_type * ecl_fkw = ecl_kw_alloc_new_shared( "KW" , 10 , ECL_FLOAT , data); test_assert_true( ecl_kw_content_equal( ecl_kw1 , ecl_ikw )); test_assert_false( ecl_kw_content_equal( ecl_kw1 , ecl_fkw )); diff --git a/ThirdParty/Ert/libecl/tests/ecl_kw_fread.c b/ThirdParty/Ert/libecl/tests/ecl_kw_fread.c index 69871c8562..be6fd6569b 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_kw_fread.c +++ b/ThirdParty/Ert/libecl/tests/ecl_kw_fread.c @@ -44,7 +44,7 @@ void test_truncated(const char * filename , offset_type truncate_size) { void test_fread_alloc() { test_work_area_type * work_area = test_work_area_alloc("ecl_kw_fread" ); { - ecl_kw_type * kw1 = ecl_kw_alloc( "INT" , 100 , ECL_INT_TYPE ); + ecl_kw_type * kw1 = ecl_kw_alloc( "INT" , 100 , ECL_INT ); int i; for (i=0; i < 100; i++) ecl_kw_iset_int( kw1 , i , i ); diff --git a/ThirdParty/Ert/libecl/tests/ecl_kw_grdecl.c b/ThirdParty/Ert/libecl/tests/ecl_kw_grdecl.c index 6dafd0a90d..bf3a3185b2 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_kw_grdecl.c +++ b/ThirdParty/Ert/libecl/tests/ecl_kw_grdecl.c @@ -26,7 +26,7 @@ int main(int argc , char ** argv) { int i; - ecl_kw_type * ecl_kw = ecl_kw_alloc("HEAD" , 10 , ECL_INT_TYPE); + ecl_kw_type * ecl_kw = ecl_kw_alloc("HEAD" , 10 , ECL_INT); for (i=0; i < 10; i++) ecl_kw_iset_int(ecl_kw , i , i ); @@ -40,7 +40,7 @@ int main(int argc , char ** argv) { stream = util_fopen( "FILE.grdecl" , "r"); { - ecl_kw_type * ecl_kw2 = ecl_kw_fscanf_alloc_grdecl( stream , "HEAD" , 10 , ECL_INT_TYPE); + ecl_kw_type * ecl_kw2 = ecl_kw_fscanf_alloc_grdecl( stream , "HEAD" , 10 , ECL_INT); test_assert_not_NULL( ecl_kw2 ); test_assert_true( ecl_kw_equal( ecl_kw , ecl_kw2)); @@ -54,10 +54,10 @@ int main(int argc , char ** argv) { stream = util_fopen( "FILE.grdecl" , "r"); { - ecl_kw_type * ecl_kw2 = ecl_kw_fscanf_alloc_grdecl( stream , "HEAD" , 10 , ECL_INT_TYPE); + ecl_kw_type * ecl_kw2 = ecl_kw_fscanf_alloc_grdecl( stream , "HEAD" , 10 , ECL_INT); test_assert_NULL( ecl_kw2 ); - ecl_kw2 = ecl_kw_fscanf_alloc_grdecl( stream , "HEAD1234" , 10 , ECL_INT_TYPE); + ecl_kw2 = ecl_kw_fscanf_alloc_grdecl( stream , "HEAD1234" , 10 , ECL_INT); test_assert_not_NULL( ecl_kw2 ); test_assert_string_equal( ecl_kw_get_header( ecl_kw2 ) , "HEAD1234" ); diff --git a/ThirdParty/Ert/libecl/tests/ecl_kw_init.c b/ThirdParty/Ert/libecl/tests/ecl_kw_init.c index 79da2ef774..9a95fdfe7e 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_kw_init.c +++ b/ThirdParty/Ert/libecl/tests/ecl_kw_init.c @@ -27,7 +27,7 @@ void test_int() { size_t N = 1000; int i; - ecl_kw_type * kw = ecl_kw_alloc("KW" , N , ECL_INT_TYPE); + ecl_kw_type * kw = ecl_kw_alloc("KW" , N , ECL_INT); for (i=0; i < N; i++) test_assert_int_equal( 0 , ecl_kw_iget_int( kw , i )); @@ -38,7 +38,7 @@ void test_int() { void test_double() { size_t N = 1000; double i; - ecl_kw_type * kw = ecl_kw_alloc("KW" , N , ECL_DOUBLE_TYPE); + ecl_kw_type * kw = ecl_kw_alloc("KW" , N , ECL_DOUBLE); for (i=0; i < N; i++) test_assert_double_equal( 0 , ecl_kw_iget_double( kw , i )); @@ -49,7 +49,7 @@ void test_double() { void test_float() { size_t N = 1000; int i; - ecl_kw_type * kw = ecl_kw_alloc("KW" , N , ECL_FLOAT_TYPE); + ecl_kw_type * kw = ecl_kw_alloc("KW" , N , ECL_FLOAT); for (i=0; i < N; i++) test_assert_int_equal( 0 , ecl_kw_iget_float( kw , i )); diff --git a/ThirdParty/Ert/libecl/tests/ecl_kw_ix_types.c b/ThirdParty/Ert/libecl/tests/ecl_kw_ix_types.c index 9c2dec9164..ac66484ffd 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_kw_ix_types.c +++ b/ThirdParty/Ert/libecl/tests/ecl_kw_ix_types.c @@ -31,7 +31,7 @@ void test_create_ECL_C010_TYPE() { - ecl_kw_type * ecl_kw = ecl_kw_alloc("TEST" , 1000 , ECL_C010_TYPE ); + ecl_kw_type * ecl_kw = ecl_kw_alloc("TEST" , 1000 , ECL_C010 ); test_assert_NULL( ecl_kw ); } diff --git a/ThirdParty/Ert/libecl/tests/ecl_layer.c b/ThirdParty/Ert/libecl/tests/ecl_layer.c index 891cefff07..e6420cecc4 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_layer.c +++ b/ThirdParty/Ert/libecl/tests/ecl_layer.c @@ -19,7 +19,6 @@ #include #include -#include #include #include diff --git a/ThirdParty/Ert/libecl/tests/ecl_layer_statoil.c b/ThirdParty/Ert/libecl/tests/ecl_layer_statoil.c index 9969aab104..df41e92c53 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_layer_statoil.c +++ b/ThirdParty/Ert/libecl/tests/ecl_layer_statoil.c @@ -28,7 +28,7 @@ ecl_kw_type * alloc_faultblock_kw( const char * filename, int grid_size) { FILE * stream = util_fopen( filename , "r"); - ecl_kw_type * kw = ecl_kw_fscanf_alloc_grdecl( stream , "FAULTBLK" , grid_size , ECL_INT_TYPE ); + ecl_kw_type * kw = ecl_kw_fscanf_alloc_grdecl( stream , "FAULTBLK" , grid_size , ECL_INT ); fclose( stream ); return kw; diff --git a/ThirdParty/Ert/libecl/tests/ecl_lfs.c b/ThirdParty/Ert/libecl/tests/ecl_lfs.c index 871b7bfa0a..d89181e6fe 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_lfs.c +++ b/ThirdParty/Ert/libecl/tests/ecl_lfs.c @@ -23,6 +23,7 @@ #include #include #include +#include @@ -30,7 +31,7 @@ int main( int argc , char ** argv) { int num_kw = 1000; // Total file size should roughly exceed 2GB int kw_size = 600000; - ecl_kw_type * kw = ecl_kw_alloc("KW" , kw_size , ECL_INT_TYPE ); + ecl_kw_type * kw = ecl_kw_alloc("KW" , kw_size , ECL_INT ); rng_type * rng = rng_alloc( MZRAN , INIT_DEFAULT ); int i; offset_type file_size; diff --git a/ThirdParty/Ert/libecl/tests/ecl_nnc_export.c b/ThirdParty/Ert/libecl/tests/ecl_nnc_export.c index 33845e49a3..527530435a 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_nnc_export.c +++ b/ThirdParty/Ert/libecl/tests/ecl_nnc_export.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -231,6 +232,20 @@ void test_export(const char * name, bool have_tran_data) { for (int i =0; i < ecl_nnc_export_get_size( grid ); i++) test_assert_true( ecl_nnc_equal( &nnc_data1[i] , &nnc_data2[i] )); + { + ecl_nnc_geometry_type * nnc_geo = ecl_nnc_geometry_alloc( grid ); + test_assert_int_equal( ecl_nnc_export_get_size( grid ), ecl_nnc_geometry_size( nnc_geo )); + for (int i=0; i < ecl_nnc_geometry_size( nnc_geo ); i++) { + const ecl_nnc_pair_type *nnc_pair = ecl_nnc_geometry_iget( nnc_geo , i ); + ecl_nnc_type * nnc1 = &nnc_data1[i]; + + test_assert_int_equal( nnc_pair->grid_nr1 , nnc1->grid_nr1 ); + test_assert_int_equal( nnc_pair->grid_nr2 , nnc1->grid_nr2 ); + test_assert_int_equal( nnc_pair->global_index1 , nnc1->global_index1 ); + test_assert_int_equal( nnc_pair->global_index2 , nnc1->global_index2 ); + } + ecl_nnc_geometry_free( nnc_geo ); + } free( nnc_data2 ); free( nnc_data1 ); diff --git a/ThirdParty/Ert/libecl/tests/ecl_nnc_geometry.c b/ThirdParty/Ert/libecl/tests/ecl_nnc_geometry.c new file mode 100644 index 0000000000..276a7a30c1 --- /dev/null +++ b/ThirdParty/Ert/libecl/tests/ecl_nnc_geometry.c @@ -0,0 +1,60 @@ +/* + Copyright (C) 2017 Statoil ASA, Norway. + + The file 'ecl_nnc_geometry.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 at + for more details. +*/ +#include +#include + +#include +#include +#include +#include +#include +#include + + +void test_create_empty() { + ecl_grid_type * grid = ecl_grid_alloc_rectangular(10,10,10,1,1,1,NULL); + ecl_nnc_geometry_type * nnc_geo = ecl_nnc_geometry_alloc( grid ); + test_assert_true( ecl_nnc_geometry_is_instance( nnc_geo )); + test_assert_int_equal( ecl_nnc_geometry_size( nnc_geo ) , 0 ); + ecl_nnc_geometry_free( nnc_geo ); + ecl_grid_free( grid ); +} + +void test_create_simple() { + int nx = 10; + int ny = 10; + int nz = 10; + ecl_grid_type * grid0 = ecl_grid_alloc_rectangular(nx,ny,nz,1,1,1,NULL); + + ecl_grid_add_self_nnc(grid0, 0 ,nx*ny + 0, 0 ); + ecl_grid_add_self_nnc(grid0, 1 ,nx*ny + 1, 1 ); + ecl_grid_add_self_nnc(grid0, 2 ,nx*ny + 2, 2 ); + { + ecl_nnc_geometry_type * nnc_geo = ecl_nnc_geometry_alloc( grid0 ); + test_assert_int_equal( ecl_nnc_geometry_size( nnc_geo ) , 3 ); + ecl_nnc_geometry_free( nnc_geo ); + } + ecl_grid_free( grid0 ); +} + + +int main(int argc , char ** argv) { + util_install_signals( ); + test_create_empty( ); + test_create_simple( ); +} diff --git a/ThirdParty/Ert/libecl/tests/ecl_rst_file.c b/ThirdParty/Ert/libecl/tests/ecl_rst_file.c index 5be806b92b..7d9c149180 100644 --- a/ThirdParty/Ert/libecl/tests/ecl_rst_file.c +++ b/ThirdParty/Ert/libecl/tests/ecl_rst_file.c @@ -25,18 +25,19 @@ #include #include #include +#include -void write_keyword( fortio_type * fortio , const char * kw, ecl_type_enum ecl_type ) { - ecl_kw_type * ecl_kw = ecl_kw_alloc( kw , 1000 , ecl_type ); +void write_keyword( fortio_type * fortio , const char * kw, ecl_data_type data_type ) { + ecl_kw_type * ecl_kw = ecl_kw_alloc( kw , 1000 , data_type ); ecl_kw_fwrite( ecl_kw , fortio ); ecl_kw_free( ecl_kw ); } void write_seqnum( fortio_type * fortio , int report_step ) { - ecl_kw_type * ecl_kw = ecl_kw_alloc( SEQNUM_KW , 1 , ECL_INT_TYPE ); + ecl_kw_type * ecl_kw = ecl_kw_alloc( SEQNUM_KW , 1 , ECL_INT); ecl_kw_iset_int( ecl_kw , 0 , report_step ); ecl_kw_fwrite( ecl_kw , fortio ); ecl_kw_free( ecl_kw ); @@ -68,13 +69,13 @@ void test_Xfile() { { fortio_type * f = fortio_open_writer( "TEST.X0010" , false , ECL_ENDIAN_FLIP); - write_keyword( f , "INTEHEAD" , ECL_INT_TYPE ); - write_keyword( f , "PRESSURE" , ECL_FLOAT_TYPE ); - write_keyword( f , "SWAT" , ECL_FLOAT_TYPE ); + write_keyword( f , "INTEHEAD" , ECL_INT); + write_keyword( f , "PRESSURE" , ECL_FLOAT); + write_keyword( f , "SWAT" , ECL_FLOAT); - write_keyword( f , "INTEHEAD" , ECL_INT_TYPE ); - write_keyword( f , "PRESSURE" , ECL_FLOAT_TYPE ); - write_keyword( f , "SWAT" , ECL_FLOAT_TYPE ); + write_keyword( f , "INTEHEAD" , ECL_INT); + write_keyword( f , "PRESSURE" , ECL_FLOAT); + write_keyword( f , "SWAT" , ECL_FLOAT); fortio_fclose( f ); } @@ -92,21 +93,21 @@ void test_UNRST0() { { fortio_type * f = fortio_open_writer( "TEST.UNRST" , false , ECL_ENDIAN_FLIP); write_seqnum( f , 0 ); - write_keyword( f , "INTEHEAD" , ECL_INT_TYPE ); - write_keyword( f , "PRESSURE" , ECL_FLOAT_TYPE ); - write_keyword( f , "SWAT" , ECL_FLOAT_TYPE ); + write_keyword( f , "INTEHEAD" , ECL_INT); + write_keyword( f , "PRESSURE" , ECL_FLOAT); + write_keyword( f , "SWAT" , ECL_FLOAT); pos10 = fortio_ftell( f ); write_seqnum( f , 10 ); - write_keyword( f , "INTEHEAD" , ECL_INT_TYPE ); - write_keyword( f , "PRESSURE" , ECL_FLOAT_TYPE ); - write_keyword( f , "SWAT" , ECL_FLOAT_TYPE ); + write_keyword( f , "INTEHEAD" , ECL_INT); + write_keyword( f , "PRESSURE" , ECL_FLOAT); + write_keyword( f , "SWAT" , ECL_FLOAT); pos20 = fortio_ftell( f ); write_seqnum( f , 20 ); - write_keyword( f , "INTEHEAD" , ECL_INT_TYPE ); - write_keyword( f , "PRESSURE" , ECL_FLOAT_TYPE ); - write_keyword( f , "SWAT" , ECL_FLOAT_TYPE ); + write_keyword( f , "INTEHEAD" , ECL_INT); + write_keyword( f , "PRESSURE" , ECL_FLOAT); + write_keyword( f , "SWAT" , ECL_FLOAT); pos_end = fortio_ftell( f ); fortio_fclose( f ); @@ -131,21 +132,21 @@ void test_UNRST1() { fortio_type * f = fortio_open_writer( "TEST.UNRST" , false , ECL_ENDIAN_FLIP); pos5 = fortio_ftell( f ); write_seqnum( f , 5 ); - write_keyword( f , "INTEHEAD" , ECL_INT_TYPE ); - write_keyword( f , "PRESSURE" , ECL_FLOAT_TYPE ); - write_keyword( f , "SWAT" , ECL_FLOAT_TYPE ); + write_keyword( f , "INTEHEAD" , ECL_INT); + write_keyword( f , "PRESSURE" , ECL_FLOAT); + write_keyword( f , "SWAT" , ECL_FLOAT); pos10 = fortio_ftell( f ); write_seqnum( f , 10 ); - write_keyword( f , "INTEHEAD" , ECL_INT_TYPE ); - write_keyword( f , "PRESSURE" , ECL_FLOAT_TYPE ); - write_keyword( f , "SWAT" , ECL_FLOAT_TYPE ); + write_keyword( f , "INTEHEAD" , ECL_INT); + write_keyword( f , "PRESSURE" , ECL_FLOAT); + write_keyword( f , "SWAT" , ECL_FLOAT); pos20 = fortio_ftell( f ); write_seqnum( f , 20 ); - write_keyword( f , "INTEHEAD" , ECL_INT_TYPE ); - write_keyword( f , "PRESSURE" , ECL_FLOAT_TYPE ); - write_keyword( f , "SWAT" , ECL_FLOAT_TYPE ); + write_keyword( f , "INTEHEAD" , ECL_INT); + write_keyword( f , "PRESSURE" , ECL_FLOAT); + write_keyword( f , "SWAT" , ECL_FLOAT); pos_end = fortio_ftell( f ); fortio_fclose( f ); diff --git a/ThirdParty/Ert/libecl/tests/statoil_tests.cmake b/ThirdParty/Ert/libecl/tests/statoil_tests.cmake index 0681181613..8962b49fa2 100644 --- a/ThirdParty/Ert/libecl/tests/statoil_tests.cmake +++ b/ThirdParty/Ert/libecl/tests/statoil_tests.cmake @@ -1,21 +1,21 @@ add_executable( ecl_coarse_test ecl_coarse_test.c ) -target_link_libraries( ecl_coarse_test ecl test_util ) +target_link_libraries( ecl_coarse_test ecl ) add_test( ecl_coarse_test ${EXECUTABLE_OUTPUT_PATH}/ecl_coarse_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/LGCcase/LGC_TESTCASE2 ) add_executable( ecl_grid_layer_contains ecl_grid_layer_contains.c ) -target_link_libraries( ecl_grid_layer_contains ecl test_util ) +target_link_libraries( ecl_grid_layer_contains ecl ) add_test( ecl_grid_layer_contains1 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_layer_contains ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) add_test( ecl_grid_layer_contains2 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_layer_contains ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Mariner/MARINER.EGRID ) add_executable( ecl_restart_test ecl_restart_test.c ) -target_link_libraries( ecl_restart_test ecl test_util ) +target_link_libraries( ecl_restart_test ecl ) add_test( ecl_restart_test ${EXECUTABLE_OUTPUT_PATH}/ecl_restart_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST ) add_executable( ecl_nnc_export ecl_nnc_export.c ) -target_link_libraries( ecl_nnc_export ecl test_util ) +target_link_libraries( ecl_nnc_export ecl ) add_test (ecl_nnc_export1 ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_export ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE TRUE) add_test (ecl_nnc_export2 ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_export ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/10kcase/TEST10K_FLT_LGR_NNC TRUE) add_test (ecl_nnc_export3 ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_export ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Troll/MSW_LGR/2BRANCHES-CCEWELLPATH-NEW-SCH-TUNED-AR3 TRUE) @@ -25,17 +25,17 @@ add_test (ecl_nnc_export6 ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_export ${PROJECT_SO add_test (ecl_nnc_export7 ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_export ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/TYRIHANS/BASE20150218_MULTFLT FALSE) add_executable( ecl_nnc_export_get_tran ecl_nnc_export_get_tran.c ) -target_link_libraries( ecl_nnc_export_get_tran ecl test_util ) +target_link_libraries( ecl_nnc_export_get_tran ecl ) add_test (ecl_nnc_export_get_tran ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_export_get_tran ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Troll/MSW_LGR/2BRANCHES-CCEWELLPATH-NEW-SCH-TUNED-AR3) add_executable( ecl_util_make_date_shift ecl_util_make_date_shift.c ) -target_link_libraries( ecl_util_make_date_shift ecl test_util ) +target_link_libraries( ecl_util_make_date_shift ecl ) add_test( ecl_util_make_date_shift ${EXECUTABLE_OUTPUT_PATH}/ecl_util_make_date_shift ) add_executable( ecl_sum_case_exists ecl_sum_case_exists.c ) -target_link_libraries( ecl_sum_case_exists ecl test_util ) +target_link_libraries( ecl_sum_case_exists ecl ) add_test( ecl_sum_case_exists ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_case_exists ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/GurbatSummary/missingHeader/ECLIPSE @@ -43,62 +43,61 @@ add_test( ecl_sum_case_exists ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_case_exists add_executable( ecl_grid_lgr_name ecl_grid_lgr_name.c ) -target_link_libraries( ecl_grid_lgr_name ecl test_util ) +target_link_libraries( ecl_grid_lgr_name ecl ) set_target_properties( ecl_grid_lgr_name PROPERTIES COMPILE_FLAGS "-Werror") add_test( ecl_grid_lgr_name ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_lgr_name ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Troll/MSW_LGR/2BRANCHES-CCEWELLPATH-NEW-SCH-TUNED-AR3.EGRID) add_executable( ecl_region ecl_region.c ) -target_link_libraries( ecl_region ecl test_util ) +target_link_libraries( ecl_region ecl ) add_test( ecl_region ${EXECUTABLE_OUTPUT_PATH}/ecl_region ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) add_executable( ecl_grid_fwrite ecl_grid_fwrite.c ) -target_link_libraries( ecl_grid_fwrite ecl test_util ) +target_link_libraries( ecl_grid_fwrite ecl ) add_test( ecl_grid_fwrite ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_fwrite ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) -add_executable( ecl_grid_cell_contains ecl_grid_cell_contains.c ) -target_link_libraries( ecl_grid_cell_contains ecl test_util ) -add_test( ecl_grid_cell_contains1 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_contains 1 ) -add_test( ecl_grid_cell_contains2 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_contains 2 ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) -add_test( ecl_grid_cell_contains3 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_contains 3 ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/FF12/FF12_2013B2.EGRID ) +add_test( ecl_grid_cell_contains2 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_contains ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) +add_test( ecl_grid_cell_contains3 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_contains ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/FF12/FF12_2013B2.EGRID ) +add_test( ecl_grid_cell_contains4 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_contains ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Brazil/R3_ICD.EGRID ) -add_test( ecl_grid_cell_contains4 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_contains 4 ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Brazil/R3_ICD.EGRID ) +add_executable( ecl_grid_cell_contains_wellpath ecl_grid_cell_contains_wellpath.c ) +target_link_libraries( ecl_grid_cell_contains_wellpath ecl ) +add_test( ecl_grid_cell_contains_wellpath1 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_contains_wellpath ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/CellContains/model/SMS-0.EGRID ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/CellContains/R_PB-4H.jira ) add_executable( ecl_grid_cell_volume ecl_grid_cell_volume.c ) -target_link_libraries( ecl_grid_cell_volume ecl test_util ) +target_link_libraries( ecl_grid_cell_volume ecl ) add_test( ecl_grid_cell_volume1 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_volume) add_test( ecl_grid_cell_volume2 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_volume ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) add_test( ecl_grid_cell_volume3 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_volume ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Heidrun/Summary/FF12_2013B3_CLEAN_RS.EGRID ) add_executable( ecl_region2region ecl_region2region_test.c ) -target_link_libraries( ecl_region2region ecl test_util ) +target_link_libraries( ecl_region2region ecl ) add_test( ecl_region2region ${EXECUTABLE_OUTPUT_PATH}/ecl_region2region ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/R2R/R2R.SMSPEC ) add_executable( ecl_grid_case ecl_grid_case.c ) -target_link_libraries( ecl_grid_case ecl test_util ) +target_link_libraries( ecl_grid_case ecl ) add_test( ecl_grid_case ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_case ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ) add_executable( ecl_lgr_test ecl_lgr_test.c ) -target_link_libraries( ecl_lgr_test ecl test_util ) +target_link_libraries( ecl_lgr_test ecl ) add_test( ecl_lgr_test1 ${EXECUTABLE_OUTPUT_PATH}/ecl_lgr_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/10kcase/TEST10K_FLT_LGR_NNC.EGRID) add_test( ecl_lgr_test2 ${EXECUTABLE_OUTPUT_PATH}/ecl_lgr_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/10kcase/TEST10K_FLT_LGR_NNC.GRID) add_test( ecl_lgr_test3 ${EXECUTABLE_OUTPUT_PATH}/ecl_lgr_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Troll/MSW_LGR/2BRANCHES-CCEWELLPATH-NEW-SCH-TUNED-AR3.EGRID ) add_executable( ecl_grid_simple ecl_grid_simple.c ) -target_link_libraries( ecl_grid_simple ecl test_util ) +target_link_libraries( ecl_grid_simple ecl ) add_test( ecl_grid_simple ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_simple ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) -add_test( ecl_grid_ecl2015_1 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_simple ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Eclipse2015_NNC_BUG/FF15_2015B2_LGRM_RDI15_HIST_RDIREAL1_NOSIM_GRID.EGRID ) add_test( ecl_grid_ecl2015_2 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_simple ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Eclipse2015_NNC_BUG/FF15_2015B2_LGRM_RDI15_HIST_RDIREAL1_20142.EGRID ) add_executable( ecl_grid_export_statoil ecl_grid_export.c ) -target_link_libraries( ecl_grid_export_statoil ecl test_util ) +target_link_libraries( ecl_grid_export_statoil ecl ) add_test( ecl_grid_export_statoil ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_export_statoil ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) add_executable( ecl_grid_volume ecl_grid_volume.c ) -target_link_libraries( ecl_grid_volume ecl test_util ) +target_link_libraries( ecl_grid_volume ecl ) add_test( ecl_grid_volume1 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_volume ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ) add_test( ecl_grid_volume2 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_volume ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/VolumeTest/TEST1 ) add_test( ecl_grid_volume3 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_volume ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/OsebergSyd/Omega/OMEGA-0) @@ -112,7 +111,7 @@ add_test( ecl_grid_volume4 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_volume ${PROJECT_ # add_test( ecl_grid_volume5 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_volume ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Heidrun/Summary/FF12_2013B3_CLEAN_RS) add_executable( ecl_grid_dims ecl_grid_dims.c ) -target_link_libraries( ecl_grid_dims ecl test_util ) +target_link_libraries( ecl_grid_dims ecl ) add_test( ecl_grid_dims0 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_dims ) add_test( ecl_grid_dims1 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_dims ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.INIT ) @@ -124,7 +123,7 @@ add_test( ecl_grid_dims5 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_dims ${PROJECT_SOUR add_executable( ecl_nnc_test ecl_nnc_test.c ) -target_link_libraries( ecl_nnc_test ecl test_util ) +target_link_libraries( ecl_nnc_test ecl ) add_test (ecl_nnc_test1 ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) add_test (ecl_nnc_test2 ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/10kcase/TEST10K_FLT_LGR_NNC.EGRID ) add_test (ecl_nnc_test3 ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Troll/MSW_LGR/2BRANCHES-CCEWELLPATH-NEW-SCH-TUNED-AR3.EGRID) @@ -133,21 +132,21 @@ add_test (ecl_nnc_test5 ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_test ${PROJECT_SOURCE add_executable( ecl_layer_statoil ecl_layer_statoil.c ) -target_link_libraries( ecl_layer_statoil ecl test_util ) +target_link_libraries( ecl_layer_statoil ecl ) add_test(ecl_layer_statoil ${EXECUTABLE_OUTPUT_PATH}/ecl_layer_statoil ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Mariner/MARINER.EGRID ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Mariner/faultblock.grdecl) add_executable( ecl_dualp ecl_dualp.c ) -target_link_libraries( ecl_dualp ecl test_util ) +target_link_libraries( ecl_dualp ecl ) add_test( ecl_dualp ${EXECUTABLE_OUTPUT_PATH}/ecl_dualp ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/LGCcase/LGC_TESTCASE2 ) add_executable( ecl_sum_test ecl_sum_test.c ) -target_link_libraries( ecl_sum_test ecl test_util ) +target_link_libraries( ecl_sum_test ecl ) add_test( ecl_sum_test ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ) add_executable( ecl_sum_report_step_equal ecl_sum_report_step_equal.c ) -target_link_libraries( ecl_sum_report_step_equal ecl test_util ) +target_link_libraries( ecl_sum_report_step_equal ecl ) add_test( ecl_sum_report_step_equal1 ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_report_step_equal ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Snorre/SNORRE FALSE) add_test( ecl_sum_report_step_equal2 ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_report_step_equal ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE TRUE) add_test( ecl_sum_report_step_equal3 ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_report_step_equal ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/modGurbat/extraMinistep/ECLIPSE TRUE) @@ -156,7 +155,7 @@ add_test( ecl_sum_report_step_equal5 ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_report_st add_test( ecl_sum_report_step_equal6 ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_report_step_equal ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Snorre/SNORRE ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Snorre2/SNORRE2 FALSE) add_executable( ecl_sum_report_step_compatible ecl_sum_report_step_compatible.c ) -target_link_libraries( ecl_sum_report_step_compatible ecl test_util ) +target_link_libraries( ecl_sum_report_step_compatible ecl ) add_test( ecl_sum_report_step_compatible1 ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_report_step_compatible ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Snorre/SNORRE FALSE) add_test( ecl_sum_report_step_compatible2 ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_report_step_compatible ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE TRUE) add_test( ecl_sum_report_step_compatible3 ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_report_step_compatible ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/modGurbat/extraMinistep/ECLIPSE TRUE) @@ -166,40 +165,40 @@ add_test( ecl_sum_report_step_compatible6 ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_repo if (HAVE_UTIL_ABORT_INTERCEPT) add_executable( ecl_fortio ecl_fortio.c ) - target_link_libraries( ecl_fortio ecl test_util ) + target_link_libraries( ecl_fortio ecl ) add_test( ecl_fortio ${EXECUTABLE_OUTPUT_PATH}/ecl_fortio ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST ) set_property( TEST ecl_fortio PROPERTY LABELS StatoilData) endif() add_executable( ecl_file ecl_file.c ) -target_link_libraries( ecl_file ecl test_util ) +target_link_libraries( ecl_file ecl ) add_test( ecl_file ${EXECUTABLE_OUTPUT_PATH}/ecl_file ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST ECLIPSE.UNRST) add_executable( ecl_fmt ecl_fmt.c ) -target_link_libraries( ecl_fmt ecl test_util ) +target_link_libraries( ecl_fmt ecl ) add_test( ecl_fmt ${EXECUTABLE_OUTPUT_PATH}/ecl_fmt ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.DATA) add_executable( ecl_rsthead ecl_rsthead.c ) -target_link_libraries( ecl_rsthead ecl test_util ) +target_link_libraries( ecl_rsthead ecl ) add_test( ecl_rsthead ${EXECUTABLE_OUTPUT_PATH}/ecl_rsthead ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/DualPoro/DUALPORO.X0005 ) add_executable( ecl_smspec ecl_smspec.c ) -target_link_libraries( ecl_smspec ecl test_util ) +target_link_libraries( ecl_smspec ecl ) add_test( ecl_smspec ${EXECUTABLE_OUTPUT_PATH}/ecl_smspec ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.SMSPEC ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Heidrun/Summary/FF12_2013B3_CLEAN_RS.SMSPEC ) add_executable( ecl_rft ecl_rft.c ) -target_link_libraries( ecl_rft ecl test_util ) +target_link_libraries( ecl_rft ecl ) add_test( ecl_rft_rft ${EXECUTABLE_OUTPUT_PATH}/ecl_rft ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.RFT RFT) add_test( ecl_rft_rft_rw ${EXECUTABLE_OUTPUT_PATH}/ecl_rft ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.RFT RFT_RW) add_test( ecl_rft_plt ${EXECUTABLE_OUTPUT_PATH}/ecl_rft ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/RFT/TEST1_1A.RFT PLT) add_test( ecl_rft_plt ${EXECUTABLE_OUTPUT_PATH}/ecl_rft ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/RFT/RFT2.RFT MSW-PLT) add_executable( ecl_grid_copy_statoil ecl_grid_copy_statoil.c ) -target_link_libraries( ecl_grid_copy_statoil ecl test_util ) +target_link_libraries( ecl_grid_copy_statoil ecl ) add_test( ecl_grid_copy_statoil1 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_copy_statoil ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) @@ -213,7 +212,7 @@ add_test( ecl_grid_copy_statoil4 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_copy_statoil add_executable( ecl_fault_block_layer_statoil ecl_fault_block_layer_statoil.c ) -target_link_libraries( ecl_fault_block_layer_statoil ecl test_util ) +target_link_libraries( ecl_fault_block_layer_statoil ecl ) add_test( ecl_fault_block_layer_statoil ${EXECUTABLE_OUTPUT_PATH}/ecl_fault_block_layer_statoil ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Mariner/MARINER.EGRID ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Mariner/faultblock.grdecl) @@ -293,5 +292,4 @@ set_property( TEST ecl_grid_copy_statoil4 PROPERTY LABELS StatoilData ) set_property( TEST ecl_layer_statoil PROPERTY LABELS StatoilData ) set_property( TEST ecl_grid_layer_contains1 PROPERTY LABELS StatoilData ) set_property( TEST ecl_grid_layer_contains2 PROPERTY LABELS StatoilData ) -set_property( TEST ecl_grid_ecl2015_1 PROPERTY LABELS StatoilData ) set_property( TEST ecl_grid_ecl2015_2 PROPERTY LABELS StatoilData ) diff --git a/ThirdParty/Ert/libecl/tests/tests.cmake b/ThirdParty/Ert/libecl/tests/tests.cmake index bc8105323d..667b44fcea 100644 --- a/ThirdParty/Ert/libecl/tests/tests.cmake +++ b/ThirdParty/Ert/libecl/tests/tests.cmake @@ -1,99 +1,107 @@ +add_executable( ecl_nnc_geometry ecl_nnc_geometry.c ) +target_link_libraries( ecl_nnc_geometry ecl ) +add_test( ecl_nnc_geometry ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_geometry ) + add_executable( ecl_alloc_grid_dxv_dyv_dzv ecl_alloc_grid_dxv_dyv_dzv.c ) -target_link_libraries( ecl_alloc_grid_dxv_dyv_dzv ecl test_util ) +target_link_libraries( ecl_alloc_grid_dxv_dyv_dzv ecl ) add_test( ecl_alloc_grid_dxv_dyv_dzv ${EXECUTABLE_OUTPUT_PATH}/ecl_alloc_grid_dxv_dyv_dzv ) +add_executable( ecl_alloc_cpgrid ecl_alloc_cpgrid.c ) +target_link_libraries( ecl_alloc_cpgrid ecl ) +add_test( ecl_alloc_cpgrid ${EXECUTABLE_OUTPUT_PATH}/ecl_alloc_cpgrid ) + add_executable( ecl_kw_init ecl_kw_init.c ) -target_link_libraries( ecl_kw_init ecl test_util ) +target_link_libraries( ecl_kw_init ecl ) add_test( ecl_kw_init ${EXECUTABLE_OUTPUT_PATH}/ecl_kw_init ) add_executable( ecl_kw_ix_types ecl_kw_ix_types.c ) -target_link_libraries( ecl_kw_ix_types ecl test_util ) +target_link_libraries( ecl_kw_ix_types ecl ) add_test( ecl_kw_ix_types ${EXECUTABLE_OUTPUT_PATH}/ecl_kw_ix_types ) add_executable( ecl_grid_init_fwrite ecl_grid_init_fwrite.c ) -target_link_libraries( ecl_grid_init_fwrite ecl test_util ) +target_link_libraries( ecl_grid_init_fwrite ecl ) add_test( ecl_grid_init_fwrite ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_init_fwrite ) add_executable( ecl_init_file ecl_init_file.c ) -target_link_libraries( ecl_init_file ecl test_util ) +target_link_libraries( ecl_init_file ecl ) add_test( ecl_init_file ${EXECUTABLE_OUTPUT_PATH}/ecl_kw_init ) add_executable( ecl_kw_fread ecl_kw_fread.c ) -target_link_libraries( ecl_kw_fread ecl test_util ) +target_link_libraries( ecl_kw_fread ecl ) add_test( ecl_kw_fread ${EXECUTABLE_OUTPUT_PATH}/ecl_kw_fread ) add_executable( ecl_valid_basename ecl_valid_basename.c ) -target_link_libraries( ecl_valid_basename ecl test_util ) +target_link_libraries( ecl_valid_basename ecl ) add_test( ecl_valid_basename ${EXECUTABLE_OUTPUT_PATH}/ecl_valid_basename) add_executable( ecl_util_make_date_no_shift ecl_util_make_date_no_shift.c ) -target_link_libraries( ecl_util_make_date_no_shift ecl test_util ) +target_link_libraries( ecl_util_make_date_no_shift ecl ) add_test( ecl_util_make_date_no_shift ${EXECUTABLE_OUTPUT_PATH}/ecl_util_make_date_no_shift ) add_executable( ecl_sum_writer ecl_sum_writer.c ) -target_link_libraries( ecl_sum_writer ecl test_util ) +target_link_libraries( ecl_sum_writer ecl ) add_test( ecl_sum_writer ${EXECUTABLE_OUTPUT_PATH}/ecl_sum_writer ) add_executable( ecl_grid_add_nnc ecl_grid_add_nnc.c ) -target_link_libraries( ecl_grid_add_nnc ecl test_util ) +target_link_libraries( ecl_grid_add_nnc ecl ) add_test( ecl_grid_add_nnc ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_add_nnc ) add_executable( ecl_grid_create ecl_grid_create.c ) -target_link_libraries( ecl_grid_create ecl test_util ) +target_link_libraries( ecl_grid_create ecl ) add_test( ecl_grid_create ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_create ) add_executable( ecl_grid_DEPTHZ ecl_grid_DEPTHZ.c ) -target_link_libraries( ecl_grid_DEPTHZ ecl test_util ) +target_link_libraries( ecl_grid_DEPTHZ ecl ) add_test( ecl_grid_DEPTHZ ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_DEPTHZ ) add_executable( ecl_grid_reset_actnum ecl_grid_reset_actnum.c ) -target_link_libraries( ecl_grid_reset_actnum ecl test_util ) +target_link_libraries( ecl_grid_reset_actnum ecl ) add_test( ecl_grid_reset_actnum ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_reset_actnum ) add_executable( ecl_nnc_info_test ecl_nnc_info_test.c ) -target_link_libraries( ecl_nnc_info_test ecl test_util ) +target_link_libraries( ecl_nnc_info_test ecl ) add_test (ecl_nnc_info_test ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_info_test ) add_executable( ecl_nnc_vector ecl_nnc_vector.c ) -target_link_libraries( ecl_nnc_vector ecl test_util ) +target_link_libraries( ecl_nnc_vector ecl ) add_test(ecl_nnc_vector ${EXECUTABLE_OUTPUT_PATH}/ecl_nnc_vector ) add_executable( ecl_kw_grdecl ecl_kw_grdecl.c ) -target_link_libraries( ecl_kw_grdecl ecl test_util ) +target_link_libraries( ecl_kw_grdecl ecl ) add_test( ecl_kw_grdecl ${EXECUTABLE_OUTPUT_PATH}/ecl_kw_grdecl ) add_executable( ecl_kw_equal ecl_kw_equal.c ) -target_link_libraries( ecl_kw_equal ecl test_util ) +target_link_libraries( ecl_kw_equal ecl ) add_test( ecl_kw_equal ${EXECUTABLE_OUTPUT_PATH}/ecl_kw_equal ) add_executable( ecl_kw_cmp_string ecl_kw_cmp_string.c ) -target_link_libraries( ecl_kw_cmp_string ecl test_util ) +target_link_libraries( ecl_kw_cmp_string ecl ) add_test( ecl_kw_cmp_string ${EXECUTABLE_OUTPUT_PATH}/ecl_kw_cmp_string ) add_executable( ecl_util_month_range ecl_util_month_range.c ) -target_link_libraries( ecl_util_month_range ecl test_util ) +target_link_libraries( ecl_util_month_range ecl ) add_test( ecl_util_month_range ${EXECUTABLE_OUTPUT_PATH}/ecl_util_month_range ) if (HAVE_UTIL_ABORT_INTERCEPT) add_executable( ecl_grid_corner ecl_grid_corner.c ) - target_link_libraries( ecl_grid_corner ecl test_util ) + target_link_libraries( ecl_grid_corner ecl ) add_test( ecl_grid_corner ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_corner ) add_executable( ecl_layer ecl_layer.c ) - target_link_libraries( ecl_layer ecl test_util ) + target_link_libraries( ecl_layer ecl ) add_test(ecl_layer ${EXECUTABLE_OUTPUT_PATH}/ecl_layer ) endif() add_executable( ecl_rft_cell ecl_rft_cell.c ) -target_link_libraries( ecl_rft_cell ecl test_util ) +target_link_libraries( ecl_rft_cell ecl ) add_test( ecl_rft_cell ${EXECUTABLE_OUTPUT_PATH}/ecl_rft_cell ) add_executable( ecl_grid_copy ecl_grid_copy.c ) -target_link_libraries( ecl_grid_copy ecl test_util ) +target_link_libraries( ecl_grid_copy ecl ) add_test( ecl_grid_copy ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_copy ) add_executable( ecl_get_num_cpu ecl_get_num_cpu_test.c ) -target_link_libraries( ecl_get_num_cpu ecl test_util ) +target_link_libraries( ecl_get_num_cpu ecl ) add_test( ecl_get_num_cpu ${EXECUTABLE_OUTPUT_PATH}/ecl_get_num_cpu ${PROJECT_SOURCE_DIR}/libecl/tests/data/num_cpu1 ${PROJECT_SOURCE_DIR}/libecl/tests/data/num_cpu2 @@ -101,13 +109,15 @@ add_test( ecl_get_num_cpu ${EXECUTABLE_OUTPUT_PATH}/ecl_get_num_cpu ${PROJECT_SOURCE_DIR}/libecl/tests/data/num_cpu4 ) add_executable( ecl_fault_block_layer ecl_fault_block_layer.c ) -target_link_libraries( ecl_fault_block_layer ecl test_util ) +target_link_libraries( ecl_fault_block_layer ecl ) add_test( ecl_fault_block_layer ${EXECUTABLE_OUTPUT_PATH}/ecl_fault_block_layer ) add_executable( ecl_grid_export ecl_grid_export.c ) -target_link_libraries( ecl_grid_export ecl test_util ) +target_link_libraries( ecl_grid_export ecl ) add_test( ecl_grid_export ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_export ) add_executable( ecl_rst_file ecl_rst_file.c ) -target_link_libraries( ecl_rst_file ecl test_util ) +target_link_libraries( ecl_rst_file ecl ert_util ) add_test( ecl_rst_file ${EXECUTABLE_OUTPUT_PATH}/ecl_rst_file ) + +add_test( ecl_grid_cell_contains1 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_cell_contains ) diff --git a/ThirdParty/Ert/libecl_well/tests/statoil_tests.cmake b/ThirdParty/Ert/libecl_well/tests/statoil_tests.cmake index 35cbae9e30..85be1f7494 100644 --- a/ThirdParty/Ert/libecl_well/tests/statoil_tests.cmake +++ b/ThirdParty/Ert/libecl_well/tests/statoil_tests.cmake @@ -1,9 +1,9 @@ add_executable( well_state_load well_state_load.c ) -target_link_libraries( well_state_load ecl_well test_util ) +target_link_libraries( well_state_load ecl_well ) set_target_properties( well_state_load PROPERTIES COMPILE_FLAGS "-Werror") add_executable( well_state_load_missing_RSEG well_state_load_missing_RSEG.c ) -target_link_libraries( well_state_load_missing_RSEG ecl_well test_util ) +target_link_libraries( well_state_load_missing_RSEG ecl_well ) set_target_properties( well_state_load_missing_RSEG PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_state_load1 ${EXECUTABLE_OUTPUT_PATH}/well_state_load ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID @@ -29,28 +29,28 @@ add_test( well_state_load_missing_RSEG2 ${EXECUTABLE_OUTPUT_PATH}/well_state_loa add_executable( well_segment_load well_segment_load.c ) -target_link_libraries( well_segment_load ecl_well test_util ) +target_link_libraries( well_segment_load ecl_well ) set_target_properties( well_segment_load PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_segment_load ${EXECUTABLE_OUTPUT_PATH}/well_segment_load ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/MSWcase/MSW_CASE.X0021) add_executable( well_segment_branch_conn_load well_segment_branch_conn_load.c ) -target_link_libraries( well_segment_branch_conn_load ecl_well test_util ) +target_link_libraries( well_segment_branch_conn_load ecl_well ) set_target_properties( well_segment_branch_conn_load PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_segment_branch_conn_load ${EXECUTABLE_OUTPUT_PATH}/well_segment_branch_conn_load ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/MSWcase/MSW_CASE.X0021) add_executable( well_info well_info.c ) -target_link_libraries( well_info ecl_well test_util ) +target_link_libraries( well_info ecl_well ) set_target_properties( well_info PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_info ${EXECUTABLE_OUTPUT_PATH}/well_info ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID ) add_executable( well_conn_CF well_conn_CF.c ) -target_link_libraries( well_conn_CF ecl_well test_util ) +target_link_libraries( well_conn_CF ecl_well ) add_test( well_conn_CF ${EXECUTABLE_OUTPUT_PATH}/well_conn_CF ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.X0060) add_executable( well_conn_load well_conn_load.c ) -target_link_libraries( well_conn_load ecl_well test_util ) +target_link_libraries( well_conn_load ecl_well ) set_target_properties( well_conn_load PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_conn_load1 ${EXECUTABLE_OUTPUT_PATH}/well_conn_load ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.X0030 F) add_test( well_conn_load2 ${EXECUTABLE_OUTPUT_PATH}/well_conn_load ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/10kcase/TEST10K_FLT_LGR_NNC.X0021 F) @@ -60,17 +60,17 @@ add_test( well_conn_load5 ${EXECUTABLE_OUTPUT_PATH}/well_conn_load ${PROJECT_SOU add_test( well_conn_load6 ${EXECUTABLE_OUTPUT_PATH}/well_conn_load ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/0.9.2_LGR/BASE_REF_XY3Z1_T30_WI.X0003 F) add_executable( well_ts well_ts.c ) -target_link_libraries( well_ts ecl_well test_util ) +target_link_libraries( well_ts ecl_well ) add_test( well_ts ${EXECUTABLE_OUTPUT_PATH}/well_ts ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/CO2case/BASE_CASE ) add_executable( well_dualp well_dualp.c ) -target_link_libraries( well_dualp ecl_well test_util ) +target_link_libraries( well_dualp ecl_well ) add_test( well_dualp ${EXECUTABLE_OUTPUT_PATH}/well_dualp ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/DualPoro/DUALPORO.X0005 ) add_executable( well_lgr_load well_lgr_load.c ) -target_link_libraries( well_lgr_load ecl_well test_util ) +target_link_libraries( well_lgr_load ecl_well ) add_test( well_lgr_load1 ${EXECUTABLE_OUTPUT_PATH}/well_lgr_load ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/0.9.2_LGR/BASE_REF_XY3Z1_T30_WI.EGRID ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/0.9.2_LGR/BASE_REF_XY3Z1_T30_WI.X0003) add_test( well_lgr_load2 ${EXECUTABLE_OUTPUT_PATH}/well_lgr_load ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/AmalgLGRcase/TESTCASE_AMALG_LGR.EGRID ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/AmalgLGRcase/TESTCASE_AMALG_LGR.X0016) diff --git a/ThirdParty/Ert/libecl_well/tests/tests.cmake b/ThirdParty/Ert/libecl_well/tests/tests.cmake index bce5831ece..20dc5381ba 100644 --- a/ThirdParty/Ert/libecl_well/tests/tests.cmake +++ b/ThirdParty/Ert/libecl_well/tests/tests.cmake @@ -1,35 +1,35 @@ add_executable( well_conn_collection well_conn_collection.c ) -target_link_libraries( well_conn_collection ecl_well test_util ) +target_link_libraries( well_conn_collection ecl_well ) set_target_properties( well_conn_collection PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_conn_collection ${EXECUTABLE_OUTPUT_PATH}/well_conn_collection ) add_executable( well_branch_collection well_branch_collection.c ) -target_link_libraries( well_branch_collection ecl_well test_util ) +target_link_libraries( well_branch_collection ecl_well ) set_target_properties( well_branch_collection PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_branch_collection ${EXECUTABLE_OUTPUT_PATH}/well_branch_collection ) add_executable( well_conn well_conn.c ) -target_link_libraries( well_conn ecl_well test_util ) +target_link_libraries( well_conn ecl_well ) set_target_properties( well_conn PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_conn ${EXECUTABLE_OUTPUT_PATH}/well_conn ) add_executable( well_state well_state.c ) -target_link_libraries( well_state ecl_well test_util ) +target_link_libraries( well_state ecl_well ) set_target_properties( well_state PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_state ${EXECUTABLE_OUTPUT_PATH}/well_state ) add_executable( well_segment well_segment.c ) -target_link_libraries( well_segment ecl_well test_util ) +target_link_libraries( well_segment ecl_well ) set_target_properties( well_segment PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_segment ${EXECUTABLE_OUTPUT_PATH}/well_segment ) add_executable( well_segment_conn well_segment_conn.c ) -target_link_libraries( well_segment_conn ecl_well test_util ) +target_link_libraries( well_segment_conn ecl_well ) set_target_properties( well_segment_conn PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_segment_conn ${EXECUTABLE_OUTPUT_PATH}/well_segment_conn ) add_executable( well_segment_collection well_segment_collection.c ) -target_link_libraries( well_segment_collection ecl_well test_util ) +target_link_libraries( well_segment_collection ecl_well ) set_target_properties( well_segment_collection PROPERTIES COMPILE_FLAGS "-Werror") add_test( well_segment_collection ${EXECUTABLE_OUTPUT_PATH}/well_segment_collection ) diff --git a/ThirdParty/Ert/libeclxx/include/ert/ecl/EclKW.hpp b/ThirdParty/Ert/libeclxx/include/ert/ecl/EclKW.hpp index 079b2c2551..d703a71751 100644 --- a/ThirdParty/Ert/libeclxx/include/ert/ecl/EclKW.hpp +++ b/ThirdParty/Ert/libeclxx/include/ert/ecl/EclKW.hpp @@ -28,11 +28,11 @@ #include #include +#include #include #include - namespace ERT { template< typename > struct ecl_type {}; @@ -55,7 +55,7 @@ namespace ERT { class EclKW_ref { public: explicit EclKW_ref( ecl_kw_type* kw ) : m_kw( kw ) { - if( ecl_kw_get_type( kw ) != ecl_type< T >::type ) + if( ecl_type_get_type(ecl_kw_get_data_type( kw )) != ecl_type< T >::type ) throw std::invalid_argument("Type error"); } @@ -132,7 +132,7 @@ class EclKW : public EclKW_ref< T > { } EclKW( const std::string& kw, int size_ ) : - base( ecl_kw_alloc( kw.c_str(), size_, ecl_type< T >::type ) ) + base( ecl_kw_alloc( kw.c_str(), size_, ecl_type_create_from_type(ecl_type< T >::type) ) ) {} EclKW( const std::string& kw, const std::vector< T >& data ) : diff --git a/ThirdParty/Ert/libeclxx/src/EclFilename.cpp b/ThirdParty/Ert/libeclxx/src/EclFilename.cpp index 0476ad2d34..225ad52b46 100644 --- a/ThirdParty/Ert/libeclxx/src/EclFilename.cpp +++ b/ThirdParty/Ert/libeclxx/src/EclFilename.cpp @@ -16,6 +16,7 @@ for more details. */ +#include #include #include @@ -23,11 +24,17 @@ namespace ERT { std::string EclFilename( const std::string& path, const std::string& base, ecl_file_enum file_type , int report_step, bool fmt_file) { - return ecl_util_alloc_filename( path.c_str(), base.c_str(), file_type, fmt_file , report_step ); + char* tmp = ecl_util_alloc_filename( path.c_str(), base.c_str(), file_type, fmt_file , report_step ); + std::string retval = tmp; + free(tmp); + return retval; } std::string EclFilename( const std::string& base, ecl_file_enum file_type , int report_step, bool fmt_file) { - return ecl_util_alloc_filename( nullptr, base.c_str(), file_type, fmt_file , report_step ); + char* tmp = ecl_util_alloc_filename( nullptr, base.c_str(), file_type, fmt_file , report_step ); + std::string retval = tmp; + free(tmp); + return retval; } namespace { @@ -42,16 +49,24 @@ namespace { std::string EclFilename( const std::string& path, const std::string& base, ecl_file_enum file_type , bool fmt_file) { if (require_report_step( file_type )) throw std::runtime_error("Must use overload with report step for this file type"); - else - return ecl_util_alloc_filename( path.c_str(), base.c_str(), file_type, fmt_file , -1); + else { + char* tmp = ecl_util_alloc_filename( path.c_str(), base.c_str(), file_type, fmt_file , -1); + std::string retval = tmp; + free(tmp); + return retval; + } } std::string EclFilename( const std::string& base, ecl_file_enum file_type , bool fmt_file) { if (require_report_step( file_type )) throw std::runtime_error("Must use overload with report step for this file type"); - else - return ecl_util_alloc_filename( nullptr , base.c_str(), file_type, fmt_file , -1); + else { + char* tmp = ecl_util_alloc_filename( nullptr , base.c_str(), file_type, fmt_file , -1); + std::string retval = tmp; + free(tmp); + return retval; + } } diff --git a/ThirdParty/Ert/libeclxx/tests/CMakeLists.txt b/ThirdParty/Ert/libeclxx/tests/CMakeLists.txt index 89b67e4432..be233b2ae3 100644 --- a/ThirdParty/Ert/libeclxx/tests/CMakeLists.txt +++ b/ThirdParty/Ert/libeclxx/tests/CMakeLists.txt @@ -1,15 +1,19 @@ add_executable(eclxx_kw eclxx_kw.cpp) -target_link_libraries(eclxx_kw eclxx test_util ert_utilxx) +target_link_libraries(eclxx_kw eclxx ert_utilxx) add_test(eclxx_kw ${EXECUTABLE_OUTPUT_PATH}/eclxx_kw) add_executable(eclxx_fortio eclxx_fortio.cpp) -target_link_libraries(eclxx_fortio eclxx test_util ert_utilxx) +target_link_libraries(eclxx_fortio eclxx ert_utilxx) add_test(eclxx_fortio ${EXECUTABLE_OUTPUT_PATH}/eclxx_fortio) add_executable(eclxx_smspec eclxx_smspec.cpp) -target_link_libraries(eclxx_smspec eclxx test_util ert_utilxx) +target_link_libraries(eclxx_smspec eclxx ert_utilxx) add_test(eclxx_smspec ${EXECUTABLE_OUTPUT_PATH}/eclxx_smspec) add_executable(eclxx_filename eclxx_filename.cpp) -target_link_libraries(eclxx_filename eclxx test_util ert_utilxx) +target_link_libraries(eclxx_filename eclxx ert_utilxx) add_test(eclxx_filename ${EXECUTABLE_OUTPUT_PATH}/eclxx_filename) + +add_executable(eclxx_types eclxx_types.cpp) +target_link_libraries(eclxx_types eclxx ert_utilxx) +add_test(eclxx_types ${EXECUTABLE_OUTPUT_PATH}/eclxx_types) diff --git a/ThirdParty/Ert/libeclxx/tests/eclxx_kw.cpp b/ThirdParty/Ert/libeclxx/tests/eclxx_kw.cpp index 14c7fe51da..3191250797 100644 --- a/ThirdParty/Ert/libeclxx/tests/eclxx_kw.cpp +++ b/ThirdParty/Ert/libeclxx/tests/eclxx_kw.cpp @@ -78,7 +78,7 @@ void test_move_semantics_no_crash() { } void test_exception_assing_ref_wrong_type() { - auto* ptr = ecl_kw_alloc( "XYZ", 1, ECL_INT_TYPE ); + auto* ptr = ecl_kw_alloc( "XYZ", 1, ECL_INT ); try { ERT::EclKW< double > kw( ptr ); diff --git a/ThirdParty/Ert/libeclxx/tests/eclxx_types.cpp b/ThirdParty/Ert/libeclxx/tests/eclxx_types.cpp new file mode 100644 index 0000000000..2ecd3add39 --- /dev/null +++ b/ThirdParty/Ert/libeclxx/tests/eclxx_types.cpp @@ -0,0 +1,63 @@ +/* + Copyright (C) 2017 Statoil ASA, Norway. + + This file is part of ERT - Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 at + for more details. +*/ + +#include +#include + + +#include +#include +#include +#include + + +void test_ECL_INT() { + ecl_data_type dt = ECL_INT; + test_assert_int_equal( dt.element_size , sizeof(int) ); + test_assert_int_equal( dt.type , ECL_INT_TYPE ); +} + + +void test_ECL_FLOAT() { + ecl_data_type dt = ECL_FLOAT; + test_assert_int_equal( dt.element_size , sizeof(float) ); + test_assert_int_equal( dt.type , ECL_FLOAT_TYPE ); +} + + +void test_ECL_DOUBLE() { + ecl_data_type dt = ECL_DOUBLE; + test_assert_int_equal( dt.element_size , sizeof(double) ); + test_assert_int_equal( dt.type , ECL_DOUBLE_TYPE ); +} + + +void test_ECL_CHAR() { + ecl_data_type dt = ECL_CHAR; + test_assert_int_equal( dt.element_size , ECL_STRING8_LENGTH + 1 ); + test_assert_int_equal( dt.type , ECL_CHAR_TYPE ); +} + + + +int main(int argc , char ** argv) { + test_ECL_INT(); + test_ECL_FLOAT(); + test_ECL_DOUBLE(); + test_ECL_CHAR(); +} diff --git a/ThirdParty/Ert/libenkf/CMakeLists.txt b/ThirdParty/Ert/libenkf/CMakeLists.txt deleted file mode 100644 index d6f06317db..0000000000 --- a/ThirdParty/Ert/libenkf/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_subdirectory( src ) -add_subdirectory( applications/ert_tui ) -if (BUILD_TESTS) - add_subdirectory( tests ) -endif() diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/CMake/config/ert_build_config_file.h.in b/ThirdParty/Ert/libenkf/applications/ert_tui/CMake/config/ert_build_config_file.h.in deleted file mode 100644 index 89829a9a18..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/CMake/config/ert_build_config_file.h.in +++ /dev/null @@ -1,3 +0,0 @@ -#define SITE_CONFIG_FILE "@SITE_CONFIG_FILE@" -#define COMPILE_TIME_STAMP "@COMPILE_TIME_STAMP@" -#define SVN_VERSION "@SVN_VERSION@" diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/CMakeLists.txt b/ThirdParty/Ert/libenkf/applications/ert_tui/CMakeLists.txt deleted file mode 100644 index 10b40fc1f4..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) - -set( src_list main.c enkf_tui_main.c enkf_tui_fs.c enkf_tui_ranking.c enkf_tui_misc.c enkf_tui_table.c - enkf_tui_run.c enkf_tui_util.c enkf_tui_init.c enkf_tui_export.c enkf_tui_analysis.c enkf_tui_help.c enkf_tui_simple.c enkf_tui_workflow.c) - -execute_process(COMMAND date "+%Y-%m-%d %H:%M:%S" OUTPUT_VARIABLE BUILD_TIME ) -string(STRIP ${BUILD_TIME} BUILD_TIME) - -find_package(Git) -if(GIT_EXECUTABLE) - execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - OUTPUT_VARIABLE GIT_COMMIT) - string(STRIP "${GIT_COMMIT}" GIT_COMMIT) -else() - set(GIT_COMMIT) -endif() - -set_source_files_properties( main.c PROPERTIES COMPILE_DEFINITIONS "COMPILE_TIME_STAMP=\"${BUILD_TIME}\";GIT_COMMIT=\"${GIT_COMMIT}\"") - -add_executable( ert_tui ${src_list} ) -target_link_libraries( ert_tui enkf sched rms ecl config job_queue analysis ert_util ) -if (USE_RUNPATH) - add_runpath( ert_tui ) -endif() - -set (destination ${CMAKE_INSTALL_PREFIX}/bin) - -if (INSTALL_ERT) - install(TARGETS ert_tui DESTINATION ${destination}) - if (INSTALL_GROUP) - install(CODE "EXECUTE_PROCESS(COMMAND chgrp ${INSTALL_GROUP} ${destination}/ert_tui)") - install(CODE "EXECUTE_PROCESS(COMMAND chmod g+w ${destination}/ert_tui)") - endif() -endif() diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/ERT.h b/ThirdParty/Ert/libenkf/applications/ert_tui/ERT.h deleted file mode 100644 index 5993a6b4a0..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/ERT.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ERT.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#define SPLASH_LENGTH 11 -const char * splash_text[SPLASH_LENGTH] = { - " _________________________________ ", - " / \\", - " | ______ ______ _______ |", - " | | ____| | __ \\ |__ __| |", - " | | |__ | |__) | | | |", - " | | __| | _ / | | |", - " | | |____ | | \\ \\ | | |", - " | |______| |_| \\_\\ |_| |", - " | |", - " | Ensemble based Reservoir Tool |", - " \\_________________________________/"}; - - - diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_QC.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_QC.h deleted file mode 100644 index 137de3cb05..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_QC.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'enkf_tui_QC.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_QC_H -#define ERT_ENKF_TUI_QC_H - - - -void enkf_tui_QC_menu(void * ); - - - -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_analysis.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_analysis.c deleted file mode 100644 index 577b151a72..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_analysis.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_analysis.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include - - - -void enkf_tui_analysis_scale_observation_std__(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast(arg); - - double scale_factor = enkf_tui_util_scanf_double_with_lower_limit("Global scaling factor", PROMPT_LEN, 0); - - if (enkf_main_have_obs(enkf_main)) { - enkf_obs_type * observations = enkf_main_get_obs(enkf_main); - enkf_obs_scale_std(observations, scale_factor); - } -} - - - - - - -static void enkf_tui_analysis_update_title( enkf_main_type * enkf_main , menu_type * menu ) { - analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main ); - analysis_module_type * analysis_module = analysis_config_get_active_module( analysis_config ); - char * title = util_alloc_sprintf("Analysis menu [Current module:%s]" , analysis_module_get_name( analysis_module )); - menu_set_title( menu , title ); - free( title ); -} - - -void enkf_tui_analysis_select_module__(void * arg) { - int prompt_len = 50; - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - enkf_main_type * enkf_main = arg_pack_iget_ptr( arg_pack , 0 ); - menu_type * menu = arg_pack_iget_ptr( arg_pack , 1 ); - - { - analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main ); - char module_name[256]; - util_printf_prompt("Name module to select" , prompt_len , '=' , "=> "); - scanf("%s", module_name); - if (analysis_config_select_module( analysis_config , module_name )) - enkf_tui_analysis_update_title( enkf_main , menu ); - } -} - - -void enkf_tui_analysis_list_modules__(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main ); - - printf("Available modules: "); - { - stringlist_type * modules = analysis_config_alloc_module_names( analysis_config ); - stringlist_fprintf( modules , " " , stdout ); - printf("\n"); - stringlist_free( modules ); - } -} - - -void enkf_tui_analysis_reload_module__(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main ); - analysis_config_reload_module( analysis_config , NULL ); -} - - -void enkf_tui_analysis_update_module__(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - int prompt_len = 50; - { - analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main ); - analysis_module_type * analysis_module = analysis_config_get_active_module( analysis_config ); - char var_name[256]; - char value[256]; - - util_printf_prompt("Variable to modify" , prompt_len , '=' , "=> "); - scanf("%s", var_name); - { - char * value_prompt = util_alloc_sprintf("New value for %s" , var_name); - util_printf_prompt(value_prompt , prompt_len , '=' , "=> "); - free( value_prompt ); - } - scanf("%s", value); - - if (analysis_module_set_var( analysis_module , var_name , value)) - printf("\'%s\' successfully set to \'%s\' \n",var_name , value); - else - printf("** Variable/type combination: %s/%s not recognized \n", var_name , value); - - } -} - - - - -void enkf_tui_analysis_menu(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - menu_type * menu = menu_alloc( "Analysis menu" , "Back" , "bB"); - - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr( arg_pack , enkf_main ); - arg_pack_append_ptr( arg_pack , menu ); - - { - enkf_tui_analysis_update_title(enkf_main, menu); - - if (enkf_main_have_obs(enkf_main)) { - menu_add_item(menu, "Global scaling of uncertainty", "gG", enkf_tui_analysis_scale_observation_std__, enkf_main, NULL); - menu_add_separator(menu); - } - - menu_add_item(menu, "Select analysis module", "sS", enkf_tui_analysis_select_module__, arg_pack, NULL); - menu_add_item(menu, "List available modules", "lL", enkf_tui_analysis_list_modules__, enkf_main, NULL); - menu_add_item(menu, "Modify analysis module parameters", "mM", enkf_tui_analysis_update_module__, enkf_main, NULL); - menu_add_item(menu, "Reload current module (external only)", "rR", enkf_tui_analysis_reload_module__, enkf_main, NULL); - } - menu_run(menu); - menu_free(menu); - arg_pack_free(arg_pack); -} - diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_analysis.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_analysis.h deleted file mode 100644 index c38c7c93ca..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_analysis.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_analysis.h' is part of ERT - Ensemble based - Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_ANALYSIS_H -#define ERT_ENKF_TUI_ANALYSIS_H - -void enkf_tui_analysis_menu(void *); - - -#endif - diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_export.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_export.c deleted file mode 100644 index cfe9e0b69b..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_export.c +++ /dev/null @@ -1,687 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_export.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#define PROMPT_LEN 60 - - -void enkf_tui_export_field(const enkf_main_type * enkf_main , field_file_format_type file_type) { - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - const bool output_transform = true; - const enkf_config_node_type * config_node; - const int last_report = enkf_main_get_history_length( enkf_main ); - int iens1 , iens2 , iens , report_step; - path_fmt_type * export_path; - - config_node = enkf_tui_util_scanf_key(ensemble_config , PROMPT_LEN , FIELD , INVALID_VAR ); - - report_step = util_scanf_int_with_limits("Report step: ", PROMPT_LEN , 0 , last_report); - enkf_tui_util_scanf_iens_range("Realizations members to export(0 - %d)" , enkf_main_get_ensemble_size( enkf_main ) , PROMPT_LEN , &iens1 , &iens2); - - { - char * path_fmt; - util_printf_prompt("Filename to store files in (with %d) in: " , PROMPT_LEN , '=' , "=> "); - path_fmt = util_alloc_stdin_line(); - export_path = path_fmt_alloc_path_fmt( path_fmt ); - free( path_fmt ); - } - - { - enkf_fs_type * fs = enkf_main_tui_get_fs(enkf_main); - enkf_node_type * node = enkf_node_alloc(config_node); - - for (iens = iens1; iens <= iens2; iens++) { - node_id_type node_id = {.report_step = report_step , .iens = iens }; - if (enkf_node_try_load(node , fs , node_id)) { - char * filename = path_fmt_alloc_path( export_path , false , iens); - { - char * path; - util_alloc_file_components(filename , &path , NULL , NULL); - if (path != NULL) { - util_make_path( path ); - free( path ); - } - } - - { - const field_type * field = enkf_node_value_ptr(node); - field_export(field , filename , NULL , file_type , output_transform, NULL); - } - free(filename); - } else - printf("Warning: could not load realization:%d \n", iens); - } - enkf_node_free(node); - } -} - - -void enkf_tui_export_grdecl(void * enkf_main) { - enkf_tui_export_field(enkf_main , ECL_GRDECL_FILE); -} - - - -void enkf_tui_export_roff(void * enkf_main) { - enkf_tui_export_field(enkf_main , RMS_ROFF_FILE); -} - - -void enkf_tui_export_restart_active(void * enkf_main) { - enkf_tui_export_field(enkf_main , ECL_KW_FILE_ACTIVE_CELLS); -} - - -void enkf_tui_export_restart_all(void * enkf_main) { - enkf_tui_export_field(enkf_main , ECL_KW_FILE_ALL_CELLS); -} - - -void enkf_tui_export_gen_data(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - { - enkf_var_type var_type; - int report_step; - int iens1 , iens2; - const int last_report = enkf_main_get_history_length( enkf_main ); - - const enkf_config_node_type * config_node; - path_fmt_type * file_fmt; - - config_node = enkf_tui_util_scanf_key(ensemble_config , PROMPT_LEN , GEN_DATA , INVALID_VAR); - var_type = enkf_config_node_get_var_type(config_node); - - - report_step = util_scanf_int_with_limits("Report step: ", PROMPT_LEN , 0 , last_report); - enkf_tui_util_scanf_iens_range("Realizations members to export(0 - %d)" , enkf_main_get_ensemble_size( enkf_main ) , PROMPT_LEN , &iens1 , &iens2); - { - char path_fmt[512]; - util_printf_prompt("Filename to store files in (with %d) in: " , PROMPT_LEN , '=' , "=> "); - scanf("%s" , path_fmt); - file_fmt = path_fmt_alloc_path_fmt( path_fmt ); - } - - { - msg_type * msg = msg_alloc("Writing file: " , false); - enkf_fs_type * fs = enkf_main_tui_get_fs(enkf_main); - enkf_node_type * node = enkf_node_alloc(config_node); - gen_data_file_format_type export_type = gen_data_guess_export_type( enkf_node_value_ptr(node) ); - int iens; - - msg_show( msg ); - for (iens = iens1; iens <= iens2; iens++) { - node_id_type node_id = {.report_step = report_step , .iens = iens}; - if (enkf_node_try_load(node , fs, node_id)) { - char * full_path = path_fmt_alloc_path( file_fmt , false , iens); - char * path; - util_alloc_file_components(full_path , &path , NULL , NULL); - if (path != NULL) util_make_path( path ); - - { - const gen_data_type * gen_data = enkf_node_value_ptr(node); - msg_update(msg , full_path); - gen_data_export(gen_data , full_path , export_type , NULL); - } - - free(full_path); - util_safe_free(path); - } - } - enkf_node_free(node); - msg_free( msg , true ); - } - } -} - - - -void enkf_tui_export_profile(void * enkf_main) { - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - int iens1 , iens2; - const int last_report = enkf_main_get_history_length( enkf_main ); - bool * iens_active ; - bool * report_active; - - const enkf_config_node_type * config_node; - int direction; /* 0: i running, 1: j running, 2: k running */ - int total_cells; - int *cell_list; - path_fmt_type * file_fmt; - - config_node = enkf_tui_util_scanf_key(ensemble_config , PROMPT_LEN , FIELD , INVALID_VAR); - iens_active = enkf_tui_util_scanf_alloc_iens_active( ens_size , PROMPT_LEN , &iens1 , &iens2); /* Not used yet ... */ - report_active = enkf_tui_util_scanf_alloc_report_active( last_report , PROMPT_LEN ); - direction = util_scanf_int_with_limits("Give scan direction 0:i 1:j 2:k" , PROMPT_LEN , 0 , 2); - - { - const field_config_type * field_config = enkf_config_node_get_ref( config_node ); - int nx,ny,nz; - int i1,i2,j1,j2,k1,k2; - field_config_get_dims( field_config , &nx , &ny , &nz); - i2 = j2 = k2 = 0; /* Dummy for compiler */ - - /* i1,i2,j1,j2,k1 and k2 should be incluseive */ - switch (direction) { - case(0): - i1 = 0; i2 = nx-1; - enkf_tui_util_scanf_ijk__(field_config , PROMPT_LEN , NULL , &j1 , &k1); - j2 = j1; - k2 = k1; - break; - case(1): - j1 = 0; j2 = ny-1; - enkf_tui_util_scanf_ijk__(field_config , PROMPT_LEN , &i1 , NULL , &k1); - i2 = i1; - k2 = k1; - break; - case(2): - k1 = 0; k2 = nz-1; - enkf_tui_util_scanf_ijk__(field_config , PROMPT_LEN , &i1 , &j1 , NULL); - i2 = i1; - j2 = j1; - break; - default: - util_abort("%s: internal error \n",__func__); - } - total_cells = (i2 - i1 + 1) * (j2 - j1 + 1) * (k2 - k1 + 1); - cell_list = util_calloc(total_cells , sizeof * cell_list ); - { - int cell_index = 0; - int i,j,k; - for (i=i1; i<=i2; i++) - for (j= j1; j <=j2; j++) - for (k=k1; k <= k2; k++) { - cell_list[cell_index] = field_config_active_index(field_config , i,j,k); - cell_index++; - } - } - - file_fmt = path_fmt_scanf_alloc("Give filename to store profiles (with TWO %d specifiers) =>" , 0 , NULL , false); - { - double * profile = util_calloc(total_cells , sizeof * profile ); - int iens , report_step; - enkf_node_type * node = enkf_node_alloc( config_node ); - enkf_fs_type * fs = enkf_main_tui_get_fs(enkf_main); - - for (report_step = 0; report_step <= last_report; report_step++) { - if (report_active[report_step]) { - for (iens = iens1; iens <= iens2; iens++) { - node_id_type node_id = {.report_step = report_step , .iens = iens }; - if (enkf_node_try_load(node , fs, node_id)) { - { - const field_type * field = enkf_node_value_ptr( node ); - int field_index; - for (field_index = 0 ; field_index < total_cells; field_index++) - profile[field_index] = field_iget_double(field , cell_list[field_index]); - { - char * filename = path_fmt_alloc_file(file_fmt , true , report_step , iens); - FILE * stream = util_fopen(filename , "w"); - for (field_index = 0; field_index < total_cells; field_index++) - fprintf(stream, "%d %g\n",field_index , profile[field_index]); - - fclose(stream); - free(filename); - } - } - } else - fprintf(stderr," ** Warning field:%s is missing for member,report: %d,%d \n",enkf_config_node_get_key(config_node) , iens , report_step); - } - } - } - free(iens_active); - free(report_active); - free(profile); - } - } - free(cell_list); - } -} - - - - - - -void enkf_tui_export_cell(void * enkf_main) { - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - { - const enkf_config_node_type * config_node; - int cell_nr; - - config_node = enkf_tui_util_scanf_key(ensemble_config , PROMPT_LEN , FIELD , INVALID_VAR); - cell_nr = enkf_tui_util_scanf_ijk(enkf_config_node_get_ref(config_node) , PROMPT_LEN); - { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - const int last_report = enkf_main_get_history_length( enkf_main ); - int iens1 , iens2; - bool * iens_active = enkf_tui_util_scanf_alloc_iens_active( ens_size , PROMPT_LEN , &iens1 , &iens2); /* Not used yet ... */ - bool * report_active = enkf_tui_util_scanf_alloc_report_active( last_report , PROMPT_LEN); - double * cell_data = util_calloc(ens_size , sizeof * cell_data); - int iens , report_step; /* Observe that iens and report_step loops below should be inclusive.*/ - enkf_node_type * node = enkf_node_alloc( config_node ); - enkf_fs_type * fs = enkf_main_tui_get_fs(enkf_main); - path_fmt_type * file_fmt = path_fmt_scanf_alloc("Give filename to store historgrams (with %d for report step) =>" , 0 , NULL , false); - - - for (report_step = 0; report_step <= last_report; report_step++) { - if (report_active[report_step]) { - node_id_type node_id = {.report_step = report_step , .iens = iens1 }; - if (enkf_node_try_load(node , fs , node_id)) { - for (iens = iens1; iens <= iens2; iens++) { - node_id.iens = iens; - if (enkf_node_try_load(node , fs , node_id )) { - { - const field_type * field = enkf_node_value_ptr( node ); - cell_data[iens] = field_iget_double(field , cell_nr); - } - } else { - fprintf(stderr," ** Warning field:%s is missing for member,report: %d,%d \n",enkf_config_node_get_key(config_node) , iens , report_step); - cell_data[iens] = -1; - } - } - { - char * filename = path_fmt_alloc_file(file_fmt , true , report_step); - FILE * stream = util_fopen(filename , "w"); - for (iens = iens1; iens <= iens2; iens++) - fprintf(stream,"%g\n",cell_data[iens]); - - fclose(stream); - free(filename); - } - } else printf("Skipping report_step:%d \n",report_step); - } - } - free(iens_active); - free(report_active); - free(cell_data); - path_fmt_free(file_fmt); - } - } -} - - - - -void enkf_tui_export_time(void * enkf_main) { - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - { - const enkf_config_node_type * config_node; - int cell_nr; - - config_node = enkf_tui_util_scanf_key(ensemble_config , PROMPT_LEN , FIELD ,INVALID_VAR); - cell_nr = enkf_tui_util_scanf_ijk(enkf_config_node_get_ref(config_node) , PROMPT_LEN); - { - const int last_report = enkf_main_get_history_length( enkf_main ); - const int step1 = util_scanf_int_with_limits("First report step",PROMPT_LEN , 0 , last_report); - const int step2 = util_scanf_int_with_limits("Last report step",PROMPT_LEN , step1 , last_report); - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - int iens1 , iens2; - bool * iens_active = enkf_tui_util_scanf_alloc_iens_active( ens_size , PROMPT_LEN , &iens1 , &iens2); /* Not used yet ... */ - double * x, *y; - int iens; /* Observe that iens and report_step loops below should be inclusive.*/ - enkf_node_type * node = enkf_node_alloc( config_node ); - enkf_fs_type * fs = enkf_main_tui_get_fs(enkf_main); - path_fmt_type * file_fmt = path_fmt_scanf_alloc("Give filename to store line (with %d for report iens) =>" , 0 , NULL , false); - - - { - x = util_calloc( (step2 - step1 + 1) , sizeof * x); - y = util_calloc( (step2 - step1 + 1) , sizeof * y); - } - - - for (iens = iens1; iens <= iens2; iens++) { - enkf_tui_util_get_time(fs , config_node , node , cell_nr , step1 , step2 , iens , x ,y); - { - char * filename = path_fmt_alloc_file(file_fmt , true , iens); - FILE * stream = util_fopen(filename , "w"); - int index = 0; - int report_step; - for (report_step = step1; report_step <= step2; report_step++) { - fprintf(stream , "%g %g \n",x[index] , y[index]); - index++; - } - fclose(stream); - free(filename); - } - } - free(iens_active); - free(x); - free(y); - path_fmt_free(file_fmt); - } - } -} - - -/*****************************************************************/ - -void enkf_tui_export_fieldP(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - const enkf_config_node_type * config_node = enkf_tui_util_scanf_key(ensemble_config , PROMPT_LEN , FIELD , INVALID_VAR ); - int iens1 = 0; - int iens2 = enkf_main_get_ensemble_size( enkf_main ); - const int last_report = enkf_main_get_history_length( enkf_main ); - int report_step = util_scanf_int_with_limits("Report step: ", PROMPT_LEN , 0 , last_report); - double lower_limit = util_scanf_double("Lower limit", PROMPT_LEN); - double upper_limit = util_scanf_double("Upper limit", PROMPT_LEN); - char * export_file; - util_printf_prompt("Filename to store file: " , PROMPT_LEN , '=' , "=> "); - export_file = util_alloc_stdin_line(); - { - enkf_fs_type * fs = enkf_main_tui_get_fs(enkf_main); - enkf_node_type ** ensemble = enkf_node_load_alloc_ensemble( config_node , fs , report_step , iens1 , iens2 ); - enkf_node_type * sum = enkf_node_alloc( config_node ); - int active_ens_size = 0; - int iens; - - enkf_node_clear( sum ); - { - /* OK going low level */ - field_type * sum_field = enkf_node_value_ptr( sum ); - - for (iens = iens1; iens < iens2; iens++) { - if (ensemble[iens - iens1] != NULL) { - field_type * field = enkf_node_value_ptr( ensemble[iens - iens1] ); - field_update_sum( sum_field , field , lower_limit , upper_limit); - active_ens_size++; - } - } - if (active_ens_size > 0) { - field_scale( sum_field , 1.0 / active_ens_size ); - { - char * path; - util_alloc_file_components( export_file , &path , NULL , NULL); - if (path != NULL) { - util_make_path( path ); - free( path ); - } - } - field_export(sum_field , export_file , NULL , RMS_ROFF_FILE , false, NULL); - } else fprintf(stderr,"Warning: no data found \n"); - } - - for (iens = iens1; iens < iens2; iens++) { - if (ensemble[iens - iens1] != NULL) - enkf_node_free( ensemble[iens - iens1] ); - } - - free( ensemble ); - enkf_node_free( sum ); - } - free( export_file ); -} - - -/*****************************************************************/ - - -/** - This is a very simple function for exporting a scalar value for all - member/report steps to a CSV file. The file is characterized by: - - * Missing elements are represented with an empty string. - - * The header strings are quoted with "". - - * End of line is \r\n - - Unfortunately Excel does not seem to recognize the csv format, and - it is necessary to go through a text import wizard in excel. To - import this file you go through the following hoops in excel: - - 1. [Data> - [Import external data> - [Import data> - - 2. Select the file to import from. - - 3. The text import wizard from excel should pop up: - - 1. Select (*) Delimited - press next. - 2. Select delimiter "Comma" - press next. - 3. press finish. - - Finally you are asked where in the excel workbook you want to - insert the data. -*/ - - -#define CSV_NEWLINE "\r\n" -#define CSV_MISSING_VALUE "" -#define CSV_SEP "," - - -void enkf_tui_export_scalar2csv(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - const enkf_config_node_type * config_node; - char * user_key, *key_index; - - util_printf_prompt("Scalar to export (KEY:INDEX)" , PROMPT_LEN , '=' , "=> "); user_key = util_alloc_stdin_line(); - config_node = ensemble_config_user_get_node( ensemble_config , user_key , &key_index); - if (config_node != NULL) { - int report_step , first_report, last_report; - int iens1 , iens2, iens; - char * csv_file; - - iens2 = enkf_main_get_ensemble_size( enkf_main ) - 1; - iens1 = 0; - first_report = 0; - last_report = enkf_main_get_history_length( enkf_main ); - { - char * path; - char * prompt = util_alloc_sprintf("File to store \'%s\'", user_key); - util_printf_prompt(prompt , PROMPT_LEN , '=' , "=> "); - csv_file = util_alloc_stdin_line(); - - util_alloc_file_components( csv_file , &path , NULL , NULL); - if (path != NULL) { - if (util_entry_exists( path )) { - if (!util_is_directory( path )) { - /* The path component already exists in the filesystem - and it is not a directory - we leave the building. */ - fprintf(stderr,"Sorry: %s already exists - and is not a directory.\n",path); - free(path); - free(csv_file); - free(user_key); - return ; - } - } else { - /* The path does not exist - we make it. */ - enkf_tui_util_msg("Creating new directory: %s\n" , path); - util_make_path( path ); - } - } - free(prompt); - } - { - /* Seriously manual creation of csv file. */ - enkf_fs_type * fs = enkf_main_tui_get_fs(enkf_main); - enkf_node_type * node = enkf_node_alloc( config_node ); - FILE * stream = util_fopen( csv_file , "w"); - msg_type * msg = msg_alloc("Exporting report_step/member: " , false); - node_id_type node_id; - - - /* Header line */ - fprintf(stream , "\"Report step\""); - for (iens = iens1; iens <= iens2; iens++) - fprintf(stream , "%s\"%s(%d)\"" , CSV_SEP , user_key , iens); - fprintf(stream , CSV_NEWLINE); - - msg_show(msg); - for (report_step = first_report; report_step <= last_report; report_step++) { - fprintf(stream , "%6d" , report_step); - node_id.report_step = report_step; - for (iens = iens1; iens <= iens2; iens++) { - double value; - char label[32]; - /* - Have not implemented a choice on forecast/analyzed. Tries - analyzed first, then forecast. - */ - node_id.iens = iens; - sprintf(label , "%03d/%03d" , report_step , iens); - msg_update( msg , label); - - if (enkf_node_user_get( node , fs , key_index , node_id , &value)) - fprintf(stream , "%s%g" , CSV_SEP , value); - else - fprintf(stream , "%s%s" , CSV_SEP , CSV_MISSING_VALUE); - - } - fprintf(stream , CSV_NEWLINE); - } - - msg_free( msg , true ); - enkf_node_free( node ); - fclose(stream); - } - } else - fprintf(stderr,"Sorry - could not find any nodes with key:%s\n",user_key); - - free(user_key); -} - - -#undef CSV_NEWLINE -#undef CSV_MISSING_VALUE -#undef CSV_SEP - -/*****************************************************************/ - -void enkf_tui_export_stat(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - { - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - const enkf_config_node_type * config_node; - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - const int last_report = enkf_main_get_history_length( enkf_main ); - int report_step; - - config_node = enkf_tui_util_scanf_key( ensemble_config , PROMPT_LEN , INVALID , INVALID_VAR ); - report_step = util_scanf_int_with_limits("Report step: ", PROMPT_LEN , 0 , last_report); - { - char * mean_file , * mean_path; - char * std_file , * std_path; - - util_printf_prompt("Filename to store mean in " , PROMPT_LEN , '=' , "=> "); - { - char * tmp = util_alloc_stdin_line(); - char * mean_base , * mean_ext; - util_alloc_file_components( tmp , &mean_path , &mean_base , &mean_ext ); - if (mean_path != NULL) - util_make_path( mean_path ); - mean_file = util_alloc_filename( NULL , mean_base , mean_ext ); - util_safe_free( mean_base ); - util_safe_free( mean_ext ); - free( tmp ); - } - - util_printf_prompt("Filename to store std in " , PROMPT_LEN , '=' , "=> "); - { - char * tmp = util_alloc_stdin_line(); - char * std_base , * std_ext; - util_alloc_file_components( tmp , &std_path , &std_base , &std_ext ); - if (std_path != NULL) - util_make_path( std_path ); - std_file = util_alloc_filename( NULL , std_base , std_ext ); - util_safe_free( std_base ); - util_safe_free( std_ext ); - free( tmp ); - } - - { - enkf_node_type ** ensemble = enkf_main_get_node_ensemble( enkf_main , - enkf_main_tui_get_fs( enkf_main ) , - enkf_config_node_get_key( config_node ) , - report_step ); - enkf_node_type * mean = enkf_node_copyc( ensemble[0] ); - enkf_node_type * std = enkf_node_copyc( ensemble[0] ); - - /* Calculating */ - enkf_main_node_mean( (const enkf_node_type **) ensemble , ens_size , mean ); - enkf_main_node_std( (const enkf_node_type **) ensemble , ens_size , mean , std ); - - { - ecl_write_ftype * ecl_write_func = enkf_node_get_func_pointer( mean ); - ecl_write_func( enkf_node_value_ptr( mean ) , mean_path , mean_file , NULL ); - ecl_write_func( enkf_node_value_ptr( std ) , std_path , std_file , NULL ); - } - - free( ensemble ); - util_safe_free( std_file ); - util_safe_free( std_path ); - util_safe_free( mean_file ); - util_safe_free( mean_path ); - enkf_node_free( mean ); - enkf_node_free( std ); - } - } - } -} - - - - -void enkf_tui_export_menu(void * arg) { - - enkf_main_type * enkf_main = enkf_main_safe_cast(arg); - menu_type * menu = menu_alloc("Export data to other formats" , "Back" , "bB"); - menu_add_item(menu , "Export scalar value to CSV file" , "xX" , enkf_tui_export_scalar2csv , enkf_main , NULL); - menu_add_separator(menu); - menu_add_item(menu , "Export fields to RMS Roff format" , "rR" , enkf_tui_export_roff , enkf_main , NULL); - menu_add_item(menu , "Export fields to ECLIPSE grdecl format" , "gG" , enkf_tui_export_grdecl , enkf_main , NULL); - menu_add_item(menu , "Export fields to ECLIPSE restart format (active cells)" , "aA" , enkf_tui_export_restart_active , enkf_main , NULL); - menu_add_item(menu , "Export fields to ECLIPSE restart format (all cells)" , "lL" , enkf_tui_export_restart_all , enkf_main , NULL); - menu_add_separator(menu); - menu_add_item(menu , "Export P( a =< x < b )" , "sS" , enkf_tui_export_fieldP , enkf_main , NULL); - menu_add_separator(menu); - menu_add_item(menu , "Export cell values to text file(s)" , "cC" , enkf_tui_export_cell , enkf_main , NULL); - menu_add_item(menu , "Export line profile of a field to text file(s)" , "pP" , enkf_tui_export_profile , enkf_main , NULL); - menu_add_item(menu , "Export time development in one cell to text file(s)" , "tT" , enkf_tui_export_time , enkf_main , NULL); - menu_add_separator(menu); - menu_add_item(menu , "Export GEN_DATA/GEN_PARAM to file" , "dD" , enkf_tui_export_gen_data , enkf_main , NULL); - menu_add_separator( menu ); - menu_add_item(menu , "EclWrite mean and std" , "mM" , enkf_tui_export_stat , enkf_main , NULL ); - menu_add_item(menu , "Help" , "hH" , enkf_tui_help_menu_export , enkf_main , NULL ); - menu_run(menu); - menu_free(menu); -} diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_export.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_export.h deleted file mode 100644 index c7aa3021bd..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_export.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_export.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_EXPORT_H -#define ERT_ENKF_TUI_EXPORT_H - -void enkf_tui_export_menu(void *); - - - -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_fs.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_fs.c deleted file mode 100644 index e415060278..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_fs.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_fs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - - -void enkf_tui_fs_ls_case(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - stringlist_type * dirlist = enkf_main_alloc_caselist( enkf_main ); - int idir; - - printf("Available cases: "); - for (idir = 0; idir < stringlist_get_size( dirlist ); idir++) - printf("%s ",stringlist_iget( dirlist , idir )); - - printf("\n"); - stringlist_free( dirlist ); -} - - -void enkf_tui_fs_create_case(void * arg) -{ - int prompt_len = 50; - char new_case[256]; - char * menu_title; - - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - enkf_main_type * enkf_main = enkf_main_safe_cast( arg_pack_iget_ptr(arg_pack, 0) ); - menu_type * menu = arg_pack_iget_ptr(arg_pack, 1); - - util_printf_prompt("Name of new case" , prompt_len , '=' , "=> "); - if (fgets(new_case, prompt_len, stdin) != NULL){ - char *newline = strchr(new_case, '\n'); - if (newline) - *newline = 0; - - if(strlen(new_case) != 0) - enkf_main_select_fs( enkf_main , new_case ); - - } - menu_title = util_alloc_sprintf("Manage cases. Current: %s", enkf_main_get_current_fs(enkf_main)); - menu_set_title(menu, menu_title); - free(menu_title); -} - - - -/** - Return NULL if no action should be performed. -*/ -static char * enkf_tui_fs_alloc_existing_case(enkf_main_type * enkf_main , const char * prompt , int prompt_len) { - char * name; - while (true) { - util_printf_prompt(prompt , prompt_len , '=' , "=> "); - name = util_alloc_stdin_line(); - - if (name == NULL) /* The user entered a blank string */ - break; - else { - char * mount_point = enkf_main_alloc_mount_point( enkf_main , name ); - - if (enkf_fs_exists( mount_point )) - break; - else { - printf("** can not find case: \"%s\" \n",name); - free(name); - } - - free( mount_point ); - } - - } - - return name; -} - - - - -void enkf_tui_fs_select_case(void * arg) -{ - int prompt_len = 40; - char * new_case; - char * menu_title; - - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - enkf_main_type * enkf_main = enkf_main_safe_cast( arg_pack_iget_ptr(arg_pack, 0) ); - menu_type * menu = arg_pack_iget_ptr(arg_pack, 1); - new_case = enkf_tui_fs_alloc_existing_case( enkf_main , "Name of case" , prompt_len); - if (new_case != NULL) { - enkf_main_select_fs( enkf_main , new_case ); - - menu_title = util_alloc_sprintf("Manage cases. Current: %s", enkf_main_get_current_fs( enkf_main )); - menu_set_title(menu, menu_title); - free(menu_title); - free(new_case); - } -} - - - - - - -static void enkf_tui_fs_copy_ensemble__( - enkf_main_type * enkf_main, - const char * source_case, - const char * target_case, - int report_step_from, - int report_step_to, - bool only_parameters) -{ - msg_type * msg = msg_alloc("Copying: " , false); - ensemble_config_type * config = enkf_main_get_ensemble_config(enkf_main); - int ens_size = enkf_main_get_ensemble_size(enkf_main); - char * ranking_key; - const perm_vector_type * ranking_permutation = NULL; - int * identity_permutation_raw; - ranking_table_type * ranking_table = enkf_main_get_ranking_table( enkf_main ); - - - if (ranking_table_get_size( ranking_table ) > 0) { - util_printf_prompt("Name of ranking to resort by (or blank)" , 50 , '=' , "=> "); - ranking_key = util_alloc_stdin_line(); - if (ranking_table_has_ranking( ranking_table , ranking_key )) - ranking_permutation = ranking_table_get_permutation( ranking_table , ranking_key ); - else { - fprintf(stderr," Sorry: ranking:%s does not exist \n", ranking_key ); - return; - } - } - identity_permutation_raw = util_calloc( ens_size , sizeof * identity_permutation_raw ); - { - int iens; - for (iens =0; iens < ens_size; iens++) - identity_permutation_raw[iens] = iens; - } - - if (ranking_permutation == NULL) - ranking_permutation = perm_vector_alloc(identity_permutation_raw, ens_size); - - - { - /* If the current target_case does not exist it is automatically created by the select_write_dir function */ - enkf_fs_type * src_fs = enkf_main_mount_alt_fs( enkf_main , source_case , false ); - enkf_fs_type * target_fs = enkf_main_mount_alt_fs( enkf_main , target_case , true ); - - stringlist_type * nodes = ensemble_config_alloc_keylist_from_var_type(config, PARAMETER); - - { - int num_nodes = stringlist_get_size(nodes); - msg_show(msg); - for(int i = 0; i < num_nodes; i++) { - const char * key = stringlist_iget(nodes, i); - enkf_config_node_type * config_node = ensemble_config_get_node(config , key); - msg_update(msg , key); - enkf_node_copy_ensemble(config_node, src_fs , target_fs , report_step_from, report_step_to , ens_size , ranking_permutation); - } - } - - enkf_fs_decref( src_fs ); - enkf_fs_decref( target_fs ); - - msg_free(msg , true); - stringlist_free(nodes); - } - free( identity_permutation_raw ); -} - - - - - -void enkf_tui_fs_initialize_case_from_copy(void * arg) -{ - int prompt_len =50; - char * source_case; - int ens_size; - int last_report; - int src_step; - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - - ens_size = enkf_main_get_ensemble_size( enkf_main ); - - - last_report = enkf_main_get_history_length( enkf_main ); - - source_case = enkf_tui_fs_alloc_existing_case( enkf_main , "Initialize from case" , prompt_len); - if (source_case != NULL) { - src_step = util_scanf_int_with_limits("Source report step",prompt_len , 0 , last_report); - enkf_fs_type * source_fs = enkf_main_mount_alt_fs( enkf_main , source_case , false ); - enkf_main_init_current_case_from_existing(enkf_main, source_fs , src_step); - enkf_fs_decref(source_fs); - } - util_safe_free( source_case ); -} - - - -void enkf_tui_fs_copy_ensemble(void * arg) -{ - int prompt_len = 35; - char * source_case; - - int last_report; - int report_step_from; - char * report_step_from_as_char; - int report_step_to; - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - - source_case = util_alloc_string_copy(enkf_main_get_current_fs( enkf_main )); - last_report = enkf_main_get_history_length( enkf_main ); - - report_step_from_as_char = util_scanf_int_with_limits_return_char("Source report step",prompt_len , 0 , last_report); - if(strlen(report_step_from_as_char) !=0){ - util_sscanf_int(report_step_from_as_char , &report_step_from); - { - util_printf_prompt("Target case" , prompt_len , '=' , "=> "); - char target_case[256]; - - if ( fgets(target_case, prompt_len, stdin)) { - char *newline = strchr(target_case, '\n'); - if (newline) - *newline = 0; - } - - if (strlen(target_case)) { - char * report_step_to_as_char = util_scanf_int_with_limits_return_char("Target report step",prompt_len , 0 , last_report); - if (strlen(report_step_to_as_char)) { - util_sscanf_int(report_step_to_as_char , &report_step_to); - enkf_tui_fs_copy_ensemble__(enkf_main, source_case, target_case, report_step_from, report_step_to, false); - } - free(report_step_to_as_char); - } - } - } - free(source_case); - free(report_step_from_as_char); -} - - - -void enkf_tui_fs_copy_ensemble_of_parameters(void * arg) -{ - int prompt_len = 35; - char * source_case; - - int last_report; - int report_step_from; - char * report_step_from_as_char; - int report_step_to; - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - - source_case = util_alloc_string_copy(enkf_main_get_current_fs( enkf_main )); - last_report = enkf_main_get_history_length( enkf_main ); - - report_step_from_as_char = util_scanf_int_with_limits_return_char("Source report step",prompt_len , 0 , last_report); - if(strlen(report_step_from_as_char) !=0){ - util_sscanf_int(report_step_from_as_char , &report_step_from); - { - - util_printf_prompt("Target case" , prompt_len , '=' , "=> "); - char target_case[256]; - - if ( fgets(target_case, prompt_len, stdin) ) { - char *newline = strchr(target_case, '\n'); - if (newline) - *newline = 0; - } - - if (strlen(target_case)) { - char * report_step_to_as_char = util_scanf_int_with_limits_return_char("Target report step",prompt_len , 0 , last_report); - if(strlen(report_step_to_as_char) !=0){ - util_sscanf_int(report_step_to_as_char , &report_step_to); - enkf_tui_fs_copy_ensemble__(enkf_main, source_case, target_case, report_step_from, report_step_to, true); - } - free(report_step_to_as_char); - } - } - } - free(source_case); - free(report_step_from_as_char); -} - - -void enkf_tui_fs_menu(void * arg) { - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - - const char * menu_title = util_alloc_sprintf("Manage cases - current: %s", enkf_main_get_current_fs( enkf_main )); - menu_type * menu = menu_alloc(menu_title , "Back" , "bB"); - - menu_add_item(menu , "List available cases" , "lL" , enkf_tui_fs_ls_case , enkf_main , NULL); - - { - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr(arg_pack , enkf_main); - arg_pack_append_ptr(arg_pack , menu); - menu_add_item(menu , "Create and select new case" , "cC" , enkf_tui_fs_create_case, arg_pack , arg_pack_free__); - } - - { - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr(arg_pack , enkf_main); - arg_pack_append_ptr(arg_pack , menu); - menu_add_item(menu , "Select case" , "sS" , enkf_tui_fs_select_case, arg_pack , arg_pack_free__); - } - - menu_add_separator(menu); - menu_add_item(menu, "Initialize case from scratch" , "iI" , enkf_tui_init_menu , enkf_main , NULL); - menu_add_item(menu, "Initialize case from existing case" , "aA" , enkf_tui_fs_initialize_case_from_copy , enkf_main , NULL); - - menu_add_separator(menu); - /* Are these two in use??? */ - menu_add_item(menu, "Copy full ensemble to another case", "eE", enkf_tui_fs_copy_ensemble, enkf_main, NULL); - menu_add_item(menu, "Copy ensemble of parameters to another case", "oO", enkf_tui_fs_copy_ensemble_of_parameters, enkf_main, NULL); - menu_add_item(menu , "Help" , "hH" , enkf_tui_help_menu_cases , enkf_main , NULL); - - menu_run(menu); - menu_free(menu); -} - diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_fs.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_fs.h deleted file mode 100644 index 49b8f1efc3..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_fs.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_fs.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_FS_H -#define ERT_ENKF_TUI_FS_H - -void enkf_tui_fs_menu(void * ); - -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_help.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_help.c deleted file mode 100644 index 6297ad91aa..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_help.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'enkf_tui_QC.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - - -void enkf_tui_help_manual_main( void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const site_config_type * site_config = enkf_main_get_site_config ( enkf_main ); - const char * manual_url = site_config_get_manual_url( site_config ); - const char * browser = getenv("BROWSER"); - - if (browser == NULL) - browser = site_config_get_default_browser( site_config ); - - { - char * cmd = util_alloc_sprintf("%s %s &" , browser , manual_url); - system(cmd); - free( cmd ); - } -} - -void enkf_tui_help_menu_main(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - { - menu_type * menu = menu_alloc("Help: Main menu" , "Back" , "bB"); - menu_add_helptext(menu , "Choose the different options from the main menu to read more about the different options."); - menu_add_item(menu , "Open manual (firefox)" , "mM" , enkf_tui_help_manual_main , enkf_main , NULL); - menu_run(menu); - menu_free(menu); - } -} - -void enkf_tui_help_manual_cases( void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const site_config_type * site_config = enkf_main_get_site_config ( enkf_main ); - const char * manual_url = site_config_get_manual_url( site_config ); - const char * browser = getenv("BROWSER"); - - if (browser == NULL) - browser = site_config_get_default_browser( site_config ); - - { - char * cmd = util_alloc_sprintf("%s %s%s &" , browser , manual_url , "#Manage_cases"); - system(cmd); - free( cmd ); - } -} - -void enkf_tui_help_menu_cases(void * arg) { - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - menu_type * menu = menu_alloc("Help: Manage cases" , "Back" , "bB"); - menu_add_helptext(menu , "Use this menu to navgate between cases and to initialize cases. A case has to be initialized before it can be used."); - menu_add_item(menu , "Open manual (firefox)" , "mM" , enkf_tui_help_manual_cases , enkf_main , NULL); - menu_run(menu); - menu_free(menu); -} - -void enkf_tui_help_manual_run( void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const site_config_type * site_config = enkf_main_get_site_config ( enkf_main ); - const char * manual_url = site_config_get_manual_url( site_config ); - const char * browser = getenv("BROWSER"); - - if (browser == NULL) - browser = site_config_get_default_browser( site_config ); - - { - char * cmd = util_alloc_sprintf("%s %s%s &" , browser , manual_url , "#Run_or_restart_experiment"); - system(cmd); - free( cmd ); - } -} - -void enkf_tui_help_menu_run(void * arg) { - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - menu_type * menu = menu_alloc("Help: Run menu" , "Back" , "bB"); - menu_add_helptext(menu , "This menu is used to do the main work in ERT. The first option, x: Ensemble run: history, will just run the case without any data conditioning. Options r and s will initiate classical enkf runs. The two options i and t invokes the ensemble kalman smoother."); - menu_add_item(menu , "Open manual (firefox)" , "mM" , enkf_tui_help_manual_run , enkf_main , NULL); - menu_run(menu); - menu_free(menu); -} - - -void enkf_tui_help_manual_rank( void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const site_config_type * site_config = enkf_main_get_site_config ( enkf_main ); - const char * manual_url = site_config_get_manual_url( site_config ); - const char * browser = getenv("BROWSER"); - - if (browser == NULL) - browser = site_config_get_default_browser( site_config ); - - { - char * cmd = util_alloc_sprintf("%s %s%s &" , browser , manual_url , "#Rank_Results"); - system(cmd); - free( cmd ); - } -} - -void enkf_tui_help_menu_rank(void * arg) { - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - menu_type * menu = menu_alloc("Help: Rank results" , "Back" , "bB"); - menu_add_helptext(menu , "Use this option to rank results after the case has been run."); - menu_add_item(menu , "Open manual (firefox)" , "mM" , enkf_tui_help_manual_rank , enkf_main , NULL); - menu_run(menu); - menu_free(menu); -} - -void enkf_tui_help_manual_export( void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const site_config_type * site_config = enkf_main_get_site_config ( enkf_main ); - const char * manual_url = site_config_get_manual_url( site_config ); - const char * browser = getenv("BROWSER"); - - if (browser == NULL) - browser = site_config_get_default_browser( site_config ); - - { - char * cmd = util_alloc_sprintf("%s %s%s &" , browser , manual_url , "#Export_data_to_other_formats"); - system(cmd); - free( cmd ); - } -} - -void enkf_tui_help_menu_export(void * arg) { - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - menu_type * menu = menu_alloc("Help: Export results" , "Back" , "bB"); - menu_add_helptext(menu , "Use this option to export results after the case has been run."); - menu_add_item(menu , "Open manual (firefox)" , "mM" , enkf_tui_help_manual_export , enkf_main , NULL); - menu_run(menu); - menu_free(menu); -} - -void enkf_tui_help_manual_table( void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const site_config_type * site_config = enkf_main_get_site_config ( enkf_main ); - const char * manual_url = site_config_get_manual_url( site_config ); - const char * browser = getenv("BROWSER"); - - if (browser == NULL) - browser = site_config_get_default_browser( site_config ); - - { - char * cmd = util_alloc_sprintf("%s %s%s &" , browser , manual_url , "#Table_of_results"); - system(cmd); - free( cmd ); - } -} - -void enkf_tui_help_menu_table(void * arg) { - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - menu_type * menu = menu_alloc("Help: Table of results" , "Back" , "bB"); - menu_add_helptext(menu , "This option can generate a table of results after the case has been run."); - menu_add_item(menu , "Open manual (firefox)" , "mM" , enkf_tui_help_manual_table , enkf_main , NULL); - menu_run(menu); - menu_free(menu); -} - -void enkf_tui_help_manual_misc( void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const site_config_type * site_config = enkf_main_get_site_config ( enkf_main ); - const char * manual_url = site_config_get_manual_url( site_config ); - const char * browser = getenv("BROWSER"); - - if (browser == NULL) - browser = site_config_get_default_browser( site_config ); - - { - char * cmd = util_alloc_sprintf("%s %s%s &" , browser , manual_url , "#Miscellaneous"); - system(cmd); - free( cmd ); - } -} - -void enkf_tui_help_menu_misc(void * arg) { - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - menu_type * menu = menu_alloc("Help: Miscellanous" , "Back" , "bB"); - menu_add_helptext(menu , "This option contains miscellaneous options."); - menu_add_item(menu , "Open manual (firefox)" , "mM" , enkf_tui_help_manual_misc , enkf_main , NULL); - menu_run(menu); - menu_free(menu); -} - -void enkf_tui_help_menu_simple(void * arg) { - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - menu_type * menu = menu_alloc("Help: Simple menu" , "Back" , "bB"); - menu_add_helptext(menu , "The top four options in the simple menu will run eclipse simulations. Option s: Sensitivity run: No data conditioning, will initialize all parameters and run one eclipse simulation for each set of different parameters. e: Assimilation run: EnKF updates, will initialize all parameters and run one eclipse simulation for each set of different parameters. The eclipse simulations will run until the first data time step is encountered and condition on data before continuing. a: Assimilation run: Smoother update, will do one pass of the sensitivity run, then condition the parameters to all the data and rerun all experiments. i: Assimilation run: Iterated smoother [RML-EnKF] will iterate the smoother run several times."); - menu_add_item(menu , "Open manual (firefox)" , "mM" , enkf_tui_help_manual_main , enkf_main , NULL); - menu_run(menu); - menu_free(menu); -} - diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_help.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_help.h deleted file mode 100644 index b9f0a5ec0b..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_help.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'enkf_tui_QC.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_HELP_H -#define ERT_ENKF_TUI_HELP_H - - - -void enkf_tui_help_menu_main(void * ); -void enkf_tui_help_menu_cases(void * ); -void enkf_tui_help_menu_run(void * ); -void enkf_tui_help_menu_plot(void * ); -void enkf_tui_help_menu_rank(void * ); -void enkf_tui_help_menu_export(void * ); -void enkf_tui_help_menu_table(void * ); -void enkf_tui_help_menu_misc(void * ); -void enkf_tui_help_menu_simple(void * ); -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_init.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_init.c deleted file mode 100644 index b028caefa7..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_init.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_init.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - - - - -void enkf_tui_init(enkf_main_type * enkf_main, bool all_members , bool all_parameters , bool interval ) { - const int prompt_len = 35; - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - int ens_size = enkf_main_get_ensemble_size( enkf_main ); - int iens1, iens2; - init_mode_type init_mode = INIT_FORCE; - bool iens_valid = false; - - /* iens2 should be interpreted as __inclusive__ */ - if ( all_members ) { - iens1 = 0; - iens2 = ens_size - 1; - iens_valid = true; - } else { - if( interval ) { - char * iens1char = util_scanf_int_with_limits_return_char("First ensemble member in interval" , prompt_len , 0 , ens_size - 1); - if (strlen(iens1char)) { - util_sscanf_int(iens1char , &iens1); - char * iens2char = util_scanf_int_with_limits_return_char("Second ensemble member in interval" , prompt_len , iens1 , ens_size - 1); - if (strlen(iens2char)) { - util_sscanf_int(iens2char , &iens2); - iens_valid = true; - } - free(iens2char); - } - free(iens1char); - } else { - char * iens1char = util_scanf_int_with_limits_return_char("Initialize ensemble member" , prompt_len , 0 , ens_size - 1); - if (strlen(iens1char)) { - util_sscanf_int(iens1char , &iens1); - iens2 = iens1; - iens_valid = true; - } - free(iens1char); - } - } - - if (iens_valid) { - stringlist_type * param_list = NULL; - if (all_parameters) - param_list = ensemble_config_alloc_keylist_from_var_type( ensemble_config , PARAMETER ); - else { - const enkf_config_node_type * config_node = NULL; - param_list = stringlist_alloc_new(); - config_node = enkf_tui_util_scanf_key(ensemble_config , prompt_len , INVALID , INVALID_VAR); - if( config_node != NULL ) - stringlist_append_copy( param_list , enkf_config_node_get_key(config_node)); - } - - if (param_list != NULL) { - enkf_fs_type * init_fs = enkf_main_tui_get_fs( enkf_main ); - bool_vector_type * iens_mask = bool_vector_alloc( ens_size , false ); - bool_vector_iset_block( iens_mask , iens1 , iens2 - iens1 + 1, true ); - enkf_main_initialize_from_scratch(enkf_main , init_fs , param_list , iens_mask , init_mode); - bool_vector_free( iens_mask ); - stringlist_free( param_list ); - } - } -} - - -static void enkf_tui_init1(void * enkf_main) { - enkf_tui_init(enkf_main, true , true , false); -} - -static void enkf_tui_init2(void * enkf_main) { - enkf_tui_init(enkf_main , true , false , false); -} - -static void enkf_tui_init3(void * enkf_main) { - enkf_tui_init(enkf_main , false , true , false); -} - -static void enkf_tui_init4(void * enkf_main) { - enkf_tui_init(enkf_main , false , false, false); -} - -static void enkf_tui_init5(void * enkf_main) { - enkf_tui_init(enkf_main , false , true, true); -} - -static void enkf_tui_init6(void * enkf_main) { - enkf_tui_init(enkf_main , false , false, true); -} - -void enkf_tui_init_menu(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast(arg); - - menu_type * menu = menu_alloc("Initialize from scratch" , "Back" , "bB"); - menu_add_item(menu , "Initialize all members/all parameters" , "1" , enkf_tui_init1 , enkf_main , NULL); - menu_add_item(menu , "Initialize all members/one parameter" , "2" , enkf_tui_init2 , enkf_main , NULL); - menu_add_item(menu , "Initialize one member/all parameters" , "3" , enkf_tui_init3 , enkf_main , NULL); - menu_add_item(menu , "Initialize one member/one parameter" , "4" , enkf_tui_init4 , enkf_main , NULL); - menu_add_item(menu , "Initialize interval of ensemble members/all parameters" , "5" , enkf_tui_init5 , enkf_main , NULL); - menu_add_item(menu , "Initialize interval of ensemble members/one parameter" , "6" , enkf_tui_init6 , enkf_main , NULL); - menu_run(menu); - menu_free(menu); - -} diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_init.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_init.h deleted file mode 100644 index 73bc1f78c2..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_init.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_init.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_INIT_H -#define ERT_ENKF_TUI_INIT_H - - -void enkf_tui_init_menu(void * ); - - -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_main.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_main.c deleted file mode 100644 index 0741f7c9c0..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_main.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_main.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/** - This file implements the (text based) user interface in the enkf - system. -*/ - - - -/** - The main loop. -*/ - - - - - -void enkf_tui_main_menu(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - menu_type * menu = menu_alloc("Main menu" , "Quit" , "qQ"); - - menu_add_item(menu , "Manage cases" , "cC" , enkf_tui_fs_menu , enkf_main , NULL); - menu_add_item(menu , "Run, restart or analyse experiment" , "rR" , enkf_tui_run_menu , enkf_main , NULL); - menu_add_item(menu , "Rank results" , "aA" , enkf_tui_ranking_menu , enkf_main , NULL); - menu_add_item(menu , "Export data to other formats" , "eE" , enkf_tui_export_menu , enkf_main , NULL); - menu_add_item(menu , "Table of results" , "tT" , enkf_tui_table_menu , enkf_main , NULL); - menu_add_item(menu , "Miscellanous" , "mM" , enkf_tui_misc_menu , enkf_main , NULL); - menu_add_item(menu , "Workflows" , "wW" , enkf_tui_workflow_menu , enkf_main , NULL); - menu_add_item(menu , "Help" , "hH" , enkf_tui_help_menu_main , enkf_main , NULL); - menu_add_item(menu , "Simple menu" , "sS" , enkf_tui_simple_menu , enkf_main , NULL); - menu_run(menu); - menu_free(menu); -} - - diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_main.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_main.h deleted file mode 100644 index 0016bb50c4..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_main.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_main.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_INTER_MAIN_H -#define ERT_ENKF_INTER_MAIN_H -#include - - -void enkf_tui_main_menu(void * arg); - - -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_misc.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_misc.c deleted file mode 100644 index 790cbe26da..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_misc.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_misc.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include - -static void enkf_tui_misc_printf_subst_list(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - - /* These could/should be user input ... */ - int step1 = 0; /* < 0 => no reinitializtion of the dynamic substitutions. */ - int step2 = 10; - int iens = 0; - - enkf_state_type * enkf_state = enkf_main_iget_state( enkf_main , iens ); - enkf_state_printf_subst_list( enkf_state , step1 , step2 ); -} - - -static void enkf_tui_misc_list_jobs(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const ext_joblist_type * installed_jobs = enkf_main_get_installed_jobs( enkf_main ); - stringlist_type * job_names = ext_joblist_alloc_list( installed_jobs ); - int job_nr; - stringlist_sort( job_names , NULL ); - printf("================================================================================\n"); - printf("%-30s : Arguments\n" , "Job name"); - printf("--------------------------------------------------------------------------------\n"); - for (job_nr = 0; job_nr < stringlist_get_size( job_names ); job_nr++) { - const ext_job_type * job = ext_joblist_get_job( installed_jobs , stringlist_iget( job_names , job_nr )); - const stringlist_type * arglist = ext_job_get_arglist( job ); - printf("%-30s : " , stringlist_iget( job_names , job_nr )); - if (arglist != NULL) - stringlist_fprintf( arglist , " " , stdout ); - printf("\n"); - } - printf("================================================================================\n"); - stringlist_free( job_names ); -} - - - - -void enkf_tui_misc_menu( void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - menu_type * menu = menu_alloc( "Misceallanous stuff" , "Back" , "bB"); - menu_add_item(menu , "List all \'magic\' <...> strings" , "lL" , enkf_tui_misc_printf_subst_list , enkf_main , NULL); - menu_add_item(menu , "List all available forward model jobs","jJ" , enkf_tui_misc_list_jobs , enkf_main , NULL ); - menu_add_item(menu , "Help","hH" , enkf_tui_help_menu_misc , enkf_main , NULL ); - menu_run(menu); - menu_free(menu); -} diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_misc.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_misc.h deleted file mode 100644 index 0a260649ab..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_misc.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_misc.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_MISC_H -#define ERT_ENKF_TUI_MISC_H - - -void enkf_tui_misc_menu( void * arg); - - -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_ranking.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_ranking.c deleted file mode 100644 index d4267c7227..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_ranking.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_ranking.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -static void enkf_tui_ranking_make_misfit_ensemble( void * arg) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - enkf_main_type * enkf_main = arg_pack_iget_ptr( arg_pack , 0 ); - - enkf_fs_type * fs = enkf_main_tui_get_fs(enkf_main); - enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - const int history_length = enkf_main_get_history_length( enkf_main ); - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - - - misfit_ensemble_type * misfit_ensemble = enkf_fs_get_misfit_ensemble( fs ); - misfit_ensemble_initialize( misfit_ensemble , ensemble_config , enkf_obs , fs , ens_size , history_length , false); - { - menu_item_type * obs_item = arg_pack_iget_ptr( arg_pack , 1 ); - menu_item_enable( obs_item ); - } -} - - -static void enkf_tui_ranking_create_obs( void * arg ) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - enkf_fs_type * fs = enkf_main_tui_get_fs( enkf_main ); - misfit_ensemble_type * misfit_ensemble = enkf_fs_get_misfit_ensemble( fs ); - - if (!misfit_ensemble_initialized( misfit_ensemble )) { - fprintf(stderr,"Sorry: must initialzie the misfit table first \n"); - return; - } else { - ranking_table_type * ranking_table = enkf_main_get_ranking_table( enkf_main ); - const int history_length = enkf_main_get_history_length( enkf_main ); - const int prompt_len = 50; - const char * prompt1 = "Observations to use for ranking"; - const char * prompt2 = "Name to store ranking under"; - const char * store_prompt = "Name of file to store ranking"; - int step1,step2; - stringlist_type * ranking_keys; - char * obs_keys_input; - char * ranking_key; - char * ranking_file; - util_printf_prompt(prompt1 , prompt_len , '=' , "=> "); - obs_keys_input = util_alloc_stdin_line(); - ranking_keys = enkf_obs_alloc_matching_keylist( enkf_obs , obs_keys_input ); - enkf_tui_util_scanf_report_steps(history_length , prompt_len , &step1 , &step2); - - util_printf_prompt(prompt2 , prompt_len , '=' , "=> "); - ranking_key = util_alloc_stdin_line(); - if (ranking_key == NULL) - ranking_key = util_alloc_string_copy( MISFIT_DEFAULT_RANKING_KEY ); - - util_printf_prompt(store_prompt , prompt_len , '=' , "=> "); - ranking_file = util_alloc_stdin_line(); - - char * report_steps = util_alloc_sprintf("%d-%d", step1, step2); - int_vector_type * steps_vector = string_util_alloc_value_list(report_steps); - - if (stringlist_get_size( ranking_keys ) > 0) { - ranking_table_add_misfit_ranking( ranking_table , misfit_ensemble , ranking_keys , steps_vector, ranking_key ); - ranking_table_display_ranking( ranking_table , ranking_key); - } else - fprintf(stderr,"The input string : \"%s\" did not resolve to any valid observation keys \n", obs_keys_input); - - free(report_steps); - int_vector_free(steps_vector); - free( obs_keys_input ); - stringlist_free( ranking_keys ); - free( ranking_key ); - util_safe_free( ranking_file ); - } -} - - - - -static void enkf_tui_ranking_create_data__( void * arg , bool sort_increasing) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - ranking_table_type * ranking_table = enkf_main_get_ranking_table( enkf_main ); - enkf_fs_type * fs = enkf_main_tui_get_fs( enkf_main ); - ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config( enkf_main ); - time_map_type * time_map = enkf_fs_get_time_map( fs ); - const int prompt_len = 60; - const char * prompt1 = "Data key to use for ranking"; - const char * prompt2 = "Report step of data [Blank: last step]"; - const char * ranking_name = "Name of new ranking"; - - char * user_key; - - util_printf_prompt(prompt1 , prompt_len , '=' , "=> "); - user_key = util_alloc_stdin_line(); - if (user_key != NULL) { - util_printf_prompt( prompt2 , prompt_len , '=' , "=> "); - { - int step = -1; - { - char * step_char = util_alloc_stdin_line(); - - if (step_char == NULL) - step = time_map_get_last_step( time_map ); - else { - util_sscanf_int( step_char , &step ); - free( step_char ); - } - } - - if (step >= 0) { - const enkf_config_node_type * config_node; - char * key_index; - config_node = ensemble_config_user_get_node( ensemble_config , user_key , &key_index); - if (config_node) { - util_printf_prompt(ranking_name , prompt_len , '=' , "=> "); - char * ranking_key = util_alloc_stdin_line(); - if (ranking_key != NULL) { - ranking_table_add_data_ranking( ranking_table , sort_increasing , ranking_key , user_key , key_index , fs , config_node, step ); - ranking_table_display_ranking( ranking_table , ranking_key ); - } - util_safe_free( ranking_key ); - } - } - } - } - util_safe_free( user_key ); -} - -static void enkf_tui_ranking_create_data_increasing( void * arg ) { - enkf_tui_ranking_create_data__( arg , true ); -} - - -static void enkf_tui_ranking_create_data_decreasing( void * arg ) { - enkf_tui_ranking_create_data__( arg , false ); -} - - - -static void enkf_tui_ranking_display( void * arg ) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - ranking_table_type * ranking_table = enkf_main_get_ranking_table( enkf_main ); - - const int prompt_len = 50; - const char * prompt1 = "Ranking to display"; - char * ranking_key; - - util_printf_prompt(prompt1 , prompt_len , '=' , "=> "); - ranking_key = util_alloc_stdin_line(); - if (ranking_key == NULL) - ranking_key = util_alloc_string_copy( MISFIT_DEFAULT_RANKING_KEY); - if (ranking_table_has_ranking( ranking_table , ranking_key)) - ranking_table_display_ranking( ranking_table , ranking_key); - else - fprintf(stderr,"Sorry: could not find ranking key: %s \n", ranking_key ); - - free( ranking_key ); -} - - -void enkf_tui_ranking_menu(void * arg) { - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - { - menu_type * menu = menu_alloc("Ranking of results" , "Back" , "bB"); - menu_item_type * obs_item; - { - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr( arg_pack , enkf_main ); - menu_add_item(menu , "Create/update misfit table" , "cC" , enkf_tui_ranking_make_misfit_ensemble , arg_pack , arg_pack_free__); - menu_add_separator( menu ); - obs_item = menu_add_item(menu , "New observation based ranking" , "nN" , enkf_tui_ranking_create_obs , enkf_main , NULL); - arg_pack_append_ptr( arg_pack , obs_item ); - } - menu_add_item(menu , "New data based ranking (Sort: increasing)" , "iI" , enkf_tui_ranking_create_data_increasing , enkf_main , NULL); - menu_add_item(menu , "New data based ranking (Sort: decreasing)" , "dD" , enkf_tui_ranking_create_data_decreasing , enkf_main , NULL); - menu_add_item(menu , "Show ranking" , "sS" , enkf_tui_ranking_display , enkf_main , NULL); - { - enkf_fs_type * fs = enkf_main_tui_get_fs( enkf_main ); - misfit_ensemble_type * misfit_ensemble = enkf_fs_get_misfit_ensemble( fs ); - if (!misfit_ensemble_initialized( misfit_ensemble )) - menu_item_disable( obs_item ); - } - menu_add_item(menu , "Help" , "hH" , enkf_tui_help_menu_rank , enkf_main , NULL); - menu_run(menu); - menu_free(menu); - } - -} diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_ranking.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_ranking.h deleted file mode 100644 index 36fbed1505..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_ranking.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_ranking.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_RANKING_H -#define ERT_ENKF_TUI_RANKING_H - - - -void enkf_tui_ranking_menu(void * ); - - - -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_run.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_run.c deleted file mode 100644 index 64e3354236..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_run.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_run.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - - - - -void enkf_tui_run_smoother(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc( ens_size , true ); - enkf_fs_type * source_fs = enkf_main_tui_get_fs( enkf_main ); - enkf_main_run_smoother(enkf_main , source_fs , "AUTO-SMOOTHER" , iactive , 0 , true ); - bool_vector_free( iactive ); -} - - - -void enkf_tui_run_iterated_ES(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const analysis_config_type * analysis_config = enkf_main_get_analysis_config(enkf_main); - analysis_iter_config_type * iter_config = analysis_config_get_iter_config(analysis_config); - int num_iter = analysis_iter_config_get_num_iterations(iter_config); - enkf_main_run_iterated_ES(enkf_main , num_iter ); -} - - -/** - Experiments will always start with the parameters at time == 0; if - you want to simulate with updated (posterior) parameters, you - ensure that by initializing from a report_step > 0 from an - existing case. - - Prediction part is included if it exists. -*/ - -void enkf_tui_run_exp(void * enkf_main) { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc(0,false); - bool ok = false; // is active_list select_string within range (< ens_size) - { - - char * prompt = util_alloc_sprintf("Which realizations [0,%d) to simulate (Ex: 1,3-5) [M to return to menu] : " , ens_size); - char * select_string; - - util_printf_prompt(prompt , PROMPT_LEN , '=' , "=> "); - select_string = util_alloc_stdin_line(); - ok = enkf_tui_util_sscanf_active_list( iactive , select_string , ens_size); - util_safe_free( select_string ); - free( prompt ); - } - if (ok && bool_vector_count_equal(iactive , true)) - enkf_main_run_tui_exp(enkf_main , iactive ); - - bool_vector_free(iactive); -} - - - -void enkf_tui_run_create_runpath__(void * __enkf_main) { - enkf_main_type * enkf_main = enkf_main_safe_cast(__enkf_main); - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc(0,false); - - { - char * prompt = util_alloc_sprintf("Which realizations to create[ensemble size:%d] : " , ens_size); - char * select_string; - - util_printf_prompt(prompt , PROMPT_LEN , '=' , "=> "); - select_string = util_alloc_stdin_line(); - enkf_tui_util_sscanf_active_list( iactive , select_string , ens_size ); - - util_safe_free( select_string ); - free( prompt ); - } - enkf_main_create_run_path(enkf_main , iactive , 0 ); - bool_vector_free(iactive); -} - - - -static void enkf_tui_display_load_msg( int iens , const stringlist_type * msg_list ) { - for (int i=0; i < stringlist_get_size( msg_list ); i++) - printf("[%03d] : %s \n", iens , stringlist_iget( msg_list , i )); -} - - -void enkf_tui_run_manual_load__( void * arg ) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc( 0 , false ); - int iter = 0; - - { - char * prompt = util_alloc_sprintf("Which realizations to load (Ex: 1,3-5) [M to return to menu] : [ensemble size:%d] : " , ens_size); - char * select_string; - util_printf_prompt(prompt , PROMPT_LEN , '=' , "=> "); - select_string = util_alloc_stdin_line(); - - enkf_tui_util_sscanf_active_list( iactive , select_string , ens_size ); - util_safe_free( select_string ); - - free( prompt ); - } - - { - const model_config_type * model_config = enkf_main_get_model_config( enkf_main ); - if (model_config_runpath_requires_iter( model_config )) { - const char * prompt = "Which iteration to load from [0...?) : "; - char * input; - bool OK; - util_printf_prompt(prompt , PROMPT_LEN , '=' , "=> "); - - input = util_alloc_stdin_line(); - if (input == NULL) - return; - - OK = util_sscanf_int( input , &iter ); - - free( input ); - if (!OK) - return; - } - } - - - if (bool_vector_count_equal( iactive , true )) { - stringlist_type ** realizations_msg_list = util_calloc( ens_size , sizeof * realizations_msg_list ); - int iens = 0; - for (; iens < ens_size; ++iens) { - realizations_msg_list[iens] = stringlist_alloc_new(); - } - - enkf_main_load_from_forward_model(enkf_main, iter , iactive, realizations_msg_list); - - for (iens = 0; iens < ens_size; ++iens) { - stringlist_type * msg_list = realizations_msg_list[iens]; - if (bool_vector_iget(iactive, iens)) { - if (stringlist_get_size( msg_list )) { - enkf_tui_display_load_msg( iens , msg_list ); - } - } - stringlist_free(msg_list); - } - free(realizations_msg_list); - } - - bool_vector_free( iactive ); -} - - - - - - -/*****************************************************************/ - -void enkf_tui_run_menu(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - model_config_type * model_config = enkf_main_get_model_config( enkf_main ); - path_fmt_type * runpath_fmt = model_config_get_runpath_fmt( model_config ); - menu_type * menu; - - { - char * title = util_alloc_sprintf("Run menu [case:%s Runpath:%s]" , enkf_main_get_current_fs( enkf_main ) , path_fmt_get_fmt ( runpath_fmt )); - menu = menu_alloc(title , "Back" , "bB"); - free(title); - } - menu_add_item(menu , "Ensemble run: history" , "xX" , enkf_tui_run_exp , enkf_main , NULL); - { - const analysis_config_type * analysis_config = enkf_main_get_analysis_config(enkf_main); - const enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - - - menu_item_type * ES_item = menu_add_item(menu , "Integrated smoother update" , "iI" , enkf_tui_run_smoother , enkf_main , NULL); - menu_item_type * it_ES_item = menu_add_item(menu , "Iterated smoother [RML-EnKF]" , "tT" , enkf_tui_run_iterated_ES , enkf_main , NULL); - - if (!analysis_config_get_module_option(analysis_config , ANALYSIS_ITERABLE)) { - menu_item_disable( it_ES_item ); - } else - menu_item_disable( ES_item ); - - if (!enkf_obs_have_obs( enkf_obs )) { - menu_item_disable( it_ES_item ); - menu_item_disable( ES_item ); - } - } - menu_add_separator(menu); - menu_add_item(menu , "Create runpath directories - NO simulation" , "cC" , enkf_tui_run_create_runpath__ , enkf_main , NULL ); - menu_add_item(menu , "Load results manually" , "lL" , enkf_tui_run_manual_load__ , enkf_main , NULL); - menu_add_separator(menu); - { - menu_item_type * analysis_item = menu_add_item(menu , "Analysis menu" , "aA" , enkf_tui_analysis_menu , enkf_main , NULL); - - if (!enkf_main_have_obs( enkf_main )) - menu_item_disable( analysis_item ); - } - menu_add_item(menu , "Help" , "hH" , enkf_tui_help_menu_run , enkf_main , NULL); - menu_run(menu); - menu_free(menu); -} diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_run.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_run.h deleted file mode 100644 index 331aefc993..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_run.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_run.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_RUN_H -#define ERT_ENKF_TUI_RUN_H - -void enkf_tui_run_menu(void *); -void enkf_tui_run_exp(void *); -void enkf_tui_run_start(void *); -void enkf_tui_run_smoother(void *); -void enkf_tui_run_iterated_ES(void *); - -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_simple.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_simple.c deleted file mode 100644 index 5e8fd2f5c7..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_simple.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_init.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -void enkf_tui_simple_menu(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast(arg); - menu_type * menu = menu_alloc("Simple menu" , "Quit" , "qQ"); - menu_add_item(menu , "Sensitivity run: No data conditioning" , "sS" , enkf_tui_run_exp , enkf_main , NULL); - const model_config_type * model_config = enkf_main_get_model_config( enkf_main ); - menu_item_type * ES_item = menu_add_item(menu , "Assimilation run: Smoother update" , "aA" , enkf_tui_run_smoother , enkf_main , NULL); - menu_item_type * it_ES_item = menu_add_item(menu , "Assimilation run: Iterated smoother [RML-EnKF]" , "iI" , enkf_tui_run_iterated_ES , enkf_main , NULL); - - if (!model_config_has_history( model_config )) { - menu_item_disable( it_ES_item ); - menu_item_disable( ES_item ); - } - menu_add_separator( menu ); - menu_add_item(menu , "Help" , "hH" , enkf_tui_help_menu_simple , enkf_main , NULL); - menu_add_item(menu , "Advanced menu" , "dD" , enkf_tui_main_menu , enkf_main , NULL); - menu_run(menu); - menu_free(menu); - -} diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_simple.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_simple.h deleted file mode 100644 index 36d612ade7..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_simple.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_main.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_SIMPLE_H -#define ERT_ENKF_TUI_SIMPLE_H - - -void enkf_tui_simple_menu(void * ); - - -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_table.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_table.c deleted file mode 100644 index 36fc097a23..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_table.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_table.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - - - - -static void enkf_tui_table__(enkf_main_type * enkf_main , bool gen_kw_table , bool ens_plot) { - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - enkf_fs_type * fs = enkf_main_tui_get_fs(enkf_main); - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - const int last_report = enkf_main_get_history_length( enkf_main ); - int iens1, iens2, step1 , step2; - int ikey , num_keys; - int length; - FILE * stream = NULL; - int * index; - char ** user_keys; - char ** index_keys; - double ** data; - bool * active; - enkf_config_node_type ** config_nodes; - enkf_node_type ** nodes; - - const int prompt_len = 50; - const char * keylist_prompt = "Table headings: KEY1:INDEX1 KEY2:INDEX2 ...."; - const char * gen_kw_prompt = "GEN_KW Parameter"; - const char * file_prompt = "File to save in (blank for nothing) "; - - if (gen_kw_table) { - char * key; - enkf_config_node_type * config_node; - util_printf_prompt(gen_kw_prompt , prompt_len , '=' , "=> "); - key = util_alloc_stdin_line(); - if (ensemble_config_has_key( ensemble_config , key )) { - config_node = ensemble_config_get_node( ensemble_config , key ); - if (enkf_config_node_get_impl_type( config_node ) == GEN_KW) { - gen_kw_config_type * gen_kw_config = enkf_config_node_get_ref( config_node ); - num_keys = gen_kw_config_get_data_size( gen_kw_config ); - - user_keys = util_calloc( num_keys , sizeof * user_keys ); - for (int i=0; i < num_keys; i++) - user_keys[i] = gen_kw_config_alloc_user_key( gen_kw_config , i); - - } else { - fprintf(stderr,"wrong type of: %s \n",key); - free( key ); - return; /* going home on invalid input */ - } - } else { - fprintf(stderr,"** warning: do not have key:%s \n", key); - free( key ); - return ; /* going home on invalid input */ - } - free( key ); - } else { - char * input_keys; - util_printf_prompt(keylist_prompt , prompt_len , '=' , "=> "); - input_keys = util_alloc_stdin_line(); - util_split_string(input_keys , " " , &num_keys , &user_keys); - free( input_keys ); - } - - - util_printf_prompt(file_prompt , prompt_len , '=' , "=> "); - { - char * filename = util_alloc_stdin_line( ); - if (filename != NULL) - stream = util_mkdir_fopen( filename , "w"); - free( filename ); - } - - active = util_calloc( num_keys , sizeof * active ); - nodes = util_calloc( num_keys , sizeof * nodes ); - config_nodes = util_calloc( num_keys , sizeof * config_nodes ); - index_keys = util_calloc( num_keys , sizeof * index_keys ); - for (ikey = 0; ikey < num_keys; ikey++) { - config_nodes[ikey] = (enkf_config_node_type *) ensemble_config_user_get_node( ensemble_config , user_keys[ikey] , &index_keys[ikey]); - if (config_nodes[ikey] != NULL) { - nodes[ikey] = enkf_node_alloc( config_nodes[ikey] ); - active[ikey] = true; - } else { - fprintf(stderr,"** Warning: could not lookup node: %s \n",user_keys[ikey]); - nodes[ikey] = NULL; - active[ikey] = false; - } - } - - if (ens_plot) { - iens1 = 0; - iens2 = enkf_main_get_ensemble_size( enkf_main ); - step1 = util_scanf_int_with_limits("report step",prompt_len , 0 , last_report); - step2 = step1 + 1; - length = (iens2 - iens1); - } else { - iens1 = util_scanf_int_with_limits("ensemble member",prompt_len , 0 , ens_size - 1); - iens2 = iens1 + 1; - step1 = 0; - step2 = last_report + 1; - length = (step2 - step1); - } - index = util_calloc( length , sizeof * index ); - data = util_calloc( num_keys , sizeof * data ); - { - int i; - for (i = 0; i < num_keys; i++) - data[i] = util_calloc( length , sizeof * data[i] ); - } - - { - int active_length = 0; - int total_line_count = 0; - double line[num_keys]; - int iens, step; - - for (iens = iens1; iens < iens2; iens ++) { - for (step = step1; step < step2; step++) { - int line_count = 0; - - for (ikey = 0; ikey < num_keys; ikey++) { - if (active[ikey]) { - node_id_type node_id = {.report_step = step, - .iens = iens }; - if (enkf_node_user_get( nodes[ikey] , fs , index_keys[ikey] , node_id , &line[ikey])) - line_count++; - else - line[ikey] = -1; - } - } - - if (line_count > 0) { - for (ikey=0; ikey < num_keys; ikey++) - data[ikey][active_length] = line[ikey]; - index[active_length] = total_line_count; - active_length++; - } - - total_line_count++; - } - } - - if (stream != NULL) { - if (ens_plot) - enkf_util_fprintf_data( index , (const double **) data , "Realization" , (const char **) user_keys , active_length , num_keys , active , true , stream); - else - enkf_util_fprintf_data( index , (const double **) data , "Report-step" , (const char **) user_keys , active_length , num_keys , active , false , stream); - fclose(stream); - } - - printf("\n\n"); - if (ens_plot) - enkf_util_fprintf_data( index , (const double **) data , "Realization" , (const char **) user_keys , active_length , num_keys , active , true , stdout); - else - enkf_util_fprintf_data( index , (const double **) data , "Report-step" , (const char **) user_keys , active_length , num_keys , active , false , stdout); - } - - for (ikey = 0; ikey < num_keys; ikey++) { - if (active[ikey]) - enkf_node_free( nodes[ikey] ); - - free(index_keys[ikey]); - free(user_keys[ikey]); - free(data[ikey]); - } - free( user_keys ); - free( active ); - free( index_keys); - free( data ); - free( nodes ); - free( config_nodes ); -} - - - - - -static void enkf_tui_table_ensemble(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - enkf_tui_table__(enkf_main , false , true); -} - - -static void enkf_tui_table_GEN_KW_ensemble(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - enkf_tui_table__(enkf_main , true , true); -} - - -static void enkf_tui_table_time(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - enkf_tui_table__(enkf_main , false , false); -} - - - - - -void enkf_tui_table_menu(void * arg) { - - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - { - menu_type * menu = menu_alloc("Table of results" , "Back" , "bB"); - menu_add_item(menu , "Ensemble of parameters" , "eE" , enkf_tui_table_ensemble , enkf_main , NULL); - menu_add_item(menu , "GEN_KW ensemble" , "gG" , enkf_tui_table_GEN_KW_ensemble , enkf_main , NULL); - menu_add_item(menu , "Time development of parameters" , "tT" , enkf_tui_table_time , enkf_main , NULL); - menu_add_item(menu , "Help" , "hH" , enkf_tui_help_menu_table , enkf_main , NULL); - menu_run(menu); - menu_free(menu); - } -} diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_table.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_table.h deleted file mode 100644 index 304ee727ab..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_table.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_table.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_TABLE -#define ERT_ENKF_TUI_TABLE - -void enkf_tui_table_menu(void * ); - -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_util.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_util.c deleted file mode 100644 index 54dd60fc36..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_util.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_util.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -/** - This file implements various small utility functions for the (text - based) EnKF user interface. -*/ - - - - - -/** - Very simple function which is in interactive functions. Used to - query the user: - - - Key identifying a field. - - An integer report step. - - Whether we are considering the analyzed state or the forecast. - - The config_node is returned, and in addition the report_step, iens - and analysis_state are returned by reference. It is OK the pass in - NULL for these pointers; in that case the user is not queried for - these values. - - The keyword is checked for existence; but it is not checked whether - the report_step actually exists. If impl_type == INVALID, any - implementation type will be accepted, otherwise we loop until the - keyword is of type impl_type. -*/ - -const enkf_config_node_type * enkf_tui_util_scanf_key(const ensemble_config_type * config , int prompt_len , ert_impl_type impl_type , enkf_var_type var_type) { - char * kw; - bool OK; - const enkf_config_node_type * config_node = NULL; - do { - OK = true; - util_printf_prompt("Keyword" , prompt_len , '=' , "=> "); - kw = util_alloc_stdin_line(); - if(kw==NULL){ - OK = true; - } - else if (ensemble_config_has_key(config , kw)) { - config_node = ensemble_config_get_node(config , kw); - - if (impl_type != INVALID) - if (enkf_config_node_get_impl_type(config_node) != impl_type) - OK = false; - - if (var_type != INVALID_VAR) - if (enkf_config_node_get_var_type(config_node) != var_type) - OK = false; - } else OK = false; - free(kw); - } while (!OK); - return config_node; -} - - -/** - Present the user with the queries: - - First ensemble member ==> - Last ensemble member ===> - - It then allocates (bool *) pointer [0..ens_size-1], where the - interval gven by the user is true (i.e. actve), and the rest is - false. It s the responsiibility of the calling scope to free this. -*/ - - -bool * enkf_tui_util_scanf_alloc_iens_active(int ens_size, int prompt_len , int * _iens1 , int * _iens2) { - bool * iactive = util_calloc(ens_size , sizeof * iactive ); - int iens1 = util_scanf_int_with_limits("First ensemble member" , prompt_len , 0 , ens_size - 1); - int iens2 = util_scanf_int_with_limits("Last ensemble member" , prompt_len , iens1 , ens_size - 1); - int iens; - - for (iens = 0; iens < ens_size; iens++) - iactive[iens] = false; - - for (iens = iens1; iens <= iens2; iens++) - iactive[iens] = true; - - - *_iens1 = iens1; - *_iens2 = iens2; - return iactive; -} - - - -/** - Presents the reader with a prompt, and reads a string containing - two integers separated by a character(s) in the set: " ,-:". If the - user enters a blank string that is interpreted as "all - realizations", and the return variabels are set to: - - iens1 = 0 iens2 = ens_size - 1 - - Will not return before the user has actually presented a valid - string. -*/ - - -void enkf_tui_util_scanf_iens_range(const char * prompt_fmt , int ens_size , int prompt_len , int * iens1 , int * iens2) { - char * prompt = util_alloc_sprintf(prompt_fmt , ens_size - 1); - bool OK = false; - - util_printf_prompt(prompt , prompt_len , '=' , "=> "); - - while (!OK) { - char * input = util_alloc_stdin_line(); - const char * current_ptr = input; - OK = true; - - if (input != NULL) { - current_ptr = util_parse_int(current_ptr , iens1 , &OK); - current_ptr = util_skip_sep(current_ptr , " ,-:" , &OK); - current_ptr = util_parse_int(current_ptr , iens2 , &OK); - - if (!OK) - printf("Failed to parse two integers from: \"%s\". Example: \"0 - 19\" to get the 20 first members.\n",input); - free(input); - } else { - *iens1 = 0; - *iens2 = ens_size - 1; - } - } - free(prompt); -} - - -void enkf_tui_util_scanf_report_steps(int last_report , int prompt_len , int * __step1 , int * __step2) { - char * prompt = util_alloc_sprintf("Report steps (0 - %d)" , last_report); - bool OK = false; - - util_printf_prompt(prompt , prompt_len , '=' , "=> "); - - while (!OK) { - char * input = util_alloc_stdin_line(); - const char * current_ptr = input; - int step1 , step2; - OK = true; - if(input == NULL){ - step1=0; - step2=last_report; - } - else{ - current_ptr = util_parse_int(current_ptr , &step1 , &OK); - current_ptr = util_skip_sep(current_ptr , " ,-:" , &OK); - current_ptr = util_parse_int(current_ptr , &step2 , &OK); - } - if (!OK) - printf("Failed to parse two integers from: \"%s\". Example: \"0 - 19\" to get the 20 first report steps.\n",input); - free(input); - - step1 = util_int_min(step1 , last_report); - step2 = util_int_min(step2 , last_report); - if (step1 > step2) - util_exit("%s: ohh come on - must have a finite interval forward in time - no plots for you.\n",__func__); - *__step1 = step1; - *__step2 = step2; - - } - free(prompt); -} - - - -/** - Similar to enkf_tui_util_scanf_alloc_iens_active(), but based on report steps. -*/ - -bool * enkf_tui_util_scanf_alloc_report_active(int last_step, int prompt_len) { - bool * iactive = util_calloc((last_step + 1) , sizeof * iactive ); - int step1 = util_scanf_int_with_limits("First report step" , prompt_len , 0 , last_step); - int step2 = util_scanf_int_with_limits("Last report step" , prompt_len , step1 , last_step); - int step; - - for (step = 0; step <= last_step; step++) - iactive[step] = false; - - for (step = step1; step <= step2; step++) - iactive[step] = true; - - return iactive; -} - - -/** - This functions reads i,j,k and returns them be reference; if the - reference pointer is NULL, that coordinate is skipped. I.e. - - enkf_tui_util_scanf_ijk__(config , 100 , &i , &j , NULL); - - Will read i and j. If your are interested in all three coordinates - you should use enkf_tui_util_scanf_ijk() which has a more flexible - parser. -*/ - - -void enkf_tui_util_scanf_ijk__(const field_config_type * config, int prompt_len , int *i , int *j , int *k) { - int nx,ny,nz; - - field_config_get_dims(config , &nx , &ny , &nz); - if (i != NULL) (*i) = util_scanf_int_with_limits("Give i-index" , prompt_len , 1 , nx) - 1; - if (j != NULL) (*j) = util_scanf_int_with_limits("Give j-index" , prompt_len , 1 , ny) - 1; - if (k != NULL) (*k) = util_scanf_int_with_limits("Give k-index" , prompt_len , 1 , nz) - 1; -} - - - - -/** - The function reads ijk, but it returns a global 1D index. Observe - that the user is supposed to enter an index starting at one - whichs - is immediately shifted down to become zero based. - - The function will loop until the user has entered ijk corresponding - to an active cell. -*/ - -int enkf_tui_util_scanf_ijk(const field_config_type * config, int prompt_len) { - int global_index; - field_config_scanf_ijk(config , true , "Give (i,j,k) indices" , prompt_len , NULL , NULL , NULL , &global_index); - return global_index; -} - - - - - - - - - -/** - This function runs through all the report steps [step1:step2] for - member iens, and gets the value of the cell 'get_index'. Current - implementation assumes that the config_node/node combination are of - field type - this should be generalized to use the enkf_node_iget() - function. - - The value is returned (by reference) in y, and the corresponding - time (currently report_step) is returned in 'x'. -*/ - - -void enkf_tui_util_get_time(enkf_fs_type * fs , const enkf_config_node_type * config_node, enkf_node_type * node , int get_index , int step1 , int step2 , int iens , double * x , double * y ) { - const char * key = enkf_config_node_get_key(config_node); - int report_step; - int index = 0; - for (report_step = step1; report_step <= step2; report_step++) { - node_id_type node_id = {.report_step = report_step , .iens = iens }; - if (enkf_node_try_load(node , fs , node_id)) { - const field_type * field = enkf_node_value_ptr( node ); - y[index] = field_iget_double(field , get_index); - } else { - fprintf(stderr," ** Warning field:%s is missing for member,report: %d,%d \n",key , iens , report_step); - y[index] = -1; - } - x[index] = report_step; - index++; - } -} - - -int enkf_tui_util_scanf_report_step(int last_report, const char * prompt , int prompt_len) { - int report_step = util_scanf_int_with_limits(prompt , prompt_len , 0 , last_report); - return report_step; -} - -char * enkf_tui_util_scanf_report_step_as_char(int last_report, const char * prompt , int prompt_len) { - char * report_step = util_scanf_int_with_limits_return_char(prompt , prompt_len , 0 , last_report); - return report_step; -} - -int enkf_tui_util_scanf_int_with_default(const char * prompt , int prompt_len , bool * default_used) { - bool OK; - int value; - *default_used = false; - do { - char * input; - - util_printf_prompt(prompt , prompt_len , '=' , "=> "); - input = util_alloc_stdin_line(); - if (input == NULL) { - *default_used = true; - OK = true; - value = -1; - } else { - OK = util_sscanf_int( input , &value ); - free( input ); - } - } while (!OK); - return value; -} - -int enkf_tui_util_scanf_int_with_default_return_to_menu(const char * prompt , int prompt_len , bool * default_used) { - bool OK; - int value; - *default_used = false; - do { - char * input; - - util_printf_prompt(prompt , prompt_len , '=' , "=> "); - input = util_alloc_stdin_line(); - if (input == NULL) { - *default_used = true; - OK = true; - value = -1; - } - else if (strcmp(input,"M")==0 || strcmp(input,"m")==0){ - OK = true; - value = -2; - } - else { - OK = util_sscanf_int( input , &value ); - free( input ); - } - } while (!OK); - return value; -} - -bool enkf_tui_util_sscanf_active_list( bool_vector_type * iactive , const char * select_string , int ens_size ) { - if (select_string == NULL) { - bool_vector_set_default( iactive , true ); - bool_vector_iset( iactive , ens_size - 1 , true ); - return true; - } else { - bool OK; - OK = string_util_init_active_mask( select_string , iactive ); - - if (bool_vector_size( iactive ) < ens_size) - bool_vector_iset( iactive , ens_size - 1 , false ); - else if (bool_vector_size( iactive ) > ens_size) - return false; - return OK; - } -} - -/** - The limit is not inclusive -*/ -double enkf_tui_util_scanf_double_with_lower_limit(const char * prompt , int prompt_len , double min_value) { - double value; - char * new_prompt = util_alloc_sprintf("%s (greater than %g)" , prompt , min_value ); - do { - value = util_scanf_double(new_prompt , prompt_len); - } while (value <= min_value); - free(new_prompt); - return value; -} - - -/*****************************************************************/ - - -/* Minimum wrapping of vfprintf */ -void enkf_tui_util_msg(const char * fmt , ...) { - va_list ap; - va_start(ap , fmt); - vfprintf(stdout , fmt , ap); - va_end(ap); -} - - diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_util.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_util.h deleted file mode 100644 index 6e74bdbb06..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_util.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_tui_util.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_UTIL_H -#define ERT_ENKF_TUI_UTIL_H - -#include - -#include -#include -#include -#include -#include - -void enkf_tui_util_scanf_report_steps(int , int , int * , int * ); -const enkf_config_node_type * enkf_tui_util_scanf_key(const ensemble_config_type * , int , ert_impl_type , enkf_var_type); -int enkf_tui_util_scanf_ijk(const field_config_type * , int); -void enkf_tui_util_scanf_ijk__(const field_config_type * , int , int * , int * , int *); -bool * enkf_tui_util_scanf_alloc_report_active(int , int ); -bool * enkf_tui_util_scanf_alloc_iens_active(int , int , int * , int *); -void enkf_tui_util_get_time(enkf_fs_type * , const enkf_config_node_type * , enkf_node_type * , int , int , int , int , double * , double * ); -void enkf_tui_util_scanf_iens_range(const char * , int , int , int * , int * ); -int enkf_tui_util_scanf_report_step(int , const char * , int ); -char * enkf_tui_util_scanf_report_step_as_char(int , const char * , int ); -void enkf_tui_util_msg(const char * , ...); -int enkf_tui_util_scanf_int_with_default(const char * prompt , int prompt_len , bool * default_used); -int enkf_tui_util_scanf_int_with_default_return_to_menu(const char * prompt , int prompt_len , bool * default_used); -double enkf_tui_util_scanf_double_with_lower_limit(const char * prompt , int prompt_len , double min_value); -bool enkf_tui_util_sscanf_active_list( bool_vector_type * iactive , const char * select_string , int ens_size ); -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_workflow.c b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_workflow.c deleted file mode 100644 index f4a5a96576..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_workflow.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'enkf_tui_workflow.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -void enkf_tui_workflow_run( void * arg ) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - { - ert_workflow_list_type * workflow_list = enkf_main_get_workflow_list( enkf_main ); - util_printf_prompt("Name of workflow" , PROMPT_LEN , '=' , "=> "); - { - char * workflow_name = util_alloc_stdin_line(); - if (workflow_name != NULL) { - if (ert_workflow_list_has_workflow( workflow_list , workflow_name )) { - bool runOK = ert_workflow_list_run_workflow_blocking( workflow_list , workflow_name , enkf_main); - if (!runOK) { - printf("Errors in workflow:%s \n", workflow_name ); - printf("-----------------------------------------------------------------\n"); - config_error_fprintf( ert_workflow_list_get_last_error( workflow_list ) , true , stdout); - printf("-----------------------------------------------------------------\n"); - } - } - } - util_safe_free( workflow_name ); - } - } -} - - -void enkf_tui_workflow_load( void * arg ) { - // ... -} - - -void enkf_tui_workflow_list( void * arg ) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - { - ert_workflow_list_type * workflow_list = enkf_main_get_workflow_list( enkf_main ); - stringlist_type * name_list = ert_workflow_list_alloc_namelist( workflow_list ); - - printf("Available workflows: \n"); - { - int i; - for (i=0; i < stringlist_get_size( name_list ); i++) { - if ((i % 5) == 0) - printf("\n "); - else - printf(" "); - - printf("%s", stringlist_iget( name_list , i )); - } - } - stringlist_free( name_list ); - printf("\n\n"); - } -} - - -void enkf_tui_workflow_menu(void * arg) { - enkf_main_type * enkf_main = enkf_main_safe_cast( arg ); - menu_type * menu = menu_alloc("Workflows" , "Back" , "bB"); - - menu_add_item(menu , "Run workflow" , "rR" , enkf_tui_workflow_run , enkf_main , NULL ); - menu_add_item(menu , "Load workflow" , "lL" , enkf_tui_workflow_load , enkf_main , NULL ); - menu_add_item(menu , "List available workflows" , "iI" , enkf_tui_workflow_list , enkf_main , NULL ); - - menu_add_item(menu , "Help" , "hH" , enkf_tui_help_menu_run , enkf_main , NULL); - menu_run(menu); - menu_free(menu); - -} - diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_workflow.h b/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_workflow.h deleted file mode 100644 index fe6cc12720..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/enkf_tui_workflow.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'enkf_tui_workflow.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TUI_WORKFLOW_H -#define ERT_ENKF_TUI_WORKFLOW_H - -void enkf_tui_workflow_menu(void *); - -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/ert_tui_const.h b/ThirdParty/Ert/libenkf/applications/ert_tui/ert_tui_const.h deleted file mode 100644 index 4f2981569e..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/ert_tui_const.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ert_tui_const.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_TUI_CONST -#ifdef __cplusplus -extern "C" { -#endif - -#define PROMPT_LEN 80 - - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/main.c b/ThirdParty/Ert/libenkf/applications/ert_tui/main.c deleted file mode 100644 index e86be1850e..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/main.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'main.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#define WORKFLOW_OPTION "-wf" - -void text_splash() { - const int usleep_time = 1000; - int i; - { -#include "ERT.h" - printf("\n\n"); - for (i = 0; i < SPLASH_LENGTH; i++) { - printf("%s\n" , splash_text[i]); - util_usleep(usleep_time); - } - printf("\n\n"); - - sleep(1); -#undef SPLASH_LENGTH - } -} - - -/* - GIT_COMMIT and COMPILE_TIME_STAMP are env variables set by the - makefile. Will exit if the config file does not exist. -*/ -void enkf_welcome(const char * config_file) { - if (util_file_exists( config_file )) { - char * abs_path = util_alloc_realpath( config_file ); - char * config_file_msg = util_alloc_sprintf("Configuration file...: %s \n",abs_path); - - /* This will be printed if/when util_abort() is called on a later stage. */ - /* The svn_version and compile_time are added with the functione enkf_main_init_debug(). */ - util_abort_append_version_info(config_file_msg); - - free(config_file_msg); - free(abs_path); - } else util_exit(" ** Sorry: can not locate configuration file: %s \n\n" , config_file); -} - - -void enkf_usage() { - printf("\n"); - printf(" *********************************************************************\n"); - printf(" ** **\n"); - printf(" ** E R T **\n"); - printf(" ** **\n"); - printf(" **-----------------------------------------------------------------**\n"); - printf(" ** You have successfully started the ert program developed at **\n"); - printf(" ** Statoil. Before you can actually start using the program, you **\n"); - printf(" ** must create a configuration file. When the configuration file **\n"); - printf(" ** has been created, you can start the ert application with: **\n"); - printf(" ** **\n"); - printf(" ** bash> ert config_file **\n"); - printf(" ** **\n"); - printf(" ** Instructions on how to create the configuration file can be **\n"); - printf(" ** found at: http://ert.nr.no **\n"); - printf(" *********************************************************************\n"); -} - - - - -static void init_debug( const char * argv0) { - char * git_commit = util_alloc_sprintf("git commit...........: %s \n",GIT_COMMIT); - char * compile_time = util_alloc_sprintf("Compile time.........: %s \n",COMPILE_TIME_STAMP); - - /* This will be printed if/when util_abort() is called on a later stage. */ - util_abort_append_version_info( git_commit ); - util_abort_append_version_info( compile_time ); - - free(git_commit); - free(compile_time); - - util_abort_set_executable( argv0 ); -} - - - -void parse_workflows(int argc , char ** argv , stringlist_type * workflows) { - /* bool workflow_on = false; */ - for (int iarg = 2; iarg < argc; iarg++) { - stringlist_append_copy( workflows , argv[iarg]); - - /*if (strcmp( argv[iarg] , WORKFLOW_OPTION) == 0) - workflow_on = true; - else { - if (workflow_on) - stringlist_append_copy( workflows , argv[iarg]); - else - fprintf(stderr,"**Warning - option:\'%s\' ignored\n",argv[iarg]); - } - */ - } -} - - - - -int main (int argc , char ** argv) { - text_splash(); - init_debug( argv[0] ); - printf("\n"); - printf("Documentation : %s \n","http://ert.nr.no"); - printf("git commit : %s \n",GIT_COMMIT); - printf("compile time : %s \n",COMPILE_TIME_STAMP); - printf("site config : %s \n", site_config_get_location()); - - enkf_main_install_SIGNALS(); /* Signals common to both tui and gui. */ - signal(SIGINT , util_abort_signal); /* Control C - tui only. */ - if (argc < 2) { - enkf_usage(); - exit(1); - } else { - const char * model_config_file = argv[1]; - stringlist_type * workflow_list = stringlist_alloc_new(); - - parse_workflows( argc , argv , workflow_list ); - if ( !(util_entry_readable(model_config_file) && util_is_file(model_config_file)) ) - util_exit("Can not read file %s - exiting \n", model_config_file); - - { - char * abs_config = util_alloc_realpath( model_config_file ); - printf("model config : %s \n\n", abs_config); - free(abs_config); - } - enkf_welcome( model_config_file ); - { - enkf_main_type * enkf_main = enkf_main_bootstrap(model_config_file , true , true); - enkf_main_run_workflows( enkf_main , workflow_list ); - enkf_tui_main_menu(enkf_main); - enkf_main_free(enkf_main); - } - - stringlist_free( workflow_list ); - util_abort_free_version_info(); /* No fucking leaks ... */ - } - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/applications/ert_tui/upgrade_fs104.c b/ThirdParty/Ert/libenkf/applications/ert_tui/upgrade_fs104.c deleted file mode 100644 index 0a96b2a825..0000000000 --- a/ThirdParty/Ert/libenkf/applications/ert_tui/upgrade_fs104.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'main.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define BLOCK_FS_DRIVER_INDEX_ID 3002 - - -config_type * create_config( ) { - config_type * config = config_alloc( ); - config_schema_item_type * item; - - item = config_add_schema_item(config , ENSPATH_KEY , true , false); - config_schema_item_set_argc_minmax(item , 1 , 1 , 0 , NULL); - - item = config_add_schema_item(config , NUM_REALIZATIONS_KEY , true , false); - config_schema_item_set_argc_minmax(item , 1 , 1 , 1, (const config_item_types [1]) {CONFIG_INT}); - - item = config_add_schema_item(config , REFCASE_KEY , true , false); - config_schema_item_set_argc_minmax(item , 1 , 1 , 1 , NULL ); - - return config; -} - - -void fskip_block_fs( FILE * stream ) { - util_fread_int( stream ); - util_fread_int( stream ); -} - - -void fskip_block_fs_index( FILE * stream ) { - return; -} - - -char * check_enspath( const char * ens_path , stringlist_type * case_list ) { - char * mount_file = util_alloc_filename( ens_path , "enkf_mount_info" , NULL); - FILE * stream = util_fopen( mount_file , "r"); - int version; - - util_fread_long( stream ); - version = util_fread_int( stream ); - - if (version != 104) - util_exit("This application is only for upgrading fs from version 104\n"); - - { - for (int driver_nr = 0; driver_nr < 5; driver_nr++) { - int driver_id; - util_fread_int( stream ); - - driver_id = util_fread_int( stream ); - if (driver_id == BLOCK_FS_DRIVER_ID) - fskip_block_fs(stream); - else if (driver_id == BLOCK_FS_DRIVER_INDEX_ID) - fskip_block_fs_index(stream); - else - util_abort("%s: sorry can only convert BLOCK_FS cases\n",__func__); - } - } - - { - int num_case = util_fread_int( stream ); - for (int icase = 0; icase < num_case; icase++) { - char * case_name = util_fread_alloc_string( stream ); - stringlist_append_owned_ref( case_list , case_name ); - } - } - - - fclose( stream ); - return mount_file; -} - - - - - -void upgrade_case( int ens_size , const ecl_sum_type * refcase , const char * enspath , const char * case_path , const char * file) { - int num_drivers = 32; - int length = ecl_sum_get_last_report_step( refcase ); - block_fs_type ** fs_list = util_calloc( num_drivers , sizeof * fs_list ); - buffer_type * buffer = buffer_alloc(100); - double_vector_type * vector = double_vector_alloc( 0,0 ); - int driver_nr; - - - for (driver_nr = 0; driver_nr < num_drivers; driver_nr++) { - char * mount_file = util_alloc_sprintf( "%s/%s/mod_%d/%s.mnt" , enspath , case_path , driver_nr , file); - fs_list[driver_nr] = block_fs_mount( mount_file , 32 , 0 , 1 , 1 , true , false ); - free( mount_file ); - } - - { - const ecl_smspec_type * smspec = ecl_sum_get_smspec( refcase ); - int num_params = ecl_smspec_get_params_size( smspec ); - msg_type * msg; - { - char * prefix = util_alloc_sprintf("Upgrading %s/mod_nnn/%s: " , case_path , file ); - msg = msg_alloc( prefix , false ); - free( prefix ); - } - msg_show( msg ); - - for (int i=0; i < num_params; i++) { - const smspec_node_type * smspec_node = ecl_smspec_iget_node( smspec , i ); - const char * gen_key = smspec_node_get_gen_key1( smspec_node ); - { - char * progress = util_alloc_sprintf("%4.1f %s" , i * 100.0 / num_params , "%"); - msg_update( msg , progress ); - free( progress ); - } - if (gen_key != NULL) { - for (int iens = 0; iens < ens_size; iens++) { - block_fs_type * fs = fs_list[ iens % num_drivers ]; - double_vector_reset( vector ); - for (int tstep = 0; tstep <= length; tstep++) { - char * node_key = util_alloc_sprintf("%s.%d.%d" , gen_key , tstep , iens ); - - if (block_fs_has_file( fs , node_key )) { - block_fs_fread_realloc_buffer( fs , node_key , buffer ); - buffer_fskip( buffer , 12 ); - double_vector_iset( vector , tstep , buffer_fread_double( buffer )); - block_fs_unlink_file( fs , node_key ); - } - free( node_key ); - } - - if (double_vector_size( vector ) > 0) { - char * vector_key = util_alloc_sprintf("%s.%d" , gen_key , iens ); - buffer_rewind( buffer ); - buffer_fwrite_time_t( buffer , time(NULL)); - buffer_fwrite_int( buffer , SUMMARY ); - double_vector_buffer_fwrite( vector , buffer ); - - block_fs_fwrite_buffer( fs , vector_key , buffer ); - free( vector_key ); - } - } - } - } - msg_free( msg , false); - } - - double_vector_free( vector ); - buffer_free( buffer ); - for (driver_nr = 0; driver_nr < num_drivers; driver_nr++) { - block_fs_close( fs_list[driver_nr] , true ); - } - free( fs_list ); -} - - -void update_index( int ens_size, int length, const char * ens_path , const char * case_path ) { - char * index_path = util_alloc_sprintf("%s/%s/Index" , ens_path , case_path ); - char * old_path = util_alloc_sprintf("%s/%s" , ens_path , case_path ); - - util_make_path( index_path ); - util_move_file4( "INDEX.data_0" , NULL , old_path , index_path ); - util_move_file4( "INDEX.mnt" , NULL , old_path , index_path ); - - free( old_path ); - - { - char * mount_file = util_alloc_sprintf("%s/INDEX.mnt" , index_path); - block_fs_type * index = block_fs_mount( mount_file , 32 , 0 , 1 , 1 , true , false ); - buffer_type * buffer = buffer_alloc( 512 ); - for (int iens = 0; iens < ens_size; iens++) - for (int tstep = 0; tstep < length; tstep++) { - char * old_key = util_alloc_sprintf("kw_list_%d.%d" , tstep , iens); - char * new_key = util_alloc_sprintf("kw_list.%d.%d" , tstep , iens); - - if (block_fs_has_file( index , old_key )) { - block_fs_fread_realloc_buffer( index , old_key , buffer ); - block_fs_fwrite_buffer( index , new_key , buffer ); - block_fs_unlink_file( index , old_key ); - } - - free( old_key ); - free( new_key ); - } - - free( mount_file ); - block_fs_close( index , true ); - } -} - - -void create_fstab( const char * ens_path , const char * case_path ) { - int num_drivers = 32; - char * mount_point = util_alloc_sprintf("%s/%s" , ens_path , case_path ); - FILE * stream = fs_driver_open_fstab( mount_point , true ); - fs_driver_init_fstab( stream, BLOCK_FS_DRIVER_ID); - - block_fs_driver_create_fs( stream , mount_point , DRIVER_PARAMETER , num_drivers , "mod_%d" , "PARAMETER"); - block_fs_driver_create_fs( stream , mount_point , DRIVER_STATIC , num_drivers , "mod_%d" , "STATIC"); - block_fs_driver_create_fs( stream , mount_point , DRIVER_DYNAMIC_FORECAST , num_drivers , "mod_%d" , "FORECAST"); - block_fs_driver_create_fs( stream , mount_point , DRIVER_DYNAMIC_ANALYZED , num_drivers , "mod_%d" , "ANALYZED"); - block_fs_driver_create_fs( stream , mount_point , DRIVER_INDEX , 1 , "Index" , "INDEX"); - - fclose( stream ); - free( mount_point ); -} - - - - - -int main (int argc , char ** argv) { - enkf_main_install_SIGNALS(); /* Signals common to both tui and gui. */ - signal(SIGINT , util_abort_signal); /* Control C - tui only. */ - enkf_main_init_debug( NULL ); - if (argc != 2) { - printf("Usage: upgrade_fs104 config_file\n"); - exit(1); - } else { - const char * model_config_file = argv[1]; - char * enspath; - int ens_size; - ecl_sum_type * refcase; - { - config_type * config = create_config(); - if (!config_parse( config , model_config_file , "--" , "INCLUDE" , "DEFINE" , CONFIG_UNRECOGNIZED_IGNORE , true )) { - config_fprintf_erors( config , stderr ); - exit(1); - } - - { - char * path; - util_alloc_file_components(model_config_file , &path , NULL , NULL); - if (path != NULL) { - printf("Changing to directory:%s\n" , path); - chdir(path); - } - util_safe_free( path ); - } - - ens_size = config_get_value_as_int( config , NUM_REALIZATIONS_KEY ); - enspath = util_alloc_string_copy( config_get_value( config , ENSPATH_KEY )); - refcase = ecl_sum_fread_alloc_case( config_get_value( config , REFCASE_KEY ) , ":"); - config_free( config ); - } - - { - stringlist_type * case_list = stringlist_alloc_new(); - int ic; - char * mount_file = check_enspath( enspath , case_list ); - - for (ic = 0; ic < stringlist_get_size( case_list ); ic++) { - const char * case_path = stringlist_iget( case_list , ic); - - upgrade_case( ens_size, refcase , enspath , case_path , "FORECAST"); - upgrade_case( ens_size, refcase , enspath , case_path , "ANALYZED"); - - update_index( ens_size, ecl_sum_get_last_report_step( refcase ), enspath , case_path ); - create_fstab( enspath , case_path ); - } - { - FILE * stream = util_fopen( mount_file , "w"); - util_fwrite_long(FS_MAGIC_ID , stream); - util_fwrite_int( 105 , stream); - fclose( stream ); - } - stringlist_free( case_list ); - free( mount_file ); - - } - free( enspath ); - ecl_sum_free( refcase ); - util_abort_free_version_info(); /* No fucking leaks ... */ - } -} diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/README.new_type.h b/ThirdParty/Ert/libenkf/include/ert/enkf/README.new_type.h deleted file mode 100644 index 9fd3d05df7..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/README.new_type.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'README.new_type.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/** -The two files README.new_type.c and README.new_type_config.c (along -with the corresponding header files) are meant to serve as a -documentation and reference on how to add new object types to the enkf -system. - - -new_type.h -========== -When implementing a new type, the header file should contain a typedef like this: - - typedef struct new_type_struct new_type; - -This typedef means two things: - - 1. The entity "new_type" is to be interpreted as a "struc - new_type_struct". - - 2. We are informing the compiler that a declaration of the struct - new_type_struct will come at a later stage. However for the rest - of the header file we can refer only to "new_type" - -The advantages of this way to do it is that only the existence of -"struct new_type_struct" is exported, the actual implementation is -hidden for other files; it is a bit like making all the data private -in a C++ class. - - _____________________ E X A M P L E _____________________________ - / - | new.h - | ----- - | typedef struct new_struct new_type; - | - | new_type * new_type_alloc(int , const char *); - | double * new_get_data_ref(const new_type *); - | void new_type_free(new_type *); - | - | - | new.c - | ----- - | #include - | #include - | - | struct new_struct { - | double *data; - | } - | - | new_type * new_type_alloc(int size) { - | new_type * new = util_malloc(sizeof * new_type , __func__); - new->date = util_malloc(size * sizeof new->data); - | return new; - | } - | - | double * new_get_data_ref(const new_type * new) { - | return new->data; - | } - | - | - | void new_type_free(new_type * new) { - | free(new->data); - | free(new); - | } - | - | - | other.c - | ------- - | #include - | - | void some_func() { - | new_type * new = new_type_alloc(100 , "Programmer ..."); - | .... - | .... - | new_type_free(new); - | } - \_________________________________________________________________ - -What happen in this little example is the following things: - - 1. In the header file "new.h" we say that an implementation of a - struct new_type_struct will be forthcoming. This struct can - (without the implementation) be referred to as new_type. - - In the header file we also claim that the three functions: - - i new_type * new_type_alloc(int , const chat*); - ii double * new_get_data_ref(const new_type *); - iii void new_type_free(new_type *); - - will be coming. - - 2. In the source file new.c we have the implementation of the struct - new_struct, along with the three functions listed above. - - 3. In the third file, other.c which includes "new.h", we can refer to - the type new_type, and the three functions listed in the - header. However we can *NOT* get to the fields in the struct of - type new_type_struct, i.e. code like: - - .... - new->data[17] = 178.9; - .... - - in "other.c" will *NOT* compile. It will fail with the message - "dereferencing pointer to imcomplete type." - -*/ diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/README.new_type_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/README.new_type_config.h deleted file mode 100644 index 91963a1c4d..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/README.new_type_config.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'README.new_type_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/** -The two files README.new_type.c and README.new_type_config.c (along -with the corresponding header files) are meant to serve as a -documentation and reference on how to add new object types to the enkf -system. - - -new_type_config.h -========== -*/ diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/active_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/active_config.h deleted file mode 100644 index da374cffed..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/active_config.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'active_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ACTIVE_CONFIG_H -#define ERT_ACTIVE_CONFIG_H - - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/active_list.h b/ThirdParty/Ert/libenkf/include/ert/enkf/active_list.h deleted file mode 100644 index 5f03fcfbcb..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/active_list.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'active_list.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ACTIVE_LIST_H -#define ERT_ACTIVE_LIST_H - -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include - - -typedef struct active_list_struct active_list_type; - - active_list_type * active_list_alloc( ); - void active_list_add_index(active_list_type * , int); - void active_list_free( active_list_type *); - const int * active_list_get_active(const active_list_type * ); - int active_list_get_active_size(const active_list_type * , int total_size ); - void active_list_set_all_active(active_list_type * ); - void active_list_set_data_size(active_list_type * , int ); - void active_list_free( active_list_type * ); - active_mode_type active_list_get_mode(const active_list_type * ); - void active_list_free__( void * arg ); - active_list_type * active_list_alloc_copy( const active_list_type * src); - void active_list_fprintf( const active_list_type * active_list , const char * dataset_key , const char * key , FILE * stream ); - void active_list_summary_fprintf( const active_list_type * active_list , const char * dataset_key , const char * key , FILE * stream); - bool active_list_iget( const active_list_type * active_list , int index ); - bool active_list_equal( const active_list_type * active_list1 , const active_list_type * active_list2); - void active_list_copy( active_list_type * target , const active_list_type * src); - -UTIL_IS_INSTANCE_HEADER( active_list ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/active_node.h b/ThirdParty/Ert/libenkf/include/ert/enkf/active_node.h deleted file mode 100644 index c8fcc09e7d..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/active_node.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'active_node.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ACTIVE_NODE_H -#define ERT_ACTIVE_NODE_H - - -typedef struct active_var_struct active_var_type; -typedef struct active_obs_struct active_obs_type; - - -typedef void (active_config_destructor_ftype) (void *); /* A destructor for the (node-spesific) object holding inactive/active information. */ - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/analysis_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/analysis_config.h deleted file mode 100644 index 8c849c1cc3..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/analysis_config.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'analysis_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_ANALYSIS_CONFIG_H -#define ERT_ANALYSIS_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include - -#include -#include - -#include - -#include -#include - - - - -typedef struct analysis_config_struct analysis_config_type; - -analysis_iter_config_type * analysis_config_get_iter_config( const analysis_config_type * config ); -analysis_module_type * analysis_config_get_module( analysis_config_type * config , const char * module_name ); -bool analysis_config_has_module( analysis_config_type * config , const char * module_name ); -void analysis_config_load_internal_module( analysis_config_type * config , const char * symbol_table ); -void analysis_config_load_internal_modules( analysis_config_type * analysis ); -void analysis_config_reload_module( analysis_config_type * config , const char * module_name); -bool analysis_config_get_module_option( const analysis_config_type * config , long flag); -bool analysis_config_load_external_module( analysis_config_type * config , const char * lib_name, const char * user_name); -void analysis_config_load_all_external_modules_from_config ( analysis_config_type * analysis_config, const config_content_type * config); - -stringlist_type * analysis_config_alloc_module_names( analysis_config_type * config ); -const char * analysis_config_get_log_path( const analysis_config_type * config ); -void analysis_config_init( analysis_config_type * analysis , const config_content_type * config); -analysis_config_type * analysis_config_alloc( rng_type * rng ); -void analysis_config_free( analysis_config_type * ); -bool analysis_config_get_merge_observations(const analysis_config_type * ); -double analysis_config_get_alpha(const analysis_config_type * config); -double analysis_config_get_truncation(const analysis_config_type * config); -bool analysis_config_Xbased(const analysis_config_type * config); -bool analysis_config_get_rerun(const analysis_config_type * config); -bool analysis_config_get_random_rotation(const analysis_config_type * config); -int analysis_config_get_rerun_start(const analysis_config_type * config); -bool analysis_config_get_do_local_cross_validation(const analysis_config_type * config); -bool analysis_config_get_force_subspace_dimension(const analysis_config_type * config); -bool analysis_config_get_do_kernel_regression(const analysis_config_type * config); -int analysis_config_get_kernel_function(const analysis_config_type * config); -int analysis_config_get_kernel_param(const analysis_config_type * config); -int analysis_config_get_nfolds_CV(const analysis_config_type * config); -int analysis_config_get_subspace_dimension(const analysis_config_type * config); -bool analysis_config_get_bootstrap(const analysis_config_type * config); -bool analysis_config_get_penalised_press(const analysis_config_type * config); -bool analysis_config_get_do_scaling(const analysis_config_type * config); -void analysis_config_set_rerun(analysis_config_type * config , bool rerun); -void analysis_config_set_rerun_start( analysis_config_type * config , int rerun_start ); -void analysis_config_set_truncation( analysis_config_type * config , double truncation); -void analysis_config_set_alpha( analysis_config_type * config , double alpha); -void analysis_config_set_merge_observations( analysis_config_type * config , bool merge_observations); -void analysis_config_set_nfolds_CV( analysis_config_type * config , int folds); -void analysis_config_set_subspace_dimension( analysis_config_type * config , int dimension); -void analysis_config_set_do_bootstrap( analysis_config_type * config , bool do_bootstrap); -void analysis_config_set_penalised_press( analysis_config_type * config , bool do_pen_press); -void analysis_config_set_log_path(analysis_config_type * config , const char * log_path ); -void analysis_config_set_std_cutoff( analysis_config_type * config , double std_cutoff ); -double analysis_config_get_std_cutoff( const analysis_config_type * config ); -void analysis_config_add_config_items( config_parser_type * config ); -void analysis_config_fprintf_config( analysis_config_type * config , FILE * stream); - -bool analysis_config_select_module( analysis_config_type * config , const char * module_name ); -analysis_module_type * analysis_config_get_active_module( analysis_config_type * config ); -void analysis_config_set_single_node_update(analysis_config_type * config , bool single_node_update); -bool analysis_config_get_single_node_update(const analysis_config_type * config); - -void analysis_config_set_store_PC( analysis_config_type * config , bool store_PC); -bool analysis_config_get_store_PC( const analysis_config_type * config ); -void analysis_config_set_PC_filename( analysis_config_type * config , const char * filename ); -const char * analysis_config_get_PC_filename( const analysis_config_type * config ); -void analysis_config_set_PC_path( analysis_config_type * config , const char * path ); -const char * analysis_config_get_PC_path( const analysis_config_type * config ); -bool analysis_config_have_enough_realisations( const analysis_config_type* config, int realisations, int ensemble_size); -void analysis_config_set_stop_long_running( analysis_config_type * config, bool stop_long_running ); -bool analysis_config_get_stop_long_running( const analysis_config_type * config); -void analysis_config_set_max_runtime( analysis_config_type * config, int max_runtime ); -int analysis_config_get_max_runtime( const analysis_config_type * config ); -const char * analysis_config_get_active_module_name( const analysis_config_type * config ); -bool analysis_config_get_std_scale_correlated_obs( const analysis_config_type * config); -void analysis_config_set_std_scale_correlated_obs( analysis_config_type * config, bool std_scale_correlated_obs); - -double analysis_config_get_global_std_scaling(const analysis_config_type * config); -void analysis_config_set_global_std_scaling(analysis_config_type * config, double global_std_scaling); - - UTIL_IS_INSTANCE_HEADER( analysis_config ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/analysis_iter_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/analysis_iter_config.h deleted file mode 100644 index e0a2e007b8..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/analysis_iter_config.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'analysis_iter_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ANALYSIS_ITER_CONFIG_H -#define ERT_ANALYSIS_ITER_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -typedef struct analysis_iter_config_struct analysis_iter_config_type; - - void analysis_iter_config_set_num_iterations( analysis_iter_config_type * config , int num_iterations); - int analysis_iter_config_get_num_iterations( const analysis_iter_config_type * config ); - void analysis_iter_config_set_num_retries_per_iteration( analysis_iter_config_type * config , int num_retries); - int analysis_iter_config_get_num_retries_per_iteration( const analysis_iter_config_type * config ); - void analysis_iter_config_set_case_fmt( analysis_iter_config_type * config, const char * case_fmt); - char * analysis_iter_config_get_case_fmt( analysis_iter_config_type * config); - analysis_iter_config_type * analysis_iter_config_alloc(); - void analysis_iter_config_free( analysis_iter_config_type * config ); - const char * analysis_iter_config_iget_case( analysis_iter_config_type * config , int iter); - void analysis_iter_config_add_config_items( config_parser_type * config ); - void analysis_iter_config_init(analysis_iter_config_type * iter_config , const config_content_type * config); - bool analysis_iter_config_case_fmt_set( const analysis_iter_config_type * config ); - bool analysis_iter_config_num_iterations_set( const analysis_iter_config_type * config ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/block_fs_driver.h b/ThirdParty/Ert/libenkf/include/ert/enkf/block_fs_driver.h deleted file mode 100644 index da9bc072e9..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/block_fs_driver.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'block_fs_driver.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_BLOCK_FS_DRIVER_H -#define ERT_BLOCK_FS_DRIVER_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - - typedef struct block_fs_driver_struct block_fs_driver_type; - - - void block_fs_driver_fwrite_mount_info(FILE * stream , fs_driver_enum driver_type , int num_block_fs_drivers); - block_fs_driver_type * block_fs_driver_fread_alloc(const char * root_path , FILE * stream); - bool block_fs_sscanf_key(const char * key , char ** config_key , int * __report_step , int * __iens); - void * block_fs_driver_open(FILE * fstab_stream , const char * mount_point , fs_driver_enum driver_type , bool read_only); - void block_fs_driver_create_fs( FILE * stream , - const char * mount_point , - fs_driver_enum driver_type , - int num_fs , - const char * ens_path_fmt, - const char * filename ); - void block_fs_driver_fskip(FILE * fstab_stream); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/block_obs.h b/ThirdParty/Ert/libenkf/include/ert/enkf/block_obs.h deleted file mode 100644 index 47c8dbfb13..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/block_obs.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'block_obs.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_BLOCK_OBS_H -#define ERT_BLOCK_OBS_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include - - - -typedef struct block_obs_struct block_obs_type; - - typedef enum { - SOURCE_FIELD = 10, - SOURCE_SUMMARY = 12 - } block_obs_source_type; - - - block_obs_type * block_obs_alloc_complete(const char * obs_label, - block_obs_source_type source_type , - const stringlist_type * summary_keys , - const void * data_config , - const ecl_grid_type * grid , - int size, - const int * i, - const int * j, - const int * k, - const double * obs_value, - const double * obs_std); - - block_obs_type * block_obs_alloc(const char * obs_key, - const void * data_config , - const ecl_grid_type * grid); - - -void block_obs_free( - block_obs_type * block_obs); - - -block_obs_type * block_obs_alloc_from_BLOCK_OBSERVATION(const conf_instance_type * conf_instance, const history_type * history); - -double block_obs_iget_depth( const block_obs_type * block_obs , int index); -int block_obs_iget_i(const block_obs_type * , int index); -int block_obs_iget_j(const block_obs_type * , int index); -int block_obs_iget_k(const block_obs_type * , int index); -int block_obs_get_size(const block_obs_type * ); -void block_obs_iget(const block_obs_type * block_obs, int , double * , double * ); -double block_obs_iget_value(const block_obs_type * block_obs, int index ); -double block_obs_iget_std(const block_obs_type * block_obs, int index ); -void block_obs_iget_ijk(const block_obs_type * block_obs , int block_nr , int * i , int * j , int * k); -double block_obs_iget_data( const block_obs_type * block_obs, const void * state , int iobs , node_id_type node_id ); -double block_obs_iget_std_scaling(const block_obs_type * block_obs, int index ); -void block_obs_update_std_scale(block_obs_type * block_obs, double scale_factor, const active_list_type * active_list); -void block_obs_append_field_obs( block_obs_type * block_obs , int i , int j , int k , double value , double std); -void block_obs_append_summary_obs( block_obs_type * block_obs , int i , int j , int k , const char * sum_key , double value , double std); - -VOID_FREE_HEADER(block_obs); -VOID_GET_OBS_HEADER(block_obs); -UTIL_IS_INSTANCE_HEADER(block_obs); -VOID_MEASURE_HEADER(block_obs); -VOID_USER_GET_OBS_HEADER(block_obs); -VOID_CHI2_HEADER(block_obs); -VOID_UPDATE_STD_SCALE_HEADER(block_obs); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/cases_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/cases_config.h deleted file mode 100644 index 78915cc31d..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/cases_config.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'cases_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CASES_CONFIG_H -#define ERT_CASES_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - - -typedef struct cases_config_struct cases_config_type; - - bool cases_config_set_int( cases_config_type * config , const char * var_name, int num_iterations); - int cases_config_get_iteration_number( const cases_config_type * config ); - void cases_config_fwrite( cases_config_type * config , const char * filename ); - void cases_config_fread( cases_config_type * config , const char * filename); - cases_config_type * cases_config_alloc(); - void cases_config_free( cases_config_type * config ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/config_keys.h b/ThirdParty/Ert/libenkf/include/ert/enkf/config_keys.h deleted file mode 100644 index dc8c835089..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/config_keys.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'config_keys.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ - - -#ifndef ERT_CONFIG_KEYS_H -#define ERT_CONFIG_KEYS_H -#ifdef __cplusplus -extern "C" { -#endif - -/* These keys are used as options in KEY:VALUE statements */ -#define BASE_SURFACE_KEY "BASE_SURFACE" -#define DEFINE_KEY "DEFINE" -#define DYNAMIC_KEY "DYNAMIC" -#define ECL_FILE_KEY "ECL_FILE" -#define FORWARD_INIT_KEY "FORWARD_INIT" -#define GENERAL_KEY "GENERAL" -#define INCLUDE_KEY "INCLUDE" -#define INIT_FILES_KEY "INIT_FILES" -#define INIT_TRANSFORM_KEY "INIT_TRANSFORM" -#define INPUT_FORMAT_KEY "INPUT_FORMAT" -#define INPUT_TRANSFORM_KEY "INPUT_TRANSFORM" -#define KEY_KEY "KEY" -#define MAX_KEY "MAX" -#define MIN_KEY "MIN" -#define MIN_STD_KEY "MIN_STD" -#define OUTPUT_FILE_KEY "OUTPUT_FILE" -#define OUTPUT_FORMAT_KEY "OUTPUT_FORMAT" -#define OUTPUT_TRANSFORM_KEY "OUTPUT_TRANSFORM" -#define PARAMETER_KEY "PARAMETER" -#define REPORT_STEPS_KEY "REPORT_STEPS" -#define RESULT_FILE_KEY "RESULT_FILE" -#define TEMPLATE_KEY "TEMPLATE" - - -#define ADD_FIXED_LENGTH_SCHEDULE_KW_KEY "ADD_FIXED_LENGTH_SCHEDULE_KW" -#define ANALYSIS_COPY_KEY "ANALYSIS_COPY" -#define ANALYSIS_LOAD_KEY "ANALYSIS_LOAD" -#define ANALYSIS_SET_VAR_KEY "ANALYSIS_SET_VAR" -#define ANALYSIS_SELECT_KEY "ANALYSIS_SELECT" -#define CASE_TABLE_KEY "CASE_TABLE" -#define CONTAINER_KEY "CONTAINER" -#define CUSTOM_KW_KEY "CUSTOM_KW" -#define DATA_FILE_KEY "DATA_FILE" -#define DATA_KW_KEY "DATA_KW" -#define DBASE_TYPE_KEY "DBASE_TYPE" -#define DELETE_RUNPATH_KEY "DELETE_RUNPATH" -#define ECLBASE_KEY "ECLBASE" -#define END_DATE_KEY "END_DATE" -#define ENKF_BOOTSTRAP_KEY "ENKF_BOOTSTRAP" -#define ENKF_PEN_PRESS_KEY "ENKF_PEN_PRESS" -#define ENKF_ALPHA_KEY "ENKF_ALPHA" -#define ENKF_CROSS_VALIDATION_KEY "ENKF_CROSS_VALIDATION" -#define ENKF_CV_FOLDS_KEY "ENKF_CV_FOLDS" -#define ENKF_SCALING_KEY "ENKF_SCALING" -#define ENKF_KERNEL_REG_KEY "ENKF_KERNEL_REGRESSION" -#define ENKF_KERNEL_FUNC_KEY "ENKF_KERNEL_FUNCTION" -#define ENKF_KERNEL_PARAM_KEY "ENKF_KERNEL_PARAM" -#define ENKF_LOCAL_CV_KEY "ENKF_LOCAL_CV" -#define ENKF_MERGE_OBSERVATIONS_KEY "ENKF_MERGE_OBSERVATIONS" -#define ENKF_MODE_KEY "ENKF_MODE" -#define ENKF_RERUN_KEY "ENKF_RERUN" -#define ENKF_TRUNCATION_KEY "ENKF_TRUNCATION" -#define ENSPATH_KEY "ENSPATH" -#define ITER_CASE_KEY "ITER_CASE" -#define ITER_COUNT_KEY "ITER_COUNT" -#define ITER_RETRY_COUNT_KEY "ITER_RETRY_COUNT" -#define FIELD_KEY "FIELD" -#define FORWARD_MODEL_KEY "FORWARD_MODEL" -#define GEN_DATA_KEY "GEN_DATA" -#define GEN_KW_KEY "GEN_KW" -#define GEN_KW_TAG_FORMAT_KEY "GEN_KW_TAG_FORMAT" -#define GEN_KW_EXPORT_FILE_KEY "GEN_KW_EXPORT_FILE" -#define GEN_PARAM_KEY "GEN_PARAM" -#define GRID_KEY "GRID" -#define HISTORY_SOURCE_KEY "HISTORY_SOURCE" -#define HOSY_TYPE_KEY "HOST_TYPE" -#define IGNORE_SCHEDULE_KEY "IGNORE_SCHEDULE" -#define INIT_SECTION_KEY "INIT_SECTION" -#define INSTALL_JOB_KEY "INSTALL_JOB" -#define INSTALL_JOB_DIRECTORY_KEY "INSTALL_JOB_DIRECTORY" -#define JOB_SCRIPT_KEY "JOB_SCRIPT" -#define JOBNAME_KEY "JOBNAME" -#define LICENSE_PATH_KEY "LICENSE_PATH" -#define LOAD_SEED_KEY "LOAD_SEED" -#define LOCAL_CONFIG_KEY "LOCAL_CONFIG" -#define LOG_FILE_KEY "LOG_FILE" -#define LOG_LEVEL_KEY "LOG_LEVEL" -#define LSF_QUEUE_KEY "LSF_QUEUE" -#define LSF_RESOURCES_KEY "LSF_RESOURCES" -#define LSF_SERVER_KEY "LSF_SERVER" -#define TORQUE_QUEUE_KEY "TORQUE_QUEUE" -#define MAX_RESAMPLE_KEY "MAX_RESAMPLE" -#define MAX_RUNNING_LOCAL_KEY "MAX_RUNNING_LOCAL" -#define MAX_RUNNING_LSF_KEY "MAX_RUNNING_LSF" -#define MAX_RUNNING_RSH_KEY "MAX_RUNNING_RSH" -#define MAX_SUBMIT_KEY "MAX_SUBMIT" -#define NUM_REALIZATIONS_KEY "NUM_REALIZATIONS" -#define MIN_REALIZATIONS_KEY "MIN_REALIZATIONS" -#define OBS_CONFIG_KEY "OBS_CONFIG" -#define PLOT_PATH_KEY "PLOT_PATH" -#define PRE_CLEAR_RUNPATH_KEY "PRE_CLEAR_RUNPATH" -#define QUEUE_SYSTEM_KEY "QUEUE_SYSTEM" -#define QUEUE_OPTION_KEY "QUEUE_OPTION" -#define QC_PATH_KEY "QC_PATH" -#define QC_WORKFLOW_KEY "QC_WORKFLOW" -#define HOOK_WORKFLOW_KEY "HOOK_WORKFLOW" -#define REFCASE_KEY "REFCASE" -#define REFCASE_LIST_KEY "REFCASE_LIST" -#define RERUN_START_KEY "RERUN_START" -#define RSH_COMMAND_KEY "RSH_COMMAND" -#define RSH_HOST_KEY "RSH_HOST" -#define RUNPATH_FILE_KEY "RUNPATH_FILE" -#define RUNPATH_KEY "RUNPATH" -#define ITER_RUNPATH_KEY "ITER_RUNPATH" -#define RERUN_PATH_KEY "RERUN_PATH" -#define RUN_TEMPLATE_KEY "RUN_TEMPLATE" -#define RFT_CONFIG_KEY "RFT_CONFIG" -#define RFTPATH_KEY "RFTPATH" -#define SCHEDULE_FILE_KEY "SCHEDULE_FILE" -#define SCHEDULE_PREDICTION_FILE_KEY "SCHEDULE_PREDICTION_FILE" -#define SETENV_KEY "SETENV" -#define STATIC_KW_KEY "ADD_STATIC_KW" -#define STD_CUTOFF_KEY "STD_CUTOFF" -#define SUMMARY_KEY "SUMMARY" -#define SURFACE_KEY "SURFACE" -#define UPDATE_LOG_PATH_KEY "UPDATE_LOG_PATH" -#define UPDATE_PATH_KEY "UPDATE_PATH" -#define SINGLE_NODE_UPDATE_KEY "SINGLE_NODE_UPDATE" -#define STORE_SEED_KEY "STORE_SEED" -#define UMASK_KEY "UMASK" -#define WORKFLOW_JOB_DIRECTORY_KEY "WORKFLOW_JOB_DIRECTORY" -#define LOAD_WORKFLOW_KEY "LOAD_WORKFLOW" -#define LOAD_WORKFLOW_JOB_KEY "LOAD_WORKFLOW_JOB" -#define STOP_LONG_RUNNING_KEY "STOP_LONG_RUNNING" -#define MAX_RUNTIME_KEY "MAX_RUNTIME" -#define TIME_MAP_KEY "TIME_MAP" -#define EXT_JOB_SEARCH_PATH_KEY "EXT_JOB_SEARCH_PATH" -#define STD_SCALE_CORRELATED_OBS_KEY "STD_SCALE_CORRELATED_OBS" -#define PLOT_SETTING_KEY "PLOT_SETTINGS" -#define UPDATE_SETTING_KEY "UPDATE_SETTINGS" - -#define CONFIG_BOOL_STRING( var ) (var) ? "TRUE" : "FALSE" - - - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/config_parser.h b/ThirdParty/Ert/libenkf/include/ert/enkf/config_parser.h deleted file mode 100644 index 4df730dcf4..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/config_parser.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'config_parser.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CONFIG_PARSER_H -#define ERT_CONFIG_PARSER_H - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/container.h b/ThirdParty/Ert/libenkf/include/ert/enkf/container.h deleted file mode 100644 index 215c6f0969..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/container.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'container.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CONTAINER_H -#define ERT_CONTAINER_H - -#ifdef __cplusplus -extern "C" { -#endif -#include - - - typedef struct container_struct container_type; - - void container_add_node(container_type * container , void * child_node ); - const void * container_iget_node(const container_type * container , int index); - int container_get_size( const container_type * container ); - void container_assert_size( const container_type * container ); - - VOID_ALLOC_HEADER(container); - VOID_FREE_HEADER(container); - UTIL_IS_INSTANCE_HEADER(container); - UTIL_SAFE_CAST_HEADER_CONST(container); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/container_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/container_config.h deleted file mode 100644 index ed0399345c..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/container_config.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'container_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_CONTAINER_CONFIG_H -#define ERT_CONTAINER_CONFIG_H - - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - - typedef struct container_config_struct container_config_type; - - - container_config_type * container_config_alloc( const char * key ); - void container_config_free( container_config_type * container ); - void container_config_add_node( container_config_type * container, const enkf_config_node_type * config_node); - const char * container_config_iget_key( const container_config_type * container_config , int index); - const void * container_config_iget_node(const container_config_type * container_config , int index); - int container_config_get_size( const container_config_type * container_config ); - - UTIL_IS_INSTANCE_HEADER(container_config); - UTIL_SAFE_CAST_HEADER_CONST(container_config); - GET_DATA_SIZE_HEADER(container); - VOID_GET_DATA_SIZE_HEADER(container); - VOID_CONFIG_FREE_HEADER(container); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw.h b/ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw.h deleted file mode 100644 index f8282cd830..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef ERT_CUSTOM_KW_H -#define ERT_CUSTOM_KW_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - - typedef struct custom_kw_struct custom_kw_type; - - custom_kw_type * custom_kw_alloc(const custom_kw_config_type * config); - void custom_kw_free(custom_kw_type * custom_kw); - custom_kw_config_type * custom_kw_get_config(const custom_kw_type * custom_kw); - const stringlist_type * custom_kw_get_data(const custom_kw_type * custom_kw); - bool custom_kw_key_is_null(const custom_kw_type * custom_kw, char * key); - double custom_kw_iget_as_double(const custom_kw_type * custom_kw, int index); - const char * custom_kw_iget_as_string(const custom_kw_type * custom_kw, int index); - void custom_kw_set_string(custom_kw_type * custom_kw, const char * key, const char * value); - void custom_kw_set_double(custom_kw_type * custom_kw, const char * key, double value); - - bool custom_kw_fload(custom_kw_type * custom_kw, const char * filename); - bool custom_kw_forward_load(custom_kw_type * custom_kw, const char * ecl_file, const forward_load_context_type * load_context); - - bool custom_kw_write_to_buffer(const custom_kw_type * custom_kw, buffer_type * buffer, int report_step); - void custom_kw_read_from_buffer(const custom_kw_type * custom_kw, buffer_type * buffer, enkf_fs_type * fs, int report_step); - void custom_kw_ecl_write(const custom_kw_type * custom_kw, const char * run_path, const char * base_file, void * filestream); - void custom_kw_serialize(const custom_kw_type * custom_kw, node_id_type node_id, const active_list_type * active_list, matrix_type * A, int row_offset, int column); - void custom_kw_deserialize(custom_kw_type * custom_kw, node_id_type node_id, const active_list_type * active_list, const matrix_type * A, int row_offset , int column); - - - UTIL_SAFE_CAST_HEADER(custom_kw); - UTIL_SAFE_CAST_HEADER_CONST(custom_kw); - VOID_USER_GET_HEADER(custom_kw); - VOID_ALLOC_HEADER(custom_kw); - VOID_FREE_HEADER(custom_kw); - VOID_FORWARD_LOAD_HEADER(custom_kw) - VOID_FLOAD_HEADER(custom_kw) - VOID_ECL_WRITE_HEADER(custom_kw); - VOID_READ_FROM_BUFFER_HEADER(custom_kw); - VOID_WRITE_TO_BUFFER_HEADER(custom_kw); - VOID_SERIALIZE_HEADER(custom_kw) - VOID_DESERIALIZE_HEADER(custom_kw) -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw_config.h deleted file mode 100644 index e532807d1f..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw_config.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef ERT_CUSTOM_KW_CONFIG_H -#define ERT_CUSTOM_KW_CONFIG_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include -#include -#include - -#include -#include -#include - - typedef struct custom_kw_config_struct custom_kw_config_type; - - custom_kw_config_type * custom_kw_config_alloc_empty(const char * key, const char * result_file, const char * output_file); - custom_kw_config_type * custom_kw_config_alloc_with_definition(const char * key, const hash_type * definition); - void custom_kw_config_free(custom_kw_config_type * config); - const char * custom_kw_config_get_name(const custom_kw_config_type * config); - char * custom_kw_config_get_result_file(const custom_kw_config_type * config); - char * custom_kw_config_get_output_file(const custom_kw_config_type * config); - bool custom_kw_config_parse_result_file(custom_kw_config_type * config, const char * result_file, stringlist_type * result); - void custom_kw_config_serialize(const custom_kw_config_type * config, stringlist_type * config_set); - void custom_kw_config_deserialize(custom_kw_config_type * config, stringlist_type * config_set); - bool custom_kw_config_has_key(const custom_kw_config_type * config, const char * key); - bool custom_kw_config_key_is_double(const custom_kw_config_type * config, const char * key); - int custom_kw_config_index_of_key(const custom_kw_config_type * config, const char * key); - int custom_kw_config_size(const custom_kw_config_type * config); - stringlist_type * custom_kw_config_get_keys(const custom_kw_config_type * config); - - - UTIL_IS_INSTANCE_HEADER(custom_kw_config); - UTIL_SAFE_CAST_HEADER(custom_kw_config); - UTIL_SAFE_CAST_HEADER_CONST(custom_kw_config); - VOID_FREE_HEADER(custom_kw_config) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw_config_set.h b/ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw_config_set.h deleted file mode 100644 index b99ca9c9b8..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/custom_kw_config_set.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef ERT_CUSTOM_KW_CONFIG_SET_H -#define ERT_CUSTOM_KW_CONFIG_SET_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - - typedef struct custom_kw_config_set_struct custom_kw_config_set_type; - - custom_kw_config_set_type * custom_kw_config_set_alloc(); - custom_kw_config_set_type * custom_kw_config_set_alloc_from_file(const char * filename); - void custom_kw_config_set_free(custom_kw_config_set_type * set); - void custom_kw_config_set_add_config(custom_kw_config_set_type * set, const custom_kw_config_type * config); - void custom_kw_config_set_update_config(custom_kw_config_set_type * set, custom_kw_config_type * config); - void custom_kw_config_set_reset(custom_kw_config_set_type * set); - stringlist_type * custom_kw_config_set_get_keys_alloc(custom_kw_config_set_type * set); - void custom_kw_config_set_fwrite(custom_kw_config_set_type * set, const char * filename); - bool custom_kw_config_set_fread(custom_kw_config_set_type * set, const char * filename); - - UTIL_IS_INSTANCE_HEADER(custom_kw_config_set); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/data_ranking.h b/ThirdParty/Ert/libenkf/include/ert/enkf/data_ranking.h deleted file mode 100644 index a85e90fea7..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/data_ranking.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'data_ranking.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_DATA_RANKING_H -#define ERT_DATA_RANKING_H - -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -#include -#include - -#include - - typedef struct data_ranking_struct data_ranking_type; - - UTIL_IS_INSTANCE_HEADER( data_ranking ); - UTIL_SAFE_CAST_HEADER(data_ranking); - - const perm_vector_type * data_ranking_get_permutation( const data_ranking_type * data_ranking ); - data_ranking_type * data_ranking_alloc( bool sort_increasing , int ens_size , const char * user_key , const char * key_index , enkf_fs_type * fs , const enkf_config_node_type * config_node , int step ); - void data_ranking_free__( void * arg ); - void data_ranking_display( const data_ranking_type * data_ranking , FILE * stream); - -#ifdef __cplusplus -} -#endif -#endif - - - - - diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/ecl_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/ecl_config.h deleted file mode 100644 index a8270d2c47..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/ecl_config.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ecl_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ECL_CONFIG_H -#define ERT_ECL_CONFIG_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include - -#include - - - typedef struct ecl_config_struct ecl_config_type; - - const char * ecl_config_get_data_file(const ecl_config_type * ); - void ecl_config_set_data_file( ecl_config_type * ecl_config , const char * data_file); - ui_return_type * ecl_config_validate_data_file(const ecl_config_type * ecl_config, const char * data_file); - - void ecl_config_set_schedule_file(ecl_config_type * ecl_config, const char * schedule_file, const char * schedule_target_file); - ui_return_type * ecl_config_validate_schedule_file(const ecl_config_type * ecl_config , const char * schedule_file); - const char * ecl_config_get_schedule_file( const ecl_config_type * ecl_config ); - const char * ecl_config_get_schedule_target(const ecl_config_type * ); - bool ecl_config_has_schedule( const ecl_config_type * ecl_config ); - - void ecl_config_set_eclbase( ecl_config_type * ecl_config , const char * eclbase_fmt ); - ui_return_type * ecl_config_validate_eclbase( const ecl_config_type * ecl_config , const char * eclbase_fmt ); - const path_fmt_type * ecl_config_get_eclbase_fmt(const ecl_config_type * ); - - void ecl_config_set_init_section( ecl_config_type * ecl_config , const char * input_init_section ); - ui_return_type * ecl_config_validate_init_section( const ecl_config_type * ecl_config , const char * input_init_section ); - const char * ecl_config_get_init_section(const ecl_config_type * ecl_config); - const char * ecl_config_get_equil_init_file(const ecl_config_type * ); - bool ecl_config_has_init_section( const ecl_config_type * ecl_config ); - - - void ecl_config_set_grid( ecl_config_type * ecl_config , const char * grid_file ); - const char * ecl_config_get_gridfile( const ecl_config_type * ecl_config ); - ecl_grid_type * ecl_config_get_grid(const ecl_config_type * ); - ui_return_type * ecl_config_validate_grid( const ecl_config_type * ecl_config , const char * grid_file ); - - bool ecl_config_load_refcase( ecl_config_type * ecl_config , const char * refcase); - ui_return_type * ecl_config_validate_refcase( const ecl_config_type * ecl_config , const char * refcase ); - const ecl_sum_type * ecl_config_get_refcase(const ecl_config_type * ecl_config); - bool ecl_config_has_refcase( const ecl_config_type * ecl_config ); - ecl_refcase_list_type * ecl_config_get_refcase_list( const ecl_config_type * ecl_config ); - - /*****************************************************************/ - - void ecl_config_static_kw_init( ecl_config_type * ecl_config , const config_content_type * config ); - bool ecl_config_active( const ecl_config_type * config ); - time_t ecl_config_get_end_date( const ecl_config_type * ecl_config ); - time_t ecl_config_get_start_date( const ecl_config_type * ecl_config ); - - const char * ecl_config_get_schedule_prediction_file( const ecl_config_type * ecl_config ); - void ecl_config_set_schedule_prediction_file( ecl_config_type * ecl_config , const char * schedule_prediction_file ); - sched_file_type * ecl_config_get_sched_file(const ecl_config_type * ); - - - int ecl_config_get_num_cpu( const ecl_config_type * ecl_config ); - void ecl_config_init( ecl_config_type * ecl_config , const config_content_type * config); - void ecl_config_free( ecl_config_type *); - bool ecl_config_include_static_kw(const ecl_config_type * , const char * ); - void ecl_config_add_static_kw(ecl_config_type *, const char *); - ecl_io_config_type * ecl_config_get_io_config(const ecl_config_type * ); - - bool ecl_config_get_formatted(const ecl_config_type * ); - bool ecl_config_get_unified_restart(const ecl_config_type * ); - bool ecl_config_get_unified_summary(const ecl_config_type * ); - int ecl_config_get_num_restart_files(const ecl_config_type * ); - int ecl_config_get_last_history_restart( const ecl_config_type * ); - bool ecl_config_can_restart( const ecl_config_type * ecl_config ); - void ecl_config_assert_restart( const ecl_config_type * ecl_config ); - const char * ecl_config_get_eclbase( const ecl_config_type * ecl_config ); - const char * ecl_config_get_refcase_name( const ecl_config_type * ecl_config); - void ecl_config_clear_static_kw( ecl_config_type * ecl_config ); - stringlist_type * ecl_config_get_static_kw_list( const ecl_config_type * ecl_config ); - void ecl_config_fprintf_config( const ecl_config_type * ecl_config , FILE * stream ); - ecl_config_type * ecl_config_alloc( ); - void ecl_config_add_config_items( config_parser_type * config ); - const char * ecl_config_get_depth_unit( const ecl_config_type * ecl_config ); - const char * ecl_config_get_pressure_unit( const ecl_config_type * ecl_config ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/ecl_refcase_list.h b/ThirdParty/Ert/libenkf/include/ert/enkf/ecl_refcase_list.h deleted file mode 100644 index 22627d7b31..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/ecl_refcase_list.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'ecl_refcase_list.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_ECL_REFCASE_LIST_H -#define ERT_ECL_REFCASE_LIST_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - - - typedef struct ecl_refcase_list_struct ecl_refcase_list_type; - - ecl_refcase_list_type * ecl_refcase_list_alloc( ); - void ecl_refcase_list_free( ecl_refcase_list_type * refcase_list ); - - bool ecl_refcase_list_has_default( ecl_refcase_list_type * refcase_list ); - const ecl_sum_type * ecl_refcase_list_get_default( ecl_refcase_list_type * refcase_list ); - bool ecl_refcase_list_set_default( ecl_refcase_list_type * refcase_list , const char * default_case); - int ecl_refcase_list_get_size(ecl_refcase_list_type * refcase_list ); - int ecl_refcase_list_add_matching( ecl_refcase_list_type * refcase_list , const char * glob_string); - int ecl_refcase_list_add_case( ecl_refcase_list_type * refcase_list , const char * case_name); - const char * ecl_refcase_list_iget_pathcase( ecl_refcase_list_type * refcase_list , int index); - const ecl_sum_type * ecl_refcase_list_iget_case( ecl_refcase_list_type * refcase_list , int index); - const ecl_sum_type * ecl_refcase_list_get_case( ecl_refcase_list_type * refcase_list , const char * case_name); - bool ecl_refcase_list_has_case( ecl_refcase_list_type * refcase_list , const char * case_name); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf.h deleted file mode 100644 index 280430db55..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#define SPLASH_LENGTH 8 -const char *splash_text[SPLASH_LENGTH] = { -" 8888888888 888 d8P 8888888888", -" 888 888 d8P 888 ", -" 888 888 d8P 888 ", -" 8888888 88888b. 888d88K 8888888 ", -" 888 888 '88b 8888888b 888 ", -" 888 888 888 888 Y88b 888 ", -" 888 888 888 888 Y88b 888 ", -" 8888888888 888 888 888 Y88b 888 "}; - diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_analysis.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_analysis.h deleted file mode 100644 index 294f441fee..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_analysis.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_analysis.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_ENKF_ANALYSIS_H -#define ERT_ENKF_ANALYSIS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include - -#include - - - -void enkf_analysis_fprintf_obs_summary(const obs_data_type * obs_data , - const meas_data_type * meas_data , - const int_vector_type * step_list , - const char * ministep_name , - FILE * stream ); - -void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , - meas_data_type * meas_data , - double std_cutoff , - double alpha, - bool verbose); - -void enkf_analysis_deactivate_std_zero(obs_data_type * obs_data , - meas_data_type * meas_data, - bool verbose); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_config_node.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_config_node.h deleted file mode 100644 index bc4f84a117..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_config_node.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_config_node.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_CONFIG_NODE_H -#define ERT_ENKF_CONFIG_NODE_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include - - typedef void (config_free_ftype) (void *); - typedef int (get_data_size_ftype) (const void *); - typedef void (config_fprintf_ftype) (const void * , enkf_var_type , FILE * ); - - typedef struct enkf_config_node_struct enkf_config_node_type; - typedef struct enkf_node_struct enkf_node_type; - - - bool enkf_config_node_has_vector( const enkf_config_node_type * node , enkf_fs_type * fs , int iens); - bool enkf_config_node_has_node( const enkf_config_node_type * node , enkf_fs_type * fs , node_id_type node_id); - bool enkf_config_node_vector_storage( const enkf_config_node_type * config_node); - - enkf_config_node_type * enkf_config_node_new_GEN_PARAM( const char * key , bool forward_init); - enkf_config_node_type * enkf_config_node_new_GEN_DATA( const char * key , bool forward_init); - enkf_config_node_type * enkf_config_node_new_custom_kw(const char * key, const char * result_file, const char * output_file); - enkf_config_node_type * enkf_config_node_new_defined_custom_kw(const char * key, const hash_type * definition); - - void enkf_config_node_update_min_std( enkf_config_node_type * config_node , const char * min_std_file ); - - enkf_config_node_type * enkf_config_node_alloc_GEN_PARAM( const char * node_key , - bool forward_init , - gen_data_file_format_type input_format , - gen_data_file_format_type output_format , - const char * init_file_fmt , - const char * ert_outfile_fmt); - - - enkf_config_node_type * enkf_config_node_alloc_GEN_DATA_state( const char * key, - bool forward_init , - gen_data_file_format_type input_format, - gen_data_file_format_type output_format, - const char * init_file_fmt , - const char * template_ecl_file , - const char * template_data_key , - const char * enkf_outfile_fmt , - const char * enkf_infile_fmt , - const char * min_std_file); - - - - enkf_config_node_type * enkf_config_node_alloc_GEN_DATA_result( const char * key , - gen_data_file_format_type input_format, - const char * enkf_infile_fmt ); - - - - - void enkf_config_node_update_GEN_PARAM( enkf_config_node_type * config_node, - gen_data_file_format_type input_format, - gen_data_file_format_type output_format, - const char * init_file_fmt , - const char * template_ecl_file , - const char * template_data_key , - const char * enkf_outfile_fmt , - const char * min_std_file); - - - void enkf_config_node_update_GEN_DATA_result( enkf_config_node_type * config_node, - gen_data_file_format_type input_format, - const char * enkf_infile_fmt ); - - - void enkf_config_node_update_GEN_DATA_state( enkf_config_node_type * config_node, - gen_data_file_format_type input_format, - gen_data_file_format_type output_format, - const char * init_file_fmt , - const char * template_ecl_file , - const char * template_data_key , - const char * enkf_outfile_fmt , - const char * enkf_infile_fmt , - const char * min_std_file); - - - enkf_config_node_type * enkf_config_node_new_surface( const char * key , bool forward_init); - - - void enkf_config_node_update_surface( enkf_config_node_type * config_node , - const char * base_surface , - const char * init_file_fmt , - const char * output_file , - const char * min_std_file ); - - - void enkf_config_node_update_gen_kw( enkf_config_node_type * config_node , - const char * enkf_outfile_fmt , /* The include file created by ERT for the forward model. */ - const char * template_file , - const char * parameter_file , - const char * min_std_file , - const char * init_file_fmt ); - - void enkf_config_node_update_custom_kw(enkf_config_node_type * config_node, const char * result_file, const char * output_file); - - - enkf_config_node_type * enkf_config_node_alloc(enkf_var_type , - ert_impl_type , - bool , - const char * , - const char * , - const char * , - const char * , - void * ); - - - enkf_config_node_type * enkf_config_node_alloc_summary( const char * key , load_fail_type load_fail); - - - void enkf_config_node_update_state_field( enkf_config_node_type * config_node , int truncation , double value_min , double value_max ); - - - void enkf_config_node_update_parameter_field( enkf_config_node_type * config_node , - const char * enkf_outfile_fmt , - const char * init_file_fmt , - const char * min_std_file , - int truncation , double value_min , double value_max , - const char * init_transform , - const char * output_transform ); - - - void enkf_config_node_update_general_field( enkf_config_node_type * config_node , - const char * enkf_outfile_fmt , - const char * enkf_infile_fmt , - const char * init_file_fmt , - const char * min_std_file , - int truncation , - double value_min , - double value_max , - const char * init_transform , - const char * input_transform , - const char * output_transform ); - - - -/*****************************************************************/ - - enkf_config_node_type * enkf_config_node_new_gen_kw( const char * key , const char * tag_fmt , bool forward_init); - enkf_config_node_type * enkf_config_node_alloc_field( const char * key , ecl_grid_type * ecl_grid, field_trans_table_type * trans_table, bool forward_init); - bool enkf_config_node_is_valid( const enkf_config_node_type * config_node ); - int enkf_config_node_get_data_size( const enkf_config_node_type * node , int report_step); - char * enkf_config_node_alloc_infile(const enkf_config_node_type * , int ); - char * enkf_config_node_alloc_outfile(const enkf_config_node_type * , int ); - int enkf_config_node_get_num_obs( const enkf_config_node_type * config_node ); - int enkf_config_node_load_obs( const enkf_config_node_type * config_node , enkf_obs_type * enkf_obs ,const char * key_index , int obs_count , time_t * sim_time , double * y , double * std); - const stringlist_type * enkf_config_node_get_obs_keys(const enkf_config_node_type *); - void enkf_config_node_add_obs_key(enkf_config_node_type * , const char * ); - void enkf_config_node_clear_obs_keys(enkf_config_node_type * config_node); - void enkf_config_node_free(enkf_config_node_type * ); - bool enkf_config_node_include_type(const enkf_config_node_type * , int ); - int enkf_config_node_get_serial_size(enkf_config_node_type *, int *); - bool enkf_config_node_include_type(const enkf_config_node_type * , int); - ert_impl_type enkf_config_node_get_impl_type(const enkf_config_node_type *); - enkf_var_type enkf_config_node_get_var_type(const enkf_config_node_type *); - void * enkf_config_node_get_ref(const enkf_config_node_type * ); - const char * enkf_config_node_get_key(const enkf_config_node_type * ); - const char * enkf_config_node_get_FIELD_fill_file(enkf_config_node_type * config_node, const path_fmt_type * runpath_fmt); - void enkf_config_node_init_internalization(enkf_config_node_type * ); - void enkf_config_node_set_min_std( enkf_config_node_type * config_node , enkf_node_type * min_std ); - const char * enkf_config_node_get_min_std_file( const enkf_config_node_type * config_node ); - const char * enkf_config_node_get_enkf_outfile( const enkf_config_node_type * conifg_node ); - const char * enkf_config_node_get_enkf_infile( const enkf_config_node_type * config_node ); - const char * enkf_config_node_get_init_file_fmt( const enkf_config_node_type * config_node ); - char * enkf_config_node_alloc_initfile( const enkf_config_node_type * node , const char * path , int iens); - - void enkf_config_node_set_internalize(enkf_config_node_type * node, int report_step); - bool enkf_config_node_internalize(const enkf_config_node_type * node, int report_step); - - void enkf_config_node_fprintf_config( const enkf_config_node_type * config_node , FILE * stream ); - enkf_config_node_type * enkf_config_node_container_iget( const enkf_config_node_type * node , int index); - int enkf_config_node_container_size( const enkf_config_node_type * node ); - - enkf_config_node_type * enkf_config_node_new_container( const char * key ); - void enkf_config_node_update_container( enkf_config_node_type * config_node , const enkf_config_node_type * child_node); - const char * enkf_config_node_iget_container_key( const enkf_config_node_type * config_node , int index); - /* - The enkf_node_free() function declaration is in the enkf_config_node.h header, - because the enkf_config_node needs to know how to free the min_std node. - */ - void enkf_node_free(enkf_node_type *enkf_node); - const enkf_node_type * enkf_config_node_get_min_std( const enkf_config_node_type * config_node ); - - bool enkf_config_node_use_forward_init(const enkf_config_node_type * config_node); - void enkf_config_node_set_forward_init(enkf_config_node_type * config_node, bool forward_init); - - /*****************************************************************/ - - void enkf_config_node_add_GEN_DATA_config_schema( config_parser_type * config ); - void enkf_config_node_add_CUSTOM_KW_config_schema( config_parser_type * config ); - void enkf_config_node_add_GEN_PARAM_config_schema( config_parser_type * config ); - enkf_config_node_type * enkf_config_node_alloc_GEN_PARAM_from_config( const config_content_node_type * config_node ); - enkf_config_node_type * enkf_config_node_alloc_GEN_DATA_from_config( const config_content_node_type * node ); - -UTIL_IS_INSTANCE_HEADER( enkf_config_node ); -UTIL_SAFE_CAST_HEADER(enkf_config_node); -VOID_FREE_HEADER(enkf_config_node); -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_config_private.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_config_private.h deleted file mode 100644 index 511a05ed50..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_config_private.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_config_private.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -struct enkf_config_struct { - int ens_size; - hash_type *config_hash; - hash_type *obs_hash; - bool endian_swap; - path_fmt_type *run_path; - int Nwells; - char **well_list; -}; diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_defaults.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_defaults.h deleted file mode 100644 index 6dbac98d54..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_defaults.h +++ /dev/null @@ -1,296 +0,0 @@ -/** - This file contains verious default values which are compiled into - the enkf executable. Everytime you add something here you should - ask yourself: - - * Can we determine this automagically. - * Should the user be required to enter this information. - -*/ - -#ifndef ERT_ENKF_DEFAULT -#define ERT_ENKF_DEFAULT -#include - -#define DEFAULT_RUNPATH_KEY "DEFAULT_RUNPATH" -#define RERUN_RUNPATH_KEY "DEFAULT_RERUN_PATH" - - -/** - The format string used when creating "search-strings" which should - be replaced in the gen_kw template files - MUST contain one %s - placeholder which will be replaced with the parameter name. -*/ -#define DEFAULT_GEN_KW_TAG_FORMAT "<%s>" - - -/** - Default file name for export file for GEN_KW parameters -*/ -#define DEFAULT_GEN_KW_EXPORT_FILE "parameters.txt" - - -/** - The format string used when creating search strings from user input - with the 'DATA_KW' keyword. The format string must contain one '%s' - placeholder which will be replaced with the user supplied key; can - be just '%s' which means no ERT induced transformations. - - Example: - ------- - DATA_KW KEY1 VALUE1 - - DATA_KW_FORMAT = [<%s>] - - In this case all occurences of '[]' will be replaced with - 'VALUE1'. The DATA_KW_TAG_FORMAT used on user supplied tag keys can - in principle be different from the internal format, but this can of - course be confusing. The internal format is hard linked to job - description files, and can not easily be changed. -*/ - -//#define DEFAULT_DATA_KW_TAG_FORMAT "<%s>" - - -/** - This is the format used for tagging the internal variables like - IENS, and ECLBASE. These values are written into the various job - description files, care should therefor be taken before changing - the value of this variable. It is not user modifiable, and can only - be changed by recompiling. - -*/ -#define INTERNAL_DATA_KW_TAG_FORMAT "<%s>" - - - - -#define DEFAULT_DBASE_TYPE "BLOCK_FS" - -/** - The default number of block_fs instances allocated. -*/ -#define ENKF_DEFAULT_NUM_BLOCK_FS_DRIVERS 32 - - -/* Eclipse IO related stuff */ -#define DEFAULT_FORMATTED false -#define DEFAULT_UNIFIED false - - - -/* - Where the history is coming from - default value for config item: - HISTORY_SOURCE Observe that the function: - model_config_set_history_source() does currently not handle a - default value different from SCHEDULE. -*/ -#define DEFAULT_HISTORY_SOURCE REFCASE_HISTORY - - -#define DEFAULT_MAX_SUBMIT 2 /* The number of times to resubmit - default value for config item: MAX_SUBMIT */ -#define DEFAULT_MAX_INTERNAL_SUBMIT 1 /** Attached to keyword : MAX_RETRY */ - - -#define DEFAULT_LOG_LEVEL 1 -#define DEFAULT_LOG_FILE "log" - - - -/* - Defaults for the EnKF analysis. The analysis_config object is - instantiated with these values. -*/ -#define DEFAULT_ENKF_MODE ENKF_STANDARD -#define DEFAULT_NCOMP 1 -#define DEFAULT_ENKF_TRUNCATION 0.99 -#define DEFAULT_ENKF_ALPHA 3.0 -#define DEFAULT_ENKF_STD_CUTOFF 1e-6 -#define DEFAULT_MERGE_OBSERVATIONS false -#define DEFAULT_RERUN false -#define DEFAULT_RERUN_START 0 -#define DEFAULT_UPDATE_LOG_PATH "update_log" -#define DEFAULT_CV_NFOLDS 10 -#define DEFAULT_ENKF_SCALING true -#define DEFAULT_ENKF_KERNEL_REG false -#define DEFAULT_ENKF_KERNEL_FUNC 1 /*Default is the Gaussian */ -#define DEFAULT_ENKF_KERNEL_PARAM 1 /*Scale by the maximum value in the distance matrix */ -#define DEFAULT_ENKF_CV false -#define DEFAULT_ENKF_BOOTSTRAP false -#define DEFAULT_ENKF_PEN_PRESS false -#define DEFAULT_ENKF_FORCE_NCOMP false -#define DEFAULT_UPDATE_RESULTS false -#define DEFAULT_SINGLE_NODE_UPDATE false -#define DEFAULT_ANALYSIS_MODULE "STD_ENKF" -#define DEFAULT_ANALYSIS_NUM_ITERATIONS 4 -#define DEFAULT_ANALYSIS_ITER_CASE "ITERATED_ENSEMBLE_SMOOTHER%d" -#define DEFAULT_ANALYSIS_ITER_RUNPATH "Simulations/Real%d" -#define DEFAULT_ANALYSIS_MIN_REALISATIONS 0 // 0: No lower limit -#define DEFAULT_ANALYSIS_STOP_LONG_RUNNING false -#define DEFAULT_MAX_RUNTIME 0 -#define DEFAULT_ITER_RETRY_COUNT 4 - - -/* Default directories. */ -#define DEFAULT_QC_PATH "QC" -#define DEFAULT_REPORT_PATH "reports" -#define DEFAULT_RUNPATH "simulations/realization%d" -#define DEFAULT_ENSPATH "storage" -#define DEFAULT_RFTPATH "rft" -#define DEFAULT_PLOT_REFCASE true -#define DEFAULT_REPORT_LARGE false -#define DEFAULT_REPORT_TIMEOUT 120 - -#define DEFAULT_PRE_CLEAR_RUNPATH false - -#define DEFAULT_PLOT_WIDTH 1024 -#define DEFAULT_PLOT_HEIGHT 768 -#define DEFAULT_PLOT_ERRORBAR_MAX 25 -#define DEFAULT_PLOT_ERRORBAR false -#define DEFAULT_IMAGE_TYPE "png" -#define DEFAULT_PLOT_DRIVER "PLPLOT" -#define DEFAULT_IMAGE_VIEWER "/usr/bin/display" -#define DEFAULT_PLOT_LOGY false - -#define DEFAULT_STORE_PC true -#define DEFAULT_PC_FILENAME "PC_%04d-%04d-%s" -#define DEFAULT_PC_PATH "PC" - -#define SUMMARY_KEY_JOIN_STRING ":" -#define USER_KEY_JOIN_STRING ":" - -#define DEFAULT_WORKFLOW_VERBOSE false - -/* - Some #define symbols used when saving configuration files. -*/ -#define CONFIG_OPTION_FORMAT " %s:%s" -#define CONFIG_FLOAT_OPTION_FORMAT " %s:%g" -#define CONFIG_KEY_FORMAT "%-24s" -#define CONFIG_VALUE_FORMAT " %-32s" -#define CONFIG_FLOAT_FORMAT " %32.4f" /* One size - fits all :-) */ -#define CONFIG_INT_FORMAT " %32d" /* One size - fits all :-) */ -#define CONFIG_SHORT_VALUE_FORMAT " %-12s" -#define CONFIG_ENDVALUE_FORMAT " %-32s\n" -#define CONFIG_COMMENT_FORMAT "-- %s\n" -#define CONFIG_COMMENTLINE_FORMAT "----------------------------------------------------------------------\n" - - - -/* The magic string used to signal that *ALL* static keywords should be included. */ -#define DEFAULT_ALL_STATIC_KW "ERT_ALL" -#define NUM_STATIC_KW 56 - -/* - The whole thing is defined as one literal - just because I don't - understand C-linkage. -*/ -#define DEFAULT_STATIC_KW (const char *[NUM_STATIC_KW]) { \ - "ACAQ", \ - "ACAQNUM", \ - "DOUBHEAD", \ - "ENDSOL", \ - "HIDDEN", \ - "IAAQ", \ - "ICAQ", \ - "ICAQNUM", \ - "ICON", \ - "IGRP", \ - "ILBR", \ - "ILBS", \ - "INTEHEAD", \ - "ISEG", \ - "ISTHG", \ - "ISTHW", \ - "IWEL", \ - "LOGIHEAD", \ - "PRESSURE", \ - "RS", \ - "RSEG", \ - "RV", \ - "SAAQ", \ - "SCAQ", \ - "SCAQNUM", \ - "SCON", \ - "SGAS", \ - "SGRP", \ - "STARTSOL", \ - "SWAT", \ - "SWEL", \ - "XAAQ", \ - "XCON", \ - "XGRP", \ - "XWEL", \ - "ZGRP", \ - "ZWEL", \ - "ENDLGR", \ - "LGR", \ - "LGRHEADD", \ - "LGRHEADI", \ - "LGRHEADQ", \ - "LGRNAMES", \ - "EOWC" , \ - "IOWC" , \ - "OWC" , \ - "ZNODE" , \ - "INODE" , \ - "RNODE" , \ - "LGWEL" , \ - "IBRAN" , \ - "INOBR" , \ - "RBRAN" , \ - "PRESROCC", \ - "REGDIMS" , \ - "THRESHPR"} - - - -/* - The string added at the beginning and end of string which should be - replaced with the template parser. -*/ - -#define DEFAULT_START_TAG "<" -#define DEFAULT_END_TAG ">" - -#define DEFAULT_MANUAL_URL "http://ert.nr.no/ert/index.php/User_Manual" -#define DEFAULT_BROWSER "firefox" - -/*****************************************************************/ - -#define DEFAULT_VAR_DIR "/tmp/ert/var/run/ert" - -/*****************************************************************/ -/* file system spesific defaults. */ - -/** - Name of the default case. -*/ - -#define CASE_LOG "case-log" -#define CURRENT_CASE "current" -#define DEFAULT_CASE "default" -#define CURRENT_CASE_FILE "current_case" - -#define DEFAULT_PLAIN_NODE_PARAMETER_PATH "tstep/%04d/mem%03d/Parameter" -#define DEFAULT_PLAIN_NODE_STATIC_PATH "tstep/%04d/mem%03d/Static" -#define DEFAULT_PLAIN_NODE_DYNAMIC_FORECAST_PATH "tstep/%04d/mem%03d/Forecast" -#define DEFAULT_PLAIN_NODE_DYNAMIC_ANALYZED_PATH "tstep/%04d/mem%03d/Analyzed" -#define DEFAULT_PLAIN_NODE_INDEX_PATH "tstep/%04d/mem%03d/Index" - -#define DEFAULT_PLAIN_VECTOR_PARAMETER_PATH "vectors/mem%03d/Parameter" -#define DEFAULT_PLAIN_VECTOR_STATIC_PATH "vectors/mem%03d/Static" -#define DEFAULT_PLAIN_VECTOR_DYNAMIC_FORECAST_PATH "vectors/mem%03d/Forecast" -#define DEFAULT_PLAIN_VECTOR_DYNAMIC_ANALYZED_PATH "vectors/mem%03d/Analyzed" -#define DEFAULT_PLAIN_VECTOR_INDEX_PATH "vectors/mem%03d/Index" - - -#define DEFAULT_CASE_PATH "%s/files" // mountpoint -#define DEFAULT_CASE_MEMBER_PATH "%s/mem%03d/files" // mountpoint/member -#define DEFAULT_CASE_TSTEP_PATH "%s/%04d/files" // mountpoint/tstep -#define DEFAULT_CASE_TSTEP_MEMBER_PATH "%s/%04d/mem%03d/files" // mountpoint/tstep/member -// mountpoint = ENSPATH/case - - - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_fs.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_fs.h deleted file mode 100644 index 1dbe607810..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_fs.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_fs.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_FS_H -#define ERT_ENKF_FS_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - const char * enkf_fs_get_mount_point( const enkf_fs_type * fs ); - const char * enkf_fs_get_root_path( const enkf_fs_type * fs ); - const char * enkf_fs_get_case_name( const enkf_fs_type * fs ); - bool enkf_fs_is_read_only(const enkf_fs_type * fs); - void enkf_fs_fsync( enkf_fs_type * fs ); - void enkf_fs_add_index_node(enkf_fs_type * , int , int , const char * , enkf_var_type, ert_impl_type); - - enkf_fs_type * enkf_fs_get_ref( enkf_fs_type * fs ); - int enkf_fs_decref( enkf_fs_type * fs ); - int enkf_fs_incref( enkf_fs_type * fs ); - int enkf_fs_get_refcount( const enkf_fs_type * fs ); - enkf_fs_type * enkf_fs_mount( const char * path ); - bool enkf_fs_update_disk_version(const char * mount_point , int src_version , int target_version); - int enkf_fs_disk_version(const char * mount_point ); - int enkf_fs_get_version104( const char * path ); - void enkf_fs_fwrite_node(enkf_fs_type * enkf_fs , buffer_type * buffer , const char * node_key, enkf_var_type var_type, - int report_step , int iens); - - void enkf_fs_fwrite_vector(enkf_fs_type * enkf_fs , - buffer_type * buffer , - const char * node_key, - enkf_var_type var_type, - int iens); - - bool enkf_fs_exists( const char * mount_point ); - - void enkf_fs_fread_node(enkf_fs_type * enkf_fs , buffer_type * buffer , - const char * node_key , enkf_var_type var_type , - int report_step , int iens); - - void enkf_fs_fread_vector(enkf_fs_type * enkf_fs , buffer_type * buffer , - const char * node_key , - enkf_var_type var_type , - int iens); - - - bool enkf_fs_has_vector(enkf_fs_type * enkf_fs , const char * node_key , enkf_var_type var_type , int iens); - bool enkf_fs_has_node(enkf_fs_type * enkf_fs , const char * node_key , enkf_var_type var_type , int report_step , int iens); - - void enkf_fs_debug_fprintf( const enkf_fs_type * fs); - - enkf_fs_type * enkf_fs_create_fs( const char * mount_point , fs_driver_impl driver_id , void * arg, bool mount); - - char * enkf_fs_alloc_case_filename( const enkf_fs_type * fs , const char * input_name); - char * enkf_fs_alloc_case_member_filename( const enkf_fs_type * fs , int iens , const char * input_name); - char * enkf_fs_alloc_case_tstep_filename( const enkf_fs_type * fs , int tstep , const char * input_name); - char * enkf_fs_alloc_case_tstep_member_filename( const enkf_fs_type * fs , int tstep , int iens , const char * input_name); - - FILE * enkf_fs_open_case_tstep_member_file( const enkf_fs_type * fs , const char * input_name , int tstep , int iens , const char * mode); - FILE * enkf_fs_open_case_file( const enkf_fs_type * fs , const char * input_name , const char * mode); - FILE * enkf_fs_open_case_tstep_file( const enkf_fs_type * fs , const char * input_name , int tstep , const char * mode); - FILE * enkf_fs_open_case_member_file( const enkf_fs_type * fs , const char * input_name , int iens , const char * mode); - - FILE * enkf_fs_open_excase_tstep_member_file( const enkf_fs_type * fs , const char * input_name , int tstep , int iens); - FILE * enkf_fs_open_excase_file( const enkf_fs_type * fs , const char * input_name); - FILE * enkf_fs_open_excase_tstep_file( const enkf_fs_type * fs , const char * input_name , int tstep ); - FILE * enkf_fs_open_excase_member_file( const enkf_fs_type * fs , const char * input_name , int iens ); - - time_map_type * enkf_fs_alloc_readonly_time_map( const char * mount_point ); - state_map_type * enkf_fs_alloc_readonly_state_map( const char * mount_point ); - summary_key_set_type * enkf_fs_alloc_readonly_summary_key_set( const char * mount_point ); - state_map_type * enkf_fs_get_state_map( const enkf_fs_type * fs ); - time_map_type * enkf_fs_get_time_map( const enkf_fs_type * fs ); - cases_config_type * enkf_fs_get_cases_config( const enkf_fs_type * fs); - misfit_ensemble_type * enkf_fs_get_misfit_ensemble( const enkf_fs_type * fs ); - summary_key_set_type * enkf_fs_get_summary_key_set( const enkf_fs_type * fs ); - custom_kw_config_set_type * enkf_fs_get_custom_kw_config_set( const enkf_fs_type * fs ); - - void enkf_fs_increase_write_count(enkf_fs_type * fs); - void enkf_fs_decrease_write_count(enkf_fs_type * fs); - int enkf_fs_get_write_count(const enkf_fs_type * fs); - - - UTIL_SAFE_CAST_HEADER( enkf_fs ); - UTIL_IS_INSTANCE_HEADER( enkf_fs ); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_fs_type.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_fs_type.h deleted file mode 100644 index 1192ad60ea..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_fs_type.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_fs_type.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_FS_TYPES_H -#define ERT_ENKF_FS_TYPES_H -typedef struct enkf_fs_struct enkf_fs_type; -#endif - diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_macros.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_macros.h deleted file mode 100644 index 8a7103279a..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_macros.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_macros.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_MACROS_H -#define ERT_ENKF_MACROS_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - - - - - -/*****************************************************************/ - -#define VOID_CONFIG_FREE(prefix) void prefix ## _config_free__(void *void_arg) { prefix ## _config_free((prefix ## _config_type *) void_arg); } -#define VOID_CONFIG_FREE_HEADER(prefix) void prefix ## _config_free__(void *); - -/*****************************************************************/ - -#define GET_DATA_SIZE(prefix) int prefix ## _config_get_data_size (const prefix ## _config_type *arg) { return arg->data_size; } -#define GET_DATA_SIZE_HEADER(prefix) int prefix ## _config_get_data_size (const prefix ## _config_type *arg); - -#define VOID_GET_DATA_SIZE(prefix) int prefix ## _config_get_data_size__ (const void * arg) {\ - const prefix ## _config_type * config = prefix ## _config_safe_cast_const( arg ); \ - return prefix ## _config_get_data_size( config ); \ -} -#define VOID_GET_DATA_SIZE_HEADER(prefix) int prefix ## _config_get_data_size__ (const void * arg); - -/*****************************************************************/ - - - -#define VOID_ALLOC(prefix) \ -void * prefix ## _alloc__(const void *void_config) { \ - const prefix ## _config_type * config = prefix ## _config_safe_cast_const( void_config ); \ - return prefix ## _alloc(config); \ -} - -#define VOID_ALLOC_HEADER(prefix) void * prefix ## _alloc__(const void *); - -/*****************************************************************/ - -#define VOID_HAS_DATA(prefix) \ - bool prefix ##_has_data__(const void * void_arg , int report_step) { \ - const prefix ## _type * arg = prefix ## _safe_cast_const( void_arg ); \ - return prefix ## _has_data(arg , report_step); \ -} - -#define VOID_HAS_DATA_HEADER(prefix) bool prefix ##_has_data__(const void * , int); - -/*****************************************************************/ -#define VOID_WRITE_TO_BUFFER(prefix) \ - bool prefix ## _write_to_buffer__(const void * void_arg , buffer_type * buffer , int report_step) { \ - const prefix ## _type * arg = prefix ## _safe_cast_const( void_arg ); \ - return prefix ## _write_to_buffer(arg , buffer , report_step); \ -} - - -#define VOID_READ_FROM_BUFFER(prefix) \ - void prefix ## _read_from_buffer__(void * void_arg , buffer_type * buffer , enkf_fs_type * fs, int report_step) { \ - prefix ## _type * arg = prefix ## _safe_cast( void_arg ); \ - prefix ## _read_from_buffer(arg , buffer , fs, report_step); \ -} - -#define VOID_WRITE_TO_BUFFER_HEADER(prefix) bool prefix ## _write_to_buffer__(const void * , buffer_type * , int); -#define VOID_READ_FROM_BUFFER_HEADER(prefix) void prefix ## _read_from_buffer__(void * , buffer_type * , enkf_fs_type * , int); - -#define VOID_FLOAD(prefix) \ -bool prefix ## _fload__(void * void_arg , const char * filename) { \ - prefix ## _type * arg = prefix ## _safe_cast( void_arg ); \ - return prefix ## _fload(arg , filename); \ -} -#define VOID_FLOAD_HEADER(prefix) bool prefix ## _fload__(void * , const char * ); - - -/*****************************************************************/ - -#define VOID_ECL_WRITE(prefix) \ -void prefix ## _ecl_write__(const void * void_arg , const char * path , const char * file , void * filestream) { \ - const prefix ## _type * arg = prefix ## _safe_cast_const( void_arg ); \ - prefix ## _ecl_write(arg , path , file , filestream); \ -} - -#define VOID_ECL_WRITE_HEADER(prefix) void prefix ## _ecl_write__(const void * , const char * , const char * , void *); - -/*****************************************************************/ - -#define VOID_FORWARD_LOAD(prefix) \ -bool prefix ## _forward_load__(void * void_arg , const char * ecl_file , const forward_load_context_type * load_context) { \ - prefix ## _type * arg = prefix ## _safe_cast( void_arg ); \ - return prefix ## _forward_load(arg , ecl_file , load_context); \ -} - -#define VOID_FORWARD_LOAD_HEADER(prefix) bool prefix ## _forward_load__(void * , const char * , const forward_load_context_type * load_context); - - /*****************************************************************/ - -#define VOID_FORWARD_LOAD_VECTOR(prefix) \ - bool prefix ## _forward_load_vector__(void * void_arg , const char * ecl_file , const forward_load_context_type * load_context, const int_vector_type * time_index) { \ - prefix ## _type * arg = prefix ## _safe_cast( void_arg ); \ - return prefix ## _forward_load_vector(arg , ecl_file ,load_context , time_index); \ -} - -#define VOID_FORWARD_LOAD_VECTOR_HEADER(prefix) bool prefix ## _forward_load_vector__(void * , const char * , const forward_load_context_type * load_context, const int_vector_type * time_index); - - -/*****************************************************************/ - -#define VOID_FREE(prefix) \ -void prefix ## _free__(void * void_arg) { \ - prefix ## _type * arg = prefix ## _safe_cast( void_arg ); \ - prefix ## _free( arg ); \ -} - -#define VOID_FREE_HEADER(prefix) void prefix ## _free__(void * ); - - -/*****************************************************************/ - -#define VOID_USER_GET(prefix) \ -bool prefix ## _user_get__(void * void_arg , const char * key , int report_step , double * value) { \ - prefix ## _type * arg = prefix ## _safe_cast( void_arg ); \ - return prefix ## _user_get(arg , key , report_step, value); \ -} - -#define VOID_USER_GET_HEADER(prefix) bool prefix ## _user_get__(void * , const char * , int, double *); - - -/*****************************************************************/ - -#define VOID_USER_GET_VECTOR(prefix) \ -void prefix ## _user_get_vector__(void * void_arg , const char * key , double_vector_type * value) { \ - prefix ## _type * arg = prefix ## _safe_cast( void_arg ); \ - prefix ## _user_get_vector(arg , key , value); \ -} - -#define VOID_USER_GET_VECTOR_HEADER(prefix) void prefix ## _user_get_vector__(void * , const char * , double_vector_type *); - -/*****************************************************************/ - -#define VOID_USER_GET_OBS(prefix) \ -void prefix ## _user_get__(void * void_arg , const char * key , double * value, double * std, bool * valid) { \ - prefix ## _user_get((prefix ## _type *) void_arg , key , value , std , valid); \ -} - -#define VOID_USER_GET_OBS_HEADER(prefix) void prefix ## _user_get__(void * , const char * , double * , double * , bool *); - - -/*****************************************************************/ - -#define VOID_FREE_DATA(prefix) \ -void prefix ## _free_data__(void * void_arg) { \ - prefix ## _type * arg = prefix ## _safe_cast( void_arg ); \ - prefix ## _free_data( arg ); \ -} - -#define VOID_FREE_DATA_HEADER(prefix) void prefix ## _free_data__(void * ); - -/*****************************************************************/ - -#define VOID_COPY(prefix) \ -void prefix ## _copy__(const void * void_src, void * void_target) { \ - const prefix ## _type * src = prefix ## _safe_cast_const( void_src ); \ - prefix ## _type * target = prefix ## _safe_cast( void_target ); \ - prefix ## _copy( src , target ); \ -} -#define VOID_COPY_HEADER(prefix) void prefix ## _copy__(const void * , void * ); - -/*****************************************************************/ - - -#define CONFIG_GET_ECL_KW_NAME(prefix) const char * prefix ## _config_get_ecl_kw_name(const prefix ## _config_type * config) { return config->ecl_kw_name; } -#define CONFIG_GET_ECL_KW_NAME_HEADER(prefix) const char * prefix ## _config_get_ecl_kw_name(const prefix ## _config_type * ) - - -/*****************************************************************/ - -#define VOID_SERIALIZE(prefix) \ - void prefix ## _serialize__(const void *void_arg, node_id_type node_id , const active_list_type * active_list , matrix_type * A , int row_offset , int column) { \ - const prefix ## _type *arg = prefix ## _safe_cast_const( void_arg ); \ - prefix ## _serialize (arg , node_id , active_list , A , row_offset , column); \ -} -#define VOID_SERIALIZE_HEADER(prefix) void prefix ## _serialize__(const void * , node_id_type , const active_list_type * , matrix_type * , int , int); - - -#define VOID_DESERIALIZE(prefix) \ - void prefix ## _deserialize__(void *void_arg, node_id_type node_id , const active_list_type * active_list , const matrix_type * A , int row_offset , int column) { \ - prefix ## _type *arg = prefix ## _safe_cast( void_arg ); \ - prefix ## _deserialize (arg , node_id , active_list , A , row_offset , column); \ -} -#define VOID_DESERIALIZE_HEADER(prefix) void prefix ## _deserialize__(void * , node_id_type , const active_list_type * , const matrix_type * , int , int); - - - - -/*****************************************************************/ - -#define VOID_INITIALIZE(prefix) \ - bool prefix ## _initialize__(void *void_arg, int iens , const char * init_file, rng_type * rng) { \ - prefix ## _type *arg = prefix ## _safe_cast(void_arg); \ - return prefix ## _initialize (arg , iens , init_file , rng); \ -} -#define VOID_INITIALIZE_HEADER(prefix) bool prefix ## _initialize__(void *, int , const char * , rng_type * ); - -/*****************************************************************/ - -#define VOID_SET_INFLATION(prefix) \ -void prefix ## _set_inflation__( void * void_inflation , const void * void_std , const void * void_min_std) { \ - prefix ## _set_inflation( prefix ## _safe_cast( void_inflation ) , prefix ## _safe_cast_const( void_std ) , prefix ## _safe_cast_const( void_min_std )); \ -} -#define VOID_SET_INFLATION_HEADER(prefix) void prefix ## _set_inflation__( void * void_inflation , const void * void_std , const void * void_min_std ); - - -/*****************************************************************/ - -#define VOID_GET_OBS(prefix) \ -void prefix ## _get_observations__(const void * void_arg , obs_data_type * obs_data, enkf_fs_type * fs, int report_step , const active_list_type * __active_list) { \ - prefix ## _get_observations((prefix ## _type *) void_arg , obs_data , fs, report_step , __active_list); \ -} - -#define VOID_GET_OBS_HEADER(prefix) void prefix ## _get_observations__(const void * , obs_data_type * , enkf_fs_type *, int , const active_list_type * ) - -/*****************************************************************/ - -#define VOID_MEASURE(obs_prefix, state_prefix) \ -void obs_prefix ## _measure__(const void * void_obs , const void * void_state , node_id_type node_id , meas_data_type * meas_data , const active_list_type * __active_list) { \ - const obs_prefix ## _type * obs = obs_prefix ## _safe_cast_const( void_obs ); \ - const state_prefix ## _type * state = state_prefix ## _safe_cast_const( void_state ); \ - obs_prefix ## _measure(obs , state , node_id , meas_data , __active_list); \ -} - -#define VOID_MEASURE_UNSAFE(obs_prefix, state_prefix) \ -void obs_prefix ## _measure__(const void * void_obs , const void * state , node_id_type node_id , meas_data_type * meas_data , const active_list_type * __active_list) { \ - const obs_prefix ## _type * obs = obs_prefix ## _safe_cast_const( void_obs ); \ - obs_prefix ## _measure(obs , state , node_id , meas_data , __active_list); \ -} - - -#define VOID_MEASURE_HEADER(obs_prefix) void obs_prefix ## _measure__(const void * , const void * , node_id_type , meas_data_type * , const active_list_type *) - -/*****************************************************************/ - -#define VOID_UPDATE_STD_SCALE(prefix)\ -void prefix ## _update_std_scale__( void * void_obs , double std_multiplier , const active_list_type * active_list) { \ - prefix ## _type * obs = prefix ## _safe_cast( void_obs ); \ - prefix ## _update_std_scale( obs , std_multiplier , active_list ); \ -} - -#define VOID_UPDATE_STD_SCALE_HEADER(prefix) void prefix ## _update_std_scale__(void * void_obs , double std_multiplier , const active_list_type * active_list); - -/*****************************************************************/ - -#define VOID_CHI2(obs_prefix, state_prefix) \ - double obs_prefix ## _chi2__(const void * void_obs , const void * void_state, node_id_type node_id) { \ - const obs_prefix ## _type * obs = obs_prefix ## _safe_cast_const( void_obs ); \ - return obs_prefix ## _chi2(obs , void_state , node_id); \ -} - -#define VOID_CHI2_HEADER(obs_prefix) double obs_prefix ## _chi2__(const void * , const void *, node_id_type); - - -/*****************************************************************/ - -#define VOID_TRUNCATE(prefix) void prefix ## _truncate__(void * void_arg) { prefix ## _truncate( (prefix ## _type *) void_arg); } -#define VOID_TRUNCATE_HEADER(prefix) void prefix ## _truncate__(void * ) - -/*****************************************************************/ -#define VOID_SCALE(prefix) void prefix ## _scale__(void * void_arg , double scale_factor) { prefix ## _scale( prefix ## _safe_cast( void_arg ) , scale_factor ); } -#define VOID_SCALE_HEADER(prefix) void prefix ## _scale__(void * , double ); - -/*****************************************************************/ - -#define VOID_CLEAR(prefix) void prefix ## _clear__(void * void_arg) { prefix ## _clear( prefix ## _safe_cast( void_arg )); } -#define VOID_CLEAR_HEADER(prefix) void prefix ## _clear__(void * ) - -/*****************************************************************/ - - -#define VOID_ISQRT(prefix) void prefix ## _isqrt__(void * void_arg) { prefix ## _isqrt( prefix ## _safe_cast( void_arg )); } -#define VOID_ISQRT_HEADER(prefix) void prefix ## _isqrt__(void * ) - -/*****************************************************************/ - -#define VOID_IADD(prefix) void prefix ## _iadd__( void * void_arg , const void * void_delta ) { \ - prefix ## _iadd( prefix ## _safe_cast( void_arg ) , prefix ## _safe_cast_const( void_delta ) ); \ -} - -#define VOID_IADD_HEADER(prefix) void prefix ## _iadd__( void * void_arg , const void * void_delta ); - -/*****************************************************************/ - -#define VOID_IMUL(prefix) void prefix ## _imul__( void * void_arg , const void * void_delta ) { \ - prefix ## _imul( prefix ## _safe_cast( void_arg ) , prefix ## _safe_cast_const( void_delta ) ); \ -} - -#define VOID_IMUL_HEADER(prefix) void prefix ## _imul__( void * void_arg , const void * void_delta ); - -/*****************************************************************/ - -#define VOID_IADDSQR(prefix) void prefix ## _iaddsqr__( void * void_arg , const void * void_delta ) { \ - prefix ## _iaddsqr( prefix ## _safe_cast( void_arg ) , prefix ## _safe_cast_const( void_delta ) ); \ -} - -#define VOID_IADDSQR_HEADER(prefix) void prefix ## _iaddsqr__( void * void_arg , const void * void_delta ); - -/*****************************************************************/ - -#define CONFIG_GET_ENSFILE(prefix) const char * prefix ## _config_get_ensfile_ref(const prefix ## _config_type * config) { return config->ensfile; } -#define CONFIG_GET_ECLFILE(prefix) const char * prefix ## _config_get_eclfile_ref(const prefix ## _config_type * config) { return config->eclfile; } -#define CONFIG_GET_ENSFILE_HEADER(prefix) const char * prefix ## _config_get_ensfile_ref(const prefix ## _config_type * ) -#define CONFIG_GET_ECLFILE_HEADER(prefix) const char * prefix ## _config_get_eclfile_ref(const prefix ## _config_type * ) - -/*****************************************************************/ - -#define VOID_IGET(prefix) double prefix ## _iget__(const void * void_arg, int index) { return prefix ## _iget((const prefix ## _type *) void_arg , index); } -#define VOID_IGET_HEADER(prefix) double prefix ## _iget__(const void * , int ) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main.h deleted file mode 100644 index df01172709..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main.h +++ /dev/null @@ -1,327 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_main.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_MAIN_H -#define ERT_ENKF_MAIN_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - /*****************************************************************/ - - typedef struct enkf_main_struct enkf_main_type; - ui_return_type * enkf_main_set_eclbase( enkf_main_type * enkf_main , const char * eclbase_fmt); - ui_return_type * enkf_main_set_data_file( enkf_main_type * enkf_main , const char * data_file ); - void enkf_main_set_user_config_file( enkf_main_type * enkf_main , const char * user_config_file ); - const char * enkf_main_get_user_config_file( const enkf_main_type * enkf_main ); - void enkf_main_set_rft_config_file( enkf_main_type * enkf_main , const char * rft_config_file ); - const char * enkf_main_get_rft_config_file( const enkf_main_type * enkf_main ); - bool enkf_main_get_pre_clear_runpath( const enkf_main_type * enkf_main ); - void enkf_main_set_pre_clear_runpath( enkf_main_type * enkf_main , bool pre_clear_runpath); - bool enkf_main_set_refcase( enkf_main_type * enkf_main , const char * refcase_path); - ui_return_type * enkf_main_validata_refcase( const enkf_main_type * enkf_main , const char * refcase_path); - - ert_templates_type * enkf_main_get_templates( enkf_main_type * enkf_main ); - void enkf_main_set_log_file( enkf_main_type * enkf_main , const char * log_file ); - const char * enkf_main_get_log_file( const enkf_main_type * enkf_main ); - void enkf_main_set_log_level( enkf_main_type * enkf_main , int log_level ); - int enkf_main_get_log_level( const enkf_main_type * enkf_main ); - - member_config_type * enkf_main_iget_member_config(const enkf_main_type * enkf_main , int iens); - void enkf_main_del_unused_static(enkf_main_type * , int ); - const char * enkf_main_get_data_file(const enkf_main_type * ); - const char ** enkf_main_get_well_list_ref(const enkf_main_type * , int *); - - - bool enkf_main_get_endian_swap(const enkf_main_type * ); - bool enkf_main_get_fmt_file(const enkf_main_type * ); - bool enkf_main_has_key(const enkf_main_type * , const char *); - void enkf_main_add_gen_kw(enkf_main_type * , const char * ); - void enkf_main_add_type(enkf_main_type * , const char * , enkf_var_type , ert_impl_type , const char * , const void *); - void enkf_main_add_type0(enkf_main_type * , const char * , int , enkf_var_type , ert_impl_type ); - void enkf_main_add_well(enkf_main_type * , const char * , int , const char ** ); - void enkf_main_analysis(enkf_main_type * ); - void enkf_main_free(enkf_main_type * ); - void enkf_main_exit(enkf_main_type * enkf_main); - void enkf_main_init_eclipse(enkf_main_type * , int , int ); - void enkf_main_init_run( enkf_main_type * enkf_main, const ert_run_context_type * run_context , init_mode_type init_mode); - void enkf_main_load_ecl_init_mt(enkf_main_type * enkf_main , int ); - void enkf_main_load_ecl_complete_mt(enkf_main_type *); - void enkf_main_iload_ecl_mt(enkf_main_type *enkf_main , int ); - - bool enkf_main_UPDATE(enkf_main_type * enkf_main , const int_vector_type * step_list, enkf_fs_type * source_fs, enkf_fs_type * target_fs , int target_step , run_mode_type run_mode); - bool enkf_main_smoother_update(enkf_main_type * enkf_main , enkf_fs_type * source_fs, enkf_fs_type * target_fs); - void enkf_main_create_run_path(enkf_main_type * enkf_main , const bool_vector_type * iactive , int iter); - int enkf_main_run_simple_step( enkf_main_type* enkf_main, bool_vector_type* iactive, init_mode_type init_mode, int iter ); - - void enkf_main_run_tui_exp(enkf_main_type * enkf_main , - bool_vector_type * iactive); - - - void enkf_main_run_smoother(enkf_main_type * enkf_main , enkf_fs_type * source_fs, const char * target_fs_name , bool_vector_type * iactive , int iter , bool rerun); - void enkf_main_run_iterated_ES(enkf_main_type * enkf_main, int num_iterations); - void enkf_main_set_data_kw(enkf_main_type * , const char * , const char *); - void enkf_main_set_state_run_path(const enkf_main_type * , int ); - void enkf_main_set_state_eclbase(const enkf_main_type * , int ); - void enkf_main_interactive_set_runpath__(void * ); - enkf_main_type * enkf_main_bootstrap(const char * model_config, bool strict, bool verbose); - void enkf_main_create_new_config( const char * config_file , const char * storage_path , const char * dbase_type , int num_realizations); - - enkf_node_type ** enkf_main_get_node_ensemble(const enkf_main_type * enkf_main , enkf_fs_type * src_fs , const char * key , int report_step); - void enkf_main_node_mean( const enkf_node_type ** ensemble , int ens_size , enkf_node_type * mean ); - void enkf_main_node_std( const enkf_node_type ** ensemble , int ens_size , const enkf_node_type * mean , enkf_node_type * std); - - ert_impl_type enkf_main_impl_type(const enkf_main_type *, const char * ); - enkf_state_type * enkf_main_iget_state(const enkf_main_type * , int ); - enkf_state_type ** enkf_main_get_ensemble( enkf_main_type * enkf_main); - const enkf_state_type ** enkf_main_get_ensemble_const( const enkf_main_type * enkf_main); - - const enkf_config_node_type * enkf_main_get_config_node(const enkf_main_type * , const char *); - const sched_file_type * enkf_main_get_sched_file(const enkf_main_type *); - ranking_table_type * enkf_main_get_ranking_table( const enkf_main_type * enkf_main ); - ecl_config_type * enkf_main_get_ecl_config(const enkf_main_type * enkf_main); - ensemble_config_type * enkf_main_get_ensemble_config(const enkf_main_type * enkf_main); - int enkf_main_get_ensemble_size( const enkf_main_type * enkf_main ); - int enkf_main_get_history_length( const enkf_main_type * ); - bool enkf_main_has_prediction( const enkf_main_type * ); - //const enkf_sched_type * enkf_main_get_enkf_sched(const enkf_main_type *); - model_config_type * enkf_main_get_model_config( const enkf_main_type * ); - local_config_type * enkf_main_get_local_config( const enkf_main_type * enkf_main ); - config_settings_type * enkf_main_get_plot_config( const enkf_main_type * enkf_main ); - void enkf_main_load_obs( enkf_main_type * enkf_main , const char * obs_config_file , bool clear_existing); - enkf_obs_type * enkf_main_get_obs(const enkf_main_type * ); - bool enkf_main_have_obs( const enkf_main_type * enkf_main ); - analysis_config_type * enkf_main_get_analysis_config(const enkf_main_type * ); - - void * enkf_main_get_enkf_config_node_type(const ensemble_config_type *, const char *); - void enkf_main_set_field_config_iactive(const ensemble_config_type *, int); - const char * enkf_main_get_image_viewer(const enkf_main_type * ); - const char * enkf_main_get_plot_driver(const enkf_main_type * enkf_main ); - const char * enkf_main_get_image_type(const enkf_main_type * enkf_main); - - - - - void enkf_main_list_users( set_type * users , const char * executable ); - const ext_joblist_type * enkf_main_get_installed_jobs( const enkf_main_type * enkf_main ); - - subst_list_type * enkf_main_get_data_kw( const enkf_main_type * enkf_main ); - void enkf_main_clear_data_kw( enkf_main_type * enkf_main ); - site_config_type * enkf_main_get_site_config( const enkf_main_type * enkf_main ); - void enkf_main_resize_ensemble( enkf_main_type * enkf_main , int new_ens_size ); - void enkf_main_get_observations( const enkf_main_type * enkf_main, const char * user_key , int obs_count , time_t * obs_time , double * y , double * std); - int enkf_main_get_observation_count( const enkf_main_type * enkf_main, const char * user_key ); - - keep_runpath_type enkf_main_iget_keep_runpath( const enkf_main_type * enkf_main , int iens ); - void enkf_main_iset_keep_runpath( enkf_main_type * enkf_main , int iens , keep_runpath_type keep_runpath); - - /*****************************************************************/ - void enkf_main_install_SIGNALS(void); - const char * enkf_main_get_SVN_VERSION( void ); - const char * enkf_main_get_COMPILE_TIME( void ); - void enkf_main_del_node(enkf_main_type * enkf_main , const char * key); - void enkf_main_add_node(enkf_main_type * enkf_main, enkf_config_node_type * enkf_config_node); - void enkf_main_update_node( enkf_main_type * enkf_main , const char * key ); - int_vector_type * enkf_main_update_alloc_step_list( const enkf_main_type * enkf_main , int load_start , int step2 , int stride); - - hook_manager_type * enkf_main_get_hook_manager( const enkf_main_type * enkf_main ); - - void enkf_main_get_PC( const matrix_type * S, - const matrix_type * dObs, - double truncation , - int ncomp , - matrix_type * PC , - matrix_type * PC_obs, - double_vector_type * singular_values); - - - void enkf_main_fprintf_PC(const char * filename , - matrix_type * PC , - matrix_type * PC_obs); - - - void enkf_main_set_verbose( enkf_main_type * enkf_main , bool verbose); - bool enkf_main_get_verbose( const enkf_main_type * enkf_main ); - - ert_workflow_list_type * enkf_main_get_workflow_list( enkf_main_type * enkf_main ); - void enkf_main_run_workflows( enkf_main_type * enkf_main , const stringlist_type * workflows); - bool enkf_main_run_workflow( enkf_main_type * enkf_main , const char * workflow); - - enkf_main_type * enkf_main_alloc_empty( ); - - rng_config_type * enkf_main_get_rng_config( const enkf_main_type * enkf_main ); - void enkf_main_rng_init( enkf_main_type * enkf_main); - - bool enkf_main_export_field(const enkf_main_type * enkf_main, - const char * kw, - const char * path, - bool_vector_type * iactive, - field_file_format_type file_type, - int report_step); - - bool enkf_main_export_field_with_fs(const enkf_main_type * enkf_main, - const char * kw, - const char * path, - bool_vector_type * iactive, - field_file_format_type file_type, - int report_step, - enkf_fs_type * fs); - - - int enkf_main_load_from_forward_model_with_fs(enkf_main_type * enkf_main, int iter , bool_vector_type * iactive, stringlist_type ** realizations_msg_list, enkf_fs_type * fs); - int enkf_main_load_from_forward_model(enkf_main_type * enkf_main, int iter , bool_vector_type * iactive, stringlist_type ** realizations_msg_list); - int enkf_main_load_from_forward_model_from_gui(enkf_main_type * enkf_main, int iter , bool_vector_type * iactive, enkf_fs_type * fs); - - void enkf_main_rank_on_observations(enkf_main_type * enkf_main, - const char * ranking_key, - const stringlist_type * obs_ranking_keys, - const int_vector_type * steps); - - - - void enkf_main_rank_on_data(enkf_main_type * enkf_main, - const char * ranking_key, - const char * data_key, - bool sort_increasing, - int step); - - - void enkf_main_export_ranking(enkf_main_type * enkf_main, const char * ranking_key, const char * ranking_file); - - - - - - - - /********* File System / Case Management ********** - Implementation: enkf_main_manage_fs.c */ - - - bool enkf_main_case_is_current(const enkf_main_type * enkf_main , const char * case_path); - char * enkf_main_read_alloc_current_case_name(const enkf_main_type * enkf_main); - stringlist_type * enkf_main_alloc_caselist( const enkf_main_type * enkf_main ); - void enkf_main_set_case_table( enkf_main_type * enkf_main , const char * case_table_file ); - - void enkf_main_initialize_from_scratch(enkf_main_type * enkf_main , - enkf_fs_type * init_fs, - const stringlist_type * param_list , - const bool_vector_type * iens_mask , - init_mode_type init_mode); - - void enkf_main_init_current_case_from_existing(enkf_main_type * enkf_main, - enkf_fs_type * source_case_fs, - int source_report_step); - - void enkf_main_init_current_case_from_existing_custom(enkf_main_type * enkf_main, - enkf_fs_type * source_case_fs, - int source_report_step, - stringlist_type * node_list, - bool_vector_type * iactive); - - - void enkf_main_init_case_from_existing(const enkf_main_type * enkf_main, - enkf_fs_type * source_case_fs, - int source_report_step, - enkf_fs_type * target_case); - - void enkf_main_init_case_from_existing_custom(const enkf_main_type * enkf_main, - enkf_fs_type * source_case_fs, - int source_report_step, - enkf_fs_type * target_case, - stringlist_type * node_list, - bool_vector_type * iactive); - - bool enkf_main_case_is_initialized( const enkf_main_type * enkf_main , - const char * case_name , - bool_vector_type * __mask); - - bool enkf_main_is_initialized( const enkf_main_type * enkf_main ,bool_vector_type * __mask); - - char * enkf_main_alloc_mount_point( const enkf_main_type * enkf_main , const char * case_path); - enkf_fs_type * enkf_main_get_fs(const enkf_main_type * ); - enkf_fs_type * enkf_main_tui_get_fs(const enkf_main_type * ); - enkf_fs_type * enkf_main_job_get_fs(const enkf_main_type * ); - enkf_fs_type * enkf_main_get_fs_ref(const enkf_main_type * enkf_main); - const char * enkf_main_get_current_fs( const enkf_main_type * enkf_main ); - enkf_fs_type * enkf_main_mount_alt_fs(const enkf_main_type * enkf_main , const char * case_path , bool create); - void enkf_main_set_fs( enkf_main_type * enkf_main , enkf_fs_type * fs , const char * case_path ); - void enkf_main_user_select_fs(enkf_main_type * enkf_main , const char * case_path ); - void enkf_main_select_fs( enkf_main_type * enkf_main , const char * case_path ); - bool enkf_main_fs_exists(const enkf_main_type * enkf_main, const char * input_case); - const char * enkf_main_get_mount_root( const enkf_main_type * enkf_main); - - - state_map_type * enkf_main_alloc_readonly_state_map( const enkf_main_type * enkf_main , const char * case_path); - time_map_type * enkf_main_alloc_readonly_time_map( const enkf_main_type * enkf_main , const char * case_path ); - - runpath_list_type * enkf_main_get_runpath_list( const enkf_main_type * enkf_main ); - ert_run_context_type * enkf_main_alloc_ert_run_context_ENSEMBLE_EXPERIMENT(const enkf_main_type * enkf_main , enkf_fs_type * fs , bool_vector_type * iactive , int iter); - ert_init_context_type * enkf_main_alloc_ert_init_context(const enkf_main_type * enkf_main , enkf_fs_type * fs, const bool_vector_type * iactive , init_mode_type init_mode , int iter); - - -UTIL_SAFE_CAST_HEADER(enkf_main); -UTIL_IS_INSTANCE_HEADER(enkf_main); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main_jobs.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main_jobs.h deleted file mode 100644 index b57353ca4e..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main_jobs.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_main_jobs.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ENKF_MAIN_JOBS_H -#define ENKF_MAIN_JOBS_H - -#ifdef __cplusplus -extern "C" { -#endif - - -void * enkf_main_select_case_JOB( void * self , const stringlist_type * args); -void * enkf_main_create_case_JOB( void * self , const stringlist_type * args); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main_update.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main_update.h deleted file mode 100644 index e7e3e9d919..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_main_update.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_main_update.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_MAIN_UPDATE -#define ERT_ENKF_MAIN_UPDATE - -#include - -void enkf_main_update(enkf_main_type * enkf_main , int step1 , int step2); - - - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_node.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_node.h deleted file mode 100644 index e1d52b207b..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_node.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_node.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_NODE_H -#define ERT_ENKF_NODE_H -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/**********************************/ - - - typedef void (serialize_ftype) (const void * , node_id_type , const active_list_type * , matrix_type * , int , int); - typedef void (deserialize_ftype) ( void * , node_id_type , const active_list_type * , const matrix_type * , int , int); - - - - - typedef void (ecl_write_ftype) (const void * , /* Node object */ - const char * , /* Directory to write to. */ - const char * , /* Filename - can be NULL. */ - void * ); /* fortio or FILE inistance for writing elements in restart files. */ - - typedef bool (fload_ftype) ( void * , const char *); - typedef void (read_from_buffer_ftype) ( void * , buffer_type * , enkf_fs_type * , int); - typedef bool (write_to_buffer_ftype) (const void * , buffer_type * , int); - typedef bool (has_data_ftype) (const void * , int); - - - typedef void (set_inflation_ftype) (void * , - const void * , /* Node object with the ensemble standard deviation. */ - const void * ); /* Node object with the minimum standard deviation - supplied by the user. */ - - - typedef void (user_get_vector_ftype) (void * , const char * , double_vector_type *); - typedef bool (user_get_ftype) (void * , const char * , int , double *); - typedef void * (alloc_ftype) (const void *); - typedef bool (initialize_ftype) ( void * , int , const char * , rng_type * ); - typedef bool (forward_load_ftype) (void * , const char * , const forward_load_context_type *); - typedef bool (forward_load_vector_ftype) (void * , const char * , const forward_load_context_type *, const int_vector_type *); - typedef void (realloc_data_ftype) (void * ); - typedef void (free_data_ftype) (void * ); - typedef void (node_free_ftype) ( void *); - typedef void (clear_ftype) ( void *); - typedef void (node_copy_ftype) (const void * , void *); - typedef void (isqrt_ftype) ( void *); - typedef void (scale_ftype) ( void * , double); - typedef void (iadd_ftype) ( void * , const void *); - typedef void (imul_ftype) ( void * , const void *); - typedef void (iaddsqr_ftype) ( void * , const void *); - typedef void (ensemble_mulX_vector_ftype) ( void * , int , const void ** , const double *); - - - typedef enum {alloc_func = 0, - ecl_write_func = 1, - forward_load_func = 2, - fread_func = 3, - fwrite_func = 4, - copy_func = 5, - initialize_func = 6, - free_func = 7, - free_data_func = 8, - clear_serial_state_func = 9, - serialize = 10, - deserialize = 11} node_function_type; - - - typedef void (enkf_node_ftype1) (enkf_node_type *); - typedef void (enkf_node_ftype_NEW) (enkf_node_type * , arg_pack_type * ); - - - bool enkf_node_user_get_vector( enkf_node_type * enkf_node , enkf_fs_type * fs , const char * key , int iens , double_vector_type * values); - bool enkf_node_user_get_no_id(enkf_node_type * enkf_node , enkf_fs_type * fs , const char * key , int report_step, int iens, double * value); - bool enkf_node_user_get(enkf_node_type * , enkf_fs_type * , const char * , node_id_type , double * ); - enkf_node_type * enkf_node_deep_alloc(const enkf_config_node_type * config); - enkf_node_type * enkf_node_alloc(const enkf_config_node_type *); - enkf_node_type * enkf_node_copyc(const enkf_node_type * ); - /* - The enkf_node_free() function declaration is in the enkf_config_node.h header, - because the enkf_config_node needs to know how to free the min_std node. - - void enkf_node_free(enkf_node_type *enkf_node); - */ - - bool enkf_node_forward_init(enkf_node_type * enkf_node , const char * run_path , int iens); - bool enkf_node_has_data( enkf_node_type * enkf_node , enkf_fs_type * fs , node_id_type node_id); - //void enkf_node_free_data(enkf_node_type * ); - void enkf_node_free__(void *); - void enkf_initialize(enkf_node_type * , int); - bool enkf_node_include_type(const enkf_node_type * , int ); - void * enkf_node_value_ptr(const enkf_node_type * ); - ert_impl_type enkf_node_get_impl_type(const enkf_node_type * ); - enkf_var_type enkf_node_get_var_type(const enkf_node_type * ); - bool enkf_node_use_forward_init( const enkf_node_type * enkf_node ); - void enkf_node_clear_serial_state(enkf_node_type * ); - void enkf_node_serialize(enkf_node_type * enkf_node , enkf_fs_type * fs , node_id_type node_id , const active_list_type * active_list , matrix_type * A , int row_offset , int column); - void enkf_node_deserialize(enkf_node_type *enkf_node , enkf_fs_type * fs , node_id_type node_id , const active_list_type * active_list , const matrix_type * A , int row_offset , int column); - - bool enkf_node_forward_load_vector(enkf_node_type *enkf_node , const forward_load_context_type * load_context , const int_vector_type * time_index); - bool enkf_node_forward_load (enkf_node_type *, const forward_load_context_type * load_context); - void enkf_node_ecl_write (const enkf_node_type *, const char * , void * , int); - bool enkf_node_initialize(enkf_node_type *enkf_node , int , rng_type * ); - void enkf_node_printf(const enkf_node_type *); - bool enkf_node_fwrite (enkf_node_type * , FILE * stream, bool , int , int); - void enkf_node_clear (enkf_node_type *); - void enkf_node_fread (enkf_node_type * , FILE * stream , int , int); - - void enkf_node_copy_ensemble(const enkf_config_node_type * config_node , - enkf_fs_type * src_case, - enkf_fs_type * target_case , - int report_step_from, /* src state */ - int report_step_to , /* target state */ - int ens_size, - const perm_vector_type * permutations); - - void enkf_node_copy(const enkf_config_node_type * config_node , - enkf_fs_type * src_case , - enkf_fs_type * target_case , - node_id_type src_id , - node_id_type target_id ); - enkf_node_type ** enkf_node_load_alloc_ensemble( const enkf_config_node_type * config_node , enkf_fs_type * fs , - int report_step , int iens1 , int iens2 ); - enkf_node_type * enkf_node_load_alloc( const enkf_config_node_type * config_node , enkf_fs_type * fs , node_id_type node_id); - bool enkf_node_fload( enkf_node_type * enkf_node , const char * filename ); - void enkf_node_load(enkf_node_type * enkf_node , enkf_fs_type * fs , node_id_type node_id ); - void enkf_node_load_vector( enkf_node_type * enkf_node , enkf_fs_type * fs , int iens); - bool enkf_node_store(enkf_node_type * enkf_node , enkf_fs_type * fs , bool force_vectors , node_id_type node_id); - bool enkf_node_store_vector(enkf_node_type *enkf_node , enkf_fs_type * fs , int iens ); - bool enkf_node_try_load(enkf_node_type *enkf_node , enkf_fs_type * fs , node_id_type node_id); - bool enkf_node_try_load_vector(enkf_node_type *enkf_node , enkf_fs_type * fs , int iens ); - bool enkf_node_exists( enkf_node_type *enkf_node , enkf_fs_type * fs , int report_step , int iens); - bool enkf_node_vector_storage( const enkf_node_type * node ); - enkf_node_type * enkf_node_alloc_shared_container(const enkf_config_node_type * config, hash_type * node_hash); - enkf_node_type * enkf_node_alloc_private_container(const enkf_config_node_type * config); -/*****************************************************************/ -/* Function callbacks */ -ecl_write_ftype * enkf_node_get_func_pointer( const enkf_node_type * node ); - - - -void enkf_node_set_inflation( enkf_node_type * inflation , const enkf_node_type * std , const enkf_node_type * min_std); -void enkf_node_sqrt(enkf_node_type *enkf_node); -void enkf_node_scale(enkf_node_type * , double ); -void enkf_node_iadd(enkf_node_type * , const enkf_node_type * ); -void enkf_node_iaddsqr(enkf_node_type * , const enkf_node_type * ); -void enkf_node_imul(enkf_node_type * , const enkf_node_type * ); -const enkf_config_node_type * enkf_node_get_config(const enkf_node_type * ); -const char * enkf_config_node_get_infile(const enkf_config_node_type * ); -const char * enkf_node_get_key(const enkf_node_type * ); -const char * enkf_node_get_swapfile(const enkf_node_type *); -bool enkf_node_has_func(const enkf_node_type * , node_function_type ); -bool enkf_node_internalize(const enkf_node_type * , int ); - -void enkf_node_upgrade_file_103( const char * path , const char * file , ert_impl_type impl_type , int perc_complete , msg_type * msg); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_obs.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_obs.h deleted file mode 100644 index fd23a65269..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_obs.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_obs.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_OBS_H -#define ERT_ENKF_OBS_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - bool enkf_obs_have_obs( const enkf_obs_type * enkf_obs ); - enkf_obs_type * enkf_obs_alloc( const history_type * history , - time_map_type * external_time_map , - const ecl_grid_type * grid , - const ecl_sum_type * refcase, - ensemble_config_type * ensemble_config ); - - void enkf_obs_free( enkf_obs_type * enkf_obs); - - obs_vector_type * enkf_obs_iget_vector(const enkf_obs_type * obs, int index); - obs_vector_type * enkf_obs_get_vector(const enkf_obs_type * , const char * ); - void enkf_obs_add_obs_vector(enkf_obs_type * enkf_obs, - const obs_vector_type * vector); - - bool enkf_obs_load(enkf_obs_type * enkf_obs, - const char * config_file, - double std_cutoff); - void enkf_obs_clear( enkf_obs_type * enkf_obs ); - - void enkf_obs_get_obs_and_measure_node( const enkf_obs_type * enkf_obs, - enkf_fs_type * fs, - const local_obsdata_node_type * obs_node , - const int_vector_type * ens_active_list , - meas_data_type * meas_data, - obs_data_type * obs_data); - - - void enkf_obs_get_obs_and_measure_data(const enkf_obs_type * enkf_obs, - enkf_fs_type * fs, - const local_obsdata_type * local_obsdata , - const int_vector_type * ens_active_list , - meas_data_type * meas_data, - obs_data_type * obs_data); - - - stringlist_type * enkf_obs_alloc_typed_keylist( enkf_obs_type * enkf_obs , obs_impl_type ); - hash_type * enkf_obs_alloc_data_map(enkf_obs_type * enkf_obs); - - const obs_vector_type * enkf_obs_user_get_vector(const enkf_obs_type * obs , const char * full_key, char ** index_key ); - bool enkf_obs_has_key(const enkf_obs_type * , const char * ); - int enkf_obs_get_size( const enkf_obs_type * obs ); - - hash_iter_type * enkf_obs_alloc_iter( const enkf_obs_type * enkf_obs ); - - stringlist_type * enkf_obs_alloc_keylist(enkf_obs_type * enkf_obs ); - stringlist_type * enkf_obs_alloc_matching_keylist(const enkf_obs_type * enkf_obs , const char * input_string); - time_t enkf_obs_iget_obs_time(const enkf_obs_type * enkf_obs , int report_step); - void enkf_obs_scale_std(enkf_obs_type * enkf_obs, double scale_factor); - void enkf_obs_local_scale_std( const enkf_obs_type * enkf_obs , const local_obsdata_type * local_obsdata, double scale_factor); - void enkf_obs_add_local_nodes_with_data(const enkf_obs_type * enkf_obs , local_obsdata_type * local_obs , enkf_fs_type *fs , const bool_vector_type * ens_mask); - double enkf_obs_scale_correlated_std(const enkf_obs_type * enkf_obs , enkf_fs_type * fs , const int_vector_type * ens_active_list , const local_obsdata_type * local_obsdata); - local_obsdata_type * enkf_obs_alloc_all_active_local_obs( const enkf_obs_type * enkf_obs , const char * key); - - UTIL_IS_INSTANCE_HEADER( enkf_obs ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_data.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_data.h deleted file mode 100644 index d1e619a1b9..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_data.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'enkf_plot_data.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_ENKF_PLOT_DATA_H -#define ERT_ENKF_PLOT_DATA_H - -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include - -#include -#include -#include -#include - - typedef struct enkf_plot_data_struct enkf_plot_data_type; - - enkf_plot_data_type * enkf_plot_data_alloc( const enkf_config_node_type * config_node ); - void enkf_plot_data_free( enkf_plot_data_type * plot_data ); - void enkf_plot_data_load( enkf_plot_data_type * plot_data , - enkf_fs_type * fs , - const char * user_key , - const bool_vector_type * input_mask); - int enkf_plot_data_get_size( const enkf_plot_data_type * plot_data ); - enkf_plot_tvector_type * enkf_plot_data_iget( const enkf_plot_data_type * plot_data , int index); - - UTIL_IS_INSTANCE_HEADER( enkf_plot_data ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gen_kw.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gen_kw.h deleted file mode 100644 index 6819d0464e..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gen_kw.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_gen_kw.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_ENKF_PLOT_GEN_KW_H -#define ERT_ENKF_PLOT_GEN_KW_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include -#include - - typedef struct enkf_plot_gen_kw_struct enkf_plot_gen_kw_type; - - enkf_plot_gen_kw_type * enkf_plot_gen_kw_alloc( const enkf_config_node_type * enkf_config_node); - void enkf_plot_gen_kw_free( enkf_plot_gen_kw_type * gen_kw ); - int enkf_plot_gen_kw_get_size( const enkf_plot_gen_kw_type * gen_kw ); - enkf_plot_gen_kw_vector_type * enkf_plot_gen_kw_iget( const enkf_plot_gen_kw_type * vector , int index); - void enkf_plot_gen_kw_load( enkf_plot_gen_kw_type * gen_kw , - enkf_fs_type * fs , - bool transform_data , - int report_step , - const bool_vector_type * input_mask); - - const char * enkf_plot_gen_kw_iget_key( const enkf_plot_gen_kw_type * plot_gen_kw, int index); - int enkf_plot_gen_kw_get_keyword_count( const enkf_plot_gen_kw_type * gen_kw ); - bool enkf_plot_gen_kw_should_use_log_scale(const enkf_plot_gen_kw_type * gen_kw , int index); - - UTIL_IS_INSTANCE_HEADER( enkf_plot_gen_kw ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gen_kw_vector.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gen_kw_vector.h deleted file mode 100644 index 8e659306e0..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gen_kw_vector.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_gen_kw.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_ENKF_PLOT_GEN_KW_VECTOR_H -#define ERT_ENKF_PLOT_GEN_KW_VECTOR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - - typedef struct enkf_plot_gen_kw_vector_struct enkf_plot_gen_kw_vector_type; - - enkf_plot_gen_kw_vector_type * enkf_plot_gen_kw_vector_alloc( const enkf_config_node_type * config_node , int iens ); - void enkf_plot_gen_kw_vector_free( enkf_plot_gen_kw_vector_type * vector ); - int enkf_plot_gen_kw_vector_get_size( const enkf_plot_gen_kw_vector_type * vector ); - void enkf_plot_gen_kw_vector_reset( enkf_plot_gen_kw_vector_type * vector ); - void enkf_plot_gen_kw_vector_load( enkf_plot_gen_kw_vector_type * vector , enkf_fs_type * fs , bool transform_data , int report_step ); - void * enkf_plot_gen_kw_vector_load__( void * arg ); - double enkf_plot_gen_kw_vector_iget( const enkf_plot_gen_kw_vector_type * vector , int index); - - UTIL_IS_INSTANCE_HEADER( enkf_plot_gen_kw_vector ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gendata.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gendata.h deleted file mode 100644 index d2a4ecd16a..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_gendata.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_gendata.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_PLOT_GENDATA_H -#define ERT_ENKF_PLOT_GENDATA_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include -#include -#include - - - -typedef struct enkf_plot_gendata_struct enkf_plot_gendata_type; - -enkf_plot_gendata_type * enkf_plot_gendata_alloc( const enkf_config_node_type * enkf_config_node); -enkf_plot_gendata_type * enkf_plot_gendata_alloc_from_obs_vector( const obs_vector_type * obs_vector ); -void enkf_plot_gendata_free( enkf_plot_gendata_type * data ); -int enkf_plot_gendata_get_size( const enkf_plot_gendata_type * data ); -enkf_plot_genvector_type * enkf_plot_gendata_iget( const enkf_plot_gendata_type * plot_data , int index); -void enkf_plot_gendata_load( enkf_plot_gendata_type * plot_data , - enkf_fs_type * fs , - int report_step , - const bool_vector_type * input_mask); - -double_vector_type * enkf_plot_gendata_get_min_values(enkf_plot_gendata_type * plot_data); -double_vector_type * enkf_plot_gendata_get_max_values(enkf_plot_gendata_type * plot_data); - - -UTIL_IS_INSTANCE_HEADER( enkf_plot_gendata ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_genvector.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_genvector.h deleted file mode 100644 index 0cf27d665c..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_genvector.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_genvector.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_PLOT_GENVECTOR_H -#define ERT_ENKF_PLOT_GENVECTOR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -typedef struct enkf_plot_genvector_struct enkf_plot_genvector_type; - -enkf_plot_genvector_type * enkf_plot_genvector_alloc( const enkf_config_node_type * enkf_config_node , int iens); -void enkf_plot_genvector_free( enkf_plot_genvector_type * vector ); -int enkf_plot_genvector_get_size( const enkf_plot_genvector_type * vector ); -void enkf_plot_genvector_reset( enkf_plot_genvector_type * vector ); - void * enkf_plot_genvector_load__( void * arg ); -double enkf_plot_genvector_iget( const enkf_plot_genvector_type * vector , int index); - -UTIL_IS_INSTANCE_HEADER( enkf_plot_genvector ); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_tvector.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_tvector.h deleted file mode 100644 index c23f1ddf7a..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_plot_tvector.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'enkf_plot_tvector.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_ENKF_PLOT_TVECTOR_H -#define ERT_ENKF_PLOT_TVECTOR_H - -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -#include - -#include -#include -#include - - typedef struct enkf_plot_tvector_struct enkf_plot_tvector_type; - - UTIL_SAFE_CAST_HEADER( enkf_plot_tvector ); - UTIL_IS_INSTANCE_HEADER( enkf_plot_tvector ); - - - - void enkf_plot_tvector_reset( enkf_plot_tvector_type * plot_tvector ); - enkf_plot_tvector_type * enkf_plot_tvector_alloc( const enkf_config_node_type * config_node , int iens); - void enkf_plot_tvector_load( enkf_plot_tvector_type * plot_tvector , enkf_fs_type * fs , const char * user_key ); - void * enkf_plot_tvector_load__( void * arg ); - void enkf_plot_tvector_free( enkf_plot_tvector_type * plot_tvector ); - void enkf_plot_tvector_iset( enkf_plot_tvector_type * plot_tvector , int index , time_t time , double value); - - int enkf_plot_tvector_size( const enkf_plot_tvector_type * plot_tvector ); - double enkf_plot_tvector_iget_value( const enkf_plot_tvector_type * plot_tvector , int index); - time_t enkf_plot_tvector_iget_time( const enkf_plot_tvector_type * plot_tvector , int index); - bool enkf_plot_tvector_iget_active( const enkf_plot_tvector_type * plot_tvector , int index); - bool enkf_plot_tvector_all_active( const enkf_plot_tvector_type * plot_tvector ); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_serialize.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_serialize.h deleted file mode 100644 index 5db999ac9a..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_serialize.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_serialize.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_SERIALIZE_H -#define ERT_ENKF_SERIALIZE_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -#include - -#include - - - - -void enkf_matrix_serialize(const void * __node_data , - int node_size , - ecl_type_enum node_type , - const active_list_type * __active_list , - matrix_type * A, - int row_offset, - int column); - - -void enkf_matrix_deserialize(void * __node_data , - int node_size , - ecl_type_enum node_type , - const active_list_type * __active_list , - const matrix_type * A, - int row_offset, - int column); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_state.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_state.h deleted file mode 100644 index 2f67e700ba..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_state.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_state.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_STATE_H -#define ERT_ENKF_STATE_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include -#include -#include -#include - - -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct enkf_state_struct enkf_state_type; - - bool enkf_state_get_pre_clear_runpath( const enkf_state_type * enkf_state ); - void enkf_state_set_pre_clear_runpath( enkf_state_type * enkf_state , bool pre_clear_runpath ); - - keep_runpath_type enkf_state_get_keep_runpath( const enkf_state_type * enkf_state ); - void enkf_state_set_keep_runpath( enkf_state_type * enkf_state , keep_runpath_type keep_runpath); - keep_runpath_type member_config_get_keep_runpath(const member_config_type * member_config); - //void * enkf_state_complete_forward_model__(void * arg ); - void * enkf_state_load_from_forward_model_mt( void * arg ); - void enkf_state_initialize(enkf_state_type * enkf_state , enkf_fs_type * fs, const stringlist_type * param_list , init_mode_type init_mode); - void enkf_state_fread(enkf_state_type * , enkf_fs_type * fs , int , int ); - void enkf_state_swapout_node(const enkf_state_type * , const char *); - void enkf_state_swapin_node(const enkf_state_type * , const char *); - void enkf_state_iset_eclpath(enkf_state_type * , int , const char *); - enkf_node_type * enkf_state_get_node(const enkf_state_type * , const char * ); - bool enkf_state_has_node(const enkf_state_type * enkf_state , const char * node_key); - void enkf_state_del_node(enkf_state_type * , const char * ); - void enkf_state_load_ecl_summary(enkf_state_type * , bool , int ); - void * enkf_state_run_eclipse__(void * ); - void * enkf_state_start_forward_model__(void * ); - - int enkf_state_load_from_forward_model(enkf_state_type * enkf_state , - run_arg_type * run_arg , - stringlist_type * msg_list); - - int enkf_state_forward_init(enkf_state_type * enkf_state , - run_arg_type * run_arg); - - void enkf_state_init_eclipse(enkf_state_type *enkf_state, const run_arg_type * run_arg ); - - enkf_state_type * enkf_state_alloc(int , - rng_type * main_rng , - const char * casename , - bool pre_clear_runpath, - keep_runpath_type , - model_config_type * , - ensemble_config_type * , - const site_config_type * , - const ecl_config_type * , - ert_templates_type * templates, - subst_list_type * parent_subst); - void enkf_state_update_node( enkf_state_type * enkf_state , const char * node_key ); - void enkf_state_update_jobname( enkf_state_type * enkf_state ); - void enkf_state_update_eclbase( enkf_state_type * enkf_state ); - void enkf_state_add_node(enkf_state_type * , const char * , const enkf_config_node_type * ); - enkf_node_type * enkf_state_get_or_create_node(enkf_state_type * enkf_state, const enkf_config_node_type * config_node); - void enkf_state_load_ecl_restart(enkf_state_type * , bool , int ); - void enkf_state_sample(enkf_state_type * , int); - void enkf_state_fwrite(const enkf_state_type * , enkf_fs_type * fs , int , int ); - void enkf_state_ens_read( enkf_state_type * , const char * , int); - void enkf_state_ecl_write(enkf_state_type *, const run_arg_type * run_arg , enkf_fs_type * fs); - void enkf_state_free(enkf_state_type * ); - void enkf_state_apply(enkf_state_type * , enkf_node_ftype1 * , int ); - void enkf_state_serialize(enkf_state_type * , size_t); - void enkf_state_set_iens(enkf_state_type * , int ); - int enkf_state_get_iens(const enkf_state_type * ); - member_config_type *enkf_state_get_member_config(const enkf_state_type * enkf_state); - const char * enkf_state_get_run_path(const enkf_state_type * ); - const char * enkf_state_get_eclbase( const enkf_state_type * enkf_state ); - void enkf_state_printf_subst_list(enkf_state_type * enkf_state , int step1 , int step2); - - rng_type * enkf_state_get_rng( const enkf_state_type * enkf_state ); - unsigned int enkf_state_get_random( enkf_state_type * enkf_state ); - run_status_type enkf_state_get_simple_run_status(const enkf_state_type * state); - void enkf_state_add_subst_kw(enkf_state_type * enkf_state , const char * kw , const char * value , const char * doc_string); - subst_list_type * enkf_state_get_subst_kw( enkf_state_type * enkf_state ); - const ensemble_config_type * enkf_state_get_ensemble_config( const enkf_state_type * enkf_state ); - -/******************************************************************/ -/* Forward model callbacks: */ - -bool enkf_state_complete_forward_modelOK__(void * arg ); -bool enkf_state_complete_forward_modelRETRY__(void * arg ); -bool enkf_state_complete_forward_modelEXIT__(void * arg ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_types.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_types.h deleted file mode 100644 index fdef2ec2a2..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_types.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_types.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_TYPES_H -#define ERT_ENKF_TYPES_H -#ifdef __cplusplus -extern "C" { -#endif - - - - - -/* - This enum signals the three different states a "cell" in - observation/data node can be in: - - ACTIVE: The cell is active and should be used/updated in EnKF - analysis. - - LOCAL_INACTIVE: The cell is not included in the current local - analysis ministep - - DEACTIVATED: The cell has been deactivated by the functionality - deactivating outliers. - -*/ - -typedef enum { ACTIVE = 1, - LOCAL_INACTIVE = 2, /* Not active in current local update scheme. */ - DEACTIVATED = 3, /* Deactivaed due to to small overlap, or... */ - MISSING = 4} active_type; /* Set as missing by the forward model. */ - - - -/* - The enkf_var_type enum defines logical groups of variables. All - variables in the same group, i.e. 'parameter' are typically treated - in the same manner. So the reason for creating this type is to be - able to say for instance: "Load all dynamic_state variables". - - Observe that these are used as bitmask's, i.e. the numerical values - must be a power of 2 series. -*/ - -typedef enum {INVALID_VAR = 0 , /* */ - PARAMETER = 1 , /* A parameter which is updated with enkf: PORO , MULTFLT , ..*/ - DYNAMIC_STATE = 2 , /* Dynamic data which are needed for a restart - i.e. pressure and saturations. */ - DYNAMIC_RESULT = 4 , /* Dynamic results which are NOT needed for a restart - i.e. well rates. */ - INDEX_STATE = 16 } /* Index data - enum value is used for storage classification */ -enkf_var_type; - - - -typedef enum { DEFAULT_KEEP = 0, /* Remove for enkf assimilation - keep for ensemble experiments. */ - EXPLICIT_DELETE = 1, /* Remove unconditionally */ - EXPLICIT_KEEP = 2} /* keep unconditionally */ -keep_runpath_type; - - - - - -/* - ert_impl_type are the actual node implementation types. Observe - that one ert_impl_type can be used in several ways as - enkf_var_type. For instance the pressure is implemented with a - field, and behaves as a dynamic_state variable, on the other hand - the permeability is also implemented as a field, but this is a - parameter. - - These correspond to implementation types. The numbers are on disk, - and should **NOT BE UPDATED**. The ERT_MIN_TYPE and MAX_TYPE - identifiers are needed for the block_fs_driver. -*/ - - - -typedef enum {INVALID = 0 , - IMPL_TYPE_OFFSET = 100 , - FIELD = 104 , /* WELL has been removed */ - GEN_KW = 107 , /* RELPERM has been removed & HAVANA_FAULT */ - CUSTOM_KW = 108 , - SUMMARY = 110 , /* TPGZONE has been removed */ - GEN_DATA = 113 , /* PILOT_POINT has been removed */ - SURFACE = 114 , - CONTAINER = 115 } ert_impl_type; - - - -/* - Should update the functions enkf_types_get_impl_name() and - enkf_types_get_impl_type__() when this enum is updated. - In addition to enkf_config_add_type(). -*/ - - - - - -typedef enum { REPORT_STEP_INCOMPATIBLE = 1, - LOAD_FAILURE = 2} enkf_fw_load_result_enum; - - - - - - - /** - These are 2^n bitmasks. - */ - -typedef enum { TRUNCATE_NONE = 0, - TRUNCATE_MIN = 1, - TRUNCATE_MAX = 2 } truncation_type; - - - - -/** - This enum is used to differentiate between different types of - run. The point is that depending on this mode we can be more or - less restrictive on the amount of input we require from the user. - - In mode enkf_assimlation ( which is the default ), we require quite - a lot of info, whereas in the case screening_experiment we require - less. - - screening_experiment: - - SIZE - - RUNPATH - - ECLBASE - - SCHEDULE_FILE - - DATA_FILE - - FORWARD_MODEL. - - ensemble_experiment: - - ENSPATH - - INIT_FILE (or estimation of EQUIL) - - enkf_assmilation: - - RESULT_PATH - -*/ - -typedef enum { //ENKF_ASSIMILATION = 1, - ENSEMBLE_EXPERIMENT = 2, - SMOOTHER_UPDATE = 4 , - INIT_ONLY = 8 } run_mode_type; - - -#define ENKF_RUN_ENUM_DEFS {.value = 1 , .name = "ENKF_ASSIMILATION"}, \ - {.value = 2 , .name = "ENSEMBLE_EXPERIMENT"} - -#define ENKF_RUN_ENUM_SIZE 2 - - - -/** - This enum enumerates the different types of inflation which should - be used. Observe that the actual variable used is not en enum - instance, but rather an ordinary integer which is in general a sum - of of the values listed in this enum. -*/ - - - typedef enum { NO_INFLATION = 0, - SCALAR_INFLATION = 1, - LOCAL_INFLATION = 2} inflation_mode_type; - - - - typedef enum { JOB_NOT_STARTED = 0, - JOB_SUBMITTED = 1, // This implies that it has been submitted to the internal queue system; we don't know if it is actually running or not. - JOB_RUN_FAILURE = 2, - JOB_LOAD_FAILURE = 3, - JOB_RUN_OK = 4 } run_status_type; - - -/*****************************************************************/ - -/** - This enum is used when we are setting up the dependencies between - observations and variables. The modes all_active and inactive are - sufficient information, for the values partly active we need - additional information. - - The same type is used both for variables (PRESSURE/PORO/MULTZ/...) - and for observations. -*/ - -typedef enum { - ALL_ACTIVE = 1, /* The variable/observation is fully active, i.e. all cells/all faults/all .. */ - INACTIVE = 2, /* Fully inactive */ - PARTLY_ACTIVE = 3 /* Partly active - must supply additonal type spesific information on what is active.*/ -} active_mode_type; - - - typedef struct { - int report_step; - int iens; - } node_id_type; - - - -/*****************************************************************/ -/* Possible transitions: */ - typedef enum { - STATE_UNDEFINED = 1, - STATE_INITIALIZED = 2, - STATE_HAS_DATA = 4, - STATE_LOAD_FAILURE = 8, - STATE_PARENT_FAILURE = 16 - } realisation_state_enum; - - - typedef enum { - INIT_NONE = 0, - INIT_CONDITIONAL = 1, - INIT_FORCE = 2 - } init_mode_type; - - - -typedef struct enkf_obs_struct enkf_obs_type; - - - - -const char * enkf_types_get_var_name(enkf_var_type var_type); -ert_impl_type enkf_types_get_impl_type(const char * ); -const char * enkf_types_get_impl_name(ert_impl_type ); -ert_impl_type enkf_types_check_impl_type(const char * ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_util.h b/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_util.h deleted file mode 100644 index 32130b5436..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/enkf_util.h +++ /dev/null @@ -1,349 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_util.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENKF_UTIL_H -#define ERT_ENKF_UTIL_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include -#include - -#include -#include - -#include - -#include - -/*****************************************************************/ - -/** - These math functions assume that the underlying data implementation - is double or float - will NOT work for fields. -*/ - - - -#define SQR_FUNC(prefix) \ -void prefix ## _isqr(void * void_arg) { \ -prefix ## _type *arg = (prefix ## _type *) void_arg;\ -const int data_size = prefix ## _config_get_data_size(arg->config); \ -int i; \ -for (i=0; i < data_size; i++) \ - arg->data[i] = arg->data[i]*arg->data[i]; \ -} -#define SQR_FUNC_VOID_HEADER(prefix) void prefix ## _isqr(void * ) -#define SQR_FUNC_HEADER(prefix) void prefix ## _isqr(prefix ## _type *) -#define SQR_FUNC_SCALAR(prefix) void prefix ## _isqr(void * void_arg) { scalar_isqr(((prefix ## _type *) void_arg)->scalar); } - - -/*****************************************************************/ - -#define SQRT_FUNC(prefix) \ -void prefix ## _isqrt(void * void_arg) { \ -prefix ## _type *arg = (prefix ## _type *) void_arg;\ -const int data_size = prefix ## _config_get_data_size(arg->config); \ -int i; \ -for (i=0; i < data_size; i++) \ - arg->data[i] = sqrt(arg->data[i]); \ -} -#define SQRT_FUNC_VOID_HEADER(prefix) void prefix ## _isqrt(void * ) -#define SQRT_FUNC_HEADER(prefix) void prefix ## _isqrt(prefix ## _type* ) -#define SQRT_FUNC_SCALAR(prefix) void prefix ## _isqrt(void * void_arg) { scalar_isqrt(((prefix ## _type *) void_arg)->scalar); } - - -/*****************************************************************/ - -#define SCALE_FUNC(prefix) \ -void prefix ## _iscale(void *void_arg , double scale_factor) { \ -prefix ## _type *arg = (prefix ## _type *) void_arg; \ -const int data_size = prefix ## _config_get_data_size(arg->config); \ -int i; \ -for (i=0; i < data_size; i++) \ - arg->data[i] *= scale_factor; \ -} -#define SCALE_FUNC_SCALAR(prefix) void prefix ## _iscale(void * void_arg, double scale_factor) { scalar_iscale(((prefix ## _type *) void_arg)->scalar , scale_factor); } -#define SCALE_FUNC_VOID_HEADER(prefix) void prefix ## _iscale(void * , double) -#define SCALE_FUNC_HEADER(prefix) void prefix ## _iscale(prefix ## _type * , double) - -/*****************************************************************/ - -#define RESET_FUNC(prefix) \ -void prefix ## _ireset(void *void_arg) { \ -prefix ## _type *arg = (prefix ## _type *) void_arg; \ -const int data_size = prefix ## _config_get_data_size(arg->config); \ -int i; \ -for (i=0; i < data_size; i++) \ - arg->data[i] = 0; \ -} -#define RESET_FUNC_SCALAR(prefix) void prefix ## _ireset(void * void_arg) { scalar_ireset(((prefix ## _type *) void_arg)->scalar); } -#define RESET_FUNC_VOID_HEADER(prefix) void prefix ## _ireset(void *) -#define RESET_FUNC_HEADER(prefix) void prefix ## _ireset(prefix ## _type *) - -/*****************************************************************/ - -#define ADD_FUNC(prefix) \ -void prefix ## _iadd(void *void_arg , const void *void_delta) { \ - prefix ## _type *arg = (prefix ## _type *) void_arg; \ -const prefix ## _type *delta = (const prefix ## _type *) void_delta; \ -const prefix ## _config_type *config = arg->config; \ -const int data_size = prefix ## _config_get_data_size(arg->config); \ -int i; \ -if (config != delta->config) { \ - fprintf(stderr,"%s:two object have different config objects - aborting \n",__func__);\ - abort(); \ -} \ -for (i=0; i < data_size; i++) \ - arg->data[i] += delta->data[i]; \ -} - -#define ADD_FUNC_SCALAR(prefix) void prefix ## _iadd(void *void_arg, const void * void_factor) { scalar_iadd( ((prefix ## _type *) void_arg)->scalar , (( const prefix ## _type *) void_factor)->scalar); } -#define ADD_FUNC_VOID_HEADER(prefix) void prefix ## _iadd(void * , const void *) -#define ADD_FUNC_HEADER(prefix) void prefix ## _iadd(prefix ## _type * , const prefix ## _type *) -/*****************************************************************/ - -#define MUL_ADD_FUNC(prefix) \ -void prefix ## _imul_add(void *void_arg , double scale_factor , const void *void_delta) { \ - prefix ## _type *arg = (prefix ## _type *) void_arg; \ -const prefix ## _type *delta = (const prefix ## _type *) void_delta; \ -const prefix ## _config_type *config = arg->config; \ -const int data_size = prefix ## _config_get_data_size(arg->config); \ -int i; \ -if (config != delta->config) { \ - fprintf(stderr,"%s:two object have different config objects - aborting \n",__func__);\ - abort(); \ -} \ -for (i=0; i < data_size; i++) \ - arg->data[i] += scale_factor * delta->data[i]; \ -} - -#define MUL_ADD_FUNC_SCALAR(prefix) void prefix ## _imul_add(void *void_arg, double scale_factor , const void * void_factor) { scalar_imul_add( ((prefix ## _type *) void_arg)->scalar , scale_factor , (( const prefix ## _type *) void_factor)->scalar); } -#define MUL_ADD_FUNC_VOID_HEADER(prefix) void prefix ## _imul_add(void * , double , const void *) -#define MUL_ADD_FUNC_HEADER(prefix) void prefix ## _imul_add(prefix ## _type* , double , const prefix ## _type *) - -/*****************************************************************/ - -#define SUB_FUNC(prefix) \ -void prefix ## _isub(void *void_arg , const void *void_diff) { \ - prefix ## _type *arg = (prefix ## _type *) void_arg; \ -const prefix ## _type *diff = (const prefix ## _type *) void_diff; \ -const prefix ## _config_type *config = arg->config; \ -const int data_size = prefix ## _config_get_data_size(arg->config); \ -int i; \ -if (config != diff->config) { \ - fprintf(stderr,"%s:two object have different config objects - aborting \n",__func__);\ - abort(); \ -} \ -for (i=0; i < data_size; i++) \ - arg->data[i] -= diff->data[i]; \ -} - -#define SUB_FUNC_SCALAR(prefix) void prefix ## _isub(void *void_arg, const void * void_factor) { scalar_isub( ((prefix ## _type *) void_arg)->scalar , (( const prefix ## _type *) void_factor)->scalar); } -#define SUB_FUNC_VOID_HEADER(prefix) void prefix ## _isub(void * , const void *) -#define SUB_FUNC_HEADER(prefix) void prefix ## _isub(prefix ## _type * , const prefix ## _type*) -/*****************************************************************/ - -#define MUL_FUNC(prefix) \ -void prefix ## _imul(void *void_arg , const void *void_factor) { \ - prefix ## _type *arg = (prefix ## _type *) void_arg; \ -const prefix ## _type *factor = (const prefix ## _type *) void_factor; \ -const prefix ## _config_type *config = arg->config; \ -const int data_size = prefix ## _config_get_data_size(arg->config); \ -int i; \ -if (config != factor->config) { \ - fprintf(stderr,"%s:two object have different config objects - aborting \n",__func__);\ - abort(); \ -} \ -for (i=0; i < data_size; i++) \ - arg->data[i] *= factor->data[i]; \ -} -#define MUL_FUNC_SCALAR(prefix) void prefix ## _imul(void *void_arg, const void * void_factor) { scalar_imul( ((prefix ## _type *) void_arg)->scalar , (( const prefix ## _type *) void_factor)->scalar); } -#define MUL_FUNC_VOID_HEADER(prefix) void prefix ## _imul(void * , const void *) -#define MUL_FUNC_HEADER(prefix) void prefix ## _imul(prefix ## _type * , const prefix ## _type*) - -/*****************************************************************/ - -#define ADDSQR_FUNC(prefix) \ -void prefix ## _iaddsqr(void *void_arg , const void *void_delta) { \ - prefix ## _type *arg = (prefix ## _type *) void_arg; \ -const prefix ## _type *delta = (const prefix ## _type *) void_delta; \ -const prefix ## _config_type *config = arg->config; \ -const int data_size = prefix ## _config_get_data_size(arg->config); \ -int i; \ -if (config != delta->config) { \ - fprintf(stderr,"%s:two object have different config objects - aborting \n",__func__);\ - abort(); \ -} \ -for (i=0; i < data_size; i++) \ - arg->data[i] += delta->data[i] * delta->data[i]; \ -} -#define ADDSQR_FUNC_SCALAR(prefix) void prefix ## _iaddsqr(void *void_arg, const void * void_factor) { scalar_iaddsqr( ((prefix ## _type *) void_arg)->scalar , (( const prefix ## _type *) void_factor)->scalar); } -#define ADDSQR_FUNC_VOID_HEADER(prefix) void prefix ## _iaddsqr(void * , const void *) -#define ADDSQR_FUNC_HEADER(prefix) void prefix ## _iaddsqr(prefix ## _type * , const prefix ## _type *) - - - -#define MATH_OPS(prefix) \ -SQR_FUNC (prefix) \ -SQRT_FUNC (prefix) \ -SCALE_FUNC (prefix) \ -ADD_FUNC (prefix) \ -ADDSQR_FUNC (prefix) \ -SUB_FUNC (prefix) \ -MUL_FUNC (prefix) \ -MUL_ADD_FUNC(prefix) - -#define MATH_OPS_SCALAR(prefix) \ -SQR_FUNC_SCALAR (prefix) \ -SQRT_FUNC_SCALAR (prefix) \ -SCALE_FUNC_SCALAR (prefix) \ -ADD_FUNC_SCALAR (prefix) \ -ADDSQR_FUNC_SCALAR (prefix) \ -SUB_FUNC_SCALAR (prefix) \ -MUL_FUNC_SCALAR (prefix) \ -MUL_ADD_FUNC_SCALAR(prefix) - - - -#define MATH_OPS_VOID_HEADER(prefix) \ -SQR_FUNC_VOID_HEADER (prefix); \ -SQRT_FUNC_VOID_HEADER (prefix); \ -SCALE_FUNC_VOID_HEADER (prefix); \ -ADD_FUNC_VOID_HEADER (prefix); \ -ADDSQR_FUNC_VOID_HEADER (prefix); \ -SUB_FUNC_VOID_HEADER (prefix); \ -MUL_FUNC_VOID_HEADER (prefix); \ -MUL_ADD_FUNC_VOID_HEADER(prefix) - -#define MATH_OPS_HEADER(prefix) \ -SQR_FUNC_HEADER (prefix); \ -SQRT_FUNC_HEADER (prefix); \ -SCALE_FUNC_HEADER (prefix); \ -ADD_FUNC_HEADER (prefix); \ -ADDSQR_FUNC_HEADER (prefix); \ -SUB_FUNC_HEADER (prefix); \ -MUL_FUNC_HEADER (prefix); \ -MUL_ADD_FUNC_HEADER(prefix) - -/*****************************************************************/ - -#define ENSEMBLE_MULX_VECTOR(prefix) \ -void prefix ## _ensemble_mulX_vector(prefix ## _type *new , int ens_size , const prefix ## _type ** prefix ## _ensemble , const double *X_vector) { \ - int iens; \ - prefix ## _clear(new); \ - for (iens=0; iens < ens_size; iens++) \ - prefix ## _imul_add(new , X_vector[iens] , prefix ## _ensemble[iens]);\ -} -#define ENSEMBLE_MULX_VECTOR_HEADER(prefix) void prefix ## _ensemble_mulX_vector(prefix ## _type *, int , const prefix ## _type ** , const double *); - - -#define ENSEMBLE_MULX_VECTOR_VOID(prefix) \ -void prefix ## _ensemble_mulX_vector__(void *new , int ens_size , const void ** prefix ## _ensemble , const double *X_vector) { \ - prefix ## _ensemble_mulX_vector((prefix ## _type *) new , ens_size , (const prefix ## _type **) prefix ## _ensemble , X_vector); \ -} - -#define ENSEMBLE_MULX_VECTOR_VOID_HEADER(prefix) void prefix ## _ensemble_mulX_vector__(void * , int , const void ** , const double *); - -/*****************************************************************/ - -#define ALLOC_STATS_SCALAR(prefix) \ -void prefix ## _alloc_stats(const prefix ## _type ** ensemble , int ens_size , prefix ## _type ** _mean , prefix ## _type ** _std) { \ - int iens; \ - prefix ## _type * mean = prefix ## _copyc(ensemble[0]); \ - prefix ## _type * std = prefix ## _copyc(ensemble[0]); \ - prefix ## _clear(mean); \ - prefix ## _clear(std); \ - for (iens = 0; iens < ens_size; iens++) { \ - prefix ## _output_transform(ensemble[iens]); \ - prefix ## _iadd(mean , ensemble[iens]); \ - prefix ## _iaddsqr(std , ensemble[iens]); \ - } \ - prefix ## _iscale(mean , 1.0 / ens_size); \ - prefix ## _iscale(std , 1.0 / ens_size); \ - { \ - prefix ## _type * tmp = prefix ## _copyc(mean); \ - prefix ## _isqr(tmp); \ - prefix ## _imul_add(std , -1.0 , tmp); \ - prefix ## _free(tmp); \ - } \ - prefix ## _isqrt(std); \ - *_mean = mean; \ - *_std = std; \ -} - - - - -#define ALLOC_STATS(prefix) \ -void prefix ## _alloc_stats(const prefix ## _type ** ensemble , int ens_size , prefix ## _type ** _mean , prefix ## _type ** _std) { \ - int iens; \ - prefix ## _type * mean = prefix ## _copyc(ensemble[0]); \ - prefix ## _type * std = prefix ## _copyc(ensemble[0]); \ - prefix ## _clear(mean); \ - prefix ## _clear(std); \ - for (iens = 0; iens < ens_size; iens++) { \ - prefix ## _iadd(mean , ensemble[iens]); \ - prefix ## _iaddsqr(std , ensemble[iens]); \ - } \ - prefix ## _iscale(mean , 1.0 / ens_size); \ - prefix ## _iscale(std , 1.0 / ens_size); \ - { \ - prefix ## _type * tmp = prefix ## _copyc(mean); \ - prefix ## _isqr(tmp); \ - prefix ## _imul_add(std , -1.0 , tmp); \ - prefix ## _free(tmp); \ - } \ - prefix ## _isqrt(std); \ - if (_mean != NULL) *_mean = mean; \ - if (_std != NULL) *_std = std; \ -} - - - -#define ALLOC_STATS_HEADER(prefix) void prefix ## _alloc_stats(const prefix ## _type ** , int , prefix ## _type ** , prefix ## _type ** ); -/*****************************************************************/ - - - -void enkf_util_truncate(void * , int , ecl_type_enum , void * , void *); -void enkf_util_rand_stdnormal_vector(int , double *, rng_type * rng); -double enkf_util_rand_normal(double , double , rng_type * rng); -void enkf_util_fwrite_target_type(FILE * , ert_impl_type); -void enkf_util_assert_buffer_type(buffer_type * buffer, ert_impl_type target_type); -void enkf_util_randperm( int * , int, rng_type * rng); - - //char * enkf_util_scanf_alloc_filename(const char * , int ); -void enkf_util_fprintf_data(const int * , const double ** , const char * , const char ** , int , int , const bool * , bool , FILE * stream); - -char * enkf_util_alloc_tagged_string(const char * ); -char * enkf_util_alloc_detagged_string( const char * tagged_string); -int enkf_util_compare_keys( const char * key1 , const char * key2 ); -int enkf_util_compare_keys__( const void * __key1 , const void * __key2 ); - -///* These #defines are used in the enkf_util_scanf_alloc_filename function. */ -//#define EXISTING_FILE 1 -//#define NEW_FILE 2 -//#define AUTO_MKDIR 4 - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/ensemble_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/ensemble_config.h deleted file mode 100644 index 332f0cac21..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/ensemble_config.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ensemble_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_ENSEMBLE_CONFIG_H -#define ERT_ENSEMBLE_CONFIG_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - - - -typedef struct ensemble_config_struct ensemble_config_type; - - void ensemble_config_set_refcase( ensemble_config_type * ensemble_config , const ecl_sum_type * refcase); - void ensemble_config_set_gen_kw_format( ensemble_config_type * ensemble_config , const char * gen_kw_format_string); - const char * ensemble_config_get_gen_kw_format( const ensemble_config_type * ensemble_config ); - enkf_config_node_type * ensemble_config_add_container( ensemble_config_type * ensemble_config , const char * key); - enkf_config_node_type * ensemble_config_add_surface( ensemble_config_type * ensemble_config , const char * key , bool forward_init); - - void ensemble_config_add_node( ensemble_config_type * ensemble_config , enkf_config_node_type * node); - enkf_config_node_type * ensemble_config_add_gen_data( ensemble_config_type * config , const char * key , bool dynamic , bool forward_init); - enkf_config_node_type * ensemble_config_add_summary(ensemble_config_type * ensemble_config , const char * key, load_fail_type load_fail); - enkf_config_node_type * ensemble_config_add_summary_observation(ensemble_config_type * ensemble_config , const char * key, load_fail_type load_fail); - enkf_config_node_type * ensemble_config_add_gen_kw( ensemble_config_type * config , const char * key , bool forward_init); - enkf_config_node_type * ensemble_config_add_custom_kw(ensemble_config_type * config, const char * key, const char * result_file, const char * output_file); - enkf_config_node_type * ensemble_config_add_defined_custom_kw(ensemble_config_type * config, const char * key, const hash_type * definition); - void ensemble_config_update_custom_kw_config(ensemble_config_type * config, custom_kw_config_set_type * config_set); - enkf_config_node_type * ensemble_config_add_field( ensemble_config_type * config , const char * key , ecl_grid_type * ecl_grid , bool forward_init); - int ensemble_config_get_observations( const ensemble_config_type * config , enkf_obs_type * enkf_obs , const char * user_key , int obs_count , - time_t * obs_time , double * y , double * std); - void ensemble_config_clear_obs_keys(ensemble_config_type * ensemble_config); - void ensemble_config_add_obs_key(ensemble_config_type * , const char * , const char * ); - const enkf_config_node_type * ensemble_config_user_get_node(const ensemble_config_type * , const char * , char **); - ert_impl_type ensemble_config_impl_type(const ensemble_config_type *, const char * ); - enkf_var_type ensemble_config_var_type(const ensemble_config_type *, const char * ); - void ensemble_config_init(ensemble_config_type * ensemble_config , const config_content_type * config , ecl_grid_type * grid , const ecl_sum_type * refcase); - void ensemble_config_free(ensemble_config_type * ); - bool ensemble_config_has_key(const ensemble_config_type * , const char * ); - bool ensemble_config_has_impl_type(const ensemble_config_type * config, const ert_impl_type impl_type); - bool ensemble_config_have_forward_init( const ensemble_config_type * ensemble_config ); - - void ensemble_config_del_node(ensemble_config_type * , const char * ); - void ensemble_config_add_config_items(config_parser_type * ); - - void ensemble_config_init_GEN_PARAM( ensemble_config_type * ensemble_config , const config_content_type * config ); - - enkf_config_node_type * ensemble_config_get_node(const ensemble_config_type * , const char * ); - enkf_config_node_type * ensemble_config_get_or_create_summary_node(ensemble_config_type * ensemble_config, const char * key); - stringlist_type * ensemble_config_alloc_keylist(const ensemble_config_type *); - stringlist_type * ensemble_config_alloc_keylist_from_var_type(const ensemble_config_type * , int var_mask); - stringlist_type * ensemble_config_alloc_keylist_from_impl_type(const ensemble_config_type *, ert_impl_type); - bool ensemble_config_iget_keep_runpath(const ensemble_config_type * , int ); - ensemble_config_type * ensemble_config_alloc( ); - void ensemble_config_fprintf_config( ensemble_config_type * ensemble_config , FILE * stream ); - const summary_key_matcher_type * ensemble_config_get_summary_key_matcher(const ensemble_config_type * ensemble_config); - int ensemble_config_get_size(const ensemble_config_type * ensemble_config ); - - - UTIL_IS_INSTANCE_HEADER( ensemble_config ); - UTIL_SAFE_CAST_HEADER( ensemble_config ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_init_context.h b/ThirdParty/Ert/libenkf/include/ert/enkf/ert_init_context.h deleted file mode 100644 index 3160782d91..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_init_context.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'ert_init_context.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_INIT_CONTEXT_H -#define ERT_INIT_CONTEXT_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#include -#include -#include - -typedef struct ert_init_context_struct ert_init_context_type; - - stringlist_type * ert_init_context_alloc_runpath_list(const bool_vector_type * iactive , path_fmt_type * runpath_fmt , subst_list_type * subst_list , int iter); - char * ert_init_context_alloc_runpath( int iens , path_fmt_type * runpath_fmt , subst_list_type * subst_list , int iter); - - ert_init_context_type * ert_init_context_alloc(enkf_fs_type * init_fs , const bool_vector_type * iactive , - path_fmt_type * runpath_fmt , - subst_list_type * subst_list , - init_mode_type init_mode , - int iter); - - void ert_init_context_free( ert_init_context_type * ); - int ert_init_context_get_size( const ert_init_context_type * context ); - init_mode_type ert_init_context_get_init_mode( const ert_init_context_type * context ); - bool_vector_type * ert_init_context_get_iactive( const ert_init_context_type * context ); - int ert_init_context_get_iter( const ert_init_context_type * context ); - run_arg_type * ert_init_context_iget_arg( const ert_init_context_type * context , int index); - run_arg_type * ert_init_context_iens_get_arg( const ert_init_context_type * context , int iens); - - - UTIL_IS_INSTANCE_HEADER( ert_init_context ); - - -#ifdef __cplusplus -} -#endif -#endif - - diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_log.h b/ThirdParty/Ert/libenkf/include/ert/enkf/ert_log.h deleted file mode 100644 index f6819fd1bf..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_log.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'ert_log.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERTLOG_H -#define ERTLOG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -void ert_log_init_log(int log_level,const char * log_file_name, bool verbose); -void ert_log_add_fmt_message(int message_level , FILE * dup_stream , const char * fmt , ...); -void ert_log_add_message(int message_level , FILE * dup_stream , char* message, bool free_message); -void ert_log_add_message_py(int message_level, char* message); -void ert_log_close(); -bool ert_log_is_open(); -int ert_log_get_log_level(); -const char * ert_log_get_filename(); -log_type * ert_log_get_logh(); -void ert_log_open_empty(); - -#ifdef __cplusplus -} -#endif -#endif // ERTLOG_H diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_run_context.h b/ThirdParty/Ert/libenkf/include/ert/enkf/ert_run_context.h deleted file mode 100644 index 7442c378db..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_run_context.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'ert_run_context.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RUN_CONTEXT_H -#define ERT_RUN_CONTEXT_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#include -#include -#include - -typedef struct ert_run_context_struct ert_run_context_type; - - stringlist_type * ert_run_context_alloc_runpath_list(const bool_vector_type * iactive , path_fmt_type * runpath_fmt , subst_list_type * subst_list , int iter); - char * ert_run_context_alloc_runpath( int iens , path_fmt_type * runpath_fmt , subst_list_type * subst_list , int iter); - ert_run_context_type * ert_run_context_alloc_ENSEMBLE_EXPERIMENT(enkf_fs_type * fs , - bool_vector_type * iactive , - path_fmt_type * runpath_fmt , - subst_list_type * subst_list , - int iter); - - - ert_run_context_type * ert_run_context_alloc_SMOOTHER_RUN(enkf_fs_type * simulate_fs , enkf_fs_type * target_update_fs , - bool_vector_type * iactive , - path_fmt_type * runpath_fmt , - subst_list_type * subst_list , - int iter); - void ert_run_context_set_init_fs(ert_run_context_type * context, enkf_fs_type * init_fs); - void ert_run_context_set_result_fs(ert_run_context_type * context, enkf_fs_type * result_fs); - void ert_run_context_set_update_target_fs(ert_run_context_type * context, enkf_fs_type * update_target_fs); - - void ert_run_context_free( ert_run_context_type * ); - int ert_run_context_get_size( const ert_run_context_type * context ); - run_mode_type ert_run_context_get_mode( const ert_run_context_type * context ); - bool_vector_type * ert_run_context_get_iactive( const ert_run_context_type * context ); - int ert_run_context_get_iter( const ert_run_context_type * context ); - int ert_run_context_get_step1( const ert_run_context_type * context ); - int ert_run_context_get_step2( const ert_run_context_type * context ); - int ert_run_context_get_load_start( const ert_run_context_type * context ); - run_arg_type * ert_run_context_iget_arg( const ert_run_context_type * context , int index); - run_arg_type * ert_run_context_iens_get_arg( const ert_run_context_type * context , int iens); - void ert_run_context_deactivate_realization( ert_run_context_type * context , int iens); - - enkf_fs_type * ert_run_context_get_init_fs(const ert_run_context_type * run_context); - enkf_fs_type * ert_run_context_get_result_fs(const ert_run_context_type * run_context); - enkf_fs_type * ert_run_context_get_update_target_fs(const ert_run_context_type * run_context); - - UTIL_IS_INSTANCE_HEADER( ert_run_context ); - - -#ifdef __cplusplus -} -#endif -#endif - - diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_template.h b/ThirdParty/Ert/libenkf/include/ert/enkf/ert_template.h deleted file mode 100644 index 3b2d4aeb91..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_template.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ert_template.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_TEMPLATE_H -#define ERT_TEMPLATE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include - -typedef struct ert_template_struct ert_template_type; -typedef struct ert_templates_struct ert_templates_type; - - -stringlist_type * ert_templates_alloc_list( ert_templates_type * ert_templates); -ert_template_type * ert_template_alloc( const char * template_file , const char * target_file, subst_list_type * parent_subst) ; -void ert_template_free( ert_template_type * ert_tamplete ); -void ert_template_instantiate( ert_template_type * ert_template , const char * path , const subst_list_type * arg_list ); -void ert_template_add_arg( ert_template_type * ert_template , const char * key , const char * value ); -void ert_template_free__(void * arg); - -void ert_templates_clear( ert_templates_type * ert_templates ); -ert_template_type * ert_templates_get_template( ert_templates_type * ert_templates , const char * key); - -ert_templates_type * ert_templates_alloc(subst_list_type * parent_subst); -void ert_templates_free( ert_templates_type * ert_templates ); -ert_template_type * ert_templates_add_template( ert_templates_type * ert_templates , const char * key , const char * template_file , const char * target_file , const char * arg_string); -void ert_templates_instansiate( ert_templates_type * ert_templates , const char * path , const subst_list_type * arg_list); -void ert_templates_del_template( ert_templates_type * ert_templates , const char * key); - -const char * ert_template_get_template_file( const ert_template_type * ert_template); -const char * ert_template_get_target_file( const ert_template_type * ert_template); -const char * ert_template_get_args_as_string( const ert_template_type * ert_template ); -void ert_templates_fprintf_config( const ert_templates_type * ert_templates , FILE * stream ); -void ert_templates_init( ert_templates_type * templates , const config_content_type * config ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_test_context.h b/ThirdParty/Ert/libenkf/include/ert/enkf/ert_test_context.h deleted file mode 100644 index 4dfacef55d..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_test_context.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'ert_test_context.h' is part of ERT - Ensemble based - Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_TEST_CONTEXT_H -#define ERT_TEST_CONTEXT_H - -#include - -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct ert_test_context_struct ert_test_context_type; - -void ert_test_context_set_store( ert_test_context_type * test_context , bool store); -ert_test_context_type * ert_test_context_alloc( const char * test_name , const char * model_config); -ert_test_context_type * ert_test_context_alloc_python( const char * test_name , const char * model_config); -void ert_test_context_free( ert_test_context_type * test_context ); -enkf_main_type * ert_test_context_get_main( ert_test_context_type * test_context ); -bool ert_test_context_install_workflow_job( ert_test_context_type * test_context , const char * job_name , const char * job_file); -bool ert_test_context_run_worklow_job( ert_test_context_type * test_context , const char * job_name, const stringlist_type * args); -void ert_test_context_fwrite_workflow_job( FILE * stream , const char * job_name , const stringlist_type * args); -bool ert_test_context_install_workflow( ert_test_context_type * test_context , const char * workflow_name , const char * workflow_file); -bool ert_test_context_run_worklow( ert_test_context_type * test_context , const char * workflow_name); -const char * ert_test_context_get_cwd( const ert_test_context_type * test_context ); - -UTIL_IS_INSTANCE_HEADER( ert_test_context ); - -#ifdef __cplusplus -} -#endif - -#endif - - diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_workflow_list.h b/ThirdParty/Ert/libenkf/include/ert/enkf/ert_workflow_list.h deleted file mode 100644 index cc861a1b3f..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/ert_workflow_list.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'ert_workflow_list.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_WORKFLOW_LIST_H -#define ERT_WORKFLOW_LIST_H - - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include -#include - -#include -#include - - - typedef struct ert_workflow_list_struct ert_workflow_list_type; - - workflow_type * ert_workflow_list_get_workflow(ert_workflow_list_type * workflow_list , const char * workflow_name ); - workflow_type * ert_workflow_list_add_workflow( ert_workflow_list_type * workflow_list , const char * workflow_file , const char * workflow_name); - void ert_workflow_list_free( ert_workflow_list_type * workflow_list ); - ert_workflow_list_type * ert_workflow_list_alloc( const subst_list_type * subst_list ); - void ert_workflow_list_add_jobs_in_directory( ert_workflow_list_type * workflow_list , const char * path ); - void ert_workflow_list_add_job( ert_workflow_list_type * workflow_list , const char * job_name , const char * config_file ); - bool ert_workflow_list_has_job( const ert_workflow_list_type * workflow_list , const char * job_name); - const workflow_job_type * ert_workflow_list_get_job( const ert_workflow_list_type * workflow_list , const char * job_name); - stringlist_type * ert_workflow_list_get_job_names(const ert_workflow_list_type * workflow_list); - void ert_workflow_list_add_alias( ert_workflow_list_type * workflow_list , const char * real_name , const char * alias); - void ert_workflow_list_add_config_items( config_parser_type * config ); - void ert_workflow_list_init( ert_workflow_list_type * workflow_list , config_content_type * config ); - bool ert_workflow_list_run_workflow(ert_workflow_list_type * workflow_list, const char * workflow_name , void * self); - bool ert_workflow_list_run_workflow__(ert_workflow_list_type * workflow_list, workflow_type * workflow, bool verbose , void * self); - bool ert_workflow_list_has_workflow(ert_workflow_list_type * workflow_list , const char * workflow_name ); - stringlist_type * ert_workflow_list_alloc_namelist( ert_workflow_list_type * workflow_list ); - const config_error_type * ert_workflow_list_get_last_error( const ert_workflow_list_type * workflow_list); - void ert_workflow_list_set_verbose( ert_workflow_list_type * workflow_list , bool verbose); - bool ert_workflow_list_run_workflow_blocking(ert_workflow_list_type * workflow_list , const char * workflow_name , void * self); - const subst_list_type * ert_workflow_list_get_context(const ert_workflow_list_type * workflow_list); - int ert_workflow_list_get_size( const ert_workflow_list_type * workflow_list); - - - UTIL_IS_INSTANCE_HEADER( ert_workflow_list ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/field.h b/ThirdParty/Ert/libenkf/include/ert/enkf/field.h deleted file mode 100644 index c2d1c3c8bc..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/field.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'field.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_FIELD_H -#define ERT_FIELD_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include - -#include -#include -#include -#include -#include - -/* Typedef field_type moved to field_config.h */ - - void field_scale(field_type * field, double scale_factor); - int field_get_global_index(const field_type * , int , int , int ); - void field_ijk_set(field_type * , int , int , int , const void * ); - void field_indexed_set(field_type * field, ecl_type_enum , int , const int * , const void * ); - void field_indexed_add(field_type * field, ecl_type_enum , int , const int * , const void * ); - double field_iget_double(const field_type * , int ); - double field_ijk_get_double(const field_type * field, int , int , int ); - float field_iget_float(const field_type * , int ); - float field_ijk_get_float(const field_type * field, int , int , int ); - void field_ijk_get(const field_type * , int , int , int , void *); - bool field_ijk_valid(const field_type * , int , int , int ); - void field_ijk_get_if_valid(const field_type * , int , int , int , void * , bool *); - void field_ecl_write1D_fortio(const field_type * , fortio_type *); - void field_ecl_write3D_fortio(const field_type * , fortio_type *, const char *); - void field_ROFF_export(const field_type * , const char * , const char *); - void field_copy_ecl_kw_data(field_type * , const ecl_kw_type * ); - field_type * field_alloc_shared(const field_config_type * , void * , int ); - void field_free(field_type *); - void field_get_dims(const field_type *, int *, int *, int *); - bool field_fload_keep_inactive(field_type * field , const char * filename); - bool field_fload_auto(field_type * , const char * , bool); - bool field_fload_rms(field_type * field , const char * filename, bool keep_inactive); - void field_export3D(const field_type * , void *, bool, ecl_type_enum , void *, const char *); - void field_export(const field_type * , const char * , fortio_type * , field_file_format_type , bool, const char *); - field_type * field_copyc(const field_type *); - bool field_cmp(const field_type * , const field_type * ); - - double * field_indexed_get_alloc(const field_type *, int, const int *); - void field_inplace_output_transform(field_type * field); - - void field_iscale(field_type * , double ); - void field_isqrt(field_type *); - void field_isqr(field_type *); - void field_iaddsqr(field_type * , const field_type *); - void field_iadd(field_type * , const field_type *); - void field_imul_add(field_type * , double , const field_type *); - ecl_kw_type * field_alloc_ecl_kw_wrapper(const field_type * ); - void field_update_sum(field_type * sum , field_type * field , double lower_limit , double upper_limit); - void field_upgrade_103(const char * filename); - - UTIL_IS_INSTANCE_HEADER(field); - UTIL_SAFE_CAST_HEADER_CONST(field); - VOID_ALLOC_HEADER(field); - VOID_FREE_HEADER(field); - VOID_COPY_HEADER (field); - VOID_INITIALIZE_HEADER(field); - VOID_ECL_WRITE_HEADER (field); - VOID_FORWARD_LOAD_HEADER(field); - VOID_USER_GET_HEADER(field); - VOID_READ_FROM_BUFFER_HEADER(field); - VOID_WRITE_TO_BUFFER_HEADER(field); - VOID_SERIALIZE_HEADER(field); - VOID_DESERIALIZE_HEADER(field); - VOID_CLEAR_HEADER(field); - VOID_SET_INFLATION_HEADER(field); - VOID_IMUL_HEADER(field); - VOID_IADD_HEADER(field); - VOID_IADDSQR_HEADER(field); - VOID_SCALE_HEADER(field); - VOID_ISQRT_HEADER(field); - VOID_FLOAD_HEADER(field); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/field_common.h b/ThirdParty/Ert/libenkf/include/ert/enkf/field_common.h deleted file mode 100644 index 5cac48ff7d..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/field_common.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'field_common.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_FIELD_COMMON_H -#define ERT_FIELD_COMMON_H - -/* - Contains some headers which both field.c and field_config.c need - - split like this to avoid circular dependencies. -*/ - - - -typedef struct field_config_struct field_config_type; -typedef struct field_struct field_type; - -field_type * field_alloc(const field_config_type * ); -bool field_fload(field_type * , const char * ); - - - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/field_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/field_config.h deleted file mode 100644 index f5bcd5b578..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/field_config.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'field_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_FIELD_CONFIG_H -#define ERT_FIELD_CONFIG_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - - -/** - This is purely a convenience structure used during initialization, - to denote which arguments are required and, which should be - defualted. - -*/ - -typedef enum { - ECLIPSE_RESTART = 1, - ECLIPSE_PARAMETER = 2, - GENERAL = 3, - UNKNOWN_FIELD_TYPE= 4 -} field_type_enum; - - -/** - The field_file_format_type denotes different ways to store a - field. Unfortunately the different elements in the enum definition - have somewhat different properties: - - - 1. ecl_kw_file is for input - either pack or unpacked. - - 2. ecl_kw_file_active_cells / ecl_kw_file_all_cells are for output. - - 3. Except for ecl_restart_file all formats are for A FILE (with a - filename), more or less assuming that this field is the only - content in the file, whereas ecl_restart_file is for a restart - block, and not a file. - - This has some slightly unlogical consequences: - - 1. The enum has 'file_format' in the name, but ecl_restart_file - is not a file. - - 2. The functions which guess/determine a file type can not return - all possible values of the enum. - - 3. Treatment is not symmetric for input/output. - -*/ - - - - -typedef enum { UNDEFINED_FORMAT = 0, - RMS_ROFF_FILE = 1, - ECL_KW_FILE = 2, /* ecl_kw format either packed (i.e. active cells) *or* all cells - used when reading from file. */ - ECL_KW_FILE_ACTIVE_CELLS = 3, /* ecl_kw format, only active cells - used writing to file. */ - ECL_KW_FILE_ALL_CELLS = 4, /* ecl_kw_format, all cells - used when writing to file. */ - ECL_GRDECL_FILE = 5, - ECL_FILE = 6, /* Assumes packed on export. */ - FILE_FORMAT_NULL = 7} field_file_format_type; /* Used when the guess functions are given NULL to check -should never be read. */ - - -/* active_cells currently not really implemented */ - - - - - -void field_config_update_state_field( field_config_type * config, int truncation, double min_value , double max_value); - - -void field_config_update_parameter_field( field_config_type * config , int truncation, double min_value , double max_value, - field_file_format_type export_format , - const char * init_transform , const char * output_transform ); - - -void field_config_update_general_field( field_config_type * config , int truncation, double min_value , double max_value, - field_file_format_type export_format , /* This can be guessed with the field_config_default_export_format( ecl_file ) function. */ - const char * init_transform , - const char * input_transform , - const char * output_transform ); - - -field_config_type * field_config_alloc_empty( const char * ecl_kw_name , ecl_grid_type * ecl_grid , field_trans_table_type * trans_table, bool global_size ); - - -void field_config_get_ijk( const field_config_type * config , int active_index , int *i , int * j , int * k); -field_type * field_config_get_min_std( const field_config_type * field_config ); -const char * field_config_default_extension(field_file_format_type , bool ); -bool field_config_write_compressed(const field_config_type * ); -field_file_format_type field_config_guess_file_type(const char * ); -field_file_format_type field_config_manual_file_type(const char * , bool); -ecl_type_enum field_config_get_ecl_type(const field_config_type * ); -rms_type_enum field_config_get_rms_type(const field_config_type * ); -void field_config_get_dims(const field_config_type * , int * , int * , int *); -int field_config_get_nx(const field_config_type * config ); -int field_config_get_ny(const field_config_type * config ); -int field_config_get_nz(const field_config_type * config ); -void field_config_free(field_config_type *); -int field_config_get_volume(const field_config_type * ); -int field_config_get_data_size_from_grid(const field_config_type * config); -void field_config_set_ecl_kw_name(field_config_type * , const char * ); -void field_config_set_ecl_type(field_config_type * , ecl_type_enum ); -void field_config_set_eclfile(field_config_type * , const char * ); -const bool * field_config_get_iactive(const field_config_type * ); -int field_config_get_byte_size(const field_config_type * ); -int field_config_get_sizeof_ctype(const field_config_type * ); -int field_config_active_index(const field_config_type * , int , int , int ); -int field_config_global_index(const field_config_type * , int , int , int ); -void field_config_get_ijk(const field_config_type * , int , int * , int * , int *); -bool field_config_ijk_valid(const field_config_type * , int , int , int ); -bool field_config_ijk_active(const field_config_type * config , int i , int j , int k); -bool field_config_active_cell(const field_config_type * , int , int , int); -char * field_config_alloc_init_file(const field_config_type * , int ); -field_file_format_type field_config_get_export_format(const field_config_type * ); -field_file_format_type field_config_get_import_format(const field_config_type * ); -void field_config_set_all_active(field_config_type * ); -void field_config_set_key(field_config_type * , const char *); -void field_config_enkf_OFF(field_config_type * ); -bool field_config_enkf_mode(const field_config_type * config); -void field_config_scanf_ijk(const field_config_type * , bool , const char * , int , int * , int * , int * , int *); -const char * field_config_get_key(const field_config_type * ); -bool field_config_keep_inactive_cells(const field_config_type *); -field_func_type * field_config_get_init_transform(const field_config_type * ); -field_func_type * field_config_get_output_transform(const field_config_type * ); -field_func_type * field_config_get_input_transform(const field_config_type * ); - //void field_config_set_output_transform(field_config_type * config , field_func_type * ); -bool field_config_is_valid( const field_config_type * field_config ); -void field_config_assert_binary( const field_config_type * , const field_config_type * , const char * ); -void field_config_assert_unary( const field_config_type * , const char * ); -void field_config_activate(field_config_type * , active_mode_type , void * ); - -const char * field_config_get_init_transform_name( const field_config_type * field_config ); -const char * field_config_get_input_transform_name( const field_config_type * field_config ); -const char * field_config_get_output_transform_name( const field_config_type * field_config ); - -void field_config_set_truncation(field_config_type * , int , double , double ); -int field_config_get_truncation_mode(const field_config_type * config ); -double field_config_get_truncation_min( const field_config_type * config ); -double field_config_get_truncation_max( const field_config_type * config ); -ecl_grid_type * field_config_get_grid(const field_config_type * ); -const char * field_config_get_grid_name( const field_config_type * ); - - int field_config_parse_user_key(const field_config_type * config, const char * index_key , int *i , int *j , int *k); - bool field_config_parse_user_key__( const char * index_key , int *i , int *j , int *k); - -field_file_format_type field_config_default_export_format(const char * filename); -const char * field_config_get_input_transform_name( const field_config_type * field_config ) ; -const char * field_config_get_output_transform_name( const field_config_type * field_config ) ; -const char * field_config_get_init_transform_name( const field_config_type * field_config ) ; - -void field_config_fprintf_config( const field_config_type * config , enkf_var_type var_type , const char * outfile , const char * infile , - const char * min_std_file , FILE * stream); - - - -/*Generated headers */ - UTIL_IS_INSTANCE_HEADER(field_config); -UTIL_SAFE_CAST_HEADER(field_config); -UTIL_SAFE_CAST_HEADER_CONST(field_config); -CONFIG_GET_ECL_KW_NAME_HEADER(field); -VOID_FREE_HEADER(field_config); -VOID_GET_DATA_SIZE_HEADER(field); -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/field_trans.h b/ThirdParty/Ert/libenkf/include/ert/enkf/field_trans.h deleted file mode 100644 index c235edc1ae..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/field_trans.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'field_trans.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_FIELD_TRANS_H -#define ERT_FIELD_TRANS_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - - -typedef float (field_func_type) ( float ); -typedef struct field_trans_table_struct field_trans_table_type; - - -void field_trans_table_fprintf(const field_trans_table_type * , FILE * ); -void field_trans_table_free(field_trans_table_type * ); -void field_trans_table_add(field_trans_table_type * , const char * , const char * , field_func_type * ); -field_trans_table_type * field_trans_table_alloc(); -bool field_trans_table_has_key(field_trans_table_type * , const char * ); -field_func_type * field_trans_table_lookup(field_trans_table_type * , const char * ); - - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/forward_load_context.h b/ThirdParty/Ert/libenkf/include/ert/enkf/forward_load_context.h deleted file mode 100644 index 991c06917f..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/forward_load_context.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'forward_load_context.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_FORWARD_LOAD_CONTEXT_H -#define ERT_FORWARD_LOAD_CONTEXT_H - -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -#include -#include - -#include -#include -#include - - typedef struct forward_load_context_struct forward_load_context_type; - - bool forward_load_context_accept_messages( const forward_load_context_type * load_context ); - void forward_load_context_add_message( forward_load_context_type * load_context , const char * message ); - void forward_load_context_update_result( forward_load_context_type * load_context , int flags); - int forward_load_context_get_result( const forward_load_context_type * load_context ); - forward_load_context_type * forward_load_context_alloc( const run_arg_type * run_arg , bool load_summary , const ecl_config_type * ecl_config , const char * eclbase, stringlist_type * messages); - void forward_load_context_free( forward_load_context_type * load_context ); - const ecl_sum_type * forward_load_context_get_ecl_sum( const forward_load_context_type * load_context); - const ecl_file_type * forward_load_context_get_restart_file( const forward_load_context_type * load_context); - int forward_load_context_get_report_step( const forward_load_context_type * load_context); - int forward_load_context_get_iens( const forward_load_context_type * load_context); - const run_arg_type * forward_load_context_get_run_arg( const forward_load_context_type * load_context ); - const char * forward_load_context_get_run_path( const forward_load_context_type * load_context ); - int forward_load_context_get_load_step(const forward_load_context_type * load_context); - enkf_fs_type * forward_load_context_get_result_fs( const forward_load_context_type * load_context ); - bool forward_load_context_load_restart_file( forward_load_context_type * load_context , int report_step ); - void forward_load_context_select_step( forward_load_context_type * load_context , int report_step); - - UTIL_IS_INSTANCE_HEADER( forward_load_context ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/fs_driver.h b/ThirdParty/Ert/libenkf/include/ert/enkf/fs_driver.h deleted file mode 100644 index 28f1bfc359..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/fs_driver.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'fs_driver.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_FS_DRIVER_H -#define ERT_FS_DRIVER_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -#include -#include - -#define FS_MAGIC_ID 123998L -#define FSTAB_FILE "ert_fstab" -#define CURRENT_FS_VERSION 107 -#define MIN_SUPPORTED_FS_VERSION 105 - -/** - Version history: - - 0 : - - - File system version | First svn version | Last svn version - -------------------------------------------------------------------------- - 100 | | 1799 - 101 | 1810 | 1886 - 102 | 1887/1902 | 1996 - 103 | 1997 | - | 2047: sqlite added | 2125 - 104 | 2127 | - | 2140: block_fs_index added - | 2190: started to distribute ert binary internally - 105 | 3918 | - 106 | Git ~ Desember 2015 - 107 | Git ~ September 2017 - ------------------------------------------------------------------------- - - - Version: 100 - ------------ - First version with subdirectories for different cases. - - - - Version: 101 - ------------ - Have changed the format for storing static keywords. Instead of a - directory with numbered files in them, the keywords get an integer - appended: - - INTEHEAD/0 ==> INTEHEAD_0 - - The actual changing of keyword is done in the function - __realloc_static_kw() in enkf_state.c. - - - - Version: 102 - ------------ - Have removed the type spesific plain drivers, now it is only - plain_driver and plain_driver index. The special functionality for - parameters/static/dynamic is now implemented at the enkf_fs level. - The upgrade from 101 only involves the mount info and the - implementation, the actual stored files are not touched by this - upgrade. - - - - Version: 103 - ------------ - Have changed the reading/writing to go through the buffer - type. This should simplify introducing other drivers than the - simple plain file based driver. - - The upgrade to version is 103 is quite extensive - all node types - have specific _103_ functions. The xxx_fread() and xxx_fwrite() - functions were removed in svn:2046. - - A very experimental version of the sqlite driver was added in - svn:2047. When (if ??) this stabilizes it should probably lead to - an upgrade to version 104. - - At the very last checkin of this version the fs prototypes also - changed to use (const enkf_config_node_type *) instances instead of - (const char * ) for the main key. - - - - Version: 104 - ------------ - In this version the treatment of read_xx and write_xx drivers has - changed. There are no longer separate read_xx and write_xx drivers, - instead the drivers have internal state which differentiates - between read and write. - - The block_fs driver is added - and reasonably stabilized in this - version. - - - Observe that all the upgrade functions were removed at svn:3305. - - - Version 104B - ------------ - Vector storage; each case is a seperate enkf_fs instance. Current - is stored with a symlink. Read about 104 -> 104B fuckup in the - function upgrade104B() in fs_driver.c - - - Version: 105 - ------------ - Using time_map to store time information; common to all members in - ensemble. - - - Version: 106 - ------------ - - Dropped drivers for storing STATIC eclipse keywords. The upgrade - from version 105 to 106 happens silently; the only thing happening - is that the information about the static driver is ignored when - reading the mount map. An older version of ert - with - CURRENT_VERSION == 105 can also read a VERSION == 106 filesystem - with a minor backport and some default heuristics. - - - Version: 107 - ------------ - - Using UTC instead of localtime throughout the code. This implies - that the timemaps written to disk with old versions have time_t - values corresponding to localtime, whereas everything now is - expected to be in utc. - - If we detect a filesystem with version below 107 we stop the - program. If a refcase is supplied the user is given a suggested - commandline to perform an inplace upgrade. -*/ - - - - - typedef struct fs_driver_struct fs_driver_type; - - typedef void (save_kwlist_ftype) (void * , int , int , buffer_type * buffer); /* Functions used to load/store restart_kw_list instances. */ - typedef void (load_kwlist_ftype) (void * , int , int , buffer_type * buffer); - - typedef void (load_node_ftype) (void * driver, const char * , int , int , buffer_type * ); - typedef void (save_node_ftype) (void * driver, const char * , int , int , buffer_type * ); - typedef void (unlink_node_ftype) (void * driver, const char * , int , int ); - typedef bool (has_node_ftype) (void * driver, const char * , int , int ); - - typedef void (load_vector_ftype) (void * driver, const char * , int , buffer_type * ); - typedef void (save_vector_ftype) (void * driver, const char * , int , buffer_type * ); - typedef void (unlink_vector_ftype) (void * driver, const char * , int ); - typedef bool (has_vector_ftype) (void * driver, const char * , int ); - - typedef void (fsync_driver_ftype) (void * driver); - typedef void (free_driver_ftype) (void * driver); - - -/** - The fs_driver_type contains a number of function pointers - and a type_id used for run-time cast checking. - - The fs_driver_type is never actually used, but the point is that - all drivers must implement the fs driver "interface". In practice - this is done by including the macro FS_DRIVER_FIELDS *at the start* - of the definition of another driver, i.e. the simplest actually - working driver, the plain_driver is implemented like this: - - struct plain_driver_struct { - FS_DRIVER_FIELDS - int plain_driver_id; - path_fmt_type * path; - } - - -*/ - - - -#define FS_DRIVER_FIELDS \ -load_node_ftype * load_node; \ -save_node_ftype * save_node; \ -has_node_ftype * has_node; \ -unlink_node_ftype * unlink_node; \ -load_vector_ftype * load_vector; \ -save_vector_ftype * save_vector; \ -has_vector_ftype * has_vector; \ -unlink_vector_ftype * unlink_vector; \ -free_driver_ftype * free_driver; \ -fsync_driver_ftype * fsync_driver; \ -int type_id - - - - -struct fs_driver_struct { - FS_DRIVER_FIELDS; -}; - - - - /*****************************************************************/ - - void fs_driver_init(fs_driver_type * ); - void fs_driver_assert_cast(const fs_driver_type * ); - fs_driver_type * fs_driver_safe_cast(void * ); - - void fs_driver_init_fstab( FILE * stream, fs_driver_impl driver_id ); - char * fs_driver_alloc_fstab_file( const char * path ); - FILE * fs_driver_open_fstab( const char * path , bool create); - fs_driver_impl fs_driver_fread_type( FILE * stream ); - void fs_driver_assert_magic( FILE * stream ); - void fs_driver_assert_version( FILE * stream , const char * mount_point); - int fs_driver_fread_version( FILE * stream ); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/fs_types.h b/ThirdParty/Ert/libenkf/include/ert/enkf/fs_types.h deleted file mode 100644 index 7f34d0519f..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/fs_types.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'fs_types.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_FS_TYPES_H -#define ERT_FS_TYPES_H - - - -/* - The various driver implementations - this goes on disk all over the - place, and the numbers should be considered SET IN STONE. When a new - driver is added the switch statement in the enkf_fs_mount() function - must be updated. -*/ - -// Version from ~ svn:3720 -//typedef enum { -// INVALID_DRIVER_ID = 0, -// PLAIN_DRIVER_INDEX_ID = 1001, -// PLAIN_DRIVER_STATIC_ID = 1002, /* Depreceated */ -// PLAIN_DRIVER_DYNAMIC_ID = 1003, /* Depreceated */ -// PLAIN_DRIVER_PARAMETER_ID = 1004, /* Depreceated */ -// PLAIN_DRIVER_ID = 1005, -// BLOCK_FS_DRIVER_ID = 3001, -// BLOCK_FS_DRIVER_INDEX_ID = 3002 } fs_driver_impl; - - -typedef enum { - INVALID_DRIVER_ID = 0, - PLAIN_DRIVER_ID = 1005, - BLOCK_FS_DRIVER_ID = 3001} fs_driver_impl; - - - - - - -/* - The categories of drivers. To reduce the risk of programming - error (or at least to detect it ...), there should be no overlap - between these ID's and the ID's of the actual implementations - above. The same comment about permanent storage applies to these - numbers as well. -*/ - -typedef enum { - DRIVER_PARAMETER = 1, - DRIVER_STATIC = 2, // Driver static is no longer in use since December 2015 - but it must be retained here for old mount files on disk. - DRIVER_INDEX = 4, // DRIVER_DYNAMIC = 3; removed at svn ~ 3720. - DRIVER_DYNAMIC_FORECAST = 5, - DRIVER_DYNAMIC_ANALYZED = 6 // Driver DYNAMIC_ANALYZED is no longer in use since April 2016 - but it must be retained here for old mount files on disk. -} fs_driver_enum; - - - - - -fs_driver_impl fs_types_lookup_string_name(const char * driver_name); -const char * fs_types_get_driver_name(fs_driver_enum driver_type); -bool fs_types_valid( fs_driver_enum driver_type); - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_common.h b/ThirdParty/Ert/libenkf/include/ert/enkf/gen_common.h deleted file mode 100644 index 906310391c..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_common.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_common.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GEN_COMMON_H -#define ERT_GEN_COMMON_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -void * gen_common_fscanf_alloc(const char * , ecl_type_enum , int * ); -void * gen_common_fread_alloc(const char * , ecl_type_enum , int * ); -void * gen_common_fload_alloc(const char * , gen_data_file_format_type , ecl_type_enum , ecl_type_enum * , int * ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_data.h b/ThirdParty/Ert/libenkf/include/ert/enkf/gen_data.h deleted file mode 100644 index 587f916230..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_data.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_data.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GEN_DATA_H -#define ERT_GEN_DATA_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -void gen_data_assert_size( gen_data_type * gen_data , int size , int report_step); -bool gen_data_forward_load(gen_data_type * gen_data , const char * ecl_file , const forward_load_context_type * load_context); -void gen_data_free(gen_data_type * ); -double gen_data_iget_double(const gen_data_type * , int ); - void gen_data_iset_double(gen_data_type * , int , double); -gen_data_config_type * gen_data_get_config(const gen_data_type * ); -const bool_vector_type * gen_data_get_forward_mask( const gen_data_type * gen_data ); -int gen_data_get_size(const gen_data_type * ); -double gen_data_iget_double(const gen_data_type * , int ); -void gen_data_export(const gen_data_type * gen_data , const char * full_path , gen_data_file_format_type export_type , fortio_type * fortio); -void gen_data_export_data(const gen_data_type * gen_data , double_vector_type * export_data); -gen_data_file_format_type gen_data_guess_export_type( const gen_data_type * gen_data ); -const char * gen_data_get_key( const gen_data_type * gen_data); -void gen_data_upgrade_103(const char * filename); -int gen_data_get_size( const gen_data_type * gen_data ); -void gen_data_copy_to_double_vector(const gen_data_type * gen_data , double_vector_type * vector); -bool gen_data_fload_with_report_step( gen_data_type * gen_data , const char * filename , const forward_load_context_type * load_context); - -UTIL_SAFE_CAST_HEADER(gen_data); -UTIL_SAFE_CAST_HEADER_CONST(gen_data); -VOID_USER_GET_HEADER(gen_data); -VOID_ALLOC_HEADER(gen_data); -VOID_FREE_HEADER(gen_data); -VOID_COPY_HEADER (gen_data); -VOID_ECL_WRITE_HEADER(gen_data); -VOID_FORWARD_LOAD_HEADER(gen_data); -VOID_INITIALIZE_HEADER(gen_data); -VOID_READ_FROM_BUFFER_HEADER(gen_data); -VOID_WRITE_TO_BUFFER_HEADER(gen_data); -VOID_SERIALIZE_HEADER(gen_data) -VOID_DESERIALIZE_HEADER(gen_data) -VOID_SET_INFLATION_HEADER(gen_data); -VOID_CLEAR_HEADER(gen_data); -VOID_IMUL_HEADER(gen_data); -VOID_IADD_HEADER(gen_data); -VOID_IADDSQR_HEADER(gen_data); -VOID_SCALE_HEADER(gen_data); -VOID_ISQRT_HEADER(gen_data); -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_data_common.h b/ThirdParty/Ert/libenkf/include/ert/enkf/gen_data_common.h deleted file mode 100644 index 4668c25bde..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_data_common.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_data_common.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GEN_DATA_COMMON_H -#define ERT_GEN_DATA_COMMON_H - -/* - Contains some headers which both gen_data.c and gen_data_config.c need - - split like this to avoid circular dependencies. -*/ - - -typedef struct gen_data_config_struct gen_data_config_type; -typedef struct gen_data_struct gen_data_type; - -gen_data_type * gen_data_alloc(const gen_data_config_type * ); -bool gen_data_fload(gen_data_type * , const char * ); - - - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_data_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/gen_data_config.h deleted file mode 100644 index 2ef3e1e955..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_data_config.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_data_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GEN_DATA_CONFIG_H -#define ERT_GEN_DATA_CONFIG_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -typedef enum { GEN_DATA_UNDEFINED = 0, - ASCII = 1, /* The file is ASCII file with a vector of numbers formatted with "%g". */ - ASCII_TEMPLATE = 2, /* The data is inserted into a user defined template file. */ - BINARY_DOUBLE = 3, /* The data is in a binary file with doubles. */ - BINARY_FLOAT = 4} /* The data is in a binary file with floats. */ - gen_data_file_format_type; - - bool gen_data_config_is_dynamic( const gen_data_config_type * config ); - void gen_data_config_load_active( gen_data_config_type * config , enkf_fs_type * fs, int report_step , bool force_load); - bool gen_data_config_valid_result_format(const char * result_file_fmt); - bool gen_data_config_set_template( gen_data_config_type * config , const char * template_ecl_file , const char * template_data_key ); - - bool gen_data_config_has_active_mask( const gen_data_config_type * config , enkf_fs_type * fs , int report_step); - - /* - Observe that the format ASCII_template can *NOT* be used for - loading files. - */ - gen_data_config_type * gen_data_config_alloc_GEN_PARAM( const char * key , gen_data_file_format_type output_format , gen_data_file_format_type input_format); - gen_data_config_type * gen_data_config_alloc_GEN_DATA_result( const char * key , gen_data_file_format_type input_format); - gen_data_config_type * gen_data_config_alloc_GEN_DATA_state( const char * key , gen_data_file_format_type output_format , gen_data_file_format_type input_format); - void gen_data_config_set_ens_size( gen_data_config_type * config , int ens_size ); - gen_data_file_format_type gen_data_config_get_input_format ( const gen_data_config_type * ); - gen_data_file_format_type gen_data_config_get_output_format ( const gen_data_config_type * ); - ecl_type_enum gen_data_config_get_internal_type(const gen_data_config_type * ); - gen_data_config_type * gen_data_config_alloc_with_options(const char * key , bool , const stringlist_type *); - void gen_data_config_free(gen_data_config_type * ); - int gen_data_config_get_initial_size( const gen_data_config_type * config ); - void gen_data_config_assert_size(gen_data_config_type * , int , int); - const bool_vector_type * gen_data_config_get_active_mask( const gen_data_config_type * config ); - void gen_data_config_update_active(gen_data_config_type * config , const forward_load_context_type * load_context , const bool_vector_type * data_mask); - const bool * gen_data_config_get_iactive(const gen_data_config_type * ); - void gen_data_config_ecl_write(const gen_data_config_type * , const char * , char * ); - void gen_data_config_get_template_data( const gen_data_config_type * , char ** , int * , int * , int *); - gen_data_config_type * gen_data_config_fscanf_alloc(const char * ); - const char * gen_data_config_get_key( const gen_data_config_type * config); - int gen_data_config_get_byte_size( const gen_data_config_type * config , int report_step); - int gen_data_config_get_data_size( const gen_data_config_type * config , int report_step); - gen_data_file_format_type gen_data_config_check_format( const void * format_string ); - - void gen_data_config_set_active_report_steps_from_string( gen_data_config_type *config , const char * range_string); - const int_vector_type * gen_data_config_get_active_report_steps( const gen_data_config_type *config); - int gen_data_config_iget_report_step( const gen_data_config_type *config , int index); - void gen_data_config_add_report_step( gen_data_config_type * config , int report_step); - bool gen_data_config_has_report_step( const gen_data_config_type * config , int report_step); - int gen_data_config_num_report_step( const gen_data_config_type * config ); - const char * gen_data_config_get_template_file( const gen_data_config_type * config ); - const char * gen_data_config_get_template_key( const gen_data_config_type * config ); - void gen_data_config_fprintf_config( const gen_data_config_type * config , enkf_var_type var_type , const char * outfile , const char * infile , - const char * min_std_file , FILE * stream); - - UTIL_IS_INSTANCE_HEADER(gen_data_config); - UTIL_SAFE_CAST_HEADER(gen_data_config); - UTIL_SAFE_CAST_HEADER_CONST(gen_data_config); - VOID_FREE_HEADER(gen_data_config) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw.h b/ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw.h deleted file mode 100644 index 92911a7a6a..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_kw.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GEN_KW_H -#define ERT_GEN_KW_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include -#include -#include -#include - - - -void gen_kw_output_transform(gen_kw_type * ); -void gen_kw_get_output_data(const gen_kw_type * , double * ); -const double * gen_kw_get_output_ref(const gen_kw_type * ); -const double * gen_kw_get_data_ref(const gen_kw_type * ); - //void gen_kw_get_data(const gen_kw_type * , double * ); - -void gen_kw_free(gen_kw_type *); -int gen_kw_data_size( gen_kw_type * ); -double gen_kw_data_iget( gen_kw_type * , int , bool ); -void gen_kw_data_iset( gen_kw_type * , int , double ); -void gen_kw_data_set_vector( gen_kw_type * gen_kw, const double_vector_type * values ); -double gen_kw_data_get( gen_kw_type * , const char * , bool ); -void gen_kw_data_set( gen_kw_type *, const char *, double ); -bool gen_kw_data_has_key( gen_kw_type *, const char *); -void gen_kw_ens_write(const gen_kw_type * , const char *); -void gen_kw_ens_read(gen_kw_type * , const char *); -void gen_kw_truncate(gen_kw_type * ); -gen_kw_type * gen_kw_alloc_mean(int , const gen_kw_type **); -const char * gen_kw_get_name(const gen_kw_type * , int ); -void gen_kw_filter_file(const gen_kw_type * , const char * ); -void gen_kw_export(const gen_kw_type * , int * , char ***, double **); -void gen_kw_upgrade_103( const char * filename ); -char * gen_kw_alloc_user_key(const gen_kw_config_type * , const char * , int ); -void gen_kw_set_subst_parent(gen_kw_type * gen_kw , const subst_list_type * parent_subst); -void gen_kw_ecl_write_template(const gen_kw_type * gen_kw , const char * file_name); - - -UTIL_SAFE_CAST_HEADER(gen_kw); -UTIL_SAFE_CAST_HEADER_CONST(gen_kw); -ALLOC_STATS_HEADER(gen_kw) -VOID_ECL_WRITE_HEADER (gen_kw) -VOID_COPY_HEADER (gen_kw); -VOID_INITIALIZE_HEADER(gen_kw); -VOID_FREE_HEADER (gen_kw); - //MATH_OPS_VOID_HEADER(gen_kw); -VOID_ALLOC_HEADER(gen_kw); -VOID_ECL_WRITE_HEADER(gen_kw); -VOID_USER_GET_HEADER(gen_kw); -VOID_WRITE_TO_BUFFER_HEADER(gen_kw); -VOID_READ_FROM_BUFFER_HEADER(gen_kw); -VOID_FLOAD_HEADER(gen_kw); -VOID_CLEAR_HEADER(gen_kw); -VOID_SERIALIZE_HEADER(gen_kw) -VOID_DESERIALIZE_HEADER(gen_kw) -VOID_IADD_HEADER(gen_kw); -VOID_IMUL_HEADER(gen_kw); -VOID_SCALE_HEADER(gen_kw); -VOID_IADDSQR_HEADER(gen_kw); -VOID_ISQRT_HEADER(gen_kw); -VOID_SET_INFLATION_HEADER(gen_kw); -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw_common.h b/ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw_common.h deleted file mode 100644 index f9a7db39f4..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw_common.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_kw_common.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GEN_KW_COMMON_H -#define ERT_GEN_KW_COMMON_H - -/* - Contains some headers which both gen_kw.c and gen_kw_config.c need - - split like this to avoid circular dependencies. -*/ - - -typedef struct gen_kw_config_struct gen_kw_config_type; -typedef struct gen_kw_struct gen_kw_type; - -gen_kw_type * gen_kw_alloc(const gen_kw_config_type * ); -bool gen_kw_fload(gen_kw_type * , const char *); - - - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw_config.h deleted file mode 100644 index d8a55f73b5..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_kw_config.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_kw_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GEN_KW_CONFIG_H -#define ERT_GEN_KW_CONFIG_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include - -#include -#include -#include - - -bool gen_kw_config_is_valid( const gen_kw_config_type * config ); -void gen_kw_config_fprintf_config( const gen_kw_config_type * config , const char * outfile , const char * min_std_file , FILE * stream ); -void gen_kw_config_set_parameter_file( gen_kw_config_type * config , const char * parameter_file ); -const char * gen_kw_config_get_parameter_file( const gen_kw_config_type * config ); -char * gen_kw_config_alloc_initfile( const gen_kw_config_type * gen_kw_config , int iens ); -void gen_kw_config_set_init_file_fmt( gen_kw_config_type * config , const char * init_file_fmt ); -const char * gen_kw_config_get_key(const gen_kw_config_type * config ); -const char * gen_kw_config_get_template_file(const gen_kw_config_type * ); -void gen_kw_config_free(gen_kw_config_type *); -double gen_kw_config_transform(const gen_kw_config_type * , int index, double x); -bool gen_kw_config_should_use_log_scale(const gen_kw_config_type * config, int index); -int gen_kw_config_get_data_size(const gen_kw_config_type * ); -const char * gen_kw_config_iget_name(const gen_kw_config_type * , int ); -const char * gen_kw_config_get_tagged_name(const gen_kw_config_type * , int ); -stringlist_type * gen_kw_config_alloc_name_list( const gen_kw_config_type * config); -int gen_kw_config_get_index(const gen_kw_config_type * , const char * ); -char * gen_kw_config_alloc_user_key(const gen_kw_config_type * config , int kw_nr); -const char * gen_kw_config_get_init_file_fmt( const gen_kw_config_type * config ); -void gen_kw_config_set_template_file( gen_kw_config_type * config , const char * template_file ); -gen_kw_config_type * gen_kw_config_alloc_empty( const char * key , const char * tag_fmt ); -void gen_kw_config_update( gen_kw_config_type * config , const char * template_file , const char * parameter_file); -void gen_kw_config_update_tag_format(gen_kw_config_type * config , const char * tag_format); - -UTIL_SAFE_CAST_HEADER_CONST( gen_kw_config ); -UTIL_SAFE_CAST_HEADER(gen_kw_config); -VOID_FREE_HEADER(gen_kw_config); -VOID_GET_DATA_SIZE_HEADER(gen_kw); -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_obs.h b/ThirdParty/Ert/libenkf/include/ert/enkf/gen_obs.h deleted file mode 100644 index 497bcf9efa..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/gen_obs.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_obs.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GEN_OBS_H -#define ERT_GEN_OBS_H - -#include -#include -#include -#include -#include - -typedef struct gen_obs_struct gen_obs_type; - -gen_obs_type * gen_obs_alloc(gen_data_config_type * config , const char * obs_key , const char * , double , double , const char * , const char * , const char * ); -gen_obs_type * gen_obs_alloc__(gen_data_config_type * data_config , const char * obs_key); // for python bindings -void gen_obs_user_get_with_data_index(const gen_obs_type * gen_obs , const char * index_key , double * value , double * std , bool * valid); - -void gen_obs_update_std_scale(gen_obs_type * gen_obs, double std_multiplier , const active_list_type * active_list); -int gen_obs_get_size(const gen_obs_type * gen_obs); -double gen_obs_iget_std(const gen_obs_type * gen_obs, int index); -double gen_obs_iget_value(const gen_obs_type * gen_obs, int index); -double gen_obs_iget_std_scaling(const gen_obs_type * gen_obs, int index); -int gen_obs_get_obs_index(const gen_obs_type * gen_obs, int index); -void gen_obs_load_observation(gen_obs_type * gen_obs, const char * obs_file); -void gen_obs_set_scalar( gen_obs_type * gen_obs , double scalar_value , double scalar_std); -void gen_obs_attach_data_index( gen_obs_type * gen_obs , const int_vector_type * data_index ); -void gen_obs_load_data_index( gen_obs_type * obs , const char * data_index_file); -void gen_obs_parse_data_index( gen_obs_type * obs , const char * data_index_string); -void gen_obs_free(gen_obs_type * gen_obs); - - - -VOID_CHI2_HEADER(gen_obs); -UTIL_IS_INSTANCE_HEADER(gen_obs); -VOID_FREE_HEADER(gen_obs); -VOID_GET_OBS_HEADER(gen_obs); -VOID_MEASURE_HEADER(gen_obs); -VOID_USER_GET_OBS_HEADER(gen_obs); -VOID_UPDATE_STD_SCALE_HEADER(gen_obs); - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/hook_manager.h b/ThirdParty/Ert/libenkf/include/ert/enkf/hook_manager.h deleted file mode 100644 index 81e910f11a..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/hook_manager.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'hook_manager.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#ifndef ERT_HOOK_MANAGER_H -#define ERT_HOOK_MANAGER_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include -#include - - typedef struct hook_manager_struct hook_manager_type; - - hook_manager_type * hook_manager_alloc(ert_workflow_list_type * workflow_list); - void hook_manager_free(); - - void hook_manager_init( hook_manager_type * hook_manager , const config_content_type * config); - void hook_manager_add_config_items( config_parser_type * config ); - - runpath_list_type * hook_manager_get_runpath_list( hook_manager_type * hook_manager ); - void hook_manager_export_runpath_list( const hook_manager_type * hook_manager ); - void hook_manager_set_runpath_list_file( hook_manager_type * hook_manager , const char * path, const char * filename); - const char * hook_manager_get_runpath_list_file(const hook_manager_type * hook_manager); - void hook_manager_run_workflows( const hook_manager_type * hook_manager , hook_run_mode_enum run_mode , void * self); - - const hook_workflow_type * hook_manager_iget_hook_workflow(const hook_manager_type * hook_manager, int index); - int hook_manager_get_size(const hook_manager_type * hook_manager); - - /*****************************************************************/ - /* Deprecated stuff */ - /*****************************************************************/ - bool hook_manager_run_post_hook_workflow( const hook_manager_type * hook_manager , void * self); - - void hook_manager_set_path( hook_manager_type * hook_manager , const char * path); - bool hook_manager_has_post_hook_workflow( const hook_manager_type * hook_manager ); - const hook_workflow_type * hook_manager_get_post_hook_workflow( const hook_manager_type * hook_manager ); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/hook_workflow.h b/ThirdParty/Ert/libenkf/include/ert/enkf/hook_workflow.h deleted file mode 100644 index f8dbb48850..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/hook_workflow.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'hook_workflow.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#ifndef ERT_HOOK_WORKFLOW_H -#define ERT_HOOK_WORKFLOW_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -#include - - - typedef enum {PRE_SIMULATION = 0, - POST_SIMULATION = 1, - PRE_UPDATE = 2, - POST_UPDATE = 3} hook_run_mode_enum; - - typedef struct hook_workflow_struct hook_workflow_type; - - - hook_workflow_type * hook_workflow_alloc( workflow_type * workflow , hook_run_mode_enum run_mode); - void hook_workflow_free(hook_workflow_type * hook_workflow); - void hook_workflow_free__( void * arg ); - - - workflow_type * hook_workflow_get_workflow( const hook_workflow_type * hook_workflow ); - bool hook_workflow_run_workflow(const hook_workflow_type * hook_workflow, ert_workflow_list_type * workflow_list, void * self); - hook_run_mode_enum hook_workflow_get_run_mode( const hook_workflow_type * hook_workflow ); - - hook_run_mode_enum hook_workflow_run_mode_from_name( const char * run_mode ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/local_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/local_config.h deleted file mode 100644 index 25f73c9e56..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/local_config.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_LOCAL_CONFIG_H -#define ERT_LOCAL_CONFIG_H - -#include - -#include - -#include - -#include -#include -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct local_config_struct local_config_type; - -local_config_type * local_config_alloc( ); -void local_config_clear( local_config_type * local_config ); -void local_config_free( local_config_type * local_config ); -local_ministep_type * local_config_alloc_ministep( local_config_type * local_config , const char * key, analysis_module_type* analysis_module ); -local_ministep_type * local_config_alloc_ministep_copy( local_config_type * local_config , const char * src_key , const char * new_key); -void local_config_set_default_updatestep( local_config_type * local_config , local_updatestep_type * update_step ); -local_updatestep_type * local_config_get_updatestep( const local_config_type * local_config ); -local_ministep_type * local_config_get_ministep( const local_config_type * local_config , const char * key); -void local_config_set_updatestep(local_config_type * local_config, int step1 , int step2 , const char * key); -void local_config_summary_fprintf( const local_config_type * local_config , const char * config_file); -local_obsdata_type * local_config_alloc_obsdata( local_config_type * local_config , const char * obsdata_name ); -bool local_config_has_obsdata( const local_config_type * local_config , const char * obsdata_name); -local_dataset_type * local_config_alloc_dataset( local_config_type * local_config , const char * key ); -bool local_config_has_dataset( const local_config_type * local_config , const char * key); -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/local_context.h b/ThirdParty/Ert/libenkf/include/ert/enkf/local_context.h deleted file mode 100644 index 7bc72b3a30..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/local_context.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_context.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_LOCAL_CONTEXT_H -#define ERT_LOCAL_CONTEXT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include -#include - -#include -#include -#include - -#define GLOBAL_GRID "GLOBAL_GRID" - - typedef struct local_context_struct local_context_type; - - - local_context_type * local_context_alloc( const ecl_grid_type * ecl_grid ); - void local_context_free( local_context_type * context ); - - ecl_region_type * local_context_get_ecl_region( local_context_type * context , const char * region_name); - void local_context_create_ecl_region( local_context_type * context , const char * grid_name , const char * region_name , bool preselect ); - - void local_context_load_file( local_context_type * context , const char * filename , const char * file_key ); - ecl_file_type * local_context_get_file( local_context_type * context , const char * file_key ); - - void local_context_add_polygon( local_context_type * context , const char * polygon_name); - geo_polygon_type * local_context_get_polygon( local_context_type * context , const char * polygon_name ); - void local_context_load_polygon( local_context_type * context , const char * polygon_name , const char * polygon_file); - - void local_context_load_surface( local_context_type * context , const char * surface_name , const char * surface_file); - geo_surface_type * local_context_get_surface( local_context_type * context , const char * surface_name ); - - void local_context_create_surface_region( local_context_type * context , const char * surface_name , const char * region_name , bool preselect ); - geo_region_type * local_context_get_surface_region( local_context_type * context , const char * region_name); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/local_dataset.h b/ThirdParty/Ert/libenkf/include/ert/enkf/local_dataset.h deleted file mode 100644 index c7dd92fc6a..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/local_dataset.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_dataset.h' is part of ERT - Ensemble based - Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_LOCAL_DATASET_H -#define ERT_LOCAL_DATASET_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct local_dataset_struct local_dataset_type; - -local_dataset_type * local_dataset_alloc_copy( local_dataset_type * src_dataset , const char * copy_name ); -local_dataset_type * local_dataset_alloc( const char * name ); -void local_dataset_free( local_dataset_type * dataset ); -void local_dataset_free__( void * arg ); -void local_dataset_add_node(local_dataset_type * dataset, const char *node_key); -void local_dataset_del_node( local_dataset_type * dataset , const char * node_key); -void local_dataset_clear( local_dataset_type * dataset); -const char * local_dataset_get_name( const local_dataset_type * dataset); -void local_dataset_fprintf( const local_dataset_type * dataset , FILE * stream); -void local_dataset_summary_fprintf( const local_dataset_type * dataset , FILE * stream); -active_list_type * local_dataset_get_node_active_list(const local_dataset_type * dataset , const char * node_key ); -stringlist_type * local_dataset_alloc_keys( const local_dataset_type * dataset ); -int local_dataset_get_size( const local_dataset_type * dataset ); -void local_dataset_del_node( local_dataset_type * dataset , const char * node_key); -void local_dataset_clear( local_dataset_type * dataset); -bool local_dataset_has_key(const local_dataset_type * dataset, const char * key); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/local_ministep.h b/ThirdParty/Ert/libenkf/include/ert/enkf/local_ministep.h deleted file mode 100644 index cedad78346..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/local_ministep.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_ministep.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_LOCAL_MINISTEP_H -#define ERT_LOCAL_MINISTEP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -#include -#include -#include -#include - -typedef struct local_ministep_struct local_ministep_type; - -local_ministep_type * local_ministep_alloc(const char * name, analysis_module_type* analysis_module); -void local_ministep_free(local_ministep_type * ministep); -void local_ministep_free__(void * arg); -void local_ministep_add_obs(local_ministep_type * ministep, const char * obs_key); -active_list_type * local_ministep_get_node_active_list(const local_ministep_type * ministep , const char * node_key ); -hash_iter_type * local_ministep_alloc_dataset_iter( const local_ministep_type * ministep ); -stringlist_type * local_ministep_alloc_data_keys( const local_ministep_type * ministep ); -bool local_ministep_has_data_key(const local_ministep_type * ministep , const char * key); -local_ministep_type * local_ministep_alloc_copy( const local_ministep_type * src , const char * name); -void local_ministep_del_obs( local_ministep_type * ministep , const char * obs_key); -void local_ministep_del_node( local_ministep_type * ministep , const char * node_key); -const char * local_ministep_get_name( const local_ministep_type * ministep ); -void local_ministep_clear_nodes( local_ministep_type * ministep); -void local_ministep_clear_observations( local_ministep_type * ministep); -void local_ministep_fprintf( const local_ministep_type * ministep , FILE * stream ); -void local_ministep_summary_fprintf( const local_ministep_type * ministep , FILE * stream); -void local_ministep_add_dataset( local_ministep_type * ministep , const local_dataset_type * dataset); -void local_ministep_add_obsdata( local_ministep_type * ministep , local_obsdata_type * obsdata); -void local_ministep_add_obsdata_node( local_ministep_type * ministep , local_obsdata_node_type * obsdatanode); -local_obsdata_type * local_ministep_get_obsdata(const local_ministep_type * ministep); -local_dataset_type * local_ministep_get_dataset( const local_ministep_type * ministep, const char * dataset_name); -bool local_ministep_has_dataset( const local_ministep_type * ministep, const char * dataset_name); -int local_ministep_get_num_dataset( const local_ministep_type * ministep ); -bool local_ministep_has_analysis_module( const local_ministep_type * ministep ); -analysis_module_type* local_ministep_get_analysis_module( const local_ministep_type * ministep ); - -UTIL_SAFE_CAST_HEADER(local_ministep); -UTIL_IS_INSTANCE_HEADER(local_ministep); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/local_obsdata.h b/ThirdParty/Ert/libenkf/include/ert/enkf/local_obsdata.h deleted file mode 100644 index 9517d513f0..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/local_obsdata.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'local_obsdata.h' - - ERT 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. - - ERT 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 at - for more details. -*/ -#ifndef ERT_LOCAL_OBSDATA_H -#define ERT_LOCAL_OBSDATA_H - -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include - -#include - -typedef struct local_obsdata_struct local_obsdata_type; - - void local_obsdata_free__( void * arg); - bool local_obsdata_has_node( const local_obsdata_type * data , const char * key); - local_obsdata_type * local_obsdata_alloc_copy( const local_obsdata_type * src, const char * target_key); - local_obsdata_type * local_obsdata_alloc( const char * name ); - void local_obsdata_free( local_obsdata_type * data ); - int local_obsdata_get_size( const local_obsdata_type * data ); - bool local_obsdata_add_node( local_obsdata_type * data , local_obsdata_node_type * node ); - local_obsdata_node_type * local_obsdata_iget( const local_obsdata_type * data , int index); - local_obsdata_type * local_obsdata_alloc_wrapper( local_obsdata_node_type * node ); - const char * local_obsdata_get_name( const local_obsdata_type * data); - local_obsdata_node_type * local_obsdata_get( const local_obsdata_type * data , const char * key); - void local_obsdata_clear( local_obsdata_type * data ); - void local_obsdata_del_node( local_obsdata_type * data , const char * key); - void local_obsdata_reset_tstep_list( local_obsdata_type * data , const int_vector_type * step_list); - active_list_type * local_obsdata_get_node_active_list(const local_obsdata_type * obsdata , const char * obs_key ); - void local_obsdata_fprintf( const local_obsdata_type * obsdata , FILE * stream ); - void local_obsdata_summary_fprintf( const local_obsdata_type * obsdata , FILE * stream); - -UTIL_IS_INSTANCE_HEADER( local_obsdata ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/local_obsdata_node.h b/ThirdParty/Ert/libenkf/include/ert/enkf/local_obsdata_node.h deleted file mode 100644 index ab1bd33c19..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/local_obsdata_node.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'local_obsdata_node.h' - - ERT 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. - - ERT 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 at - for more details. -*/ -#ifndef ERT_LOCAL_OBSDATA_NODE_H -#define ERT_LOCAL_OBSDATA_NODE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - - - typedef struct local_obsdata_node_struct local_obsdata_node_type; - - local_obsdata_node_type * local_obsdata_node_alloc( const char * obs_key , bool all_timestep_active ); - local_obsdata_node_type * local_obsdata_node_alloc_copy( const local_obsdata_node_type * src); - const char * local_obsdata_node_get_key( const local_obsdata_node_type * node ); - void local_obsdata_node_free( local_obsdata_node_type * node ); - void local_obsdata_node_free__( void * arg ); - active_list_type * local_obsdata_node_get_active_list( const local_obsdata_node_type * node ); - void local_obsdata_node_copy_active_list( local_obsdata_node_type * node , const active_list_type * active_list); - void local_obsdata_node_add_tstep( local_obsdata_node_type * node, int tstep); - void local_obsdata_node_add_range( local_obsdata_node_type * node, int step1, int step2); - - bool local_obsdata_node_tstep_active( const local_obsdata_node_type * node , int tstep ); - bool local_obsdata_node_all_timestep_active( const local_obsdata_node_type * node); - bool local_obsdata_node_has_tstep( const local_obsdata_node_type * node , int tstep); - void local_obsdata_node_reset_tstep_list( local_obsdata_node_type * node , const int_vector_type * step_list); - void local_obsdata_node_set_all_timestep_active( local_obsdata_node_type * node, bool flag); - - UTIL_IS_INSTANCE_HEADER( local_obsdata_node ); - UTIL_SAFE_CAST_HEADER( local_obsdata_node ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/local_updatestep.h b/ThirdParty/Ert/libenkf/include/ert/enkf/local_updatestep.h deleted file mode 100644 index a56de59c75..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/local_updatestep.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_updatestep.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_LOCAL_UPDATESTEP_H -#define ERT_LOCAL_UPDATESTEP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -typedef struct local_updatestep_struct local_updatestep_type; - -local_updatestep_type * local_updatestep_alloc( const char * name ); -void local_updatestep_free__(void * arg); -void local_updatestep_add_ministep( local_updatestep_type * updatestep , local_ministep_type * ministep); -local_ministep_type * local_updatestep_iget_ministep( const local_updatestep_type * updatestep , int index); -local_obsdata_type * local_updatestep_iget_obsdata( const local_updatestep_type * updatestep , int index); -int local_updatestep_get_num_ministep( const local_updatestep_type * updatestep ); -local_updatestep_type * local_updatestep_alloc_copy( const local_updatestep_type * src , const char * name ); -void local_updatestep_fprintf( const local_updatestep_type * updatestep , FILE * stream); -const char * local_updatestep_get_name( const local_updatestep_type * updatestep ); -bool local_updatestep_has_data_key( const local_updatestep_type * update_step , const char * key); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/meas_data.h b/ThirdParty/Ert/libenkf/include/ert/enkf/meas_data.h deleted file mode 100644 index 9a7e12b234..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/meas_data.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'meas_data.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_MEAS_DATA_H -#define ERT_MEAS_DATA_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include -#include -#include - -typedef struct meas_data_struct meas_data_type; -typedef struct meas_block_struct meas_block_type; - -UTIL_IS_INSTANCE_HEADER( meas_data ); -UTIL_SAFE_CAST_HEADER( meas_block ); - -bool meas_block_iens_active( const meas_block_type * meas_block , int iens); -void meas_block_iset( meas_block_type * meas_block , int iens , int iobs , double value); -double meas_block_iget( const meas_block_type * meas_block , int iens , int iobs); -double meas_block_iget_ens_mean( meas_block_type * meas_block , int iobs ); -double meas_block_iget_ens_std( meas_block_type * meas_block , int iobs); -void meas_block_deactivate( meas_block_type * meas_block , int iobs ); -bool meas_block_iget_active( const meas_block_type * meas_block , int iobs); -void meas_data_fprintf( const meas_data_type * matrix , FILE * stream); - -void meas_data_reset(meas_data_type * ); - meas_data_type * meas_data_alloc( const bool_vector_type * ens_mask); -void meas_data_free(meas_data_type * ); -void meas_data_add(meas_data_type * , int , double ); -matrix_type * meas_data_allocS(const meas_data_type * matrix); -int meas_data_get_active_obs_size( const meas_data_type * matrix ); -void meas_data_deactivate(meas_data_type * meas_data, int index); -int meas_data_get_active_ens_size( const meas_data_type * meas_data ); -int meas_data_get_nrobs( const meas_data_type * meas_data ); -meas_block_type * meas_data_add_block( meas_data_type * matrix , const char * obs_key , int report_step , int obs_size); -int meas_data_get_num_blocks( const meas_data_type * meas_block ); -meas_block_type * meas_data_iget_block( const meas_data_type * matrix , int block_mnr); -const meas_block_type * meas_data_iget_block_const( const meas_data_type * matrix , int block_nr ); -int meas_block_get_total_obs_size( const meas_block_type * meas_block ); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/member_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/member_config.h deleted file mode 100644 index 64386e99d2..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/member_config.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'member_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_MEMBER_CONFIG_H -#define ERT_MEMBER_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -#include - -#include -#include -#include -#include - - - -typedef struct member_config_struct member_config_type; - - const char * member_config_get_jobname( const member_config_type * member_config ); - void member_config_set_keep_runpath(member_config_type * member_config , keep_runpath_type keep_runpath); - keep_runpath_type member_config_get_keep_runpath(const member_config_type * member_config); - int member_config_get_iens( const member_config_type * member_config ); - const char * member_config_update_jobname(member_config_type * member_config , const char * jobname_fmt , const subst_list_type * subst_list); - const char * member_config_update_eclbase(member_config_type * member_config , const ecl_config_type * ecl_config , const subst_list_type * subst_list); - void member_config_free(member_config_type * member_config) ; - const char * member_config_get_eclbase( const member_config_type * member_config ); - const char * member_config_get_casename( const member_config_type * member_config ); - - bool member_config_pre_clear_runpath(const member_config_type * member_config); - void member_config_set_pre_clear_runpath(member_config_type * member_config , bool pre_clear_runpath); - - - member_config_type * member_config_alloc(int iens , - const char * casename , - bool pre_clear_runpath , - keep_runpath_type keep_runpath , - const ecl_config_type * ecl_config , - const ensemble_config_type * ensemble_config); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ensemble.h b/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ensemble.h deleted file mode 100644 index e6ed2ebcd0..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ensemble.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'misfit_table.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_MISFIT_ENSEMBLE_H -#define ERT_MISFIT_ENSEMBLE_H - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#define MISFIT_DEFAULT_RANKING_KEY "DEFAULT" -#include - - - - void misfit_ensemble_fread( misfit_ensemble_type * misfit_ensemble , FILE * stream ); - void misfit_ensemble_clear( misfit_ensemble_type * table); - misfit_ensemble_type * misfit_ensemble_alloc( ); - void misfit_ensemble_free( misfit_ensemble_type * table ); - void misfit_ensemble_fwrite( const misfit_ensemble_type * misfit_ensemble , FILE * stream); - bool misfit_ensemble_initialized( const misfit_ensemble_type * misfit_ensemble ); - - void misfit_ensemble_initialize( misfit_ensemble_type * misfit_ensemble , - const ensemble_config_type * ensemble_config , - const enkf_obs_type * enkf_obs , - enkf_fs_type * fs , - int ens_size , - int history_length, - bool force_init); - - void misfit_ensemble_set_ens_size( misfit_ensemble_type * misfit_ensemble , int ens_size); - int misfit_ensemble_get_ens_size( const misfit_ensemble_type * misfit_ensemble ); - - misfit_member_type * misfit_ensemble_iget_member( const misfit_ensemble_type * table , int iens); - - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ensemble_typedef.h b/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ensemble_typedef.h deleted file mode 100644 index 2c5adff7bf..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ensemble_typedef.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef ERT_MISFIT_ENSEMBLE_TYPEDEF_H -#define ERT_MISFIT_ENSEMBLE_TYPEDEF_H - -typedef struct misfit_ensemble_struct misfit_ensemble_type; - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_member.h b/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_member.h deleted file mode 100644 index 72d11ec372..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_member.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'misfit_member.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_MISFIT_MEMBER_H -#define ERT_MISFIT_MEMBER_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - - typedef struct misfit_member_struct misfit_member_type; - misfit_ts_type * misfit_member_get_ts( const misfit_member_type * member , const char * obs_key ); - bool misfit_member_has_ts( const misfit_member_type * member , const char * obs_key ); - misfit_member_type * misfit_member_fread_alloc( FILE * stream ); - void misfit_member_fwrite( const misfit_member_type * node , FILE * stream ); - void misfit_member_update( misfit_member_type * node , const char * obs_key , int history_length , int iens , const double ** work_chi2); - void misfit_member_free__( void * node ); - misfit_member_type * misfit_member_alloc(int iens); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ranking.h b/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ranking.h deleted file mode 100644 index 447ddfed3e..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ranking.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'misfit_ranking.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_MISFIT_RANKING_H -#define ERT_MISFIT_RANKING_H - -#include -#include -#include - -#include -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - - typedef struct misfit_ranking_struct misfit_ranking_type; - - UTIL_IS_INSTANCE_HEADER( misfit_ranking ); - UTIL_SAFE_CAST_HEADER( misfit_ranking ); - - void misfit_ranking_fprintf( const misfit_ranking_type * misfit_ranking , const char * filename); - void misfit_ranking_display( const misfit_ranking_type * misfit_ranking , FILE * stream); - misfit_ranking_type * misfit_ranking_alloc(const misfit_ensemble_type * ensemble , const stringlist_type * sort_keys , const int_vector_type * steps, const char * ranking_key); - void misfit_ranking_free( misfit_ranking_type * misfit_ranking ); - void misfit_ranking_free__( void * arg ); - const perm_vector_type * misfit_ranking_get_permutation( const misfit_ranking_type * misfit_ranking ); - void misfit_ranking_iset_invalid( misfit_ranking_type * misfit_ranking , int iens ); - void misfit_ranking_iset( misfit_ranking_type * misfit_ranking , int iens , hash_type * obs_hash , double total_misfit); - void misfit_ranking_init_sort( misfit_ranking_type * misfit_ranking ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ts.h b/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ts.h deleted file mode 100644 index ad3994045a..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/misfit_ts.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'misfit_ts.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_MISFIT_TS_H -#define ERT_MISFIT_TS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - - typedef struct misfit_ts_struct misfit_ts_type; - - - void misfit_ts_fwrite( const misfit_ts_type * misfit_ts , FILE * stream ); - double misfit_ts_eval( const misfit_ts_type * ts , const int_vector_type * steps ); - misfit_ts_type * misfit_ts_alloc(int history_length); - misfit_ts_type * misfit_ts_fread_alloc( FILE * stream ); - void misfit_ts_free__( void * vector ); - void misfit_ts_iset( misfit_ts_type * vector , int time_index , double value ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/model_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/model_config.h deleted file mode 100644 index 6f07abb516..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/model_config.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'model_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_MODEL_CONFIG_H -#define ERT_MODEL_CONFIG_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#include - -#include -#include -#include - - typedef struct model_config_struct model_config_type; - - const char * model_config_get_jobname_fmt( const model_config_type * model_config ); - void model_config_set_jobname_fmt( model_config_type * model_config , const char * jobname_fmt); - const char * model_config_get_case_table_file( const model_config_type * model_config ); - void model_config_set_case_table( model_config_type * model_config , int ens_size , const char * case_table_file ); - void model_config_set_enspath( model_config_type * model_config , const char * enspath); - void model_config_set_rftpath( model_config_type * model_config , const char * rftpath); - void model_config_set_dbase_type( model_config_type * model_config , const char * dbase_type_string); - void * model_config_get_dbase_args( const model_config_type * model_config ); - const char * model_config_get_enspath( const model_config_type * model_config); - const char * model_config_get_rftpath( const model_config_type * model_config); - fs_driver_impl model_config_get_dbase_type(const model_config_type * model_config ); - const ecl_sum_type * model_config_get_refcase( const model_config_type * model_config ); - void model_config_init_internalization( model_config_type * ); - void model_config_set_internalize_state( model_config_type * , int ); - void model_config_set_load_state( model_config_type * , int ); - int model_config_get_history_length(const model_config_type * ); - bool model_config_has_prediction(const model_config_type * ); - bool model_config_has_history(const model_config_type * config); - int model_config_get_last_history_restart(const model_config_type * ); - time_map_type * model_config_get_external_time_map( const model_config_type * config); - void model_config_init(model_config_type * model_config , const config_content_type * , int ens_size , const ext_joblist_type * , int , const sched_file_type * , const ecl_sum_type * refcase); - void model_config_free(model_config_type *); - bool model_config_runpath_requires_iter( const model_config_type * model_config ); - path_fmt_type * model_config_get_runpath_fmt(const model_config_type * ); - history_type * model_config_get_history(const model_config_type * ); - forward_model_type * model_config_get_forward_model( const model_config_type * ); - bool model_config_internalize_state( const model_config_type *, int ); - bool model_config_load_state( const model_config_type *, int ); - const char * model_config_iget_casename( const model_config_type * model_config , int index); - //void model_config_set_max_resample( model_config_type * model_config , int max_resample ); - //int model_config_get_max_resample(const model_config_type * model_config ); - void model_config_set_max_internal_submit(model_config_type * config, int max_resample); - int model_config_get_max_internal_submit( const model_config_type * config ); - bool model_config_select_runpath( model_config_type * model_config , const char * path_key); - void model_config_add_runpath( model_config_type * model_config , const char * path_key , const char * fmt ); - const char * model_config_get_runpath_as_char( const model_config_type * model_config ); - history_source_type model_config_get_history_source( const model_config_type * model_config ); - void model_config_set_refcase( model_config_type * model_config , const ecl_sum_type * refcase ); - void model_config_fprintf_config( const model_config_type * model_config , int ens_size ,FILE * stream ); - model_config_type * model_config_alloc(); - bool model_config_select_history( model_config_type * model_config , history_source_type source_type, const sched_file_type * schede_file , const ecl_sum_type * refcase); - void model_config_set_runpath(model_config_type * model_config , const char * fmt); - void model_config_set_gen_kw_export_file( model_config_type * model_config, const char * file_name); - const char * model_config_get_gen_kw_export_file( const model_config_type * model_config); - - UTIL_IS_INSTANCE_HEADER( model_config); - -#ifdef __cplusplus -} -#endif -#endif - - diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/obs_data.h b/ThirdParty/Ert/libenkf/include/ert/enkf/obs_data.h deleted file mode 100644 index 7d250fc2ef..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/obs_data.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'obs_data.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_OBS_DATA_H -#define ERT_OBS_DATA_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -#include -#include -#include - -#include -#include - -typedef struct obs_data_struct obs_data_type; -typedef struct obs_block_struct obs_block_type; - -active_type obs_block_iget_active_mode( const obs_block_type * obs_block , int iobs); -const char * obs_data_iget_keyword( const obs_data_type * obs_data , int index ); -double obs_data_iget_value( const obs_data_type * obs_data , int index ); -double obs_data_iget_std( const obs_data_type * obs_data , int index ); -active_type obs_data_iget_active_mode( const obs_data_type * obs_data , int index ); -void obs_block_deactivate( obs_block_type * obs_block , int iobs , bool verbose , const char * msg); -int obs_block_get_size( const obs_block_type * obs_block ); -void obs_block_iset( obs_block_type * obs_block , int iobs , double value , double std); -void obs_block_iset_missing( obs_block_type * obs_block , int iobs ); - -double obs_block_iget_std( const obs_block_type * obs_block , int iobs); -double obs_block_iget_value( const obs_block_type * obs_block , int iobs); -bool obs_block_iget_active( const obs_block_type * obs_block , int iobs); - - -obs_block_type * obs_data_iget_block( obs_data_type * obs_data , int index ); -const obs_block_type * obs_data_iget_block_const( const obs_data_type * obs_data , int block_nr); -obs_block_type * obs_data_get_block( obs_data_type * obs_data , const char * obs_key ); -obs_block_type * obs_data_add_block( obs_data_type * obs_data , const char * obs_key , int obs_size , matrix_type * error_covar , bool error_covar_owner); - -obs_data_type * obs_data_alloc(double global_std_scaling); -void obs_data_free(obs_data_type *); -void obs_data_reset(obs_data_type * obs_data); -matrix_type * obs_data_allocD(const obs_data_type * obs_data , const matrix_type * E , const matrix_type * S); -matrix_type * obs_data_allocR(const obs_data_type * obs_data ); -matrix_type * obs_data_allocdObs(const obs_data_type * obs_data ); -//matrix_type * obs_data_alloc_innov(const obs_data_type * obs_data , const meas_data_type * meas_data , int active_size); -matrix_type * obs_data_allocE(const obs_data_type * obs_data , rng_type * rng , int active_ens_size); -matrix_type * obs_data_allocE_non_centred(const obs_data_type * obs_data , rng_type * rng , int ens_size); - void obs_data_scale(const obs_data_type * obs_data , matrix_type *S , matrix_type *E , matrix_type *D , matrix_type *R , matrix_type * O); -void obs_data_scale_kernel(const obs_data_type * obs_data , matrix_type *S , matrix_type *E , matrix_type *D , double *dObs); -void obs_data_fprintf(const obs_data_type * , FILE *); -void obs_data_iget_value_std(const obs_data_type * obs_data , int index , double * value , double * std); -int obs_data_get_active_size(const obs_data_type * obs_data ); -int obs_data_get_total_size( const obs_data_type * obs_data ); -int obs_data_get_num_blocks( const obs_data_type * obs_data ); -const char * obs_block_get_key( const obs_block_type * obs_block) ; -double obs_data_iget_value( const obs_data_type * obs_data , int total_index ); -double obs_data_iget_std( const obs_data_type * obs_data , int total_index ); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/obs_vector.h b/ThirdParty/Ert/libenkf/include/ert/enkf/obs_vector.h deleted file mode 100644 index 2c1224a3aa..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/obs_vector.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'obs_vector.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_OBS_VECTOR_H -#define ERT_OBS_VECTOR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include - -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - typedef void (obs_free_ftype) (void *); - typedef void (obs_get_ftype) (const void * , obs_data_type * , enkf_fs_type *, int , const active_list_type * ); - typedef void (obs_meas_ftype) (const void * , const void *, node_id_type , meas_data_type * , const active_list_type * ); - typedef void (obs_user_get_ftype) (void * , const char * , double * , double * , bool *); - typedef void (obs_update_std_scale_ftype) (void * , double , const active_list_type * ); - typedef double (obs_chi2_ftype) (const void * , const void *, node_id_type ); - - typedef enum { GEN_OBS = 1, - SUMMARY_OBS = 2, - BLOCK_OBS = 3} obs_impl_type; - - typedef struct obs_vector_struct obs_vector_type; - - - void obs_vector_clear_nodes( obs_vector_type * obs_vector ); - void obs_vector_del_node(obs_vector_type * obs_vector , int index); - void obs_vector_free(obs_vector_type * ); - int obs_vector_get_num_active(const obs_vector_type * ); - bool obs_vector_iget_active(const obs_vector_type * , int ); - void obs_vector_iget_observations(const obs_vector_type * , int , obs_data_type * , const active_list_type * active_list, enkf_fs_type * fs); - bool obs_vector_has_data( const obs_vector_type * obs_vector , const bool_vector_type * active_mask , enkf_fs_type * fs); - void obs_vector_measure(const obs_vector_type * , enkf_fs_type * fs, int report_step , const int_vector_type * ens_active_list , meas_data_type * , const active_list_type * active_list); - const char * obs_vector_get_state_kw(const obs_vector_type * ); - const char * obs_vector_get_key(const obs_vector_type * ); - obs_impl_type obs_vector_get_impl_type(const obs_vector_type * ); - int obs_vector_get_active_report_step(const obs_vector_type * ); - const int_vector_type * obs_vector_get_step_list(const obs_vector_type * vector); - void obs_vector_user_get(const obs_vector_type * obs_vector , const char * index_key , int report_step , double * value , double * std , bool * valid); - int obs_vector_get_next_active_step(const obs_vector_type * , int ); - void * obs_vector_iget_node(const obs_vector_type * , int ); - obs_vector_type * obs_vector_alloc_from_GENERAL_OBSERVATION(const conf_instance_type * , time_map_type * obs_time , const ensemble_config_type * ); - void obs_vector_load_from_SUMMARY_OBSERVATION(obs_vector_type * obs_vector , const conf_instance_type * , time_map_type * obs_time , ensemble_config_type * ); - bool obs_vector_load_from_HISTORY_OBSERVATION(obs_vector_type * obs_vector , const conf_instance_type * , time_map_type * obs_time , const history_type * , ensemble_config_type * , double std_cutoff ); - obs_vector_type * obs_vector_alloc_from_BLOCK_OBSERVATION(const conf_instance_type * , const ecl_grid_type * grid , time_map_type * obs_time , const ecl_sum_type * refcase , ensemble_config_type * ); - void obs_vector_set_config_node(obs_vector_type * , const enkf_config_node_type * ); - obs_vector_type * obs_vector_alloc(obs_impl_type obs_type , const char * obs_key , enkf_config_node_type * config_node, int num_reports); - void obs_vector_scale_std(obs_vector_type * obs_vector, const local_obsdata_node_type * local_node , double std_multiplier); - void obs_vector_install_node(obs_vector_type * obs_vector , int obs_index , void * node ); - - double obs_vector_chi2(const obs_vector_type * , enkf_fs_type * , node_id_type node_id); - - void obs_vector_ensemble_chi2(const obs_vector_type * obs_vector , - enkf_fs_type * fs, - bool_vector_type * valid , - int step1 , int step2 , - int iens1 , int iens2 , - double ** chi2); - - double obs_vector_total_chi2(const obs_vector_type * , enkf_fs_type * , int ); - void obs_vector_ensemble_total_chi2(const obs_vector_type * , enkf_fs_type * , int , double * ); - enkf_config_node_type * obs_vector_get_config_node(const obs_vector_type * ); - const char * obs_vector_get_obs_key( const obs_vector_type * obs_vector); - local_obsdata_node_type * obs_vector_alloc_local_node(const obs_vector_type * obs_vector); - - - - UTIL_IS_INSTANCE_HEADER(obs_vector); - UTIL_SAFE_CAST_HEADER(obs_vector); - VOID_FREE_HEADER(obs_vector); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/pca_plot_data.h b/ThirdParty/Ert/libenkf/include/ert/enkf/pca_plot_data.h deleted file mode 100644 index d758e78473..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/pca_plot_data.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'pca_plot_data.h' - - ERT 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. - - ERT 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 at - for more details. -*/ -#ifndef ERT_PCA_PLOT_DATA_H -#define ERT_PCA_PLOT_DATA_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include - - typedef struct pca_plot_data_struct pca_plot_data_type; - - pca_plot_data_type * pca_plot_data_alloc( const char * name , const matrix_type * PC, const matrix_type * PC_obs, const double_vector_type * singular_values); - const double_vector_type * pca_plot_data_get_singular_values( const pca_plot_data_type * plot_data ); - void pca_plot_data_free( pca_plot_data_type * plot_data ); - const pca_plot_vector_type * pca_plot_data_iget_vector( const pca_plot_data_type * plot_data , int ivec); - int pca_plot_data_get_size( const pca_plot_data_type * plot_data ); - const char * pca_plot_data_get_name( const pca_plot_data_type * plot_data ); - int pca_plot_data_get_ens_size( const pca_plot_data_type * plot_data ); - void pca_plot_data_free__( void * arg ); - - UTIL_IS_INSTANCE_HEADER( pca_plot_data ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/pca_plot_vector.h b/ThirdParty/Ert/libenkf/include/ert/enkf/pca_plot_vector.h deleted file mode 100644 index 21ff2b4e65..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/pca_plot_vector.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'pca_plot_vector.h' - - ERT 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. - - ERT 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 at - for more details. -*/ -#ifndef ERT_PCA_PLOT_VECTOR_H -#define ERT_PCA_PLOT_VECTOR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - - typedef struct pca_plot_vector_struct pca_plot_vector_type; - - pca_plot_vector_type * pca_plot_vector_alloc( int component , const matrix_type * PC, const matrix_type * PC_obs, const double_vector_type * singular_values); - - void pca_plot_vector_free( pca_plot_vector_type * plot_vector ); - bool pca_plot_assert_input( const matrix_type * PC, const matrix_type * PC_obs , const double_vector_type * singular_values); - void pca_plot_vector_free__( void * arg ); - double pca_plot_vector_get_obs_value( const pca_plot_vector_type * vector ); - double pca_plot_vector_get_singular_value( const pca_plot_vector_type * vector ); - double pca_plot_vector_iget_sim_value( const pca_plot_vector_type * vector , int sim_index); - int pca_plot_vector_get_size( const pca_plot_vector_type * vector ); - - UTIL_IS_INSTANCE_HEADER( pca_plot_vector ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/plain_driver.h b/ThirdParty/Ert/libenkf/include/ert/enkf/plain_driver.h deleted file mode 100644 index b66774e9e9..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/plain_driver.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'plain_driver.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_PLAIN_DRIVER_H -#define ERT_PLAIN_DRIVER_H - -#include -#include - -#include - -typedef struct plain_driver_struct plain_driver_type; - -void plain_driver_create_fs( FILE * stream , fs_driver_enum driver_type , const char * node_fmt , const char * vector_fmt); -void * plain_driver_open(FILE * fstab_stream , const char * path); -void plain_driver_fskip(FILE * fstab_stream ); - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/plain_driver_obs.h b/ThirdParty/Ert/libenkf/include/ert/enkf/plain_driver_obs.h deleted file mode 100644 index cc7987bd15..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/plain_driver_obs.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'plain_driver_obs.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_PLAIN_DRIVER_OBS_H -#define ERT_PLAIN_DRIVER_OBS_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -typedef struct plain_driver_obs_struct plain_driver_obs_type; - -plain_driver_obs_type * plain_driver_obs_fread_alloc(const char * , FILE * ); - void * plain_driver_obs_alloc(const char * , const char *); -void plain_driver_obs_README(const char * ); -void plain_driver_obs_fwrite_mount_info(FILE * stream , const char * ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/plot_settings.h b/ThirdParty/Ert/libenkf/include/ert/enkf/plot_settings.h deleted file mode 100644 index eb8f762ae3..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/plot_settings.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'plot_settings.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_PLOT_SETTINGS_H -#define ERT_PLOT_SETTINGS_H - -#include -#include - -void plot_settings_init(config_settings_type * setting); -void plot_settings_add_config_items( config_parser_type * config ); - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/ranking_common.h b/ThirdParty/Ert/libenkf/include/ert/enkf/ranking_common.h deleted file mode 100644 index d9e423dccb..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/ranking_common.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'ranking_common.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RANKING_COMMON_H -#define ERT_RANKING_COMMON_H -#include - -#define INVALID_RANKING_VALUE INFINITY - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/ranking_table.h b/ThirdParty/Ert/libenkf/include/ert/enkf/ranking_table.h deleted file mode 100644 index 5b2753fd7d..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/ranking_table.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'ranking_table.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_RANKING_TABLE_H -#define ERT_RANKING_TABLE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -#include - - typedef struct ranking_table_struct ranking_table_type; - - void ranking_table_set_ens_size( ranking_table_type * table, int ens_size); - ranking_table_type * ranking_table_alloc( ) ; - void ranking_table_free( ranking_table_type * table ); - - void ranking_table_add_data_ranking( ranking_table_type * ranking_table , - bool sort_increasing , - const char * ranking_key , - const char * user_key , - const char * key_index , - enkf_fs_type * fs , - const enkf_config_node_type * config_node , - int step); - - bool ranking_table_has_ranking( const ranking_table_type * ranking_table , const char * ranking_key ); - bool ranking_table_display_ranking( const ranking_table_type * ranking_table , const char * ranking_key ); - bool ranking_table_fwrite_ranking( const ranking_table_type * ranking_table , const char * ranking_key, const char * filename ); - - void ranking_table_add_misfit_ranking( ranking_table_type * ranking_table , - const misfit_ensemble_type * misfit_ensemble , - const stringlist_type * obs_keys , - const int_vector_type * steps, - const char * ranking_key); - - - int ranking_table_get_size( const ranking_table_type * ranking_table ); - const perm_vector_type * ranking_table_get_permutation( const ranking_table_type * ranking_table , const char * ranking_key); - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/rng_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/rng_config.h deleted file mode 100644 index 695be37e12..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/rng_config.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rng_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RNG_CONFIG_H -#define ERT_RNG_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include - -typedef struct rng_config_struct rng_config_type; - - void rng_config_fprintf_config( rng_config_type * rng_config , FILE * stream ); - void rng_config_init( rng_config_type * rng_config , config_content_type * config ); - void rng_config_set_type( rng_config_type * rng_config , rng_alg_type type); - rng_alg_type rng_config_get_type(const rng_config_type * rng_config ); - const char * rng_config_get_seed_load_file( const rng_config_type * rng_config ); - void rng_config_set_seed_load_file( rng_config_type * rng_config , const char * seed_load_file); - const char * rng_config_get_seed_store_file( const rng_config_type * rng_config ); - void rng_config_set_seed_store_file( rng_config_type * rng_config , const char * seed_store_file); - rng_config_type * rng_config_alloc( ); - void rng_config_free( rng_config_type * rng); - void rng_config_add_config_items( config_parser_type * config ); - rng_type * rng_config_alloc_init_rng( const rng_config_type * rng_config); - void rng_config_init_rng(const rng_config_type * rng_config, rng_type * rng ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/run_arg.h b/ThirdParty/Ert/libenkf/include/ert/enkf/run_arg.h deleted file mode 100644 index 246e14062b..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/run_arg.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'run_arg.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RUN_ARG_H -#define ERT_RUN_ARG_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include -#include -#include - - - -UTIL_SAFE_CAST_HEADER( run_arg ); -UTIL_IS_INSTANCE_HEADER( run_arg ); - - - run_arg_type * run_arg_alloc_ENSEMBLE_EXPERIMENT(enkf_fs_type * fs , int iens , int iter , const char * runpath); - run_arg_type * run_arg_alloc_INIT_ONLY(enkf_fs_type * init_fs , int iens , int iter , const char * runpath); - run_arg_type * run_arg_alloc_SMOOTHER_RUN(enkf_fs_type * simulate_fs , enkf_fs_type * update_target_fs , int iens , int iter , const char * runpath); - - int run_arg_get_step1( const run_arg_type * run_arg ); - int run_arg_get_step2( const run_arg_type * run_arg ); - run_mode_type run_arg_get_run_mode( const run_arg_type * run_arg ); - int run_arg_get_load_start( const run_arg_type * run_arg ); - int run_arg_get_iens( const run_arg_type * run_arg ); - int run_arg_get_iter( const run_arg_type * run_arg ); - void run_arg_increase_submit_count( run_arg_type * run_arg ); - void run_arg_set_queue_index( run_arg_type * run_arg , int queue_index); - - void run_arg_free(run_arg_type * run_arg); - void run_arg_free__(void * arg); - const char * run_arg_get_runpath( const run_arg_type * run_arg); - void run_arg_complete_run(run_arg_type * run_arg); - run_status_type run_arg_get_run_status( const run_arg_type * run_arg ); - - int run_arg_get_queue_index( const run_arg_type * run_arg ); - bool run_arg_is_submitted( const run_arg_type * run_arg ); - - bool run_arg_can_retry( const run_arg_type * run_arg ); - - run_status_type run_arg_get_run_status( const run_arg_type * run_arg); - void run_arg_set_run_status( run_arg_type * run_arg , run_status_type run_status); - - enkf_fs_type * run_arg_get_init_fs(const run_arg_type * run_arg); - enkf_fs_type * run_arg_get_update_target_fs(const run_arg_type * run_arg); - enkf_fs_type * run_arg_get_result_fs(const run_arg_type * run_arg); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/run_arg_type.h b/ThirdParty/Ert/libenkf/include/ert/enkf/run_arg_type.h deleted file mode 100644 index 18bdd51f67..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/run_arg_type.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'run_arg_type.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RUN_ARG_TYPE_H -#define ERT_RUN_ARG_TYPE_H - -typedef struct run_arg_struct run_arg_type; - -#endif - diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/runpath_list.h b/ThirdParty/Ert/libenkf/include/ert/enkf/runpath_list.h deleted file mode 100644 index bf053e37d2..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/runpath_list.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - The file 'runpath_list.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RUNPATH_LIST_H -#define ERT_RUNPATH_LIST_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define RUNPATH_LIST_DEFAULT_LINE_FMT "%03d %s %s %03d\n" - - - typedef struct runpath_list_struct runpath_list_type; - - void runpath_list_free( runpath_list_type * list ); - runpath_list_type * runpath_list_alloc(const char * export_file ); - int runpath_list_size( const runpath_list_type * list ); - void runpath_list_add( runpath_list_type * list , int iens , int iter, const char * runpath , const char * basename); - void runpath_list_clear( runpath_list_type * list ); - int runpath_list_iget_iens( runpath_list_type * list , int index); - int runpath_list_iget_iter( runpath_list_type * list , int index); - char * runpath_list_iget_runpath( runpath_list_type * list , int index); - char * runpath_list_iget_basename( runpath_list_type * list , int index); - void runpath_list_set_line_fmt( runpath_list_type * list , const char * line_fmt ); - const char * runpath_list_get_line_fmt( const runpath_list_type * list ); - void runpath_list_fprintf( runpath_list_type * list); - const char * runpath_list_get_export_file( const runpath_list_type * list ); - void runpath_list_set_export_file( runpath_list_type * list , const char * export_file ); - - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/scalar_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/scalar_config.h deleted file mode 100644 index 08f94d08b0..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/scalar_config.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'scalar_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCALAR_CONFIG_H -#define ERT_SCALAR_CONFIG_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -typedef struct scalar_config_struct scalar_config_type; - - - -scalar_config_type * scalar_config_alloc_empty(int); -void scalar_config_free(scalar_config_type *); -const char * scalar_config_get_ensfile_ref(const scalar_config_type * ); -const char * scalar_config_get_eclfile_ref(const scalar_config_type * ); -void scalar_config_transform(const scalar_config_type * , const double * , double *); -double scalar_config_transform_item(const scalar_config_type *, double, int); -void scalar_config_fscanf_line(scalar_config_type * , int , FILE * ); -int scalar_config_get_active_size(const scalar_config_type *); - -SAFE_CAST_HEADER(scalar_config) -GET_DATA_SIZE_HEADER(scalar); -VOID_FREE_HEADER(scalar_config); -GET_ACTIVE_LIST_HEADER(scalar); -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/site_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/site_config.h deleted file mode 100644 index 1e3c893d56..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/site_config.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'site_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SITE_CONFIG_H -#define ERT_SITE_CONFIG_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -#include -#include - -#include -#include -#include - - -typedef struct site_config_struct site_config_type; - - const char * site_config_get_location(); - - bool site_config_has_job_script( const site_config_type * site_config ); - const char * site_config_get_manual_url( const site_config_type * site_config ); - void site_config_set_manual_url( site_config_type * site_config , const char * manual_url ); - const char * site_config_get_default_browser( const site_config_type * site_config ); - void site_config_set_default_browser( site_config_type * site_config , const char * default_browser ); - - const char * site_config_get_license_root_path( const site_config_type * site_config ); - void site_config_set_license_root_path( site_config_type * site_config , const char * license_root_path); - void site_config_init_user_mode( site_config_type * site_config ); - - void site_config_set_num_cpu( site_config_type * site_config , int num_cpu ); - void site_config_update_lsf_request(site_config_type * , const forward_model_type *); - bool site_config_init(site_config_type * site_config , const config_content_type * config); - void site_config_free(site_config_type *); - ext_joblist_type * site_config_get_installed_jobs( const site_config_type * ); - job_queue_type * site_config_get_job_queue( const site_config_type * ); - void site_config_set_ens_size( site_config_type * site_config , int ens_size ); - - void site_config_set_max_running_lsf( site_config_type * site_config , int max_running_lsf); - int site_config_get_max_running_lsf( const site_config_type * site_config ); - void site_config_set_max_running_rsh( site_config_type * site_config , int max_running_rsh); - int site_config_get_max_running_rsh( const site_config_type * site_config); - void site_config_set_max_running_local( site_config_type * site_config , int max_running_local); - int site_config_get_max_running_local( const site_config_type * site_config ); - void site_config_setenv( site_config_type * site_config , const char * variable, const char * value); - hash_type * site_config_get_env_hash( const site_config_type * site_config ); - void site_config_clear_env( site_config_type * site_config ); - void site_config_clear_pathvar( site_config_type * site_config ); - stringlist_type * site_config_get_path_variables( const site_config_type * site_config ); - stringlist_type * site_config_get_path_values( const site_config_type * site_config ); - - void site_config_clear_rsh_host_list( site_config_type * site_config ); - hash_type * site_config_get_rsh_host_list( const site_config_type * site_config ); - void site_config_add_rsh_host( site_config_type * site_config , const char * rsh_host , int max_running); - - void site_config_set_lsf_queue( site_config_type * site_config , const char * lsf_queue); - const char * site_config_get_lsf_queue( const site_config_type * site_config ); - void site_config_set_lsf_request( site_config_type * site_config , const char * lsf_request); - const char * site_config_get_lsf_request( const site_config_type * site_config ); - - const char * site_config_get_job_queue_name( const site_config_type * site_config ); - void site_config_set_job_queue( site_config_type * site_config , const char * queue_name ); - - void site_config_set_rsh_command( site_config_type * site_config , const char * rsh_command); - const char * site_config_get_rsh_command( const site_config_type * site_config ); - void site_config_set_ext_job_search_path(site_config_type * site_config, bool search_path); - - - bool site_config_set_job_script( site_config_type * site_config , const char * job_script ); - const char * site_config_get_job_script( const site_config_type * site_config ); - - void site_config_set_max_submit( site_config_type * site_config , int max_submit ); - int site_config_get_max_submit(const site_config_type * site_config ); - - bool site_config_queue_is_running( const site_config_type * site_config ); - int site_config_install_job(site_config_type * site_config , const char * job_name , const char * install_file); - bool site_config_del_job( site_config_type * site_config , const char * job_name ); - - void site_config_set_umask( site_config_type * site_config , mode_t umask); - mode_t site_config_get_umask( const site_config_type * site_config ); - - site_config_type * site_config_alloc_empty(); - void site_config_add_config_items( config_parser_type * config , bool site_mode); -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/state_map.h b/ThirdParty/Ert/libenkf/include/ert/enkf/state_map.h deleted file mode 100644 index 49a7a378a4..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/state_map.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - The file 'state_map.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_STATE_MAP_H -#define ERT_STATE_MAP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - - typedef struct state_map_struct state_map_type; - - - state_map_type * state_map_alloc( ); - state_map_type * state_map_fread_alloc( const char * filename ); - state_map_type * state_map_fread_alloc_readonly( const char * filename ); - state_map_type * state_map_alloc_copy( state_map_type * map ); - bool state_map_is_readonly(const state_map_type * state_map); - void state_map_free( state_map_type * map ); - int state_map_get_size( state_map_type * map); - realisation_state_enum state_map_iget( state_map_type * map , int index); - void state_map_update_undefined( state_map_type * map , int index , realisation_state_enum new_state); - void state_map_update_matching( state_map_type * map , int index , int state_mask , realisation_state_enum new_state); - void state_map_iset( state_map_type * map ,int index , realisation_state_enum state); - bool state_map_equal( state_map_type * map1 , state_map_type * map2); - void state_map_fwrite( state_map_type * map , const char * filename); - bool state_map_fread( state_map_type * map , const char * filename); - void state_map_select_matching( state_map_type * map , bool_vector_type * select_target , int select_mask); - void state_map_deselect_matching( state_map_type * map , bool_vector_type * select_target , int select_mask); - void state_map_set_from_inverted_mask(state_map_type * map, const bool_vector_type *mask , realisation_state_enum state); - void state_map_set_from_mask(state_map_type * map, const bool_vector_type *mask , realisation_state_enum state); - int state_map_count_matching( state_map_type * state_map , int mask); - bool state_map_legal_transition( realisation_state_enum state1 , realisation_state_enum state2); - - UTIL_IS_INSTANCE_HEADER( state_map ); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/summary.h b/ThirdParty/Ert/libenkf/include/ert/enkf/summary.h deleted file mode 100644 index fd250f0e12..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/summary.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'summary.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SUMMARY_H -#define ERT_SUMMARY_H -#include - -#include -#include - -#include -#include -#include - - - - - - -double summary_get(const summary_type * summary, int report_step ); -bool summary_active_value( double value ); -int summary_length(const summary_type * summary); - -VOID_HAS_DATA_HEADER(summary); -UTIL_SAFE_CAST_HEADER(summary); -UTIL_SAFE_CAST_HEADER_CONST(summary); -VOID_ALLOC_HEADER(summary); -VOID_FREE_HEADER(summary); -VOID_COPY_HEADER(summary); -VOID_FORWARD_LOAD_HEADER(summary); -VOID_FORWARD_LOAD_VECTOR_HEADER(summary); -VOID_USER_GET_HEADER(summary); -VOID_USER_GET_VECTOR_HEADER(summary); -VOID_WRITE_TO_BUFFER_HEADER(summary); -VOID_READ_FROM_BUFFER_HEADER(summary); -VOID_SERIALIZE_HEADER(summary) -VOID_DESERIALIZE_HEADER(summary) -VOID_SET_INFLATION_HEADER(summary); -VOID_CLEAR_HEADER(summary); - -VOID_IADD_HEADER(summary); -VOID_SCALE_HEADER(summary); -VOID_IMUL_HEADER(summary); -VOID_IADDSQR_HEADER(summary); -VOID_ISQRT_HEADER(summary); -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/summary_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/summary_config.h deleted file mode 100644 index b3aabd035c..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/summary_config.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'summary_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SUMMARY_CONFIG_H -#define ERT_SUMMARY_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -#include -#include - -#include - -/* - How should the run system handle a load problem of a summary - variable. Observe that the numerical enum values are actually used - - they should be listed with the most strict mode having the - numerically largest value. -*/ - - -typedef enum { LOAD_FAIL_SILENT = 0, // We just try to load - and if it is not there we do not care at all. - LOAD_FAIL_WARN = 2, // If the key can not be found we will print a warning on stdout - but the run will still be flagged as successfull. - LOAD_FAIL_EXIT = 4 } // The data is deemed important - and we let the run fail if this data can not be found. - load_fail_type; - - - - typedef struct summary_config_struct summary_config_type; - typedef struct summary_struct summary_type; - - void summary_config_update_load_fail_mode( summary_config_type * config , load_fail_type load_fail); - void summary_config_set_load_fail_mode( summary_config_type * config , load_fail_type load_fail); - load_fail_type summary_config_get_load_fail_mode( const summary_config_type * config); - void summary_config_update_required( summary_config_type * config , bool required ); - ecl_smspec_var_type summary_config_get_var_type(summary_config_type * , const ecl_sum_type * ecl_sum); - const char * summary_config_get_var(const summary_config_type * ); - void summary_config_set_obs_config_file(summary_config_type * , const char * ); - const char * summary_config_get_config_txt_file_ref(const summary_config_type * ); - summary_config_type * summary_config_alloc(const char * , load_fail_type load_fail); - void summary_config_free(summary_config_type * ); - int summary_config_get_active_mask(const summary_config_type *); - int summary_config_get_var_index(const summary_config_type * , const char * ); - const char ** summary_config_get_var_list_ref(const summary_config_type *); - void summary_config_add_var(summary_config_type * , const char * ); - bool summary_config_has_var(const summary_config_type * , const char * ); - void summary_config_summarize(const summary_config_type * ); - void summary_config_add_obs_key(summary_config_type * , const char * ); - int summary_config_get_byte_size(const summary_config_type * ); - - UTIL_IS_INSTANCE_HEADER(summary_config); - UTIL_SAFE_CAST_HEADER(summary_config); - UTIL_SAFE_CAST_HEADER_CONST(summary_config); - GET_DATA_SIZE_HEADER(summary); - VOID_GET_DATA_SIZE_HEADER(summary); - VOID_CONFIG_FREE_HEADER(summary); - - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/summary_key_matcher.h b/ThirdParty/Ert/libenkf/include/ert/enkf/summary_key_matcher.h deleted file mode 100644 index c82d14f3e4..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/summary_key_matcher.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef ERT_SUMMARY_KEY_MATCHER_H -#define ERT_SUMMARY_KEY_MATCHER_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - - typedef struct summary_key_matcher_struct summary_key_matcher_type; - - summary_key_matcher_type * summary_key_matcher_alloc(); - void summary_key_matcher_free(summary_key_matcher_type * matcher); - int summary_key_matcher_get_size(const summary_key_matcher_type * matcher); - void summary_key_matcher_add_summary_key(summary_key_matcher_type * matcher, const char * summary_key); - bool summary_key_matcher_match_summary_key(const summary_key_matcher_type * matcher, const char * summary_key); - bool summary_key_matcher_summary_key_is_required(const summary_key_matcher_type * matcher, const char * summary_key); - stringlist_type * summary_key_matcher_get_keys(const summary_key_matcher_type * matcher); - - UTIL_IS_INSTANCE_HEADER( summary_key_matcher ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/summary_key_set.h b/ThirdParty/Ert/libenkf/include/ert/enkf/summary_key_set.h deleted file mode 100644 index 7b167cda8c..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/summary_key_set.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef ERT_SUMMARY_KEY_SET_H -#define ERT_SUMMARY_KEY_SET_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - - typedef struct summary_key_set_struct summary_key_set_type; - - summary_key_set_type * summary_key_set_alloc(); - summary_key_set_type * summary_key_set_alloc_from_file(const char * filename, bool read_only); - void summary_key_set_free(summary_key_set_type * set); - int summary_key_set_get_size(summary_key_set_type * set); - bool summary_key_set_add_summary_key(summary_key_set_type * set, const char * summary_key); - bool summary_key_set_has_summary_key(summary_key_set_type * set, const char * summary_key); - stringlist_type * summary_key_set_alloc_keys(summary_key_set_type * set); - bool summary_key_set_is_read_only(const summary_key_set_type * set); - - void summary_key_set_fwrite(summary_key_set_type * set, const char * filename); - bool summary_key_set_fread(summary_key_set_type * set, const char * filename); - - - - UTIL_IS_INSTANCE_HEADER( summary_key_set ); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/summary_obs.h b/ThirdParty/Ert/libenkf/include/ert/enkf/summary_obs.h deleted file mode 100644 index 3d36b1bfce..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/summary_obs.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'summary_obs.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SUMMARY_OBS_H -#define ERT_SUMMARY_OBS_H - -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include - - -#define AUTO_CORRF_EXP "EXP" -#define AUTO_CORRF_GAUSS "GAUSS" - - -typedef struct summary_obs_struct summary_obs_type; - -typedef double (auto_corrf_ftype) ( double , double ); - - -void summary_obs_free( - summary_obs_type * summary_obs); - -summary_obs_type * summary_obs_alloc( - const char * summary_key, - const char * obs_key , - double value , - double std, - const char * auto_corrf_name , - double auto_corrf_param); - - - double summary_obs_get_value( const summary_obs_type * summary_obs ); - double summary_obs_get_std( const summary_obs_type * summary_obs ); - double summary_obs_get_std_scaling( const summary_obs_type * summary_obs ); - -auto_corrf_ftype * summary_obs_get_auto_corrf( const summary_obs_type * summary_obs ); -double summary_obs_get_auto_corrf_param( const summary_obs_type * summary_obs ); - -bool summary_obs_default_used( - const summary_obs_type * summary_obs, - int restart_nr); - -const char * summary_obs_get_summary_key( - const summary_obs_type * summary_obs); - -summary_obs_type * summary_obs_alloc_from_HISTORY_OBSERVATION( - const conf_instance_type * conf_instance, - const history_type * history); - -summary_obs_type * summary_obs_alloc_from_SUMMARY_OBSERVATION( - const conf_instance_type * conf_instance, - const history_type * history); - -void summary_obs_set(summary_obs_type * , double , double ); - -void summary_obs_update_std_scale(summary_obs_type * summary_obs, double std_multiplier , const active_list_type * active_list); - -VOID_FREE_HEADER(summary_obs); -VOID_GET_OBS_HEADER(summary_obs); -VOID_MEASURE_HEADER(summary_obs); -UTIL_IS_INSTANCE_HEADER(summary_obs); -VOID_USER_GET_OBS_HEADER(summary_obs); -VOID_CHI2_HEADER(summary_obs); -VOID_UPDATE_STD_SCALE_HEADER(summary_obs); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/surface.h b/ThirdParty/Ert/libenkf/include/ert/enkf/surface.h deleted file mode 100644 index 62be08f030..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/surface.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'surface.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SURFACE_H -#define ERT_SURFACE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - - typedef struct surface_struct surface_type; - - UTIL_SAFE_CAST_HEADER(surface); - UTIL_SAFE_CAST_HEADER_CONST(surface); - VOID_ALLOC_HEADER(surface); - VOID_FREE_HEADER(surface); - VOID_ECL_WRITE_HEADER(surface); - VOID_COPY_HEADER(surface); - VOID_USER_GET_HEADER(surface); - VOID_WRITE_TO_BUFFER_HEADER(surface); - VOID_READ_FROM_BUFFER_HEADER(surface); - VOID_SERIALIZE_HEADER(surface); - VOID_DESERIALIZE_HEADER(surface); - VOID_SET_INFLATION_HEADER(surface); - VOID_CLEAR_HEADER(surface); - VOID_IADD_HEADER(surface); - VOID_SCALE_HEADER(surface); - VOID_IMUL_HEADER(surface); - VOID_IADDSQR_HEADER(surface); - VOID_ISQRT_HEADER(surface); - VOID_INITIALIZE_HEADER(surface); - VOID_FLOAD_HEADER(surface); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/surface_config.h b/ThirdParty/Ert/libenkf/include/ert/enkf/surface_config.h deleted file mode 100644 index 73fb0e88b6..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/surface_config.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'surface_config.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SURFACE_CONFIG_H -#define ERT_SURFACE_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - - typedef struct surface_config_struct surface_config_type; - - void surface_config_ecl_write( const surface_config_type * config , const char * filename , const double * zcoord); - const geo_surface_type * surface_config_get_base_surface( const surface_config_type * config ); - void surface_config_free( surface_config_type * config ); - int surface_config_get_data_size(const surface_config_type * config ); - surface_config_type * surface_config_alloc_empty( ); - void surface_config_set_base_surface( surface_config_type * config , const char * base_surface ); - - UTIL_SAFE_CAST_HEADER(surface_config); - UTIL_SAFE_CAST_HEADER_CONST(surface_config); - GET_DATA_SIZE_HEADER(surface); - VOID_GET_DATA_SIZE_HEADER(surface); - VOID_CONFIG_FREE_HEADER(surface); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/time_map.h b/ThirdParty/Ert/libenkf/include/ert/enkf/time_map.h deleted file mode 100644 index 239482484b..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/time_map.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - The file 'time_map.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#ifndef ERT_TIME_MAP_H -#define ERT_TIME_MAP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include - -#include - -typedef struct time_map_struct time_map_type; - - UTIL_SAFE_CAST_HEADER( time_map ); - UTIL_IS_INSTANCE_HEADER( time_map ); - - bool time_map_try_summary_update( time_map_type * map , const ecl_sum_type * ecl_sum); - bool time_map_try_update( time_map_type * map , int step , time_t time); - bool time_map_attach_refcase( time_map_type * time_map , const ecl_sum_type * refcase); - bool time_map_has_refcase( const time_map_type * time_map ); - bool time_map_is_strict( const time_map_type * time_map ); - void time_map_set_strict( time_map_type * time_map , bool strict); - void time_map_clear( time_map_type * map ); - bool time_map_equal( const time_map_type * map1 , const time_map_type * map2); - time_map_type * time_map_alloc( ); - void time_map_free( time_map_type * map ); - bool time_map_update( time_map_type * map , int step , time_t time); - bool time_map_summary_update( time_map_type * map , const ecl_sum_type * ecl_sum); - time_t time_map_iget( time_map_type * map , int step ); - void time_map_fwrite( time_map_type * map , const char * filename); - void time_map_fread( time_map_type * map , const char * filename); - bool time_map_fscanf(time_map_type * map , const char * filename); - double time_map_iget_sim_days( time_map_type * map , int step ); - int time_map_get_last_step( time_map_type * map); - int time_map_get_size( time_map_type * map); - time_t time_map_get_start_time( time_map_type * map); - time_t time_map_get_end_time( time_map_type * map); - double time_map_get_end_days( time_map_type * map); - bool time_map_is_readonly( const time_map_type * tm); - time_map_type * time_map_fread_alloc_readonly( const char * filename); - int_vector_type * time_map_alloc_index_map( time_map_type * map , const ecl_sum_type * ecl_sum ); - int time_map_lookup_time( time_map_type * map , time_t time); - int time_map_lookup_days( time_map_type * map , double sim_days); - int time_map_lookup_time_with_tolerance( time_map_type * map , time_t time , int seconds_before_tolerance, int seconds_after_tolerance); - void time_map_summary_upgrade107( time_map_type * map , const ecl_sum_type * ecl_sum); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/include/ert/enkf/trans_func.h b/ThirdParty/Ert/libenkf/include/ert/enkf/trans_func.h deleted file mode 100644 index 1d0b9e7507..0000000000 --- a/ThirdParty/Ert/libenkf/include/ert/enkf/trans_func.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'trans_func.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_TRANS_FUNC_H -#define ERT_TRANS_FUNC_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -#include - -#include - - -typedef struct trans_func_struct trans_func_type; -typedef double (transform_ftype) (double , const arg_pack_type *); -typedef bool (validate_ftype) (const trans_func_type * ); - -trans_func_type * trans_func_fscanf_alloc( FILE * stream, const char * filename ); -double trans_func_eval( const trans_func_type * trans_func , double x); - -void trans_func_free( trans_func_type * trans_func ); -void trans_func_iset_double_param(trans_func_type * trans_func , int param_index , double value ); -bool trans_func_set_double_param( trans_func_type * trans_func , const char * param_name , double value ); -void trans_func_iset_int_param(trans_func_type * trans_func , int param_index , int value ); -bool trans_func_set_int_param( trans_func_type * trans_func , const char * param_name , int value ); -bool trans_func_use_log_scale(const trans_func_type * trans_func ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libenkf/src/CMakeLists.txt b/ThirdParty/Ert/libenkf/src/CMakeLists.txt deleted file mode 100644 index bf950ea8a4..0000000000 --- a/ThirdParty/Ert/libenkf/src/CMakeLists.txt +++ /dev/null @@ -1,239 +0,0 @@ -set( source_files - time_map.c - rng_config.c - trans_func.c - enkf_types.c - enkf_obs.c - obs_data.c - block_obs.c - enkf_config_node.c - field_config.c - field.c - enkf_state.c - enkf_util.c - enkf_node.c - gen_kw_config.c - gen_kw.c - enkf_fs.c - fs_driver.c - meas_data.c - summary_obs.c - summary.c - summary_config.c - gen_data_config.c - gen_data.c - gen_common.c - gen_obs.c - enkf_serialize.c - ecl_config.c - enkf_defaults.c - ensemble_config.c - model_config.c - site_config.c - active_list.c - obs_vector.c - field_trans.c - plain_driver.c - local_ministep.c - local_updatestep.c - container_config.c - container.c - local_context.c - local_config.c - analysis_config.c - misfit_ensemble.c - misfit_member.c - misfit_ts.c - data_ranking.c - misfit_ranking.c - ranking_table.c - fs_types.c - block_fs_driver.c - plot_settings.c - ert_template.c - member_config.c - enkf_analysis.c - enkf_main.c - local_dataset.c - surface.c - surface_config.c - enkf_plot_data.c - enkf_plot_tvector.c - enkf_plot_gendata.c - enkf_plot_genvector.c - enkf_plot_gen_kw.c - enkf_plot_gen_kw_vector.c - hook_manager.c - hook_workflow.c - runpath_list.c - ert_workflow_list.c - analysis_iter_config.c - enkf_main_jobs.c - ecl_refcase_list.c - local_obsdata_node.c - local_obsdata.c - pca_plot_data.c - pca_plot_vector.c - state_map.c - cases_config.c - state_map.c - summary_key_set.c - summary_key_matcher.c - ert_test_context.c - ert_log.c - run_arg.c - ert_run_context.c - ert_init_context.c - custom_kw.c - custom_kw_config.c - custom_kw_config_set.c - forward_load_context.c -) - -set( header_files - time_map.h - rng_config.h - enkf_analysis.h - enkf_fs_type.h - trans_func.h - enkf_obs.h - obs_data.h - enkf_config_node.h - block_obs.h - field_config.h - field.h - enkf_macros.h - enkf_state.h - enkf_util.h - enkf_main.h - enkf_main_jobs.h - enkf_node.h - enkf_fs.h - gen_kw_config.h - gen_kw.h - enkf_types.h - fs_driver.h - meas_data.h - summary_obs.h - summary_config.h - summary_config.h - gen_data_config.h - gen_data.h - gen_common.h - gen_obs.h - fs_types.h - enkf_serialize.h - plain_driver.h - ecl_config.h - ensemble_config.h - model_config.h - site_config.h - active_list.h - obs_vector.h - field_trans.h - plain_driver.h - local_ministep.h - container.h - local_updatestep.h - local_config.h - analysis_config.h - misfit_ensemble.h - misfit_ensemble_typedef.h - misfit_ts.h - misfit_member.h - data_ranking.h - ranking_table.h - ranking_common.h - misfit_ranking.h - block_fs_driver.h - field_common.h - gen_kw_common.h - gen_data_common.h - plot_settings.h - ert_template.h - member_config.h - enkf_defaults.h - container_config.h - local_dataset.h - surface.h - surface_config.h - local_context.h - enkf_plot_data.h - enkf_plot_tvector.h - enkf_plot_gendata.h - enkf_plot_genvector.h - enkf_plot_gen_kw.h - enkf_plot_gen_kw_vector.h - hook_manager.h - runpath_list.h - ert_workflow_list.h - analysis_iter_config.h - ecl_refcase_list.h - local_obsdata_node.h - local_obsdata.h - pca_plot_data.h - pca_plot_vector.h - state_map.h - summary_key_set.h - summary_key_matcher.h - cases_config.h - state_map.h - ert_test_context.h - ert_log.h - run_arg.h - run_arg_type.h - ert_run_context.h - ert_init_context.h - custom_kw.h - custom_kw_config.h - custom_kw_config_set.h - forward_load_context.h -) - - -add_library( enkf ${LIBRARY_TYPE} ${source_files} ) -set_target_properties( enkf PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR} ) - -set( STATOIL_SITE_CONFIG /project/res/etc/ERT/site-config) -if (STATOIL_TESTDATA_ROOT) - set( SITE_CONFIG_FILE ${STATOIL_SITE_CONFIG} CACHE FILEPATH "Path to global ERT Configuration file") -else() - if (EXISTS ${STATOIL_SITE_CONFIG}) - set( SITE_CONFIG_FILE ${STATOIL_SITE_CONFIG}) - else() - set( SITE_CONFIG_FILE "${PROJECT_SOURCE_DIR}/share/site-config") - endif() -endif() - -set_source_files_properties( site_config.c PROPERTIES COMPILE_DEFINITIONS "SITE_CONFIG_FILE=\"${SITE_CONFIG_FILE}\"") - -target_link_libraries( enkf ecl sched analysis rms config job_queue ) - -if (USE_RUNPATH) - add_runpath( enkf ) -endif() - -if(ERT_MAC) - add_custom_target(ert_share_symlinking ALL - COMMENT "Symlinking to the development share directory." - COMMAND ln -sfh ${PROJECT_SOURCE_DIR}/share ${PROJECT_BINARY_DIR}/share - ) - -else() - add_custom_target(ert_share_symlinking ALL - COMMENT "Symlinking to the development share directory." - COMMAND ln -sf -t ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/share - ) -endif() - -#----------------------------------------------------------------- -if (INSTALL_ERT) - install(TARGETS enkf DESTINATION ${CMAKE_INSTALL_LIBDIR}) - foreach(header ${header_files}) - install(FILES ../include/ert/enkf/${header} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/enkf) - endforeach() -endif() - -#----------------------------------------------------------------- - - diff --git a/ThirdParty/Ert/libenkf/src/README.new_config_draft b/ThirdParty/Ert/libenkf/src/README.new_config_draft deleted file mode 100644 index 0576ff4591..0000000000 --- a/ThirdParty/Ert/libenkf/src/README.new_config_draft +++ /dev/null @@ -1,251 +0,0 @@ --- QUEUE_SYSTEM prevails, but becomes a class. --- --- This is a singleton class. I.e., it can only have --- one instance. --- --- Example: -QUEUE_SYSTEM xHydro_LSF -{ - TYPE = LSF; - MAX_JOBS = 10; -}; - - - - --- SUBSTITUTION takes over for DATA_KW. --- Adding support for arbitrary files --- and keys. Adding support for sourced --- file. --- --- Example A: -SUBSTITUTION my_own_hack -{ - FILENAME = "my_magic_file.txt"; - KEY = ""; - VALUE = "SVADAFRANZ_"; -}; - --- Example B: -SUBSTITUTION your_hack -{ - FILENAME = ; - KEY = "__SVADAFRANZ__"; - VALUE = ; -}; - --- Example C: -SUBSTITUTION our_hack -{ - FILENAME = "our_file.txt"; - KEY = "__INSERT_HERE__"; - SOURCE_FILE = "the_data.txt"; - -}; - - - --- JOB takes over for INSTALL_JOB. --- --- Example: -JOB STEINFYSIKK -{ - PLATFORM_EXE i386 - { - EXE = "/bin/old/bein.exe"; - }; - - - PLATFORM_EXE x86_64 - { - EXE = "/bin/x86_64/bein.exe"; - }; - - - PLATFORM_EXE ia64 - { - EXE = "/bin/ia64/bein.exe"; - - -- Special arguments and env for this platform. - ARGUMENTS = "-finn -olje -some funky special stuff"; - SETENV F_UMFTENDIAN { VALUE = "special"; }; - }; - - - ARGUMENTS = "-finn -olje"; - - STDIN = ""; - STDOUT = "steinfysikk.stdout"; - - LSF_RESOURCES = "det skal gÃ¥ snabbt!"; - -}; - - - --- SIMULATION_WORKFLOW takes over for FORWARD_MODEL --- --- "Simulation workflow" might be more instructive? --- Not 100% sure though... --- --- Example: -SIMULATION_WORKFLOW = "RELPERM ECLIPSE100 STEINFYSIKK"; - - - --- SIMULATION_SCHEDULE takes over for ENKF_SCHED_FILE. --- --- This is a singleton class. I.e., it can only have --- one instance. --- --- Example: -SIMULATION_SCHEDULE my_schedule -{ - SEGMENT A - { - START = 0; - END = 10; - STRIDE = 5; - UPDATE = ENKF; - SIMULATION_WORKFLOW = "ECLIPSE100 ROCKPHYSICS SEISMIC"; - }; - - - SEGMENT B - { - START = 10; - END = 100; - - -- Use smoother for this interval - UPDATE = ENKS; - }; - - - SEGMENT C - { - START = 100; - END = 200; - UPDATE = NO; - }; - -}; - - - - --- PARAMETER_COLLECTION takes over for GEN_KW. --- --- Example: -PARAMETER_COLLECTION my_big_collection -{ - -- All the parameters in the collection - -- subsitutes into the TEMPLATE_FILE. - TEMPLATE_FILE = "templates/my_template.txt"; - - - -- File produced in the simulation folder. - TARGET_FILE = "my_output.txt"; - - - SCALAR foo - { - -- The key in my_template to subsitute. - -- This shold probably default to - -- __INSTANCE_NAME__ or . - TEMPLATE_KEY = ""; - - - -- Prior distribution can not be used - -- with MAX, MIN, TRANSFER_FUNCTION - -- and PRIOR_SAMPLES. - PRIOR_DISTRIBUTION = "LOGUNIF 0 1"; - }; - - - -- This parameter behaves like the old GEN_KW, - -- but reads input from a user provided file - -- and subsitutes a key different from name. - SCALAR bar - { - TEMPLATE_KEY = "__MAGIC__"; - - -- The file user_provided_realizations.txt shall - -- contain ascii doubles, one per line. - PRIOR_SAMPLES = "user_provided_realizations.txt"; - TRANSFER_FUNCTION = LOG10; - MAX = 100; - MIN = 1; - }; - - -- User provided covariance matrix. - -- - -- Note that we cannot use this if not all - -- parameters are sampled internally! - -- COVARIANCE_MATRIX = "my_covmat.txt"; -}; - - --- PARAMETER takes over for GEN_PARAM and --- FIELD * PARAMETER. --- --- Example A, subsituting FIELD * PARAMETER. -PARAMETER poro -{ - -- Need to have either: - -- 1. ECL_OUTPUT and KEYWORD (for FIELD * PARAMETER) - -- or - -- 2. TEMPLATE_FILE and KEY (for GEN_PARAM). - ECL_OUTPUT = GRDECL; - KEYWORD = "PORO"; - TARGET_FILE = "PORO.GRDECL"; - PRIOR_SAMPLES = "poro-%d.grdecl"; -}; --- Example B, subsituting FIELD * PARAMETER -PARAMETER permx -{ - ECL_OUTPUT = "ECLBIN"; - KEYWORD = "PERMX"; - TARGET_FILE = "PERMX.BIN"; - PRIOR_SAMPLES = "permx-%d.roff"; -}; --- Example C, subsituting GEN_PARAM. -PARAMETER surf -{ - TEMPLATE_FILE = "my_surf_template.txt"; - KEY = "__REPLACE_THIS__"; - TARGET_FILE = "surface.roff"; - PRIOR_SAMPLES = "surf-%d.txt"; -}; - - --- STATE takes over for FIELD * DYNAMIC --- and SUMMARY. --- --- Example A, replacing FIELD * DYNAMIC. -STATE pres -{ - ECL_SOURCE = RESTART; - KEYWORD = PRESSURE; - MIN = 100; - -- Specify UPDATE_SPACE instead of - -- input and output transform. - UPDATE_SPACE = LOG10; -}; --- Example B, replacing SUMMARY. -STATE region_pressure; -{ - ECL_SOURCE = SUMMARY; - KEYWORD = RPR:10; - -- Need to think about how this affects observations.. - UPDATE_SPACE = LOG10; -}; - - - -SUMMARY_OBSERVATION foobar -{ - KEY = WOPR:P1; - RESTARTS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - VALUES = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1]; - ERRORS = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -} diff --git a/ThirdParty/Ert/libenkf/src/README.new_type.c b/ThirdParty/Ert/libenkf/src/README.new_type.c deleted file mode 100644 index d7547500c1..0000000000 --- a/ThirdParty/Ert/libenkf/src/README.new_type.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'README.new_type.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/** -The two files README.new_type.c and README.new_type_config.c (along -with the corresponding header files) are meant to serve as a -documentation and reference on how to add new object types to the enkf -system. - -The enkf object system is based on the enkf_node_type as a sort of -abstract class, this object has a void pointer which will point to the -actual data instance (i.e. for instance an instance of the type -"new_type" implemented here), along with several function pointers to -manipulate the data object. - - _______________________________________ _______________________________ - | enkf_node_type instance | | | - | ------------------------------------- | | Actual data , e.g. a field or | - | * void * data |-------------->| a multiplier. | - | * Function pointers to manipulate | |_______________________________| - | data | - | * Something more - not relevant here | - |_______________________________________| - - -The enkf_node object can contain pointers to all types of objects. - - - - - - - -new_type.c (should read README.new_type.h first). -========== -For all the enkf objects we have split the member spesific data, and -the configuration information in two different files (objects): - - ______________ - | | - _________________| Config |_______________ - | | information | | - | /|______________|\ | - | / | \ | - | / | \ | - | / | | | - | | | | | - _|__ __|_ _|__ _|__ _|__ - | | | | | | | | | | - | 01 | | 02 | | 03 | | 04 | | 05 | - |____| |____| |____| |____| |____| - - -The figure shows an ensemble of 5 members (of some type); they all -have a pointer to a common configuration object. The thought behind -this is that all members should share configuration information, -i.e. for instance all the members in a permeability field should have -the same active/inactive cells, all the relperm instances should use -the same relperm model e.t.c. This file is about implementing the data -members, i.e. the small boxes. The implementation of the config -object, is discussed in README.new_type_config.c. - - -1. alloc_ftype: new_type * new_type_alloc(const new_type_config *); - -------------------------------------------- - - This function takes a pointer to a config object of the right type - (i.e. new_type_config_type in this case), reads the required - configuration information from this object, and returns a new new_type - instance. - - -2. ecl_write_ftype: void new_type_ecl_write(const new_type * , const char *); - -------------------------------------------------------------------------- - This function takes a const pointer to a new_type instance, along - with a filename. The function should write eclipse data to the - filename specified in the second argument. - - - -3. fread_ftype: void new_type_fread(new_type * , FILE * ); - ------------------------------------------------ - This function should take a pointer to a new_type object, and a - stream opened for reading as input, and then read in data for the - object from disk. - - -4. fwrite_ftype: void new_type_fwrite(new_type * , FILE * ); - ------------------------------------------------ - This function should take a pointer to a new_type object, and a - stream opened for writing as input, and then write the data from - the object to disk. The two functions instances fread_ftype - and - fwrite_ftype must of course match, but apart from that they are - quite free. - - -5. copyc_ftype: new_type * new_type_copyc(const new_type *); - --------------------------------------------------------------- - This function takes a const pointer to a new_type instance. A new - new_type copy instance with identical data is created. The two - instance share config object. - - -6. initialize_ftype: void new_type_initialize(new_type * , int); - ------------------------------------------------------------ - This function takes a pointer to a new_type instance, and a an - ensemble number as input; it should then initialize the data of - the new_type object - this can either be done by sampling a random - number according to some distribution, by reading in input from an - external program or by calling an external program (i.e. RMS). - - -7. serialize_ftype: int (const new_type * , int , size_t , double * , size_t , size_t , bool *); - -------------------------------------------------------------------------------------------- - This one is a bit tricky ... The enkf_state object, holding among - others things instances of new_type * can be illustrated as this: - - - -------------- - | enkf_state | - ============== ---------------- - | PRESSURE |-------->| Pressure data| - |------------| ---------------- - | New_type |---| - -------------- | ----------------- - | multz | |-------->| new_type data | - -------------- ----------------- - | - | -------------- - |------>| multz data | - -------------- - - The key point of this figure is that the various data we want to - update with enkf are at random locations in memory. To be able to - do the - A' = AX - - matrix multiplication we must assemble this data in a long - vector. That is what is meant by serializing. The serialize - routine is so complicated for (at least) two reasons: - - o We can allocate a certain amount of memory, and then the - serialize routines should continue until the available memory - is exhausted, update and the resume. - - o For efficiency reasons a "funny" stride should be used. - - - -8. deserialize_ftype: int new_type_deserialize(new_type * , int , size_t , const double * , size_t , size_t); - --------------------------------------------------------------------------------------------------------- - This is "just" the opposite of serialize, take data back after the - update (matrix multiplication). - - -9. free_ftype: void new_type_free(new_type *); - ------------------------------------------- - This function should free all the memory used by the new_type - instance. Observe that the config pointer should be left alone, - that will be collected elsewhere. - -10. free_data_ftype: void new_type_free_data(new_type *); - ----------------------------------------------------- - This function should free the data of the new_type instance, but - retain the new_type holding structure. This function is called - after an instance has swapped to disk. - -11. realloc_data_ftype: void (new_type *); - -------------------------------------------------------------- - This function is the "opposite" of function number 10, i.e. it - is to reallocate memory to hold the actual data. - - -12. ensemble_fprintf_results_ftype * fprintf_results - -------------------------------------------------------------- - This function is used to print the reuslts in a formatted nice way. Only - applicable for variables with small amounts of data, like gen_kw. - -13. ecl_load_ftype: void (new_type * , const char * run_path , const char * eclbase, const ecl_sum_type , int report_step) - ----------------------------------------------------------------- - This function is used to load ECLIPSE results from a complete - forward simulation. Observe that the restart data are not loaded - through this interface, and that the summary datka get an - ecl_sum_type * instance for convenience. If you want to add a new - which should be loaded from a eclipse directory, you must manage - with the run_path ankd ecl_base input. - - -Now - since the enkf_node objects can point to arbitrary types of -object the data pointer is a void pointer, and the function pointer -expect (void *) as input, instead of pointers to e.g. new_type -instances. To cast from the typed functions listed above, to functions -accepting (void *) there are several utility functions, i.e. the macro -VOID_ECL_WRITE() will create a void * version of the XXX_ecl_write() -function: - -The macro call: VOID_ECL_WRITE(new_type) will generate the following code: - - void new_type_ecl_write__(void *__new_type) { - new_type_ecl_write( (new_type *) __new_type); - } - -And the macro VOID_ECL_WRITE_HEADER(new_type) will generate the -corresponding header. These (void) functions are the ones used when -initializing the function pointers in the enkf_node object. For -instance for registering the new_type object in the enkf_node -implementation (function: enkf_node_alloc_empty) - -.... -.... -case(NEW_TYPE): - node->alloc = new_type_alloc__; - node->fwrite_f = new_type_fwrite__; - ... - -*/ - - - -/* -OK - here comes the implementation: -*/ - -/* - These are standard header files needed by almost any C-program: -*/ -#include -#include -#include -#include - -/* - Lots of small utility functions for: memory handling, string - handling and file handling. Implemented in the libutil library. -*/ -#include - - -/* - Lots of (ugly) C-macros to generate anonymous versions of the various - functions listed above. -*/ -#include - - -/* - This file contains several enum typedefs, the most important one in - this context is the ert_impl_type; the NEW_TYPE should be added to - this (at the end). -*/ -#include - - -/* - The header file for the actual new_type object. -*/ -#include - - - -/* - These two #define statements, along with the macros found in - enkf_debug.h allow for some simple run_time checks of the various - casts. Observe that the header file enkf_debug.h is included from - the current directory; it is *not* installed in an include/ - directory. -*/ -#define TARGET_TYPE NEW_TYPE /* The variable type in this file - according to the ert_impl_type classification */ -#define DEBUG /* We want debugging */ -#include "enkf_debug.h" - - - -/* - Here comes the new_type_struct defintion: -*/ - -struct new_type_struct { - DEBUG_DECLARE - const new_type_config_type *config; - - 1: scalar_type *scalar; - 2: double *data; -}; - -/* - Observe the following properties of the struct: - - 1. The statement DEBUG_DECLARE inserts a variable __impl_type as the - first element of the struct (if debugging is enabled) with - #define DBEUG. This should be the first element in the struct. - - 2. The struct contains a pointer to a new_type_config_type object; - this pointer is const, as the new_type instances are not allowed - to write the configuration information (it is shared among many - instances), only read it. - - 3. The actual data is stored in either a scalar instance, or just as - double * data. (1: and 2: is *NOT* some new funny C-syntax). - - The scalar_type object is described further down. If use of - scalar_type is not appropriate, you must store the data in some - other way. There are no formal rules to this, but if you stick to - the suggested "double *data;" convention suggested above, you - will get several macros for algebraic manipulation (adding, - scaling, squaring +++) of new_type instances for free. - - Hence - it is *strongly* recommended to use either: - - scalar_type * scalar; - - or - - double * data; - - to hold the actual data. -*/ - - -/* -scalar_type -=========== -This type is implemented in scalar.c / scalar_config.c. -*/ - - - - diff --git a/ThirdParty/Ert/libenkf/src/README.obs b/ThirdParty/Ert/libenkf/src/README.obs deleted file mode 100644 index 96e7c8443b..0000000000 --- a/ThirdParty/Ert/libenkf/src/README.obs +++ /dev/null @@ -1,52 +0,0 @@ -/** - -Observations/measurements are handled by three different (toplevel) -objects: - - -obs_node_type -------------- -This object contians qualitative information about the observations, -i.e. when they are active, what is the error of the observations, what -type they are, and how to measure them. The obs_node_type object -contains the two function pointers: - - get_obs : void (const void* , int , * obs_data_type) - measure : void (const void * , const voide * , meas_vector_type) - -The first of these, get_obs, is used to load/get the actual -observation, that can typically be to get an historical rate from the -history; the data is pushed onto an instance of obs_data_type. measure -on the other is used to extract information from the ensemble state, -i.e. measure for instance a simulated rate or a pressure, and push the -data onto a meas_vector_type instance. - -Several obs_node instances are collected in the enkf_obs type, which -is mostly a hash table of obs_node instances. - -The obs_node_type lives through the whole simulation, this in contrast -to the two other data types involved in the process. - - -obs_data_type -------------- -This data type is used to store all the observation AT ONE -TIMESTEP. New observations are just added with a obs_data_add(), and -the structure grows as necessary. Before the next timestep, the -obs_data_type instance is reset. - - -meas_vector_type / meas_matrix_type ------------------------------------ -This data type is used in the same way as the obs_data_type, for -measurements. When an eclipse integration is complete the -obs_node->measure function is called, and the measurements are pushed -onto the meas_vector. (The whole ensemble corresponds to meas_matrix_type). - - -Analysis --------- -Observe that the analysis step ONLY involves a meas_matrix_type -instance and an obs_data instance. - ------------------------------------------------------------------ diff --git a/ThirdParty/Ert/libenkf/src/README.paths b/ThirdParty/Ert/libenkf/src/README.paths deleted file mode 100644 index 8048a837b0..0000000000 --- a/ThirdParty/Ert/libenkf/src/README.paths +++ /dev/null @@ -1,25 +0,0 @@ -The enkf program uses an object call path_fmt_type to store/configure -various paths and filenames (The path_fmt_type is implemented in the -libutil library). For instance the main configuration file must -contain a line like this: - - RUNPATH /tmp/Eclipse/tmpdir_%04d - -This is actually a format string, so when we want to get/make a -directory for an eclipse simulation, the %04d is replaced with the -actual ensemble member. Usage example: - -/* This is common to all members in the ensemble */ -path_fmt_type * run_path_fmt = path_fmt_alloc_directory_fmt("/tmp/Eclipse/tmpdir_%04d" , true); -... -... -/* For a spesific member: */ -{ - char * run_path = path_fmt_alloc_path(run_path_fmt , iens); - -} - - - - - diff --git a/ThirdParty/Ert/libenkf/src/active_list.c b/ThirdParty/Ert/libenkf/src/active_list.c deleted file mode 100644 index 582032c535..0000000000 --- a/ThirdParty/Ert/libenkf/src/active_list.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'active_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include - -#include -#include -#include - - -/** - This file implements a small structure used to denote which - elements of a node/observation which is active. At the lowest level - the active elements in a node is just a list of integers. This - list of integers, with som extra twists is what is implemented - here. - - All the xxx_config objects have a pointer to an active_list - instance. This pointer is passed to the enkf_serialize / - enkf_deserialize routines. - - Observe that for the (very important!!) special case that all - elements are active the (int *) pointer should not be accessed, and - the code here is free to return NULL. - - -Example -------- - -Consider a situation where faults number 0,4 and 5 should be active in -a fault object. Then the code will be like: - - - .... - active_list_add_index(multflt_config->active_list , 0); - active_list_add_index(multflt_config->active_list , 4); - active_list_add_index(multflt_config->active_list , 5); - .... - - When this fault object is serialized/deserialized only the elements - 0,4,5 are updated. -*/ - - -#define ACTIVE_LIST_TYPE_ID 66109 - -struct active_list_struct { - UTIL_TYPE_ID_DECLARATION; - active_mode_type mode; /* ALL_ACTIVE | INACTIVE | PARTLY_ACTIVE */ - int_vector_type *index_list; /* A list of active indices - if data_size == active_size this can be NULL. */ -}; - -/*****************************************************************/ - - -static UTIL_SAFE_CAST_FUNCTION(active_list , ACTIVE_LIST_TYPE_ID) -UTIL_IS_INSTANCE_FUNCTION( active_list , ACTIVE_LIST_TYPE_ID) - - - - -/** - The newly created active_list default to setting all indices actiove. -*/ -active_list_type * active_list_alloc( ) { - active_list_type * active_list = util_malloc(sizeof * active_list); - UTIL_TYPE_ID_INIT( active_list , ACTIVE_LIST_TYPE_ID ); - active_list->index_list = int_vector_alloc(0 , -1); - active_list->mode = ALL_ACTIVE; - return active_list; -} - - -active_list_type * active_list_alloc_copy( const active_list_type * src) { - active_list_type * new = active_list_alloc( ); - new->mode = src->mode; - int_vector_free( new->index_list ) ; - new->index_list = int_vector_alloc_copy( src->index_list ); - return new; -} - - -void active_list_copy( active_list_type * target , const active_list_type * src) { - target->mode = src->mode; - int_vector_memcpy( target->index_list , src->index_list); -} - - -void active_list_free( active_list_type * active_list ) { - int_vector_free(active_list->index_list); - free(active_list); -} - - - -void active_list_free__( void * arg ) { - active_list_type * active_list = active_list_safe_cast ( arg ); - active_list_free(active_list); -} - - - -/** - Appends a new index to the current list of active indices, and - setting the mode to PARTLY_ACTIVE. -*/ -void active_list_add_index(active_list_type * active_list, int new_index) { - if (int_vector_contains(active_list->index_list , new_index )) - return; - active_list->mode = PARTLY_ACTIVE; - int_vector_append( active_list->index_list , new_index ); -} - - - - - - - - -/** - When mode == PARTLY_ACTIVE the active_list instance knows the size - of the active set; if the mode is INACTIVE 0 will be returned and - if the mode is ALL_ACTIVE the input parameter @total_size will be - passed back to calling scope. -*/ - - -int active_list_get_active_size(const active_list_type * active_list, int total_size) { - int active_size; - switch( active_list->mode ) { - case PARTLY_ACTIVE: - active_size = int_vector_size( active_list->index_list ); - break; - case INACTIVE: - active_size = 0; - break; - case ALL_ACTIVE: - active_size = total_size; - break; - default: - util_abort("%s: internal fuckup \n",__func__); - active_size = -1; - } - return active_size; -} - - -active_mode_type active_list_get_mode(const active_list_type * active_list) { - return active_list->mode; -} - - - -/** - This will return a (const int *) pointer to the active indices. IFF - (mode == INACTIVE || mode == ALL_ACTIVE) it will instead just - return NULL. In that case it is the responsability of the calling - scope to not dereference the NULL pointer. -*/ - -const int * active_list_get_active(const active_list_type * active_list) { - if (active_list->mode == PARTLY_ACTIVE) - return int_vector_get_const_ptr( active_list->index_list ); - else - return NULL; -} - - -bool active_list_iget( const active_list_type * active_list , int index ) { - if (active_list->mode == ALL_ACTIVE) - return true; - else if (active_list->mode == INACTIVE) - return false; - else - return int_vector_iget( active_list->index_list , index ); -} - -void active_list_summary_fprintf( const active_list_type * active_list , const char *dataset_key, const char *key , FILE * stream) { - int number_of_active = int_vector_size( active_list->index_list ); - if (active_list->mode == ALL_ACTIVE){ - fprintf(stream , "NUMBER OF ACTIVE:%d,STATUS:%s,", number_of_active, "ALL_ACTIVE"); - } - else if (active_list->mode == PARTLY_ACTIVE){ - fprintf(stream , "NUMBER OF ACTIVE:%d,STATUS:%s,", number_of_active, "PARTLY_ACTIVE"); - } - else - fprintf(stream , "NUMBER OF ACTIVE:%d,STATUS:%s,", number_of_active, "INACTIVE"); -} - - - -bool active_list_equal( const active_list_type * active_list1 , const active_list_type * active_list2) { - if (active_list1 == active_list2) - return true; - else { - if (active_list1->mode != active_list2->mode) - return false; - else { - if (active_list1->mode == PARTLY_ACTIVE) - return int_vector_equal( active_list1->index_list , active_list2->index_list); - else - return true; - } - } -} diff --git a/ThirdParty/Ert/libenkf/src/active_node.c b/ThirdParty/Ert/libenkf/src/active_node.c deleted file mode 100644 index b1434610db..0000000000 --- a/ThirdParty/Ert/libenkf/src/active_node.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'active_node.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include - -/** - This file implements the two most basic objects used in the mapping - of active/inactive observations and variables. One of these nodes - contains the information necessary to activate/deactivate one - variable/observation. -*/ - - -/** - This struct implements the holding information for the - activation/deactivation of one variable. -*/ - -struct active_var_struct { - const enkf_config_node_type * config_node; /* The enkf_config_node instance this is all about - pointer to *shared* resource. */ - active_mode_type active_mode; - void * active_config; /* An object (type depending on datatype of config_node) used to hold info abourt partly active variable. - Owned by this object. If active_mode == all_active or active_mode == inactive, this can be NULL. */ - active_config_destructor_ftype * free_active_config; /* Destructor for the active_config object, can be NULL if that object is NULL. */ -}; - - - -/** - Similar to active_var_struct, but for observations. -*/ -struct active_obs_struct { - const obs_vector_type * obs_vector; /* The obs_node instance this is all about - pointer to *shared* resource. */ - active_mode_type active_mode; - void * active_config; /* An object (type depending on datatype of obs_node) used to hold info abourt partly active variable. - Owned by this object. If active_mode == all_active or active_mode == inactive, this can be NULL. */ - active_config_destructor_ftype * free_active_config; /* Destructor for the active_config object, can be NULL if that object is NULL. */ -}; - - - - diff --git a/ThirdParty/Ert/libenkf/src/analysis_config.c b/ThirdParty/Ert/libenkf/src/analysis_config.c deleted file mode 100644 index 9e18efd529..0000000000 --- a/ThirdParty/Ert/libenkf/src/analysis_config.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'analysis_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - - -#define UPDATE_OVERLAP_KEY "OVERLAP_LIMIT" -#define UPDATE_STD_CUTOFF_KEY "STD_CUTOFF" - - -#define ANALYSIS_CONFIG_TYPE_ID 64431306 - -struct analysis_config_struct { - UTIL_TYPE_ID_DECLARATION; - hash_type * analysis_modules; - analysis_module_type * analysis_module; - char * log_path; /* Points to directory with update logs. */ - bool merge_observations; /* When observing from time1 to time2 - should ALL observations in between be used? */ - bool rerun; /* Should we rerun the simulator when the parameters have been updated? */ - int rerun_start; /* When rerunning - from where should we start? */ - config_settings_type * update_settings; - - char * PC_filename; - char * PC_path; - bool store_PC; - bool single_node_update; /* When creating the default ALL_ACTIVE local configuration. */ - rng_type * rng; - analysis_iter_config_type * iter_config; - int min_realisations; - bool stop_long_running; - bool std_scale_correlated_obs; - int max_runtime; - double global_std_scaling; -}; - - - - -UTIL_IS_INSTANCE_FUNCTION( analysis_config , ANALYSIS_CONFIG_TYPE_ID ) - -/*****************************************************************/ -/* - -Interacting with modules ------------------------- - -The modules which are included in the build must be installed/loaded with a -hard-coded call to analysis_config_load_internal_module(). External modules -are loaded with the config statement: - - ANALYSIS_LOAD ModuleName libfile - -Where 'ModuleName is the name you want to use to refer to the module, and -libfile is the name of the library file which implements the analysis -module[1]. - -It is possible to create a copy of an analysis module under a different -name, this can be convenient when trying out the same algorithm with -different parameter settings. I.e. based on the built in module STD_ENKF we -can create two copies with high and low truncation respectively: - - ANALYSIS_COPY STD_ENKF ENKF_HIGH_TRUNCATION - ANALYSIS_COPY STD_ENKF ENKF_LOW_TRUNCATION - -The copy operation does not differentiate between external and internal -modules. When a module has been loaded you can set internal parameters for -the module with the config command: - - ANALYSIS_SET_VAR ModuleName VariableName Value - -The module will be called with a function for setting variables which gets -the VariableName and value parameters as input; if the module recognizes -VariableName and Value is of the right type the module should set the -internal variable accordingly. If the module does not recognize the -variable name a warning will be printed on stderr, but no further action. - -The actual analysis module to use is selected with the statement: - -ANALYSIS_SELECT ModuleName - -[1] The libfile argument should include the '.so' extension, and can - optionally contain a path component. The libfile will be passed directly to - the dlopen() library call, this implies that normal runtime linking - conventions apply - i.e. you have three options: - - 1. The library name is given with a full path. - 2. The library is in a standard location for shared libraries. - 3. The library is in one of the directories mentioned in the - LD_LIBRARY_PATH environment variable. - -*/ - - -/*****************************************************************/ - -bool analysis_config_have_enough_realisations( const analysis_config_type * config , int realisations, int ensemble_size) { - if (config->min_realisations > 0) { - /* A value > 0 has been set in the config; compare with this value. */ - return realisations >= config->min_realisations; - } - else { - return realisations >= ensemble_size; - } -} - -void analysis_config_set_stop_long_running( analysis_config_type * config, bool stop_long_running ) { - config->stop_long_running = stop_long_running; -} - -bool analysis_config_get_stop_long_running( const analysis_config_type * config) { - return config->stop_long_running; -} - -bool analysis_config_get_std_scale_correlated_obs( const analysis_config_type * config) { - return config->std_scale_correlated_obs; -} - -void analysis_config_set_std_scale_correlated_obs( analysis_config_type * config, bool std_scale_correlated_obs) { - config->std_scale_correlated_obs = std_scale_correlated_obs; -} - -double analysis_config_get_global_std_scaling(const analysis_config_type * config) { - return config->global_std_scaling; -} - -void analysis_config_set_global_std_scaling(analysis_config_type * config, double global_std_scaling) { - config->global_std_scaling = global_std_scaling; -} - -int analysis_config_get_max_runtime( const analysis_config_type * config ) { - return config->max_runtime; -} - -void analysis_config_set_max_runtime( analysis_config_type * config, int max_runtime ) { - config->max_runtime = max_runtime; -} - -static void analysis_config_set_min_realisations( analysis_config_type * config , int min_realisations) { - config->min_realisations = min_realisations; -} - - -stringlist_type * analysis_config_alloc_module_names( analysis_config_type * config ) { - return hash_alloc_stringlist( config->analysis_modules ); -} - -void analysis_config_set_store_PC( analysis_config_type * config , bool store_PC) { - config->store_PC = store_PC; -} - -bool analysis_config_get_store_PC( const analysis_config_type * config ) { - return config->store_PC; -} - -void analysis_config_set_PC_filename( analysis_config_type * config , const char * filename ) { - config->PC_filename = util_realloc_string_copy( config->PC_filename , filename ); -} - -const char * analysis_config_get_PC_filename( const analysis_config_type * config ) { - return config->PC_filename; -} - - -void analysis_config_set_PC_path( analysis_config_type * config , const char * path ) { - config->PC_path = util_realloc_string_copy( config->PC_path , path ); -} - -const char * analysis_config_get_PC_path( const analysis_config_type * config ) { - return config->PC_path; -} - - -void analysis_config_set_alpha( analysis_config_type * config , double alpha) { - config_settings_set_double_value(config->update_settings, UPDATE_OVERLAP_KEY, alpha ); -} - - -double analysis_config_get_alpha(const analysis_config_type * config) { - return config_settings_get_double_value(config->update_settings, UPDATE_OVERLAP_KEY); -} - -void analysis_config_set_std_cutoff( analysis_config_type * config , double std_cutoff ) { - config_settings_set_double_value(config->update_settings, UPDATE_STD_CUTOFF_KEY, std_cutoff ); -} - -double analysis_config_get_std_cutoff(const analysis_config_type * config) { - return config_settings_get_double_value(config->update_settings, UPDATE_STD_CUTOFF_KEY); -} - - -void analysis_config_set_log_path(analysis_config_type * config , const char * log_path ) { - config->log_path = util_realloc_string_copy(config->log_path , log_path); -} - - -/** - Will in addition create the path. -*/ -const char * analysis_config_get_log_path( const analysis_config_type * config ) { - util_make_path( config->log_path ); - return config->log_path; -} - - - -void analysis_config_set_rerun_start( analysis_config_type * config , int rerun_start ) { - config->rerun_start = rerun_start; -} - -void analysis_config_set_rerun(analysis_config_type * config , bool rerun) { - config->rerun = rerun; -} - -bool analysis_config_get_rerun(const analysis_config_type * config) { - return config->rerun; -} - -void analysis_config_set_single_node_update(analysis_config_type * config , bool single_node_update) { - config->single_node_update = single_node_update; -} - -bool analysis_config_get_single_node_update(const analysis_config_type * config) { - return config->single_node_update; -} - - -int analysis_config_get_rerun_start(const analysis_config_type * config) { - return config->rerun_start; -} - - -void analysis_config_set_merge_observations( analysis_config_type * config , bool merge_observations) { - config->merge_observations = merge_observations; -} - - - -/*****************************************************************/ - -void analysis_config_load_internal_module( analysis_config_type * config , - const char * symbol_table ) { - analysis_module_type * module = analysis_module_alloc_internal( config->rng , symbol_table ); - if (module != NULL) - hash_insert_hash_owned_ref( config->analysis_modules , analysis_module_get_name( module ) , module , analysis_module_free__ ); - else - fprintf(stderr,"** Warning: failed to load module %s from %s.\n", analysis_module_get_name( module ) , symbol_table); -} - - -void analysis_config_load_all_external_modules_from_config ( analysis_config_type * analysis, const config_content_type * config) { - - if (config_content_has_item( config, ANALYSIS_LOAD_KEY)) { - const config_content_item_type * load_item = config_content_get_item( config , ANALYSIS_LOAD_KEY ); - for (int i=0; i < config_content_item_get_size( load_item ); i++) { - const config_content_node_type * load_node = config_content_item_iget_node( load_item , i ); - const char * user_name = config_content_node_iget( load_node , 0 ); - const char * lib_name = config_content_node_iget( load_node , 1 ); - - analysis_config_load_external_module( analysis , lib_name , user_name); - } - } -} - - -bool analysis_config_load_external_module( analysis_config_type * config , - const char * lib_name, - const char * user_name) { - analysis_module_type * module = analysis_module_alloc_external( config->rng , lib_name ); - if (module != NULL) { - if (user_name) - analysis_module_set_name(module, user_name); - hash_insert_hash_owned_ref( config->analysis_modules , analysis_module_get_name( module ) , module , analysis_module_free__ ); - return true; - } else { - fprintf(stderr,"** Warning: failed to load module from %s.\n",lib_name); - return false; - } -} - - -void analysis_config_add_module_copy( analysis_config_type * config , - const char * src_name , - const char * target_name) { - const analysis_module_type * src_module = analysis_config_get_module( config , src_name ); - analysis_module_type * target_module; - - if (analysis_module_internal( src_module )) { - const char * symbol_table = analysis_module_get_table_name( src_module ); - target_module = analysis_module_alloc_internal( config->rng , symbol_table ); - } else { - const char * lib_name = analysis_module_get_lib_name( src_module ); - target_module = analysis_module_alloc_external( config->rng , lib_name ); - } - - hash_insert_hash_owned_ref( config->analysis_modules , target_name , target_module , analysis_module_free__ ); - analysis_module_set_name( target_module , target_name ); -} - - - -/* - If module_name == NULL we will reload the current module. Unloading - modules is based on the dlclose() system call; internally the - dlopen() / dlclose() systems implements a reference counting to the - shared objects, i.e. if you have several modules defined in the same - shared library the dlclose() call will not unload the module - completely, and a subsequent dlopen() call will be satisfied by the - stale shared objects still mapped. Practically this means that: - - * Internal modules (all in libanalysis.so) can not be reloaded. - - * Modules which have been involved in copy operations, either as - source or target can not be reloaded. -*/ - -void analysis_config_reload_module( analysis_config_type * config , const char * module_name) { - analysis_module_type * module; - if (module_name != NULL) - module = analysis_config_get_module( config , module_name ); - else - module = config->analysis_module; - - if (!analysis_module_internal( module )) { - char * user_name = util_alloc_string_copy(analysis_module_get_name( module )); - char * lib_name = util_alloc_string_copy(analysis_module_get_lib_name( module )); - - bool is_current = false; - if (module == config->analysis_module) { - config->analysis_module = NULL; - is_current = true; - } - - hash_del( config->analysis_modules , user_name ); - analysis_config_load_external_module( config , user_name , lib_name ); - if (is_current) - analysis_config_select_module( config , user_name ); - - free( lib_name ); - free( user_name ); - } else - fprintf(stderr,"** Warning: Internal modules can not be reloaded.\n"); -} - - -analysis_module_type * analysis_config_get_module( analysis_config_type * config , const char * module_name ) { - return hash_get( config->analysis_modules , module_name ); -} - -bool analysis_config_has_module(analysis_config_type * config , const char * module_name) { - return hash_has_key( config->analysis_modules , module_name ); -} - -bool analysis_config_get_module_option( const analysis_config_type * config , long flag) { - if (config->analysis_module) - return analysis_module_check_option(config->analysis_module , flag); - else - return false; -} - - -bool analysis_config_select_module( analysis_config_type * config , const char * module_name ) { - if (analysis_config_has_module( config , module_name )) { - analysis_module_type * module = analysis_config_get_module( config , module_name ); - - if (analysis_module_check_option( module , ANALYSIS_ITERABLE)) { - if (analysis_config_get_single_node_update( config )) { - fprintf(stderr," ** Warning: the module:%s requires the setting \"SINGLE_NODE_UPDATE FALSE\" in the config file.\n" , module_name); - fprintf(stderr," ** the module has NOT been selected. \n"); - return false; - } - } - - config->analysis_module = module; - return true; - } else { - if (config->analysis_module == NULL) - util_abort("%s: sorry module:%s does not exist - and no module currently selected\n",__func__ , module_name); - else - fprintf(stderr , "** Warning: analysis module:%s does not exist - current selection unchanged:%s\n", - module_name , - analysis_module_get_name( config->analysis_module )); - return false; - } -} - - -analysis_module_type * analysis_config_get_active_module( analysis_config_type * config ) { - return config->analysis_module; -} - - -const char * analysis_config_get_active_module_name( const analysis_config_type * config ) { - if (config->analysis_module) - return analysis_module_get_name( config->analysis_module ); - else - return NULL; -} - - - -/*****************************************************************/ - - -void analysis_config_load_internal_modules( analysis_config_type * config ) { - analysis_config_load_internal_module( config , "STD_ENKF"); - analysis_config_load_internal_module( config , "NULL_ENKF"); - analysis_config_load_internal_module( config , "SQRT_ENKF"); - analysis_config_load_internal_module( config , "CV_ENKF"); - analysis_config_load_internal_module( config , "BOOTSTRAP_ENKF"); - analysis_config_load_internal_module( config , "FWD_STEP_ENKF"); - analysis_config_select_module( config , DEFAULT_ANALYSIS_MODULE); -} - -/** - The analysis_config object is instantiated with the default values - for enkf_defaults.h -*/ - -void analysis_config_init( analysis_config_type * analysis , const config_content_type * config ) { - config_settings_apply(analysis->update_settings , config); - - if (config_content_has_item( config , UPDATE_LOG_PATH_KEY )) - analysis_config_set_log_path( analysis , config_content_get_value( config , UPDATE_LOG_PATH_KEY )); - - if (config_content_has_item( config , STD_CUTOFF_KEY )) - analysis_config_set_std_cutoff( analysis , config_content_get_value_as_double( config , STD_CUTOFF_KEY )); - - if (config_content_has_item( config , ENKF_ALPHA_KEY )) - analysis_config_set_alpha( analysis , config_content_get_value_as_double( config , ENKF_ALPHA_KEY )); - - if (config_content_has_item( config , ENKF_MERGE_OBSERVATIONS_KEY )) - analysis_config_set_merge_observations( analysis , config_content_get_value_as_bool( config , ENKF_MERGE_OBSERVATIONS_KEY )); - - if (config_content_has_item( config , ENKF_RERUN_KEY )) - analysis_config_set_rerun( analysis , config_content_get_value_as_bool( config , ENKF_RERUN_KEY )); - - if (config_content_has_item( config , SINGLE_NODE_UPDATE_KEY )) - analysis_config_set_single_node_update( analysis , config_content_get_value_as_bool( config , SINGLE_NODE_UPDATE_KEY )); - - if (config_content_has_item( config , STD_SCALE_CORRELATED_OBS_KEY )) - analysis_config_set_std_scale_correlated_obs( analysis , config_content_get_value_as_bool( config , STD_SCALE_CORRELATED_OBS_KEY )); - - if (config_content_has_item( config , RERUN_START_KEY )) - analysis_config_set_rerun_start( analysis , config_content_get_value_as_int( config , RERUN_START_KEY )); - - if (config_content_has_item( config , MIN_REALIZATIONS_KEY )) { - - config_content_node_type * config_content = config_content_get_value_node(config , MIN_REALIZATIONS_KEY); - char * min_realizations_string = config_content_node_alloc_joined_string(config_content, " "); - - int num_realizations = config_content_get_value_as_int(config, NUM_REALIZATIONS_KEY); - int min_realizations = DEFAULT_ANALYSIS_MIN_REALISATIONS; - double percent = 0.0; - if (util_sscanf_percent(min_realizations_string, &percent)) { - - min_realizations = num_realizations * percent/100; - } else { - bool min_realizations_int_exists = util_sscanf_int(min_realizations_string, &min_realizations); - if (!min_realizations_int_exists) - fprintf(stderr, "Method %s: failed to read integer value for MIN_REALIZATIONS_KEY\n", __func__); - } - - if (min_realizations > num_realizations) - min_realizations = num_realizations; - - analysis_config_set_min_realisations(analysis, min_realizations); - free(min_realizations_string); - } - - if (config_content_has_item( config , STOP_LONG_RUNNING_KEY )) - analysis_config_set_stop_long_running( analysis , config_content_get_value_as_bool( config , STOP_LONG_RUNNING_KEY )); - - if (config_content_has_item( config, MAX_RUNTIME_KEY)) { - analysis_config_set_max_runtime( analysis, config_content_get_value_as_int( config, MAX_RUNTIME_KEY )); - } - - - /* Loading external modules */ - analysis_config_load_all_external_modules_from_config(analysis, config); - - - /* Reload/copy modules. */ - { - if (config_content_has_item( config , ANALYSIS_COPY_KEY )) { - const config_content_item_type * copy_item = config_content_get_item( config , ANALYSIS_COPY_KEY ); - for (int i=0; i < config_content_item_get_size( copy_item ); i++) { - const config_content_node_type * copy_node = config_content_item_iget_node( copy_item , i ); - const char * src_name = config_content_node_iget( copy_node , 0 ); - const char * target_name = config_content_node_iget( copy_node , 1 ); - - analysis_config_add_module_copy( analysis , src_name , target_name); - } - } - } - - - /* Setting variables for analysis modules */ - { - if (config_content_has_item( config , ANALYSIS_SET_VAR_KEY )) { - const config_content_item_type * assign_item = config_content_get_item( config , ANALYSIS_SET_VAR_KEY ); - for (int i=0; i < config_content_item_get_size( assign_item ); i++) { - const config_content_node_type * assign_node = config_content_item_iget_node( assign_item , i ); - - const char * module_name = config_content_node_iget( assign_node , 0 ); - const char * var_name = config_content_node_iget( assign_node , 1 ); - analysis_module_type * module = analysis_config_get_module( analysis , module_name ); - { - char * value = NULL; - - for (int j=2; j < config_content_node_get_size( assign_node ); j++) { - const char * config_value = config_content_node_iget( assign_node , j ); - if (value == NULL) - value = util_alloc_string_copy( config_value ); - else { - value = util_strcat_realloc( value , " " ); - value = util_strcat_realloc( value , config_value ); - } - } - - analysis_module_set_var( module , var_name , value ); - free( value ); - } - } - } - } - - if (config_content_has_item( config, ANALYSIS_SELECT_KEY )) - analysis_config_select_module( analysis , config_content_get_value( config , ANALYSIS_SELECT_KEY )); - - analysis_iter_config_init( analysis->iter_config , config ); -} - - - -bool analysis_config_get_merge_observations(const analysis_config_type * config) { - return config->merge_observations; -} - - -analysis_iter_config_type * analysis_config_get_iter_config( const analysis_config_type * config ) { - return config->iter_config; -} - - -void analysis_config_free(analysis_config_type * config) { - analysis_iter_config_free( config->iter_config ); - hash_free( config->analysis_modules ); - config_settings_free( config->update_settings ); - free( config->log_path ); - free( config->PC_filename ); - free( config->PC_path ); - free( config ); -} - - - -analysis_config_type * analysis_config_alloc( rng_type * rng ) { - analysis_config_type * config = util_malloc( sizeof * config ); - UTIL_TYPE_ID_INIT( config , ANALYSIS_CONFIG_TYPE_ID ); - - config->log_path = NULL; - config->PC_filename = NULL; - config->PC_path = NULL; - config->update_settings = config_settings_alloc( UPDATE_SETTING_KEY ); - config_settings_add_double_setting(config->update_settings, UPDATE_OVERLAP_KEY , DEFAULT_ENKF_ALPHA); - config_settings_add_double_setting(config->update_settings, UPDATE_STD_CUTOFF_KEY, DEFAULT_ENKF_STD_CUTOFF ); - - analysis_config_set_merge_observations( config , DEFAULT_MERGE_OBSERVATIONS ); - analysis_config_set_rerun( config , DEFAULT_RERUN ); - analysis_config_set_rerun_start( config , DEFAULT_RERUN_START ); - analysis_config_set_single_node_update( config , DEFAULT_SINGLE_NODE_UPDATE ); - analysis_config_set_log_path( config , DEFAULT_UPDATE_LOG_PATH); - - analysis_config_set_store_PC( config , DEFAULT_STORE_PC ); - analysis_config_set_PC_filename( config , DEFAULT_PC_FILENAME ); - analysis_config_set_PC_path( config , DEFAULT_PC_PATH ); - analysis_config_set_min_realisations( config , DEFAULT_ANALYSIS_MIN_REALISATIONS ); - analysis_config_set_stop_long_running( config , DEFAULT_ANALYSIS_STOP_LONG_RUNNING ); - analysis_config_set_max_runtime( config , DEFAULT_MAX_RUNTIME ); - - config->analysis_module = NULL; - config->analysis_modules = hash_alloc(); - config->rng = rng; - config->iter_config = analysis_iter_config_alloc(); - config->std_scale_correlated_obs = false; - config->global_std_scaling = 1.0; - return config; -} - - - -/*****************************************************************/ -/* - Keywords for the analysis - all optional. The analysis_config object - is instantiated with defaults from enkf_defaults.h -*/ - -void analysis_config_add_config_items( config_parser_type * config ) { - config_schema_item_type * item; - - config_add_key_value( config , ENKF_ALPHA_KEY , false , CONFIG_FLOAT); - config_add_key_value( config , STD_CUTOFF_KEY , false , CONFIG_FLOAT); - config_settings_init_parser__( UPDATE_SETTING_KEY , config , false ); - - config_add_key_value( config , ENKF_MERGE_OBSERVATIONS_KEY , false , CONFIG_BOOL); - config_add_key_value( config , SINGLE_NODE_UPDATE_KEY , false , CONFIG_BOOL); - config_add_key_value( config , ENKF_CROSS_VALIDATION_KEY , false , CONFIG_BOOL); - config_add_key_value( config , ENKF_LOCAL_CV_KEY , false , CONFIG_BOOL); - config_add_key_value( config , ENKF_PEN_PRESS_KEY , false , CONFIG_BOOL); - config_add_key_value( config , ENKF_SCALING_KEY , false , CONFIG_BOOL); - config_add_key_value( config , ENKF_KERNEL_REG_KEY , false , CONFIG_BOOL); - config_add_key_value( config , ENKF_KERNEL_FUNC_KEY , false , CONFIG_INT); - config_add_key_value( config , ENKF_KERNEL_PARAM_KEY , false , CONFIG_INT); - config_add_key_value( config , ENKF_CV_FOLDS_KEY , false , CONFIG_INT); - config_add_key_value( config , ENKF_RERUN_KEY , false , CONFIG_BOOL); - config_add_key_value( config , RERUN_START_KEY , false , CONFIG_INT); - config_add_key_value( config , UPDATE_LOG_PATH_KEY , false , CONFIG_STRING); - config_add_key_value( config , MIN_REALIZATIONS_KEY , false , CONFIG_STRING ); - config_add_key_value( config , MAX_RUNTIME_KEY , false , CONFIG_INT ); - config_add_key_value( config , STD_SCALE_CORRELATED_OBS_KEY, false , CONFIG_BOOL ); - - item = config_add_key_value( config , STOP_LONG_RUNNING_KEY, false, CONFIG_BOOL ); - stringlist_type * child_list = stringlist_alloc_new(); - stringlist_append_ref(child_list, MIN_REALIZATIONS_KEY); - config_schema_item_set_required_children_on_value(item , "TRUE" , child_list); - stringlist_free(child_list); - - config_add_key_value( config , ANALYSIS_SELECT_KEY , false , CONFIG_STRING); - - item = config_add_schema_item( config , ANALYSIS_LOAD_KEY , false ); - config_schema_item_set_argc_minmax( item , 2 , 2); - - item = config_add_schema_item( config , ANALYSIS_COPY_KEY , false ); - config_schema_item_set_argc_minmax( item , 2 , 2); - - - item = config_add_schema_item( config , ANALYSIS_SET_VAR_KEY , false ); - config_schema_item_set_argc_minmax( item , 3 , CONFIG_DEFAULT_ARG_MAX); - analysis_iter_config_add_config_items( config ); -} - - - -void analysis_config_fprintf_config( analysis_config_type * config , FILE * stream) { - fprintf( stream , CONFIG_COMMENTLINE_FORMAT ); - fprintf( stream , CONFIG_COMMENT_FORMAT , "Here comes configuration information related to the EnKF analysis."); - - - if (config->merge_observations != DEFAULT_MERGE_OBSERVATIONS) { - fprintf( stream , CONFIG_KEY_FORMAT , ENKF_MERGE_OBSERVATIONS_KEY); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , CONFIG_BOOL_STRING( config->merge_observations )); - } - - if (config->single_node_update != DEFAULT_SINGLE_NODE_UPDATE) { - fprintf( stream , CONFIG_KEY_FORMAT , SINGLE_NODE_UPDATE_KEY); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , CONFIG_BOOL_STRING( config->single_node_update )); - } - - if (config->rerun) { - fprintf( stream , CONFIG_KEY_FORMAT , ENKF_RERUN_KEY); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , CONFIG_BOOL_STRING( config->rerun )); - } - - if (config->rerun_start != DEFAULT_RERUN_START) { - fprintf( stream , CONFIG_KEY_FORMAT , RERUN_START_KEY); - fprintf( stream , CONFIG_INT_FORMAT , config->rerun_start ); - fprintf( stream , "\n"); - } - - if (config->log_path != NULL) { - fprintf( stream , CONFIG_KEY_FORMAT , UPDATE_LOG_PATH_KEY); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , config->log_path ); - } - - fprintf(stream , "\n\n"); -} - - - diff --git a/ThirdParty/Ert/libenkf/src/analysis_iter_config.c b/ThirdParty/Ert/libenkf/src/analysis_iter_config.c deleted file mode 100644 index b269ca447d..0000000000 --- a/ThirdParty/Ert/libenkf/src/analysis_iter_config.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'analysis_iter_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - - -struct analysis_iter_config_struct { - char * case_fmt; - stringlist_type * storage; - int num_iterations; - int num_iter_tries; - bool case_set; - bool num_iterations_set; -}; - - -void analysis_iter_config_set_num_iterations( analysis_iter_config_type * config , int num_iterations) { - config->num_iterations = num_iterations; - config->num_iterations_set = true; -} - -int analysis_iter_config_get_num_iterations( const analysis_iter_config_type * config ) { - return config->num_iterations; -} - -bool analysis_iter_config_num_iterations_set( const analysis_iter_config_type * config ) { - return config->num_iterations_set; -} - - -void analysis_iter_config_set_num_retries_per_iteration( analysis_iter_config_type * config , int num_iter_tries) { - config->num_iter_tries = num_iter_tries; -} - -int analysis_iter_config_get_num_retries_per_iteration( const analysis_iter_config_type * config ) { - return config->num_iter_tries; -} - - -void analysis_iter_config_set_case_fmt( analysis_iter_config_type * config , const char * case_fmt) { - config->case_fmt = util_realloc_string_copy( config->case_fmt , case_fmt ); - config->case_set = true; -} - - -bool analysis_iter_config_case_fmt_set( const analysis_iter_config_type * config ) { - return config->case_set; -} - - -char * analysis_iter_config_get_case_fmt( analysis_iter_config_type * config) { - return config->case_fmt; -} - - -analysis_iter_config_type * analysis_iter_config_alloc() { - analysis_iter_config_type * config = util_malloc( sizeof * config ); - config->case_fmt = NULL; - analysis_iter_config_set_case_fmt( config, DEFAULT_ANALYSIS_ITER_CASE); - config->storage = stringlist_alloc_new(); - analysis_iter_config_set_num_iterations( config , DEFAULT_ANALYSIS_NUM_ITERATIONS ); - analysis_iter_config_set_num_retries_per_iteration(config, DEFAULT_ITER_RETRY_COUNT); - - config->num_iterations_set = false; - config->case_set = false; - return config; -} - -void analysis_iter_config_free( analysis_iter_config_type * config ) { - util_safe_free( config->case_fmt ); - stringlist_free( config->storage ); - util_safe_free( config ); -} - - -const char * analysis_iter_config_iget_case( analysis_iter_config_type * config , int iter) { - if (config->case_fmt != NULL) { - char * fs_case = util_alloc_sprintf( config->case_fmt , iter ); - stringlist_append_owned_ref( config->storage , fs_case); - return fs_case; - } else - return NULL; -} - - -void analysis_iter_config_add_config_items( config_parser_type * config ) { - config_add_key_value( config , ITER_CASE_KEY , false , CONFIG_STRING); - config_add_key_value( config , ITER_COUNT_KEY , false , CONFIG_INT); - config_add_key_value( config , ITER_RETRY_COUNT_KEY , false , CONFIG_INT); -} - - -void analysis_iter_config_init(analysis_iter_config_type * iter_config , const config_content_type * config) { - if (config_content_has_item( config , ITER_CASE_KEY )) - analysis_iter_config_set_case_fmt( iter_config , config_content_get_value( config , ITER_CASE_KEY )); - - if (config_content_has_item( config , ITER_COUNT_KEY )) - analysis_iter_config_set_num_iterations( iter_config , config_content_get_value_as_int( config , ITER_COUNT_KEY )); - - if (config_content_has_item( config , ITER_RETRY_COUNT_KEY )) - analysis_iter_config_set_num_retries_per_iteration( iter_config , config_content_get_value_as_int( config , ITER_RETRY_COUNT_KEY )); -} - - diff --git a/ThirdParty/Ert/libenkf/src/block_fs_driver.c b/ThirdParty/Ert/libenkf/src/block_fs_driver.c deleted file mode 100644 index f22eb6e5ab..0000000000 --- a/ThirdParty/Ert/libenkf/src/block_fs_driver.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'block_fs_driver.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -typedef struct bfs_struct bfs_type; -typedef struct bfs_config_struct bfs_config_type; - -struct bfs_config_struct { - int fsync_interval; - double fragmentation_limit; - bool read_only; - bool preload; - int block_size; - int max_cache_size; - bool bfs_lock; -}; - - -#define BFS_TYPE_ID 5510643 - -struct bfs_struct { - UTIL_TYPE_ID_DECLARATION; - /*-----------------------------------------------------------------*/ - /* New variables */ - block_fs_type * block_fs; - char * mountfile; // The full path to the file mounted by the block_fs layer - including extension. - - const bfs_config_type * config; -}; - - - -struct block_fs_driver_struct { - FS_DRIVER_FIELDS; - int __id; - int num_fs; - bfs_config_type * config; - - // New variables - bfs_type ** fs_list; -}; - -/*****************************************************************/ - -bfs_config_type * bfs_config_alloc( fs_driver_enum driver_type , bool read_only, bool bfs_lock) { - const int PARAMETER_blocksize = 64; - const int DYNAMIC_blocksize = 64; - const int DEFAULT_blocksize = 64; - - const bool PARAMETER_preload = false; - const bool DYNAMIC_preload = true; - const bool DEFAULT_preload = false; - - const int max_cache_size = 512; - const int fsync_interval = 10; /* An fsync() call is issued for every 10'th write. */ - const double fragmentation_limit = 1.0; /* 1.0 => NO defrag is run. */ - - { - bfs_config_type * config = util_malloc( sizeof * config ); - config->max_cache_size = max_cache_size; - config->fsync_interval = fsync_interval; - config->fragmentation_limit = fragmentation_limit; - config->read_only = read_only; - config->bfs_lock = bfs_lock; - - switch (driver_type) { - case( DRIVER_PARAMETER ): - config->block_size = PARAMETER_blocksize; - config->preload = PARAMETER_preload; - break; - case(DRIVER_DYNAMIC_FORECAST): - config->block_size = DYNAMIC_blocksize; - config->preload = DYNAMIC_preload; - break; - default: - config->block_size = DEFAULT_blocksize; - config->preload = DEFAULT_preload; - } - return config; - } -} - -void bfs_config_free( bfs_config_type * config ) { - free( config ); -} - -/*****************************************************************/ - -static UTIL_SAFE_CAST_FUNCTION(bfs , BFS_TYPE_ID); - -static void bfs_close( bfs_type * bfs ) { - if (bfs->block_fs != NULL) - block_fs_close( bfs->block_fs , false); - free( bfs->mountfile ); - free( bfs ); -} - - -static void * bfs_close__( void * arg ) { - bfs_type * bfs = ( bfs_type * ) arg; - bfs_close( bfs ); - - return NULL; -} - -static bfs_type * bfs_alloc( const bfs_config_type * config ) { - bfs_type * fs = util_malloc( sizeof * fs ); - UTIL_TYPE_ID_INIT( fs , BFS_TYPE_ID ); - fs->config = config; - - // New init - fs->mountfile = NULL; - - return fs; -} - - -static bfs_type * bfs_alloc_new( const bfs_config_type * config , char * mountfile) { - bfs_type * bfs = bfs_alloc( config ); - - bfs->mountfile = mountfile; // Warning pattern break: This is allocated in external scope; and the bfs takes ownership. - return bfs; -} - - -static void bfs_mount( bfs_type * bfs) { - const bfs_config_type * config = bfs->config; - bfs->block_fs = block_fs_mount( bfs->mountfile , - config->block_size , - config->max_cache_size , - config->fragmentation_limit , - config->fsync_interval , - config->preload , - config->read_only, - config->bfs_lock); -} - - -static void * bfs_mount__( void * arg ) { - bfs_type * bfs = bfs_safe_cast( arg ); - bfs_mount( bfs ); - //printf("."); - //fflush( stdout ); - return NULL; -} - - - - -static void bfs_fsync( bfs_type * bfs ) { - block_fs_fsync( bfs->block_fs ); -} - - - -/*****************************************************************/ - - -static void block_fs_driver_assert_cast(block_fs_driver_type * block_fs_driver) { - if (block_fs_driver->__id != BLOCK_FS_DRIVER_ID) - util_abort("%s: internal error - cast failed - aborting \n",__func__); -} - - -static block_fs_driver_type * block_fs_driver_safe_cast( void * __driver) { - block_fs_driver_type * driver = (block_fs_driver_type *) __driver; - block_fs_driver_assert_cast(driver); - return driver; -} - -static char * block_fs_driver_alloc_node_key( const block_fs_driver_type * driver , const char * node_key , int report_step , int iens) { - char * key = util_alloc_sprintf("%s.%d.%d" , node_key , report_step , iens); - return key; -} - - -static char * block_fs_driver_alloc_vector_key( const block_fs_driver_type * driver , const char * node_key , int iens) { - char * key = util_alloc_sprintf("%s.%d" , node_key , iens); - return key; -} - -/** - This function will take an input string, and try to to parse it as - string.int.int, where string is the normal enkf key, and the two - integers are report_step and ensemble number respectively. The - storage for the enkf_key is allocated here in this function, and - must be freed by the calling scope. - - If the parsing fails the function will return false, and *config_key - will be set to NULL; in this case the report_step and iens poinyers - will not be touched. -*/ - -bool block_fs_sscanf_key(const char * key , char ** config_key , int * __report_step , int * __iens) { - char ** tmp; - int num_items; - - *config_key = NULL; - util_split_string(key , "." , &num_items , &tmp); /* The key can contain additional '.' - can not use sscanf(). */ - if (num_items >= 3) { - int report_step , iens; - if (util_sscanf_int(tmp[num_items - 2] , &report_step) && util_sscanf_int(tmp[num_items - 1] , &iens)) { - /* OK - all is hunkadory */ - *__report_step = report_step; - *__iens = iens; - *config_key = util_alloc_joined_string((const char **) tmp , num_items - 2 , "."); /* This must bee freed by the calling scope */ - util_free_stringlist( tmp , num_items ); - return true; - } else - /* Failed to parse the two last items as integers. */ - return false; - } else - /* Did not have at least three items. */ - return false; -} - - - - -static bfs_type * block_fs_driver_get_fs( block_fs_driver_type * driver , int iens ) { - int phase = (iens % driver->num_fs); - - return driver->fs_list[phase]; -} - - - -static void block_fs_driver_load_node(void * _driver , const char * node_key , int report_step , int iens , buffer_type * buffer) { - block_fs_driver_type * driver = block_fs_driver_safe_cast( _driver ); - { - char * key = block_fs_driver_alloc_node_key( driver , node_key , report_step , iens ); - bfs_type * bfs = block_fs_driver_get_fs( driver , iens ); - - block_fs_fread_realloc_buffer( bfs->block_fs , key , buffer); - - free( key ); - } -} - - -static void block_fs_driver_load_vector(void * _driver , const char * node_key , int iens , buffer_type * buffer) { - block_fs_driver_type * driver = block_fs_driver_safe_cast( _driver ); - { - char * key = block_fs_driver_alloc_vector_key( driver , node_key , iens ); - bfs_type * bfs = block_fs_driver_get_fs( driver , iens ); - - block_fs_fread_realloc_buffer( bfs->block_fs , key , buffer); - free( key ); - } -} - -/*****************************************************************/ - -static void block_fs_driver_save_node(void * _driver , const char * node_key , int report_step , int iens , buffer_type * buffer) { - block_fs_driver_type * driver = (block_fs_driver_type *) _driver; - block_fs_driver_assert_cast(driver); - { - char * key = block_fs_driver_alloc_node_key( driver , node_key , report_step , iens ); - bfs_type * bfs = block_fs_driver_get_fs( driver , iens ); - block_fs_fwrite_buffer( bfs->block_fs , key , buffer); - free( key ); - } -} - - -static void block_fs_driver_save_vector(void * _driver , const char * node_key , int iens , buffer_type * buffer) { - block_fs_driver_type * driver = (block_fs_driver_type *) _driver; - block_fs_driver_assert_cast(driver); - { - char * key = block_fs_driver_alloc_vector_key( driver , node_key , iens ); - bfs_type * bfs = block_fs_driver_get_fs( driver , iens ); - block_fs_fwrite_buffer( bfs->block_fs , key , buffer); - free( key ); - } -} - -/*****************************************************************/ - -void block_fs_driver_unlink_node(void * _driver , const char * node_key , int report_step , int iens ) { - block_fs_driver_type * driver = (block_fs_driver_type *) _driver; - block_fs_driver_assert_cast(driver); - { - char * key = block_fs_driver_alloc_node_key( driver , node_key , report_step , iens ); - bfs_type * bfs = block_fs_driver_get_fs( driver , iens ); - block_fs_unlink_file( bfs->block_fs , key ); - free( key ); - } -} - -void block_fs_driver_unlink_vector(void * _driver , const char * node_key , int iens ) { - block_fs_driver_type * driver = (block_fs_driver_type *) _driver; - block_fs_driver_assert_cast(driver); - { - char * key = block_fs_driver_alloc_vector_key( driver , node_key , iens ); - bfs_type * bfs = block_fs_driver_get_fs( driver , iens ); - block_fs_unlink_file( bfs->block_fs , key ); - free( key ); - } -} - - -/*****************************************************************/ - -bool block_fs_driver_has_node(void * _driver , const char * node_key , int report_step , int iens ) { - block_fs_driver_type * driver = (block_fs_driver_type *) _driver; - block_fs_driver_assert_cast(driver); - { - char * key = block_fs_driver_alloc_node_key( driver , node_key , report_step , iens ); - bfs_type * bfs = block_fs_driver_get_fs( driver , iens ); - bool has_node = block_fs_has_file( bfs->block_fs , key ); - free( key ); - return has_node; - } -} - - -bool block_fs_driver_has_vector(void * _driver , const char * node_key , int iens ) { - block_fs_driver_type * driver = (block_fs_driver_type *) _driver; - block_fs_driver_assert_cast(driver); - { - char * key = block_fs_driver_alloc_vector_key( driver , node_key , iens ); - bfs_type * bfs = block_fs_driver_get_fs( driver , iens ); - bool has_node = block_fs_has_file( bfs->block_fs , key ); - free( key ); - return has_node; - } -} - -/*****************************************************************/ - - - - - - - - - -void block_fs_driver_free(void *_driver) { - block_fs_driver_type * driver = block_fs_driver_safe_cast( _driver ); - { - int driver_nr; - thread_pool_type * tp = thread_pool_alloc( 4 , true); - for (driver_nr = 0; driver_nr < driver->num_fs; driver_nr++) - thread_pool_add_job( tp , bfs_close__ , driver->fs_list[driver_nr] ); - - thread_pool_join( tp ); - thread_pool_free( tp ); - } - bfs_config_free( driver->config ); - free( driver->fs_list ); - free(driver); -} - - - -static void block_fs_driver_fsync( void * _driver ) { - block_fs_driver_type * driver = (block_fs_driver_type *) _driver; - block_fs_driver_assert_cast(driver); - - { - int driver_nr; - block_fs_driver_type * driver = block_fs_driver_safe_cast(_driver); - for (driver_nr = 0; driver_nr < driver->num_fs; driver_nr++) - bfs_fsync( driver->fs_list[driver_nr] ); - } -} - - -static block_fs_driver_type * block_fs_driver_alloc(int num_fs) { - block_fs_driver_type * driver = util_malloc(sizeof * driver ); - { - fs_driver_type * fs_driver = (fs_driver_type *) driver; - fs_driver_init(fs_driver); - } - driver->load_node = block_fs_driver_load_node; - driver->save_node = block_fs_driver_save_node; - driver->unlink_node = block_fs_driver_unlink_node; - driver->has_node = block_fs_driver_has_node; - - driver->load_vector = block_fs_driver_load_vector; - driver->save_vector = block_fs_driver_save_vector; - driver->unlink_vector = block_fs_driver_unlink_vector; - driver->has_vector = block_fs_driver_has_vector; - - driver->free_driver = block_fs_driver_free; - driver->fsync_driver = block_fs_driver_fsync; - driver->__id = BLOCK_FS_DRIVER_ID; - driver->num_fs = num_fs; - - driver->fs_list = util_calloc( driver->num_fs , sizeof * driver->fs_list ); - return driver; -} - - - - -static void * block_fs_driver_alloc_new( fs_driver_enum driver_type , bool read_only , int num_fs , const char * mountfile_fmt, bool block_level_lock ) { - block_fs_driver_type * driver = block_fs_driver_alloc( num_fs); - driver->config = bfs_config_alloc( driver_type , read_only, block_level_lock ); - { - for (int ifs = 0; ifs < driver->num_fs; ifs++) - driver->fs_list[ifs] = bfs_alloc_new( driver->config , util_alloc_sprintf( mountfile_fmt , ifs) ); - } - return driver; -} - - -static void block_fs_driver_mount( block_fs_driver_type * driver ) { - thread_pool_type * tp = thread_pool_alloc( 4 , true ); - - for (int ifs = 0; ifs < driver->num_fs; ifs++) - thread_pool_add_job( tp , bfs_mount__ , driver->fs_list[ ifs ]); - - thread_pool_join( tp ); - thread_pool_free( tp ); -} - - - - - -/*****************************************************************/ - -void block_fs_driver_create_fs( FILE * stream , - const char * mount_point , - fs_driver_enum driver_type , - int num_fs , - const char * ens_path_fmt, - const char * filename ) { - - util_fwrite_int(driver_type , stream ); - util_fwrite_int(num_fs , stream ); - { - char * mountfile_fmt = util_alloc_sprintf("%s%c%s.mnt" , ens_path_fmt , UTIL_PATH_SEP_CHAR , filename ); - util_fwrite_string( mountfile_fmt , stream ); - free( mountfile_fmt ); - } - - for (int ifs = 0; ifs < num_fs; ifs++) { - char * path_fmt = util_alloc_sprintf("%s%c%s" , mount_point , UTIL_PATH_SEP_CHAR , ens_path_fmt); - char * ens_path = util_alloc_sprintf(path_fmt , ifs); - - util_make_path( ens_path ); - - free( path_fmt ); - free( ens_path ); - } - -} - - -/* - @path should contain both elements called root_path and case_path in - the block_fs_driver_create() function. -*/ - -void * block_fs_driver_open(FILE * fstab_stream , const char * mount_point , fs_driver_enum driver_type , bool read_only) { - int num_fs = util_fread_int( fstab_stream ); - char * tmp_fmt = util_fread_alloc_string( fstab_stream ); - char * mountfile_fmt = util_alloc_sprintf("%s%c%s" , mount_point , UTIL_PATH_SEP_CHAR , tmp_fmt ); - const bool block_level_lock = false; - - block_fs_driver_type * driver = block_fs_driver_alloc_new( driver_type , read_only , num_fs , mountfile_fmt, block_level_lock ); - - block_fs_driver_mount( driver ); - - free( tmp_fmt ); - free( mountfile_fmt ); - return driver; -} - - -void block_fs_driver_fskip(FILE * fstab_stream) { - util_fskip_int( fstab_stream ); - { - char * tmp_fmt = util_fread_alloc_string( fstab_stream ); - free( tmp_fmt ); - } -} diff --git a/ThirdParty/Ert/libenkf/src/block_obs.c b/ThirdParty/Ert/libenkf/src/block_obs.c deleted file mode 100644 index 61a6c4adea..0000000000 --- a/ThirdParty/Ert/libenkf/src/block_obs.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'block_obs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/** - See the overview documentation of the observation system in enkf_obs.c -*/ -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BLOCK_OBS_TYPE_ID 661098 -#define POINT_OBS_TYPE_ID 778196 - - -typedef struct { - UTIL_TYPE_ID_DECLARATION; - block_obs_source_type source_type; - int i; - int j; - int k; - int active_index; - double value; - double std; - double std_scaling; - char * sum_key; -} point_obs_type; - -static UTIL_SAFE_CAST_FUNCTION(point_obs , POINT_OBS_TYPE_ID); - - -struct block_obs_struct { - UTIL_TYPE_ID_DECLARATION; - char * obs_key; /** A user provided label for the observation. */ - vector_type * point_list; - const ecl_grid_type * grid; - const void * data_config; - block_obs_source_type source_type; -}; - - -static UTIL_SAFE_CAST_FUNCTION_CONST(block_obs , BLOCK_OBS_TYPE_ID); -static UTIL_SAFE_CAST_FUNCTION(block_obs , BLOCK_OBS_TYPE_ID); -UTIL_IS_INSTANCE_FUNCTION(block_obs , BLOCK_OBS_TYPE_ID); - - -/*****************************************************************/ - - - - - -static point_obs_type * point_obs_alloc( block_obs_source_type source_type , int i , int j , int k , int active_index , const char * sum_key , double value , double std) { - point_obs_type * point_obs = util_malloc( sizeof * point_obs ); - UTIL_TYPE_ID_INIT( point_obs , POINT_OBS_TYPE_ID ); - - point_obs->source_type = source_type; - point_obs->i = i; - point_obs->j = j; - point_obs->k = k; - point_obs->active_index = active_index; - point_obs->value = value; - point_obs->std = std; - point_obs->sum_key = util_alloc_string_copy( sum_key ); - point_obs->std_scaling = 1.0; - - return point_obs; -} - - - - - - -static void point_obs_free( point_obs_type * point_obs ) { - util_safe_free( point_obs->sum_key ); - free( point_obs ); -} - -static void point_obs_free__( void * arg ) { - point_obs_type * point_obs = point_obs_safe_cast( arg ); - point_obs_free( point_obs ); -} - - - -static double point_obs_iget_data( const point_obs_type * point_obs , const void * state , int iobs , node_id_type node_id) { - if (point_obs->source_type == SOURCE_FIELD) { - const field_type * field = field_safe_cast_const( state ); - return field_iget_double(field , point_obs->active_index); - } else if (point_obs->source_type == SOURCE_SUMMARY) { - const container_type * container = container_safe_cast_const( state ); - const summary_type * summary = summary_safe_cast_const( container_iget_node( container , iobs )); - return summary_get( summary , node_id.report_step ); - } else { - util_abort("%s: unknown source type: %d \n",__func__, point_obs->source_type ); - return -1; - } -} - - -/*****************************************************************/ - - -static const point_obs_type * block_obs_iget_point_const( const block_obs_type * block_obs , int index) { - return vector_iget_const( block_obs->point_list , index ); -} - - -static point_obs_type * block_obs_iget_point( const block_obs_type * block_obs , int index) { - return vector_iget( block_obs->point_list , index ); -} - - -static void block_obs_validate_ijk( const ecl_grid_type * grid , int size, const int * i , const int * j , const int * k) { - int l; - for (l = 0; l < size; l++) { - if (ecl_grid_ijk_valid(grid , i[l] , j[l] , k[l])) { - int active_index = ecl_grid_get_active_index3( grid , i[l] , j[l] , k[l]); - if (active_index < 0) - util_abort("%s: sorry: cell:(%d,%d,%d) is not active - can not observe it. \n",__func__ , i[l]+1 , j[l]+1 , k[l]+1); - - } else - util_abort("%s: sorry: cell (%d,%d,%d) is outside valid range: \n",__func__ , i[l]+1 , j[l]+1 , k[l]+1); - } -} - - -static void block_obs_append_point( block_obs_type * block_obs , point_obs_type * point) { - if (point->source_type == block_obs->source_type) - vector_append_owned_ref(block_obs->point_list , point , point_obs_free__); - else - util_abort("%s: fatal internal error - mixing points with different source type in one block_obs instance.\n",__func__); -} - - -void block_obs_append_field_obs( block_obs_type * block_obs , int i , int j , int k , double value , double std) { - int active_index = ecl_grid_get_active_index3( block_obs->grid , i , j , k ); - point_obs_type * point_obs = point_obs_alloc( SOURCE_FIELD , i , j , k , active_index , NULL , value , std); - block_obs_append_point( block_obs , point_obs ); -} - - -void block_obs_append_summary_obs( block_obs_type * block_obs , int i , int j , int k , const char * sum_key , double value , double std) { - int active_index = ecl_grid_get_active_index3( block_obs->grid , i , j , k ); - point_obs_type * point_obs = point_obs_alloc( SOURCE_SUMMARY , i , j , k , active_index , sum_key , value , std); - block_obs_append_point( block_obs , point_obs ); -} - - -block_obs_type * block_obs_alloc(const char * obs_key, - const void * data_config , - const ecl_grid_type * grid) { - - if (!(field_config_is_instance( data_config ) || container_config_is_instance( data_config ))) - return NULL; - - { - block_obs_type * block_obs = util_malloc(sizeof * block_obs); - UTIL_TYPE_ID_INIT( block_obs , BLOCK_OBS_TYPE_ID ); - - block_obs->obs_key = util_alloc_string_copy(obs_key); - block_obs->data_config = data_config; - block_obs->point_list = vector_alloc_new(); - block_obs->grid = grid; - - if (field_config_is_instance( data_config )) - block_obs->source_type = SOURCE_FIELD; - else - block_obs->source_type = SOURCE_SUMMARY; - - return block_obs; - } -} - - - -/** - The input vectors i,j,k should contain offset zero values. -*/ -block_obs_type * block_obs_alloc_complete(const char * obs_key, - block_obs_source_type source_type , - const stringlist_type * summary_keys , - const void * data_config , - const ecl_grid_type * grid , - int size, - const int * i, - const int * j, - const int * k, - const double * obs_value, - const double * obs_std) -{ - block_obs_validate_ijk( grid , size , i,j,k); - { - block_obs_type * block_obs = block_obs_alloc( obs_key , data_config , grid ); - if (block_obs) { - for (int l=0; l < size; l++) { - - if (source_type == SOURCE_SUMMARY) { - const char * sum_key = stringlist_iget( summary_keys , l ); - block_obs_append_summary_obs( block_obs , i[l] , j[l] , k[l] , sum_key , obs_value[l] , obs_std[l]); - } else - block_obs_append_field_obs( block_obs , i[l] , j[l] , k[l] , obs_value[l] , obs_std[l]); - - } - return block_obs; - } else { - util_abort("%s: internal error - block_obs_alloc() returned NULL \n",__func__); - return NULL; - } - } -} - - - -void block_obs_free( block_obs_type * block_obs) { - vector_free( block_obs->point_list ); - free(block_obs->obs_key); - free(block_obs); -} - - - - - - - -void block_obs_get_observations(const block_obs_type * block_obs, obs_data_type * obs_data, enkf_fs_type * fs, int report_step , const active_list_type * __active_list) { - int i; - int obs_size = block_obs_get_size( block_obs ); - int active_size = active_list_get_active_size( __active_list , obs_size); - active_mode_type active_mode = active_list_get_mode( __active_list ); - obs_block_type * obs_block = obs_data_add_block( obs_data , block_obs->obs_key , obs_size , NULL , false ); - - if (active_mode == ALL_ACTIVE) { - for (i=0; i < obs_size; i++) { - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , i ); - obs_block_iset(obs_block , i , point_obs->value , point_obs->std * point_obs->std_scaling ); - } - } else if (active_mode == PARTLY_ACTIVE) { - const int * active_list = active_list_get_active( __active_list ); - for (i =0 ; i < active_size; i++) { - int iobs = active_list[i]; - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , i ); - obs_block_iset(obs_block , iobs , point_obs->value , point_obs->std * point_obs->std_scaling ); - } - } -} - - -static void block_obs_assert_data( const block_obs_type * block_obs , const void * state ) { - if (block_obs->source_type == SOURCE_FIELD) { - if (!field_is_instance( state )) - util_abort("%s: state data is not of type FIELD - aborting \n",__func__); - } else if (block_obs->source_type == SOURCE_SUMMARY) { - if (!container_is_instance( state )) - util_abort("%s: state data is not of type CONTAINER - aborting \n",__func__); - } -} - - -double block_obs_iget_data( const block_obs_type * block_obs, const void * state , int iobs , node_id_type node_id ) { - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , iobs ); - return point_obs_iget_data( point_obs , state , iobs , node_id); -} - - - -void block_obs_measure(const block_obs_type * block_obs, const void * state , node_id_type node_id , meas_data_type * meas_data , const active_list_type * __active_list) { - block_obs_assert_data( block_obs , state ); - { - int obs_size = block_obs_get_size( block_obs ); - int active_size = active_list_get_active_size( __active_list , obs_size ); - meas_block_type * meas_block = meas_data_add_block( meas_data , block_obs->obs_key , node_id.report_step , obs_size ); - int iobs; - - active_mode_type active_mode = active_list_get_mode( __active_list ); - if (active_mode == ALL_ACTIVE) { - for (iobs=0; iobs < obs_size; iobs++) { - double value = block_obs_iget_data( block_obs , state , iobs , node_id ); - meas_block_iset( meas_block , node_id.iens , iobs , value ); - } - } else if (active_mode == PARTLY_ACTIVE) { - const int * active_list = active_list_get_active( __active_list ); - for (int i =0 ; i < active_size; i++) { - iobs = active_list[i]; - { - double value = block_obs_iget_data( block_obs , state , iobs , node_id); - meas_block_iset( meas_block , node_id.iens , i , value ); - } - } - } - } -} - - - -double block_obs_chi2(const block_obs_type * block_obs, const void * state, node_id_type node_id) { - double sum_chi2 = 0; - int obs_size = block_obs_get_size( block_obs ); - block_obs_assert_data(block_obs, state); - - for (int i=0; i < obs_size; i++) { - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , i ); - double sim_value = point_obs_iget_data( point_obs , state , i, node_id ); - double x = (sim_value - point_obs->value) / point_obs->std; - sum_chi2 += x*x; - } - return sum_chi2; -} - - - - -/** - The index is into the the number of active cells which are observed by this observation. -*/ -void block_obs_iget(const block_obs_type * block_obs, int index , double *value , double * std) { - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , index ); - *value = point_obs->value; - *std = point_obs->std; -} - -double block_obs_iget_value(const block_obs_type * block_obs, int index ){ - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , index ); - return point_obs->value; -} - -double block_obs_iget_std(const block_obs_type * block_obs, int index ){ - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , index ); - return point_obs->std; -} - -double block_obs_iget_std_scaling(const block_obs_type * block_obs, int index ){ - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , index ); - return point_obs->std_scaling; -} - - -void block_obs_user_get(const block_obs_type * block_obs , const char * index_key , double *value , double * std, bool * valid) { - int i,j,k; - - *valid = false; - if (field_config_parse_user_key__( index_key , &i , &j , &k)) { - int obs_size = block_obs_get_size( block_obs ); - int active_index = ecl_grid_get_active_index3(block_obs->grid , i,j,k); - int l = 0; - /* iterating through all the cells the observation is observing. */ - - while (!(*valid) && l < obs_size) { - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , l); - if (point_obs->active_index == active_index) { - *value = point_obs->value; - *std = point_obs->std; - *valid = true; - } - l++; - } - } -} - - - - -int block_obs_iget_i(const block_obs_type * block_obs, int index) { - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , index); - return point_obs->i; -} - -int block_obs_iget_j(const block_obs_type * block_obs, int index) { - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , index); - return point_obs->j; -} - -int block_obs_iget_k(const block_obs_type * block_obs, int index) { - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , index); - return point_obs->k; -} - -double block_obs_iget_depth( const block_obs_type * block_obs , int index) { - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , index); - return ecl_grid_get_cdepth3( block_obs->grid , point_obs->i , point_obs->j ,point_obs->k); -} - -/* - Returns by reference i,j,k for observation point nr block_nr. -*/ - -void block_obs_iget_ijk(const block_obs_type * block_obs , int block_nr , int * i , int * j , int * k) { - const point_obs_type * point_obs = block_obs_iget_point_const( block_obs , block_nr ); - *i = point_obs->i; - *j = point_obs->j; - *k = point_obs->k; -} - - -int block_obs_get_size(const block_obs_type * block_obs) { - return vector_get_size( block_obs->point_list ); -} - -void block_obs_update_std_scale(block_obs_type * block_obs, double scale_factor, const active_list_type * active_list) { - int obs_size = block_obs_get_size( block_obs ); - if (active_list_get_mode( active_list ) == ALL_ACTIVE) { - for (int i = 0; i < obs_size; i++) { - point_obs_type * point_observation = block_obs_iget_point( block_obs , i ); - point_observation->std_scaling = scale_factor; - } - } else { - const int * active_index = active_list_get_active( active_list ); - int size = active_list_get_active_size( active_list , obs_size ); - for (int i=0; i < size; i++) { - int obs_index = active_index[i]; - point_obs_type * point_observation = block_obs_iget_point( block_obs , obs_index ); - point_observation->std_scaling = scale_factor; - } - } -} - - - - - - -/*****************************************************************/ - -VOID_FREE(block_obs) -VOID_GET_OBS(block_obs) -VOID_MEASURE_UNSAFE(block_obs , data) // The cast of data field is not checked - that is done in block_obs_measure(). -VOID_USER_GET_OBS(block_obs) -VOID_CHI2(block_obs , field) -VOID_UPDATE_STD_SCALE(block_obs) diff --git a/ThirdParty/Ert/libenkf/src/cases_config.c b/ThirdParty/Ert/libenkf/src/cases_config.c deleted file mode 100644 index 7a3c594d37..0000000000 --- a/ThirdParty/Ert/libenkf/src/cases_config.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'cases_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - - -struct cases_config_struct { - int iteration_number; -}; - - -cases_config_type * cases_config_alloc( ) { - cases_config_type * config = util_malloc( sizeof * config ); - config->iteration_number = 0; - return config; -} - - -static void cases_config_set_iteration_number( cases_config_type * config , int num_iterations) { - config->iteration_number = num_iterations; -} - -int cases_config_get_iteration_number( const cases_config_type * config ) { - return config->iteration_number; -} - -bool cases_config_set_int( cases_config_type * cases_config , const char * var_name , int value) { - bool name_recognized = true; - if (strcmp( var_name , "iteration_number") == 0) - cases_config_set_iteration_number(cases_config, value); - else - name_recognized = false; - - return name_recognized; -} - - - -void cases_config_fwrite( cases_config_type * config , const char * filename ) { - FILE * stream = util_mkdir_fopen(filename , "w"); - int iteration_no = cases_config_get_iteration_number(config); - util_fwrite_int( iteration_no , stream ); - fclose( stream ); -} - -void cases_config_fread( cases_config_type * config , const char * filename) { - if (util_file_exists( filename )) { - FILE * stream = util_fopen( filename , "r"); - int iteration_number = util_fread_int( stream ); - cases_config_set_iteration_number(config,iteration_number); - fclose( stream ); - } -} - - -void cases_config_free( cases_config_type * config ) { - free( config ); -} - diff --git a/ThirdParty/Ert/libenkf/src/container.c b/ThirdParty/Ert/libenkf/src/container.c deleted file mode 100644 index 671a061f4e..0000000000 --- a/ThirdParty/Ert/libenkf/src/container.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'container.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include - -struct container_struct { - int __type_id; - const container_config_type * config; - vector_type * nodes; -}; - - - -container_type * container_alloc( const container_config_type * config ) { - container_type * container = util_malloc( sizeof * container ); - UTIL_TYPE_ID_INIT( container , CONTAINER ); - container->config = config; - container->nodes = vector_alloc_new(); - return container; -} - - -void container_free( container_type * container ) { - vector_free( container->nodes ); - free( container ); -} - -void container_add_node(container_type * container , void * child_node ) { - vector_append_ref( container->nodes , child_node ); -} - -const void * container_iget_node(const container_type * container , int index) { - return vector_iget_const( container->nodes , index ); -} - -int container_get_size( const container_type * container ) { - return vector_get_size( container->nodes ); -} - -void container_assert_size( const container_type * container ) { - if (vector_get_size( container->nodes ) != container_config_get_size( container->config )) - util_abort("%s: container size mismatch. Current:%d Config:%d \n",__func__ , container_get_size( container ) , container_config_get_size( container->config )); -} - - -/******************************************************************/ -/* Anonumously generated functions used by the enkf_node object */ -/******************************************************************/ - -UTIL_IS_INSTANCE_FUNCTION(container , CONTAINER) -UTIL_SAFE_CAST_FUNCTION(container , CONTAINER) -UTIL_SAFE_CAST_FUNCTION_CONST(container , CONTAINER) -VOID_ALLOC(container) -VOID_FREE(container) - - - - - - - diff --git a/ThirdParty/Ert/libenkf/src/container_config.c b/ThirdParty/Ert/libenkf/src/container_config.c deleted file mode 100644 index 50d37243c9..0000000000 --- a/ThirdParty/Ert/libenkf/src/container_config.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'container_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include - -#include -#include - -#define CONTAINER_CONFIG_TYPE_ID 51330852 - -struct container_config_struct { - UTIL_TYPE_ID_DECLARATION; - vector_type * nodes; -}; - -UTIL_IS_INSTANCE_FUNCTION(container_config , CONTAINER_CONFIG_TYPE_ID); - -container_config_type * container_config_alloc( const char * key ) { - container_config_type * container = util_malloc( sizeof * container ); - UTIL_TYPE_ID_INIT( container , CONTAINER_CONFIG_TYPE_ID ); - container->nodes = vector_alloc_new(); - return container; -} - - - -void container_config_free( container_config_type * container_config ) { - vector_free( container_config->nodes ); - free( container_config ); -} - - -void container_config_add_node( container_config_type * container_config , const enkf_config_node_type * config_node) { - vector_append_ref( container_config->nodes , config_node ); -} - -const void * container_config_iget_node(const container_config_type * container_config , int index) { - return vector_iget_const( container_config->nodes , index ); -} - -int container_config_get_size( const container_config_type * container_config ) { - return vector_get_size( container_config->nodes ); -} - - -int container_config_get_data_size( const container_config_type * container_config ) { - util_exit("%s: not implemented \n",__func__); - return 0; -} - - -/*****************************************************************/ - -UTIL_SAFE_CAST_FUNCTION(container_config , CONTAINER_CONFIG_TYPE_ID) -UTIL_SAFE_CAST_FUNCTION_CONST(container_config , CONTAINER_CONFIG_TYPE_ID) -VOID_GET_DATA_SIZE(container) -VOID_CONFIG_FREE(container) - diff --git a/ThirdParty/Ert/libenkf/src/custom_kw.c b/ThirdParty/Ert/libenkf/src/custom_kw.c deleted file mode 100644 index ab44db926c..0000000000 --- a/ThirdParty/Ert/libenkf/src/custom_kw.c +++ /dev/null @@ -1,149 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - - -struct custom_kw_struct { - int __type_id; - custom_kw_config_type * config; - /* Thin config object - mainly contains filename for remote load */ - stringlist_type * data; /* Actual storage - will be casted to double or float on use. */ -}; - - -custom_kw_type * custom_kw_alloc(const custom_kw_config_type * config) { - custom_kw_type * custom_kw = util_malloc(sizeof * custom_kw); - custom_kw->config = (custom_kw_config_type *) config; - custom_kw->data = stringlist_alloc_new(); - - stringlist_type * keys = custom_kw_config_get_keys(custom_kw->config); - for(int index = 0; index < stringlist_get_size(keys); index++) { - const char * key = stringlist_iget(keys, index); - if(custom_kw_config_key_is_double(custom_kw->config, key)) { - custom_kw_set_double(custom_kw, key, 0.0); - } else { - custom_kw_set_string(custom_kw, key, ""); - } - } - - custom_kw->__type_id = CUSTOM_KW; - return custom_kw; -} - -void custom_kw_free(custom_kw_type * custom_kw) { - stringlist_free(custom_kw->data); - free(custom_kw); -} - -const stringlist_type * custom_kw_get_data(const custom_kw_type * custom_kw) { - return custom_kw->data; -} - -bool custom_kw_key_is_null(const custom_kw_type * custom_kw, char * key) { - int index = custom_kw_config_index_of_key(custom_kw->config, key); - return stringlist_iget(custom_kw->data, index) == NULL; -} - - -void custom_kw_set_double(custom_kw_type * custom_kw, const char * key, double value) { - char value_as_string[128]; - sprintf(value_as_string, "%26.100f", value); - custom_kw_set_string(custom_kw, key, value_as_string); -} - - -void custom_kw_set_string(custom_kw_type * custom_kw, const char * key, const char * value) { - int index = custom_kw_config_index_of_key(custom_kw->config, key); - stringlist_iset_copy(custom_kw->data, index, value); -} - - -double custom_kw_iget_as_double(const custom_kw_type * custom_kw, int index) { - double value; - - util_sscanf_double(stringlist_iget(custom_kw->data, index), & value); - return value; -} - -const char * custom_kw_iget_as_string(const custom_kw_type * custom_kw, int index) { - return stringlist_iget(custom_kw->data, index); -} - -custom_kw_config_type * custom_kw_get_config(const custom_kw_type * custom_kw) { - return custom_kw->config; -} - -bool custom_kw_fload(custom_kw_type * custom_kw, const char * filename) { - return custom_kw_config_parse_result_file(custom_kw->config, filename, custom_kw->data); -} - -bool custom_kw_forward_load(custom_kw_type * custom_kw, const char * ecl_file, const forward_load_context_type * load_context) { - return custom_kw_fload(custom_kw, ecl_file); -} - -bool custom_kw_write_to_buffer(const custom_kw_type * custom_kw, buffer_type * buffer, int report_step) { - stringlist_buffer_fwrite(custom_kw->data, buffer); - return true; -} - -void custom_kw_read_from_buffer(const custom_kw_type * custom_kw, buffer_type * buffer, enkf_fs_type * fs, int report_step) { - stringlist_buffer_fread(custom_kw->data, buffer); -} - -void custom_kw_ecl_write(const custom_kw_type * custom_kw, const char * run_path, const char * base_file, void * filestream) { - //printf("CustomKW ecl_write\n"); -} - -void custom_kw_serialize(const custom_kw_type * custom_kw, node_id_type node_id, const active_list_type * active_list, matrix_type * A, int row_offset, int column) { - printf("CustomKW serialize\n"); -} - -void custom_kw_deserialize(custom_kw_type * custom_kw, node_id_type node_id, const active_list_type * active_list, const matrix_type * A, int row_offset, int column) { - printf("CustomKW deserialize\n"); -} - -/******************************************************************/ -/* Anonumously generated functions used by the enkf_node object */ -/******************************************************************/ -UTIL_SAFE_CAST_FUNCTION_CONST(custom_kw, CUSTOM_KW) - -UTIL_SAFE_CAST_FUNCTION(custom_kw, CUSTOM_KW) - -VOID_ALLOC(custom_kw) - -VOID_FREE(custom_kw) - -VOID_FORWARD_LOAD(custom_kw) - -VOID_FLOAD(custom_kw) - -VOID_ECL_WRITE(custom_kw) - -VOID_READ_FROM_BUFFER(custom_kw); - -VOID_WRITE_TO_BUFFER(custom_kw); - -VOID_SERIALIZE(custom_kw) - -VOID_DESERIALIZE(custom_kw) diff --git a/ThirdParty/Ert/libenkf/src/custom_kw_config.c b/ThirdParty/Ert/libenkf/src/custom_kw_config.c deleted file mode 100644 index d606bf4233..0000000000 --- a/ThirdParty/Ert/libenkf/src/custom_kw_config.c +++ /dev/null @@ -1,304 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include - - -#define CUSTOM_KW_CONFIG_ID 90051933 - -struct custom_kw_config_struct { - UTIL_TYPE_ID_DECLARATION; - char * name; - char * result_file; - char * output_file; - - hash_type * custom_keys; - hash_type * custom_key_types; /* True if float */ - bool undefined; - char * key_definition_file; - - pthread_rwlock_t rw_lock; -}; - - -custom_kw_config_type * custom_kw_config_alloc_empty(const char * key, const char * result_file, const char * output_file) { - custom_kw_config_type * custom_kw_config = util_malloc(sizeof * custom_kw_config); - UTIL_TYPE_ID_INIT(custom_kw_config, CUSTOM_KW_CONFIG_ID); - - custom_kw_config->name = NULL; - custom_kw_config->result_file = util_alloc_string_copy(result_file); - custom_kw_config->output_file = util_alloc_string_copy(output_file); - custom_kw_config->name = util_alloc_string_copy(key); - custom_kw_config->undefined = true; - custom_kw_config->key_definition_file = NULL; - - custom_kw_config->custom_keys = hash_alloc(); - custom_kw_config->custom_key_types = hash_alloc(); //types: 0 if string, 1 if double - pthread_rwlock_init(& custom_kw_config->rw_lock, NULL); - - return custom_kw_config; -} - - -custom_kw_config_type * custom_kw_config_alloc_with_definition(const char * key, const hash_type * definition) { - custom_kw_config_type * custom_kw_config = custom_kw_config_alloc_empty(key, NULL, NULL); - - stringlist_type * keys = hash_alloc_stringlist((hash_type *) definition); - - for(int index = 0; index < stringlist_get_size(keys); index++) { - const char * definition_key = stringlist_iget_copy(keys, index); - int type_value = hash_get_int(definition, definition_key); - - if(type_value < 0 || type_value > 1) { - fprintf(stderr ,"[%s] Warning: Value type not 0 or 1 for key: '%s', defaulting to string!\n", __func__, key); - type_value = 0; - } - hash_insert_int(custom_kw_config->custom_keys, definition_key, index); - hash_insert_int(custom_kw_config->custom_key_types, definition_key, type_value); - } - - custom_kw_config->undefined = false; - custom_kw_config->key_definition_file = util_alloc_string_copy("custom definition"); - - stringlist_free(keys); - - return custom_kw_config; -} - - -void custom_kw_config_free(custom_kw_config_type * config) { - util_safe_free(config->name); - util_safe_free(config->result_file); - util_safe_free(config->output_file); - util_safe_free(config->key_definition_file); - - hash_free(config->custom_keys); - hash_free(config->custom_key_types); - - pthread_rwlock_destroy(& config->rw_lock); - - free(config); -} - -static void custom_kw_config_reset__(custom_kw_config_type * config) { - config->undefined = true; - hash_clear(config->custom_keys); - hash_clear(config->custom_key_types); - util_safe_free(config->key_definition_file); - config->key_definition_file = NULL; -} - -void custom_kw_config_serialize(const custom_kw_config_type * config, stringlist_type * config_set) { - pthread_rwlock_t * rw_lock = (pthread_rwlock_t *)& config->rw_lock; - pthread_rwlock_rdlock(rw_lock); - { - stringlist_clear(config_set); - - stringlist_type * configured_keys = custom_kw_config_get_keys(config); - - for (int i = 0; i < stringlist_get_size(configured_keys); i++) { - const char * key = stringlist_iget(configured_keys, i); - bool double_type = custom_kw_config_key_is_double(config, key); - int index = custom_kw_config_index_of_key(config, key); - char buffer[256]; - - sprintf(buffer, "%s %d %d", key, index, double_type); - stringlist_append_copy(config_set, buffer); - } - - stringlist_free(configured_keys); - - } - pthread_rwlock_unlock(rw_lock); -} - -void custom_kw_config_deserialize(custom_kw_config_type * config, stringlist_type * config_set) { - pthread_rwlock_wrlock(& config->rw_lock); - { - custom_kw_config_reset__(config); - - for (int i = 0; i < stringlist_get_size(config_set); i++) { - const char * items = stringlist_iget(config_set, i); - - char key[128]; - int index; - int is_double; - - int count = sscanf(items, "%s %d %d", key, &index, &is_double); - - if (count == 3) { - hash_insert_int(config->custom_keys, key, index); - hash_insert_int(config->custom_key_types, key, is_double); - } else - util_abort("%s: internal error - deserialize failed\n",__func__); - } - config->undefined = false; - config->key_definition_file = util_alloc_string_copy("from storage"); //Todo: Handle this differently? - } - pthread_rwlock_unlock(& config->rw_lock); -} - -int custom_kw_config_size(const custom_kw_config_type * config) { - return hash_get_size(config->custom_keys); -} - -const char * custom_kw_config_get_name(const custom_kw_config_type * config) { - return config->name; -} - -char * custom_kw_config_get_result_file(const custom_kw_config_type * config) { - return config->result_file; -} - -char * custom_kw_config_get_output_file(const custom_kw_config_type * config) { - return config->output_file; -} - -bool custom_kw_config_has_key(const custom_kw_config_type * config, const char * key) { - return hash_has_key(config->custom_keys, key); -} - -bool custom_kw_config_key_is_double(const custom_kw_config_type * config, const char * key) { - return hash_get_int(config->custom_key_types, key) == 1; -} - -int custom_kw_config_index_of_key(const custom_kw_config_type * config, const char * key) { - return hash_get_int(config->custom_keys, key); -} - -stringlist_type * custom_kw_config_get_keys(const custom_kw_config_type * config) { - return hash_alloc_stringlist(config->custom_keys); -} - -static bool custom_kw_config_setup__(custom_kw_config_type * config, const char * result_file) { - FILE * stream = util_fopen__(result_file, "r"); - if (stream != NULL) { - bool read_ok = true; - config->key_definition_file = util_alloc_string_copy(result_file); - - int counter = 0; - char key[128]; - char value[128]; - int read_count; - while ((read_count = fscanf(stream, "%s %s", key, value)) != EOF) { - if (read_count == 1) { - fprintf(stderr ,"[%s] Warning: Key: '%s:%s' is missing value in file: '%s'\n", __func__, config->name, key, result_file); - read_ok = false; - break; - } - - if (custom_kw_config_has_key(config, key)) { - fprintf(stderr ,"[%s] Warning: Key: '%s:%s' already defined!\n", __func__, config->name, key); - } else { - hash_insert_int(config->custom_keys, key, counter++); - hash_insert_int(config->custom_key_types, key, util_sscanf_double(value, NULL)); - } - } - - fclose(stream); - return read_ok; - } - return false; -} - -static bool custom_kw_config_read_data__(const custom_kw_config_type * config, const char * result_file, stringlist_type * result) { - FILE * stream = util_fopen__(result_file, "r"); - if (stream != NULL) { - bool read_ok = true; - - stringlist_clear(result); - stringlist_iset_ref(result, hash_get_size(config->custom_keys) - 1, NULL); - hash_type * read_keys = hash_alloc(); - - char key[128]; - char value[128]; - int read_count; - while ((read_count = fscanf(stream, "%s %s", key, value)) != EOF) { - if (read_count == 1) { - fprintf(stderr ,"[%s] Warning: Key: '%s:%s' missing value in file: %s!\n", __func__, config->name, key, result_file); - read_ok = false; - break; - } - - if (custom_kw_config_has_key(config, key)) { - if (hash_has_key(read_keys, key)) { - fprintf(stderr ,"[%s] Warning: Key: '%s:%s' has appeared multiple times. Only the last occurrence will be used!\n", __func__, config->name, key); - } - - hash_insert_int(read_keys, key, 1); - int index = custom_kw_config_index_of_key(config, key); - stringlist_iset_copy(result, index, value); - - } else { - fprintf(stderr ,"[%s] Warning: Key: '%s:%s' not in the available set. Ignored!\n", __func__, config->name, key); - } - } - - fclose(stream); - - if (read_ok) { - read_ok = hash_key_list_compare(read_keys, config->custom_keys); - } - - return read_ok; - } - return false; -} - -bool custom_kw_config_parse_result_file(custom_kw_config_type * config, const char * result_file, stringlist_type * result) { - bool read_ok = true; - - // if config->result_file is NULL then the CustomKWConfig was made dynamically - // for storing data manually and not as part of a forward model output. - if(config->result_file != NULL) { - pthread_rwlock_wrlock(&config->rw_lock); - if (config->undefined) { - read_ok = custom_kw_config_setup__(config, result_file); - if (read_ok) { - config->undefined = false; - } - } - pthread_rwlock_unlock(&config->rw_lock); - - if (read_ok) { - read_ok = custom_kw_config_read_data__(config, result_file, result); - } - } - - return read_ok; -} - - - -/*****************************************************************/ - -UTIL_IS_INSTANCE_FUNCTION(custom_kw_config, CUSTOM_KW_CONFIG_ID) - -UTIL_SAFE_CAST_FUNCTION(custom_kw_config, CUSTOM_KW_CONFIG_ID) - -UTIL_SAFE_CAST_FUNCTION_CONST(custom_kw_config, CUSTOM_KW_CONFIG_ID) - - - -/*****************************************************************/ - -VOID_FREE(custom_kw_config) diff --git a/ThirdParty/Ert/libenkf/src/custom_kw_config_set.c b/ThirdParty/Ert/libenkf/src/custom_kw_config_set.c deleted file mode 100644 index 681ebe379c..0000000000 --- a/ThirdParty/Ert/libenkf/src/custom_kw_config_set.c +++ /dev/null @@ -1,143 +0,0 @@ -#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */ - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - - -#define CUSTOM_KW_CONFIG_SET_TYPE_ID 701622133 - -struct custom_kw_config_set_struct { - UTIL_TYPE_ID_DECLARATION; - hash_type * config_set; - pthread_rwlock_t rw_lock; -}; - - -UTIL_IS_INSTANCE_FUNCTION(custom_kw_config_set, CUSTOM_KW_CONFIG_SET_TYPE_ID) - - -custom_kw_config_set_type * custom_kw_config_set_alloc() { - custom_kw_config_set_type * set = util_malloc(sizeof * set); - UTIL_TYPE_ID_INIT(set, CUSTOM_KW_CONFIG_SET_TYPE_ID); - set->config_set = hash_alloc(); - pthread_rwlock_init(& set->rw_lock, NULL); - return set; -} - -custom_kw_config_set_type * custom_kw_config_set_alloc_from_file(const char * filename) { - custom_kw_config_set_type * set = custom_kw_config_set_alloc(); - custom_kw_config_set_fread(set, filename); - return set; -} - -void custom_kw_config_set_free(custom_kw_config_set_type * set) { - hash_free(set->config_set); - free(set); -} - -void custom_kw_config_set_add_config(custom_kw_config_set_type * set, const custom_kw_config_type * config) { - pthread_rwlock_wrlock(& set->rw_lock); - { - const char * name = custom_kw_config_get_name(config); - - if (!hash_has_key(set->config_set, name)) { - stringlist_type * stringlist = stringlist_alloc_new(); - hash_insert_hash_owned_ref(set->config_set, name, stringlist, stringlist_free__); - } - - stringlist_type * formatted_keys = (stringlist_type *) hash_get(set->config_set, name); - custom_kw_config_serialize(config, formatted_keys); - - } - pthread_rwlock_unlock(& set->rw_lock); -} - -void custom_kw_config_set_update_config(custom_kw_config_set_type * set, custom_kw_config_type * config) { - pthread_rwlock_rdlock(& set->rw_lock); - { - const char * name = custom_kw_config_get_name(config); - - if(!hash_has_key(set->config_set, name)) { - printf("[%s] Warning: The key:'%s' is not part of this set. Ignored!\n", __func__, name); - } else { - stringlist_type * formatted_keys = (stringlist_type *) hash_get(set->config_set, name); - custom_kw_config_deserialize(config, formatted_keys); - } - } - pthread_rwlock_unlock(& set->rw_lock); -} - - -void custom_kw_config_set_reset(custom_kw_config_set_type * set) { - pthread_rwlock_wrlock(& set->rw_lock); - { - hash_clear(set->config_set); - } - pthread_rwlock_unlock(& set->rw_lock); -} - -stringlist_type * custom_kw_config_set_get_keys_alloc(custom_kw_config_set_type * set) { - return hash_alloc_stringlist(set->config_set); -} - -void custom_kw_config_set_fwrite(custom_kw_config_set_type * set, const char * filename) { - pthread_rwlock_rdlock(& set->rw_lock); - { - FILE * stream = util_mkdir_fopen(filename, "w"); - if (stream) { - stringlist_type * keys = hash_alloc_stringlist(set->config_set); - stringlist_fwrite(keys, stream); - - for (int i = 0; i < stringlist_get_size(keys); i++) { - const char * key = stringlist_iget(keys, i); - stringlist_type * formatted_keys = (stringlist_type *) hash_get(set->config_set, key); - stringlist_fwrite(formatted_keys, stream); - } - - stringlist_free(keys); - fclose(stream); - } else { - util_abort("%s: failed to open: %s for writing \n", __func__, filename); - } - } - pthread_rwlock_unlock(& set->rw_lock); -} - - -bool custom_kw_config_set_fread(custom_kw_config_set_type * set, const char * filename) { - bool file_exists = false; - - pthread_rwlock_wrlock(& set->rw_lock); - { - hash_clear(set->config_set); - - if (util_file_exists(filename)) { - FILE * stream = util_fopen(filename, "r"); - if (stream) { - stringlist_type * key_set = stringlist_fread_alloc(stream); - - for (int i = 0; i < stringlist_get_size(key_set); i++) { - const char * key = stringlist_iget(key_set, i); - stringlist_type * config_keys = stringlist_fread_alloc(stream); - hash_insert_hash_owned_ref(set->config_set, key, config_keys, stringlist_free__); - } - stringlist_free(key_set); - fclose(stream); - } else { - util_abort("%s: failed to open: %s for reading \n", __func__, filename); - } - file_exists = true; - } - } - pthread_rwlock_unlock(& set->rw_lock); - return file_exists; -} diff --git a/ThirdParty/Ert/libenkf/src/data_ranking.c b/ThirdParty/Ert/libenkf/src/data_ranking.c deleted file mode 100644 index 366c230c80..0000000000 --- a/ThirdParty/Ert/libenkf/src/data_ranking.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'data_ranking.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -#define DATA_RANKING_TYPE_ID 71420672 - -struct data_ranking_struct { - UTIL_TYPE_ID_DECLARATION; - int ens_size; - double_vector_type * data_ensemble; - perm_vector_type * sort_permutation; - bool_vector_type * valid; - char * user_key; - bool sort_increasing; -}; - - -UTIL_SAFE_CAST_FUNCTION( data_ranking , DATA_RANKING_TYPE_ID ) -UTIL_IS_INSTANCE_FUNCTION( data_ranking , DATA_RANKING_TYPE_ID ); - - -void data_ranking_free( data_ranking_type * ranking ) { - double_vector_free( ranking->data_ensemble ); - bool_vector_free( ranking->valid ); - - if (ranking->sort_permutation) - perm_vector_free( ranking->sort_permutation ); - - util_safe_free( ranking->user_key ); - free( ranking ); -} - - - - - -static void data_ranking_init(data_ranking_type * ranking , - enkf_fs_type * fs , - const enkf_config_node_type * config_node, - const char * key_index , - int step) { - - enkf_node_type * enkf_node = enkf_node_alloc( config_node ); - int iens; - for (iens = 0; iens < ranking->ens_size; iens++) { - - double value; - node_id_type node_id = {.report_step = step , - .iens = iens }; - - if (enkf_node_user_get( enkf_node , fs , key_index , node_id , &value)) { - double_vector_iset( ranking->data_ensemble , iens , value ); - bool_vector_iset( ranking->valid , iens , true ); - } - } - - if (ranking->sort_increasing) - ranking->sort_permutation = double_vector_alloc_sort_perm( ranking->data_ensemble ); - else - ranking->sort_permutation = double_vector_alloc_rsort_perm( ranking->data_ensemble ); - - enkf_node_free( enkf_node ); -} - - - -data_ranking_type * data_ranking_alloc( bool sort_increasing , int ens_size , const char * user_key , const char * key_index , enkf_fs_type * fs , const enkf_config_node_type * config_node , int step) { - data_ranking_type * ranking = util_malloc( sizeof * ranking ); - UTIL_TYPE_ID_INIT( ranking , DATA_RANKING_TYPE_ID ); - ranking->ens_size = ens_size; - ranking->sort_increasing = sort_increasing; - - if (ranking->sort_increasing) - ranking->data_ensemble = double_vector_alloc( ens_size , INFINITY); // To ensure it comes last when sorting - else - ranking->data_ensemble = double_vector_alloc( ens_size , -INFINITY); // To ensure it comes last when sorting - - ranking->valid = bool_vector_alloc( ens_size , false ); - ranking->sort_permutation = NULL; - ranking->user_key = util_alloc_string_copy( user_key ); - - data_ranking_init( ranking , fs , config_node , key_index , step ); - return ranking; -} - - - -void data_ranking_free__( void * arg) { - data_ranking_type * ranking = data_ranking_safe_cast( arg ); - data_ranking_free( ranking ); -} - - -const perm_vector_type * data_ranking_get_permutation( const data_ranking_type * data_ranking ) { - return data_ranking->sort_permutation; -} - - -void data_ranking_display( const data_ranking_type * data_ranking , FILE * stream) { - const int ens_size = data_ranking->ens_size; - const perm_vector_type * permutations = data_ranking->sort_permutation; - - { - int i; - fprintf(stream,"\n\n"); - fprintf(stream," # Realization %12s\n" , data_ranking->user_key); - fprintf(stream,"----------------------------------\n"); - for (i = 0; i < ens_size; i++) { - int iens = perm_vector_iget( permutations , i ); - if (bool_vector_iget( data_ranking->valid , iens)) - fprintf(stream,"%3d %3d %14.3f\n",i,iens,double_vector_iget(data_ranking->data_ensemble , iens)); - - } - fprintf(stream,"----------------------------------\n"); - } -} diff --git a/ThirdParty/Ert/libenkf/src/dependencies b/ThirdParty/Ert/libenkf/src/dependencies deleted file mode 100644 index cb79581d6c..0000000000 --- a/ThirdParty/Ert/libenkf/src/dependencies +++ /dev/null @@ -1,71 +0,0 @@ -enkf_tui_fs.o : enkf_tui_fs.c enkf_tui_fs.h enkf_tui_util.o enkf_tui_init.o enkf_main.o enkf_types.o enkf_fs.o -summary_obs.o : summary_obs.c summary_obs.h obs_data.o meas_matrix.o summary.o active_list.o -enkf_fs.o : enkf_fs.c enkf_fs.h enkf_defaults.o enkf_node.o basic_driver.o fs_types.o ecl_static_kw.o plain_driver_index.o plain_driver.o sqlite3_driver.o block_fs_driver.o block_fs_driver_index.o -local_updatestep.o : local_updatestep.c local_updatestep.h local_ministep.o enkf_macros.h -enkf_config_node.o : enkf_config_node.c enkf_config_node.h enkf_types.o enkf_macros.h field_config.o gen_data_config.o gen_kw_config.o summary_config.o -enkf_tui_util.o : enkf_tui_util.c enkf_tui_util.h enkf_node.o field.o field_config.o enkf_state.o ensemble_config.o enkf_types.o -enkf_defaults.o : enkf_defaults.c enkf_defaults.h -gen_data.o : gen_data.c gen_data.h enkf_serialize.o enkf_types.o enkf_macros.h enkf_util.o gen_data_config.o gen_data_common.h gen_common.o -block_fs_driver_index.o : block_fs_driver_index.c block_fs_driver_index.h fs_types.o basic_driver.o -field_obs.o : field_obs.c field_obs.h enkf_util.o field_config.o obs_data.o meas_vector.o field_config.o field.o active_list.o -enkf_tui_init.o : enkf_tui_init.c enkf_tui_init.h enkf_main.o enkf_sched.o enkf_types.o enkf_tui_util.o enkf_state.o enkf_node.o enkf_fs.o ensemble_config.o -block_fs_driver.o : block_fs_driver.c block_fs_driver.h fs_types.o basic_driver.o enkf_types.o -enkf_tui_ranking.o : enkf_tui_ranking.c enkf_tui_ranking.h enkf_main.o enkf_obs.o enkf_tui_util.o -enkf_main.o : enkf_main.c enkf_main.h enkf_config_node.o enkf_types.o obs_data.o meas_matrix.o enkf_state.o enkf_obs.o enkf_fs.o enkf_serialize.o enkf_sched.o ecl_config.o ensemble_config.o model_config.o site_config.o active_config.o enkf_analysis.o local_ministep.o local_updatestep.o local_config.o misfit_table.o plot_config.o ert_template.o enkf_defaults.o -plain_driver_common.o : plain_driver_common.c plain_driver_common.h enkf_types.o enkf_node.o -gen_data_active.o : gen_data_active.c gen_data_active.h enkf_macros.h -active_node.o : active_node.c active_node.h enkf_types.o enkf_config_node.o ensemble_config.o obs_vector.o -enkf_sched.o : enkf_sched.c enkf_sched.h enkf_types.o enkf_defaults.o -summary.o : summary.c summary.h enkf_macros.h enkf_util.o summary_config.o enkf_types.o enkf_util.o enkf_serialize.o -enkf_types.o : enkf_types.c enkf_types.h -plain_driver.o : plain_driver.c plain_driver.h fs_types.o basic_driver.o plain_driver_index.o plain_driver_common.o enkf_node.o -model_config.o : model_config.c model_config.h enkf_sched.o enkf_types.o plain_driver.o fs_types.o enkf_defaults.o -fs_types.o : fs_types.c fs_types.h -site_config.o : site_config.c site_config.h -ert_template.o : ert_template.c ert_template.h -misfit_table.o : misfit_table.c misfit_table.h enkf_obs.o enkf_fs.o -field_active.o : field_active.c field_active.h enkf_macros.h active_list.o -enkf_obs.o : enkf_obs.c enkf_obs.h summary_obs.o field_obs.o enkf_fs.o obs_vector.o enkf_state.o local_ministep.o local_config.o -enkf_state.o : enkf_state.c enkf_state.h enkf_node.o enkf_types.o ecl_static_kw.o field.o field_config.o gen_kw.o summary.o enkf_fs.o basic_driver.o ensemble_config.o model_config.o site_config.o ecl_config.o ert_template.o -active_config.o : active_config.c active_config.h enkf_types.o ensemble_config.o enkf_obs.o active_node.o -ensemble_config.o : ensemble_config.c ensemble_config.h enkf_config_node.o enkf_types.o field_config.o gen_data_config.o meas_matrix.o enkf_types.o enkf_fs.o gen_kw_config.o summary.o summary_config.o gen_data.o pilot_point_config.o gen_data_config.o gen_data_config.o field_trans.o -field_trans.o : field_trans.c field_trans.h -sqlite3_driver.o : sqlite3_driver.c sqlite3_driver.h sqlite3.o basic_driver.o fs_types.o enkf_config_node.o -field_config.o : field_config.c field_config.h enkf_types.o enkf_macros.h field_active.o active_list.o field_trans.o field_common.h -obs_vector.o : obs_vector.c obs_vector.h enkf_fs.o summary_obs.o field_obs.o gen_obs.o ensemble_config.o active_list.o -enkf_tui_export.o : enkf_tui_export.c enkf_tui_export.h enkf_main.o field.o field_config.o enkf_state.o enkf_fs.o enkf_tui_util.o field_config.o gen_data.o -enkf_tui_table.o : enkf_tui_table.c enkf_tui_table.h enkf_main.o enkf_tui_plot.o enkf_tui_fs.o enkf_obs.o field_obs.o field_config.o obs_vector.o enkf_tui_util.o ensemble_config.o gen_kw_config.o -enkf_tui_main.o : enkf_tui_main.c enkf_tui_main.h enkf_tui_run.o enkf_tui_export.o enkf_tui_plot.o enkf_tui_table.o enkf_tui_fs.o enkf_tui_ranking.o enkf_tui_misc.o enkf_main.o enkf_sched.o -enkf_util.o : enkf_util.c enkf_util.h enkf_defaults.o -main.o : main.c enkf_fs.o enkf_main.o enkf_types.o enkf_sched.o enkf_tui_main.o ERT.h -scalar.o : scalar.c scalar.h enkf_types.o scalar_config.o enkf_util.o enkf_serialize.o -pilot_point_config.o : pilot_point_config.c pilot_point_config.h enkf_types.o enkf_macros.h scalar_config.o -enkf_tui_plot.o : enkf_tui_plot.c enkf_tui_plot.h enkf_main.o enkf_tui_fs.o enkf_obs.o field_obs.o gen_obs.o field_config.o obs_vector.o enkf_tui_util.o ensemble_config.o enkf_state.o gen_kw_config.o enkf_defaults.o plot_config.o -summary_config.o : summary_config.c summary_config.h enkf_types.o enkf_util.o enkf_macros.h active_list.o -meas_matrix.o : meas_matrix.c meas_matrix.h meas_vector.o -gen_data_config.o : gen_data_config.c gen_data_config.h enkf_macros.h enkf_types.o gen_data_common.h gen_data_active.o active_list.o -active_list.o : active_list.c active_list.h enkf_macros.h -gen_kw.o : gen_kw.c gen_kw.h enkf_types.o enkf_util.o scalar.o enkf_macros.h gen_kw_common.h gen_kw_config.o -gen_obs.o : gen_obs.c gen_obs.h enkf_util.o enkf_types.o enkf_macros.h meas_vector.o obs_data.o gen_data.o gen_common.o gen_obs_active.o active_list.o -meas_vector.o : meas_vector.c meas_vector.h enkf_util.o -scalar_config.o : scalar_config.c scalar_config.h enkf_util.o enkf_macros.h trans_func.o active_list.o -enkf_tui_run.o : enkf_tui_run.c enkf_tui_run.h enkf_main.o enkf_fs.o enkf_sched.o ensemble_config.o enkf_analysis.o enkf_tui_util.o enkf_tui_fs.o -enkf_serialize.o : enkf_serialize.c enkf_serialize.h enkf_types.o active_list.o -sqlite3.o : sqlite3.c sqlite3.h -gen_obs_active.o : gen_obs_active.c gen_obs_active.h enkf_macros.h -basic_driver.o : basic_driver.c basic_driver.h fs_types.o -enkf_node.o : enkf_node.c enkf_node.h enkf_config_node.o field.o summary.o ecl_static_kw.o gen_kw.o gen_data.o enkf_serialize.o -ecl_config.o : ecl_config.c ecl_config.h enkf_util.o enkf_defaults.o -trans_func.o : trans_func.c trans_func.h -gen_common.o : gen_common.c gen_common.h gen_data_config.o -local_config.o : local_config.c local_config.h local_ministep.o local_updatestep.o -obs_data.o : obs_data.c obs_data.h enkf_util.o meas_matrix.o -plain_driver_index.o : plain_driver_index.c plain_driver_index.h fs_types.o plain_driver_common.o basic_driver.o -field.o : field.c field.h field_config.o enkf_serialize.o -plot_config.o : plot_config.c plot_config.h enkf_defaults.o -ecl_static_kw.o : ecl_static_kw.c ecl_static_kw.h enkf_util.o enkf_macros.h -local_ministep.o : local_ministep.c local_ministep.h active_list.o enkf_macros.h -enkf_tui_misc.o : enkf_tui_misc.c enkf_tui_misc.h enkf_types.o enkf_main.o enkf_state.o -enkf_analysis.o : enkf_analysis.c enkf_analysis.h meas_matrix.o obs_data.o analysis_config.o enkf_util.o -gen_kw_config.o : gen_kw_config.c gen_kw_config.h enkf_util.o enkf_macros.h trans_func.o scalar_config.o enkf_defaults.o gen_kw_common.h -analysis_config.o : analysis_config.c analysis_config.h enkf_types.o enkf_defaults.o diff --git a/ThirdParty/Ert/libenkf/src/ecl_config.c b/ThirdParty/Ert/libenkf/src/ecl_config.c deleted file mode 100644 index c4bc48e3b9..0000000000 --- a/ThirdParty/Ert/libenkf/src/ecl_config.c +++ /dev/null @@ -1,1012 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ecl_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/** - This file implements a struct which holds configuration information - needed to run ECLIPSE. - - Pointers to the fields in this structure are passed on to e.g. the - enkf_state->shared_info object, but this struct is the *OWNER* of - this information, and hence responsible for booting and deleting - these objects. - - Observe that the distinction of what goes in model_config, and what - goes in ecl_config is not entirely clear. - */ - -struct ecl_config_struct -{ - ecl_io_config_type * io_config; /* This struct contains information of whether the eclipse files should be formatted|unified|endian_fliped */ - path_fmt_type * eclbase; /* A path_fmt instance with one %d specifer which will be used for eclbase - members will allocate private eclbase; i.e. updates will not be reflected. */ - sched_file_type * sched_file; /* Will only contain the history - if predictions are active the member_config objects will have a private sched_file instance. */ - hash_type * fixed_length_kw; /* Set of user-added SCHEDULE keywords with fixed length. */ - bool include_all_static_kw; /* If true all static keywords are stored.*/ - set_type * static_kw_set; /* Minimum set of static keywords which must be included to make valid restart files. */ - stringlist_type * user_static_kw; - char * data_file; /* Eclipse data file. */ - time_t start_date; /* The start date of the ECLIPSE simulation - parsed from the data_file. */ - time_t end_date; /* An optional date value which can be used to check if the ECLIPSE simulation has been 'long enough'. */ - ecl_refcase_list_type * refcase_list; - ecl_grid_type * grid; /* The grid which is active for this model. */ - char * schedule_prediction_file; /* Name of schedule prediction file - observe that this is internally handled as a gen_kw node. */ - char * schedule_target_file; /* File name to write schedule info to */ - char * input_init_section; /* File name for ECLIPSE (EQUIL) initialisation - can be NULL if the user has not supplied INIT_SECTION. */ - char * init_section; /* Equal to the full path of input_init_section IFF input_init_section points to an existing file - otherwise equal to input_init_section. */ - int last_history_restart; - bool can_restart; /* Have we found the tag in the data file? */ - int num_cpu; /* We should parse the ECLIPSE data file and determine how many cpus this eclipse file needs. */ - ert_ecl_unit_enum unit_system; /* Either metric, field or lab */ -}; - -/*****************************************************************/ - -/** - With this function we try to determine whether ECLIPSE is active - for this case, i.e. if ECLIPSE is part of the forward model. This - should ideally be inferred from the FORWARD model, but what we do - here is just to check if the core field ->eclbase and ->data_file - have been set. If they are both equal to NULL we assume that - ECLIPSE is not active and return false, otherwise we return true. - */ - -bool ecl_config_active(const ecl_config_type * config) -{ - if ((config->eclbase == NULL )&& (config->data_file == NULL)) - return false; - else - return true; -} - - /** - Could look up the sched_file instance directly - because the - ecl_config will never be the owner of a file with predictions. - */ - -int ecl_config_get_last_history_restart(const ecl_config_type * ecl_config) -{ - return ecl_config->last_history_restart; -} - -bool ecl_config_can_restart(const ecl_config_type * ecl_config) -{ - return ecl_config->can_restart; -} - -void ecl_config_assert_restart(const ecl_config_type * ecl_config) -{ - if (!ecl_config_can_restart(ecl_config)) - { - fprintf(stderr, "** Warning - tried to restart case which is not properly set up for restart.\n"); - fprintf(stderr, "** Need in datafile and INIT_SECTION keyword in config file.\n"); - util_exit("%s: exiting \n", __func__); - } -} - -ui_return_type * ecl_config_validate_data_file(const ecl_config_type * ecl_config, const char * data_file) { - if (util_file_exists(data_file)) - return ui_return_alloc(UI_RETURN_OK); - else { - ui_return_type * ui_return = ui_return_alloc(UI_RETURN_FAIL); - char * error_msg = util_alloc_sprintf("File not found:%s" , data_file); - ui_return_add_error(ui_return , error_msg); - free( error_msg ); - return ui_return; - } -} - - -void ecl_config_set_data_file(ecl_config_type * ecl_config, const char * data_file) { - ecl_config->data_file = util_realloc_string_copy(ecl_config->data_file, data_file); - { - FILE * stream = util_fopen(ecl_config->data_file, "r"); - basic_parser_type * parser = basic_parser_alloc(NULL, NULL, NULL, NULL, "--", "\n"); - char * init_tag = enkf_util_alloc_tagged_string("INIT"); - - ecl_config->can_restart = basic_parser_fseek_string(parser, stream, init_tag, false, true); - - free(init_tag); - basic_parser_free(parser); - fclose(stream); - } - ecl_config->start_date = ecl_util_get_start_date(ecl_config->data_file); - ecl_config->num_cpu = ecl_util_get_num_cpu(ecl_config->data_file); - ecl_config->unit_system = ecl_util_get_unit_set(ecl_config->data_file); -} - - -const char * ecl_config_get_data_file(const ecl_config_type * ecl_config) -{ - return ecl_config->data_file; -} - -time_t ecl_config_get_start_date(const ecl_config_type * ecl_config) -{ - return ecl_config->start_date; -} - -time_t ecl_config_get_end_date(const ecl_config_type * ecl_config) -{ - return ecl_config->end_date; -} - -static void ecl_config_set_end_date(ecl_config_type * ecl_config, time_t end_date) -{ - ecl_config->end_date = end_date; -} - -int ecl_config_get_num_cpu(const ecl_config_type * ecl_config) -{ - return ecl_config->num_cpu; -} - -const char * ecl_config_get_schedule_prediction_file(const ecl_config_type * ecl_config) -{ - return ecl_config->schedule_prediction_file; -} - -/** - Observe: The real schedule prediction functionality is implemented - as a special GEN_KW node in ensemble_config. - */ - -void ecl_config_set_schedule_prediction_file(ecl_config_type * ecl_config, const char * schedule_prediction_file) -{ - ecl_config->schedule_prediction_file = util_realloc_string_copy(ecl_config->schedule_prediction_file, schedule_prediction_file); -} - -const char * ecl_config_get_schedule_file(const ecl_config_type * ecl_config) -{ - if (ecl_config->sched_file != NULL ) - return sched_file_iget_filename(ecl_config->sched_file, 0); - else - return NULL ; -} - -bool ecl_config_has_schedule(const ecl_config_type * ecl_config) -{ - if (ecl_config->sched_file == NULL ) - return false; - else - return true; -} - -bool ecl_config_has_init_section(const ecl_config_type * ecl_config) -{ - if (ecl_config->init_section == NULL ) - return false; - else - return true; -} - - - -ui_return_type * ecl_config_validate_schedule_file(const ecl_config_type * ecl_config , const char * schedule_file) { - if ((ecl_config->start_date != -1) && (util_file_exists(schedule_file))) - return ui_return_alloc(UI_RETURN_OK); - else { - ui_return_type * ui_return = ui_return_alloc(UI_RETURN_FAIL); - - if (ecl_config->start_date == -1) - ui_return_add_error(ui_return, "You must set the ECLIPSE datafile before you can set the SCHEDULE file."); - - if (!util_file_exists(schedule_file)) { - char * error_msg = util_alloc_sprintf("SCHEDULE file:%s not found" , schedule_file); - ui_return_add_error(ui_return , error_msg); - free(error_msg); - } - - return ui_return; - } -} - - -/** - Observe: This function makes a hard assumption that the - ecl_config->start_date has already been set. (And should not be - changed either ...) -*/ - -void ecl_config_set_schedule_file(ecl_config_type * ecl_config, const char * schedule_file, const char * schedule_target_file) -{ - if (schedule_target_file) - ecl_config->schedule_target_file = util_alloc_string_copy(schedule_target_file); - else { - char * base; /* The schedule target file will be without any path component */ - char * ext; - util_alloc_file_components(schedule_file, NULL, &base, &ext); - ecl_config->schedule_target_file = util_alloc_filename(NULL, base, ext); - free(ext); - free(base); - } - - ecl_config->sched_file = sched_file_alloc(ecl_config->start_date); - sched_file_parse(ecl_config->sched_file, schedule_file); - ecl_config->last_history_restart = sched_file_get_num_restart_files(ecl_config->sched_file) - 1; /* We keep track of this - so we can stop assimilation at the end of history */ - - { - hash_iter_type * iter = hash_iter_alloc(ecl_config->fixed_length_kw); - while (!hash_iter_is_complete(iter)) { - const char * key = hash_iter_get_next_key(iter); - int length = hash_get_int(ecl_config->fixed_length_kw, key); - - sched_file_add_fixed_length_kw(ecl_config->sched_file, key, length); - } - hash_iter_free(iter); - } -} - - - -void ecl_config_add_fixed_length_schedule_kw(ecl_config_type * ecl_config, const char * kw, int length) -{ - hash_insert_int(ecl_config->fixed_length_kw, kw, length); - if (ecl_config->sched_file != NULL ) - sched_file_add_fixed_length_kw(ecl_config->sched_file, kw, length); - -} - - -ui_return_type * ecl_config_validate_eclbase(const ecl_config_type * ecl_config, const char * eclbase_fmt) { - if (ecl_util_valid_basename_fmt(eclbase_fmt)) - return ui_return_alloc(UI_RETURN_OK); - else { - ui_return_type * ui_return = ui_return_alloc(UI_RETURN_FAIL); - { - char * error_msg = util_alloc_sprintf("The format string: %s was invalid as ECLBASE format", eclbase_fmt); - ui_return_add_error(ui_return, error_msg); - free(error_msg); - } - ui_return_add_help(ui_return , "The eclbase format must have all characters in the same case,"); - ui_return_add_help(ui_return , "in addition it can contain a %d specifier which will be"); - ui_return_add_help(ui_return , "with the realization number."); - - return ui_return; - } -} - -/** - The value of eclbase is in addition internalized in each enkf_state - object, i.e. the _set routine must be called from enkf_main, and - call enkf_state_update_eclbase() afterwards. - */ - -void ecl_config_set_eclbase(ecl_config_type * ecl_config, const char * eclbase_fmt) -{ - if (ecl_config->eclbase != NULL ) - path_fmt_free(ecl_config->eclbase); - ecl_config->eclbase = path_fmt_alloc_path_fmt(eclbase_fmt); -} - - -/** - Observe that this function returns a (char *) - corresponding to - the argument used when calling the ecl_config_set_eclbase() - function, and not a path_fmt instance. - */ - -const char * ecl_config_get_eclbase(const ecl_config_type * ecl_config) -{ - return path_fmt_get_fmt(ecl_config->eclbase); -} - -/** - Can be called with @refcase == NULL - which amounts to clearing the - current refcase. -*/ -bool ecl_config_load_refcase(ecl_config_type * ecl_config, const char * refcase) -{ - return ecl_refcase_list_set_default(ecl_config->refcase_list, refcase); -} - - -ui_return_type * ecl_config_validate_refcase( const ecl_config_type * ecl_config , const char * refcase) { - if (ecl_sum_case_exists( refcase )) - return ui_return_alloc( UI_RETURN_OK ); - else { - ui_return_type * ui_return = ui_return_alloc( UI_RETURN_FAIL ); - char * error_msg = util_alloc_sprintf( "Could not load summary case from:%s \n",refcase); - ui_return_add_error( ui_return , error_msg ); - free( error_msg ); - return ui_return; - } -} - - -/** - Will return NULL if no refcase is set. - */ -const char * ecl_config_get_refcase_name(const ecl_config_type * ecl_config) -{ - const ecl_sum_type * refcase = ecl_refcase_list_get_default(ecl_config->refcase_list); - if (refcase == NULL ) - return NULL ; - else - return ecl_sum_get_case(refcase); - -} - -/** - This function will clear the list of static keywords supplied by - the user. The default built in keywords are not touched. - */ - -void ecl_config_clear_static_kw(ecl_config_type * ecl_config) -{ - ecl_config->include_all_static_kw = false; - stringlist_clear(ecl_config->user_static_kw); -} - -/** - Returns a stringlist of the user-defined static keywords. - */ -stringlist_type * ecl_config_get_static_kw_list(const ecl_config_type * ecl_config) -{ - return ecl_config->user_static_kw; -} - - /* The semantic regarding INIT_SECTION is as follows: - - 1. If the INIT_SECTION points to an existing file - the - ecl_config->input_init_section is set to the absolute path of - this file. - - 2. If the INIT_SECTION points to a not existing file: - - a. We assert that INIT_SECTION points to a pure filename, - i.e. /some/path/which/does/not/exist is NOT accepted. In - the case the input argument contain a path a error message - will be printed on stderr and the ->init_section will not - be set. - b. The ecl_config->input_init_section is set to point to this - file. - c. WE TRUST THE USER TO SUPPLY CONTENT (THROUGH SOME FUNKY - FORWARD MODEL) IN THE RUNPATH. This can unfortunately not - be checked/verified before the ECLIPSE simulation fails. - - - The INIT_SECTION keyword and in the datafile (checked with - ecl_config->can_restart) interplay as follows: - - - CASE | INIT_SECTION | | OK ? - --------------------------------------------- - 0 | Present | Present | Yes - 1 | Not Present | Present | No - 2 | Present | Not present| No - 3 | Not Present | Not present| Yes - --------------------------------------------- - - - Case 0: This is the most flexible case, which can do arbitrary - restart. - - Case 1: In this case the datafile will contain a tag, we - we do not have the info to replace that tag with for - initialisation, and ECLIPSE will fail. Strictly speaking this - case can actually restart, but that is not enough - we let - this case fail hard. - - Case 2: We have some INIT_SECTION infor, but no tag in he - datafile to update. If the datafile has embedded - initialisation info this case will work for init; but it is - logically flawed, and not accepted. Currently only a warning. - - Case 3: This case has just the right amount of information for - initialisation, but it is 'consistently unable' to restart. - -*/ - -ui_return_type * ecl_config_validate_init_section(const ecl_config_type * ecl_config, const char * input_init_section) { - if (ecl_config->can_restart) - return ui_return_alloc( UI_RETURN_OK ); - else { - ui_return_type * ui_return = ui_return_alloc(UI_RETURN_FAIL); - ui_return_add_error( ui_return , "The tag was not found in datafile - can not set INIT_SECTION keyword\n"); - return ui_return; - } -} - - -void ecl_config_set_init_section(ecl_config_type * ecl_config, const char * input_init_section) { - if (ecl_config->can_restart) { - /* The tag is set. */ - ecl_config->input_init_section = util_realloc_string_copy(ecl_config->input_init_section, input_init_section); /* input_init_section = path/to/init_section */ - if (util_file_exists(ecl_config->input_init_section)) - { /* init_section = $CWD/path/to/init_section */ - util_safe_free(ecl_config->init_section); - ecl_config->init_section = util_alloc_realpath(input_init_section); - } - else - { - char * path; - - util_alloc_file_components(ecl_config->input_init_section, &path, NULL, NULL ); - if (path != NULL ) - fprintf(stderr, - "** Warning: %s: When INIT_SECTION:%s points to a non-existing file - you can not have any path components.\n", - __func__, input_init_section); - else - ecl_config->init_section = util_alloc_string_copy(input_init_section); - - util_safe_free(path); - } - } - else - /* - The tag is not set - we can not utilize the - input_init_section info, and we just ignore it. - */ - fprintf(stderr, - "** Warning: tag was not found in datafile - can not utilize INIT_SECTION keyword - ignored.\n"); -} - - -/** - This just returns the string which has been set with the - ecl_config_set_init_section() function, whereas the - ecl_config_get_equil_init_file() function will return the absolute - path to the init_section (if it exists). - */ - -const char * ecl_config_get_init_section(const ecl_config_type * ecl_config) -{ - return ecl_config->input_init_section; -} - -const char * ecl_config_get_equil_init_file(const ecl_config_type * ecl_config) -{ - return ecl_config->init_section; -} - - -static void ecl_config_init_static_kw(ecl_config_type * ecl_config) -{ - int i; - for (i = 0; i < NUM_STATIC_KW; i++) - set_add_key(ecl_config->static_kw_set, DEFAULT_STATIC_KW - [i]); -} - -ecl_config_type * ecl_config_alloc() -{ - ecl_config_type * ecl_config = util_malloc(sizeof *ecl_config); - - ecl_config->io_config = ecl_io_config_alloc(DEFAULT_FORMATTED, DEFAULT_UNIFIED, DEFAULT_UNIFIED); - ecl_config->fixed_length_kw = hash_alloc(); - ecl_config->eclbase = NULL; - ecl_config->include_all_static_kw = false; - ecl_config->static_kw_set = set_alloc_empty(); - ecl_config->user_static_kw = stringlist_alloc_new(); - ecl_config->num_cpu = 1; /* This must get a valid default in case no ECLIPSE datafile is provided. */ - ecl_config->unit_system = ECL_METRIC_UNITS; - ecl_config->data_file = NULL; - ecl_config->input_init_section = NULL; - ecl_config->init_section = NULL; - ecl_config->grid = NULL; - ecl_config->can_restart = false; - ecl_config->start_date = -1; - ecl_config->end_date = -1; - ecl_config->sched_file = NULL; - ecl_config->schedule_prediction_file = NULL; - ecl_config->schedule_target_file = NULL; - ecl_config->refcase_list = ecl_refcase_list_alloc(); - - ecl_config_init_static_kw(ecl_config); - - return ecl_config; -} - -void ecl_config_init(ecl_config_type * ecl_config, const config_content_type * config) -{ - if (config_content_has_item(config, ECLBASE_KEY)) { - ui_return_type * ui_return = ecl_config_validate_eclbase(ecl_config, config_content_iget(config, ECLBASE_KEY, 0, 0)); - if (ui_return_get_status(ui_return) == UI_RETURN_OK) - ecl_config_set_eclbase(ecl_config, config_content_iget(config, ECLBASE_KEY, 0, 0)); - else - util_abort("%s: failed to set eclbase format. Error:%s\n", __func__ , ui_return_get_last_error(ui_return)); - ui_return_free(ui_return); - } - - if (config_content_has_item(config, DATA_FILE_KEY)) - { - ui_return_type * ui_return = ecl_config_validate_data_file(ecl_config, config_content_iget(config, DATA_FILE_KEY, 0, 0)); - if (ui_return_get_status( ui_return ) == UI_RETURN_OK) - ecl_config_set_data_file( ecl_config, config_content_iget(config, DATA_FILE_KEY, 0, 0) ); - else - util_abort("%s: problem setting ECLIPSE data file\n",__func__ , ui_return_get_last_error(ui_return)); - - ui_return_free(ui_return); - } - - if (config_content_has_item(config, SCHEDULE_FILE_KEY)) { - const char * schedule_target_file = config_content_safe_iget(config, SCHEDULE_FILE_KEY, 0, 1); - if (schedule_target_file) { - ui_return_type * ui_return_sched_target_file = ecl_config_validate_schedule_file(ecl_config, schedule_target_file); - if (!ui_return_get_status(ui_return_sched_target_file) == UI_RETURN_OK) { - util_abort("%s: failed to set target schedule file. Error:%s\n",__func__ , ui_return_get_last_error(ui_return_sched_target_file)); - } - ui_return_free(ui_return_sched_target_file); - } - - ui_return_type * ui_return = ecl_config_validate_schedule_file(ecl_config, config_content_iget(config, SCHEDULE_FILE_KEY, 0, 0)); - if (ui_return_get_status(ui_return) == UI_RETURN_OK) - ecl_config_set_schedule_file(ecl_config, config_content_iget(config, SCHEDULE_FILE_KEY, 0, 0), schedule_target_file); - else - util_abort("%s: failed to set schedule file. Error:%s\n",__func__ , ui_return_get_last_error(ui_return)); - - ui_return_free(ui_return); - } - - if (config_content_has_item(config, GRID_KEY)) { - const char * grid_file = config_content_iget(config, GRID_KEY, 0, 0); - ui_return_type * ui_return = ecl_config_validate_grid( ecl_config , grid_file); - if (ui_return_get_status(ui_return) == UI_RETURN_OK) - ecl_config_set_grid(ecl_config, grid_file ); - else - util_abort("%s: failed to set grid file:%s Error:%s \n",__func__ , grid_file , ui_return_get_last_error(ui_return)); - - ui_return_free( ui_return ); - } - - - if (config_content_has_item(config, ADD_FIXED_LENGTH_SCHEDULE_KW_KEY)) - { - int iocc; - for (iocc = 0; iocc < config_content_get_occurences(config, ADD_FIXED_LENGTH_SCHEDULE_KW_KEY); iocc++) - ecl_config_add_fixed_length_schedule_kw(ecl_config, - config_content_iget(config, ADD_FIXED_LENGTH_SCHEDULE_KW_KEY, iocc, 0), - config_content_iget_as_int(config, ADD_FIXED_LENGTH_SCHEDULE_KW_KEY, iocc, 1)); - } - - if (config_content_has_item(config, REFCASE_KEY)) - { - const char * refcase_path = config_content_get_value_as_path(config, REFCASE_KEY); - if (!ecl_config_load_refcase(ecl_config, refcase_path)) - fprintf(stderr, "** Warning: loading refcase:%s failed \n", refcase_path); - } - - if (config_content_has_item(config, REFCASE_LIST_KEY)) - { - config_content_item_type * item = config_content_get_item(config, REFCASE_LIST_KEY); - int i; - for (i = 0; i < config_content_item_get_size(item); i++) - { - config_content_node_type * node = config_content_item_iget_node(item, i); - int j; - for (j = 0; j < config_content_node_get_size(node); j++) - { - const char * case_glob = config_content_node_iget_as_path(node, j); - ecl_refcase_list_add_matching(ecl_config->refcase_list, case_glob); - } - } - } - - if (config_content_has_item(config, INIT_SECTION_KEY)) - ecl_config_set_init_section(ecl_config, config_content_get_value(config, INIT_SECTION_KEY)); - else if (ecl_config->can_restart) - /** - This is a hard error - the datafile contains , however - the config file does NOT contain INIT_SECTION, i.e. we have - no information to fill in for the section. This case - will not be able to initialize an ECLIPSE model, and that is - broken behaviour. - */ - util_exit("Sorry: when the datafile contains the config file MUST have the INIT_SECTION keyword. \n"); - - /* - The user has not supplied a INIT_SECTION keyword whatsoever, - this essentially means that we can not restart - because: - - 1. The EQUIL section must be inlined in the DATAFILE without any - special markup. - - 2. ECLIPSE will fail hard if the datafile contains both an EQUIL - section and a restart statement, and when we have not marked - the EQUIL section specially with the INIT_SECTION keyword it - is impossible for ERT to dynamically change between a - datafile with initialisation and a datafile for restart. - - IFF the user has no intentitions of any form of restart, this is - perfectly legitemate. - */ - if (config_content_has_item(config, END_DATE_KEY)) - { - const char * date_string = config_content_get_value(config, END_DATE_KEY); - time_t end_date; - if (util_sscanf_date_utc(date_string, &end_date)) - ecl_config_set_end_date(ecl_config, end_date); - else - fprintf(stderr, "** WARNING **: Failed to parse %s as a date - should be in format dd/mm/yyyy \n", date_string); - } -} - -void ecl_config_free(ecl_config_type * ecl_config) -{ - ecl_io_config_free(ecl_config->io_config); - if (ecl_config->eclbase != NULL ) - path_fmt_free(ecl_config->eclbase); - - set_free(ecl_config->static_kw_set); - stringlist_free(ecl_config->user_static_kw); - util_safe_free(ecl_config->data_file); - if (ecl_config->sched_file != NULL ) - sched_file_free(ecl_config->sched_file); - - util_safe_free(ecl_config->schedule_target_file); - hash_free(ecl_config->fixed_length_kw); - - util_safe_free(ecl_config->input_init_section); - util_safe_free(ecl_config->init_section); - util_safe_free(ecl_config->schedule_prediction_file); - - if (ecl_config->grid != NULL ) - ecl_grid_free(ecl_config->grid); - - ecl_refcase_list_free(ecl_config->refcase_list); - - free(ecl_config); -} - -/** - This function adds a keyword to the list of restart keywords wich - are included. Observe that ecl_util_escape_kw() is called prior to - adding it. - - The kw __ALL__ is magic; and will result in a request to store all - static kewyords. This wastes disk-space, but might be beneficial - when debugging. - */ - -void ecl_config_add_static_kw(ecl_config_type * ecl_config, const char * _kw) -{ - if (strcmp(_kw, DEFAULT_ALL_STATIC_KW) == 0) - ecl_config->include_all_static_kw = true; - else - { - char * kw = util_alloc_string_copy(_kw); - ecl_util_escape_kw(kw); - if (!stringlist_contains(ecl_config->user_static_kw, kw)) - stringlist_append_owned_ref(ecl_config->user_static_kw, kw); - } -} - -/** - This function checks whether the static kw should be - included. Observe that it is __assumed__ that ecl_util_escape_kw() - has already been called on the kw. - */ - -bool ecl_config_include_static_kw(const ecl_config_type * ecl_config, const char * kw) -{ - if (ecl_config->include_all_static_kw) - return true; - else - { - if (set_has_key(ecl_config->static_kw_set, kw)) - return true; - else - return stringlist_contains(ecl_config->user_static_kw, kw); - } -} - -ecl_grid_type * ecl_config_get_grid(const ecl_config_type * ecl_config) -{ - return ecl_config->grid; -} - -const char * ecl_config_get_gridfile(const ecl_config_type * ecl_config) -{ - if (ecl_config->grid == NULL ) - return NULL ; - else - return ecl_grid_get_name(ecl_config->grid); -} - -/** - The ecl_config object isolated supports run-time changing of the - grid, however this does not (in general) apply to the system as a - whole. Other objects which internalize pointers (i.e. field_config - objects) to an ecl_grid_type instance will be left with dangling - pointers; and things will probably die an ugly death. So - changing - grid runtime should be done with extreme care. -*/ - -void ecl_config_set_grid(ecl_config_type * ecl_config, const char * grid_file) -{ - if (ecl_config->grid != NULL ) - ecl_grid_free(ecl_config->grid); - ecl_config->grid = ecl_grid_alloc(grid_file); -} - -ui_return_type * ecl_config_validate_grid( const ecl_config_type * ecl_config , const char * grid_file ) { - ui_return_type * ui_return; - if (util_file_exists( grid_file )) { - ecl_file_enum file_type = ecl_util_get_file_type( grid_file , NULL , NULL ); - if ((file_type == ECL_EGRID_FILE) || (file_type == ECL_GRID_FILE)) - ui_return = ui_return_alloc( UI_RETURN_OK ); - else { - ui_return = ui_return_alloc( UI_RETURN_FAIL ); - ui_return_add_error( ui_return , "Input argument is not a GRID/EGRID file"); - } - } else { - ui_return = ui_return_alloc( UI_RETURN_FAIL ); - ui_return_add_error( ui_return , "Input argument does not exist."); - } - return ui_return; -} - - - -ecl_refcase_list_type * ecl_config_get_refcase_list(const ecl_config_type * ecl_config) -{ - return ecl_config->refcase_list; -} - -const ecl_sum_type * ecl_config_get_refcase(const ecl_config_type * ecl_config) -{ - return ecl_refcase_list_get_default(ecl_config->refcase_list); -} - -bool ecl_config_has_refcase(const ecl_config_type * ecl_config) -{ - const ecl_sum_type * refcase = ecl_config_get_refcase(ecl_config); - if (refcase) - return true; - else - return false; -} - -ecl_io_config_type * ecl_config_get_io_config(const ecl_config_type * ecl_config) -{ - return ecl_config->io_config; -} - -const path_fmt_type * ecl_config_get_eclbase_fmt(const ecl_config_type * ecl_config) -{ - return ecl_config->eclbase; -} - -sched_file_type * ecl_config_get_sched_file(const ecl_config_type * ecl_config) -{ - return ecl_config->sched_file; -} - - -const char * ecl_config_get_schedule_target(const ecl_config_type * ecl_config) -{ - return ecl_config->schedule_target_file; -} - -int ecl_config_get_num_restart_files(const ecl_config_type * ecl_config) -{ - return sched_file_get_num_restart_files(ecl_config->sched_file); -} - -bool ecl_config_get_formatted(const ecl_config_type * ecl_config) -{ - return ecl_io_config_get_formatted(ecl_config->io_config); -} -bool ecl_config_get_unified_restart(const ecl_config_type * ecl_config) -{ - return ecl_io_config_get_unified_restart(ecl_config->io_config); -} -bool ecl_config_get_unified_summary(const ecl_config_type * ecl_config) -{ - return ecl_io_config_get_unified_summary(ecl_config->io_config); -} - -void ecl_config_static_kw_init(ecl_config_type * ecl_config, const config_content_type * config) -{ - if (config_content_has_item( config , STATIC_KW_KEY)) { - const config_content_item_type * content_item = config_content_get_item(config, STATIC_KW_KEY); - int j; - for (j = 0; j < config_content_item_get_size(content_item); j++) { - const config_content_node_type * content_node = config_content_item_iget_node(content_item, j); - int k; - for (k = 0; k < config_content_node_get_size(content_node); k++) - ecl_config_add_static_kw(ecl_config, config_content_node_iget(content_node, k)); - } - } -} - -void ecl_config_add_config_items(config_parser_type * config) -{ - config_schema_item_type * item; - - item = config_add_schema_item(config, SCHEDULE_FILE_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 2); - config_schema_item_iset_type(item, 0, CONFIG_EXISTING_PATH); - /* - Observe that SCHEDULE_PREDICTION_FILE - which is implemented as a - GEN_KW is added in ensemble_config.c - */ - - item = config_add_schema_item(config, IGNORE_SCHEDULE_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_BOOL); - - item = config_add_schema_item(config, ECLBASE_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - - item = config_add_schema_item(config, DATA_FILE_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_EXISTING_PATH); - - item = config_add_schema_item(config, STATIC_KW_KEY, false); - config_schema_item_set_argc_minmax(item, 1, CONFIG_DEFAULT_ARG_MAX); - - item = config_add_schema_item(config, ADD_FIXED_LENGTH_SCHEDULE_KW_KEY, false); - config_schema_item_set_argc_minmax(item, 2, 2); - config_schema_item_iset_type(item, 1, CONFIG_INT); - - item = config_add_schema_item(config, REFCASE_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_PATH); - - item = config_add_schema_item(config, REFCASE_LIST_KEY, false); - config_schema_item_set_default_type(item, CONFIG_PATH); - - item = config_add_schema_item(config, GRID_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_EXISTING_PATH); - - item = config_add_schema_item(config, INIT_SECTION_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_PATH); - config_add_alias(config, INIT_SECTION_KEY, "EQUIL_INIT_FILE"); - - item = config_add_schema_item(config, END_DATE_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); -} - -void ecl_config_fprintf_config(const ecl_config_type * ecl_config, FILE * stream) -{ - fprintf(stream, CONFIG_COMMENTLINE_FORMAT); - fprintf(stream, CONFIG_COMMENT_FORMAT, "Here comes configuration information related to the ECLIPSE model."); - - fprintf(stream, CONFIG_KEY_FORMAT, DATA_FILE_KEY); - fprintf(stream, CONFIG_ENDVALUE_FORMAT, ecl_config->data_file); - - fprintf(stream, CONFIG_KEY_FORMAT, SCHEDULE_FILE_KEY); - fprintf(stream, CONFIG_ENDVALUE_FORMAT, sched_file_iget_filename(ecl_config->sched_file, 0)); - - fprintf(stream, CONFIG_KEY_FORMAT, ECLBASE_KEY); - fprintf(stream, CONFIG_ENDVALUE_FORMAT, path_fmt_get_fmt(ecl_config->eclbase)); - - if (ecl_config->include_all_static_kw) - { - fprintf(stream, CONFIG_KEY_FORMAT, STATIC_KW_KEY); - fprintf(stream, CONFIG_ENDVALUE_FORMAT, DEFAULT_ALL_STATIC_KW); - } - { - int size = stringlist_get_size(ecl_config->user_static_kw); - if (size > 0) - { - int i; - fprintf(stream, CONFIG_KEY_FORMAT, STATIC_KW_KEY); - for (i = 0; i < size; i++) - if (i < (size - 1)) - fprintf(stream, CONFIG_VALUE_FORMAT, stringlist_iget(ecl_config->user_static_kw, i)); - else - fprintf(stream, CONFIG_ENDVALUE_FORMAT, stringlist_iget(ecl_config->user_static_kw, i)); - } - } - - /* - if (ecl_config->refcase != NULL) { - fprintf( stream , CONFIG_KEY_FORMAT , REFCASE_KEY ); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , ecl_config_get_refcase_name( ecl_config )); - } - */ - - if (ecl_config->grid != NULL ) - { - fprintf(stream, CONFIG_KEY_FORMAT, GRID_KEY); - fprintf(stream, CONFIG_ENDVALUE_FORMAT, ecl_config_get_gridfile(ecl_config)); - } - - if (ecl_config->schedule_prediction_file != NULL ) - { - fprintf(stream, CONFIG_KEY_FORMAT, SCHEDULE_PREDICTION_FILE_KEY); - fprintf(stream, CONFIG_ENDVALUE_FORMAT, ecl_config_get_schedule_prediction_file(ecl_config)); - } - - if (ecl_config->init_section != NULL ) - { - fprintf(stream, CONFIG_KEY_FORMAT, INIT_SECTION_KEY); - fprintf(stream, CONFIG_ENDVALUE_FORMAT, ecl_config_get_init_section(ecl_config)); - } - - { - hash_iter_type * iter = hash_iter_alloc(ecl_config->fixed_length_kw); - while (!hash_iter_is_complete(iter)) - { - const char * kw = hash_iter_get_next_key(iter); - int length = hash_get_int(ecl_config->fixed_length_kw, kw); - - fprintf(stream, CONFIG_KEY_FORMAT, ADD_FIXED_LENGTH_SCHEDULE_KW_KEY); - fprintf(stream, CONFIG_VALUE_FORMAT, kw); - fprintf(stream, CONFIG_INT_FORMAT, length); - fprintf(stream, "\n"); - - } - hash_iter_free(iter); - } - - fprintf(stream, "\n\n"); -} - -/* Units as specified in the ECLIPSE technical manual */ -const char * ecl_config_get_depth_unit(const ecl_config_type * ecl_config) -{ - switch(ecl_config->unit_system) { - case ECL_METRIC_UNITS: - return "M"; - case ECL_FIELD_UNITS: - return "FT"; - case ECL_LAB_UNITS: - return "CM"; - default: - util_abort("%s: unit system enum value:%d not recognized \n",__func__ , ecl_config->unit_system); - return NULL; - } -} - - -const char * ecl_config_get_pressure_unit(const ecl_config_type * ecl_config) -{ - switch(ecl_config->unit_system) { - case ECL_METRIC_UNITS: - return "BARSA"; - case ECL_FIELD_UNITS: - return "PSIA"; - case ECL_LAB_UNITS: - return "ATMA"; - default: - util_abort("%s: unit system enum value:%d not recognized \n",__func__ , ecl_config->unit_system); - return NULL; - } -} diff --git a/ThirdParty/Ert/libenkf/src/ecl_refcase_list.c b/ThirdParty/Ert/libenkf/src/ecl_refcase_list.c deleted file mode 100644 index 9e2e599729..0000000000 --- a/ThirdParty/Ert/libenkf/src/ecl_refcase_list.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'ecl_refcase_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include -#include - -#include - -#include - - -/* - This file implements a quite simple collection of ecl_sum instances, - with the following twists: - - o The default case is special in several ways: - - - It is added with the ecl_refcase_list_set_default() function. - - - The default case is always the first case, i.e. iget(0) will - return the default case. - - - When setting the default we verify that it can be loaded, and - the thing fails if not. That is in contrast to the other cases - where the actual summary loading is lazy and on demand. - - o The collection has an internal dictionary which ensures that the - same case is not added twice. - - o When calling iget( ) the default case will come as index 0, and - the remaining cases will come in util_strcmp_int() ordering. - - o Observe that the functions in this module return NULL quite - liberally: - - - If you have added a case which does not exist you will get - NULL when you (at a later stage) try to access the ecl_sum - instance. - - - If you ask for the default case before one has been set you - will get NULL. - */ - - -#define SUM_PAIR_TYPE_ID 665109971 - -typedef struct sum_pair_struct { - UTIL_TYPE_ID_DECLARATION; - char * case_name; // This should be (path)/basename - no extension - ecl_sum_type * ecl_sum; -} sum_pair_type; - - - -struct ecl_refcase_list_struct { - sum_pair_type * default_case; - hash_type * case_dict; - vector_type * case_list; /* This is created, and sorted, on demand when we do indexed lookup of cases. */ - bool sorted; -}; - -/*****************************************************************/ - - - -static sum_pair_type * sum_pair_alloc( const char * case_name , bool strict_load) { - ecl_sum_type * ecl_sum = NULL; - char * path = NULL; - char * basename = NULL; - - util_alloc_file_components( case_name , &path , &basename , NULL); - if (basename != NULL) { - char * use_case = util_alloc_filename( path , basename , NULL); - if (strict_load) - ecl_sum = ecl_sum_fread_alloc_case( use_case , ":"); - - util_safe_free( path ); - free( basename ); - if (strict_load && (ecl_sum == NULL)) { - free( use_case ); - return NULL; - } - - - { - sum_pair_type * pair = util_malloc( sizeof * pair ); - UTIL_TYPE_ID_INIT( pair , SUM_PAIR_TYPE_ID ); - pair->case_name = use_case; - pair->ecl_sum = ecl_sum; - return pair; - } - } else { - util_safe_free( path ); - util_safe_free( basename ); - return NULL; - } -} - - -static UTIL_SAFE_CAST_FUNCTION( sum_pair , SUM_PAIR_TYPE_ID ); -static UTIL_SAFE_CAST_FUNCTION_CONST( sum_pair , SUM_PAIR_TYPE_ID ); - -const ecl_sum_type * sum_pair_get_ecl_sum( sum_pair_type * sum_pair ) { - if (sum_pair->ecl_sum == NULL) - sum_pair->ecl_sum = ecl_sum_fread_alloc_case( sum_pair->case_name , ":"); - return sum_pair->ecl_sum; -} - - -static void sum_pair_free( sum_pair_type * sum_pair ) { - free( sum_pair->case_name ); - if (sum_pair->ecl_sum != NULL) - ecl_sum_free( sum_pair->ecl_sum ); - free( sum_pair ); -} - - -static void sum_pair_free__( void * arg ) { - sum_pair_type * pair = sum_pair_safe_cast( arg ); - sum_pair_free( pair ); -} - - - - -static int sum_pair_cmp( const void * arg1 , const void * arg2) { - const sum_pair_type * pair1 = sum_pair_safe_cast_const( arg1 ); - const sum_pair_type * pair2 = sum_pair_safe_cast_const( arg2 ); - - return util_strcmp_int( pair1->case_name , pair2->case_name ); -} - -/*****************************************************************/ - - -ecl_refcase_list_type * ecl_refcase_list_alloc( ) { - ecl_refcase_list_type * refcase_list = util_malloc( sizeof * refcase_list ); - refcase_list->default_case = NULL; - refcase_list->case_list = vector_alloc_new(); - refcase_list->case_dict = hash_alloc(); - refcase_list->sorted = false; - return refcase_list; -} - - - -void ecl_refcase_list_free( ecl_refcase_list_type * refcase_list ) { - vector_free( refcase_list->case_list ); - hash_free( refcase_list->case_dict ); - free( refcase_list ); -} - - - -const ecl_sum_type * ecl_refcase_list_get_default( ecl_refcase_list_type * refcase_list ) { - const ecl_sum_type * return_value = NULL; - if (refcase_list->default_case) - return_value = sum_pair_get_ecl_sum( refcase_list->default_case ); - - return return_value; -} - - -bool ecl_refcase_list_has_default( ecl_refcase_list_type * refcase_list ) { - if (refcase_list->default_case) - return true; - else - return false; -} - - -static void ecl_refcase_list_del_default( ecl_refcase_list_type * refcase_list ) { - sum_pair_type * default_pair = refcase_list->default_case; - if (default_pair) { - hash_del( refcase_list->case_dict , default_pair->case_name ); - refcase_list->default_case = NULL; - } -} - - -/* - If a valid refcase has been set already, and this fails, nothing happens. -*/ - -bool ecl_refcase_list_set_default( ecl_refcase_list_type * refcase_list , const char * default_case) { - - if (default_case) { - sum_pair_type * default_pair = sum_pair_alloc( default_case , true ); - if (default_pair) { - ecl_refcase_list_del_default( refcase_list ); - refcase_list->default_case = default_pair; - - hash_insert_hash_owned_ref( refcase_list->case_dict , default_pair->case_name , default_pair , sum_pair_free__); - refcase_list->sorted = false; - return true; - } else - return false; - } else { - ecl_refcase_list_del_default( refcase_list ); - return true; - } -} - - - - -/** - Will sort the list and remove all elements which can not be loaded. -*/ - -static void ecl_refcase_list_assert_clean( ecl_refcase_list_type * refcase_list ) { - if (!refcase_list->sorted) { - vector_free( refcase_list->case_list ); - refcase_list->case_list = vector_alloc_new(); - - { - stringlist_type * tmp_list = hash_alloc_stringlist( refcase_list->case_dict ); - sum_pair_type * default_case = refcase_list->default_case; - int i; - - for (i =0; i < stringlist_get_size( tmp_list ); i++) { - const char * casename = stringlist_iget( tmp_list , i ); - bool normal_case = true; - - if (default_case && util_string_equal( casename , default_case->case_name)) - normal_case = false; - - if (normal_case) { - sum_pair_type * pair = hash_get( refcase_list->case_dict , casename); - const ecl_sum_type * ecl_sum = sum_pair_get_ecl_sum( pair ); - - if (ecl_sum) - vector_append_ref( refcase_list->case_list , pair); - else - hash_del( refcase_list->case_dict , casename ); - - } - } - stringlist_free( tmp_list ); - } - - vector_sort( refcase_list->case_list , sum_pair_cmp ); - refcase_list->sorted = true; - } -} - - -static sum_pair_type * ecl_refcase_list_get_pair( ecl_refcase_list_type * refcase_list , const char * case_name) { - ecl_refcase_list_assert_clean( refcase_list ); - { - if (hash_has_key( refcase_list->case_dict , case_name)) - return hash_get( refcase_list->case_dict , case_name ); - else - return NULL; - } -} - - -static sum_pair_type * ecl_refcase_list_iget_pair( ecl_refcase_list_type * refcase_list , int index) { - ecl_refcase_list_assert_clean( refcase_list ); - { - int index_offset = refcase_list->default_case ? 1 : 0; - index -= index_offset; - - if (index < 0) - return refcase_list->default_case; - else - return vector_safe_iget( refcase_list->case_list , index); - } -} - - -int ecl_refcase_list_get_size(ecl_refcase_list_type * refcase_list ) { - ecl_refcase_list_assert_clean( refcase_list ); - { - int size = hash_get_size( refcase_list->case_dict ); - return size; - } -} - - - -const ecl_sum_type * ecl_refcase_list_iget_case( ecl_refcase_list_type * refcase_list , int index) { - sum_pair_type * pair = ecl_refcase_list_iget_pair( refcase_list , index ); - if (pair) - return sum_pair_get_ecl_sum( pair ); - else - return NULL; -} - - -const ecl_sum_type * ecl_refcase_list_get_case( ecl_refcase_list_type * refcase_list , const char * case_name) { - sum_pair_type * pair = ecl_refcase_list_get_pair( refcase_list , case_name ); - if (pair) - return sum_pair_get_ecl_sum( pair ); - else - return NULL; -} - - -bool ecl_refcase_list_has_case( ecl_refcase_list_type * refcase_list , const char * case_name) { - const sum_pair_type * pair = ecl_refcase_list_get_pair( refcase_list , case_name ); - if (pair) - return true; - else - return false; -} - - - -const char * ecl_refcase_list_iget_pathcase( ecl_refcase_list_type * refcase_list , int index) { - const ecl_sum_type * ecl_sum = ecl_refcase_list_iget_case( refcase_list , index ); - if (ecl_sum) - return ecl_sum_get_case( ecl_sum ); - else - return NULL; -} - - - -int ecl_refcase_list_add_case( ecl_refcase_list_type * refcase_list , const char * case_name) { - sum_pair_type * pair = sum_pair_alloc( case_name , false ); - if (pair) { - if (hash_has_key( refcase_list->case_dict , pair->case_name)) { - sum_pair_free( pair ); - return 0; - } else { - hash_insert_hash_owned_ref( refcase_list->case_dict , pair->case_name , pair , sum_pair_free__); - refcase_list->sorted = false; - return 1; - } - } else - return 0; -} - -/* - The glob_string pattern must (for all practical purposes) end in an - explicit extension: - - - If it ends without an extension there will be zero mathces. It - - it ends with a '*' there will be a hell-of-a-lot of duplicate - matches. - - If the input glob string does not have an explicit extension we add - .*SMSPEC for the matching purpose. -*/ - - -int ecl_refcase_list_add_matching( ecl_refcase_list_type * refcase_list , const char * __glob_string) { - int count = 0; - char * glob_string; - - { - char * glob_ext; - util_alloc_file_components( __glob_string , NULL , NULL , &glob_ext); - if (glob_ext == NULL) - glob_string = util_alloc_filename(NULL , __glob_string , "*SMSPEC"); - else { - glob_string = util_alloc_string_copy( __glob_string ); - free( glob_ext ); - } - } - - { - stringlist_type * case_list = stringlist_alloc_new(); - int i; - stringlist_select_matching( case_list , glob_string ); - for (i=0; i < stringlist_get_size( case_list ); i++) { - count += ecl_refcase_list_add_case( refcase_list , stringlist_iget( case_list , i ) ); - } - stringlist_free( case_list ); - } - - free( glob_string ); - return count; -} - diff --git a/ThirdParty/Ert/libenkf/src/enkf_analysis.c b/ThirdParty/Ert/libenkf/src/enkf_analysis.c deleted file mode 100644 index 44a10d143f..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_analysis.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_analysis.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - - - - - - -/*****************************************************************/ - -void enkf_analysis_fprintf_obs_summary(const obs_data_type * obs_data , const meas_data_type * meas_data , const int_vector_type * step_list , const char * ministep_name , FILE * stream ) { - const char * float_fmt = "%15.3f"; - fprintf(stream , "===============================================================================================================================\n"); - fprintf(stream , "Report step...: %04d",int_vector_iget( step_list , 0)); - if (int_vector_size( step_list ) == 1) - fprintf(stream , "\n"); - else - fprintf(stream , " - %04d \n",int_vector_get_last( step_list )); - - - fprintf(stream , "Ministep......: %s \n",ministep_name); - fprintf(stream , "-------------------------------------------------------------------------------------------------------------------------------\n"); - { - char * obs_fmt = util_alloc_sprintf(" %%-3d : %%-32s %s +/- %s" , float_fmt , float_fmt); - char * sim_fmt = util_alloc_sprintf(" %s +/- %s \n" , float_fmt , float_fmt); - - fprintf(stream , " Observed history | Simulated data \n"); - fprintf(stream , "-------------------------------------------------------------------------------------------------------------------------------\n"); - - { - int block_nr; - int obs_count = 1; /* Only for printing */ - for (block_nr =0; block_nr < obs_data_get_num_blocks( obs_data ); block_nr++) { - const obs_block_type * obs_block = obs_data_iget_block_const( obs_data , block_nr); - meas_block_type * meas_block = meas_data_iget_block( meas_data , block_nr ); - const char * obs_key = obs_block_get_key( obs_block ); - - for (int iobs = 0; iobs < obs_block_get_size( obs_block ); iobs++) { - active_type active_mode = obs_block_iget_active_mode( obs_block , iobs ); - if ((active_mode == MISSING) || (active_mode == LOCAL_INACTIVE)) - continue; - else { - const char * print_key; - if (iobs == 0) - print_key = obs_key; - else - print_key = " ..."; - - fprintf(stream , obs_fmt , obs_count , print_key , obs_block_iget_value( obs_block , iobs ) , obs_block_iget_std( obs_block , iobs )); - - if (active_mode == ACTIVE) - fprintf(stream , " Active |"); - else if (active_mode == DEACTIVATED) - fprintf(stream , " Inactive |"); - else if (active_mode == LOCAL_INACTIVE) - fprintf(stream , " |"); - else if (active_mode == MISSING) - fprintf(stream , " |"); - else - util_abort("%s: enum_value:%d not handled - internal error\n" , __func__ , active_mode); - - if (active_mode == MISSING) - fprintf(stream , " Missing\n"); - else if (active_mode == LOCAL_INACTIVE) - fprintf(stream , " Deactivated - local updates\n"); - else - fprintf(stream , sim_fmt, meas_block_iget_ens_mean( meas_block , iobs ) , meas_block_iget_ens_std( meas_block , iobs )); - - obs_count++; - } - } - } - } - - free( obs_fmt ); - free( sim_fmt ); - } - fprintf(stream , "===============================================================================================================================\n"); - fprintf(stream , "\n\n\n"); -} - - - - -void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , meas_data_type * meas_data , double std_cutoff , double alpha, bool verbose) { - for (int block_nr =0; block_nr < obs_data_get_num_blocks( obs_data ); block_nr++) { - obs_block_type * obs_block = obs_data_iget_block( obs_data , block_nr); - meas_block_type * meas_block = meas_data_iget_block( meas_data , block_nr ); - - { - int iobs; - for (iobs =0; iobs < meas_block_get_total_obs_size( meas_block ); iobs++) { - if (meas_block_iget_active( meas_block , iobs )) { - double ens_std = meas_block_iget_ens_std( meas_block , iobs ); - if (ens_std <= std_cutoff) { - /* - De activated because the ensemble has to small - variation for this particular measurement. - */ - obs_block_deactivate( obs_block , iobs , verbose , "No ensemble variation"); - meas_block_deactivate( meas_block , iobs ); - } else { - double ens_mean = meas_block_iget_ens_mean( meas_block , iobs ); - double obs_std = obs_block_iget_std( obs_block , iobs ); - double obs_value = obs_block_iget_value( obs_block , iobs ); - double innov = obs_value - ens_mean; - - /* - Deactivated because the distance between the observed data - and the ensemble prediction is to large. Keeping these - outliers will lead to numerical problems. - */ - - if (fabs( innov ) > alpha * (ens_std + obs_std)) { - obs_block_deactivate(obs_block , iobs , verbose , "No overlap"); - meas_block_deactivate(meas_block , iobs); - } - } - } - } - } - } -} - -void enkf_analysis_deactivate_std_zero(obs_data_type * obs_data , meas_data_type * meas_data , bool verbose) { - - for (int block_nr =0; block_nr < obs_data_get_num_blocks( obs_data ); block_nr++) { - obs_block_type * obs_block = obs_data_iget_block( obs_data , block_nr); - meas_block_type * meas_block = meas_data_iget_block( meas_data , block_nr ); - - { - int iobs; - for (iobs =0; iobs < meas_block_get_total_obs_size( meas_block ); iobs++) { - if (meas_block_iget_active( meas_block , iobs )) { - double ens_std = meas_block_iget_ens_std( meas_block , iobs ); - if (ens_std <= 0.0) { - /* - De activated because the ensemble has to small - variation for this particular measurement. - */ - obs_block_deactivate( obs_block , iobs , verbose , "No ensemble variation"); - meas_block_deactivate( meas_block , iobs ); - } - } - } - } - } -} - - - - - - - - - diff --git a/ThirdParty/Ert/libenkf/src/enkf_config_node.c b/ThirdParty/Ert/libenkf/src/enkf_config_node.c deleted file mode 100644 index 7fc3e245ad..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_config_node.c +++ /dev/null @@ -1,1072 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_config_node.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ENKF_CONFIG_NODE_TYPE_ID 776104 - -struct enkf_config_node_struct { - UTIL_TYPE_ID_DECLARATION; - ert_impl_type impl_type; - enkf_var_type var_type; - bool vector_storage; - bool forward_init; /* Should the (parameter) node be initialized by loading results from the Forward model? */ - - bool_vector_type * internalize; /* Should this node be internalized - observe that question of what to internalize is MOSTLY handled at a higher level - without consulting this variable. Can be NULL. */ - stringlist_type * obs_keys; /* Keys of observations which observe this node. */ - char * key; - char * init_file_abs_path; - path_fmt_type * init_file_fmt; /* Format used to create files for initialization. */ - path_fmt_type * enkf_infile_fmt; /* Format used to load in file from forward model - one %d (if present) is replaced with report_step. */ - path_fmt_type * enkf_outfile_fmt; /* Name of file which is written by EnKF, and read by the forward model. */ - void * data; /* This points to the config object of the actual implementation. */ - enkf_node_type * min_std; - char * min_std_file; - - vector_type * container_nodes; - /*****************************************************************/ - /* Function pointers to methods working on the underlying config object. */ - get_data_size_ftype * get_data_size; /* Function pointer to ask the underlying config object of the size - i.e. number of elements. */ - config_free_ftype * freef; -}; - - -UTIL_IS_INSTANCE_FUNCTION( enkf_config_node , ENKF_CONFIG_NODE_TYPE_ID ) - - -static bool enkf_config_node_has_container(const enkf_config_node_type * node , enkf_fs_type * fs , node_id_type node_id) { - bool has_container = true; - for (int inode=0; inode < vector_get_size( node->container_nodes ); inode++) { - enkf_config_node_type * child_node = vector_iget( node->container_nodes , inode ); - bool has_child; - if (child_node->vector_storage) - has_child = enkf_config_node_has_vector( child_node , fs , node_id.iens ); - else - has_child = enkf_config_node_has_node( child_node , fs , node_id ); - - if (!has_child) { - has_container = false; - break; - } - } - return has_container; -} - - - -bool enkf_config_node_has_node( const enkf_config_node_type * node , enkf_fs_type * fs , node_id_type node_id) { - if (node->impl_type == CONTAINER) - return enkf_config_node_has_container( node , fs , node_id ); - else - return enkf_fs_has_node( fs , node->key , node->var_type , node_id.report_step , node_id.iens ); -} - - -bool enkf_config_node_has_vector( const enkf_config_node_type * node , enkf_fs_type * fs , int iens) { - bool has_vector = enkf_fs_has_vector( fs , node->key , node->var_type , iens ); - return has_vector; -} - - - -static enkf_config_node_type * enkf_config_node_alloc__(enkf_var_type var_type, ert_impl_type impl_type, const char * key, bool forward_init) { - enkf_config_node_type * node = util_malloc( sizeof *node ); - UTIL_TYPE_ID_INIT( node , ENKF_CONFIG_NODE_TYPE_ID ); - node->forward_init = forward_init; - node->var_type = var_type; - node->impl_type = impl_type; - node->key = util_alloc_string_copy( key ); - node->container_nodes = vector_alloc_new(); - node->vector_storage = false; - - node->init_file_abs_path = NULL, - node->init_file_fmt = NULL; - node->enkf_infile_fmt = NULL; - node->enkf_outfile_fmt = NULL; - node->internalize = NULL; - node->data = NULL; - node->obs_keys = stringlist_alloc_new(); - node->min_std = NULL; - node->min_std_file = NULL; - - node->get_data_size = NULL; - node->freef = NULL; - - switch(impl_type) { - case(FIELD): - node->freef = field_config_free__; - node->get_data_size = field_config_get_data_size__; - break; - case(GEN_KW): - node->freef = gen_kw_config_free__; - node->get_data_size = gen_kw_config_get_data_size__; - break; - case(CUSTOM_KW): - node->freef = custom_kw_config_free__; - node->get_data_size = NULL; - break; - case(SUMMARY): - node->vector_storage = true; - node->freef = summary_config_free__; - node->get_data_size = summary_config_get_data_size__; - break; - case(GEN_DATA): - node->freef = gen_data_config_free__; - node->get_data_size = NULL; - break; - case(SURFACE): - node->freef = surface_config_free__; - node->get_data_size = surface_config_get_data_size__; - break; - case(CONTAINER): - node->freef = container_config_free__; - node->get_data_size = container_config_get_data_size__; - break; - default: - util_abort("%s : invalid implementation type: %d - aborting \n",__func__ , impl_type); - } - return node; -} - - -bool enkf_config_node_vector_storage( const enkf_config_node_type * config_node) { - return config_node->vector_storage; -} - -/** - Requires that enkf_outfile_fmt (i.e. the name of the file produced - by ERT) is set to a non NULL value; in addition to the type - specific validation in gen_kw_config_is_valid(). -*/ - -static bool enkf_config_node_is_valid_GEN_KW( const enkf_config_node_type * config_node ) { - bool valid = gen_kw_config_is_valid( config_node->data ); - valid = (valid && (config_node->enkf_outfile_fmt != NULL)); - - return valid; -} - - -static bool enkf_config_node_is_valid_FIELD( const enkf_config_node_type * config_node ) { - bool valid = false; - if ( config_node->var_type != INVALID_VAR ) - valid = field_config_is_valid( config_node->data ); - - - return valid; -} - - -static bool enkf_config_node_is_valid_GEN_DATA( const enkf_config_node_type * config_node ) { - bool valid = gen_kw_config_is_valid( config_node->data ); - valid = (valid && (config_node->enkf_outfile_fmt != NULL)); - - return valid; -} - - - - - -bool enkf_config_node_is_valid( const enkf_config_node_type * config_node ) { - bool valid = false; - - switch(config_node->impl_type) { - case(FIELD): - valid = enkf_config_node_is_valid_FIELD( config_node ); - break; - case(SUMMARY): - valid = true; - break; - case(GEN_KW): - valid = enkf_config_node_is_valid_GEN_KW( config_node ); - break; - case(GEN_DATA): - valid = enkf_config_node_is_valid_GEN_DATA( config_node ); - break; - default: - util_abort("%s: - what the fuXX - internal bug. \n",__func__); - } - - return valid; -} - -void enkf_config_node_update_min_std( enkf_config_node_type * config_node , const char * min_std_file ) { - if (!util_string_equal( config_node->min_std_file , min_std_file )) { - /* The current min_std_file and the new input are different, and - the min_std node must be cleared. */ - if (config_node->min_std != NULL) { - enkf_node_free( config_node->min_std ); - config_node->min_std = NULL; - free( config_node->min_std_file ); - } - } - config_node->min_std_file = util_realloc_string_copy( config_node->min_std_file , min_std_file ); - if (config_node->min_std_file != NULL) { - config_node->min_std = enkf_node_alloc( config_node ); - enkf_node_fload( config_node->min_std , min_std_file ); - } -} - - -static void enkf_config_node_update( enkf_config_node_type * config_node , - const char * initfile_fmt , - const char * enkf_outfile_fmt , - const char * enkf_infile_fmt , - const char * min_std_file ) { - - config_node->init_file_fmt = path_fmt_realloc_path_fmt( config_node->init_file_fmt , initfile_fmt ); - config_node->enkf_infile_fmt = path_fmt_realloc_path_fmt( config_node->enkf_infile_fmt , enkf_infile_fmt ); - config_node->enkf_outfile_fmt = path_fmt_realloc_path_fmt( config_node->enkf_outfile_fmt , enkf_outfile_fmt ); - enkf_config_node_update_min_std( config_node , min_std_file ); -} - - - - -enkf_config_node_type * enkf_config_node_alloc(enkf_var_type var_type, - ert_impl_type impl_type, - bool forward_init , - const char * key , - const char * init_file_fmt , - const char * enkf_outfile_fmt , - const char * enkf_infile_fmt , - void * data) { - - enkf_config_node_type * node = enkf_config_node_alloc__( var_type , impl_type , key , forward_init); - enkf_config_node_update( node , init_file_fmt, enkf_outfile_fmt , enkf_infile_fmt , NULL ); - node->data = data; - return node; -} - - - - - -void enkf_config_node_update_gen_kw( enkf_config_node_type * config_node , - const char * enkf_outfile_fmt , /* The include file created by ERT for the forward model. */ - const char * template_file , - const char * parameter_file , - const char * min_std_file , - const char * init_file_fmt ) { - - /* 1: Update the low level gen_kw_config stuff. */ - gen_kw_config_update( config_node->data , template_file , parameter_file ); - - /* 2: Update the stuff which is owned by the upper-level enkf_config_node instance. */ - enkf_config_node_update( config_node , init_file_fmt , enkf_outfile_fmt , NULL , min_std_file); -} - - -void enkf_config_node_update_custom_kw(enkf_config_node_type * config_node, const char * result_file, const char * output_file) { - enkf_config_node_update(config_node, NULL, output_file, result_file, NULL); -} - -/** - This will create a new gen_kw_config instance which is NOT yet - valid. -*/ -enkf_config_node_type * enkf_config_node_new_gen_kw( const char * key , const char * tag_fmt , bool forward_init) { - enkf_config_node_type * config_node = enkf_config_node_alloc__( PARAMETER , GEN_KW , key , forward_init); - config_node->data = gen_kw_config_alloc_empty( key , tag_fmt ); - return config_node; -} - -enkf_config_node_type * enkf_config_node_new_custom_kw(const char * key, const char * result_file, const char * output_file) { - enkf_config_node_type * config_node = enkf_config_node_alloc__(DYNAMIC_RESULT, CUSTOM_KW, key, false); - config_node->data = custom_kw_config_alloc_empty(key, result_file, output_file); - return config_node; -} - -enkf_config_node_type * enkf_config_node_new_defined_custom_kw(const char * key, const hash_type * definition) { - enkf_config_node_type * config_node = enkf_config_node_alloc__(DYNAMIC_RESULT, CUSTOM_KW, key, false); - config_node->data = custom_kw_config_alloc_with_definition(key, definition); - return config_node; -} - -enkf_config_node_type * enkf_config_node_new_surface( const char * key , bool forward_init) { - enkf_config_node_type * config_node = enkf_config_node_alloc__( PARAMETER , SURFACE , key , forward_init); - config_node->data = surface_config_alloc_empty( ); - return config_node; -} - - -void enkf_config_node_update_surface( enkf_config_node_type * config_node , const char * base_surface, const char * init_file_fmt , const char * output_file , const char * min_std_file ) { - - /* 1: Update the data owned by the surface node. */ - surface_config_set_base_surface( config_node->data , base_surface ); - - /* 2: Update the stuff which is owned by the upper-level enkf_config_node instance. */ - enkf_config_node_update( config_node , init_file_fmt , output_file , NULL , min_std_file); -} - - -/*****************************************************************/ - -enkf_config_node_type * enkf_config_node_alloc_summary( const char * key , load_fail_type load_fail) { - enkf_config_node_type * config_node = enkf_config_node_alloc__( DYNAMIC_RESULT , SUMMARY , key , false); - config_node->data = summary_config_alloc( key , load_fail ); - return config_node; -} - - - - -enkf_config_node_type * enkf_config_node_alloc_GEN_PARAM( const char * node_key , - bool forward_init , - gen_data_file_format_type input_format , - gen_data_file_format_type output_format , - const char * init_file_fmt , - const char * ert_outfile_fmt) { - - - enkf_config_node_type * config_node = enkf_config_node_alloc__( PARAMETER , GEN_DATA , node_key , forward_init ); - config_node->data = gen_data_config_alloc_GEN_PARAM( node_key , output_format , input_format); - - enkf_config_node_update( config_node , /* Generic update - needs the format settings from the special.*/ - init_file_fmt , - ert_outfile_fmt , - NULL , - NULL ); - - return config_node; -} - - - - -enkf_config_node_type * enkf_config_node_alloc_GEN_DATA_result( const char * key , - gen_data_file_format_type input_format, - const char * enkf_infile_fmt ) { - - enkf_config_node_type * config_node = enkf_config_node_alloc__( DYNAMIC_RESULT , GEN_DATA , key , false); - config_node->data = gen_data_config_alloc_GEN_DATA_result( key , input_format ); - - enkf_config_node_update( config_node , /* Generic update - needs the format settings from the special.*/ - NULL , - NULL , - enkf_infile_fmt , - NULL ); - - return config_node; -} - - -enkf_config_node_type * enkf_config_node_alloc_GEN_DATA_state( const char * key, - bool forward_init , - gen_data_file_format_type input_format, - gen_data_file_format_type output_format, - const char * init_file_fmt , - const char * template_ecl_file , - const char * template_data_key , - const char * enkf_outfile_fmt , - const char * enkf_infile_fmt , - const char * min_std_file) { - - if (gen_data_config_valid_result_format( enkf_infile_fmt )) { - enkf_config_node_type * config_node = enkf_config_node_alloc__( DYNAMIC_STATE , GEN_DATA , key , forward_init); - config_node->data = gen_data_config_alloc_GEN_DATA_state( key , output_format , input_format ); - - enkf_config_node_update(config_node , /* Generic update - needs the format settings from the special.*/ - init_file_fmt , - enkf_outfile_fmt , - enkf_infile_fmt, - min_std_file); - - return config_node; - } else { - fprintf(stderr, "** ERROR: The RESULT_FILE setting for %s is invalid - must have an embedded %%d - and be a relative path.\n" , key ); - return NULL; - } -} - - - -/*****************************************************************/ - -enkf_config_node_type * enkf_config_node_new_container( const char * key ) { - enkf_config_node_type * config_node = enkf_config_node_alloc__( INVALID , CONTAINER , key , false); - config_node->data = container_config_alloc( key ); - return config_node; -} - -void enkf_config_node_update_container( enkf_config_node_type * config_node , const enkf_config_node_type * child_node) { - vector_append_ref( config_node->container_nodes , child_node ); - container_config_add_node( config_node->data , child_node ); -} - -const char * enkf_config_node_iget_container_key( const enkf_config_node_type * config_node , int index) { - const enkf_config_node_type * child_node = vector_iget_const( config_node->container_nodes , index ); - return child_node->key; -} - - -/*****************************************************************/ - -/** - This will create a new gen_kw_config instance which is NOT yet - valid. Mainly support code for the GUI. -*/ -enkf_config_node_type * enkf_config_node_alloc_field( const char * key , ecl_grid_type * ecl_grid, field_trans_table_type * trans_table, bool forward_init) { - enkf_config_node_type * config_node = enkf_config_node_alloc__( INVALID , FIELD , key , forward_init); - config_node->data = field_config_alloc_empty( key , ecl_grid , trans_table, false ); - return config_node; -} - - - -/** - This is for dynamic ECLIPSE fields like PRESSURE and SWAT; they - only have truncation as possible parameters. -*/ -void enkf_config_node_update_state_field( enkf_config_node_type * config_node , int truncation , double value_min , double value_max ) { - config_node->var_type = DYNAMIC_STATE; - field_config_update_state_field( config_node->data , truncation , value_min , value_max ); - enkf_config_node_update( config_node , NULL , NULL , NULL , NULL ); -} - - - -void enkf_config_node_update_parameter_field( enkf_config_node_type * config_node , - const char * enkf_outfile_fmt , - const char * init_file_fmt , - const char * min_std_file , - int truncation , double value_min , double value_max , - const char * init_transform , - const char * output_transform ) { - - field_file_format_type export_format = field_config_default_export_format( enkf_outfile_fmt ); /* Purely based on extension, recognizes ROFF and GRDECL, the rest will be ecl_kw format. */ - field_config_update_parameter_field( config_node->data , truncation , value_min , value_max , - export_format , - init_transform , - output_transform ); - config_node->var_type = PARAMETER; - enkf_config_node_update( config_node , init_file_fmt , enkf_outfile_fmt , NULL , min_std_file); -} - - - - - -/*****************************************************************/ - - -void enkf_config_node_update_general_field( enkf_config_node_type * config_node , - const char * enkf_outfile_fmt , - const char * enkf_infile_fmt , - const char * init_file_fmt , - const char * min_std_file , - int truncation , - double value_min , - double value_max , - const char * init_transform , - const char * input_transform , - const char * output_transform ) { - - - field_file_format_type export_format = field_config_default_export_format( enkf_outfile_fmt ); /* Purely based on extension, recognizes ROFF and GRDECL, the rest will be ecl_kw format. */ - { - enkf_var_type var_type; - if (enkf_infile_fmt == NULL) - var_type = PARAMETER; - else { - if (enkf_outfile_fmt == NULL) - var_type = DYNAMIC_RESULT; /* Probably not very realistic */ - else - var_type = DYNAMIC_STATE; - } - config_node->var_type = var_type; - } - field_config_update_general_field( config_node->data , - truncation , value_min , value_max , - export_format , - init_transform , - input_transform , - output_transform ); - - enkf_config_node_update( config_node , init_file_fmt , enkf_outfile_fmt , enkf_infile_fmt, min_std_file); -} - - - - - - -/*****************************************************************/ - - -enkf_config_node_type * enkf_config_node_container_iget( const enkf_config_node_type * node , int index) { - return vector_iget( node->container_nodes , index ); -} - -int enkf_config_node_container_size( const enkf_config_node_type * node ) { - return vector_get_size( node->container_nodes ); -} - - -/*****************************************************************/ - -/** - Invokes the get_data_size() function of the underlying node object. -*/ - -int enkf_config_node_get_data_size( const enkf_config_node_type * node , int report_step) { - if (node->impl_type == GEN_DATA) - return gen_data_config_get_data_size( node->data , report_step); - else - return node->get_data_size( node->data ); -} - -void enkf_config_node_free(enkf_config_node_type * node) { - /* Freeing the underlying node object. */ - if (node->freef != NULL) node->freef(node->data); - free(node->key); - stringlist_free(node->obs_keys); - - free(node->init_file_abs_path); - - if (node->enkf_infile_fmt != NULL) - path_fmt_free( node->enkf_infile_fmt ); - - if (node->enkf_outfile_fmt != NULL) - path_fmt_free( node->enkf_outfile_fmt ); - - if (node->init_file_fmt != NULL) - path_fmt_free( node->init_file_fmt ); - - if (node->internalize != NULL) - bool_vector_free( node->internalize ); - - if (node->min_std != NULL) - enkf_node_free( node->min_std ); - - vector_free( node->container_nodes ); - free(node); -} - - - -const enkf_node_type * enkf_config_node_get_min_std( const enkf_config_node_type * config_node ) { - return config_node->min_std; -} - -const char * enkf_config_node_get_min_std_file( const enkf_config_node_type * config_node ) { - return config_node->min_std_file; -} - - -const char * enkf_config_node_get_enkf_outfile( const enkf_config_node_type * config_node ) { - return path_fmt_get_fmt( config_node->enkf_outfile_fmt ); -} - -const char * enkf_config_node_get_enkf_infile( const enkf_config_node_type * config_node ) { - return path_fmt_get_fmt( config_node->enkf_infile_fmt ); -} - - -const char * enkf_config_node_get_FIELD_fill_file(enkf_config_node_type * config_node, const path_fmt_type * runpath_fmt) { - if (config_node->init_file_abs_path) - return config_node->init_file_abs_path; - - char * runpath = NULL; - bool forward_init = enkf_config_node_use_forward_init(config_node); - - if (forward_init && runpath_fmt) { - runpath = path_fmt_alloc_path(runpath_fmt , false , 0, 0); /* Replace first %d with iens, if a second %d replace with iter */ - config_node->init_file_abs_path = enkf_config_node_alloc_initfile(config_node, runpath, 0); - } else - config_node->init_file_abs_path = enkf_config_node_alloc_initfile(config_node, NULL, 0); - - if (config_node->init_file_abs_path) { - config_node->init_file_abs_path = util_alloc_abs_path(config_node->init_file_abs_path); - if (!util_file_exists(config_node->init_file_abs_path)) { - free(config_node->init_file_abs_path); - config_node->init_file_abs_path = NULL; - } - } - - free(runpath); - - return config_node->init_file_abs_path; -} - - - -const char * enkf_config_node_get_init_file_fmt( const enkf_config_node_type * config_node) -{ - return path_fmt_get_fmt( config_node->init_file_fmt ); -} - -void enkf_config_node_set_min_std( enkf_config_node_type * config_node , enkf_node_type * min_std ) { - if (config_node->min_std != NULL) - enkf_node_free( config_node->min_std ); - - config_node->min_std = min_std; -} - - -void enkf_config_node_set_internalize(enkf_config_node_type * node, int report_step) { - ert_impl_type impl_type = enkf_config_node_get_impl_type( node ); - if (impl_type == CONTAINER) { - int inode; - int container_size = enkf_config_node_container_size( node ); - for (inode = 0; inode < container_size; inode++) { - enkf_config_node_type * child_node = enkf_config_node_container_iget( node , inode ); - enkf_config_node_set_internalize( child_node , report_step ); - } - } else { - if (node->internalize == NULL) - node->internalize = bool_vector_alloc( 0 , false ); - bool_vector_iset( node->internalize , report_step , true); - } -} - - -void enkf_config_node_init_internalization(enkf_config_node_type * node) { - if (node->internalize != NULL) - bool_vector_reset( node->internalize ); -} - - -/* Query function: */ -bool enkf_config_node_internalize(const enkf_config_node_type * node, int report_step) { - if (node->internalize == NULL) - return false; - else - return bool_vector_safe_iget( node->internalize , report_step); /* Will return default value if report_step is beyond size. */ -} - - - -/** - This is the filename used when loading from a completed forward - model. -*/ - -char * enkf_config_node_alloc_infile(const enkf_config_node_type * node , int report_step) { - if (node->enkf_infile_fmt != NULL) - return path_fmt_alloc_path(node->enkf_infile_fmt , false , report_step); - else - return NULL; -} - - -char * enkf_config_node_alloc_outfile(const enkf_config_node_type * node , int report_step) { - if (node->enkf_outfile_fmt != NULL) - return path_fmt_alloc_path(node->enkf_outfile_fmt , false , report_step); - else - return NULL; -} - -/* - The path argument is used when the function is during forward_model - based initialisation. -*/ - -char * enkf_config_node_alloc_initfile( const enkf_config_node_type * node , const char * path , int iens) { - if (node->init_file_fmt == NULL) - return NULL; - else { - char * file = path_fmt_alloc_file( node->init_file_fmt , false , iens ); - if (util_is_abs_path( file )) - return file; - else { - char * full_path = util_alloc_filename( path , file , NULL ); - free( file ); - return full_path; - } - } -} - - - - -void * enkf_config_node_get_ref(const enkf_config_node_type * node) { - return node->data; -} - - - -bool enkf_config_node_include_type(const enkf_config_node_type * config_node , int mask) { - - enkf_var_type var_type = config_node->var_type; - if (var_type & mask) - return true; - else - return false; - -} - - -bool enkf_config_node_use_forward_init(const enkf_config_node_type * config_node) { - return config_node->forward_init; -} - - -ert_impl_type enkf_config_node_get_impl_type(const enkf_config_node_type *config_node) { - return config_node->impl_type; -} - - -enkf_var_type enkf_config_node_get_var_type(const enkf_config_node_type *config_node) { - return config_node->var_type; -} - - -const char * enkf_config_node_get_key(const enkf_config_node_type * config_node) { return config_node->key; } - - -const stringlist_type * enkf_config_node_get_obs_keys(const enkf_config_node_type *config_node) { - return config_node->obs_keys; -} - - -int enkf_config_node_get_num_obs( const enkf_config_node_type * config_node ) { - return stringlist_get_size( config_node->obs_keys ); -} - - -/** - This checks the index_key - and sums up over all the time points of the observation. -*/ - -int enkf_config_node_load_obs( const enkf_config_node_type * config_node , enkf_obs_type * enkf_obs ,const char * key_index , int obs_count , time_t * _sim_time , double * _y , double * _std) { - ert_impl_type impl_type = enkf_config_node_get_impl_type(config_node); - int num_obs = 0; - int iobs; - - for (iobs = 0; iobs < stringlist_get_size( config_node->obs_keys ); iobs++) { - obs_vector_type * obs_vector = enkf_obs_get_vector( enkf_obs , stringlist_iget( config_node->obs_keys , iobs)); - - int report_step = -1; - while (true) { - report_step = obs_vector_get_next_active_step( obs_vector , report_step); - if (report_step == -1) break; - { - bool valid; - double value , std1; - - /** - The user index used when calling the user_get function on the - gen_obs data type is different depending on whether is called with a - data context user_key (as here) or with a observation context - user_key (as when plotting an observation plot). See more - documentation of the function gen_obs_user_get_data_index(). - */ - - if (impl_type == GEN_DATA) - gen_obs_user_get_with_data_index( obs_vector_iget_node( obs_vector , report_step ) , key_index , &value , &std1 , &valid); - else - obs_vector_user_get( obs_vector , key_index , report_step , &value , &std1 , &valid); - - if (valid) { - if (obs_count > 0) { - _sim_time[num_obs] = enkf_obs_iget_obs_time( enkf_obs , report_step ); - _y[num_obs] = value; - _std[num_obs] = std1; - } - num_obs++; - } - } - } - } - - /* Sorting the observations in time order. */ - if (obs_count > 0) { - double_vector_type * y = double_vector_alloc_shared_wrapper( 0 , 0 , _y , obs_count ); - double_vector_type * std = double_vector_alloc_shared_wrapper( 0 , 0 , _std , obs_count ); - time_t_vector_type * sim_time = time_t_vector_alloc_shared_wrapper( 0 , 0 , _sim_time , obs_count ); - perm_vector_type * sort_perm = time_t_vector_alloc_sort_perm( sim_time ); - - time_t_vector_permute( sim_time , sort_perm ); - double_vector_permute( y , sort_perm ); - double_vector_permute( std , sort_perm ); - - free( sort_perm ); - double_vector_free( y ); - double_vector_free( std ); - time_t_vector_free( sim_time ); - } - return num_obs; -} - - - -void enkf_config_node_add_obs_key(enkf_config_node_type * config_node , const char * obs_key) { - if (!stringlist_contains(config_node->obs_keys , obs_key)) - stringlist_append_copy(config_node->obs_keys , obs_key); -} - - -void enkf_config_node_clear_obs_keys(enkf_config_node_type * config_node) { - stringlist_clear( config_node->obs_keys ); -} - -/*****************************************************************/ - - - -void enkf_config_node_fprintf_config( const enkf_config_node_type * config_node , FILE * stream ) { - switch( config_node->impl_type) { - case(GEN_KW): - fprintf( stream , CONFIG_KEY_FORMAT , GEN_KW_KEY ); - fprintf( stream , CONFIG_VALUE_FORMAT , config_node->key ); - gen_kw_config_fprintf_config( config_node->data , path_fmt_get_fmt( config_node->enkf_outfile_fmt ) , config_node->min_std_file , stream ); - break; - case(FIELD): - fprintf( stream , CONFIG_KEY_FORMAT , FIELD_KEY ); - fprintf( stream , CONFIG_VALUE_FORMAT , config_node->key ); - field_config_fprintf_config( config_node->data , - config_node->var_type , - path_fmt_get_fmt( config_node->enkf_outfile_fmt ) , - path_fmt_get_fmt( config_node->enkf_infile_fmt ) , - config_node->min_std_file , - stream ); - break; - case(GEN_DATA): - - if (config_node->var_type == PARAMETER) - fprintf( stream , CONFIG_KEY_FORMAT , GEN_PARAM_KEY ); - else - fprintf( stream , CONFIG_KEY_FORMAT , GEN_DATA_KEY ); - - gen_data_config_fprintf_config( config_node->data , - config_node->var_type , - path_fmt_get_fmt( config_node->enkf_outfile_fmt ) , - path_fmt_get_fmt( config_node->enkf_infile_fmt ) , - config_node->min_std_file , - stream ); - break; - default: - util_abort("%s: internal error - function can not store configuration for: %s variables. \n",__func__ , enkf_types_get_impl_name( config_node->impl_type) ); - } - fprintf( stream , "\n"); -} -/*****************************************************************/ - -void enkf_config_node_add_GEN_PARAM_config_schema( config_parser_type * config ) { - config_schema_item_type * item; - item = config_add_schema_item(config , GEN_PARAM_KEY , false ); - config_schema_item_set_argc_minmax(item , 2 , CONFIG_DEFAULT_ARG_MAX); -} - - -void enkf_config_node_add_GEN_DATA_config_schema( config_parser_type * config ) { - config_schema_item_type * item; - item = config_add_schema_item(config , GEN_DATA_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , CONFIG_DEFAULT_ARG_MAX); -} - -void enkf_config_node_add_CUSTOM_KW_config_schema(config_parser_type * config){ - config_schema_item_type * item = config_add_schema_item(config, CUSTOM_KW_KEY, false); - config_schema_item_set_argc_minmax(item, 2, 3); - config_schema_item_iset_type(item, 0, CONFIG_STRING); - config_schema_item_iset_type(item, 1, CONFIG_PATH); - config_schema_item_iset_type(item, 2, CONFIG_PATH); -} - -enkf_config_node_type * enkf_config_node_alloc_GEN_DATA_from_config( const config_content_node_type * node ) { - enkf_config_node_type * config_node = NULL; - const char * node_key = config_content_node_iget( node , 0 ); - { - hash_type * options = hash_alloc(); - - config_content_node_init_opt_hash( node , options , 1 ); - { - gen_data_file_format_type input_format = gen_data_config_check_format( hash_safe_get( options , INPUT_FORMAT_KEY)); - gen_data_file_format_type output_format = gen_data_config_check_format( hash_safe_get( options , OUTPUT_FORMAT_KEY)); - const char * init_file_fmt = hash_safe_get( options , INIT_FILES_KEY); - const char * ecl_file = hash_safe_get( options , ECL_FILE_KEY); - const char * template = hash_safe_get( options , TEMPLATE_KEY); - const char * data_key = hash_safe_get( options , KEY_KEY); - const char * result_file = hash_safe_get( options , RESULT_FILE_KEY); - const char * min_std_file = hash_safe_get( options , MIN_STD_KEY); - const char * forward_string = hash_safe_get( options , FORWARD_INIT_KEY ); - const char * report_steps_string = hash_safe_get( options , REPORT_STEPS_KEY ); - int_vector_type * report_steps = int_vector_alloc(0,0); - bool forward_init = false; - bool valid_input = true; - - if (input_format == GEN_DATA_UNDEFINED) - valid_input = false; - - if (!gen_data_config_valid_result_format( result_file )) { - fprintf(stderr, "** ERROR: The RESULT_FILE:%s setting for %s is invalid - must have an embedded %%d - and be a relative path.\n" , result_file , node_key ); - valid_input = false; - } - - if (report_steps_string) { - if (!string_util_update_active_list( report_steps_string , report_steps )) { - valid_input = false; - fprintf(stderr,"** ERROR: The REPORT_STEPS:%s attribute was not valid.\n",report_steps_string); - } - } else { - fprintf(stderr,"** ERROR: As of July 2014 the GEN_DATA keywords must have a REPORT_STEPS:xxxx \n"); - fprintf(stderr," attribute to indicate which report step(s) you want to load data \n"); - fprintf(stderr," from. By requiring the user to enter this information in advance\n"); - fprintf(stderr," it is easier for ERT for to check that the results are valid, and\n"); - fprintf(stderr," handle errors with the GEN_DATA results gracefully.\n"); - fprintf(stderr," \n"); - fprintf(stderr," You can list several report steps separated with ',' and ranges with '-' \n"); - fprintf(stderr," but observe that spaces is NOT ALLOWED. \n"); - fprintf(stderr," \n"); - fprintf(stderr," - load from report step 100: REPORT_STEPS:100 \n"); - fprintf(stderr," - load from report steps 10, 20 and 30-40 REPORT_STEPS:10,20,30-40 \n"); - fprintf(stderr," \n"); - fprintf(stderr," The GEN_DATA keyword: %s will be ignored\n",node_key); - valid_input = false; - } - - if (valid_input) { - - if (forward_string) { - if (!util_sscanf_bool( forward_string , &forward_init)) - fprintf(stderr,"** Warning: parsing %s as bool failed - using FALSE \n",forward_string); - } - - if ((init_file_fmt == NULL) && - (ecl_file == NULL) && - (result_file != NULL)) - config_node = enkf_config_node_alloc_GEN_DATA_result( node_key , input_format , result_file); - else if ((init_file_fmt != NULL) && - (ecl_file != NULL) && - (result_file != NULL)) - config_node = enkf_config_node_alloc_GEN_DATA_state( node_key , - forward_init , - input_format , - output_format , - init_file_fmt , - template , - data_key , - ecl_file , - result_file , - min_std_file); - - { - gen_data_config_type * gen_data_config = enkf_config_node_get_ref( config_node ); - - if (template) - gen_data_config_set_template( gen_data_config , template , data_key); - - for (int i=0; i < int_vector_size( report_steps ); i++) { - int report_step = int_vector_iget( report_steps , i ); - gen_data_config_add_report_step( gen_data_config , report_step); - enkf_config_node_set_internalize( config_node , report_step ); - } - } - } - - int_vector_free( report_steps ); - } - hash_free( options ); - } - - return config_node; -} - - -enkf_config_node_type * enkf_config_node_alloc_GEN_PARAM_from_config( const config_content_node_type * node ) { - enkf_config_node_type * config_node = NULL; - const char * node_key = config_content_node_iget( node , 0 ); - const char * ecl_file = config_content_node_iget( node , 1 ); - { - hash_type * options = hash_alloc(); - - config_content_node_init_opt_hash( node , options , 2 ); - { - gen_data_file_format_type input_format = gen_data_config_check_format( hash_safe_get( options , INPUT_FORMAT_KEY)); - gen_data_file_format_type output_format = gen_data_config_check_format( hash_safe_get( options , OUTPUT_FORMAT_KEY)); - const char * init_file_fmt = hash_safe_get( options , INIT_FILES_KEY); - const char * template = hash_safe_get( options , TEMPLATE_KEY); - const char * data_key = hash_safe_get( options , KEY_KEY); - const char * min_std_file = hash_safe_get( options , MIN_STD_KEY); - const char * forward_string = hash_safe_get( options , FORWARD_INIT_KEY ); - bool forward_init = false; - bool valid_input = true; - - - if (input_format == GEN_DATA_UNDEFINED) - valid_input = false; - - if (input_format == ASCII_TEMPLATE) - valid_input = false; - - if (output_format == GEN_DATA_UNDEFINED) - valid_input = false; - - if (init_file_fmt == NULL) - valid_input = false; - - if (valid_input) { - - if (forward_string) { - if (!util_sscanf_bool( forward_string , &forward_init)) - fprintf(stderr,"** Warning: parsing %s as bool failed - using FALSE \n",forward_string); - } - - config_node = enkf_config_node_alloc_GEN_PARAM( node_key , forward_init , input_format , output_format , init_file_fmt , ecl_file); - - if (template) { - bool template_set_ok = gen_data_config_set_template( enkf_config_node_get_ref( config_node ) , template , data_key); - if (!template_set_ok) - fprintf(stderr,"** Warning: the template settings were not applied correctly - ignored\n"); - } - - if (min_std_file) - enkf_config_node_update_min_std( config_node , min_std_file ); - - } - } - hash_free( options ); - } - return config_node; -} - - -/*****************************************************************/ -UTIL_SAFE_CAST_FUNCTION( enkf_config_node , ENKF_CONFIG_NODE_TYPE_ID) -VOID_FREE(enkf_config_node) diff --git a/ThirdParty/Ert/libenkf/src/enkf_defaults.c b/ThirdParty/Ert/libenkf/src/enkf_defaults.c deleted file mode 100644 index f8647b2ac3..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_defaults.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_defaults.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -/** - Currently no code here - but the way DEFAULT_STATIC_KW is implemented - is dang ugly. Should be compiled. -*/ diff --git a/ThirdParty/Ert/libenkf/src/enkf_fs.c b/ThirdParty/Ert/libenkf/src/enkf_fs.c deleted file mode 100644 index 6074363d42..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_fs.c +++ /dev/null @@ -1,1058 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_fs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - - About storage in the EnKF system - ================================ - - The system for storage in the EnKF system is quite complicated, maybe too - complicated. The reason the system is so complex is (at least) twofold: - - 1. It is a goal that it should be relatively easy to write new - systems (i.e. drivers) for storage. The current suite of - drivers (plain_driver_xx) are based on normal (compressed) - fread() and fwrite() system calls. But with the current - implementation one could write e.g. a MySQL based driver for - storage without touching(??) the rest of the EnKF code. - - 2. The parameters / static restart data / dynamic restart data - have very different storage characteristics. By splitting the - storage up in different drivers we can write drivers which are - specialized for the different types of data. - - - The interface - ------------- - - The unit of storage in the enkf_fs system is one enkf_node instance. The - interface between the storage system and the rest of the EnKF system is - through the enkf_fs functions: - - enkf_fs_fread_node() - enkf_fs_has_node() - enkf_fs_fwrite_node() - enkf_fs_unlink_node() - not implemented yet. - - - So all these functions (partly except enkf_fs_has_node()) work on a enkf_node - instance, and in addition they take the following input: - - - iens : ensemble member number - - report_step : the report_step number we are interested in - - state : whether we are considering an analyzed node or a forecast. - - In addition to the functions enkf_fs_fread_node() and enkf_fs_fwrite_node() there - are higher level functions enkf_fs_fread_alloc_ensemble() to load an ensemble of - nodes and enkf_fs_fread_alloc_ts() to load a time series of nodes. The driver can - implement these functions (to get a performance gain when loading many nodes). It - is not necceasry to implement these functions, the enkf_fs layer has simple - functions doing repeated calls to the enkf_fs_fread_node() function. - - - The drivers - ----------- - - The enkf_fs layer does not self implement the functions to read and write - nodes. Instead what happens is: - - 1. We determine the type of the node (static/dynamic/parameter), and select - the appropriate driver. - - 2. The appropriate driver is called to implement e.g. the fread_node - functions. - - The different types of data have different characteristcs, which the driver is - implemented to support. The characteristics the drivers support are the - following: - - - dynamic driver - -------------- - This is the simplest driver, all data is stored both in a forecast version and - an analyzed version. - - - parameter driver - ---------------- - This driver utilizes that parameters do not change during the forward model, - i.e. (analyzed , t) = (forecast , t - 1). So, only one version of the data is - actually stored; if you ask for the forecast you just get the data from the - previous report_step. - To support spin-ups and such the driver will actually go backwards in - report_time all the way until a node is found on disk. - - - static driver - ------------- - Like the parameter driver this also only stores one version od the data, - however in addition it has to query the node for a ID to support multiply - occuring keywords in ECLIPSE restart files. - - Currently only the plain_driver_xxx family has been implemented. Observe that - there is no dependencies between the drivers, it is perfectly possible to - implement a new driver for storage of static datat only. (There is probably a - large amount of static data which is common both between members and for - several consecutive report steps; utilizing that one could write a static - driver which was admittedly slower, but leaner on the storage.) - - The drivers are allocated prior to allocating the enkf_fs instance, and - pointers are passed in when allocating the enkf_fs instance. - - - Mounting the filesystem - ----------------------- - - Mounting the filesystem - cool ehh?? Anyway, the important point is - that the moment ensemble information has hit the filesystem later - versions of the enkf program must support exactly that lay-out, - those drivers+++. To ensure this I see two possibilities: - - 1. We can freeze the filesystem drivers, and the layout on disk - indefinetly. - - 2. We can store the information needed to bootstrap the drivers, - according to the current layout on disk, in the - filesystem. I.e. something like a '/etc/fstab' file. - - We have chosen the second alternative. Currently this implemented as - follows: - - 1. In main() we query for the file {root-path}/enkf_mount_info. If - that file does not exists it is created by calls to the - selected drivers xxxx_fwrite_mount_info() functions. - - 2. enkf_fs_mount() is called with the enkf_mount_info as input. - - The enkf_mount_info file (BINARY) consists of four records (one for - each driver, including the index). The format of each record is: - - DRIVER_CATEGORY DRIVER_ID INFO - int int void * - - The driver category should be one of the four integer values in - fs_driver_type (fs_types.h) and DRIVER_ID is one the integer - values in fs_driver_impl. The last void * data is whatever - (serialized) info the driver needs to bootstrap. This info is - written by the drivers xxxx_fwrite_mount_info() function, and it is - used when the driver is allocated with xxxx_fread_alloc(). - - The different drivers can be in arbitrary order in the - enkf_mount_info file, but when four records are read it checks that - all drivers have been initialized, and aborts if that is not the - case. - - If the enkf_mount_info file is deleted you (might) be fucked. It - is currently 'protected' with chomd a-w - but that is of course not - foolprof. -*/ - - - - -/** - Observe the following convention: the initial ensemble at report - step 0 is supposed to be analyzed. If we ask for the forecast at - report_step 0, we should get the analyzed value. -*/ - - -#define ENKF_FS_TYPE_ID 1089763 -#define ENKF_MOUNT_MAP "enkf_mount_info" -#define SUMMARY_KEY_SET_FILE "summary-key-set" -#define TIME_MAP_FILE "time-map" -#define STATE_MAP_FILE "state-map" -#define MISFIT_ENSEMBLE_FILE "misfit-ensemble" -#define CASE_CONFIG_FILE "case_config" -#define CUSTOM_KW_CONFIG_SET_FILE "custom_kw_config_set" - -struct enkf_fs_struct { - UTIL_TYPE_ID_DECLARATION; - char * case_name; - char * root_path; - char * mount_point; // mount_point = root_path / case_name; the mount_point is the fundamental INPUT. - - char * lock_file; - int lock_fd; - - fs_driver_type * dynamic_forecast; - fs_driver_type * parameter; - fs_driver_type * index ; - - bool read_only; /* Whether this filesystem has been mounted read-only. */ - time_map_type * time_map; - cases_config_type * cases_config; - state_map_type * state_map; - summary_key_set_type * summary_key_set; - misfit_ensemble_type * misfit_ensemble; - custom_kw_config_set_type * custom_kw_config_set; - /* - The variables below here are for storing arbitrary files within - the enkf_fs storage directory, but not as serialized enkf_nodes. - */ - path_fmt_type * case_fmt; - path_fmt_type * case_member_fmt; - path_fmt_type * case_tstep_fmt; - path_fmt_type * case_tstep_member_fmt; - - int refcount; - int writecount; -}; - - -/*****************************************************************/ - - -UTIL_SAFE_CAST_FUNCTION( enkf_fs , ENKF_FS_TYPE_ID) -UTIL_IS_INSTANCE_FUNCTION( enkf_fs , ENKF_FS_TYPE_ID) - -static void enkf_fs_umount( enkf_fs_type * fs ); - -int enkf_fs_incref( enkf_fs_type * fs ) { - fs->refcount++; - return fs->refcount; -} - - -int enkf_fs_decref( enkf_fs_type * fs ) { - int refcount; - fs->refcount--; - refcount = fs->refcount; - - if (fs->refcount < 0) - util_abort("%s: internal fuckup. The filesystem refcount:%d is < 0 \n",__func__ , fs->refcount); - - if (refcount == 0) - enkf_fs_umount( fs ); - - return refcount; -} - - -int enkf_fs_get_refcount( const enkf_fs_type * fs ) { - return fs->refcount; -} - - -enkf_fs_type * enkf_fs_get_ref( enkf_fs_type * fs ) { - enkf_fs_incref( fs ); - return fs; -} - - -static enkf_fs_type * enkf_fs_alloc_empty( const char * mount_point ) { - enkf_fs_type * fs = util_malloc(sizeof * fs ); - UTIL_TYPE_ID_INIT( fs , ENKF_FS_TYPE_ID ); - fs->time_map = time_map_alloc( ); - fs->cases_config = cases_config_alloc(); - fs->state_map = state_map_alloc(); - fs->summary_key_set = summary_key_set_alloc(); - fs->custom_kw_config_set = custom_kw_config_set_alloc(); - fs->misfit_ensemble = misfit_ensemble_alloc(); - fs->index = NULL; - fs->parameter = NULL; - fs->dynamic_forecast = NULL; - fs->read_only = true; - fs->mount_point = util_alloc_string_copy( mount_point ); - fs->refcount = 0; - fs->writecount = 0; - fs->lock_fd = 0; - - if (mount_point == NULL) - util_abort("%s: fatal internal error: mount_point == NULL \n",__func__); - { - char ** path_tmp; - int path_len; - - util_path_split( fs->mount_point , &path_len , &path_tmp); - fs->case_name = util_alloc_string_copy( path_tmp[path_len - 1]); - fs->root_path = util_alloc_joined_string( (const char **) path_tmp , path_len , UTIL_PATH_SEP_STRING); - fs->lock_file = util_alloc_filename( fs->mount_point , fs->case_name , "lock"); - - if (util_try_lockf( fs->lock_file , S_IWUSR + S_IWGRP , &fs->lock_fd)) { - fs->read_only = false; - } else { - fprintf(stderr," Another program has already opened filesystem read-write - this instance will be UNSYNCRONIZED read-only. Cross your fingers ....\n"); - fs->read_only = true; - } - - util_free_stringlist( path_tmp , path_len ); - } - return fs; -} - - - - -static int enkf_fs_fread_fs_version__(FILE * stream) { - int version; - long fs_tag = util_fread_long( stream ); - if (fs_tag == FS_MAGIC_ID) - version = util_fread_int(stream); - else - version = 0; - return version; -} - - -/** - -1 : No mount map found. - 0 : Old mount map without version info. - x : Actual version info. -*/ - -static int enkf_fs_get_fs_version__(const char * config_file) { - int version = -1; - if (util_file_exists(config_file)) { - FILE * stream = util_fopen(config_file , "r"); - version = enkf_fs_fread_fs_version__(stream); - fclose(stream); - } - return version; -} - -/** - Function written to look for old (version <= 104) mount info maps. -*/ - -int enkf_fs_get_version104( const char * path ) { - char * config_file = util_alloc_filename( path , ENKF_MOUNT_MAP, NULL); - int version = enkf_fs_get_fs_version__( config_file ); - free( config_file ); - return version; -} - - - - - - - -/*****************************************************************/ - - -static void enkf_fs_init_path_fmt( enkf_fs_type * fs) { - /* - Installing the path_fmt instances for the storage of arbitrary files. - */ - fs->case_fmt = path_fmt_alloc_directory_fmt( DEFAULT_CASE_PATH ); - fs->case_member_fmt = path_fmt_alloc_directory_fmt( DEFAULT_CASE_MEMBER_PATH ); - fs->case_tstep_fmt = path_fmt_alloc_directory_fmt( DEFAULT_CASE_TSTEP_PATH ); - fs->case_tstep_member_fmt = path_fmt_alloc_directory_fmt( DEFAULT_CASE_TSTEP_MEMBER_PATH ); - -} - - -static void enkf_fs_create_plain_fs( FILE * stream , void * arg) { - - plain_driver_create_fs( stream , DRIVER_PARAMETER , DEFAULT_PLAIN_NODE_PARAMETER_PATH , DEFAULT_PLAIN_VECTOR_PARAMETER_PATH); - plain_driver_create_fs( stream , DRIVER_DYNAMIC_FORECAST , DEFAULT_PLAIN_NODE_DYNAMIC_FORECAST_PATH , DEFAULT_PLAIN_VECTOR_DYNAMIC_FORECAST_PATH); - plain_driver_create_fs( stream , DRIVER_INDEX , DEFAULT_PLAIN_NODE_INDEX_PATH , DEFAULT_PLAIN_VECTOR_INDEX_PATH ); - -} - - - -static void enkf_fs_create_block_fs( FILE * stream , int num_drivers , const char * mount_point , void * arg) { - - block_fs_driver_create_fs( stream , mount_point , DRIVER_PARAMETER , num_drivers , "Ensemble/mod_%d" , "PARAMETER"); - block_fs_driver_create_fs( stream , mount_point , DRIVER_DYNAMIC_FORECAST , num_drivers , "Ensemble/mod_%d" , "FORECAST"); - block_fs_driver_create_fs( stream , mount_point , DRIVER_INDEX , 1 , "Index" , "INDEX"); - -} - - -static void enkf_fs_assign_driver( enkf_fs_type * fs , fs_driver_type * driver , fs_driver_enum driver_type ) { - switch(driver_type) { - case(DRIVER_PARAMETER): - fs->parameter = driver; - break; - case(DRIVER_DYNAMIC_FORECAST): - fs->dynamic_forecast = driver; - break; - case(DRIVER_INDEX): - fs->index = driver; - break; - case(DRIVER_STATIC): - util_abort("%s: internal error - should not assign a STATIC driver \n",__func__); - break; - case(DRIVER_DYNAMIC_ANALYZED): - util_abort("%s: internal error - should not assign a DYNAMIC_ANALYZED driver \n",__func__); - break; - } -} - - -static enkf_fs_type * enkf_fs_mount_block_fs( FILE * fstab_stream , const char * mount_point ) { - enkf_fs_type * fs = enkf_fs_alloc_empty( mount_point ); - - { - while (true) { - fs_driver_enum driver_type; - if (fread( &driver_type , sizeof driver_type , 1 , fstab_stream) == 1) { - if (fs_types_valid( driver_type )) { - fs_driver_type * driver = block_fs_driver_open( fstab_stream , mount_point , driver_type , fs->read_only); - enkf_fs_assign_driver( fs , driver , driver_type ); - } else - block_fs_driver_fskip( fstab_stream ); - } else - break; - } - } - - return fs; -} - - - - -static enkf_fs_type * enkf_fs_mount_plain( FILE * fstab_stream , const char * mount_point ) { - enkf_fs_type * fs = enkf_fs_alloc_empty( mount_point ); - { - while (true) { - fs_driver_enum driver_type; - if (fread( &driver_type , sizeof driver_type , 1 , fstab_stream) == 1) { - if (fs_types_valid( driver_type )) { - fs_driver_type * driver = plain_driver_open( fstab_stream , mount_point ); - enkf_fs_assign_driver( fs , driver , driver_type ); - } else - plain_driver_fskip( fstab_stream ); - - } else - break; - } - } - return fs; -} - - - -enkf_fs_type * enkf_fs_create_fs( const char * mount_point, fs_driver_impl driver_id , void * arg , bool mount) { - const int num_drivers = 32; - FILE * stream = fs_driver_open_fstab( mount_point , true ); - if (stream != NULL) { - fs_driver_init_fstab( stream, driver_id); - { - switch( driver_id ) { - case( BLOCK_FS_DRIVER_ID ): - enkf_fs_create_block_fs( stream , num_drivers , mount_point , arg ); - break; - case( PLAIN_DRIVER_ID ): - enkf_fs_create_plain_fs( stream , arg ); - break; - default: - util_abort("%s: Invalid driver_id value:%d \n",__func__ , driver_id ); - } - } - fclose( stream ); - } - - if (mount) - return enkf_fs_mount( mount_point ); - else - return NULL; -} - - -static void enkf_fs_fsync_time_map( enkf_fs_type * fs ) { - char * filename = enkf_fs_alloc_case_filename( fs , TIME_MAP_FILE ); - time_map_fwrite( fs->time_map , filename ); - free( filename ); -} - - -static void enkf_fs_fread_time_map( enkf_fs_type * fs ) { - char * filename = enkf_fs_alloc_case_filename( fs , TIME_MAP_FILE ); - time_map_fread( fs->time_map , filename ); - free( filename ); -} - - -static void enkf_fs_fsync_cases_config( enkf_fs_type * fs ) { - char * filename = enkf_fs_alloc_case_filename( fs , CASE_CONFIG_FILE ); - cases_config_fwrite( fs->cases_config , filename ); - free( filename ); -} - -static void enkf_fs_fsync_state_map( enkf_fs_type * fs ) { - char * filename = enkf_fs_alloc_case_filename( fs , STATE_MAP_FILE ); - state_map_fwrite( fs->state_map , filename ); - free( filename ); -} - -static void enkf_fs_fsync_summary_key_set( enkf_fs_type * fs ) { - char * filename = enkf_fs_alloc_case_filename( fs , SUMMARY_KEY_SET_FILE ); - summary_key_set_fwrite( fs->summary_key_set , filename ); - free( filename ); -} - -static void enkf_fs_fsync_custom_kw_config_set( enkf_fs_type * fs ) { - char * filename = enkf_fs_alloc_case_filename(fs, CUSTOM_KW_CONFIG_SET_FILE); - custom_kw_config_set_fwrite(fs->custom_kw_config_set, filename ); - free( filename ); -} - -static void enkf_fs_fread_cases_config( enkf_fs_type * fs ) { - char * filename = enkf_fs_alloc_case_filename( fs , CASE_CONFIG_FILE ); - cases_config_fread( fs->cases_config , filename ); - free( filename ); -} - - -static void enkf_fs_fread_state_map( enkf_fs_type * fs ) { - char * filename = enkf_fs_alloc_case_filename( fs , STATE_MAP_FILE ); - state_map_fread( fs->state_map , filename ); - free( filename ); -} - -static void enkf_fs_fread_summary_key_set( enkf_fs_type * fs ) { - char * filename = enkf_fs_alloc_case_filename( fs , SUMMARY_KEY_SET_FILE ); - summary_key_set_fread( fs->summary_key_set , filename ); - free( filename ); -} - -static void enkf_fs_fread_custom_kw_config_set(enkf_fs_type * fs) { - char * filename = enkf_fs_alloc_case_filename(fs, CUSTOM_KW_CONFIG_SET_FILE); - custom_kw_config_set_fread(fs->custom_kw_config_set, filename); - free( filename ); -} - -state_map_type * enkf_fs_alloc_readonly_state_map( const char * mount_point ) { - path_fmt_type * path_fmt = path_fmt_alloc_directory_fmt( DEFAULT_CASE_PATH ); - char * filename = path_fmt_alloc_file( path_fmt , false , mount_point , STATE_MAP_FILE); - - state_map_type * state_map = state_map_fread_alloc_readonly( filename ); - - path_fmt_free( path_fmt ); - free( filename ); - return state_map; -} - -summary_key_set_type * enkf_fs_alloc_readonly_summary_key_set( const char * mount_point ) { - path_fmt_type * path_fmt = path_fmt_alloc_directory_fmt( DEFAULT_CASE_PATH ); - char * filename = path_fmt_alloc_file( path_fmt , false , mount_point , SUMMARY_KEY_SET_FILE); - - summary_key_set_type * summary_key_set = summary_key_set_alloc_from_file( filename, true ); - - path_fmt_free( path_fmt ); - free( filename ); - return summary_key_set; -} - -time_map_type * enkf_fs_alloc_readonly_time_map( const char * mount_point ) { - path_fmt_type * path_fmt = path_fmt_alloc_directory_fmt( DEFAULT_CASE_PATH ); - char * filename = path_fmt_alloc_file( path_fmt , false , mount_point , TIME_MAP_FILE); - - time_map_type * time_map = time_map_fread_alloc_readonly( filename ); - - path_fmt_free( path_fmt ); - free( filename ); - return time_map; -} - - - -static void enkf_fs_fread_misfit( enkf_fs_type * fs ) { - FILE * stream = enkf_fs_open_excase_file( fs , MISFIT_ENSEMBLE_FILE ); - if (stream != NULL) { - misfit_ensemble_fread( fs->misfit_ensemble , stream ); - fclose( stream ); - } -} - - -static void enkf_fs_fwrite_misfit( enkf_fs_type * fs ) { - if (misfit_ensemble_initialized( fs->misfit_ensemble )) { - FILE * stream = enkf_fs_open_case_file( fs , MISFIT_ENSEMBLE_FILE , "w"); - misfit_ensemble_fwrite( fs->misfit_ensemble , stream ); - fclose( stream ); - } -} - - - -int enkf_fs_disk_version(const char * mount_point ) { - int disk_version = -1; - FILE * stream = fs_driver_open_fstab( mount_point , false ); - if (stream) { - disk_version = fs_driver_fread_version( stream ); - fclose( stream ); - } - return disk_version; -} - - -bool enkf_fs_update_disk_version(const char * mount_point , int src_version , int target_version) { - if (enkf_fs_disk_version( mount_point ) == src_version) { - char * fstab_file = fs_driver_alloc_fstab_file( mount_point ); - FILE * stream = util_fopen( fstab_file , "r+"); - - fseek( stream , 0L, SEEK_SET ); - fs_driver_assert_magic( stream ); - util_fwrite_int( target_version , stream ); - - fclose( stream ); - free( fstab_file ); - - return true; - } else - return false; -} - - -enkf_fs_type * enkf_fs_mount( const char * mount_point ) { - FILE * stream = fs_driver_open_fstab( mount_point , false ); - - if (stream != NULL) { - enkf_fs_type * fs = NULL; - fs_driver_assert_magic( stream ); - fs_driver_assert_version( stream , mount_point ); - { - fs_driver_impl driver_id = util_fread_int( stream ); - - switch( driver_id ) { - case( BLOCK_FS_DRIVER_ID ): - fs = enkf_fs_mount_block_fs( stream , mount_point); - break; - case( PLAIN_DRIVER_ID ): - fs = enkf_fs_mount_plain( stream , mount_point ); - break; - default: - util_abort("%s: unrecognized driver_id:%d \n",__func__ , driver_id ); - } - } - fclose( stream ); - enkf_fs_init_path_fmt( fs ); - enkf_fs_fread_time_map( fs ); - enkf_fs_fread_cases_config( fs ); - enkf_fs_fread_state_map( fs ); - enkf_fs_fread_summary_key_set( fs ); - enkf_fs_fread_custom_kw_config_set( fs ); - enkf_fs_fread_misfit( fs ); - - enkf_fs_get_ref( fs ); - return fs; - } - return NULL; -} - - -bool enkf_fs_exists( const char * mount_point ) { - bool exists = false; - - FILE * stream = fs_driver_open_fstab( mount_point , false ); - if (stream != NULL) { - exists = true; - fclose( stream ); - } - - return exists; -} - - - - -/*****************************************************************/ - - - -static void enkf_fs_free_driver(fs_driver_type * driver) { - driver->free_driver(driver); -} - - -static void enkf_fs_umount( enkf_fs_type * fs ) { - if (!fs->read_only) { - enkf_fs_fsync( fs ); - enkf_fs_fwrite_misfit( fs ); - } - - { - int refcount = fs->refcount; - if (refcount == 0) { - enkf_fs_free_driver( fs->dynamic_forecast ); - enkf_fs_free_driver( fs->parameter ); - enkf_fs_free_driver( fs->index ); - - if (fs->lock_fd > 0) { - close( fs->lock_fd ); // Closing the lock_file file descriptor - and releasing the lock. - util_unlink_existing( fs->lock_file ); - } - - util_safe_free( fs->case_name ); - util_safe_free( fs->root_path ); - util_safe_free(fs->lock_file); - util_safe_free( fs->mount_point ); - path_fmt_free( fs->case_fmt ); - path_fmt_free( fs->case_member_fmt ); - path_fmt_free( fs->case_tstep_fmt ); - path_fmt_free( fs->case_tstep_member_fmt ); - - custom_kw_config_set_free( fs->custom_kw_config_set ); - state_map_free( fs->state_map ); - summary_key_set_free(fs->summary_key_set); - time_map_free( fs->time_map ); - cases_config_free( fs->cases_config ); - misfit_ensemble_free( fs->misfit_ensemble ); - free( fs ); - } else - util_abort("%s: internal fuckup - tried to umount a filesystem with refcount:%d\n",__func__ , refcount); - } -} - - - - - -static void * enkf_fs_select_driver(enkf_fs_type * fs , enkf_var_type var_type, const char * key) { - void * driver = NULL; - switch (var_type) { - case(PARAMETER): - driver = fs->parameter; - break; - case(DYNAMIC_RESULT): - driver = fs->dynamic_forecast; - break; - case(DYNAMIC_STATE): - driver = fs->dynamic_forecast; - break; - default: - util_abort("%s: fatal internal error - could not determine enkf_fs driver for object:%s[integer type:%d] - aborting.\n",__func__, key , var_type); - } - return driver; -} - - - -/*****************************************************************/ -/* Exported functions for enkf_node instances . */ - - -static void enkf_fs_fsync_driver( fs_driver_type * driver ) { - if (driver->fsync_driver != NULL) - driver->fsync_driver( driver ); -} - - - -void enkf_fs_fsync( enkf_fs_type * fs ) { - enkf_fs_fsync_driver( fs->parameter ); - enkf_fs_fsync_driver( fs->dynamic_forecast ); - enkf_fs_fsync_driver( fs->index ); - - enkf_fs_fsync_time_map( fs ); - enkf_fs_fsync_cases_config( fs) ; - enkf_fs_fsync_state_map( fs ); - enkf_fs_fsync_summary_key_set( fs ); - enkf_fs_fsync_custom_kw_config_set(fs); -} - - - - -void enkf_fs_fread_node(enkf_fs_type * enkf_fs , buffer_type * buffer , - const char * node_key , - enkf_var_type var_type , - int report_step, - int iens) { - - fs_driver_type * driver = enkf_fs_select_driver(enkf_fs , var_type , node_key ); - if (var_type == PARAMETER) - /* Parameters are *ONLY* stored at report_step == 0 */ - report_step = 0; - - buffer_rewind( buffer ); - driver->load_node(driver , node_key , report_step , iens , buffer); -} - - -void enkf_fs_fread_vector(enkf_fs_type * enkf_fs , buffer_type * buffer , - const char * node_key , - enkf_var_type var_type , - int iens) { - - fs_driver_type * driver = enkf_fs_select_driver(enkf_fs , var_type , node_key ); - - buffer_rewind( buffer ); - driver->load_vector(driver , node_key , iens , buffer); -} - - - -bool enkf_fs_has_node(enkf_fs_type * enkf_fs , const char * node_key , enkf_var_type var_type , int report_step , int iens) { - fs_driver_type * driver = fs_driver_safe_cast(enkf_fs_select_driver(enkf_fs , var_type , node_key)); - return driver->has_node(driver , node_key , report_step , iens ); -} - - -bool enkf_fs_has_vector(enkf_fs_type * enkf_fs , const char * node_key , enkf_var_type var_type , int iens ) { - fs_driver_type * driver = fs_driver_safe_cast(enkf_fs_select_driver(enkf_fs , var_type , node_key)); - return driver->has_vector(driver , node_key , iens ); -} - -void enkf_fs_fwrite_node(enkf_fs_type * enkf_fs , buffer_type * buffer , const char * node_key, enkf_var_type var_type, - int report_step , int iens ) { - if (enkf_fs->read_only) - util_abort("%s: attempt to write to read_only filesystem mounted at:%s - aborting. \n",__func__ , enkf_fs->mount_point); - - - if ((var_type == PARAMETER) && (report_step > 0)) - util_abort("%s: Parameters can only be saved for report_step = 0 %s:%d\n", __func__ , node_key , report_step); - { - void * _driver = enkf_fs_select_driver(enkf_fs , var_type , node_key); - { - fs_driver_type * driver = fs_driver_safe_cast(_driver); - driver->save_node(driver , node_key , report_step , iens , buffer); - } - } -} - - -void enkf_fs_fwrite_vector(enkf_fs_type * enkf_fs , buffer_type * buffer , const char * node_key, enkf_var_type var_type, - int iens ) { - if (enkf_fs->read_only) - util_abort("%s: attempt to write to read_only filesystem mounted at:%s - aborting. \n",__func__ , enkf_fs->mount_point); - { - void * _driver = enkf_fs_select_driver(enkf_fs , var_type , node_key); - { - fs_driver_type * driver = fs_driver_safe_cast(_driver); - driver->save_vector(driver , node_key , iens , buffer); - } - } -} - - - - -/*****************************************************************/ - - - - - -/*****************************************************************/ - -const char * enkf_fs_get_mount_point( const enkf_fs_type * fs ) { - return fs->mount_point; -} - -const char * enkf_fs_get_root_path( const enkf_fs_type * fs ) { - return fs->root_path; -} - -const char * enkf_fs_get_case_name( const enkf_fs_type * fs ) { - return fs->case_name; -} - - -bool enkf_fs_is_read_only(const enkf_fs_type * fs) { - return fs->read_only; -} - -void enkf_fs_set_writable(enkf_fs_type * fs, bool writable) { - fs->read_only = !writable; -} - -void enkf_fs_debug_fprintf( const enkf_fs_type * fs) { - printf("-----------------------------------------------------------------\n"); - printf("fs...................: %p \n",fs ); - printf("Mount point..........: %s \n",fs->mount_point ); - printf("Dynamic forecast.....: %p \n",fs->dynamic_forecast ); - printf("Parameter............: %p \n",fs->parameter ); - printf("Index................: %p \n",fs->index ); - printf("-----------------------------------------------------------------\n"); -} - - - - -/*****************************************************************/ -/* write_dir / read_dir confusion. */ - -char * enkf_fs_alloc_case_filename( const enkf_fs_type * fs , const char * input_name) { - char * filename = path_fmt_alloc_file( fs->case_fmt , false , fs->mount_point , input_name); - return filename; -} - - -char * enkf_fs_alloc_case_member_filename( const enkf_fs_type * fs , int iens , const char * input_name) { - char * filename = path_fmt_alloc_file( fs->case_member_fmt , false , fs->mount_point , iens , input_name); - return filename; -} - - -char * enkf_fs_alloc_case_tstep_filename( const enkf_fs_type * fs , int tstep , const char * input_name) { - char * filename = path_fmt_alloc_file( fs->case_tstep_fmt , false , fs->mount_point , tstep , input_name); - return filename; -} - -char * enkf_fs_alloc_case_tstep_member_filename( const enkf_fs_type * fs , int tstep , int iens , const char * input_name) { - char * filename = path_fmt_alloc_file( fs->case_tstep_member_fmt , false , fs->mount_point , tstep , iens , input_name); - return filename; -} - - - -FILE * enkf_fs_open_case_file( const enkf_fs_type * fs , const char * input_name , const char * mode) { - char * filename = enkf_fs_alloc_case_filename( fs , input_name ); - FILE * stream = util_mkdir_fopen( filename , mode ); - free( filename ); - return stream; -} - - -FILE * enkf_fs_open_case_member_file( const enkf_fs_type * fs , const char * input_name , int iens , const char * mode) { - char * filename = enkf_fs_alloc_case_member_filename( fs , iens , input_name ); - FILE * stream = util_mkdir_fopen( filename , mode ); - free( filename ); - return stream; -} - - -FILE * enkf_fs_open_case_tstep_file( const enkf_fs_type * fs , const char * input_name , int tstep , const char * mode) { - char * filename = enkf_fs_alloc_case_tstep_filename( fs , tstep , input_name ); - FILE * stream = util_mkdir_fopen( filename , mode ); - free( filename ); - return stream; -} - - -FILE * enkf_fs_open_case_tstep_member_file( const enkf_fs_type * fs , const char * input_name , int tstep , int iens , const char * mode) { - char * filename = enkf_fs_alloc_case_tstep_member_filename( fs , tstep , iens , input_name ); - FILE * stream = util_mkdir_fopen( filename , mode ); - free( filename ); - return stream; -} - -/*****************************************************************/ -/* - The open_exXXX functions will return NULL if the file does not - already exist. These functions can only be used to open with 'r' - mode. -*/ - - - -static FILE * enkf_fs_open_exfile( const char * filename ) { - if (util_file_exists(filename)) - return util_fopen( filename , "r"); - else - return NULL; -} - -FILE * enkf_fs_open_excase_file( const enkf_fs_type * fs , const char * input_name ) { - char * filename = enkf_fs_alloc_case_filename( fs , input_name ); - FILE * stream = enkf_fs_open_exfile( filename ); - free( filename ); - return stream; -} - - -FILE * enkf_fs_open_excase_member_file( const enkf_fs_type * fs , const char * input_name , int iens ) { - char * filename = enkf_fs_alloc_case_member_filename( fs , iens , input_name ); - FILE * stream = enkf_fs_open_exfile( filename ); - free( filename ); - return stream; -} - - -FILE * enkf_fs_open_excase_tstep_file( const enkf_fs_type * fs , const char * input_name , int tstep ) { - char * filename = enkf_fs_alloc_case_tstep_filename( fs , tstep , input_name ); - FILE * stream = enkf_fs_open_exfile( filename ); - free( filename ); - return stream; -} - - -FILE * enkf_fs_open_excase_tstep_member_file( const enkf_fs_type * fs , const char * input_name , int tstep , int iens ) { - char * filename = enkf_fs_alloc_case_tstep_member_filename( fs , tstep , iens , input_name ); - FILE * stream = enkf_fs_open_exfile( filename ); - free( filename ); - return stream; -} - -/*****************************************************************/ - -time_map_type * enkf_fs_get_time_map( const enkf_fs_type * fs ) { - return fs->time_map; -} - -cases_config_type * enkf_fs_get_cases_config( const enkf_fs_type * fs) { - return fs->cases_config; -} - -state_map_type * enkf_fs_get_state_map( const enkf_fs_type * fs ) { - return fs->state_map; -} - -summary_key_set_type * enkf_fs_get_summary_key_set( const enkf_fs_type * fs ) { - return fs->summary_key_set; -} - -custom_kw_config_set_type * enkf_fs_get_custom_kw_config_set(const enkf_fs_type * fs) { - return fs->custom_kw_config_set; -} - -misfit_ensemble_type * enkf_fs_get_misfit_ensemble( const enkf_fs_type * fs ) { - return fs->misfit_ensemble; -} - -void enkf_fs_increase_write_count(enkf_fs_type * fs) { - fs->writecount = fs->writecount + 1; -} - -void enkf_fs_decrease_write_count(enkf_fs_type * fs) { - fs->writecount = fs->writecount - 1; -} - -int enkf_fs_get_write_count(const enkf_fs_type * fs) { - return fs->writecount; -} - diff --git a/ThirdParty/Ert/libenkf/src/enkf_main.c b/ThirdParty/Ert/libenkf/src/enkf_main.c deleted file mode 100644 index ca8ea54ee1..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_main.c +++ /dev/null @@ -1,3304 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - The file 'enkf_main.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define HAVE_THREAD_POOL 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/**/ - -/** - This object should contain **everything** needed to run a enkf - simulation. A way to wrap up all available information/state and - pass it around. An attempt has been made to collect various pieces - of related information together in a couple of objects - (model_config, ecl_config, site_config and ensemble_config). When - it comes to these holding objects the following should be observed: - - 1. It not always obvious where a piece of information should be - stored, i.e. the grid is a property of the model, however it is - an eclipse grid, and hence also belongs to eclipse - configuration?? [In this case ecl_config wins out.] - - 2. The information stored in these objects is typically passed on - to the enkf_state object, where it is used. - - 3. At enkf_state level it is not really consequent - in some cases - the enkf_state object takes a scalar copy (i.e. keep_runpath), - and in other cases only a pointer down to the underlying - enkf_main object is taken. In the former case it is no way to - change global behaviour by modifying the enkf_main objects. - - In the enkf_state object the fields of the member_config, - ecl_config, site_config and ensemble_config objects are mixed - and matched into other small holding objects defined in - enkf_state.c. - -*/ - -#define ENKF_MAIN_ID 8301 - -struct enkf_main_struct { - UTIL_TYPE_ID_DECLARATION; - enkf_fs_type * dbase; /* The internalized information. */ - - ensemble_config_type * ensemble_config; /* The config objects for the various enkf nodes.*/ - hook_manager_type * hook_manager; - model_config_type * model_config; - ecl_config_type * ecl_config; - site_config_type * site_config; - analysis_config_type * analysis_config; - local_config_type * local_config; /* Holding all the information about local analysis. */ - ert_templates_type * templates; /* Run time templates */ - config_settings_type * plot_config; /* Information about plotting. */ - rng_config_type * rng_config; - rng_type * rng; - ert_workflow_list_type * workflow_list; - ranking_table_type * ranking_table; - - /*---------------------------*/ /* Variables related to substitution. */ - subst_func_pool_type * subst_func_pool; - subst_list_type * subst_list; /* A parent subst_list instance - common to all ensemble members. */ - /*-------------------------*/ - - int_vector_type * keep_runpath; /* HACK: This is only used in the initialization period - afterwards the data is held by the enkf_state object. */ - bool pre_clear_runpath; /* HACK: This is only used in the initialization period - afterwards the data is held by the enkf_state object. */ - - char * site_config_file; - char * user_config_file; - char * rft_config_file; /* File giving the configuration to the RFTwells*/ - enkf_obs_type * obs; - enkf_state_type ** ensemble; /* The ensemble ... */ - int ens_size; /* The size of the ensemble */ - bool verbose; -}; - - - - -/*****************************************************************/ - -void enkf_main_init_internalization( enkf_main_type * , run_mode_type ); -void enkf_main_update_local_updates( enkf_main_type * enkf_main); -static void enkf_main_close_fs( enkf_main_type * enkf_main ); -static void enkf_main_init_fs( enkf_main_type * enkf_main ); -static void enkf_main_user_select_initial_fs(enkf_main_type * enkf_main ); - -/*****************************************************************/ - -UTIL_SAFE_CAST_FUNCTION(enkf_main , ENKF_MAIN_ID) -UTIL_IS_INSTANCE_FUNCTION(enkf_main , ENKF_MAIN_ID) - -analysis_config_type * enkf_main_get_analysis_config(const enkf_main_type * enkf_main) { - return enkf_main->analysis_config; -} - -bool enkf_main_get_pre_clear_runpath( const enkf_main_type * enkf_main ) { - return enkf_state_get_pre_clear_runpath( enkf_main->ensemble[0] ); -} - -void enkf_main_set_pre_clear_runpath( enkf_main_type * enkf_main , bool pre_clear_runpath) { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - int iens; - for (iens = 0; iens < ens_size; iens++) - enkf_state_set_pre_clear_runpath( enkf_main->ensemble[iens] , pre_clear_runpath ); -} - - -bool enkf_main_set_refcase( enkf_main_type * enkf_main , const char * refcase_path) { - bool set_refcase = ecl_config_load_refcase( enkf_main->ecl_config , refcase_path ); - - model_config_set_refcase( enkf_main->model_config , ecl_config_get_refcase( enkf_main->ecl_config )); - ensemble_config_set_refcase( enkf_main->ensemble_config , ecl_config_get_refcase( enkf_main->ecl_config )); - - return set_refcase; -} - - -ui_return_type * enkf_main_validata_refcase( const enkf_main_type * enkf_main , const char * refcase_path) { - return ecl_config_validate_refcase( enkf_main->ecl_config , refcase_path ); -} - - -ui_return_type * enkf_main_set_eclbase( enkf_main_type * enkf_main , const char * eclbase_fmt) { - ui_return_type * ui_return = ecl_config_validate_eclbase( enkf_main->ecl_config , eclbase_fmt); - if (ui_return_get_status(ui_return) == UI_RETURN_OK) { - ecl_config_set_eclbase( enkf_main->ecl_config , eclbase_fmt ); - for (int iens = 0; iens < enkf_main->ens_size; iens++) - enkf_state_update_eclbase(enkf_main->ensemble[iens]); - } - return ui_return; -} - -void enkf_main_init_jobname( enkf_main_type * enkf_main) { - for (int iens = 0; iens < enkf_main->ens_size; iens++) - enkf_state_update_jobname( enkf_main->ensemble[iens] ); -} - - -void enkf_main_set_jobname( enkf_main_type * enkf_main , const char * jobname_fmt) { - model_config_set_jobname_fmt( enkf_main->model_config , jobname_fmt ); - enkf_main_init_jobname( enkf_main ); -} - -void enkf_main_set_user_config_file( enkf_main_type * enkf_main , const char * user_config_file ) { - enkf_main->user_config_file = util_realloc_string_copy( enkf_main->user_config_file , user_config_file ); -} - -void enkf_main_set_rft_config_file( enkf_main_type * enkf_main , const char * rft_config_file ) { - enkf_main->rft_config_file = util_realloc_string_copy( enkf_main->rft_config_file , rft_config_file ); -} - -void enkf_main_set_site_config_file( enkf_main_type * enkf_main , const char * site_config_file ) { - enkf_main->site_config_file = util_realloc_string_copy( enkf_main->site_config_file , site_config_file ); -} - -const char * enkf_main_get_user_config_file( const enkf_main_type * enkf_main ) { - return enkf_main->user_config_file; -} - -const char * enkf_main_get_site_config_file( const enkf_main_type * enkf_main ) { - return enkf_main->site_config_file; -} - -const char * enkf_main_get_rft_config_file( const enkf_main_type * enkf_main ) { - return enkf_main->rft_config_file; -} - -ensemble_config_type * enkf_main_get_ensemble_config(const enkf_main_type * enkf_main) { - return enkf_main->ensemble_config; -} - -site_config_type * enkf_main_get_site_config( const enkf_main_type * enkf_main ) { - return enkf_main->site_config; -} - - -subst_list_type * enkf_main_get_data_kw( const enkf_main_type * enkf_main ) { - return enkf_main->subst_list; -} - - -local_config_type * enkf_main_get_local_config( const enkf_main_type * enkf_main ) { - return enkf_main->local_config; -} - -model_config_type * enkf_main_get_model_config( const enkf_main_type * enkf_main ) { - return enkf_main->model_config; -} - -config_settings_type * enkf_main_get_plot_config( const enkf_main_type * enkf_main ) { - return enkf_main->plot_config; -} - -ranking_table_type * enkf_main_get_ranking_table( const enkf_main_type * enkf_main ) { - return enkf_main->ranking_table; -} - -ecl_config_type *enkf_main_get_ecl_config(const enkf_main_type * enkf_main) { - return enkf_main->ecl_config; -} - -int enkf_main_get_history_length( const enkf_main_type * enkf_main) { - return model_config_get_last_history_restart( enkf_main->model_config); -} - -bool enkf_main_has_prediction( const enkf_main_type * enkf_main ) { - return model_config_has_prediction( enkf_main->model_config ); -} - - - -enkf_obs_type * enkf_main_get_obs(const enkf_main_type * enkf_main) { - return enkf_main->obs; -} - - -bool enkf_main_have_obs( const enkf_main_type * enkf_main ) { - return enkf_obs_have_obs( enkf_main->obs ); -} - - - -hook_manager_type * enkf_main_get_hook_manager( const enkf_main_type * enkf_main ) { - return enkf_main->hook_manager; -} - - - -void enkf_main_alloc_obs( enkf_main_type * enkf_main ) { - enkf_main->obs = enkf_obs_alloc( model_config_get_history(enkf_main->model_config), - model_config_get_external_time_map(enkf_main->model_config), - ecl_config_get_grid( enkf_main->ecl_config ), - ecl_config_get_refcase( enkf_main->ecl_config ) , - enkf_main->ensemble_config ); -} - -void enkf_main_load_obs( enkf_main_type * enkf_main , const char * obs_config_file , bool clear_existing) { - if (clear_existing) - enkf_obs_clear( enkf_main->obs ); - - if (enkf_obs_load(enkf_main->obs , - obs_config_file , - analysis_config_get_std_cutoff(enkf_main->analysis_config))) { - enkf_main_update_local_updates( enkf_main ); - } else - fprintf(stderr,"** Warning: failed to load observation data from: %s \n",obs_config_file); -} - - -/** - This function should be called when a new data_file has been set. -*/ - -static void enkf_main_update_num_cpu( enkf_main_type * enkf_main ) { - /** - This is how the number of CPU's are passed on to the forward models: - */ - { - char * num_cpu_key = enkf_util_alloc_tagged_string( "NUM_CPU" ); - char * num_cpu_string = util_alloc_sprintf( "%d" , ecl_config_get_num_cpu( enkf_main->ecl_config )); - - subst_list_append_owned_ref( enkf_main->subst_list , num_cpu_key , num_cpu_string , NULL ); - free( num_cpu_key ); - } -} - - -ui_return_type * enkf_main_set_data_file( enkf_main_type * enkf_main , const char * data_file ) { - ui_return_type * ui_return = ecl_config_validate_data_file( enkf_main->ecl_config , data_file ); - if (ui_return_get_status(ui_return) == UI_RETURN_OK) { - ecl_config_set_data_file( enkf_main->ecl_config , data_file ); - enkf_main_update_num_cpu( enkf_main ); - } - return ui_return; -} - - - -static void enkf_main_free_ensemble( enkf_main_type * enkf_main ) { - if (enkf_main->ensemble != NULL) { - const int ens_size = enkf_main->ens_size; - int i; - for (i=0; i < ens_size; i++) - enkf_state_free( enkf_main->ensemble[i] ); - free(enkf_main->ensemble); - enkf_main->ensemble = NULL; - } -} - - -void enkf_main_free(enkf_main_type * enkf_main){ - if (enkf_main->rng != NULL) - rng_free( enkf_main->rng ); - rng_config_free( enkf_main->rng_config ); - - if (enkf_main->obs) - enkf_obs_free(enkf_main->obs); - - ranking_table_free( enkf_main->ranking_table ); - enkf_main_free_ensemble( enkf_main ); - enkf_main_close_fs( enkf_main ); - ert_log_close(); - - analysis_config_free(enkf_main->analysis_config); - ecl_config_free(enkf_main->ecl_config); - model_config_free( enkf_main->model_config); - - - hook_manager_free( enkf_main->hook_manager ); - site_config_free( enkf_main->site_config); - ensemble_config_free( enkf_main->ensemble_config ); - - local_config_free( enkf_main->local_config ); - - ert_workflow_list_free( enkf_main->workflow_list ); - - - int_vector_free( enkf_main->keep_runpath ); - config_settings_free( enkf_main->plot_config ); - ert_templates_free( enkf_main->templates ); - - subst_func_pool_free( enkf_main->subst_func_pool ); - subst_list_free( enkf_main->subst_list ); - util_safe_free( enkf_main->user_config_file ); - util_safe_free( enkf_main->site_config_file ); - util_safe_free( enkf_main->rft_config_file ); - free(enkf_main); -} - - - -void enkf_main_exit(enkf_main_type * enkf_main) { - enkf_main_free( enkf_main ); - exit(0); -} - - -/*****************************************************************/ - - - -/** - This function returns a (enkf_node_type ** ) pointer, which points - to all the instances with the same keyword, i.e. - - enkf_main_get_node_ensemble(enkf_main , "PRESSURE"); - - Will return an ensemble of pressure nodes. Observe that apart from - the list of pointers, *now new storage* is allocated, all the - pointers point in to the underlying enkf_node instances under the - enkf_main / enkf_state objects. Consequently there is no designated - free() function to match this, just free() the result. - - Example: - - enkf_node_type ** pressure_nodes = enkf_main_get_node_ensemble(enkf_main , "PRESSURE"); - - Do something with the pressure nodes ... - - free(pressure_nodes); - -*/ - -enkf_node_type ** enkf_main_get_node_ensemble(const enkf_main_type * enkf_main , enkf_fs_type * src_fs, const char * key , int report_step) { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - enkf_node_type ** node_ensemble = util_calloc(ens_size , sizeof * node_ensemble ); - node_id_type node_id = {.report_step = report_step , - .iens = -1 }; - int iens; - - - for (iens = 0; iens < ens_size; iens++) { - node_ensemble[iens] = enkf_state_get_node(enkf_main->ensemble[iens] , key); - node_id.iens = iens; - enkf_node_load( node_ensemble[iens] , src_fs , node_id); - } - return node_ensemble; -} - -/*****************************************************************/ - - - - -enkf_state_type * enkf_main_iget_state(const enkf_main_type * enkf_main , int iens) { - return enkf_main->ensemble[iens]; -} - - -member_config_type * enkf_main_iget_member_config(const enkf_main_type * enkf_main , int iens) { - return enkf_state_get_member_config( enkf_main->ensemble[iens] ); -} - - - -void enkf_main_node_mean( const enkf_node_type ** ensemble , int ens_size , enkf_node_type * mean ) { - int iens; - enkf_node_clear( mean ); - for (iens = 0; iens < ens_size; iens++) - enkf_node_iadd( mean , ensemble[iens] ); - - enkf_node_scale( mean , 1.0 / ens_size ); -} - - -/** - This function calculates the node standard deviation from the - ensemble. The mean can be NULL, in which case it is assumed that - the mean has already been shifted away from the ensemble. -*/ - - -void enkf_main_node_std( const enkf_node_type ** ensemble , int ens_size , const enkf_node_type * mean , enkf_node_type * std) { - int iens; - enkf_node_clear( std ); - for (iens = 0; iens < ens_size; iens++) - enkf_node_iaddsqr( std , ensemble[iens] ); - enkf_node_scale(std , 1.0 / ens_size ); - - if (mean != NULL) { - enkf_node_scale( std , -1 ); - enkf_node_iaddsqr( std , mean ); - enkf_node_scale( std , -1 ); - } - - enkf_node_sqrt( std ); -} - - -void enkf_main_inflate_node(enkf_main_type * enkf_main , enkf_fs_type * src_fs , enkf_fs_type * target_fs , int report_step , const char * key , const enkf_node_type * min_std) { - int ens_size = enkf_main_get_ensemble_size(enkf_main); - enkf_node_type ** ensemble = enkf_main_get_node_ensemble( enkf_main , src_fs , key , report_step ); // Was ANALYZED - enkf_node_type * mean = enkf_node_copyc( ensemble[0] ); - enkf_node_type * std = enkf_node_copyc( ensemble[0] ); - int iens; - - /* Shifting away the mean */ - enkf_main_node_mean( (const enkf_node_type **) ensemble , ens_size , mean ); - enkf_node_scale( mean , -1 ); - for (iens = 0; iens < ens_size; iens++) - enkf_node_iadd( ensemble[iens] , mean ); - enkf_node_scale( mean , -1 ); - - /*****************************************************************/ - /* - Now we have the ensemble represented as a mean and an ensemble of - deviations from the mean. This is the form suitable for actually - doing the inflation. - */ - { - enkf_node_type * inflation = enkf_node_copyc( ensemble[0] ); - enkf_node_set_inflation( inflation , std , min_std ); - - for (iens = 0; iens < ens_size; iens++) - enkf_node_imul( ensemble[iens] , inflation ); - - enkf_node_free( inflation ); - } - - /* Add the mean back in - and store the updated node to disk.*/ - for (iens = 0; iens < ens_size; iens++) { - node_id_type node_id = {.report_step = report_step , .iens = iens }; - enkf_node_iadd( ensemble[iens] , mean ); - enkf_node_store( ensemble[iens] , target_fs , true , node_id); - } - - enkf_node_free( mean ); - enkf_node_free( std ); - free( ensemble ); -} - - - -/** - Denne burde istedet loope gjennom noklene fra use_count - direkte. -*/ - -void enkf_main_inflate(enkf_main_type * enkf_main , enkf_fs_type * src_fs , enkf_fs_type * target_fs , int report_step , hash_type * use_count) { - stringlist_type * keys = ensemble_config_alloc_keylist_from_var_type( enkf_main->ensemble_config , PARAMETER + DYNAMIC_STATE); - - for (int ikey = 0; ikey < stringlist_get_size( keys ); ikey++) { - const char * key = stringlist_iget( keys , ikey ); - if (hash_get_counter(use_count , key) > 0) { - const enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main->ensemble_config , key ); - const enkf_node_type * min_std = enkf_config_node_get_min_std( config_node ); - - if (min_std != NULL) - enkf_main_inflate_node(enkf_main , src_fs , target_fs , report_step , key , min_std ); - - } - } - stringlist_free( keys ); -} - - - - -static int __get_active_size(const ensemble_config_type * ensemble_config , enkf_fs_type * fs , const char * key, int report_step , const active_list_type * active_list) { - const enkf_config_node_type * config_node = ensemble_config_get_node( ensemble_config , key ); - /** - This is very awkward; the problem is that for the GEN_DATA - type the config object does not really own the size. Instead - the size is pushed (on load time) from gen_data instances to - the gen_data_config instance. Therefor we have to assert - that at least one gen_data instance has been loaded (and - consequently updated the gen_data_config instance) before we - query for the size. - */ - { - if (enkf_config_node_get_impl_type( config_node ) == GEN_DATA) { - enkf_node_type * node = enkf_node_alloc( config_node ); - node_id_type node_id = {.report_step = report_step , - .iens = 0 }; - - enkf_node_load( node , fs , node_id ); - enkf_node_free( node ); - } - } - - { - active_mode_type active_mode = active_list_get_mode( active_list ); - int active_size; - if (active_mode == INACTIVE) - active_size = 0; - else if (active_mode == ALL_ACTIVE) - active_size = enkf_config_node_get_data_size( config_node , report_step ); - else if (active_mode == PARTLY_ACTIVE) - active_size = active_list_get_active_size( active_list , -1 ); - else { - util_abort("%s: internal error .. \n",__func__); - active_size = -1; /* Compiler shut up */ - } - return active_size; - } -} - - -/*****************************************************************/ -/** - Helper struct used to pass information to the multithreaded - serialize / deserialize functions. -*/ - -typedef struct { - enkf_fs_type * src_fs; - enkf_fs_type * target_fs; - enkf_state_type ** ensemble; - int iens1; /* Inclusive lower limit. */ - int iens2; /* NOT inclusive upper limit. */ - const char * key; - int report_step; - int target_step; - run_mode_type run_mode; - int row_offset; - const active_list_type * active_list; - matrix_type * A; - const int_vector_type * iens_active_index; -} serialize_info_type; - - -static void serialize_node( enkf_fs_type * fs , - enkf_state_type ** ensemble , - const char * key , - int iens , - int report_step , - int row_offset , - int column, - const active_list_type * active_list, - matrix_type * A) { - - enkf_node_type * node = enkf_state_get_node( ensemble[iens] , key); - node_id_type node_id = {.report_step = report_step, .iens = iens }; - enkf_node_serialize( node , fs , node_id , active_list , A , row_offset , column); -} - - -static void * serialize_nodes_mt( void * arg ) { - serialize_info_type * info = (serialize_info_type *) arg; - int iens; - for (iens = info->iens1; iens < info->iens2; iens++) { - int column = int_vector_iget( info->iens_active_index , iens); - if (column >= 0) - serialize_node( info->src_fs , - info->ensemble , - info->key , - iens , - info->report_step , - info->row_offset , - column, - info->active_list , - info->A ); - } - return NULL; -} - - -static void enkf_main_serialize_node( const char * node_key , - const active_list_type * active_list , - int row_offset , - thread_pool_type * work_pool , - serialize_info_type * serialize_info) { - - /* Multithreaded serializing*/ - const int num_cpu_threads = thread_pool_get_max_running( work_pool ); - int icpu; - - thread_pool_restart( work_pool ); - for (icpu = 0; icpu < num_cpu_threads; icpu++) { - serialize_info[icpu].key = node_key; - serialize_info[icpu].active_list = active_list; - serialize_info[icpu].row_offset = row_offset; - - thread_pool_add_job( work_pool , serialize_nodes_mt , &serialize_info[icpu]); - } - thread_pool_join( work_pool ); -} - - - -/** - The return value is the number of rows in the serialized - A matrix. -*/ - -static int enkf_main_serialize_dataset( const ensemble_config_type * ens_config , - const local_dataset_type * dataset , - int report_step, - hash_type * use_count , - int * active_size , - int * row_offset, - thread_pool_type * work_pool, - serialize_info_type * serialize_info) { - - matrix_type * A = serialize_info->A; - stringlist_type * update_keys = local_dataset_alloc_keys( dataset ); - const int num_kw = stringlist_get_size( update_keys ); - int ens_size = matrix_get_columns( A ); - int current_row = 0; - - for (int ikw=0; ikw < num_kw; ikw++) { - const char * key = stringlist_iget(update_keys , ikw); - enkf_config_node_type * config_node = ensemble_config_get_node( ens_config , key ); - if ((serialize_info[0].run_mode == SMOOTHER_UPDATE) && (enkf_config_node_get_var_type( config_node ) != PARAMETER)) { - /* We have tried to serialize a dynamic node when we are - smoother update mode; that does not make sense and we just - continue. */ - active_size[ikw] = 0; - continue; - } else { - const active_list_type * active_list = local_dataset_get_node_active_list( dataset , key ); - enkf_fs_type * src_fs = serialize_info->src_fs; - active_size[ikw] = __get_active_size( ens_config , src_fs , key , report_step , active_list ); - row_offset[ikw] = current_row; - - { - int matrix_rows = matrix_get_rows( A ); - if ((active_size[ikw] + current_row) > matrix_rows) - matrix_resize( A , matrix_rows + 2 * active_size[ikw] , ens_size , true ); - } - - if (active_size[ikw] > 0) { - enkf_main_serialize_node( key , active_list , row_offset[ikw] , work_pool , serialize_info ); - current_row += active_size[ikw]; - } - } - } - matrix_shrink_header( A , current_row , ens_size ); - stringlist_free( update_keys ); - return matrix_get_rows( A ); -} - -static void deserialize_node( enkf_fs_type * fs, - enkf_state_type ** ensemble , - const char * key , - int iens, - int target_step , - int row_offset , - int column, - const active_list_type * active_list, - matrix_type * A) { - - enkf_node_type * node = enkf_state_get_node( ensemble[iens] , key); - node_id_type node_id = { .report_step = target_step , .iens = iens }; - enkf_node_deserialize(node , fs , node_id , active_list , A , row_offset , column); - state_map_update_undefined(enkf_fs_get_state_map(fs) , iens , STATE_INITIALIZED); -} - - - -static void * deserialize_nodes_mt( void * arg ) { - serialize_info_type * info = (serialize_info_type *) arg; - int iens; - for (iens = info->iens1; iens < info->iens2; iens++) { - int column = int_vector_iget( info->iens_active_index , iens ); - if (column >= 0) - deserialize_node( info->target_fs , info->ensemble , info->key , iens , info->target_step , info->row_offset , column, info->active_list , info->A ); - } - return NULL; -} - - -static void enkf_main_deserialize_dataset( ensemble_config_type * ensemble_config , - const local_dataset_type * dataset , - const int * active_size , - const int * row_offset , - serialize_info_type * serialize_info , - thread_pool_type * work_pool ) { - - int num_cpu_threads = thread_pool_get_max_running( work_pool ); - stringlist_type * update_keys = local_dataset_alloc_keys( dataset ); - for (int i = 0; i < stringlist_get_size( update_keys ); i++) { - const char * key = stringlist_iget(update_keys , i); - enkf_config_node_type * config_node = ensemble_config_get_node( ensemble_config , key ); - if ((serialize_info[0].run_mode == SMOOTHER_UPDATE) && (enkf_config_node_get_var_type( config_node ) != PARAMETER)) - /* - We have tried to serialize a dynamic node when we are in - smoother update mode; that does not make sense and we just - continue. - */ - continue; - else { - if (active_size[i] > 0) { - const active_list_type * active_list = local_dataset_get_node_active_list( dataset , key ); - - { - /* Multithreaded */ - int icpu; - thread_pool_restart( work_pool ); - for (icpu = 0; icpu < num_cpu_threads; icpu++) { - serialize_info[icpu].key = key; - serialize_info[icpu].active_list = active_list; - serialize_info[icpu].row_offset = row_offset[i]; - - thread_pool_add_job( work_pool , deserialize_nodes_mt , &serialize_info[icpu]); - } - thread_pool_join( work_pool ); - } - } - } - } - stringlist_free( update_keys ); -} - - -static void serialize_info_free( serialize_info_type * serialize_info ) { - free( serialize_info ); -} - -static serialize_info_type * serialize_info_alloc( enkf_fs_type * src_fs, - enkf_fs_type * target_fs , - const int_vector_type * iens_active_index , - int target_step , - enkf_state_type ** ensemble , - run_mode_type run_mode , - int report_step , - matrix_type * A , - int num_cpu_threads ) { - - serialize_info_type * serialize_info = util_calloc( num_cpu_threads , sizeof * serialize_info ); - int ens_size = int_vector_size(iens_active_index); - int icpu; - int iens_offset = 0; - for (icpu = 0; icpu < num_cpu_threads; icpu++) { - serialize_info[icpu].iens_active_index = iens_active_index; - serialize_info[icpu].run_mode = run_mode; - serialize_info[icpu].src_fs = src_fs; - serialize_info[icpu].target_fs = target_fs; - serialize_info[icpu].target_step = target_step; - serialize_info[icpu].ensemble = ensemble; - serialize_info[icpu].report_step = report_step; - serialize_info[icpu].A = A; - serialize_info[icpu].iens1 = iens_offset; - serialize_info[icpu].iens2 = iens_offset + (ens_size - iens_offset) / (num_cpu_threads - icpu); - iens_offset = serialize_info[icpu].iens2; - } - serialize_info[num_cpu_threads - 1].iens2 = ens_size; - return serialize_info; -} - -static module_info_type * enkf_main_module_info_alloc( const local_ministep_type* ministep, - const obs_data_type * obs_data, - const local_dataset_type * dataset , - const local_obsdata_type * local_obsdata , - int * active_size , - int * row_offset) -{ - // Create and initialize the module_info instance. - module_info_type * module_info = module_info_alloc(local_ministep_get_name(ministep)); - - { /* Init data blocks in module_info */ - stringlist_type * update_keys = local_dataset_alloc_keys( dataset ); - const int num_kw = stringlist_get_size( update_keys ); - module_data_block_vector_type * module_data_block_vector = module_info_get_data_block_vector(module_info); - - for (int ikw=0; ikw < num_kw; ikw++) { - const char * key = stringlist_iget(update_keys , ikw); - const active_list_type * active_list = local_dataset_get_node_active_list( dataset , key ); - const module_data_block_type * data_block = module_data_block_alloc( key, active_list_get_active(active_list), row_offset[ikw], active_size[ikw] ); - module_data_block_vector_add_data_block(module_data_block_vector, data_block); - } - stringlist_free( update_keys ); - } - - - { /* Init obs blocks in module_info */ - module_obs_block_vector_type * module_obs_block_vector = module_info_get_obs_block_vector ( module_info ); - int current_row = 0; - for (int block_nr = 0; block_nr < local_obsdata_get_size( local_obsdata ); block_nr++) { - const obs_block_type * obs_block = obs_data_iget_block_const( obs_data , block_nr); - int total_size = obs_block_get_size(obs_block); - local_obsdata_node_type * node = local_obsdata_iget ( local_obsdata, block_nr ); - const char * key = local_obsdata_node_get_key ( node ); - const active_list_type * active_list = local_obsdata_node_get_active_list( node ); - int n_active = active_list_get_active_size(active_list, total_size); - module_obs_block_type * module_obs_block = module_obs_block_alloc(key, active_list_get_active(active_list), current_row, n_active); - module_obs_block_vector_add_obs_block ( module_obs_block_vector, module_obs_block ); - current_row += n_active; - } - } - - return module_info; -} - -static void enkf_main_module_info_free( module_info_type * module_info ) { - free( module_info ); -} - -void enkf_main_fprintf_PC(const char * filename , - matrix_type * PC , - matrix_type * PC_obs) { - - FILE * stream = util_mkdir_fopen(filename , "w"); - const int num_PC = matrix_get_rows( PC ); - const int ens_size = matrix_get_columns( PC ); - int ipc,iens; - - for (ipc = 0; ipc < num_PC; ipc++) - fprintf(stream , "%10.6f " , matrix_iget( PC_obs , ipc , 0)); - fprintf(stream , "\n"); - - for (iens = 0; iens < ens_size; iens++) { - for (ipc = 0; ipc < num_PC; ipc++) - fprintf(stream ,"%10.6f " , matrix_iget( PC , ipc, iens )); - fprintf(stream , "\n"); - } - fclose( stream ); -} - - -void enkf_main_get_PC( const matrix_type * S, - const matrix_type * dObs, - double truncation , - int ncomp , - matrix_type * PC , - matrix_type * PC_obs , - double_vector_type * singular_values) { - - enkf_linalg_get_PC( S , dObs , truncation , ncomp , PC , PC_obs , singular_values); -} - - - - - - - -static void assert_matrix_size(const matrix_type * m , const char * name , int rows , int columns) { - if (m) { - if (!matrix_check_dims(m , rows , columns)) - util_abort("%s: matrix mismatch %s:[%d,%d] - expected:[%d, %d]", __func__ , name , matrix_get_rows(m) , matrix_get_columns(m) , rows , columns); - } else - util_abort("%s: matrix:%s is NULL \n",__func__ , name); -} - -static void assert_size_equal(int ens_size , const bool_vector_type * ens_mask) { - if (bool_vector_size( ens_mask ) != ens_size) - util_abort("%s: fundamental inconsistency detected. Total ens_size:%d mask_size:%d \n",__func__ , ens_size , bool_vector_size( ens_mask )); -} - - -static void enkf_main_analysis_update( enkf_main_type * enkf_main , - enkf_fs_type * target_fs , - const bool_vector_type * ens_mask , - int target_step , - hash_type * use_count, - run_mode_type run_mode , - int step1 , - int step2 , - const local_ministep_type * ministep , - const meas_data_type * forecast , - obs_data_type * obs_data) { - - const int cpu_threads = 4; - const int matrix_start_size = 250000; - thread_pool_type * tp = thread_pool_alloc( cpu_threads , false ); - int active_ens_size = meas_data_get_active_ens_size( forecast ); - int active_size = obs_data_get_active_size( obs_data ); - matrix_type * X = matrix_alloc( active_ens_size , active_ens_size ); - matrix_type * S = meas_data_allocS( forecast ); - matrix_type * R = obs_data_allocR( obs_data ); - matrix_type * dObs = obs_data_allocdObs( obs_data ); - matrix_type * A = matrix_alloc( matrix_start_size , active_ens_size ); - matrix_type * E = NULL; - matrix_type * D = NULL; - matrix_type * localA = NULL; - int_vector_type * iens_active_index = bool_vector_alloc_active_index_list(ens_mask , -1); - - analysis_module_type * module = analysis_config_get_active_module( enkf_main->analysis_config ); - if ( local_ministep_has_analysis_module (ministep)) - module = local_ministep_get_analysis_module (ministep); - - assert_matrix_size(X , "X" , active_ens_size , active_ens_size); - assert_matrix_size(S , "S" , active_size , active_ens_size); - assert_matrix_size(R , "R" , active_size , active_size); - assert_size_equal( enkf_main_get_ensemble_size( enkf_main ) , ens_mask ); - - if (analysis_module_check_option( module , ANALYSIS_NEED_ED)) { - E = obs_data_allocE( obs_data , enkf_main->rng , active_ens_size ); - D = obs_data_allocD( obs_data , E , S ); - - assert_matrix_size( E , "E" , active_size , active_ens_size); - assert_matrix_size( D , "D" , active_size , active_ens_size); - } - - if (analysis_module_check_option( module , ANALYSIS_SCALE_DATA)) - obs_data_scale( obs_data , S , E , D , R , dObs ); - - if (analysis_module_check_option( module , ANALYSIS_USE_A) || analysis_module_check_option(module , ANALYSIS_UPDATE_A)) - localA = A; - - /*****************************************************************/ - - analysis_module_init_update( module , ens_mask , S , R , dObs , E , D ); - { - hash_iter_type * dataset_iter = local_ministep_alloc_dataset_iter( ministep ); - serialize_info_type * serialize_info = serialize_info_alloc( target_fs, //src_fs - we have already copied the parameters from the src_fs to the target_fs - target_fs , - iens_active_index, - target_step , - enkf_main_get_ensemble( enkf_main ) , - run_mode , - step2 , - A , - cpu_threads); - - - // Store PC: - if (analysis_config_get_store_PC( enkf_main->analysis_config )) { - double truncation = -1; - int ncomp = active_ens_size - 1; - matrix_type * PC = matrix_alloc(1,1); - matrix_type * PC_obs = matrix_alloc(1,1); - double_vector_type * singular_values = double_vector_alloc(0,0); - local_obsdata_type * obsdata = local_ministep_get_obsdata( ministep ); - const char * obsdata_name = local_obsdata_get_name( obsdata ); - - enkf_main_get_PC( S , dObs , truncation , ncomp , PC , PC_obs , singular_values); - { - char * filename = util_alloc_sprintf(analysis_config_get_PC_filename( enkf_main->analysis_config ) , step1 , step2 , obsdata_name); - char * full_path = util_alloc_filename( analysis_config_get_PC_path( enkf_main->analysis_config) , filename , NULL ); - - enkf_main_fprintf_PC( full_path , PC , PC_obs); - - free( full_path ); - free( filename ); - } - matrix_free( PC ); - matrix_free( PC_obs ); - double_vector_free( singular_values ); - } - - if (localA == NULL) - analysis_module_initX( module , X , NULL , S , R , dObs , E , D ); - - - while (!hash_iter_is_complete( dataset_iter )) { - const char * dataset_name = hash_iter_get_next_key( dataset_iter ); - const local_dataset_type * dataset = local_ministep_get_dataset( ministep , dataset_name ); - if (local_dataset_get_size( dataset )) { - int * active_size = util_calloc( local_dataset_get_size( dataset ) , sizeof * active_size ); - int * row_offset = util_calloc( local_dataset_get_size( dataset ) , sizeof * row_offset ); - local_obsdata_type * local_obsdata = local_ministep_get_obsdata( ministep ); - - enkf_main_serialize_dataset( enkf_main->ensemble_config , dataset , step2 , use_count , active_size , row_offset , tp , serialize_info); - module_info_type * module_info = enkf_main_module_info_alloc(ministep, obs_data, dataset, local_obsdata, active_size , row_offset); - - if (analysis_module_check_option( module , ANALYSIS_UPDATE_A)){ - if (analysis_module_check_option( module , ANALYSIS_ITERABLE)){ - analysis_module_updateA( module , localA , S , R , dObs , E , D , module_info ); - } - else - analysis_module_updateA( module , localA , S , R , dObs , E , D , module_info ); - } - else { - if (analysis_module_check_option( module , ANALYSIS_USE_A)){ - analysis_module_initX( module , X , localA , S , R , dObs , E , D ); - } - - matrix_inplace_matmul_mt2( A , X , tp ); - } - - // The deserialize also calls enkf_node_store() functions. - enkf_main_deserialize_dataset( enkf_main_get_ensemble_config( enkf_main ) , dataset , active_size , row_offset , serialize_info , tp); - - free( active_size ); - free( row_offset ); - enkf_main_module_info_free( module_info ); - } - } - hash_iter_free( dataset_iter ); - serialize_info_free( serialize_info ); - } - analysis_module_complete_update( module ); - - - /*****************************************************************/ - - int_vector_free(iens_active_index); - matrix_safe_free( E ); - matrix_safe_free( D ); - matrix_free( S ); - matrix_free( R ); - matrix_free( dObs ); - matrix_free( X ); - matrix_free( A ); -} - - - -// Opens and returns a log file. A subroutine of enkf_main_UPDATE. -static FILE * enkf_main_log_step_list(enkf_main_type * enkf_main, const int_vector_type * step_list) { - const char * log_path = analysis_config_get_log_path(enkf_main->analysis_config); - char * log_file; - if (int_vector_size(step_list) == 1) - log_file = util_alloc_sprintf("%s%c%04d", log_path, UTIL_PATH_SEP_CHAR, int_vector_iget(step_list, 0)); - else - log_file = util_alloc_sprintf("%s%c%04d-%04d", log_path, UTIL_PATH_SEP_CHAR, int_vector_iget(step_list, 0), - int_vector_get_last(step_list)); - FILE * log_stream = util_fopen(log_file, "w"); - - free(log_file); - return log_stream; -} - - -/** - * This is THE ENKF update function. It should only be called from enkf_main_UPDATE. - */ -static void enkf_main_update__(enkf_main_type * enkf_main, const int_vector_type * step_list, enkf_fs_type * source_fs, - enkf_fs_type * target_fs, int target_step, run_mode_type run_mode, - const analysis_config_type * analysis_config, const local_updatestep_type * updatestep, - const int total_ens_size) -{ - /* - Observations and measurements are collected in these temporary - structures. obs_data is a precursor for the 'd' vector, and - meas_data is a precursor for the 'S' matrix'. - - The reason for going via these temporary structures is to support - deactivating observations which should not be used in the update - process. - */ - bool_vector_type * ens_mask = bool_vector_alloc(total_ens_size, false); - state_map_type * source_state_map = enkf_fs_get_state_map( source_fs ); - - state_map_select_matching(source_state_map, ens_mask, STATE_HAS_DATA); - { - FILE * log_stream = enkf_main_log_step_list(enkf_main, step_list); - double global_std_scaling = analysis_config_get_global_std_scaling(analysis_config); - meas_data_type * meas_data = meas_data_alloc(ens_mask); - obs_data_type * obs_data = obs_data_alloc(global_std_scaling); - int_vector_type * ens_active_list = bool_vector_alloc_active_list(ens_mask); - - /* - Copy all the parameter nodes from source case to target case; - nodes which are updated will be fetched from the new target - case, and nodes which are not updated will be manually copied - over there. - */ - if (target_fs != source_fs) { - stringlist_type * param_keys = ensemble_config_alloc_keylist_from_var_type(enkf_main->ensemble_config, PARAMETER); - for (int i = 0; i < stringlist_get_size(param_keys); i++) { - const char * key = stringlist_iget(param_keys, i); - enkf_config_node_type * config_node = ensemble_config_get_node(enkf_main->ensemble_config, key); - enkf_node_type * data_node = enkf_node_alloc(config_node); - for (int j = 0; j < int_vector_size(ens_active_list); j++) { - node_id_type node_id = { .iens = int_vector_iget(ens_active_list, j), .report_step = 0 }; - enkf_node_load(data_node, source_fs, node_id); - enkf_node_store(data_node, target_fs, false, node_id); - } - enkf_node_free(data_node); - } - stringlist_free(param_keys); - } - - { - hash_type * use_count = hash_alloc(); - int current_step = int_vector_get_last(step_list); - - - /* Looping over local analysis ministep */ - for (int ministep_nr = 0; ministep_nr < local_updatestep_get_num_ministep(updatestep); ministep_nr++) { - local_ministep_type * ministep = local_updatestep_iget_ministep(updatestep, ministep_nr); - local_obsdata_type * obsdata = local_ministep_get_obsdata(ministep); - - obs_data_reset(obs_data); - meas_data_reset(meas_data); - - /* - Temporarily we will just force the timestep from the input - argument onto the obsdata instance; in the future the - obsdata should hold it's own here. - */ - local_obsdata_reset_tstep_list(obsdata, step_list); - - if (analysis_config_get_std_scale_correlated_obs(enkf_main->analysis_config)) { - double scale_factor = enkf_obs_scale_correlated_std(enkf_main->obs, source_fs, - ens_active_list, obsdata); - ert_log_add_fmt_message(1, NULL, - "Scaling standard deviation in obdsata set:%s with %g", - local_obsdata_get_name(obsdata), scale_factor); - } - enkf_obs_get_obs_and_measure_data(enkf_main->obs, source_fs, obsdata, - ens_active_list, meas_data, obs_data); - - double alpha = analysis_config_get_alpha(enkf_main->analysis_config); - double std_cutoff = analysis_config_get_std_cutoff(enkf_main->analysis_config); - enkf_analysis_deactivate_outliers(obs_data, meas_data, - std_cutoff, alpha, enkf_main->verbose); - - if (enkf_main->verbose) - enkf_analysis_fprintf_obs_summary(obs_data, meas_data, step_list, local_ministep_get_name(ministep), stdout); - enkf_analysis_fprintf_obs_summary(obs_data, meas_data, step_list, local_ministep_get_name(ministep), log_stream); - - if ((obs_data_get_active_size(obs_data) > 0) && (meas_data_get_active_obs_size(meas_data) > 0)) - enkf_main_analysis_update(enkf_main, - target_fs, - ens_mask, - target_step, - use_count, - run_mode, - int_vector_get_first(step_list), - current_step, - ministep, - meas_data, - obs_data); - else if (target_fs != source_fs) - ert_log_add_fmt_message(1, stderr, "No active observations/parameters for MINISTEP: %s.", - local_ministep_get_name(ministep)); - } - - enkf_main_inflate(enkf_main, source_fs, target_fs, current_step, use_count); - hash_free(use_count); - } - - - { - state_map_type * target_state_map = enkf_fs_get_state_map(target_fs); - - if (target_state_map != source_state_map) { - state_map_set_from_inverted_mask(target_state_map, ens_mask, STATE_PARENT_FAILURE); - state_map_set_from_mask(target_state_map, ens_mask, STATE_INITIALIZED); - enkf_fs_fsync(target_fs); - } - } - - int_vector_free(ens_active_list); - obs_data_free(obs_data); - meas_data_free(meas_data); - fclose(log_stream); - } - bool_vector_free( ens_mask); -} - - -/** - * This is T H E EnKF update routine. - */ -bool enkf_main_UPDATE(enkf_main_type * enkf_main , const int_vector_type * step_list, enkf_fs_type * source_fs , enkf_fs_type * target_fs , int target_step , run_mode_type run_mode) { - /* - If merge_observations is true all observations in the time - interval [step1+1,step2] will be used, otherwise only the last - observation at step2 will be used. - */ - - state_map_type * source_state_map = enkf_fs_get_state_map( source_fs ); - const analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main ); - const int active_ens_size = state_map_count_matching( source_state_map , STATE_HAS_DATA ); - const int total_ens_size = enkf_main_get_ensemble_size(enkf_main); - - // exit if not enough realisations - if (!analysis_config_have_enough_realisations(analysis_config , active_ens_size, total_ens_size)) { - fprintf(stderr,"** ERROR ** There are %d active realisations left, which is less than the minimum specified - stopping assimilation.\n" , - active_ens_size ); - return false; - } - - local_config_type * local_config = enkf_main->local_config; - const local_updatestep_type * updatestep = local_config_get_updatestep( local_config ); - - // exit if multi step update - if ((local_updatestep_get_num_ministep( updatestep ) > 1) && - (analysis_config_get_module_option( analysis_config , ANALYSIS_ITERABLE))) { - util_exit("** ERROR: Can not combine iterable modules with multi step updates - sorry\n"); - } - - enkf_main_update__(enkf_main, - step_list, - source_fs, - target_fs, - target_step, - run_mode, - analysis_config, - updatestep, - total_ens_size); - - return true; -} - - - - - - -static bool enkf_main_smoother_update__(enkf_main_type * enkf_main , const int_vector_type * step_list , enkf_fs_type * source_fs, enkf_fs_type * target_fs) { - return enkf_main_UPDATE( enkf_main , step_list , source_fs , target_fs , 0 , SMOOTHER_UPDATE ); -} - - -bool enkf_main_smoother_update(enkf_main_type * enkf_main , enkf_fs_type * source_fs, enkf_fs_type * target_fs) { - int stride = 1; - int step2; - time_map_type * time_map = enkf_fs_get_time_map( source_fs ); - int_vector_type * step_list; - bool update_done; - - step2 = time_map_get_last_step( time_map ); - if (step2 < 0) - step2 = model_config_get_last_history_restart( enkf_main->model_config ); - - step_list = enkf_main_update_alloc_step_list( enkf_main , 0 , step2 , stride); - update_done = enkf_main_smoother_update__( enkf_main , step_list , source_fs, target_fs ); - int_vector_free( step_list ); - - return update_done; -} - - -static void enkf_main_monitor_job_queue ( const enkf_main_type * enkf_main) { - analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main ); - if (analysis_config_get_stop_long_running(analysis_config)) { - job_queue_type * job_queue = site_config_get_job_queue(enkf_main->site_config); - - bool cont = true; - while (cont) { - //Check if minimum number of realizations have run, and if so, kill the rest after a certain time - if (analysis_config_have_enough_realisations(analysis_config, job_queue_get_num_complete(job_queue), enkf_main_get_ensemble_size(enkf_main))) { - job_queue_set_auto_job_stop_time(job_queue); - cont = false; - } - - //Check if all possible successes satisfies the minimum number of realizations threshold. If not so, it is time to give up - int possible_successes = job_queue_get_num_running(job_queue) + - job_queue_get_num_waiting(job_queue) + - job_queue_get_num_pending(job_queue) + - job_queue_get_num_complete(job_queue); - - - if (analysis_config_have_enough_realisations(analysis_config, possible_successes, enkf_main_get_ensemble_size(enkf_main))) { - cont = false; - } - - if (cont) { - util_usleep(10000); - } - } - } -} - - - -void enkf_main_isubmit_job( enkf_main_type * enkf_main , run_arg_type * run_arg ) { - const ecl_config_type * ecl_config = enkf_main_get_ecl_config( enkf_main ); - enkf_state_type * enkf_state = enkf_main->ensemble[ run_arg_get_iens(run_arg) ]; - const member_config_type * member_config = enkf_state_get_member_config( enkf_state ); - const site_config_type * site_config = enkf_main_get_site_config( enkf_main ); - const char * job_script = site_config_get_job_script( site_config ); - job_queue_type * job_queue = site_config_get_job_queue( site_config ); - const char * run_path = run_arg_get_runpath( run_arg ); - - // The job_queue_node will take ownership of this arg_pack; and destroy it when - // the job_queue_node is discarded. - arg_pack_type * callback_arg = arg_pack_alloc(); - - /* - Prepare the job and submit it to the queue - */ - arg_pack_append_ptr( callback_arg , enkf_state ); - arg_pack_append_ptr( callback_arg , run_arg ); - - { - int queue_index = job_queue_add_job( job_queue , - job_script , - enkf_state_complete_forward_modelOK__ , - enkf_state_complete_forward_modelRETRY__ , - enkf_state_complete_forward_modelEXIT__, - callback_arg , - ecl_config_get_num_cpu( ecl_config ), - run_path , - member_config_get_jobname( member_config ) , - 1, - (const char *[1]) { run_path } ); - - run_arg_set_queue_index( run_arg , queue_index ); - run_arg_increase_submit_count( run_arg ); - } - -} - -void * enkf_main_icreate_run_path( enkf_main_type * enkf_main, run_arg_type * run_arg){ - enkf_state_type * enkf_state = enkf_main->ensemble[ run_arg_get_iens(run_arg) ]; - { - runpath_list_type * runpath_list = hook_manager_get_runpath_list( enkf_main->hook_manager ); - runpath_list_add( runpath_list , - run_arg_get_iens( run_arg ), - run_arg_get_iter( run_arg ), - run_arg_get_runpath( run_arg ), - enkf_state_get_eclbase( enkf_state )); - } - enkf_state_init_eclipse( enkf_state , run_arg ); - return NULL; -} - - -static void * enkf_main_create_run_path__( enkf_main_type * enkf_main, - const ert_init_context_type * init_context) { - - const bool_vector_type * iactive = ert_init_context_get_iactive(init_context); - const int active_ens_size = util_int_min( bool_vector_size( iactive ) , enkf_main_get_ensemble_size( enkf_main )); - int iens; - for (iens = 0; iens < active_ens_size; iens++) { - if (bool_vector_iget(iactive , iens)) { - run_arg_type * run_arg = ert_init_context_iens_get_arg( init_context , iens); - enkf_main_icreate_run_path(enkf_main, run_arg); - } - } - return NULL; -} - -void enkf_main_create_run_path(enkf_main_type * enkf_main , const bool_vector_type * iactive , int iter) { - init_mode_type init_mode = INIT_CONDITIONAL; - - enkf_main_init_internalization(enkf_main , init_mode); - { - stringlist_type * param_list = ensemble_config_alloc_keylist_from_var_type( enkf_main->ensemble_config , PARAMETER ); - enkf_main_initialize_from_scratch(enkf_main , - enkf_main_get_fs( enkf_main ), - param_list , - iactive, - init_mode); - stringlist_free( param_list ); - } - - - { - ert_init_context_type * init_context = enkf_main_alloc_ert_init_context( enkf_main , - enkf_main_get_fs( enkf_main ), - iactive , - init_mode , - iter ); - enkf_main_create_run_path__( enkf_main , init_context ); - ert_init_context_free( init_context ); - } - - - /* - The runpath_list is written to disk here, when all the simulation - folders have been created and filled with content. The - runpath_list instance is owned and managed by the hook manager; - could say that the responsability for writing that data should be - with the hook_manager? - */ - - { - runpath_list_type * runpath_list = hook_manager_get_runpath_list(enkf_main->hook_manager ); - runpath_list_fprintf( runpath_list ); - } -} - - - -void * enkf_main_isubmit_job__( void * arg ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - enkf_main_type * enkf_main = enkf_main_safe_cast( arg_pack_iget_ptr( arg_pack , 0 )); - run_arg_type * run_arg = run_arg_safe_cast( arg_pack_iget_ptr( arg_pack , 1)); - - enkf_main_isubmit_job( enkf_main , run_arg ); - return NULL; -} - - - - - -static void enkf_main_submit_jobs__( enkf_main_type * enkf_main , - const ert_run_context_type * run_context , - thread_pool_type * submit_threads, - arg_pack_type ** arg_pack_list) { - { - int iens; - const bool_vector_type * iactive = ert_run_context_get_iactive( run_context ); - const int active_ens_size = util_int_min( bool_vector_size( iactive ) , enkf_main_get_ensemble_size( enkf_main )); - - for (iens = 0; iens < active_ens_size; iens++) { - if (bool_vector_iget(iactive , iens)) { - run_arg_type * run_arg = ert_run_context_iens_get_arg( run_context , iens); - arg_pack_type * arg_pack = arg_pack_list[iens]; - - arg_pack_append_ptr( arg_pack , enkf_main ); - arg_pack_append_ptr( arg_pack , run_arg); - - run_arg_set_run_status( run_arg, JOB_SUBMITTED ); - thread_pool_add_job(submit_threads , enkf_main_isubmit_job__ , arg_pack); - } - } - } -} - - -void enkf_main_submit_jobs( enkf_main_type * enkf_main , - const ert_run_context_type * run_context) { - - int ens_size = enkf_main_get_ensemble_size( enkf_main ); - arg_pack_type ** arg_pack_list = util_malloc( ens_size * sizeof * arg_pack_list ); - thread_pool_type * submit_threads = thread_pool_alloc( 4 , true ); - runpath_list_type * runpath_list = hook_manager_get_runpath_list( enkf_main->hook_manager ); - int iens; - for (iens = 0; iens < ens_size; iens++) - arg_pack_list[iens] = arg_pack_alloc( ); - - runpath_list_clear( runpath_list ); - enkf_main_submit_jobs__(enkf_main , run_context , submit_threads , arg_pack_list); - - /* - After this join all directories/files for the simulations - have been set up correctly, and all the jobs have been added - to the job_queue manager. - */ - - thread_pool_join(submit_threads); - thread_pool_free(submit_threads); - - for (iens = 0; iens < ens_size; iens++) - arg_pack_free( arg_pack_list[iens] ); - free( arg_pack_list ); -} - - - -/** - The function will return number of non-failing jobs. -*/ - - -static int enkf_main_run_step(enkf_main_type * enkf_main , - ert_run_context_type * run_context) { - - if (ert_run_context_get_step1(run_context)) - ecl_config_assert_restart( enkf_main_get_ecl_config( enkf_main ) ); - - { - int job_size , iens; - bool verbose_queue = enkf_main->verbose; - const int active_ens_size = util_int_min( bool_vector_size( ert_run_context_get_iactive( run_context )) , enkf_main_get_ensemble_size( enkf_main )); - - state_map_deselect_matching( enkf_fs_get_state_map( ert_run_context_get_init_fs( run_context )) , - ert_run_context_get_iactive( run_context ), STATE_LOAD_FAILURE | STATE_PARENT_FAILURE); - - ert_log_add_fmt_message( 1 , NULL , "===================================================================", false); - - job_size = bool_vector_count_equal( ert_run_context_get_iactive(run_context) , true ); - { - job_queue_type * job_queue = site_config_get_job_queue(enkf_main->site_config); - job_queue_manager_type * queue_manager = job_queue_manager_alloc( job_queue ); - bool restart_queue = true; - - /* Start the queue */ - if (site_config_has_job_script( enkf_main->site_config )) - job_queue_manager_start_queue( queue_manager , job_size , verbose_queue , restart_queue); - else - util_exit("No job script specified, can not start any jobs. Use the key JOB_SCRIPT in the config file\n"); - - - enkf_main_submit_jobs( enkf_main , run_context ); - - - job_queue_submit_complete( job_queue ); - ert_log_add_message( 1 , NULL , "All jobs submitted to internal queue - waiting for completion" , false); - - int max_runtime = analysis_config_get_max_runtime(enkf_main_get_analysis_config( enkf_main )); - job_queue_set_max_job_duration(job_queue, max_runtime); - enkf_main_monitor_job_queue( enkf_main ); - - job_queue_manager_wait( queue_manager ); - job_queue_manager_free( queue_manager ); - } - - - /* This should be carefully checked for the situation where only a - subset (with offset > 0) of realisations are simulated. */ - - int totalOK = 0; - int totalFailed = 0; - for (iens = 0; iens < active_ens_size; iens++) { - if (bool_vector_iget(ert_run_context_get_iactive(run_context) , iens)) { - run_arg_type * run_arg = ert_run_context_iens_get_arg( run_context , iens ); - run_status_type run_status = run_arg_get_run_status( run_arg ); - - if ((run_status == JOB_LOAD_FAILURE) || (run_status == JOB_RUN_FAILURE)) { - ert_run_context_deactivate_realization(run_context, iens); - totalFailed++; - } - else { - totalOK++; - } - } - } - - enkf_fs_fsync( ert_run_context_get_result_fs( run_context ) ); - if (totalFailed == 0) - ert_log_add_fmt_message( 1 , NULL , "All jobs complete and data loaded."); - - - return totalOK; - } -} - -/** - The special value stride == 0 means to just include step2. -*/ -int_vector_type * enkf_main_update_alloc_step_list( const enkf_main_type * enkf_main , int load_start , int step2 , int stride) { - int_vector_type * step_list = int_vector_alloc( 0 , 0 ); - - if (step2 < load_start) - util_abort("%s: fatal internal error: Tried to make step list %d ... %d \n",__func__ , load_start , step2); - - if (stride == 0) - int_vector_append( step_list , step2 ); - else { - int step = util_int_max( 1 , load_start ); - while (true) { - int_vector_append( step_list , step ); - - if (step == step2) - break; - else { - step += stride; - if (step >= step2) { - int_vector_append( step_list , step2 ); - break; - } - } - - } - } - return step_list; -} - - - - -void * enkf_main_get_enkf_config_node_type(const ensemble_config_type * ensemble_config, const char * key){ - enkf_config_node_type * config_node_type = ensemble_config_get_node(ensemble_config, key); - return enkf_config_node_get_ref(config_node_type); -} - - -/** - This function will initialize the necessary enkf_main structures - before a run. Currently this means: - - 1. Set the enkf_sched instance - either by loading from file or - by using the default. - - 2. Set up the configuration of what should be internalized. - -*/ - - -void enkf_main_init_run( enkf_main_type * enkf_main, const ert_run_context_type * run_context, init_mode_type init_mode) { - enkf_main_init_internalization(enkf_main , ert_run_context_get_mode( run_context )); - { - stringlist_type * param_list = ensemble_config_alloc_keylist_from_var_type( enkf_main->ensemble_config , PARAMETER ); - enkf_main_initialize_from_scratch(enkf_main , - ert_run_context_get_init_fs( run_context ), - param_list , - ert_run_context_get_iactive( run_context ), - init_mode); - stringlist_free( param_list ); - } -} - - - - -void enkf_main_run_tui_exp(enkf_main_type * enkf_main , - bool_vector_type * iactive) { - - int active_before = bool_vector_count_equal(iactive, true); - hook_manager_type * hook_manager = enkf_main_get_hook_manager(enkf_main); - ert_run_context_type * run_context; - init_mode_type init_mode = INIT_CONDITIONAL; - int iter = 0; - - run_context = enkf_main_alloc_ert_run_context_ENSEMBLE_EXPERIMENT(enkf_main , - enkf_main_get_fs( enkf_main ) , - iactive , - iter ); - enkf_main_init_run( enkf_main , run_context , init_mode); - enkf_main_create_run_path( enkf_main , iactive , iter ); - hook_manager_run_workflows(hook_manager, PRE_SIMULATION, enkf_main); - enkf_main_run_step(enkf_main , run_context); - - int active_after = bool_vector_count_equal(iactive, true); - if (active_after == active_before) - hook_manager_run_workflows(hook_manager, POST_SIMULATION, enkf_main); - - ert_run_context_free( run_context ); -} - - - - -int enkf_main_run_simple_step(enkf_main_type * enkf_main , bool_vector_type * iactive , init_mode_type init_mode, int iter) { - ert_run_context_type * run_context = enkf_main_alloc_ert_run_context_ENSEMBLE_EXPERIMENT( enkf_main , - enkf_main_get_fs( enkf_main ) , - iactive , - iter ); - enkf_main_init_run( enkf_main , run_context , init_mode); - int successful_realizations = enkf_main_run_step( enkf_main , run_context ); - ert_run_context_free( run_context ); - - return successful_realizations; -} - - - -void enkf_main_run_smoother(enkf_main_type * enkf_main , enkf_fs_type * source_fs, const char * target_fs_name , bool_vector_type * iactive , int iter , bool rerun) { - analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main ); - if (!analysis_config_get_module_option( analysis_config , ANALYSIS_ITERABLE)) { - if (enkf_main_run_simple_step( enkf_main , iactive , INIT_CONDITIONAL, iter)) { - hook_manager_type * hook_manager = enkf_main_get_hook_manager(enkf_main); - hook_manager_run_workflows(hook_manager, POST_SIMULATION, enkf_main); - } - - { - enkf_fs_type * target_fs = enkf_main_mount_alt_fs( enkf_main , target_fs_name , true ); - bool update_done = enkf_main_smoother_update( enkf_main , source_fs , target_fs ); - - if (rerun) { - if (update_done) { - enkf_main_set_fs( enkf_main , target_fs , target_fs_name); - if (enkf_main_run_simple_step(enkf_main , iactive , INIT_NONE, iter + 1)) { - hook_manager_type * hook_manager = enkf_main_get_hook_manager(enkf_main); - hook_manager_run_workflows(hook_manager, POST_SIMULATION, enkf_main); - } - } else - fprintf(stderr,"** Warning: the analysis update failed - no rerun started.\n"); - } - enkf_fs_decref( target_fs ); - - } - } else - fprintf(stderr,"** ERROR: The normal smoother should not be combined with an iterable analysis module\n"); -} - - -static bool enkf_main_run_simulation_and_postworkflow(enkf_main_type * enkf_main, ert_run_context_type * run_context) { - bool ret = true; - analysis_config_type * analysis_config = enkf_main_get_analysis_config(enkf_main); - - int active_after_step = enkf_main_run_step(enkf_main , run_context); - if (analysis_config_have_enough_realisations(analysis_config, active_after_step, enkf_main_get_ensemble_size(enkf_main))) { - hook_manager_type * hook_manager = enkf_main_get_hook_manager(enkf_main); - hook_manager_run_workflows(hook_manager, POST_SIMULATION, enkf_main); - } else { - fprintf(stderr,"Simulation in iteration %d failed, stopping Iterated Ensemble Smoother\n", ert_run_context_get_iter( run_context )); - ret = false; - } - - return ret; -} - - -static bool enkf_main_run_analysis(enkf_main_type * enkf_main, enkf_fs_type * source_fs ,const char * target_fs_name, int iteration_number) { - bool updateOK = false; - analysis_config_type * analysis_config = enkf_main_get_analysis_config(enkf_main); - analysis_module_type * analysis_module = analysis_config_get_active_module(analysis_config); - int pre_iteration_number = analysis_module_get_int(analysis_module, "ITER"); - - if (target_fs_name == NULL){ - fprintf(stderr,"Sorry: the updated ensemble will overwrite the current case in the iterated ensemble smoother."); - printf("Running analysis on case %s, target case is %s\n", enkf_main_get_current_fs(enkf_main), enkf_main_get_current_fs(enkf_main)); - updateOK = enkf_main_smoother_update(enkf_main, source_fs, enkf_main_get_fs(enkf_main)); - } else { - enkf_fs_type * target_fs = enkf_main_mount_alt_fs(enkf_main , target_fs_name , true ); - updateOK = enkf_main_smoother_update(enkf_main, source_fs , target_fs); - enkf_fs_decref( target_fs ); - } - - int post_iteration_number = analysis_module_get_int(analysis_module, "ITER"); - - if (post_iteration_number <= pre_iteration_number) - updateOK = false; - - if (updateOK) { - enkf_fs_type * target_fs = enkf_main_mount_alt_fs(enkf_main , target_fs_name , true ); - cases_config_set_int(enkf_fs_get_cases_config(target_fs), "iteration_number", iteration_number+1); - enkf_fs_decref( target_fs ); - } - - return updateOK; -} - - -void enkf_main_run_iterated_ES(enkf_main_type * enkf_main, int num_iterations_to_run) { - const analysis_config_type * analysis_config = enkf_main_get_analysis_config(enkf_main); - - if (analysis_config_get_module_option( analysis_config , ANALYSIS_ITERABLE)) { - const int ens_size = enkf_main_get_ensemble_size(enkf_main); - bool_vector_type * iactive = bool_vector_alloc(ens_size , true); - enkf_fs_type * current_case = enkf_main_get_fs( enkf_main ); - analysis_iter_config_type * iter_config = analysis_config_get_iter_config(analysis_config); - int current_iteration = 0; - const char * initial_case_name = analysis_iter_config_iget_case( iter_config , current_iteration ); - - if (!util_string_equal( initial_case_name , enkf_fs_get_case_name( current_case ))) { - enkf_fs_type * initial_case = enkf_main_mount_alt_fs( enkf_main , initial_case_name , true); - enkf_main_init_case_from_existing(enkf_main, current_case, 0, initial_case); // ANALYZED argument removed. - enkf_main_set_fs( enkf_main , initial_case , NULL ); - enkf_fs_decref( initial_case ); - } - - { //Iteration 0 - ert_run_context_type * run_context = NULL; - enkf_main_init_run(enkf_main , run_context , INIT_CONDITIONAL ); - enkf_main_run_simulation_and_postworkflow(enkf_main, run_context); - ert_run_context_free( run_context ); - } - - { // Iteration 1 - num_iterations [iteration 1, num iterations] - int num_retries_per_iteration = analysis_iter_config_get_num_retries_per_iteration(iter_config); - int num_tries = 0; - enkf_fs_type * source_fs = enkf_main_get_fs( enkf_main ); - current_iteration = 1; - - while ((current_iteration <= num_iterations_to_run) && (num_tries < num_retries_per_iteration)) { - ert_run_context_type * run_context = NULL; - - const char * target_fs_name = analysis_iter_config_iget_case( iter_config , current_iteration ); - - if (enkf_main_run_analysis(enkf_main, source_fs, target_fs_name, current_iteration)) { - enkf_main_select_fs(enkf_main, target_fs_name); - if (!enkf_main_run_simulation_and_postworkflow(enkf_main, run_context )) - break; - num_tries = 0; - ++current_iteration; - } else { - fprintf(stderr, "\nAnalysis failed, rerunning simulation on changed initial parameters\n"); - enkf_fs_type * target_fs = enkf_main_mount_alt_fs( enkf_main , target_fs_name , false ); - enkf_main_init_current_case_from_existing(enkf_main, target_fs, 0); // ANALYZED argument removed - enkf_fs_decref(target_fs); - ++num_tries; - - if (!enkf_main_run_simulation_and_postworkflow(enkf_main, run_context )) - //if (!enkf_main_run_simulation_and_postworkflow(enkf_main, current_iteration-1, iactive)) - break; - } - - ert_run_context_free( run_context ); - } - } - - bool_vector_free(iactive); - } else - fprintf(stderr,"** ERROR: The current analysis module:%s can not be used for iterations \n", analysis_config_get_active_module_name( analysis_config )); -} - - -ert_run_context_type * enkf_main_alloc_ert_run_context_ENSEMBLE_EXPERIMENT(const enkf_main_type * enkf_main , enkf_fs_type * fs , bool_vector_type * iactive , int iter) { - return ert_run_context_alloc_ENSEMBLE_EXPERIMENT( fs , iactive , model_config_get_runpath_fmt( enkf_main->model_config ) , enkf_main->subst_list , iter ); -} - -ert_init_context_type * enkf_main_alloc_ert_init_context(const enkf_main_type * enkf_main , enkf_fs_type * fs, const bool_vector_type * iactive , init_mode_type init_mode , int iter) { - return ert_init_context_alloc( fs, iactive , model_config_get_runpath_fmt( enkf_main->model_config ) , enkf_main->subst_list , init_mode , iter ); -} - - - - -/** - This function creates a local_config file corresponding to the - default 'ALL_ACTIVE' configuration. We eat our own dogshit around - here... -*/ - -void enkf_main_create_all_active_config( const enkf_main_type * enkf_main) { - - - bool single_node_update = analysis_config_get_single_node_update( enkf_main->analysis_config ); - local_config_type * local_config = enkf_main->local_config; - local_config_clear( local_config ); - { - local_updatestep_type * default_step = local_config_get_updatestep(local_config); - local_ministep_type * ministep = local_config_alloc_ministep( local_config , "ALL_ACTIVE", NULL); - local_obsdata_type * obsdata = local_config_alloc_obsdata(local_config, "ALL_OBS"); - local_dataset_type * all_active_dataset = local_config_alloc_dataset(local_config, "ALL_DATA"); - - local_updatestep_add_ministep( default_step , ministep ); - - /* Adding all observation keys */ - { - hash_iter_type * obs_iter = enkf_obs_alloc_iter( enkf_main->obs ); - while ( !hash_iter_is_complete(obs_iter) ) { - const char * obs_key = hash_iter_get_next_key( obs_iter ); - local_obsdata_node_type * obsdata_node = local_obsdata_node_alloc( obs_key , true ); - local_obsdata_add_node(obsdata, obsdata_node ); - } - local_ministep_add_obsdata(ministep, obsdata); - hash_iter_free( obs_iter ); - } - - /* Adding all node which can be updated. */ - { - stringlist_type * keylist = ensemble_config_alloc_keylist_from_var_type( enkf_main->ensemble_config , PARAMETER); - int i; - for (i = 0; i < stringlist_get_size( keylist ); i++) { - const char * key = stringlist_iget( keylist , i); - bool add_node = true; - - /* - Make sure the funny GEN_KW instance masquerading as - SCHEDULE_PREDICTION_FILE is not added to the soup. - */ - if (util_string_equal(key , "PRED")) - add_node = false; - - - if (add_node) { - if (single_node_update) { - local_dataset_type * this_dataset = local_config_alloc_dataset(local_config, key); - local_dataset_add_node(this_dataset, key); - local_ministep_add_dataset(ministep, this_dataset); - } - local_dataset_add_node(all_active_dataset, key); - } - } - stringlist_free( keylist); - } - if (!single_node_update) - local_ministep_add_dataset(ministep, all_active_dataset); - - } -} - - -static void enkf_main_user_config_deprecate( config_parser_type * config ) -{ - config_parser_deprecate( config , "MAX_RUNNING_LSF" , "MAX_RUNNING_LSF is deprecated. Use the general QUEUE_OPTION LSF MAX_RUNNING instead."); - config_parser_deprecate( config , "MAX_RUNNING_LOCAL" , "MAX_RUNNING_LOCAL is deprecated. Use the general QUEUE_OPTION LOCAL MAX_RUNNING instead."); - config_parser_deprecate( config , "MAX_RUNNING_RSH" , "MAX_RUNNING_RSH is deprecated. Use the general QUEUE_OPTION RSH MAX_RUNNING instead."); -} - - -static void enkf_main_init_user_config( const enkf_main_type * enkf_main , config_parser_type * config ) { - config_schema_item_type * item; - - /*****************************************************************/ - /* config_add_schema_item(): */ - /* */ - /* 1. boolean - required? */ - /*****************************************************************/ - - ert_workflow_list_add_config_items( config ); - plot_settings_add_config_items( config ); - analysis_config_add_config_items( config ); - ensemble_config_add_config_items( config ); - ecl_config_add_config_items( config ); - rng_config_add_config_items( config ); - - /*****************************************************************/ - /* Required keywords from the ordinary model_config file */ - - item = config_add_schema_item(config , CASE_TABLE_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1); - config_schema_item_iset_type( item , 0 , CONFIG_EXISTING_PATH ); - - config_add_key_value( config , LOG_LEVEL_KEY , false , CONFIG_INT); - config_add_key_value( config , LOG_FILE_KEY , false , CONFIG_STRING); - - config_add_key_value(config , MAX_RESAMPLE_KEY , false , CONFIG_INT); - - - item = config_add_schema_item(config , NUM_REALIZATIONS_KEY , true ); - config_schema_item_set_argc_minmax(item , 1 , 1); - config_schema_item_iset_type( item , 0 , CONFIG_INT ); - config_add_alias(config , NUM_REALIZATIONS_KEY , "SIZE"); - config_add_alias(config , NUM_REALIZATIONS_KEY , "NUM_REALISATIONS"); - config_install_message(config , "SIZE" , "** Warning: \'SIZE\' is depreceated - use \'NUM_REALIZATIONS\' instead."); - - - /*****************************************************************/ - /* Optional keywords from the model config file */ - - item = config_add_schema_item( config , RUN_TEMPLATE_KEY , false ); - config_schema_item_set_argc_minmax(item , 2 , CONFIG_DEFAULT_ARG_MAX ); - config_schema_item_iset_type( item , 0 , CONFIG_EXISTING_PATH ); - - config_add_key_value(config , RUNPATH_KEY , false , CONFIG_STRING); - - item = config_add_schema_item(config , ENSPATH_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - - item = config_add_schema_item( config , JOBNAME_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - - item = config_add_schema_item(config , DBASE_TYPE_KEY , false ); - config_schema_item_set_argc_minmax(item , 1, 1 ); - config_schema_item_set_common_selection_set(item , 2 , (const char *[2]) {"PLAIN" , "BLOCK_FS"}); - - item = config_add_schema_item(config , FORWARD_MODEL_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , CONFIG_DEFAULT_ARG_MAX); - - item = config_add_schema_item(config , DATA_KW_KEY , false ); - config_schema_item_set_argc_minmax(item , 2 , 2); - - config_add_key_value(config , PRE_CLEAR_RUNPATH_KEY , false , CONFIG_BOOL); - - item = config_add_schema_item(config , DELETE_RUNPATH_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , CONFIG_DEFAULT_ARG_MAX); - - item = config_add_schema_item(config , OBS_CONFIG_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , CONFIG_EXISTING_PATH ); - - config_add_key_value(config , TIME_MAP_KEY , false , CONFIG_EXISTING_PATH); - - item = config_add_schema_item(config , RFT_CONFIG_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , CONFIG_EXISTING_PATH ); - - item = config_add_schema_item(config , RFTPATH_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - - item = config_add_schema_item(config, GEN_KW_EXPORT_FILE_KEY, false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - - item = config_add_schema_item(config , LOCAL_CONFIG_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , CONFIG_EXISTING_PATH ); - - { - stringlist_type * refcase_dep = stringlist_alloc_argv_ref( (const char *[1]) { REFCASE_KEY } , 1); - - item = config_add_schema_item(config , HISTORY_SOURCE_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1); - config_schema_item_set_common_selection_set(item , 3 , (const char *[3]) {"SCHEDULE" , "REFCASE_SIMULATED" , "REFCASE_HISTORY"}); - config_schema_item_set_required_children_on_value(item , "REFCASE_SIMULATED" , refcase_dep); - config_schema_item_set_required_children_on_value(item , "REFCASE_HISTORY" , refcase_dep); - - stringlist_free(refcase_dep); - } - - hook_manager_add_config_items( config ); -} - - -keep_runpath_type enkf_main_iget_keep_runpath( const enkf_main_type * enkf_main , int iens ) { - return enkf_state_get_keep_runpath( enkf_main->ensemble[iens] ); -} - -void enkf_main_iset_keep_runpath( enkf_main_type * enkf_main , int iens , keep_runpath_type keep_runpath) { - enkf_state_set_keep_runpath( enkf_main->ensemble[iens] , keep_runpath); -} - -void enkf_main_set_verbose( enkf_main_type * enkf_main , bool verbose) { - enkf_main->verbose = verbose; -} - - -bool enkf_main_get_verbose( const enkf_main_type * enkf_main ) { - return enkf_main->verbose; -} - -/** - Observe that this function parses and TEMPORARILY stores the keep_runpath - information ion the enkf_main object. This is subsequently passed on the - enkf_state members, and the functions enkf_main_iget_keep_runpath() and - enkf_main_iset_keep_runpath() act on the enkf_state objects, and not on the - internal keep_runpath field of the enkf_main object (what a fxxxing mess). -*/ - - -void enkf_main_parse_keep_runpath(enkf_main_type * enkf_main , const char * delete_runpath_string , int ens_size ) { - - int i; - for (i = 0; i < ens_size; i++) - int_vector_iset( enkf_main->keep_runpath , i , DEFAULT_KEEP); - - { - int_vector_type * active_list = string_util_alloc_active_list(delete_runpath_string); - - for (i = 0; i < int_vector_size( active_list ); i++) - int_vector_iset( enkf_main->keep_runpath , int_vector_iget( active_list , i ) , EXPLICIT_DELETE); - - int_vector_free( active_list ); - } -} - - - -/** - There is NO tagging anymore - if the user wants tags - the user - supplies the key __WITH__ tags. -*/ -void enkf_main_add_data_kw(enkf_main_type * enkf_main , const char * key , const char * value) { - subst_list_append_copy( enkf_main->subst_list , key , value , "Supplied by the user in the configuration file."); -} - - -void enkf_main_data_kw_fprintf_config( const enkf_main_type * enkf_main , FILE * stream ) { - for (int i = 0; i < subst_list_get_size( enkf_main->subst_list ); i++) { - fprintf(stream , CONFIG_KEY_FORMAT , DATA_KW_KEY ); - fprintf(stream , CONFIG_VALUE_FORMAT , subst_list_iget_key( enkf_main->subst_list , i )); - fprintf(stream , CONFIG_ENDVALUE_FORMAT , subst_list_iget_value( enkf_main->subst_list , i )); - } -} - - -void enkf_main_clear_data_kw( enkf_main_type * enkf_main ) { - subst_list_clear( enkf_main->subst_list ); -} - -static void enkf_main_add_subst_kw( enkf_main_type * enkf_main , const char * key , const char * value, const char * help_text , bool insert_copy) { - char * tagged_key = util_alloc_sprintf( INTERNAL_DATA_KW_TAG_FORMAT , key ); - - if (insert_copy) - subst_list_append_owned_ref( enkf_main->subst_list , tagged_key , util_alloc_string_copy( value ), help_text); - else - subst_list_append_ref( enkf_main->subst_list , tagged_key , value , help_text); - - free(tagged_key); -} - - -static void enkf_main_init_hook_manager( enkf_main_type * enkf_main , config_content_type * config ) { - hook_manager_init( enkf_main->hook_manager , config ); -} - -static void enkf_main_init_subst_list( enkf_main_type * enkf_main ) { - /* Here we add the functions which should be available for string substitution operations. */ - subst_func_pool_add_func( enkf_main->subst_func_pool , "EXP" , "exp" , subst_func_exp , false , 1 , 1 , NULL); - subst_func_pool_add_func( enkf_main->subst_func_pool , "LOG" , "log" , subst_func_log , false , 1 , 1 , NULL); - subst_func_pool_add_func( enkf_main->subst_func_pool , "POW10" , "Calculates 10^x" , subst_func_pow10 , false , 1 , 1 , NULL); - subst_func_pool_add_func( enkf_main->subst_func_pool , "ADD" , "Adds arguments" , subst_func_add , true , 1 , 0 , NULL); - subst_func_pool_add_func( enkf_main->subst_func_pool , "MUL" , "Multiplies arguments" , subst_func_mul , true , 1 , 0 , NULL); - subst_func_pool_add_func( enkf_main->subst_func_pool , "RANDINT" , "Returns a random integer - 32 bit" , subst_func_randint , false , 0 , 0 , enkf_main->rng); - subst_func_pool_add_func( enkf_main->subst_func_pool , "RANDFLOAT" , "Returns a random float 0-1." , subst_func_randfloat , false , 0 , 0 , enkf_main->rng); - - /** - Allocating the parent subst_list instance. This will (should ...) - be the top level subst instance for all substitions in the ert - program. - - All the functions available or only installed in this - subst_list. - - The key->value replacements installed in this instance are - key,value pairs which are: - - o Common to all ensemble members. - - o Constant in time. - */ - - - /* Installing the functions. */ - subst_list_insert_func( enkf_main->subst_list , "EXP" , "__EXP__"); - subst_list_insert_func( enkf_main->subst_list , "LOG" , "__LOG__"); - subst_list_insert_func( enkf_main->subst_list , "POW10" , "__POW10__"); - subst_list_insert_func( enkf_main->subst_list , "ADD" , "__ADD__"); - subst_list_insert_func( enkf_main->subst_list , "MUL" , "__MUL__"); - subst_list_insert_func( enkf_main->subst_list , "RANDINT" , "__RANDINT__"); - subst_list_insert_func( enkf_main->subst_list , "RANDFLOAT" , "__RANDFLOAT__"); -} - - - -enkf_main_type * enkf_main_alloc_empty( ) { - enkf_main_type * enkf_main = util_malloc(sizeof * enkf_main); - UTIL_TYPE_ID_INIT(enkf_main , ENKF_MAIN_ID); - ert_log_open_empty(); - enkf_main->ensemble = NULL; - enkf_main->user_config_file = NULL; - enkf_main->site_config_file = NULL; - enkf_main->rft_config_file = NULL; - enkf_main->local_config = NULL; - enkf_main->rng = NULL; - enkf_main->ens_size = 0; - enkf_main->keep_runpath = int_vector_alloc( 0 , DEFAULT_KEEP ); - enkf_main->rng_config = rng_config_alloc( ); - enkf_main->site_config = site_config_alloc_empty(); - enkf_main->ensemble_config = ensemble_config_alloc(); - enkf_main->ecl_config = ecl_config_alloc(); - enkf_main->ranking_table = ranking_table_alloc( 0 ); - enkf_main->obs = NULL; - enkf_main->model_config = model_config_alloc( ); - enkf_main->local_config = local_config_alloc( ); - - enkf_main->plot_config = config_settings_alloc( PLOT_SETTING_KEY ); - plot_settings_init( enkf_main->plot_config ); - - enkf_main_rng_init( enkf_main ); - enkf_main->subst_func_pool = subst_func_pool_alloc( ); - enkf_main->subst_list = subst_list_alloc( enkf_main->subst_func_pool ); - enkf_main->templates = ert_templates_alloc( enkf_main->subst_list ); - enkf_main->workflow_list = ert_workflow_list_alloc( enkf_main->subst_list ); - enkf_main->hook_manager = hook_manager_alloc( enkf_main->workflow_list ); - enkf_main->analysis_config = analysis_config_alloc( enkf_main->rng ); - - enkf_main_init_subst_list( enkf_main ); - enkf_main_set_verbose( enkf_main , true ); - enkf_main_init_fs( enkf_main ); - return enkf_main; -} - - - - - -static void enkf_main_install_data_kw( enkf_main_type * enkf_main , hash_type * config_data_kw) { - /* - Installing the DATA_KW keywords supplied by the user - these are - at the very top level, so they can reuse everything defined later. - */ - if (config_data_kw) { - hash_iter_type * iter = hash_iter_alloc(config_data_kw); - const char * key = hash_iter_get_next_key(iter); - while (key != NULL) { - enkf_main_add_data_kw( enkf_main , key , hash_get( config_data_kw , key )); - key = hash_iter_get_next_key(iter); - } - hash_iter_free(iter); - } -} - - - -static void enkf_main_install_common_data_kw( enkf_main_type * enkf_main ) { - /* - Installing the based (key,value) pairs which are common to all - ensemble members, and independent of time. - */ - char * cwd = util_alloc_cwd(); - char * date_string = util_alloc_date_stamp_utc(); - const char * num_cpu_string = "1"; - - enkf_main_add_subst_kw( enkf_main , "CWD" , cwd , "The current working directory we are running from - the location of the config file." , true); - enkf_main_add_subst_kw( enkf_main , "CONFIG_PATH" , cwd , "The current working directory we are running from - the location of the config file." , true); - enkf_main_add_subst_kw( enkf_main , "DATE" , date_string , "The current date." , true); - enkf_main_add_subst_kw( enkf_main , "NUM_CPU" , num_cpu_string , "The number of CPU used for one forward model." , true ); - enkf_main_add_subst_kw( enkf_main , "RUNPATH_FILE" , hook_manager_get_runpath_list_file( enkf_main->hook_manager ) , "The name of a file with a list of run directories." , true); - - free( cwd ); - free( date_string ); -} - - - -runpath_list_type * enkf_main_get_runpath_list( const enkf_main_type * enkf_main ) { - return hook_manager_get_runpath_list( enkf_main->hook_manager ); -} - - -/** - This function will resize the enkf_main->ensemble vector, - allocating or freeing enkf_state instances as needed. -*/ - - -void enkf_main_resize_ensemble( enkf_main_type * enkf_main , int new_ens_size ) { - int iens; - - /* No change */ - if (new_ens_size == enkf_main->ens_size) - return ; - - ranking_table_set_ens_size( enkf_main->ranking_table , new_ens_size ); - /* Tell the site_config object (i.e. the queue drivers) about the new ensemble size: */ - site_config_set_ens_size( enkf_main->site_config , new_ens_size ); - - - /* The ensemble is shrinking. */ - if (new_ens_size < enkf_main->ens_size) { - /*1: Free all ensemble members which go out of scope. */ - for (iens = new_ens_size; iens < enkf_main->ens_size; iens++) - enkf_state_free( enkf_main->ensemble[iens] ); - - /*2: Shrink the ensemble pointer. */ - enkf_main->ensemble = util_realloc(enkf_main->ensemble , new_ens_size * sizeof * enkf_main->ensemble ); - enkf_main->ens_size = new_ens_size; - return; - } - - - /* The ensemble is expanding */ - if (new_ens_size > enkf_main->ens_size) { - /*1: Grow the ensemble pointer. */ - enkf_main->ensemble = util_realloc(enkf_main->ensemble , new_ens_size * sizeof * enkf_main->ensemble ); - - /*2: Allocate the new ensemble members. */ - for (iens = enkf_main->ens_size; iens < new_ens_size; iens++) - - /* Observe that due to the initialization of the rng - this function is currently NOT thread safe. */ - enkf_main->ensemble[iens] = enkf_state_alloc(iens, - enkf_main->rng , - model_config_iget_casename( enkf_main->model_config , iens ) , - enkf_main->pre_clear_runpath , - int_vector_safe_iget( enkf_main->keep_runpath , iens) , - enkf_main->model_config , - enkf_main->ensemble_config , - enkf_main->site_config , - enkf_main->ecl_config , - enkf_main->templates , - enkf_main->subst_list); - enkf_main->ens_size = new_ens_size; - return; - } - - util_abort("%s: something is seriously broken - should NOT be here .. \n",__func__); -} - - -void enkf_main_add_node(enkf_main_type * enkf_main, enkf_config_node_type * enkf_config_node) { - for (int iens = 0; iens < enkf_main_get_ensemble_size(enkf_main); iens++) { - - enkf_state_add_node(enkf_main->ensemble[iens], enkf_config_node_get_key(enkf_config_node), enkf_config_node); - } -} - - - -void enkf_main_update_node( enkf_main_type * enkf_main , const char * key ) { - int iens; - for (iens = 0; iens < enkf_main->ens_size; iens++) - enkf_state_update_node( enkf_main->ensemble[iens] , key ); -} - - - - - - - - - - - - - - -/******************************************************************/ - -/** - SCHEDULE_PREDICTION_FILE. - - The SCHEDULE_PREDICTION_FILE is implemented as a GEN_KW instance, - with some twists. Observe the following: - - 1. The SCHEDULE_PREDICTION_FILE is added to the ensemble_config - as a GEN_KW node with key 'PRED'. - - 2. The target file is set equal to the initial prediction file - (i.e. the template in this case), NOT including any path - components. - -*/ - - -void enkf_main_set_schedule_prediction_file__( enkf_main_type * enkf_main , const char * template_file , const char * parameters , const char * min_std , const char * init_file_fmt) { - const char * key = "PRED"; - /* - First remove/delete existing PRED node if it is already installed. - */ - if (ensemble_config_has_key( enkf_main->ensemble_config , key)) - enkf_main_del_node( enkf_main , key ); - - if (template_file != NULL) { - char * target_file; - bool forward_init = false; - enkf_config_node_type * config_node = ensemble_config_add_gen_kw( enkf_main->ensemble_config , key , forward_init); - { - char * base; - char * ext; - util_alloc_file_components( template_file , NULL , &base , &ext); - target_file = util_alloc_filename(NULL , base , ext ); - util_safe_free( base ); - util_safe_free( ext ); - } - enkf_config_node_update_gen_kw( config_node , target_file , template_file , parameters , min_std , init_file_fmt ); - free( target_file ); - ecl_config_set_schedule_prediction_file( enkf_main->ecl_config , template_file ); - } -} - - -void enkf_main_set_schedule_prediction_file( enkf_main_type * enkf_main , const char * schedule_prediction_file) { - enkf_main_set_schedule_prediction_file__(enkf_main , schedule_prediction_file , NULL , NULL , NULL ); -} - - -const char * enkf_main_get_schedule_prediction_file( const enkf_main_type * enkf_main ) { - return ecl_config_get_schedule_prediction_file( enkf_main->ecl_config ); -} - - - -/*****************************************************************/ - -static void enkf_main_init_data_kw( enkf_main_type * enkf_main , config_content_type * config ) { - { - const subst_list_type * define_list = config_content_get_define_list( config ); - for (int i=0; i < subst_list_get_size( define_list ); i++) { - const char * key = subst_list_iget_key( define_list , i ); - const char * value = subst_list_iget_value( define_list , i ); - enkf_main_add_data_kw( enkf_main , key , value ); - } - } - - if (config_content_has_item( config , DATA_KW_KEY)) { - config_content_item_type * data_item = config_content_get_item( config , DATA_KW_KEY ); - hash_type * data_kw = config_content_item_alloc_hash(data_item , true); - enkf_main_install_data_kw( enkf_main , data_kw ); - hash_free( data_kw ); - } - - enkf_main_install_common_data_kw( enkf_main ); -} - - - - - -/*****************************************************************/ - - -rng_config_type * enkf_main_get_rng_config( const enkf_main_type * enkf_main ) { - return enkf_main->rng_config; -} - - -void enkf_main_rng_init( enkf_main_type * enkf_main) { - if (enkf_main->rng != NULL) - rng_config_init_rng(enkf_main->rng_config, enkf_main->rng); - else - enkf_main->rng = rng_config_alloc_init_rng( enkf_main->rng_config ); -} - - -void enkf_main_update_local_updates( enkf_main_type * enkf_main) { - const enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - if (enkf_obs_have_obs( enkf_obs )) { - /* First create the default ALL_ACTIVE configuration. */ - enkf_main_create_all_active_config( enkf_main ); - } -} - -static char * __enkf_main_alloc_user_config_file(const enkf_main_type * enkf_main, bool base_only) { - char * base_name; - char * extension; - util_alloc_file_components(enkf_main_get_user_config_file(enkf_main), NULL, &base_name, &extension); - - char * config_file; - if (base_only) { - config_file = util_alloc_filename(NULL, base_name, NULL);; - } else { - config_file = util_alloc_filename(NULL, base_name, extension); - } - - free(base_name); - free(extension); - return config_file; -} - -static hash_type *__enkf_main_alloc_predefined_kw_map(const enkf_main_type *enkf_main) { - char * config_file_base = __enkf_main_alloc_user_config_file(enkf_main, true); - char * config_file = __enkf_main_alloc_user_config_file(enkf_main, false); - hash_type * pre_defined_kw_map = hash_alloc(); - - hash_insert_string(pre_defined_kw_map, "", config_file); - hash_insert_string(pre_defined_kw_map, "", config_file_base); - - free( config_file ) ; - free( config_file_base ); - return pre_defined_kw_map; -} - - -/** - Observe that the site-config initializations starts with chdir() to - the location of the site_config_file; this ensures that the - site_config can contain relative paths to job description files and - scripts. -*/ - - -static void enkf_main_bootstrap_site(enkf_main_type * enkf_main , const char * site_config_file) { - if (site_config_file != NULL) { - if (!util_file_exists(site_config_file)) util_exit("%s: can not locate site configuration file:%s \n",__func__ , site_config_file); - config_parser_type * config = config_alloc(); - site_config_add_config_items( config , true ); - { - config_content_type * content = config_parse(config , site_config_file , "--" , INCLUDE_KEY , DEFINE_KEY , NULL, CONFIG_UNRECOGNIZED_WARN , false); - if (config_content_is_valid( content )) { - site_config_init( enkf_main->site_config , content ); - analysis_config_load_all_external_modules_from_config(enkf_main->analysis_config, content); - ert_workflow_list_init( enkf_main->workflow_list , content ); - } else { - config_error_type * errors = config_content_get_errors( content ); - fprintf(stderr , "** ERROR: Parsing site configuration file:%s failed \n\n" , site_config_file); - config_error_fprintf( errors , true , stderr ); - exit(1); - } - config_content_free( content ); - } - config_free( config ); - } -} - - -/** - This function boots everything needed for running a EnKF - application. Very briefly it can be summarized as follows: - - 1. A large config object is initalized with all the possible - keywords we are looking for. - - 2. All the config files are parsed in one go. - - 3. The various objects are build up by reading from the config - object. - - 4. The resulting enkf_main object contains *EVERYTHING* - (whoaha...) - - - Observe that the function will start with chdir() to the directory - containing the configuration file, so that all subsequent file - references are relative to the location of the configuration - file. This also applies if the command_line argument given is a - symlink. - - - If the parameter @strict is set to false a configuration with some - missing parameters will validate; this is to support bootstrapping - from a minimal configuration created by the GUI. The parameters - which become optional in a non-strict mode are: - - FORWARD_MODEL - DATA_FILE - SCHEDULE_FILE - ECLBASE - -*/ - - -/** - It is possible to pass NULL as the model_config argument, in that - case only the site config file will be parsed. The purpose of this - is mainly to be able to test that the site config file is valid. -*/ - - -enkf_main_type * enkf_main_bootstrap(const char * _model_config, bool strict , bool verbose) { - const char * site_config = site_config_get_location(); - char * model_config = NULL; - enkf_main_type * enkf_main; /* The enkf_main object is allocated when the config parsing is completed. */ - - if (_model_config) { - { - char * path; - char * base; - char * ext; - if (util_is_link( _model_config )) { /* The command line argument given is a symlink - we start by changing to */ - /* the real location of the configuration file. */ - char * realpath = util_alloc_link_target( _model_config ); - util_alloc_file_components(realpath , &path , &base , &ext); - free( realpath ); - } else - util_alloc_file_components(_model_config , &path , &base , &ext); - - if (path != NULL) { - if (util_chdir(path) != 0) - util_abort("%s: failed to change directory to: %s : %s \n",__func__ , path , strerror(errno)); - - if (verbose) - printf("Changing to directory ...................: %s \n",path); - - if (ext != NULL) - model_config = util_alloc_filename( NULL , base , ext ); - else - model_config = util_alloc_string_copy( base ); - } else - model_config = util_alloc_string_copy(_model_config); - - util_safe_free( path ); - util_safe_free( base ); - util_safe_free( ext ); - } - - if (!util_file_exists(model_config)) - util_exit("%s: can not locate user configuration file:%s \n",__func__ , model_config); - } - - - { - config_parser_type * config; - config_content_type * content; - enkf_main = enkf_main_alloc_empty( ); - enkf_main_set_verbose( enkf_main , verbose ); - enkf_main_bootstrap_site( enkf_main , site_config); - - if (model_config) { - enkf_main_set_site_config_file( enkf_main , site_config ); - enkf_main_set_user_config_file( enkf_main , model_config ); - - config = config_alloc(); - enkf_main_init_user_config( enkf_main , config ); - site_config_add_config_items( config , false ); - site_config_init_user_mode( enkf_main->site_config ); - enkf_main_user_config_deprecate( config ); - - { - hash_type *pre_defined_kw_map = __enkf_main_alloc_predefined_kw_map(enkf_main); - content = config_parse(config , model_config , "--" , INCLUDE_KEY , DEFINE_KEY , pre_defined_kw_map, CONFIG_UNRECOGNIZED_WARN , true); - hash_free(pre_defined_kw_map); - } - - { - const stringlist_type * warnings = config_content_get_warnings( content ); - if (stringlist_get_size( warnings ) > 0) { - fprintf(stderr," ** There were warnings when parsing the configuration file: %s" , model_config ); - for (int i=0; i < stringlist_get_size( warnings ); i++) - fprintf(stderr, " %02d : %s \n",i , stringlist_iget( warnings , i )); - } - } - - if (!config_content_is_valid( content )) { - config_error_type * errors = config_content_get_errors( content ); - config_error_fprintf( errors , true , stderr ); - exit(1); - } - - site_config_init( enkf_main->site_config , content ); /* <---- model_config : second pass. */ - - /*****************************************************************/ - /* - OK - now we have parsed everything - and we are ready to start - populating the enkf_main object. - */ - - - - - { - char * log_file; - int log_level = DEFAULT_LOG_LEVEL; - if(config_content_has_item( content , LOG_LEVEL_KEY)) - log_level = config_content_get_value_as_int(content , LOG_LEVEL_KEY); - - if (config_content_has_item( content , LOG_FILE_KEY)) - log_file = util_alloc_string_copy( config_content_get_value(content , LOG_FILE_KEY)); - else - log_file = util_alloc_filename( NULL , enkf_main->user_config_file , "log"); - - ert_log_init_log(log_level, log_file , enkf_main->verbose); - - free( log_file ); - } - - /* - Initializing the various 'large' sub config objects. - */ - rng_config_init( enkf_main->rng_config , content ); - enkf_main_rng_init( enkf_main ); /* Must be called before the ensmeble is created. */ - - enkf_main_init_subst_list( enkf_main ); - ert_workflow_list_init( enkf_main->workflow_list , content ); - - analysis_config_load_internal_modules( enkf_main->analysis_config ); - analysis_config_init( enkf_main->analysis_config , content ); - ecl_config_init( enkf_main->ecl_config , content ); - config_settings_apply( enkf_main->plot_config , content ); - - ensemble_config_init( enkf_main->ensemble_config , content , - ecl_config_get_grid( enkf_main->ecl_config ) , - ecl_config_get_refcase( enkf_main->ecl_config) ); - - model_config_init( enkf_main->model_config , - content , - enkf_main_get_ensemble_size( enkf_main ), - site_config_get_installed_jobs(enkf_main->site_config) , - ecl_config_get_last_history_restart( enkf_main->ecl_config ), - ecl_config_get_sched_file(enkf_main->ecl_config) , - ecl_config_get_refcase( enkf_main->ecl_config )); - - enkf_main_init_hook_manager( enkf_main , content ); - enkf_main_init_data_kw( enkf_main , content ); - enkf_main_update_num_cpu( enkf_main ); - { - if (config_content_has_item( content , SCHEDULE_PREDICTION_FILE_KEY )) { - const config_content_item_type * pred_item = config_content_get_item( content , SCHEDULE_PREDICTION_FILE_KEY ); - config_content_node_type * pred_node = config_content_item_get_last_node( pred_item ); - const char * template_file = config_content_node_iget_as_path( pred_node , 0 ); - { - hash_type * opt_hash = hash_alloc(); - config_content_node_init_opt_hash( pred_node , opt_hash , 1 ); - - const char * parameters = hash_safe_get( opt_hash , "PARAMETERS" ); - const char * min_std = hash_safe_get( opt_hash , "MIN_STD" ); - const char * init_files = hash_safe_get( opt_hash , "INIT_FILES" ); - - enkf_main_set_schedule_prediction_file__( enkf_main , template_file , parameters , min_std , init_files ); - hash_free( opt_hash ); - } - } - } - - - /*****************************************************************/ - /** - By default the simulation directories are left intact when - the simulations re complete, but using the keyword - DELETE_RUNPATH you can request (some of) the directories to - be wiped after the simulations are complete. - */ - { - { - char * delete_runpath_string = NULL; - int ens_size = config_content_get_value_as_int(content , NUM_REALIZATIONS_KEY); - - if (config_content_has_item(content , DELETE_RUNPATH_KEY)) - delete_runpath_string = config_content_alloc_joined_string(content , DELETE_RUNPATH_KEY , ""); - - enkf_main_parse_keep_runpath( enkf_main , delete_runpath_string , ens_size ); - - util_safe_free( delete_runpath_string ); - } - - /* This is really in the wrong place ... */ - { - enkf_main->pre_clear_runpath = DEFAULT_PRE_CLEAR_RUNPATH; - if (config_content_has_item(content , PRE_CLEAR_RUNPATH_KEY)) - enkf_main->pre_clear_runpath = config_content_get_value_as_bool( content , PRE_CLEAR_RUNPATH_KEY); - } - - ecl_config_static_kw_init( enkf_main->ecl_config , content ); - - /* Installing templates */ - ert_templates_init( enkf_main->templates , content ); - - { - const char * rft_config_file = NULL; - if (config_content_has_item(content , RFT_CONFIG_KEY)) - rft_config_file = config_content_iget(content , RFT_CONFIG_KEY , 0,0); - - enkf_main_set_rft_config_file( enkf_main , rft_config_file ); - } - - - /*****************************************************************/ - enkf_main_user_select_initial_fs( enkf_main ); - - /* Adding ensemble members */ - enkf_main_resize_ensemble( enkf_main, config_content_iget_as_int(content, NUM_REALIZATIONS_KEY , 0 , 0) ); - - /*****************************************************************/ - - /* Loading observations */ - enkf_main_alloc_obs(enkf_main); - if (config_content_has_item(content , OBS_CONFIG_KEY)) { - const char * obs_config_file = config_content_iget(content , OBS_CONFIG_KEY , 0,0); - enkf_main_load_obs( enkf_main , obs_config_file , true ); - } - - } - config_content_free( content ); - config_free(config); - } - enkf_main_init_jobname( enkf_main ); - free( model_config ); - } - return enkf_main; -} - - - - -/** - This function creates a minimal configuration file, with a few - parameters (a bit arbitrary) parameters read from (typically) a GUI - configuration dialog. - - The set of parameters written by this function is _NOT_ a minimum - set to generate a valid configuration. -*/ - -void enkf_main_create_new_config( const char * config_file , const char * storage_path , const char * dbase_type , int num_realizations) { - - FILE * stream = util_mkdir_fopen( config_file , "w" ); - - fprintf(stream , CONFIG_KEY_FORMAT , ENSPATH_KEY); - fprintf(stream , CONFIG_ENDVALUE_FORMAT , storage_path ); - - fprintf(stream , CONFIG_KEY_FORMAT , DBASE_TYPE_KEY); - fprintf(stream , CONFIG_ENDVALUE_FORMAT , dbase_type); - - fprintf(stream , CONFIG_KEY_FORMAT , NUM_REALIZATIONS_KEY); - fprintf(stream , CONFIG_INT_FORMAT , num_realizations); - fprintf(stream , "\n"); - - fclose( stream ); - - printf("Have created configuration file: %s \n",config_file ); -} - - - - - - - - -/** - First deleting all the nodes - then the configuration. -*/ - -void enkf_main_del_node(enkf_main_type * enkf_main , const char * key) { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - int iens; - for (iens = 0; iens < ens_size; iens++) - enkf_state_del_node(enkf_main->ensemble[iens] , key); - ensemble_config_del_node(enkf_main->ensemble_config , key); -} - - - -int enkf_main_get_ensemble_size( const enkf_main_type * enkf_main ) { - return enkf_main->ens_size; -} - - -enkf_state_type ** enkf_main_get_ensemble( enkf_main_type * enkf_main) { - return enkf_main->ensemble; -} - - -const enkf_state_type ** enkf_main_get_ensemble_const( const enkf_main_type * enkf_main) { - return (const enkf_state_type **) enkf_main->ensemble; -} - - - -/** - In this function we initialize the variables which control - which nodes are internalized (i.e. loaded from the forward - simulation and stored in the enkf_fs 'database'). The system is - based on two-levels: - - * Should we store the state? This is goverened by the variable - model_config->internalize_state. If this is true we will - internalize all nodes which have enkf_var_type = {dynamic_state , - static_state}. In the same way the variable - model_config->internalize_results governs whether the dynamic - results (i.e. summary variables in ECLIPSE speak) should be - internalized. - - * In addition we have fine-grained control in the enkf_config_node - objects where we can explicitly say that, altough we do not want - to internalize the full state, we want to internalize e.g. the - pressure field. - - * All decisions on internalization are based on a per report step - basis. - - The user-space API for manipulating this is (extremely) - limited. What is implemented here is the following: - - 1. We internalize the initial dynamic state. - - 2. For all the end-points in the current enkf_sched instance we - internalize the state. - - 3. store_results is set to true for all report steps irrespective - of run_mode. - - 4. We iterate over all the observations, and ensure that the - observed nodes (i.e. the pressure for an RFT) are internalized - (irrespective of whether they are of type dynamic_state or - dynamic_result). - - Observe that this cascade can result in some nodes, i.e. a rate we - are observing, to be marked for internalization several times - - that is no problem. - - ----- - - For performance reason model_config contains the bool vector - __load_eclipse_restart; if it is true the ECLIPSE restart state is - loaded from disk, otherwise no loading is performed. This implies - that if we do not want to internalize the full state but for - instance the pressure (i.e. for an RFT) we must set the - __load_state variable for the actual report step to true. For this - reason calls enkf_config_node_internalize() must be accompanied by - calls to model_config_set_load_state|results() - this is ensured - when using this function to manipulate the configuration of - internalization. - -*/ - - -void enkf_main_init_internalization( enkf_main_type * enkf_main , run_mode_type run_mode ) { - /* Clearing old internalize flags. */ - model_config_init_internalization( enkf_main->model_config ); - - /* Internalizing the initial state. */ - model_config_set_internalize_state( enkf_main->model_config , 0); - - - /* Make sure we internalize at all observation times.*/ - { - hash_type * map = enkf_obs_alloc_data_map(enkf_main->obs); - hash_iter_type * iter = hash_iter_alloc(map); - const char * obs_key = hash_iter_get_next_key(iter); - - while (obs_key != NULL) { - obs_vector_type * obs_vector = enkf_obs_get_vector( enkf_main->obs , obs_key ); - enkf_config_node_type * data_node = obs_vector_get_config_node( obs_vector ); - int active_step = -1; - do { - active_step = obs_vector_get_next_active_step( obs_vector , active_step ); - if (active_step >= 0) { - enkf_config_node_set_internalize( data_node , active_step ); - { - enkf_var_type var_type = enkf_config_node_get_var_type( data_node ); - if (var_type == DYNAMIC_STATE) - model_config_set_load_state( enkf_main->model_config , active_step); - } - } - } while (active_step >= 0); - obs_key = hash_iter_get_next_key(iter); - } - hash_iter_free(iter); - hash_free(map); - } -} - - - - -/*****************************************************************/ - - - - - - -const ext_joblist_type * enkf_main_get_installed_jobs( const enkf_main_type * enkf_main ) { - return site_config_get_installed_jobs( enkf_main->site_config ); -} - - - -/*****************************************************************/ - -void enkf_main_get_observations( const enkf_main_type * enkf_main, const char * user_key , int obs_count , time_t * obs_time , double * y , double * std) { - ensemble_config_get_observations( enkf_main->ensemble_config , enkf_main->obs , user_key , obs_count , obs_time , y , std); -} - - -int enkf_main_get_observation_count( const enkf_main_type * enkf_main, const char * user_key ) { - return ensemble_config_get_observations( enkf_main->ensemble_config , enkf_main->obs , user_key , 0 , NULL , NULL , NULL); -} - - - -void enkf_main_log_fprintf_config( const enkf_main_type * enkf_main , FILE * stream ) { - fprintf( stream , CONFIG_COMMENTLINE_FORMAT ); - fprintf( stream , CONFIG_COMMENT_FORMAT , "Here comes configuration information about the ERT logging."); - fprintf( stream , CONFIG_KEY_FORMAT , LOG_FILE_KEY ); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , ert_log_get_filename()); - - if (ert_log_get_log_level() != DEFAULT_LOG_LEVEL) { - fprintf(stream , CONFIG_KEY_FORMAT , LOG_LEVEL_KEY ); - fprintf(stream , CONFIG_INT_FORMAT , ert_log_get_log_level()); - fprintf(stream , "\n"); - } - - fprintf(stream , "\n"); - fprintf(stream , "\n"); -} - - -void enkf_main_install_SIGNALS(void) { - util_install_signals(); -} - - - - -ert_templates_type * enkf_main_get_templates( enkf_main_type * enkf_main ) { - return enkf_main->templates; -} - - - -/*****************************************************************/ - - -void enkf_main_fprintf_runpath_config( const enkf_main_type * enkf_main , FILE * stream ) { - fprintf(stream , CONFIG_KEY_FORMAT , PRE_CLEAR_RUNPATH_KEY ); - fprintf(stream , CONFIG_ENDVALUE_FORMAT , CONFIG_BOOL_STRING( enkf_state_get_pre_clear_runpath( enkf_main->ensemble[0] ))); - - { - bool del_comma = false; - - - for (int iens = 0; iens < enkf_main->ens_size; iens++) { - keep_runpath_type keep_runpath = enkf_main_iget_keep_runpath( enkf_main , iens ); - if (keep_runpath == EXPLICIT_DELETE) { - if (!del_comma) { - fprintf(stream , CONFIG_KEY_FORMAT , DELETE_RUNPATH_KEY ); - fprintf(stream , CONFIG_INT_FORMAT , iens); - del_comma = true; - } else { - fprintf(stream , ","); - fprintf(stream , CONFIG_INT_FORMAT , iens); - } - } - } - fprintf(stream , "\n"); - } -} - - - -/*****************************************************************/ - -ert_workflow_list_type * enkf_main_get_workflow_list( enkf_main_type * enkf_main ) { - return enkf_main->workflow_list; -} - -bool enkf_main_run_workflow( enkf_main_type * enkf_main , const char * workflow ) { - ert_workflow_list_type * workflow_list = enkf_main_get_workflow_list( enkf_main ); - if (ert_workflow_list_has_workflow( workflow_list , workflow)){ - return ert_workflow_list_run_workflow_blocking( workflow_list , workflow , enkf_main); - } - else{ - return false; - } -} - - -void enkf_main_run_workflows( enkf_main_type * enkf_main , const stringlist_type * workflows) { - int iw; - for (iw = 0; iw < stringlist_get_size( workflows ); iw++) - enkf_main_run_workflow( enkf_main , stringlist_iget( workflows , iw )); -} - - -int enkf_main_load_from_forward_model_from_gui(enkf_main_type * enkf_main, int iter , bool_vector_type * iactive, enkf_fs_type * fs){ - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - stringlist_type ** realizations_msg_list = util_calloc( ens_size , sizeof * realizations_msg_list ); - for (int iens = 0; iens < ens_size; ++iens) - realizations_msg_list[iens] = stringlist_alloc_new(); - - int loaded = enkf_main_load_from_forward_model_with_fs(enkf_main, iter , iactive, realizations_msg_list, fs); - - for (int iens = 0; iens < ens_size; ++iens) - stringlist_free( realizations_msg_list[iens] ); - - free(realizations_msg_list); - return loaded; -} - -int enkf_main_load_from_forward_model(enkf_main_type * enkf_main, int iter , bool_vector_type * iactive, stringlist_type ** realizations_msg_list){ - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - return enkf_main_load_from_forward_model_with_fs(enkf_main, iter, iactive, realizations_msg_list, fs); -} - - -int enkf_main_load_from_forward_model_with_fs(enkf_main_type * enkf_main, int iter , bool_vector_type * iactive, stringlist_type ** realizations_msg_list, enkf_fs_type * fs) { - printf("Loading from forward model\n"); - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - int result[ens_size]; - model_config_type * model_config = enkf_main->model_config; - - ert_run_context_type * run_context = ert_run_context_alloc_ENSEMBLE_EXPERIMENT( fs , iactive , model_config_get_runpath_fmt( model_config ) , enkf_main->subst_list , iter ); - arg_pack_type ** arg_list = util_calloc( ens_size , sizeof * arg_list ); - thread_pool_type * tp = thread_pool_alloc( 4 , true ); /* num_cpu - HARD coded. */ - - int iens = 0; - for (; iens < ens_size; ++iens) { - printf("\tloading %d (realization %d/%d) ", iens, (1+iens), ens_size); - result[iens] = 0; - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_list[iens] = arg_pack; - - if (bool_vector_iget(iactive, iens)) { - printf("... "); - enkf_state_type * enkf_state = enkf_main_iget_state( enkf_main , iens ); - arg_pack_append_ptr( arg_pack , enkf_state); /* 0: enkf_state*/ - arg_pack_append_ptr( arg_pack , ert_run_context_iens_get_arg( run_context , iens )); /* 1: run_arg */ - arg_pack_append_ptr(arg_pack, realizations_msg_list[iens]); /* 2: List of interactive mode messages. */ - arg_pack_append_bool( arg_pack, true ); /* 3: Manual load */ - arg_pack_append_ptr(arg_pack, &result[iens]); /* 4: Result */ - thread_pool_add_job( tp , enkf_state_load_from_forward_model_mt , arg_pack); - } - printf("done\n"); - } - - thread_pool_join( tp ); - thread_pool_free( tp ); - printf("\n"); - - int loaded = 0; - for (iens = 0; iens < ens_size; ++iens) { - if (bool_vector_iget(iactive, iens)) { - if (result[iens] & LOAD_FAILURE) - fprintf(stderr, "** Warning: Function %s: Realization %d load failure\n", __func__, iens); - else if (result[iens] & REPORT_STEP_INCOMPATIBLE) - fprintf(stderr, "** Warning: Function %s: Realization %d report step incompatible\n", __func__, iens); - else - loaded++; - } - arg_pack_free(arg_list[iens]); - } - free( arg_list ); - ert_run_context_free( run_context ); - return loaded; -} - - -bool enkf_main_export_field(const enkf_main_type * enkf_main, - const char * kw, - const char * path, - bool_vector_type * iactive, - field_file_format_type file_type, - int report_step) -{ - enkf_fs_type * fs = enkf_main_get_fs(enkf_main); - bool result = enkf_main_export_field_with_fs(enkf_main, kw, path, iactive, file_type, report_step, fs); - return result; -} - - - - -bool enkf_main_export_field_with_fs(const enkf_main_type * enkf_main, - const char * kw, - const char * path, - bool_vector_type * iactive, - field_file_format_type file_type, - int report_step, - enkf_fs_type * fs) { - - bool ret = false; - if (util_int_format_count(path) < 1) { - printf("EXPORT FIELD: There must be a %%d in the file name\n"); - return ret; - } - - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - enkf_config_node_type * config_node = NULL; - bool node_found = false; - - if (ensemble_config_has_key(ensemble_config, kw)) { - config_node = ensemble_config_get_node(ensemble_config, kw); - if (config_node && enkf_config_node_get_impl_type(config_node) == FIELD) { - node_found = true; - } else - printf("Did not find a FIELD %s node\n", kw); - } else - printf("Ensemble config does not have key %s\n", kw); - - if (node_found) { - enkf_node_type * node = NULL; - model_config_type * mc = enkf_main_get_model_config(enkf_main); - path_fmt_type * runpath_fmt = model_config_get_runpath_fmt(mc); - const char * init_file = enkf_config_node_get_FIELD_fill_file(config_node, runpath_fmt); - if (init_file) - printf("init_file found: \"%s\", exporting initial value for inactive cells\n", init_file); - else - printf("no init_file found, exporting 0 or fill value for inactive cells\n"); - - int iens; - for (iens = 0; iens < bool_vector_size(iactive); ++iens) { - if (bool_vector_iget(iactive, iens)) { - node_id_type node_id = {.report_step = report_step , .iens = iens }; - node = enkf_state_get_node(enkf_main->ensemble[iens] , kw); - if (node) { - if (enkf_node_try_load(node , fs , node_id)) { - path_fmt_type * export_path = path_fmt_alloc_path_fmt( path ); - char * filename = path_fmt_alloc_path( export_path , false , iens); - path_fmt_free(export_path); - - { - char * path; - util_alloc_file_components(filename , &path , NULL , NULL); - if (path != NULL) { - util_make_path( path ); - free( path ); - } - } - - { - const field_type * field = enkf_node_value_ptr(node); - const bool output_transform = true; - field_export(field , filename , NULL , file_type , output_transform, init_file); - ret = true; - } - free(filename); - } else - printf("%s : enkf_node_try_load returned returned false \n", __func__); - } else - printf("%s : enkf_state_get_node returned NULL for parameters %d, %s \n", __func__, iens, kw); - } - } - } - - - if (ret) - printf("Successful export of FIELD %s\n", kw); - else - printf("Errors during export of FIELD %s\n", kw); - - return ret; -} - - -void enkf_main_rank_on_observations(enkf_main_type * enkf_main, - const char * ranking_key, - const stringlist_type * obs_ranking_keys, - const int_vector_type * steps) { - - enkf_fs_type * fs = enkf_main_get_fs(enkf_main); - const enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - const int history_length = enkf_main_get_history_length( enkf_main ); - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - - misfit_ensemble_type * misfit_ensemble = enkf_fs_get_misfit_ensemble( fs ); - misfit_ensemble_initialize( misfit_ensemble , ensemble_config , enkf_obs , fs , ens_size , history_length, false); - - ranking_table_type * ranking_table = enkf_main_get_ranking_table( enkf_main ); - - ranking_table_add_misfit_ranking( ranking_table , misfit_ensemble , obs_ranking_keys , steps , ranking_key ); - ranking_table_display_ranking( ranking_table , ranking_key); -} - - - -void enkf_main_rank_on_data(enkf_main_type * enkf_main, - const char * ranking_key, - const char * data_key, - bool sort_increasing, - int step) { - - ranking_table_type * ranking_table = enkf_main_get_ranking_table( enkf_main ); - ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config( enkf_main ); - enkf_fs_type * fs = enkf_main_get_fs(enkf_main); - char * key_index; - - const enkf_config_node_type * config_node = ensemble_config_user_get_node( ensemble_config , data_key , &key_index); - if (config_node) { - ranking_table_add_data_ranking( ranking_table , sort_increasing , ranking_key , data_key , key_index , fs , config_node, step ); - ranking_table_display_ranking( ranking_table , ranking_key ); - } else { - fprintf(stderr,"** No data found for key %s\n", data_key); - } -} - - -void enkf_main_export_ranking(enkf_main_type * enkf_main, const char * ranking_key, const char * ranking_file) { - ranking_table_type * ranking_table = enkf_main_get_ranking_table( enkf_main ); - ranking_table_fwrite_ranking(ranking_table, ranking_key, ranking_file); -} - - -#include "enkf_main_manage_fs.c" diff --git a/ThirdParty/Ert/libenkf/src/enkf_main_jobs.c b/ThirdParty/Ert/libenkf/src/enkf_main_jobs.c deleted file mode 100644 index 6718e2be54..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_main_jobs.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'enkf_main_jobs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include -#include - -#include -#include -#include -#include - - - -static bool_vector_type * alloc_iactive_vector_from_range(const stringlist_type * range, int startindex, int endindex, int ens_size) { - bool_vector_type * iactive; - int range_list_size = stringlist_get_size(range); - if ((range_list_size > startindex) && (range_list_size >= endindex)) { - char * arg_string = stringlist_alloc_joined_substring( range, startindex, endindex, ""); - iactive = bool_vector_alloc(ens_size, false); - string_util_update_active_mask( arg_string, iactive ); - free ( arg_string ); - } else { - iactive = bool_vector_alloc(ens_size, true); - } - return iactive; -} - -void enkf_main_jobs_sleep(){ - while(true){ - printf("Hi from internal \n"); - sleep(1); - } -} - -void * enkf_main_exit_JOB(void * self , const stringlist_type * args ) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - enkf_main_exit( enkf_main ); - return NULL; -} - - -/** - This job is purely added to make sure we have a job in the - internal-gui/config subdirectory. As soon as there is a real job - there; this can be removed. -*/ - -void * enkf_main_dummy_JOB(void * self , const stringlist_type * args ) { - return NULL; -} - - - - - -void * enkf_main_ensemble_run_JOB( void * self , const stringlist_type * args ) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = alloc_iactive_vector_from_range(args, 0, stringlist_get_size(args), ens_size); - - bool_vector_iset( iactive , ens_size - 1 , true ); - enkf_main_run_tui_exp( enkf_main , iactive); - bool_vector_free(iactive); - return NULL; -} - - -static void * enkf_main_smoother_JOB__( void * self , int iter , const stringlist_type * args ) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc( ens_size , true ); - bool valid = true; - const char * target_case = stringlist_iget( args , 0 ); - enkf_fs_type * source_fs = enkf_main_job_get_fs( enkf_main ); - //Argument 2: Rerun. Default false. - bool rerun = (stringlist_get_size(args) >= 2) ? stringlist_iget_as_bool(args, 1, &valid) : false; - - if (!valid) { - fprintf(stderr, "** Warning: Function %s : Second argument must be a bool value. Exiting job\n", __func__); - return NULL; - } - enkf_main_run_smoother( enkf_main , source_fs , target_case , iactive , iter , rerun); - bool_vector_free( iactive ); - return NULL; -} - - -void * enkf_main_smoother_JOB( void * self , const stringlist_type * args ) { - return enkf_main_smoother_JOB__( self, 0 , args ); -} - - -void * enkf_main_smoother_with_iter_JOB( void * self , const stringlist_type * args ) { - int iter; - stringlist_type * sub_args = stringlist_alloc_shallow_copy_with_limits( args , 1 , stringlist_get_size( args ) - 1); - util_sscanf_int( stringlist_iget(args , 0 ) , &iter ); - - enkf_main_smoother_JOB__( self , iter , sub_args ); - - stringlist_free( sub_args ); - return NULL; -} - - - -void * enkf_main_iterated_smoother_JOB( void * self , const stringlist_type * args ) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - const analysis_config_type * analysis_config = enkf_main_get_analysis_config(enkf_main); - analysis_iter_config_type * iter_config = analysis_config_get_iter_config(analysis_config); - int num_iter = analysis_iter_config_get_num_iterations(iter_config); - - enkf_main_run_iterated_ES( enkf_main , num_iter); - return NULL; -} - - -void * enkf_main_select_module_JOB( void * self , const stringlist_type * args ) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main ); - - analysis_config_select_module( analysis_config , stringlist_iget( args , 0 )); - - return NULL; -} - - -void * enkf_main_scale_obs_std_JOB(void * self, const stringlist_type * args ) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - - double scale_factor; - if (util_sscanf_double(stringlist_iget(args, 0), &scale_factor)) { - analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main ); - analysis_config_set_global_std_scaling( analysis_config , scale_factor ); - } - return NULL; -} - -/*****************************************************************/ - -/* - Will create the new case if it does not exist. -*/ -void * enkf_main_select_case_JOB( void * self , const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - const char * new_case = stringlist_iget( args , 0 ); - enkf_main_select_fs( enkf_main , new_case ); - return NULL; -} - - -void * enkf_main_create_case_JOB( void * self , const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - const char * new_case = stringlist_iget( args , 0 ); - enkf_fs_type * fs = enkf_main_mount_alt_fs( enkf_main , new_case , true ); - enkf_fs_decref( fs ); - return NULL; -} - - - -void * enkf_main_init_case_from_existing_JOB( void * self , const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - - const char * source_case = stringlist_iget( args , 0 ); - enkf_fs_type * source_fs = enkf_main_mount_alt_fs( enkf_main , source_case , true ); - { - enkf_fs_type * target_fs; - - if (stringlist_get_size(args) > 1) { - const char * current_case = enkf_main_get_current_fs(enkf_main); - const char * target_case = stringlist_iget( args , 1 ); - if (0 != strcmp(current_case, target_case)) { - target_fs = enkf_main_mount_alt_fs( enkf_main , target_case , true ); - } else - target_fs = enkf_fs_get_ref( enkf_main_job_get_fs(enkf_main) ); // Using get_ref so that we can unconditionally call decref() further down. - } else - target_fs = enkf_fs_get_ref( enkf_main_job_get_fs(enkf_main) ); // Using get_ref so that we can unconditionally call decref() further down. - - enkf_main_init_case_from_existing(enkf_main, source_fs, 0, target_fs); // Removed ANALYZED argument - enkf_fs_decref(target_fs); - } - enkf_fs_decref(source_fs); - - return NULL; -} - - -/*****************************************************************/ - -static void * enkf_main_load_results_JOB__( enkf_main_type * enkf_main , int iter , const stringlist_type * args) { - bool_vector_type * iactive = alloc_iactive_vector_from_range(args, 0, stringlist_get_size(args), enkf_main_get_ensemble_size(enkf_main)); - int ens_size = enkf_main_get_ensemble_size(enkf_main); - stringlist_type ** realizations_msg_list = util_calloc(ens_size, sizeof * realizations_msg_list); - for (int iens = 0; iens < ens_size; ++iens) - realizations_msg_list[iens] = stringlist_alloc_new(); - - enkf_main_load_from_forward_model(enkf_main, iter , iactive, realizations_msg_list); - - for (int iens = 0; iens < ens_size; ++iens) { - stringlist_type * msg = realizations_msg_list[iens]; - if (stringlist_get_size(msg)) { - int msg_count = 0; - for (; msg_count < stringlist_get_size(msg); ++msg_count) - fprintf(stderr, "** Warning: Function %s : Load of realization number %d returned the following warning: %s\n", __func__, iens, stringlist_iget(msg, msg_count)); - } - stringlist_free(msg); - } - - free(realizations_msg_list); - bool_vector_free(iactive); - return NULL; -} - - -void * enkf_main_load_results_JOB( void * self , const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - int iter = 0; - { - const model_config_type * model_config = enkf_main_get_model_config( enkf_main ); - if (model_config_runpath_requires_iter( model_config )) - fprintf(stderr,"**Warning: the runpath format:%s requires an iteration number - using default:0. Use the job: LOAD_RESULT_ITER instead.\n" , model_config_get_runpath_as_char( model_config )); - } - return enkf_main_load_results_JOB__(enkf_main , iter , args ); -} - - -void * enkf_main_load_results_iter_JOB( void * self , const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - stringlist_type * iens_args = stringlist_alloc_shallow_copy_with_limits( args , 1 , stringlist_get_size( args ) - 1); - int iter; - - util_sscanf_int( stringlist_iget( args , 0 ) , &iter); - enkf_main_load_results_JOB__(enkf_main , iter , iens_args ); - stringlist_free( iens_args ); - - return NULL; -} - - -/*****************************************************************/ - -static void enkf_main_jobs_export_field(const enkf_main_type * enkf_main, const stringlist_type * args, field_file_format_type file_type) { - const char * field = stringlist_iget(args, 0); - const char * file_name = stringlist_iget(args, 1); - int report_step = 0; - util_sscanf_int(stringlist_iget(args,2), &report_step); - - bool_vector_type * iactive = alloc_iactive_vector_from_range(args, 4, stringlist_get_size(args), enkf_main_get_ensemble_size(enkf_main)); - enkf_main_export_field(enkf_main,field, file_name, iactive, file_type, report_step ) ; - bool_vector_free(iactive); -} - - - -void * enkf_main_export_field_JOB(void * self, const stringlist_type * args) { - const char * file_name = stringlist_iget(args, 1); - field_file_format_type file_type = field_config_default_export_format(file_name); - - if ((RMS_ROFF_FILE == file_type) || (ECL_GRDECL_FILE == file_type)) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - enkf_main_jobs_export_field(enkf_main, args, file_type); - } else - printf("EXPORT_FIELD filename argument: File extension must be either .roff or .grdecl\n"); - - return NULL; -} - -void * enkf_main_export_field_to_RMS_JOB(void * self, const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - enkf_main_jobs_export_field(enkf_main, args, RMS_ROFF_FILE); - return NULL; -} - -void * enkf_main_export_field_to_ECL_JOB(void * self, const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - enkf_main_jobs_export_field(enkf_main, args, ECL_GRDECL_FILE); - return NULL; -} - - -/*****************************************************************/ - -void * enkf_main_rank_on_observations_JOB(void * self, const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - const char * ranking_name = stringlist_iget(args, 0); - - bool step_arguments = false; - bool obs_arguments = false; - int delimiter = 0; - { - delimiter = stringlist_find_first(args, "|"); - if (delimiter > -1) { - step_arguments = (delimiter > 1) ? true : false; - obs_arguments = (stringlist_get_size(args) > delimiter + 1) ? true : false; - } else if (stringlist_get_size(args) > 1) { - step_arguments = true; - delimiter = stringlist_get_size(args); - } - } - - int_vector_type * steps_vector = NULL; - { - char * report_steps = NULL; - - if (step_arguments) - report_steps = stringlist_alloc_joined_substring(args, 1, delimiter, ","); - else - report_steps = util_alloc_sprintf("0-%d", enkf_main_get_history_length(enkf_main)); - - steps_vector = string_util_alloc_value_list(report_steps); - - free(report_steps); - } - - - stringlist_type * obs_ranking_keys = NULL; - { - char * obs_key_char = NULL; - if (obs_arguments) - obs_key_char = stringlist_alloc_joined_substring( args , delimiter+1 , stringlist_get_size(args) , " "); - - enkf_obs_type * enkf_obs = enkf_main_get_obs(enkf_main); - obs_ranking_keys = enkf_obs_alloc_matching_keylist( enkf_obs , obs_key_char ); - - if ((obs_arguments) && (stringlist_get_size(obs_ranking_keys) == 0)) { - fprintf(stderr,"The input string : \"%s\" did not resolve to any valid observation keys. Job not started\n", obs_key_char); - return NULL; - } - - if (obs_arguments) - free(obs_key_char); - } - - - enkf_main_rank_on_observations(enkf_main, ranking_name, obs_ranking_keys, steps_vector); - - stringlist_free(obs_ranking_keys); - int_vector_free(steps_vector); - return NULL; -} - - -void * enkf_main_rank_on_data_JOB(void * self, const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - const char * ranking_name = stringlist_iget(args, 0); - const char * data_key = stringlist_iget(args, 1); - bool valid = true; - bool sort_increasing = stringlist_iget_as_bool(args, 2, &valid); - - if (!valid) { - fprintf(stderr,"** Third argument \"sort increasing\" not recognized as bool value, job not started\n"); - return NULL; - } - - int report_step = (stringlist_get_size(args) > 3) ? stringlist_iget_as_int(args, 3, &valid) : enkf_main_get_history_length(enkf_main) ; - if (!valid) { - fprintf(stderr,"** Fourth argument \"step\" not recognized as integer value, job not started\n"); - return NULL; - } - - if (report_step < 0) { - fprintf(stderr,"** Negative report step, job not started\n"); - return NULL; - } - - enkf_main_rank_on_data(enkf_main, ranking_name, data_key, sort_increasing, report_step); - return NULL; -} - - -void * enkf_main_export_ranking_JOB(void * self, const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - const char * ranking_name = stringlist_iget(args, 0); - const char * ranking_file = stringlist_iget(args, 1); - - enkf_main_export_ranking(enkf_main, ranking_name, ranking_file); - return NULL; -} - -void * enkf_main_init_misfit_table_JOB(void * self, const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - int history_length = enkf_main_get_history_length(enkf_main); - enkf_obs_type * enkf_obs = enkf_main_get_obs(enkf_main); - int ens_size = enkf_main_get_ensemble_size(enkf_main); - enkf_fs_type * fs = enkf_main_job_get_fs(enkf_main); - bool force_update = true; - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - - - misfit_ensemble_type * misfit_ensemble = enkf_fs_get_misfit_ensemble( fs ); - misfit_ensemble_initialize( misfit_ensemble , ensemble_config , enkf_obs , fs , ens_size , history_length, force_update); - - return NULL; -} - - - - -static void enkf_main_export_runpath_file(enkf_main_type * enkf_main, - const int_vector_type * realizations, - const int_vector_type * iterations) { - - ecl_config_type * ecl_config = enkf_main_get_ecl_config(enkf_main); - const model_config_type * model_config = enkf_main_get_model_config(enkf_main); - const char * basename_fmt = ecl_config_get_eclbase(ecl_config); - const char * runpath_fmt = model_config_get_runpath_as_char(model_config); - const hook_manager_type * hook_manager = enkf_main_get_hook_manager( enkf_main ); - - runpath_list_type * runpath_list = runpath_list_alloc( hook_manager_get_runpath_list_file( hook_manager )); - - for (int iter = 0; iter < int_vector_size(iterations); ++iter) { - for (int iens = 0; iens < int_vector_size(realizations); ++iens) { - int iter_value = int_vector_iget(iterations, iter); - int iens_value = int_vector_iget(realizations, iens); - char * basename; - char * runpath; - - if (basename_fmt) - basename = util_alloc_sprintf(basename_fmt, iens_value); - else - basename = util_alloc_sprintf("--%d", iens_value); - - if (model_config_runpath_requires_iter(model_config)) - runpath = util_alloc_sprintf(runpath_fmt, iens_value, iter_value); - else - runpath = util_alloc_sprintf(runpath_fmt, iens_value); - - runpath_list_add(runpath_list, iens_value, iter_value, runpath, basename); - - free(basename); - free(runpath); - } - } - runpath_list_fprintf(runpath_list); - runpath_list_free(runpath_list); -} - - - - -void * enkf_main_export_runpath_file_JOB(void * self, const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - int ensemble_size = enkf_main_get_ensemble_size(enkf_main); - analysis_config_type * analysis_config = enkf_main_get_analysis_config(enkf_main); - analysis_iter_config_type * iter_config = analysis_config_get_iter_config(analysis_config); - int num_iterations = analysis_iter_config_get_num_iterations(iter_config); - const model_config_type * model_config = enkf_main_get_model_config(enkf_main); - int_vector_type * realizations = int_vector_alloc(1, 0); - int_vector_init_range(realizations, 0, ensemble_size, 1); - int_vector_type * iterations = int_vector_alloc(1, 0); - - - if (stringlist_get_size(args) > 0) { - int offset = 0; - while (true) { - if (offset == stringlist_get_size( args )) - break; - if (0 == strcmp("|" , stringlist_iget( args, offset ))) - break; - ++offset; - } - - if (0 != strcmp("*", stringlist_iget(args,0))) { - char * range_str = stringlist_alloc_joined_substring( args, 0, offset, ""); - string_util_init_value_list(range_str, realizations); - free(range_str); - } - - if ((offset < stringlist_get_size(args)) && model_config_runpath_requires_iter(model_config)) { - if (0 == strcmp("*", stringlist_iget(args, (offset+1)))) - int_vector_init_range(iterations, 0, num_iterations, 1); - else { - char * range_str = stringlist_alloc_joined_substring( args, offset+1, stringlist_get_size(args), ""); - string_util_init_value_list(range_str, iterations); - free(range_str); - } - } - } - - enkf_main_export_runpath_file(enkf_main, realizations, iterations); - - int_vector_free(realizations); - int_vector_free(iterations); - - return NULL; -} - - - -void * enkf_main_std_scale_correlated_obs_JOB(void * self, const stringlist_type * args) { - - if (stringlist_get_size(args) > 0) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - int ensemble_size = enkf_main_get_ensemble_size(enkf_main); - enkf_fs_type * fs = enkf_main_job_get_fs( enkf_main ); - enkf_obs_type * obs = enkf_main_get_obs( enkf_main ); - int_vector_type * realizations = int_vector_alloc(1, 0); - local_obsdata_type * obsdata = local_obsdata_alloc( "OBS-JOB" ); - - int_vector_init_range(realizations, 0, ensemble_size, 1); - - for (int iarg = 0; iarg < stringlist_get_size(args); iarg++) { - const char * arg_key = stringlist_iget( args , iarg ); - stringlist_type * key_list = enkf_obs_alloc_matching_keylist(obs, arg_key); - for (int iobs=0; iobs < stringlist_get_size( key_list ); iobs++) { - const char * obs_key = stringlist_iget( key_list , iobs); - const obs_vector_type * obs_vector = enkf_obs_get_vector(obs, obs_key); - local_obsdata_add_node( obsdata , obs_vector_alloc_local_node(obs_vector) ); - } - stringlist_free( key_list ); - } - - if (local_obsdata_get_size(obsdata) > 0) - enkf_obs_scale_correlated_std(obs, fs, realizations, obsdata ); - - local_obsdata_free( obsdata ); - } - - return NULL; -} - - -void * enkf_main_analysis_update_JOB( void * self , const stringlist_type * args) { - enkf_main_type * enkf_main = enkf_main_safe_cast( self ); - enkf_fs_type * source_fs = enkf_main_mount_alt_fs( enkf_main , stringlist_iget(args , 0 ) , false); - enkf_fs_type * target_fs = enkf_main_mount_alt_fs( enkf_main , stringlist_iget(args , 1 ) , true); - - enkf_main_smoother_update( enkf_main , source_fs , target_fs); - - enkf_fs_decref( source_fs ); - enkf_fs_decref( target_fs ); - return NULL; -} - diff --git a/ThirdParty/Ert/libenkf/src/enkf_main_manage_fs.c b/ThirdParty/Ert/libenkf/src/enkf_main_manage_fs.c deleted file mode 100644 index e5961ac895..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_main_manage_fs.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_main_manage_fs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - - -/* - This small function is here only to make sure that the main - enkf_main.c file does not contain any explicit mention of the - dbase member. -*/ - -static void enkf_main_init_fs( enkf_main_type * enkf_main ) { - enkf_main->dbase = NULL; -} - - - -bool enkf_main_case_is_current(const enkf_main_type * enkf_main , const char * case_path) { - char * mount_point = enkf_main_alloc_mount_point( enkf_main , case_path ); - const char * current_mount_point = NULL; - bool is_current; - - if (enkf_main->dbase != NULL) - current_mount_point = enkf_fs_get_mount_point( enkf_main->dbase ); - - is_current = util_string_equal( mount_point , current_mount_point ); - free( mount_point ); - return is_current; -} - -static bool enkf_main_current_case_file_exists( const enkf_main_type * enkf_main) { - const char * ens_path = model_config_get_enspath( enkf_main->model_config); - char * current_case_file = util_alloc_filename(ens_path, CURRENT_CASE_FILE, NULL); - bool exists = util_file_exists(current_case_file); - free(current_case_file); - return exists; -} - -char* enkf_main_read_alloc_current_case_name(const enkf_main_type * enkf_main) { - char * current_case = NULL; - const char * ens_path = model_config_get_enspath( enkf_main->model_config); - char * current_case_file = util_alloc_filename(ens_path, CURRENT_CASE_FILE, NULL); - if (enkf_main_current_case_file_exists(enkf_main)) { - FILE * stream = util_fopen( current_case_file , "r"); - current_case = util_fscanf_alloc_token(stream); - util_fclose(stream); - } else { - util_abort("%s: File: storage/current_case not found, aborting! \n",__func__); - } - free(current_case_file); - return current_case; -} - - - - - -stringlist_type * enkf_main_alloc_caselist( const enkf_main_type * enkf_main ) { - stringlist_type * case_list = stringlist_alloc_new( ); - { - const char * ens_path = model_config_get_enspath( enkf_main->model_config ); - DIR * ens_dir = opendir( ens_path ); - if (ens_dir != NULL) { - int ens_fd = dirfd( ens_dir ); - if (ens_fd != -1) { - struct dirent * dp; - do { - dp = readdir( ens_dir ); - if (dp != NULL) { - if (!(util_string_equal( dp->d_name , ".") || util_string_equal(dp->d_name , ".."))) { - if (!util_string_equal( dp->d_name , CURRENT_CASE_FILE)) { - char * full_path = util_alloc_filename( ens_path , dp->d_name , NULL); - if (util_is_directory( full_path )) - stringlist_append_copy( case_list , dp->d_name ); - free( full_path); - } - } - } - } while (dp != NULL); - } - } - closedir( ens_dir ); - } - return case_list; -} - - -void enkf_main_set_case_table( enkf_main_type * enkf_main , const char * case_table_file ) { - model_config_set_case_table( enkf_main->model_config , enkf_main->ens_size , case_table_file ); -} - - - -static void * enkf_main_initialize_from_scratch_mt(void * void_arg) { - arg_pack_type * arg_pack = arg_pack_safe_cast( void_arg ); - enkf_main_type * enkf_main = arg_pack_iget_ptr( arg_pack , 0); - enkf_fs_type * init_fs = arg_pack_iget_ptr( arg_pack , 1); - const stringlist_type * param_list = arg_pack_iget_const_ptr( arg_pack , 2 ); - int iens = arg_pack_iget_int( arg_pack , 3 ); - init_mode_type init_mode = arg_pack_iget_int( arg_pack , 4 ); - enkf_state_type * state = enkf_main_iget_state( enkf_main , iens); - enkf_state_initialize( state , init_fs , param_list , init_mode); - return NULL; -} - -void enkf_main_initialize_from_scratch(enkf_main_type * enkf_main , enkf_fs_type * init_fs , const stringlist_type * param_list ,const bool_vector_type * iens_mask , init_mode_type init_mode) { - int num_cpu = 4; - int ens_size = enkf_main_get_ensemble_size( enkf_main ); - thread_pool_type * tp = thread_pool_alloc( num_cpu , true ); - arg_pack_type ** arg_list = util_calloc( ens_size , sizeof * arg_list ); - int i; - int iens; - - for (iens = 0; iens < ens_size; iens++) { - arg_list[iens] = arg_pack_alloc(); - if (bool_vector_safe_iget(iens_mask , iens)) { - arg_pack_append_ptr( arg_list[iens] , enkf_main ); - arg_pack_append_ptr( arg_list[iens] , init_fs ); - arg_pack_append_const_ptr( arg_list[iens] , param_list ); - arg_pack_append_int( arg_list[iens] , iens ); - arg_pack_append_int( arg_list[iens] , init_mode ); - - thread_pool_add_job( tp , enkf_main_initialize_from_scratch_mt , arg_list[iens]); - } - } - thread_pool_join( tp ); - for (i = 0; i < ens_size; i++){ - arg_pack_free( arg_list[i] ); - } - free( arg_list ); - thread_pool_free( tp ); -} - - - - -static void enkf_main_copy_ensemble( const enkf_main_type * enkf_main, - enkf_fs_type * source_case_fs, - int source_report_step, - enkf_fs_type * target_case_fs, - int target_report_step, - const bool_vector_type * iens_mask, - const char * ranking_key , /* It is OK to supply NULL - but if != NULL it must exist */ - const stringlist_type * node_list) { - - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - state_map_type * target_state_map = enkf_fs_get_state_map(target_case_fs); - - { - int * ranking_permutation; - int inode , src_iens; - - if (ranking_key != NULL) { - ranking_table_type * ranking_table = enkf_main_get_ranking_table( enkf_main ); - ranking_permutation = (int *) ranking_table_get_permutation( ranking_table , ranking_key ); - } else { - ranking_permutation = util_calloc( ens_size , sizeof * ranking_permutation ); - for (src_iens = 0; src_iens < ens_size; src_iens++) - ranking_permutation[src_iens] = src_iens; - } - - for (inode =0; inode < stringlist_get_size( node_list ); inode++) { - enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main_get_ensemble_config(enkf_main) , stringlist_iget( node_list , inode )); - for (src_iens = 0; src_iens < enkf_main_get_ensemble_size( enkf_main ); src_iens++) { - if (bool_vector_safe_iget(iens_mask , src_iens)) { - int target_iens = ranking_permutation[src_iens]; - node_id_type src_id = {.report_step = source_report_step , .iens = src_iens }; - node_id_type target_id = {.report_step = target_report_step , .iens = target_iens }; - - /* The copy is careful ... */ - if (enkf_config_node_has_node( config_node , source_case_fs , src_id)) - enkf_node_copy( config_node , - source_case_fs , target_case_fs , - src_id , target_id ); - - if (0 == target_report_step) - state_map_iset(target_state_map, target_iens, STATE_INITIALIZED); - } - } - } - - if (ranking_permutation == NULL) - free( ranking_permutation ); - } -} - - - -void enkf_main_init_current_case_from_existing(enkf_main_type * enkf_main, - enkf_fs_type * source_case_fs, - int source_report_step) { - - enkf_fs_type * current_fs = enkf_main_get_fs(enkf_main); - - enkf_main_init_case_from_existing(enkf_main, - source_case_fs, - source_report_step, - current_fs); - -} - - -void enkf_main_init_current_case_from_existing_custom(enkf_main_type * enkf_main, - enkf_fs_type * source_case_fs, - int source_report_step, - stringlist_type * node_list, - bool_vector_type * iactive) { - - enkf_fs_type * current_fs = enkf_main_get_fs(enkf_main); - - enkf_main_init_case_from_existing_custom(enkf_main, - source_case_fs, - source_report_step, - current_fs, - node_list, - iactive); - -} - - -void enkf_main_init_case_from_existing(const enkf_main_type * enkf_main, - enkf_fs_type * source_case_fs, - int source_report_step, - enkf_fs_type * target_case_fs ) { - - stringlist_type * param_list = ensemble_config_alloc_keylist_from_var_type( enkf_main_get_ensemble_config(enkf_main) , PARAMETER ); /* Select only paramters - will fail for GEN_DATA of type DYNAMIC_STATE. */ - int target_report_step = 0; - bool_vector_type * iactive = bool_vector_alloc( 0 , true ); - - enkf_main_copy_ensemble(enkf_main, - source_case_fs, - source_report_step, - target_case_fs, - target_report_step, - iactive, - NULL, - param_list); - - - enkf_fs_fsync(target_case_fs); - - bool_vector_free(iactive); - stringlist_free(param_list); -} - - -void enkf_main_init_case_from_existing_custom(const enkf_main_type * enkf_main, - enkf_fs_type * source_case_fs, - int source_report_step, - enkf_fs_type * target_case_fs, - stringlist_type * node_list, - bool_vector_type * iactive) { - - int target_report_step = 0; - - enkf_main_copy_ensemble(enkf_main, - source_case_fs, - source_report_step, - target_case_fs, - target_report_step, - iactive, - NULL, - node_list); - - enkf_fs_fsync(target_case_fs); -} - - - - -/** - This function will go through the filesystem and check that we have - initial data for all parameters and all realizations. If the second - argument mask is different from NULL, the function will only - consider the realizations for which mask is true (if mask == NULL - all realizations will be checked). -*/ - -static bool enkf_main_case_is_initialized__( const enkf_main_type * enkf_main , enkf_fs_type * fs , bool_vector_type * __mask) { - stringlist_type * parameter_keys = ensemble_config_alloc_keylist_from_var_type( enkf_main->ensemble_config , PARAMETER ); - bool_vector_type * mask; - bool initialized = true; - int ikey = 0; - if (__mask != NULL) - mask = __mask; - else - mask = bool_vector_alloc(0 , true ); - - while ((ikey < stringlist_get_size( parameter_keys )) && (initialized)) { - const enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main->ensemble_config , stringlist_iget( parameter_keys , ikey) ); - int iens = 0; - do { - if (bool_vector_safe_iget( mask , iens)) { - node_id_type node_id = {.report_step = 0 , .iens = iens }; - initialized = enkf_config_node_has_node( config_node , fs , node_id); - } - iens++; - } while ((iens < enkf_main->ens_size) && (initialized)); - ikey++; - } - - stringlist_free( parameter_keys ); - if (__mask == NULL) - bool_vector_free( mask ); - return initialized; -} - - - -bool enkf_main_case_is_initialized( const enkf_main_type * enkf_main , const char * case_name , bool_vector_type * __mask) { - enkf_fs_type * fs = enkf_main_mount_alt_fs(enkf_main , case_name , false ); - if (fs) { - bool initialized = enkf_main_case_is_initialized__(enkf_main , fs , __mask); - enkf_fs_decref( fs ); - return initialized; - } else - return false; -} - - - -bool enkf_main_is_initialized( const enkf_main_type * enkf_main , bool_vector_type * __mask) { - return enkf_main_case_is_initialized__(enkf_main , enkf_main->dbase , __mask); -} - - -static void update_case_log(enkf_main_type * enkf_main , const char * case_path) { - /* : Update a small text file with the name of the host currently - running ert, the pid number of the process, the active case - and when it started. - - If the previous shutdown was unclean the file will be around, - and we will need the info from the previous invocation which - is in the file. For that reason we open with mode 'a' instead - of 'w'. - */ - - const char * ens_path = model_config_get_enspath( enkf_main->model_config); - - { - int buffer_size = 256; - char * current_host = util_alloc_filename( ens_path , CASE_LOG , NULL ); - FILE * stream = util_fopen( current_host , "a"); - - fprintf(stream , "CASE:%-16s " , case_path ); - fprintf(stream , "PID:%-8d " , getpid()); - { - char hostname[buffer_size]; - gethostname( hostname , buffer_size ); - fprintf(stream , "HOST:%-16s " , hostname ); - } - - - { - int year,month,day,hour,minute,second; - time_t now = time( NULL ); - - util_set_datetime_values_utc( now , &second , &minute , &hour , &day , &month , &year ); - - fprintf(stream , "TIME:%02d/%02d/%4d-%02d.%02d.%02d\n" , day , month , year , hour , minute , second); - } - fclose( stream ); - free( current_host ); - } -} - - - -static void enkf_main_write_current_case_file( const enkf_main_type * enkf_main, const char * case_path) { - const char * ens_path = model_config_get_enspath( enkf_main->model_config); - const char * base = CURRENT_CASE_FILE; - char * current_case_file = util_alloc_filename(ens_path , base, NULL); - FILE * stream = util_fopen( current_case_file , "w"); - fprintf(stream, "%s", case_path); - util_fclose(stream); - free(current_case_file); -} - - -static void enkf_main_gen_data_special( enkf_main_type * enkf_main , enkf_fs_type * fs ) { - stringlist_type * gen_data_keys = ensemble_config_alloc_keylist_from_impl_type( enkf_main->ensemble_config , GEN_DATA); - for (int i=0; i < stringlist_get_size( gen_data_keys ); i++) { - enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main->ensemble_config , stringlist_iget( gen_data_keys , i)); - gen_data_config_type * gen_data_config = enkf_config_node_get_ref( config_node ); - - if (gen_data_config_is_dynamic( gen_data_config )) - gen_data_config_set_ens_size( gen_data_config , enkf_main->ens_size ); - - } - stringlist_free( gen_data_keys ); -} - - -static void enkf_main_update_current_case( enkf_main_type * enkf_main , const char * case_path /* Can be NULL */) { - if (!case_path) - case_path = enkf_fs_get_case_name( enkf_main_get_fs(enkf_main) ); - - enkf_main_write_current_case_file(enkf_main, case_path); - update_case_log(enkf_main , case_path); - - enkf_main_gen_data_special( enkf_main , enkf_main_get_fs( enkf_main )); - enkf_main_add_subst_kw( enkf_main , "ERT-CASE" , enkf_main_get_current_fs( enkf_main ) , "Current case" , true ); - enkf_main_add_subst_kw( enkf_main , "ERTCASE" , enkf_main_get_current_fs( enkf_main ) , "Current case" , true ); -} - - - -static void enkf_main_create_fs( const enkf_main_type * enkf_main , const char * case_path ) { - char * new_mount_point = enkf_main_alloc_mount_point( enkf_main , case_path ); - - enkf_fs_create_fs( new_mount_point, - model_config_get_dbase_type( enkf_main->model_config ) , - model_config_get_dbase_args( enkf_main->model_config ) , - false ); - - free( new_mount_point ); -} - - -const char * enkf_main_get_mount_root( const enkf_main_type * enkf_main) { - return model_config_get_enspath( enkf_main->model_config); -} - - - -char * enkf_main_alloc_mount_point( const enkf_main_type * enkf_main , const char * case_path) { - char * mount_point; - if (util_is_abs_path( case_path )) - mount_point = util_alloc_string_copy( case_path ); - else - mount_point = util_alloc_filename( model_config_get_enspath( enkf_main->model_config) , case_path , NULL); - return mount_point; -} - -/* - Return a weak reference - i.e. the refcount is not increased. -*/ -enkf_fs_type * enkf_main_get_fs(const enkf_main_type * enkf_main) { - return enkf_main->dbase; -} - -enkf_fs_type * enkf_main_tui_get_fs(const enkf_main_type * enkf_main) { - return enkf_main->dbase; -} - -enkf_fs_type * enkf_main_job_get_fs(const enkf_main_type * enkf_main) { - return enkf_main->dbase; -} - - -enkf_fs_type * enkf_main_get_fs_ref(const enkf_main_type * enkf_main) { - return enkf_fs_get_ref( enkf_main->dbase ); -} - - -const char * enkf_main_get_current_fs( const enkf_main_type * enkf_main ) { - return enkf_fs_get_case_name( enkf_main->dbase ); -} - - - -/* - This function will return a valid enkf_fs instance; either just a - pointer to the current enkf_main->dbase, or alternatively it will - create a brand new fs instance. Because we do not really know whether - a new instance has been created or not resource handling becomes - slightly non trivial: - - - 1. When calling scope is finished with the enkf_fs instance it - must call enkf_fs_decref(); the enkf_fs_decref() function will - close the filesystem and free all resources when the reference - count has reached zero. -*/ - - -enkf_fs_type * enkf_main_mount_alt_fs(const enkf_main_type * enkf_main , const char * case_path , bool create) { - if (enkf_main_case_is_current( enkf_main , case_path )) { - // Fast path - we just return a reference to the currently selected case; - // with increased refcount. - enkf_fs_incref( enkf_main->dbase ); - return enkf_main->dbase; - } else { - // We have asked for an alterantive fs - must mount and possibly create that first. - enkf_fs_type * new_fs = NULL; - if (case_path != NULL) { - char * new_mount_point = enkf_main_alloc_mount_point( enkf_main , case_path ); - - if (!enkf_fs_exists( new_mount_point )) { - if (create) - enkf_main_create_fs( enkf_main , case_path ); - } - - new_fs = enkf_fs_mount( new_mount_point ); - if (new_fs) { - const model_config_type * model_config = enkf_main_get_model_config( enkf_main ); - const ecl_sum_type * refcase = model_config_get_refcase( model_config ); - - if (refcase) { - time_map_type * time_map = enkf_fs_get_time_map( new_fs ); - if (time_map_attach_refcase( time_map , refcase)) - time_map_set_strict( time_map , false ); - else - ert_log_add_fmt_message(1 , stderr , "Warning mismatch between refcase:%s and existing case:%s" , ecl_sum_get_case( refcase ) , new_mount_point); - } - } - - free( new_mount_point ); - } - return new_fs; - } -} - - -static void enkf_main_update_summary_config_from_fs__(enkf_main_type * enkf_main, enkf_fs_type * fs) { - ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - summary_key_set_type * summary_key_set = enkf_fs_get_summary_key_set(fs); - stringlist_type * keys = summary_key_set_alloc_keys(summary_key_set); - - for(int i = 0; i < stringlist_get_size(keys); i++) { - const char * key = stringlist_iget(keys, i); - ensemble_config_add_summary(ensemble_config, key, LOAD_FAIL_SILENT); - } - stringlist_free( keys ); -} - - -static void enkf_main_update_custom_kw_config_from_fs__(enkf_main_type * enkf_main, enkf_fs_type * fs) { - ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - custom_kw_config_set_type * custom_kw_config_set = enkf_fs_get_custom_kw_config_set(fs); - - ensemble_config_update_custom_kw_config(ensemble_config, custom_kw_config_set); -} - - -/** - The enkf_fs instances employ a simple reference counting - scheme. The main point with this system is to avoid opening the - full timesystem more than necessary (this is quite compute - intensive). This is essentially achieved by: - - 1. Create new fs instances by using the function - enkf_main_mount_alt_fs() - depending on the input arguments - this will either create a new enkf_fs instance or it will - just return a pointer to currently open fs instance; with an - increased refcount. - - 2. When you are finished with working with filesystem pointer - call enkf_fs_unmount() - this will reduce the refcount with - one, and eventually discard the complete datastructure when - the refcount has reached zero. - - 3. By using the function enkf_main_get_fs() / - enkf_fs_get_weakref() you get a pointer to the current fs - instance WITHOUT INCREASING THE REFCOUNT. This means that - scope calling one of these functions does not get any - ownership to the enkf_fs instance. - - The enkf_main instance will take ownership of the enkf_fs instance; - this implies that the calling scope must have proper ownership of - the fs instance which is passed in. The return value from - enkf_main_get_fs() can NOT be used as input to this function; this - is not checked for in any way - but the crash will be horrible if - this is not adhered to. -*/ - -void enkf_main_set_fs( enkf_main_type * enkf_main , enkf_fs_type * fs , const char * case_path /* Can be NULL */) { - if (enkf_main->dbase != fs) { - enkf_fs_incref( fs ); - - if (enkf_main->dbase) - enkf_fs_decref(enkf_main->dbase); - - enkf_main->dbase = fs; - enkf_main_update_current_case(enkf_main, case_path); - - enkf_main_update_summary_config_from_fs__(enkf_main, fs); - enkf_main_update_custom_kw_config_from_fs__(enkf_main, fs); - } -} - - - -void enkf_main_select_fs( enkf_main_type * enkf_main , const char * case_path ) { - if (enkf_main_case_is_current( enkf_main , case_path )) - return; /* We have tried to select the currently selected case - just return. */ - else { - enkf_fs_type * new_fs = enkf_main_mount_alt_fs( enkf_main , case_path , true ); - if (enkf_main->dbase == new_fs) - util_abort("%s : return reference to current FS in situation where that should not happen.\n",__func__); - - if (new_fs != NULL) - enkf_main_set_fs( enkf_main , new_fs , case_path); - else { - const char * ens_path = model_config_get_enspath( enkf_main->model_config ); - util_exit("%s: select filesystem %s:%s failed \n",__func__ , ens_path , case_path ); - } - enkf_fs_decref( new_fs ); - } -} - - -static void enkf_main_user_select_initial_fs(enkf_main_type * enkf_main) { - const char * ens_path = model_config_get_enspath( enkf_main->model_config); - int root_version = enkf_fs_get_version104( ens_path ); - if (root_version == -1 || root_version == 105) { - char * current_mount_point = util_alloc_filename( ens_path , CURRENT_CASE , NULL); - - if (enkf_main_current_case_file_exists(enkf_main)) { - char * current_case = enkf_main_read_alloc_current_case_name(enkf_main); - enkf_main_select_fs(enkf_main, current_case); - free (current_case); - } else if (enkf_fs_exists( current_mount_point ) && util_is_link( current_mount_point )) { - /*If the current_case file does not exists, but the 'current' symlink does we use readlink to - get hold of the actual target before calling the enkf_main_select_fs() function. We then - write the current_case file and delete the symlink.*/ - char * target_case = util_alloc_atlink_target( ens_path , CURRENT_CASE ); - enkf_main_select_fs( enkf_main , target_case ); - unlink(current_mount_point); - enkf_main_write_current_case_file(enkf_main, target_case); - free( target_case ); - } else - enkf_main_select_fs( enkf_main , DEFAULT_CASE ); // Selecting (a new) default case - - free( current_mount_point ); - } else { - fprintf(stderr,"Sorry: the filesystem located in %s must be upgraded before the current ERT version can read it.\n" , ens_path); - exit(1); - } -} - - -bool enkf_main_fs_exists(const enkf_main_type * enkf_main, const char * input_case){ - bool exists = false; - char * new_mount_point = enkf_main_alloc_mount_point( enkf_main , input_case); - if(enkf_fs_exists( new_mount_point )) - exists = true; - - free( new_mount_point ); - return exists; -} - - - -state_map_type * enkf_main_alloc_readonly_state_map( const enkf_main_type * enkf_main , const char * case_path) { - char * mount_point = enkf_main_alloc_mount_point( enkf_main , case_path ); - state_map_type * state_map = enkf_fs_alloc_readonly_state_map( mount_point ); - free( mount_point ); - return state_map; -} - - - -time_map_type * enkf_main_alloc_readonly_time_map( const enkf_main_type * enkf_main , const char * case_path ) { - char * mount_point = enkf_main_alloc_mount_point( enkf_main , case_path ); - time_map_type * time_map = enkf_fs_alloc_readonly_time_map( mount_point ); - free( mount_point ); - return time_map; -} - - -void enkf_main_close_fs( enkf_main_type * enkf_main ) { - if (enkf_main->dbase != NULL) - enkf_fs_decref( enkf_main->dbase ); -} - diff --git a/ThirdParty/Ert/libenkf/src/enkf_main_update.c b/ThirdParty/Ert/libenkf/src/enkf_main_update.c deleted file mode 100644 index bff4eb8ee8..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_main_update.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_main_update.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -/** - This file implements functions related to updating the state. The - really low level functions related to the analysis is implemented - in enkf_analysis.h. - - This file only implements code for updating, and not any data - structures. -*/ - -#include "enkf_main_struct.h" - - diff --git a/ThirdParty/Ert/libenkf/src/enkf_node.c b/ThirdParty/Ert/libenkf/src/enkf_node.c deleted file mode 100644 index 38f185ef89..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_node.c +++ /dev/null @@ -1,1077 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_node.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - A small illustration (says more than thousand words ...) of how the - enkf_node, enkf_config_node, field[1] and field_config[1] objects - are linked. - - - ================ - | | o----------- - | ================ | ===================== - | | | o-------- | | - | | ================ |-------------> | | - | | | | | | enkf_config_node | - | | | | | | | - ===| | enkf_node | o------ | | - o | | | | | - | ===| | ===================== - | o | | o - | | ================ | - | | o | - | \ | | - | \ | | - | | | | - | | | | - | | | | - | | | | - \|/ | | | - ======|======|== \|/ - | \|/ | | o----------- - | ==========|===== | ===================== - | | \|/ | o-------- | | - | | ================ |-------------> | | - | | | | | | field_config | - | | | | | | | - ===| | field | o------ | | - | | | | | - === | | ===================== - | | - ================ - - - To summarize in words: - - * The enkf_node object is an abstract object, which again contains - a spesific enkf_object, like e.g. the field objects shown - here. In general we have an ensemble of enkf_node objects. - - * The enkf_node objects contain a pointer to a enkf_config_node - object. - - * The enkf_config_node object contains a pointer to the spesific - config object, i.e. field_config in this case. - - * All the field objects contain a pointer to a field_config object. - - - [1]: field is just an example, and could be replaced with any of - the enkf object types. -*/ - -/*-----------------------------------------------------------------*/ - -/** - A note on memory - ================ - - The enkf_nodes can consume large amounts of memory, and for large - models/ensembles we have a situation where not all the - members/fields can be in memory simultanouesly - such low-memory - situations are not really supported at the moment, but we have - implemented some support for such problems: - - o All enkf objects should have a xxx_realloc_data() function. This - function should be implemented in such a way that it is always - safe to call, i.e. if the object already has allocated data the - function should just return. - - o All enkf objects should implement a xxx_free_data() - function. This function free the data of the object, and set the - data pointer to NULL. - - - The following 'rules' apply to the memory treatment: - ---------------------------------------------------- - - o Functions writing to memory can always be called, and it is their - responsibility to allocate memory before actually writing on it. The - writer functions are: - - enkf_node_initialize() - enkf_node_fread() - enkf_node_forward_load() - - These functions should all start with a call to - enkf_node_ensure_memory(). The (re)allocation of data is done at - the enkf_node level, and **NOT** in the low level object - (altough that is where it is eventually done of course). - - o When it comes to functions reading memory it is a bit more - tricky. It could be that if the functions are called without - memory, that just means that the object is not active or - something (and the function should just return). On the other - hand trying to read a NULL pointer does indicate that program - logic is not fully up to it? And should therefor maybe be - punished? - - o The only memory operation which is exported to 'user-space' - (i.e. the enkf_state object) is enkf_node_free_data(). - -*/ - - -/** - Keeeping track of node state. - ============================= - - To keep track of the state of the node's data (actually the data of - the contained enkf_object, i.e. a field) we have three higly - internal variables __state, __modified , __iens, and - __report_step. These three variables are used/updated in the - following manner: - - - - 1. The nodes are created with (modified, report_step, state, iens) == - (true , -1 , undefined , -1). - - 2. After initialization we set: report_step -> 0 , state -> - analyzed, modified -> true, iens -> -1 - - 3. After load (both from ensemble and ECLIPSE). We set modified -> - false, and report_step, state and iens according to the load - arguments. - - 4. After deserialize (i.e. update) we set modified -> true. - - 5. After write (to ensemble) we set in the same way as after load. - - 6. After free_data we invalidate according to the newly allocated - status. - - 7. In the ens_load routine we check if modified == false and the - report_step and state arguments agree with the current - values. IN THAT CASE WE JUST RETURN WITHOUT ACTUALLY HITTING - THE FILESYSTEM. This performance gain is the main point of the - whole excercise. -*/ - - - -#define ENKF_NODE_TYPE_ID 71043086 - -struct enkf_node_struct { - UTIL_TYPE_ID_DECLARATION; - alloc_ftype * alloc; - ecl_write_ftype * ecl_write; - forward_load_ftype * forward_load; - forward_load_vector_ftype * forward_load_vector; - free_data_ftype * free_data; - user_get_ftype * user_get; - user_get_vector_ftype * user_get_vector; - set_inflation_ftype * set_inflation; - fload_ftype * fload; - has_data_ftype * has_data; - - serialize_ftype * serialize; - deserialize_ftype * deserialize; - read_from_buffer_ftype * read_from_buffer; - write_to_buffer_ftype * write_to_buffer; - initialize_ftype * initialize; - node_free_ftype * freef; - clear_ftype * clear; - node_copy_ftype * copy; - scale_ftype * scale; - iadd_ftype * iadd; - imul_ftype * imul; - isqrt_ftype * isqrt; - iaddsqr_ftype * iaddsqr; - - /******************************************************************/ - bool vector_storage; - char *node_key; /* The (hash)key this node is identified with. */ - void *data; /* A pointer to the underlying enkf_object, i.e. gen_kw_type instance, or a field_type instance or ... */ - const enkf_config_node_type *config; /* A pointer to a enkf_config_node instance (which again cointans a pointer to the config object of data). */ - /*****************************************************************/ - - vector_type *container_nodes; -}; - - -const enkf_config_node_type * enkf_node_get_config(const enkf_node_type * node) { - return node->config; -} - - -bool enkf_node_vector_storage( const enkf_node_type * node ) { - return node->vector_storage; -} - -static UTIL_IS_INSTANCE_FUNCTION( enkf_node , ENKF_NODE_TYPE_ID ) - - -/*****************************************************************/ - -/* - All the function pointers REALLY should be in the config object ... -*/ - - -#define FUNC_ASSERT(func) if (func == NULL) util_abort("%s: function handler: %s not registered for node:%s - aborting\n",__func__ , #func , enkf_node->node_key); - - - - -void enkf_node_alloc_domain_object(enkf_node_type * node) { - if (node->data != NULL) - node->freef( node->data ); - node->data = node->alloc(enkf_config_node_get_ref(node->config)); -} - - - - -enkf_node_type * enkf_node_copyc(const enkf_node_type * enkf_node) { - FUNC_ASSERT(enkf_node->copy); - { - const enkf_node_type * src = enkf_node; - enkf_node_type * target; - target = enkf_node_alloc(src->config); - src->copy( src->data , target->data ); /* Calling the low level copy function */ - return target; - } -} - - - -bool enkf_node_include_type(const enkf_node_type * enkf_node, int mask) { - return enkf_config_node_include_type(enkf_node->config , mask); -} - - -ert_impl_type enkf_node_get_impl_type(const enkf_node_type * enkf_node) { - return enkf_config_node_get_impl_type(enkf_node->config); -} - - -enkf_var_type enkf_node_get_var_type(const enkf_node_type * enkf_node) { - return enkf_config_node_get_var_type(enkf_node->config); -} - -bool enkf_node_use_forward_init( const enkf_node_type * enkf_node ) { - return enkf_config_node_use_forward_init( enkf_node->config ); -} - - - -void * enkf_node_value_ptr(const enkf_node_type * enkf_node) { - return enkf_node->data; -} - - - -/** - This function calls the node spesific ecl_write function. IF the - ecl_file of the (node == NULL) *ONLY* the path is sent to the node - spesific file. -*/ - -void enkf_node_ecl_write(const enkf_node_type *enkf_node , const char *path , void * filestream , int report_step) { - if (enkf_node->ecl_write != NULL) { - char * node_eclfile = enkf_config_node_alloc_outfile(enkf_node->config , report_step); /* Will return NULL if the node does not have any outfile format. */ - /* - If the node does not have a outfile (i.e. ecl_file), the - ecl_write function will be called with file argument NULL. It - is then the responsability of the low-level implementation to - do "the right thing". - */ - enkf_node->ecl_write(enkf_node->data , path , node_eclfile , filestream); - util_safe_free( node_eclfile ); - } -} - - - -/** - This function takes a string - key - as input an calls a node - specific function to look up one scalar based on that key. The key - is always a string, but the the type of content will vary for the - different objects. For a field, the key will be a string of "i,j,k" - for a cell. - - If the user has asked for something which does not exist the - function SHOULD NOT FAIL; it should return false and set the *value - to 0. -*/ - - -bool enkf_node_user_get(enkf_node_type * enkf_node , enkf_fs_type * fs , const char * key , node_id_type node_id , double * value) { - return enkf_node_user_get_no_id( enkf_node , fs , key , node_id.report_step , node_id.iens , value ); -} - -bool enkf_node_user_get_no_id(enkf_node_type * enkf_node , enkf_fs_type * fs , const char * key , int report_step, int iens, double * value) { - node_id_type node_id = {.report_step = report_step , .iens = iens}; - bool loadOK; - FUNC_ASSERT( enkf_node->user_get ); - { - loadOK = enkf_node_try_load( enkf_node , fs , node_id); - - if (loadOK) - return enkf_node->user_get(enkf_node->data , key , report_step, value); - else { - *value = 0; - return false; - } - } -} - -bool enkf_node_user_get_vector( enkf_node_type * enkf_node , enkf_fs_type * fs , const char * key , int iens , double_vector_type * values) { - if (enkf_node->vector_storage) { - if (enkf_node_try_load_vector( enkf_node , fs , iens )) { - enkf_node->user_get_vector( enkf_node->data , key , values); - return true; - } else - return false; - } else { - util_abort("%s: internal error - function should only be called by nodes with vector storage.\n",__func__); - return false; - } -} - - - -bool enkf_node_fload( enkf_node_type * enkf_node , const char * filename ) { - FUNC_ASSERT( enkf_node->fload ); - return enkf_node->fload( enkf_node->data , filename ); -} - - - -/** - This function loads (internalizes) ECLIPSE results, the ecl_file - instance with restart data, and the ecl_sum instance with summary - data must already be loaded by the calling function. - - IFF the enkf_node has registered a filename to load from, that is - passed to the specific load function, otherwise the run_path is sent - to the load function. - - If the node does not have a forward_load function, the function just - returns. -*/ - - -bool enkf_node_forward_load(enkf_node_type *enkf_node , const forward_load_context_type * load_context) { - bool loadOK; - FUNC_ASSERT(enkf_node->forward_load); - { - if (enkf_node_get_impl_type(enkf_node) == SUMMARY) - /* Fast path for loading summary data. */ - loadOK = enkf_node->forward_load(enkf_node->data , NULL , load_context); - else { - char * input_file = enkf_config_node_alloc_infile(enkf_node->config , forward_load_context_get_load_step( load_context )); - - if (input_file != NULL) { - char * file = util_alloc_filename( forward_load_context_get_run_path( load_context ) , input_file , NULL); - loadOK = enkf_node->forward_load(enkf_node->data , file , load_context); - free(file); - } else - loadOK = enkf_node->forward_load(enkf_node->data , NULL , load_context); - - util_safe_free( input_file ); - } - } - return loadOK; -} - - -bool enkf_node_forward_init(enkf_node_type * enkf_node , const char * run_path , int iens) { - char * init_file = enkf_config_node_alloc_initfile( enkf_node->config , run_path , iens ); - bool init = enkf_node->initialize(enkf_node->data , iens , init_file, NULL); - util_safe_free( init_file ); - return init; -} - - - -bool enkf_node_forward_load_vector(enkf_node_type *enkf_node , const forward_load_context_type * load_context , const int_vector_type * time_index) { - bool loadOK; - FUNC_ASSERT(enkf_node->forward_load_vector); - loadOK = enkf_node->forward_load_vector(enkf_node->data , NULL , load_context , time_index); - - return loadOK; -} - - - - - - -/** - This function compares the internal __report_step with the input - report_step, and return true if they are equal. It is used in the - calling scope to discard static nodes which are no longer in use. -*/ - - - -static bool enkf_node_store_buffer( enkf_node_type * enkf_node , enkf_fs_type * fs , int report_step , int iens) { - FUNC_ASSERT(enkf_node->write_to_buffer); - { - bool data_written; - buffer_type * buffer = buffer_alloc( 100 ); - const enkf_config_node_type * config_node = enkf_node_get_config( enkf_node ); - buffer_fwrite_time_t( buffer , time(NULL)); - data_written = enkf_node->write_to_buffer(enkf_node->data , buffer , report_step ); - if (data_written) { - const char * node_key = enkf_config_node_get_key( config_node ); - enkf_var_type var_type = enkf_config_node_get_var_type( config_node ); - - if (enkf_node->vector_storage) - enkf_fs_fwrite_vector( fs , buffer , node_key , var_type , iens ); - else - enkf_fs_fwrite_node( fs , buffer , node_key , var_type , report_step , iens ); - - } - buffer_free( buffer ); - return data_written; - } -} - -bool enkf_node_store_vector(enkf_node_type *enkf_node , enkf_fs_type * fs , int iens ) { - return enkf_node_store_buffer( enkf_node , fs , -1 , iens ); -} - - - -bool enkf_node_store(enkf_node_type * enkf_node , enkf_fs_type * fs , bool force_vectors , node_id_type node_id) { - if (enkf_node->vector_storage) { - if (force_vectors) - return enkf_node_store_vector( enkf_node , fs , node_id.iens ); - else - return false; - } else { - if (node_id.report_step == 0) { - ert_impl_type impl_type = enkf_node_get_impl_type(enkf_node); - if (impl_type == SUMMARY) - return false; /* For report step == 0 the summary data is just garbage. */ - } - - return enkf_node_store_buffer( enkf_node , fs , node_id.report_step , node_id.iens ); - } -} - - - -/** - This function will load a node from the filesystem if it is - available; if not it will just return false. - - The state argument can be 'both' - in which case it will first try - the analyzed, and then subsequently the forecast before giving up - and returning false. If the function returns true with state == - 'both' it is no way to determine which version was actually loaded. -*/ - -bool enkf_node_try_load(enkf_node_type *enkf_node , enkf_fs_type * fs , node_id_type node_id) { - if (enkf_node_has_data( enkf_node , fs , node_id)) { - enkf_node_load( enkf_node , fs , node_id); - return true; - } else - return false; -} - - -static void enkf_node_buffer_load( enkf_node_type * enkf_node , enkf_fs_type * fs , int report_step , int iens) { - FUNC_ASSERT(enkf_node->read_from_buffer); - { - buffer_type * buffer = buffer_alloc( 100 ); - const enkf_config_node_type * config_node = enkf_node_get_config( enkf_node ); - const char * node_key = enkf_config_node_get_key( config_node ); - enkf_var_type var_type = enkf_config_node_get_var_type( config_node ); - - if (enkf_node->vector_storage) - enkf_fs_fread_vector( fs , buffer , node_key , var_type , iens ); - else - enkf_fs_fread_node( fs , buffer , node_key , var_type , report_step , iens ); - - buffer_fskip_time_t( buffer ); - enkf_node->read_from_buffer(enkf_node->data , buffer , fs , report_step ); - buffer_free( buffer ); - } -} - - - - -void enkf_node_load_vector( enkf_node_type * enkf_node , enkf_fs_type * fs , int iens ) { - enkf_node_buffer_load( enkf_node , fs , -1 , iens ); -} - - - -static void enkf_node_load_container( enkf_node_type * enkf_node , enkf_fs_type * fs , node_id_type node_id ) { - for (int inode=0; inode < vector_get_size( enkf_node->container_nodes ); inode++) { - enkf_node_type * child_node = vector_iget( enkf_node->container_nodes , inode ); - enkf_node_load( child_node , fs , node_id ); - } -} - - -void enkf_node_load(enkf_node_type * enkf_node , enkf_fs_type * fs , node_id_type node_id) { - if (enkf_node_get_impl_type(enkf_node) == CONTAINER) - enkf_node_load_container( enkf_node , fs , node_id ); - else { - if (enkf_node->vector_storage) - enkf_node_load_vector( enkf_node , fs , node_id.iens ); - else - /* Normal load path */ - enkf_node_buffer_load( enkf_node , fs , node_id.report_step, node_id.iens ); - } -} - - -bool enkf_node_try_load_vector(enkf_node_type *enkf_node , enkf_fs_type * fs , int iens ) { - if (enkf_config_node_has_vector( enkf_node->config , fs , iens)) { - enkf_node_load_vector( enkf_node , fs , iens ); - return true; - } else - return false; -} - - - - - -/* - In the case of nodes with vector storage this function - will load the entire vector. -*/ - -enkf_node_type * enkf_node_load_alloc( const enkf_config_node_type * config_node , enkf_fs_type * fs , node_id_type node_id) { - if (enkf_config_node_vector_storage( config_node )) { - if (enkf_config_node_has_vector( config_node , fs , node_id.iens)) { - enkf_node_type * node = enkf_node_alloc( config_node ); - enkf_node_load( node , fs , node_id ); - return node; - } else { - util_abort("%s: could not load vector:%s from iens:%d\n",__func__ , enkf_config_node_get_key( config_node ), - node_id.iens ); - return NULL; - } - } else { - if (enkf_config_node_has_node( config_node , fs , node_id)) { - enkf_node_type * node = enkf_node_alloc( config_node ); - enkf_node_load( node , fs , node_id ); - return node; - } else { - util_abort("%s: Could not load node: key:%s iens:%d report:%d \n", - __func__ , - enkf_config_node_get_key( config_node ) , - node_id.iens , node_id.report_step ); - return NULL; - } - } -} - - - -void enkf_node_copy(const enkf_config_node_type * config_node , - enkf_fs_type * src_case, - enkf_fs_type * target_case, - node_id_type src_id , - node_id_type target_id) { - - enkf_node_type * enkf_node = enkf_node_load_alloc(config_node, src_case , src_id); - - - /* Hack to ensure that size is set for the gen_data instances. - This sneeks low level stuff into a high level scope. BAD. */ - { - ert_impl_type impl_type = enkf_node_get_impl_type( enkf_node ); - if (impl_type == GEN_DATA) { - /* Read the size at report_step_from */ - gen_data_type * gen_data = enkf_node_value_ptr( enkf_node ); - int size = gen_data_get_size( gen_data ); - - /* Enforce the size at report_step_to */ - gen_data_assert_size( gen_data , size , target_id.report_step); - } - } - - enkf_node_store(enkf_node, target_case , true , target_id ); - enkf_node_free(enkf_node); -} - -bool enkf_node_has_data( enkf_node_type * enkf_node , enkf_fs_type * fs , node_id_type node_id) { - if (enkf_node->vector_storage) { - FUNC_ASSERT(enkf_node->has_data); - { - int report_step = node_id.report_step; - int iens = node_id.iens; - - // Try to load the vector. - if (enkf_config_node_has_vector( enkf_node->config , fs , iens )) { - enkf_node_load_vector( enkf_node , fs , iens); - - // The vector is loaded. Check if we have the report_step/state asked for: - return enkf_node->has_data( enkf_node->data , report_step ); - } else - return false; - } - } else - return enkf_config_node_has_node( enkf_node->config , fs , node_id ); -} - - -/** - Copy an ensemble of nodes. Note that the limits are inclusive. -*/ - -void enkf_node_copy_ensemble(const enkf_config_node_type * config_node , - enkf_fs_type * src_case , - enkf_fs_type * target_case , - int report_step_from, /* src state */ - int report_step_to , /* target state */ - int ens_size, - const perm_vector_type * permutations) { - - node_id_type src_id = {.report_step = report_step_from , .iens = 0 }; - node_id_type target_id = {.report_step = report_step_to , .iens = 0 }; - - for(int iens_from = 0; iens_from < ens_size; iens_from++) { - int iens_to; - if (permutations == NULL) - iens_to = iens_from; - else - iens_to = perm_vector_iget(permutations, iens_from); - - src_id.iens = iens_from; - target_id.iens = iens_to; - - enkf_node_copy(config_node , src_case , target_case , src_id , target_id ); - } -} - - - -enkf_node_type ** enkf_node_load_alloc_ensemble( const enkf_config_node_type * config_node , enkf_fs_type * fs , - int report_step , int iens1 , int iens2) { - enkf_node_type ** ensemble = util_calloc( (iens2 - iens1) , sizeof * ensemble ); - for (int iens = iens1; iens < iens2; iens++) { - node_id_type node_id = {.report_step = report_step , .iens = iens }; - ensemble[iens - iens1] = NULL; - ensemble[iens - iens1] = enkf_node_load_alloc(config_node , fs , node_id); - } - - return ensemble; -} - - - - -void enkf_node_serialize(enkf_node_type *enkf_node , enkf_fs_type * fs, node_id_type node_id , - const active_list_type * active_list , matrix_type * A , int row_offset , int column) { - - FUNC_ASSERT(enkf_node->serialize); - enkf_node_load( enkf_node , fs , node_id); - enkf_node->serialize(enkf_node->data , node_id , active_list , A , row_offset , column); - -} - - - -void enkf_node_deserialize(enkf_node_type *enkf_node , enkf_fs_type * fs , node_id_type node_id, - const active_list_type * active_list , const matrix_type * A , int row_offset , int column) { - - FUNC_ASSERT(enkf_node->deserialize); - enkf_node->deserialize(enkf_node->data , node_id , active_list , A , row_offset , column); - enkf_node_store( enkf_node , fs , true , node_id ); -} - - - -void enkf_node_set_inflation( enkf_node_type * inflation , const enkf_node_type * std , const enkf_node_type * min_std) { - { - enkf_node_type * enkf_node = inflation; - FUNC_ASSERT(enkf_node->set_inflation); - } - inflation->set_inflation( inflation->data , std->data , min_std->data ); -} - - -void enkf_node_sqrt(enkf_node_type *enkf_node) { - FUNC_ASSERT(enkf_node->isqrt); - enkf_node->isqrt(enkf_node->data); -} - - -void enkf_node_scale(enkf_node_type *enkf_node , double scale_factor) { - FUNC_ASSERT(enkf_node->scale); - enkf_node->scale(enkf_node->data , scale_factor); -} - - -void enkf_node_iadd(enkf_node_type *enkf_node , const enkf_node_type * delta_node) { - FUNC_ASSERT(enkf_node->iadd); - enkf_node->iadd(enkf_node->data , delta_node->data); -} - - -void enkf_node_iaddsqr(enkf_node_type *enkf_node , const enkf_node_type * delta_node) { - FUNC_ASSERT(enkf_node->iaddsqr); - enkf_node->iaddsqr(enkf_node->data , delta_node->data); -} - - -void enkf_node_imul(enkf_node_type *enkf_node , const enkf_node_type * delta_node) { - FUNC_ASSERT(enkf_node->imul); - enkf_node->imul(enkf_node->data , delta_node->data); -} - - - -/** - The return value is whether any initialization has actually taken - place. If the function returns false it is for instance not - necessary to internalize anything. -*/ - -bool enkf_node_initialize(enkf_node_type *enkf_node, int iens , rng_type * rng) { - if (enkf_node_use_forward_init( enkf_node )) - return false; // This node will be initialized by loading results from the forward model. - else { - if (enkf_node->initialize != NULL) { - char * init_file = enkf_config_node_alloc_initfile( enkf_node->config , NULL , iens ); - bool init = enkf_node->initialize(enkf_node->data , iens , init_file, rng); - util_safe_free( init_file ); - return init; - } else - return false; /* No init performed */ - } -} - - - - -void enkf_node_clear(enkf_node_type *enkf_node) { - FUNC_ASSERT(enkf_node->clear); - enkf_node->clear(enkf_node->data); -} - - -void enkf_node_free(enkf_node_type *enkf_node) { - if (enkf_node->freef != NULL) - enkf_node->freef(enkf_node->data); - free(enkf_node->node_key); - vector_free(enkf_node->container_nodes); - free(enkf_node); -} - - -void enkf_node_free__(void *void_node) { - enkf_node_free((enkf_node_type *) void_node); -} - -const char * enkf_node_get_key(const enkf_node_type * enkf_node) { - return enkf_node->node_key; -} - - -#undef FUNC_ASSERT - - - -/*****************************************************************/ - - - -/* Manual inheritance - .... */ -static enkf_node_type * enkf_node_alloc_empty(const enkf_config_node_type *config ) { - const char *node_key = enkf_config_node_get_key(config); - ert_impl_type impl_type = enkf_config_node_get_impl_type(config); - enkf_node_type * node = util_malloc(sizeof * node ); - node->vector_storage = enkf_config_node_vector_storage( config ); - node->config = config; - node->node_key = util_alloc_string_copy(node_key); - node->data = NULL; - node->container_nodes = vector_alloc_new( ); - - /* - Start by initializing all function pointers to NULL. - */ - node->alloc = NULL; - node->ecl_write = NULL; - node->forward_load = NULL; - node->forward_load_vector = NULL; - node->copy = NULL; - node->initialize = NULL; - node->freef = NULL; - node->free_data = NULL; - node->user_get = NULL; - node->user_get_vector = NULL; - node->fload = NULL; - node->read_from_buffer = NULL; - node->write_to_buffer = NULL; - node->serialize = NULL; - node->deserialize = NULL; - node->clear = NULL; - node->set_inflation = NULL; - node->has_data = NULL; - - /* Math operations: */ - node->iadd = NULL; - node->scale = NULL; - node->isqrt = NULL; - node->iaddsqr = NULL; - node->imul = NULL; - - switch (impl_type) { - case(CONTAINER): - node->alloc = container_alloc__; - node->freef = container_free__; - break; - case(GEN_KW): - node->alloc = gen_kw_alloc__; - node->ecl_write = gen_kw_ecl_write__; - node->copy = gen_kw_copy__; - node->initialize = gen_kw_initialize__; - node->freef = gen_kw_free__; - node->user_get = gen_kw_user_get__; - node->write_to_buffer = gen_kw_write_to_buffer__; - node->read_from_buffer = gen_kw_read_from_buffer__; - node->serialize = gen_kw_serialize__; - node->deserialize = gen_kw_deserialize__; - node->clear = gen_kw_clear__; - node->iadd = gen_kw_iadd__; - node->scale = gen_kw_scale__; - node->iaddsqr = gen_kw_iaddsqr__; - node->imul = gen_kw_imul__; - node->isqrt = gen_kw_isqrt__; - node->set_inflation = gen_kw_set_inflation__; - node->fload = gen_kw_fload__; - break; - case(CUSTOM_KW): - node->alloc = custom_kw_alloc__; - node->freef = custom_kw_free__; - node->forward_load = custom_kw_forward_load__; - node->fload = custom_kw_fload__; - node->ecl_write = custom_kw_ecl_write__; - node->write_to_buffer = custom_kw_write_to_buffer__; - node->read_from_buffer = custom_kw_read_from_buffer__; - node->serialize = custom_kw_serialize__; - node->deserialize = custom_kw_deserialize__; - break; - case(SUMMARY): - node->forward_load = summary_forward_load__; - node->forward_load_vector = summary_forward_load_vector__; - node->alloc = summary_alloc__; - node->copy = summary_copy__; - node->freef = summary_free__; - node->user_get = summary_user_get__; - node->user_get_vector = summary_user_get_vector__; - node->read_from_buffer = summary_read_from_buffer__; - node->write_to_buffer = summary_write_to_buffer__; - node->serialize = summary_serialize__; - node->deserialize = summary_deserialize__; - node->clear = summary_clear__; - node->has_data = summary_has_data__; - /* - node->iadd = summary_iadd__; - node->scale = summary_scale__; - node->iaddsqr = summary_iaddsqr__; - node->imul = summary_imul__; - node->isqrt = summary_isqrt__; - */ - break; - case(SURFACE): - node->initialize = surface_initialize__; - node->ecl_write = surface_ecl_write__; - node->alloc = surface_alloc__; - node->copy = surface_copy__; - node->freef = surface_free__; - node->user_get = surface_user_get__; - node->read_from_buffer = surface_read_from_buffer__; - node->write_to_buffer = surface_write_to_buffer__; - node->serialize = surface_serialize__; - node->deserialize = surface_deserialize__; - node->clear = surface_clear__; - node->iadd = surface_iadd__; - node->scale = surface_scale__; - node->iaddsqr = surface_iaddsqr__; - node->imul = surface_imul__; - node->isqrt = surface_isqrt__; - node->fload = surface_fload__; - break; - case(FIELD): - node->alloc = field_alloc__; - node->ecl_write = field_ecl_write__; - node->forward_load = field_forward_load__; - node->copy = field_copy__; - node->initialize = field_initialize__; - node->freef = field_free__; - node->user_get = field_user_get__; - node->read_from_buffer = field_read_from_buffer__; - node->write_to_buffer = field_write_to_buffer__; - node->serialize = field_serialize__; - node->deserialize = field_deserialize__; - - node->clear = field_clear__; - node->set_inflation = field_set_inflation__; - node->iadd = field_iadd__; - node->scale = field_scale__; - node->iaddsqr = field_iaddsqr__; - node->imul = field_imul__; - node->isqrt = field_isqrt__; - node->fload = field_fload__; - break; - case(GEN_DATA): - node->alloc = gen_data_alloc__; - node->initialize = gen_data_initialize__; - node->copy = gen_data_copy__; - node->freef = gen_data_free__; - node->ecl_write = gen_data_ecl_write__; - node->forward_load = gen_data_forward_load__; - node->user_get = gen_data_user_get__; - node->read_from_buffer = gen_data_read_from_buffer__; - node->write_to_buffer = gen_data_write_to_buffer__; - node->serialize = gen_data_serialize__; - node->deserialize = gen_data_deserialize__; - node->set_inflation = gen_data_set_inflation__; - - node->clear = gen_data_clear__; - node->iadd = gen_data_iadd__; - node->scale = gen_data_scale__; - node->iaddsqr = gen_data_iaddsqr__; - node->imul = gen_data_imul__; - node->isqrt = gen_data_isqrt__; - //node->fload = gen_data_fload__; - break; - default: - util_abort("%s: implementation type: %d unknown - all hell is loose - aborting \n",__func__ , impl_type); - } - return node; -} - - - -#define CASE_SET(type , func) case(type): has_func = (func != NULL); break; -bool enkf_node_has_func(const enkf_node_type * node , node_function_type function_type) { - bool has_func = false; - switch (function_type) { - CASE_SET(alloc_func , node->alloc); - CASE_SET(ecl_write_func , node->ecl_write); - CASE_SET(forward_load_func , node->forward_load); - CASE_SET(copy_func , node->copy); - CASE_SET(initialize_func , node->initialize); - CASE_SET(free_func , node->freef); - default: - fprintf(stderr,"%s: node_function_identifier: %d not recognized - aborting \n",__func__ , function_type); - } - return has_func; -} -#undef CASE_SET - - - - -enkf_node_type * enkf_node_alloc(const enkf_config_node_type * config) { - enkf_node_type * node = enkf_node_alloc_empty(config); - UTIL_TYPE_ID_INIT( node , ENKF_NODE_TYPE_ID ); - enkf_node_alloc_domain_object(node); - return node; -} - - - - - -static void enkf_node_container_add_node( enkf_node_type * node , const enkf_node_type * child_node , bool shared) { - if (shared) - vector_append_ref( node->container_nodes , child_node ); - else - vector_append_owned_ref( node->container_nodes , child_node, enkf_node_free__ ); -} - -static enkf_node_type * enkf_node_alloc_container(const enkf_config_node_type * config, hash_type * node_hash , bool shared) { - enkf_node_type * container_node = enkf_node_alloc( config ); - { - for (int i=0; i < enkf_config_node_container_size( config ); i++) { - const enkf_config_node_type * child_config = enkf_config_node_container_iget( config , i ); - enkf_node_type * child_node; - - if (shared) - child_node = hash_get( node_hash , enkf_config_node_get_key( child_config )); - else - child_node = enkf_node_alloc( child_config ); - - enkf_node_container_add_node( container_node , child_node , shared); - container_add_node( enkf_node_value_ptr( container_node ) , enkf_node_value_ptr( child_node )); - } - } - return container_node; -} - -enkf_node_type * enkf_node_alloc_shared_container(const enkf_config_node_type * config, hash_type * node_hash) { - return enkf_node_alloc_container( config , node_hash , true ); -} - - -enkf_node_type * enkf_node_alloc_private_container(const enkf_config_node_type * config) { - return enkf_node_alloc_container( config , NULL , false ); -} - -enkf_node_type * enkf_node_deep_alloc(const enkf_config_node_type * config) { - if (enkf_config_node_get_impl_type( config ) == CONTAINER) { - enkf_node_type * container = enkf_node_alloc_container( config , NULL , false ); - container_assert_size( enkf_node_value_ptr( container )); - return container; - } else - return enkf_node_alloc( config ); -} - - - -bool enkf_node_internalize(const enkf_node_type * node, int report_step) { - return enkf_config_node_internalize( node->config , report_step ); -} - - -/*****************************************************************/ - - -ecl_write_ftype * enkf_node_get_func_pointer( const enkf_node_type * node ) { - return node->ecl_write; -} diff --git a/ThirdParty/Ert/libenkf/src/enkf_obs.c b/ThirdParty/Ert/libenkf/src/enkf_obs.c deleted file mode 100644 index 43fa6e60ad..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_obs.c +++ /dev/null @@ -1,1270 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_obs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - -The observation system ----------------------- - -The observation system in the EnKF code is a three layer system. At -the the top is the enkf_obs_type. The enkf_main object contains one -enkf_obs instance which has internalized ALL the observation data. In -enkf_obs the the data is internalized in a hash table, where the keys -in the table are the keys used the observation file. - -The next level is the obs_vector type which is a vector of length -num_report_steps. Each element in this vector can either point a -spesific observation instance (which actually contains the data), or -be NULL, if the observation is not active at this report step. In -addition the obs_vector contains function pointers to manipulate the -observation data at the lowest level. - -At the lowest level we have specific observation instances, -field_obs, summary_obs and gen_obs. These instances contain the actual -data. - -To summarize we can say: - - 1. enkf_obs has ALL the observation data. - - 2. obs_vector has the full time series for one observation key, - i.e. all the watercuts in well P2. - - 3. field_obs/gen_obs/summary_obs instances contain the actual - observed data for one (logical) observation and one report step. - - -In the following example we have two observations - - WWCT:OP1 The water cut in well OP1. This is an observation which is - active for many report steps, at the lowest level it is - implemented as summary_obs. - - RFT_P2 This is an RFT test for one well. Only active at one report - step, implemented at the lowest level as a field_obs instance. - - - In the example below there are in total five report steps, hence all - the obs_vector instances have five 'slots'. If there is no active - observation for a particular report step, the corresponding pointer - in the obs_vector instance is NULL. - - - - _____________________ _____________________ - / enkf_obs \ - | | - | | - | obs_hash: {"WWCT:OP1" , "RFT_P2"} | - | | | | - | | | | - \________________|___________|________________________/ - | | - | | - | | - | \--------------------------------------------------------------\ - | | - | | - \|/ | - |--- obs_vector: WWCT:OP1 -----------------------------------------------------| | - | Function pointers: -------- -------- -------- -------- -------- | | - | Pointing to the | | | | | | | | | | | | - | underlying | NULL | | X | | X | | NULL | | X | | | - | implementation in the | | | | | | | | | | | | | | | - | summary_obs object. -------- ---|---- ---|---- -------- ---|---- | | - |---------------------------------------|---------|-------------------|--------| | - | | | | - \|/ | | | - |-- summary_obs -| | \|/ | - | Value: 0.56.. | | |-- summary_obs -| | - | std : 0.15.. | | | Value: 0.70.. | | - |----------------| | | std : 0.25.. | | - | |----------------| | - \|/ | - |-- summary_obs -| | - | Value: 0.62.. | | - | std : 0.12.. | | - |----------------| | - | - | - | - The observation WWCT:OP1 is an observation of summary type, and the | - obs_vector contains pointers to summary_obs instances; along with | - function pointers to manipulate the summary_obs instances. The | - observation is not active for report steps 0 and 3, so for these | - report steps the obse vector has a NULL pointer. | - | - | - | - | - | - | - |--- obs_vector: RFT_P2 -------------------------------------------------------| | - | Function pointers: -------- -------- -------- -------- -------- | | - | Pointing to the | | | | | | | | | | |<---------------/ - | underlying | NULL | | NULL | | NULL | | X | | NULL | | - | implementation in the | | | | | | | | | | | | - | field_obs object. -------- -------- -------- ---|---- -------- | - |-----------------------------------------------------------|------------------| - | - | - \|/ - |-- field_obs -----------------------------------| - | i = 25 , j = 16, k = 10, value = 278, std = 10 | - | i = 25 , j = 16, k = 11, value = 279, std = 10 | - | i = 25 , j = 16, k = 12, value = 279, std = 10 | - | i = 25 , j = 17, k = 12, value = 281, std = 10 | - | i = 25 , j = 18, k = 12, value = 282, std = 10 | - |------------------------------------------------| - - - The observation RFT_P2 is an RFT observation which is only active at - one report step, i.e. 4/5 pointers in the obs_vector are just NULL - pointers. The actual observation(s) are stored in a field_obs - instance. - - */ - - -/** -TODO - - This static function header shall be removed when the - configuration is unified.... -*/ -static conf_class_type * enkf_obs_get_obs_conf_class(); - - - -////////////////////////////////////////////////////////////////////////////////////// - - -#define ENKF_OBS_TYPE_ID 637297 -struct enkf_obs_struct { - UTIL_TYPE_ID_DECLARATION; - /** A hash of obs_vector_types indexed by user provided keys. */ - vector_type * obs_vector; - hash_type * obs_hash; - time_map_type * obs_time; /* For fast lookup of report_step -> obs_time */ - - bool valid; - /* Several shared resources - can generally be NULL*/ - const history_type * history; /* A shared (not owned by enkf_obs) reference to the history object - used when - adding HISTORY observations. */ - const ecl_sum_type * refcase; - const ecl_grid_type * grid; - time_map_type * external_time_map; - ensemble_config_type * ensemble_config; -}; - - - - -////////////////////////////////////////////////////////////////////////////////////// - - -static void enkf_obs_iset_obs_time(enkf_obs_type * enkf_obs , int report_step, time_t obs_time) { - time_map_update( enkf_obs->obs_time , report_step , obs_time); -} - - -static int enkf_obs_get_last_restart( const enkf_obs_type * enkf_obs ) { - return time_map_get_size( enkf_obs->obs_time ) - 1; -} - -UTIL_IS_INSTANCE_FUNCTION( enkf_obs , ENKF_OBS_TYPE_ID ) - -enkf_obs_type * enkf_obs_alloc( const history_type * history , - time_map_type * external_time_map , - const ecl_grid_type * grid , - const ecl_sum_type * refcase, - ensemble_config_type * ensemble_config ) -{ - enkf_obs_type * enkf_obs = util_malloc(sizeof * enkf_obs); - UTIL_TYPE_ID_INIT( enkf_obs , ENKF_OBS_TYPE_ID ); - enkf_obs->obs_hash = hash_alloc(); - enkf_obs->obs_vector = vector_alloc_new(); - enkf_obs->obs_time = time_map_alloc(); - - enkf_obs->history = history; - enkf_obs->refcase = refcase; - enkf_obs->grid = grid; - enkf_obs->ensemble_config = ensemble_config; - enkf_obs->external_time_map = external_time_map; - enkf_obs->valid = false; - - /* Initialize obs time: */ - { - if (enkf_obs->history) { - int last_report = history_get_last_restart( enkf_obs->history ); - int step; - for (step =0; step <= last_report; step++) { - time_t obs_time = history_get_time_t_from_restart_nr( enkf_obs->history , step ); - enkf_obs_iset_obs_time( enkf_obs , step , obs_time ); - } - enkf_obs->valid = true; - } else { - if (enkf_obs->external_time_map) { - int last_report = time_map_get_size( enkf_obs->external_time_map ) - 1; - int step; - for (step =0; step <= last_report; step++) { - time_t obs_time = time_map_iget( enkf_obs->external_time_map , step ); - enkf_obs_iset_obs_time( enkf_obs , step , obs_time ); - } - enkf_obs->valid = true; - } - } - } - - return enkf_obs; -} - - - -bool enkf_obs_have_obs( const enkf_obs_type * enkf_obs ) { - if (vector_get_size( enkf_obs->obs_vector ) > 0) - return true; - else - return false; -} - - -void enkf_obs_free(enkf_obs_type * enkf_obs) { - hash_free(enkf_obs->obs_hash); - vector_free( enkf_obs->obs_vector ); - time_map_free( enkf_obs->obs_time ); - free(enkf_obs); -} - - - - -time_t enkf_obs_iget_obs_time(const enkf_obs_type * enkf_obs , int report_step) { - return time_map_iget( enkf_obs->obs_time , report_step ); -} - - - - - -/** - Observe that the obs_vector can be NULL - in which it is of course not added. -*/ -void enkf_obs_add_obs_vector(enkf_obs_type * enkf_obs, - const obs_vector_type * vector) -{ - - if (vector != NULL) { - const char * obs_key = obs_vector_get_key( vector ); - if (hash_has_key(enkf_obs->obs_hash , obs_key)) - util_abort("%s: Observation with key:%s already added.\n",__func__ , obs_key); - - hash_insert_ref(enkf_obs->obs_hash , obs_key , vector ); - vector_append_owned_ref( enkf_obs->obs_vector , vector , obs_vector_free__); - } -} - - -bool enkf_obs_has_key(const enkf_obs_type * obs , const char * key) { - return hash_has_key(obs->obs_hash , key); -} - -obs_vector_type * enkf_obs_get_vector(const enkf_obs_type * obs, const char * key) { - return hash_get(obs->obs_hash , key); -} - -obs_vector_type * enkf_obs_iget_vector(const enkf_obs_type * obs, int index) { - return vector_iget( obs->obs_vector , index ); -} - -int enkf_obs_get_size( const enkf_obs_type * obs ) { - return vector_get_size( obs->obs_vector ); -} - - -static matrix_type * estimate_covar_alloc_matrix(const enkf_obs_type * enkf_obs, - obs_vector_type * obs_vector, - double_vector_type * obs_std, - int step, int size) { - matrix_type * error_covar = NULL; - auto_corrf_ftype * auto_corrf; - double auto_corrf_param; - { - const summary_obs_type * summary_obs = obs_vector_iget_node( obs_vector , step ); - auto_corrf = summary_obs_get_auto_corrf( summary_obs ); - auto_corrf_param = summary_obs_get_auto_corrf_param( summary_obs ); - } - - if (size <= 1 || auto_corrf == NULL) - return NULL; - - int i,j; - error_covar = matrix_alloc( size, size ); - for (i = 0; i < size; i++) { - for (j=0; j <= i; j++) { - double covar = sqrt( double_vector_iget( obs_std , i ) * double_vector_iget( obs_std , j )); - double delta_t = enkf_obs_iget_obs_time( enkf_obs , i ) - enkf_obs_iget_obs_time( enkf_obs , j ); - double corr = auto_corrf(delta_t / (24.00 * 3600) , auto_corrf_param ); - - matrix_iset(error_covar , i , j , covar * corr ); - if (i != j) - matrix_iset(error_covar , j , i , covar * corr ); - } - } - return error_covar; -} - - -static void enkf_obs_get_obs_and_measure_summary(const enkf_obs_type * enkf_obs, - obs_vector_type * obs_vector , - enkf_fs_type * fs, - const local_obsdata_node_type * obs_node , - const int_vector_type * ens_active_list , - meas_data_type * meas_data, - obs_data_type * obs_data, - double_vector_type * obs_value , - double_vector_type * obs_std) { - - const active_list_type * active_list = local_obsdata_node_get_active_list( obs_node ); - - matrix_type * error_covar = NULL; - int active_count = 0; - int last_step = -1; - int step = -1; - - /*1: Determine which report_steps have active observations; and collect the observed values. */ - double_vector_reset( obs_std ); - double_vector_reset( obs_value ); - - while (true) { - step = obs_vector_get_next_active_step( obs_vector , step ); - if (step < 0) - break; - - if (local_obsdata_node_tstep_active(obs_node, step) - && obs_vector_iget_active( obs_vector , step ) - && active_list_iget( active_list , 0 /* Index into the scalar summary observation */)) { - const summary_obs_type * summary_obs = obs_vector_iget_node( obs_vector , step ); - double_vector_iset( obs_std , active_count , summary_obs_get_std( summary_obs ) * summary_obs_get_std_scaling( summary_obs )); - double_vector_iset( obs_value , active_count , summary_obs_get_value( summary_obs )); - last_step = step; - active_count++; - } - } - - if (active_count <= 0) - return; - - /* - 2: Estimate a covariance matrix. - Will be owned by the obs_block instance. - */ - error_covar = estimate_covar_alloc_matrix(enkf_obs, obs_vector, obs_std, - last_step, active_count); - - /* - 3: Fill up the obs_block and meas_block structures with this - time-aggregated summary observation. Passing in the error_covar - matrix (which can be NULL) to the obs_block instance. - */ - - { - obs_block_type * obs_block = obs_data_add_block( obs_data , obs_vector_get_obs_key( obs_vector ) , active_count , error_covar , true); - meas_block_type * meas_block = meas_data_add_block( meas_data, obs_vector_get_obs_key( obs_vector ) , last_step , active_count ); - - enkf_node_type * work_node = enkf_node_alloc( obs_vector_get_config_node( obs_vector )); - - for (int i=0; i < active_count; i++) - obs_block_iset( obs_block , i , double_vector_iget( obs_value , i) , double_vector_iget( obs_std , i )); - - int active_size = int_vector_size( ens_active_list ); - active_count = 0; - step = -1; - while (true) { - step = obs_vector_get_next_active_step( obs_vector , step ); - if (step < 0) - break; - - if (local_obsdata_node_tstep_active(obs_node, step) - && obs_vector_iget_active( obs_vector , step ) - && active_list_iget( active_list , 0 /* Index into the scalar summary observation */)) { - for (int iens_index = 0; iens_index < active_size; iens_index++) { - const int iens = int_vector_iget( ens_active_list , iens_index ); - node_id_type node_id = {.report_step = step, - .iens = iens}; - enkf_node_load( work_node , fs , node_id ); - - int smlength = summary_length( enkf_node_value_ptr( work_node ) ); - if (step >= smlength) { - // if obs vector and sim vector have different length - // deactivate and continue to next - char * msg = util_alloc_sprintf("length of observation vector and simulated differ: %d vs. %d ", step, smlength); - meas_block_deactivate(meas_block , active_count); - obs_block_deactivate(obs_block , active_count, true, msg); - free( msg ); - break; - } else { - meas_block_iset(meas_block , iens , active_count , - summary_get( enkf_node_value_ptr( work_node ), - node_id.report_step )); - } - } - active_count++; - } - } - enkf_node_free( work_node ); - } -} - - -void enkf_obs_get_obs_and_measure_node( const enkf_obs_type * enkf_obs, - enkf_fs_type * fs, - const local_obsdata_node_type * obs_node , - const int_vector_type * ens_active_list , - meas_data_type * meas_data, - obs_data_type * obs_data) { - - const char * obs_key = local_obsdata_node_get_key( obs_node ); - obs_vector_type * obs_vector = hash_get( enkf_obs->obs_hash , obs_key ); - obs_impl_type obs_type = obs_vector_get_impl_type( obs_vector ); - - if (obs_type == SUMMARY_OBS) { - // this if also used to test: (end_step >= start_step+2) - double_vector_type * work_value = double_vector_alloc( 0 , -1 ); - double_vector_type * work_std = double_vector_alloc( 0 , -1 ); - - enkf_obs_get_obs_and_measure_summary( enkf_obs , - obs_vector , - fs , - obs_node , - ens_active_list , - meas_data , - obs_data , - work_value, - work_std); - - double_vector_free( work_std ); - double_vector_free( work_value ); - return; - } - - - // obs_type is GEN_OBS or BLOCK_OBS - int report_step = -1; - while (true) { - report_step = obs_vector_get_next_active_step( obs_vector , report_step ); - if (report_step < 0) - return; - - if (local_obsdata_node_tstep_active(obs_node, report_step) - && (obs_vector_iget_active(obs_vector , report_step))) { - /* The observation is active for this report step. */ - const active_list_type * active_list = local_obsdata_node_get_active_list( obs_node ); - /* Collect the observed data in the obs_data instance. */ - obs_vector_iget_observations(obs_vector , report_step , obs_data , active_list, fs); - obs_vector_measure(obs_vector , fs , report_step , ens_active_list , meas_data , active_list); - } - } -} - - -/* - This will append observations and simulated responses from - report_step to obs_data and meas_data. - Call obs_data_reset and meas_data_reset on obs_data and meas_data - if you want to use fresh instances. -*/ - -void enkf_obs_get_obs_and_measure_data(const enkf_obs_type * enkf_obs, - enkf_fs_type * fs, - const local_obsdata_type * local_obsdata , - const int_vector_type * ens_active_list , - meas_data_type * meas_data, - obs_data_type * obs_data) { - - - int iobs; - for (iobs = 0; iobs < local_obsdata_get_size( local_obsdata ); iobs++) { - const local_obsdata_node_type * obs_node = local_obsdata_iget( local_obsdata , iobs ); - enkf_obs_get_obs_and_measure_node( enkf_obs , - fs , - obs_node , - ens_active_list , - meas_data , - obs_data); - } -} - - - - -void enkf_obs_clear( enkf_obs_type * enkf_obs ) { - hash_clear( enkf_obs->obs_hash ); - vector_clear( enkf_obs->obs_vector ); - ensemble_config_clear_obs_keys(enkf_obs->ensemble_config); -} - - - - - -/* - Adding inverse observation keys to the enkf_nodes; can be called - several times. -*/ - - -static void enkf_obs_update_keys( enkf_obs_type * enkf_obs ) { - /* First clear all existing observation keys. */ - ensemble_config_clear_obs_keys( enkf_obs->ensemble_config ); - - /* Add new observation keys. */ - { - hash_type * map = enkf_obs_alloc_data_map(enkf_obs); - hash_iter_type * iter = hash_iter_alloc(map); - const char * obs_key = hash_iter_get_next_key(iter); - while (obs_key != NULL) { - const char * state_kw = hash_get(map , obs_key); - ensemble_config_add_obs_key(enkf_obs->ensemble_config , state_kw , obs_key); - obs_key = hash_iter_get_next_key(iter); - } - hash_iter_free(iter); - hash_free(map); - } -} - - - -/** - This function will load an observation configuration from the - observation file @config_file. - - If called several times during one invocation the function will - start by clearing the current content. -*/ - - - -bool enkf_obs_load(enkf_obs_type * enkf_obs , - const char * config_file, - double std_cutoff) { - - if (enkf_obs->valid) { - int last_report = enkf_obs_get_last_restart( enkf_obs ); - conf_class_type * enkf_conf_class = enkf_obs_get_obs_conf_class(); - conf_instance_type * enkf_conf = conf_instance_alloc_from_file(enkf_conf_class, "enkf_conf", config_file); - - if(conf_instance_validate(enkf_conf) == false) - util_abort("Can not proceed with this configuration.\n"); - - /** Handle HISTORY_OBSERVATION instances. */ - { - stringlist_type * hist_obs_keys = conf_instance_alloc_list_of_sub_instances_of_class_by_name(enkf_conf, "HISTORY_OBSERVATION"); - int num_hist_obs = stringlist_get_size(hist_obs_keys); - - for (int hist_obs_nr = 0; hist_obs_nr < num_hist_obs; hist_obs_nr++) { - const char * obs_key = stringlist_iget(hist_obs_keys, hist_obs_nr); - if (enkf_obs->history) { - const conf_instance_type * hist_obs_conf = conf_instance_get_sub_instance_ref(enkf_conf, obs_key); - obs_vector_type * obs_vector; - enkf_config_node_type * config_node; - config_node = ensemble_config_add_summary_observation( enkf_obs->ensemble_config , obs_key , LOAD_FAIL_WARN ); - if (config_node != NULL) { - obs_vector = obs_vector_alloc( SUMMARY_OBS , obs_key , ensemble_config_get_node( enkf_obs->ensemble_config , obs_key ), last_report); - if (obs_vector != NULL) { - if (obs_vector_load_from_HISTORY_OBSERVATION(obs_vector , - hist_obs_conf , - enkf_obs->obs_time , - enkf_obs->history , - enkf_obs->ensemble_config, - std_cutoff )) { - enkf_obs_add_obs_vector(enkf_obs, obs_vector); - } else { - fprintf(stderr,"** Could not load historical data for observation:%s - ignored\n",obs_key); - obs_vector_free( obs_vector ); - } - } - } else - fprintf(stderr,"** Warning: summary:%s does not exist - observation:%s not added. \n", obs_key , obs_key); - } else - fprintf(stderr,"** Warning: no history object registered - observation:%s is ignored\n",obs_key); - } - - stringlist_free(hist_obs_keys); - } - - - - /** Handle SUMMARY_OBSERVATION instances. */ - { - stringlist_type * sum_obs_keys = conf_instance_alloc_list_of_sub_instances_of_class_by_name(enkf_conf, "SUMMARY_OBSERVATION"); - int num_sum_obs = stringlist_get_size(sum_obs_keys); - - - for(int sum_obs_nr = 0; sum_obs_nr < num_sum_obs; sum_obs_nr++) { - const char * obs_key = stringlist_iget(sum_obs_keys, sum_obs_nr); - const conf_instance_type * sum_obs_conf = conf_instance_get_sub_instance_ref(enkf_conf, obs_key); - const char * sum_key = conf_instance_get_item_value_ref( sum_obs_conf , "KEY" ); - obs_vector_type * obs_vector; - enkf_config_node_type * config_node; - - config_node = ensemble_config_add_summary_observation( enkf_obs->ensemble_config , sum_key , LOAD_FAIL_WARN ); - if (config_node != NULL) { - obs_vector = obs_vector_alloc( SUMMARY_OBS , obs_key , ensemble_config_get_node( enkf_obs->ensemble_config , sum_key ), last_report); - if (obs_vector != NULL) { - obs_vector_load_from_SUMMARY_OBSERVATION(obs_vector , sum_obs_conf , enkf_obs->obs_time , enkf_obs->ensemble_config); - enkf_obs_add_obs_vector(enkf_obs, obs_vector); - } - } else - fprintf(stderr,"** Warning: summary key:%s does not exist - observation key:%s not added.\n", sum_key , obs_key); - } - stringlist_free(sum_obs_keys); - } - - - /** Handle BLOCK_OBSERVATION instances. */ - { - stringlist_type * block_obs_keys = conf_instance_alloc_list_of_sub_instances_of_class_by_name(enkf_conf, "BLOCK_OBSERVATION"); - int num_block_obs = stringlist_get_size(block_obs_keys); - - for(int block_obs_nr = 0; block_obs_nr < num_block_obs; block_obs_nr++) - { - const char * obs_key = stringlist_iget(block_obs_keys, block_obs_nr); - const conf_instance_type * block_obs_conf = conf_instance_get_sub_instance_ref(enkf_conf, obs_key); - obs_vector_type * obs_vector = obs_vector_alloc_from_BLOCK_OBSERVATION(block_obs_conf , enkf_obs->grid , enkf_obs->obs_time , enkf_obs->refcase , enkf_obs->ensemble_config); - if (obs_vector != NULL) - enkf_obs_add_obs_vector(enkf_obs, obs_vector); - } - stringlist_free(block_obs_keys); - } - - - /** Handle GENERAL_OBSERVATION instances. */ - { - stringlist_type * block_obs_keys = conf_instance_alloc_list_of_sub_instances_of_class_by_name(enkf_conf, "GENERAL_OBSERVATION"); - int num_block_obs = stringlist_get_size(block_obs_keys); - - for(int block_obs_nr = 0; block_obs_nr < num_block_obs; block_obs_nr++) - { - const char * obs_key = stringlist_iget(block_obs_keys, block_obs_nr); - const conf_instance_type * gen_obs_conf = conf_instance_get_sub_instance_ref(enkf_conf, obs_key); - - obs_vector_type * obs_vector = obs_vector_alloc_from_GENERAL_OBSERVATION(gen_obs_conf , enkf_obs->obs_time , enkf_obs->ensemble_config); - if (obs_vector != NULL) - enkf_obs_add_obs_vector(enkf_obs, obs_vector); - } - stringlist_free(block_obs_keys); - } - - - conf_instance_free(enkf_conf ); - conf_class_free( enkf_conf_class); - - enkf_obs_update_keys( enkf_obs ); - return true; - } else - return false; -} - - - - - - - static conf_class_type * enkf_obs_get_obs_conf_class( void ) { - const char * enkf_conf_help = "An instance of the class ENKF_CONFIG shall contain neccessary infomation to run the enkf."; - conf_class_type * enkf_conf_class = conf_class_alloc_empty("ENKF_CONFIG", true , false , enkf_conf_help); - conf_class_set_help(enkf_conf_class, enkf_conf_help); - - - - /** Create and insert HISTORY_OBSERVATION class. */ - { - const char * help_class_history_observation = "The class HISTORY_OBSERVATION is used to condition on a time series from the production history. The name of the an instance is used to define the item to condition on, and should be in summary.x syntax. E.g., creating a HISTORY_OBSERVATION instance with name GOPR:P4 conditions on GOPR for group P4."; - - conf_class_type * history_observation_class = conf_class_alloc_empty("HISTORY_OBSERVATION", false , false, help_class_history_observation); - - conf_item_spec_type * item_spec_error_mode = conf_item_spec_alloc("ERROR_MODE", true, DT_STR , "The string ERROR_MODE gives the error mode for the observation."); - conf_item_spec_type * item_spec_auto_corrf_param = conf_item_spec_alloc("AUTO_CORRF_PARAM", false, DT_FLOAT , "A parameter passed to the auto correlation function."); - const char * help_item_spec_auto_corrf = "The name of the auto correlation function used for smoother updates."; - conf_item_spec_type * item_spec_auto_corrf = conf_item_spec_alloc("AUTO_CORRF", false , DT_STR , help_item_spec_auto_corrf); - conf_item_spec_add_restriction( item_spec_auto_corrf , AUTO_CORRF_EXP); - conf_item_spec_add_restriction( item_spec_auto_corrf , AUTO_CORRF_GAUSS); - - - conf_item_spec_add_restriction(item_spec_error_mode, "REL"); - conf_item_spec_add_restriction(item_spec_error_mode, "ABS"); - conf_item_spec_add_restriction(item_spec_error_mode, "RELMIN"); - conf_item_spec_set_default_value(item_spec_error_mode, "RELMIN"); - - conf_item_spec_type * item_spec_error = conf_item_spec_alloc("ERROR", true, DT_POSFLOAT , "The positive floating number ERROR gives the standard deviation (ABS) or the relative uncertainty (REL/RELMIN) of the observations."); - conf_item_spec_set_default_value(item_spec_error, "0.10"); - - conf_item_spec_type * item_spec_error_min = conf_item_spec_alloc("ERROR_MIN", true, DT_POSFLOAT , "The positive floating point number ERROR_MIN gives the minimum value for the standard deviation of the observation when RELMIN is used."); - conf_item_spec_set_default_value(item_spec_error_min, "0.10"); - - conf_class_insert_owned_item_spec(history_observation_class, item_spec_error_mode); - conf_class_insert_owned_item_spec(history_observation_class, item_spec_error); - conf_class_insert_owned_item_spec(history_observation_class, item_spec_error_min); - conf_class_insert_owned_item_spec(history_observation_class, item_spec_auto_corrf); - conf_class_insert_owned_item_spec(history_observation_class, item_spec_auto_corrf_param); - - /** Sub class segment. */ - { - const char * help_class_segment = "The class SEGMENT is used to fine tune the error model."; - conf_class_type * segment_class = conf_class_alloc_empty("SEGMENT", false , false, help_class_segment); - - conf_item_spec_type * item_spec_start_segment = conf_item_spec_alloc("START", true, DT_INT, "The first restart in the segment."); - conf_item_spec_type * item_spec_stop_segment = conf_item_spec_alloc("STOP", true, DT_INT, "The last restart in the segment."); - - conf_item_spec_type * item_spec_error_mode_segment = conf_item_spec_alloc("ERROR_MODE", true, DT_STR , "The string ERROR_MODE gives the error mode for the observation."); - conf_item_spec_add_restriction(item_spec_error_mode_segment, "REL"); - conf_item_spec_add_restriction(item_spec_error_mode_segment, "ABS"); - conf_item_spec_add_restriction(item_spec_error_mode_segment, "RELMIN"); - conf_item_spec_set_default_value(item_spec_error_mode_segment, "RELMIN"); - - conf_item_spec_type * item_spec_error_segment = conf_item_spec_alloc("ERROR", true, DT_POSFLOAT , "The positive floating number ERROR gives the standard deviation (ABS) or the relative uncertainty (REL/RELMIN) of the observations."); - conf_item_spec_set_default_value(item_spec_error_segment, "0.10"); - - conf_item_spec_type * item_spec_error_min_segment = conf_item_spec_alloc("ERROR_MIN", true, DT_POSFLOAT , "The positive floating point number ERROR_MIN gives the minimum value for the standard deviation of the observation when RELMIN is used."); - conf_item_spec_set_default_value(item_spec_error_min_segment, "0.10"); - - - conf_class_insert_owned_item_spec(segment_class, item_spec_start_segment); - conf_class_insert_owned_item_spec(segment_class, item_spec_stop_segment); - conf_class_insert_owned_item_spec(segment_class, item_spec_error_mode_segment); - conf_class_insert_owned_item_spec(segment_class, item_spec_error_segment); - conf_class_insert_owned_item_spec(segment_class, item_spec_error_min_segment); - - conf_class_insert_owned_sub_class(history_observation_class, segment_class); - } - - conf_class_insert_owned_sub_class(enkf_conf_class, history_observation_class); - } - - - - /** Create and insert SUMMARY_OBSERVATION class. */ - { - const char * help_class_summary_observation = "The class SUMMARY_OBSERVATION can be used to condition on any observation whos simulated value is written to the summary file."; - conf_class_type * summary_observation_class = conf_class_alloc_empty("SUMMARY_OBSERVATION", false , false, help_class_summary_observation); - - const char * help_item_spec_value = "The floating point number VALUE gives the observed value."; - conf_item_spec_type * item_spec_value = conf_item_spec_alloc("VALUE", true, DT_FLOAT , help_item_spec_value); - - const char * help_item_spec_error = "The positive floating point number ERROR is the standard deviation of the observed value."; - conf_item_spec_type * item_spec_error = conf_item_spec_alloc("ERROR", true, DT_POSFLOAT ,help_item_spec_error ); - - const char * help_item_spec_date = "The DATE item gives the observation time as the date date it occured. Format is dd/mm/yyyy."; - conf_item_spec_type * item_spec_date = conf_item_spec_alloc("DATE", false, DT_DATE , help_item_spec_date); - - const char * help_item_spec_days = "The DAYS item gives the observation time as days after simulation start."; - conf_item_spec_type * item_spec_days = conf_item_spec_alloc("DAYS", false, DT_POSFLOAT , help_item_spec_days); - - const char * help_item_spec_hours = "The HOURS item gives the observation time as hours after simulation start."; - conf_item_spec_type * item_spec_hours = conf_item_spec_alloc("HOURS", false, DT_POSFLOAT , help_item_spec_hours); - - const char * help_item_spec_restart = "The RESTART item gives the observation time as the ECLIPSE restart nr."; - conf_item_spec_type * item_spec_restart = conf_item_spec_alloc("RESTART", false, DT_POSINT , help_item_spec_restart); - - const char * help_item_spec_sumkey = "The string SUMMARY_KEY is used to look up the simulated value in the summary file. It has the same format as the summary.x program, e.g. WOPR:P4"; - conf_item_spec_type * item_spec_sumkey = conf_item_spec_alloc("KEY", true, DT_STR , help_item_spec_sumkey); - - conf_item_spec_type * item_spec_error_min = conf_item_spec_alloc("ERROR_MIN", true, DT_POSFLOAT , - "The positive floating point number ERROR_MIN gives the minimum value for the standard deviation of the observation when RELMIN is used."); - conf_item_spec_type * item_spec_error_mode = conf_item_spec_alloc("ERROR_MODE", true, DT_STR , "The string ERROR_MODE gives the error mode for the observation."); - - conf_item_spec_add_restriction(item_spec_error_mode, "REL"); - conf_item_spec_add_restriction(item_spec_error_mode, "ABS"); - conf_item_spec_add_restriction(item_spec_error_mode, "RELMIN"); - conf_item_spec_set_default_value(item_spec_error_mode, "ABS"); - conf_item_spec_set_default_value(item_spec_error_min, "0.10"); - - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_value); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_error); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_date); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_days); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_hours); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_restart); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_sumkey); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_error_mode); - conf_class_insert_owned_item_spec(summary_observation_class, item_spec_error_min); - - /** Create a mutex on DATE, DAYS and RESTART. */ - conf_item_mutex_type * time_mutex = conf_class_new_item_mutex(summary_observation_class , true , false); - - conf_item_mutex_add_item_spec(time_mutex , item_spec_date); - conf_item_mutex_add_item_spec(time_mutex , item_spec_days); - conf_item_mutex_add_item_spec(time_mutex , item_spec_hours); - conf_item_mutex_add_item_spec(time_mutex , item_spec_restart); - conf_item_mutex_add_item_spec(time_mutex , item_spec_days ); - - conf_class_insert_owned_sub_class(enkf_conf_class, summary_observation_class); - } - - - - /** Create and insert BLOCK_OBSERVATION class. */ - { - const char * help_class_block_observation = "The class BLOCK_OBSERVATION can be used to condition on an observation whos simulated values are block/cell values of a field, e.g. RFT tests."; - conf_class_type * block_observation_class = conf_class_alloc_empty("BLOCK_OBSERVATION", false , false, help_class_block_observation); - - const char * help_item_spec_field = "The item FIELD gives the observed field. E.g., ECLIPSE fields such as PRESSURE, SGAS or any user defined fields such as PORO or PERMX."; - conf_item_spec_type * item_spec_field = conf_item_spec_alloc("FIELD", true , DT_STR , help_item_spec_field); - - const char * help_item_spec_date = "The DATE item gives the observation time as the date date it occured. Format is dd/mm/yyyy."; - conf_item_spec_type * item_spec_date = conf_item_spec_alloc("DATE", false, DT_DATE , help_item_spec_date); - - const char * help_item_spec_days = "The DAYS item gives the observation time as days after simulation start."; - conf_item_spec_type * item_spec_days = conf_item_spec_alloc("DAYS", false, DT_POSFLOAT , help_item_spec_days); - - const char * help_item_spec_hours = "The HOURS item gives the observation time as hours after simulation start."; - conf_item_spec_type * item_spec_hours = conf_item_spec_alloc("HOURS", false, DT_POSFLOAT , help_item_spec_hours); - - const char * help_item_spec_restart = "The RESTART item gives the observation time as the ECLIPSE restart nr."; - conf_item_spec_type * item_spec_restart = conf_item_spec_alloc("RESTART", false, DT_POSINT , help_item_spec_restart); - - conf_item_spec_type * item_spec_source = conf_item_spec_alloc("SOURCE", false, DT_STR , "The simulated data can be taken from the field or summary keys."); - - - conf_item_spec_add_restriction(item_spec_source, "FIELD"); - conf_item_spec_add_restriction(item_spec_source, "SUMMARY"); - conf_item_spec_set_default_value(item_spec_source, "FIELD"); - - conf_class_insert_owned_item_spec(block_observation_class, item_spec_source); - conf_class_insert_owned_item_spec(block_observation_class, item_spec_field); - conf_class_insert_owned_item_spec(block_observation_class, item_spec_date); - conf_class_insert_owned_item_spec(block_observation_class, item_spec_days); - conf_class_insert_owned_item_spec(block_observation_class, item_spec_restart); - conf_class_insert_owned_item_spec(block_observation_class, item_spec_hours); - /** Create a mutex on DATE, DAYS and RESTART. */ - { - conf_item_mutex_type * time_mutex = conf_class_new_item_mutex(block_observation_class , true , false); - conf_item_mutex_add_item_spec(time_mutex, item_spec_date); - conf_item_mutex_add_item_spec(time_mutex, item_spec_days); - conf_item_mutex_add_item_spec(time_mutex, item_spec_restart); - conf_item_mutex_add_item_spec(time_mutex, item_spec_hours); - } - - /** Create and insert the sub class OBS. */ - { - const char * help_class_obs = "The class OBS is used to specify a single observed point."; - conf_class_type * obs_class = conf_class_alloc_empty("OBS", true , false, help_class_obs); - - const char * help_item_i = "The item I gives the I index of the block observation."; - conf_item_spec_type * item_spec_i = conf_item_spec_alloc("I", true, DT_POSINT , help_item_i); - - const char * help_item_j = "The item J gives the J index of the block observation."; - conf_item_spec_type * item_spec_j = conf_item_spec_alloc("J", true, DT_POSINT, help_item_j); - - const char * help_item_k = "The item K gives the K index of the block observation."; - conf_item_spec_type * item_spec_k = conf_item_spec_alloc("K", true, DT_POSINT, help_item_k); - - const char * help_item_spec_value = "The floating point number VALUE gives the observed value."; - conf_item_spec_type * item_spec_value = conf_item_spec_alloc("VALUE", true, DT_FLOAT , help_item_spec_value); - - const char * help_item_spec_error = "The positive floating point number ERROR is the standard deviation of the observed value."; - conf_item_spec_type * item_spec_error = conf_item_spec_alloc("ERROR", true, DT_POSFLOAT , help_item_spec_error); - - conf_item_spec_type * item_spec_error_mode = conf_item_spec_alloc("ERROR_MODE", true, DT_STR , "The string ERROR_MODE gives the error mode for the observation."); - - conf_item_spec_type * item_spec_error_min = conf_item_spec_alloc("ERROR_MIN", true, DT_POSFLOAT , - "The positive floating point number ERROR_MIN gives the minimum value for the standard deviation of the observation when RELMIN is used."); - - conf_item_spec_add_restriction(item_spec_error_mode, "REL"); - conf_item_spec_add_restriction(item_spec_error_mode, "ABS"); - conf_item_spec_add_restriction(item_spec_error_mode, "RELMIN"); - conf_item_spec_set_default_value(item_spec_error_mode, "ABS"); - conf_item_spec_set_default_value(item_spec_error_min, "0.10" ); - - conf_class_insert_owned_item_spec(obs_class, item_spec_i); - conf_class_insert_owned_item_spec(obs_class, item_spec_j); - conf_class_insert_owned_item_spec(obs_class, item_spec_k); - conf_class_insert_owned_item_spec(obs_class, item_spec_value); - conf_class_insert_owned_item_spec(obs_class, item_spec_error); - conf_class_insert_owned_item_spec(obs_class, item_spec_error_mode); - conf_class_insert_owned_item_spec(obs_class, item_spec_error_min); - - conf_class_insert_owned_sub_class(block_observation_class, obs_class); - } - - conf_class_insert_owned_sub_class(enkf_conf_class, block_observation_class); - } - - /** Create and insert class for general observations. */ - { - const char * help_item_spec_restart = "The RESTART item gives the observation time as the ECLIPSE restart nr."; - const char * help_item_spec_field = "The item DATA gives the observed GEN_DATA instance."; - const char * help_item_spec_date = "The DATE item gives the observation time as the date date it occured. Format is dd/mm/yyyy."; - const char * help_item_spec_days = "The DAYS item gives the observation time as days after simulation start."; - const char * help_item_spec_hours = "The HOURS item gives the observation time as hours after simulation start."; - - conf_class_type * gen_obs_class = conf_class_alloc_empty("GENERAL_OBSERVATION" , false , false, "The class general_observation is used for general observations"); - - conf_item_spec_type * item_spec_field = conf_item_spec_alloc("DATA", true, DT_STR , help_item_spec_field); - conf_item_spec_type * item_spec_date = conf_item_spec_alloc("DATE", false, DT_DATE , help_item_spec_date); - conf_item_spec_type * item_spec_days = conf_item_spec_alloc("DAYS", false, DT_POSFLOAT , help_item_spec_days); - conf_item_spec_type * item_spec_hours = conf_item_spec_alloc("HOURS", false, DT_POSFLOAT , help_item_spec_hours); - conf_item_spec_type * item_spec_restart = conf_item_spec_alloc("RESTART", false, DT_POSINT , help_item_spec_restart); - conf_item_spec_type * item_spec_error_covar = conf_item_spec_alloc("ERROR_COVAR", false, DT_FILE , "Name of file containing error-covariance as formatted matrix - no header"); - - conf_class_insert_owned_item_spec(gen_obs_class, item_spec_error_covar); - conf_class_insert_owned_item_spec(gen_obs_class, item_spec_field); - conf_class_insert_owned_item_spec(gen_obs_class, item_spec_date); - conf_class_insert_owned_item_spec(gen_obs_class, item_spec_days); - conf_class_insert_owned_item_spec(gen_obs_class, item_spec_hours); - conf_class_insert_owned_item_spec(gen_obs_class, item_spec_restart); - /** Create a mutex on DATE, DAYS and RESTART. */ - { - conf_item_mutex_type * time_mutex = conf_class_new_item_mutex(gen_obs_class , true , false); - - conf_item_mutex_add_item_spec(time_mutex, item_spec_date); - conf_item_mutex_add_item_spec(time_mutex, item_spec_days); - conf_item_mutex_add_item_spec(time_mutex, item_spec_hours); - conf_item_mutex_add_item_spec(time_mutex, item_spec_restart); - } - - { - conf_item_spec_type * item_spec_obs_file = conf_item_spec_alloc("OBS_FILE" , false , DT_FILE , "The name of an (ascii) file with observation values."); - conf_item_spec_type * item_spec_value = conf_item_spec_alloc("VALUE" , false , DT_FLOAT , "One scalar observation value."); - conf_item_spec_type * item_spec_error = conf_item_spec_alloc("ERROR" , false , DT_FLOAT , "One scalar observation error."); - conf_item_mutex_type * value_mutex = conf_class_new_item_mutex( gen_obs_class , true , false); - conf_item_mutex_type * value_error_mutex = conf_class_new_item_mutex( gen_obs_class , false , true); - - conf_class_insert_owned_item_spec(gen_obs_class , item_spec_obs_file); - conf_class_insert_owned_item_spec(gen_obs_class , item_spec_value); - conf_class_insert_owned_item_spec(gen_obs_class , item_spec_error); - - - /* If the observation is in terms of VALUE - we must also have ERROR. - The conf system does not (currently ??) enforce this dependency. */ - - conf_item_mutex_add_item_spec( value_mutex , item_spec_value); - conf_item_mutex_add_item_spec( value_mutex , item_spec_obs_file); - - conf_item_mutex_add_item_spec( value_error_mutex , item_spec_value); - conf_item_mutex_add_item_spec( value_error_mutex , item_spec_error); - } - - - /* - The default is that all the elements in DATA are observed, but - we can restrict ourselves to a list of indices, with either the - INDEX_LIST or INDEX_FILE keywords. - */ - { - conf_item_spec_type * item_spec_index_list = conf_item_spec_alloc("INDEX_LIST" , false , DT_STR , "A list of indicies - possibly with ranges which should be observed in the target field."); - conf_item_spec_type * item_spec_index_file = conf_item_spec_alloc("INDEX_FILE" , false , DT_FILE , "An ASCII file containing a list of indices which should be observed in the target field."); - conf_item_mutex_type * index_mutex = conf_class_new_item_mutex( gen_obs_class , false , false); - - conf_class_insert_owned_item_spec(gen_obs_class, item_spec_index_list); - conf_class_insert_owned_item_spec(gen_obs_class, item_spec_index_file); - conf_item_mutex_add_item_spec(index_mutex , item_spec_index_list); - conf_item_mutex_add_item_spec(index_mutex , item_spec_index_file); - } - - conf_class_insert_owned_sub_class(enkf_conf_class, gen_obs_class); - } - - - return enkf_conf_class; -} - - - -/** - Allocates a stringlist of obs target keys which correspond to - summary observations, these are then added to the state vector in - enkf_main. -*/ -stringlist_type * enkf_obs_alloc_typed_keylist(enkf_obs_type * enkf_obs , obs_impl_type obs_type) { - stringlist_type * vars = stringlist_alloc_new(); - hash_iter_type * iter = hash_iter_alloc(enkf_obs->obs_hash); - const char * key = hash_iter_get_next_key(iter); - while ( key != NULL) { - obs_vector_type * obs_vector = hash_get( enkf_obs->obs_hash , key); - if (obs_vector_get_impl_type(obs_vector) == obs_type) - stringlist_append_copy(vars , key); - key = hash_iter_get_next_key(iter); - } - hash_iter_free(iter); - return vars; -} - - -obs_impl_type enkf_obs_get_type(const enkf_obs_type * enkf_obs , const char * key) { - obs_vector_type * obs_vector = hash_get( enkf_obs->obs_hash , key); - return obs_vector_get_impl_type(obs_vector); -} - -/** - */ - -stringlist_type * enkf_obs_alloc_matching_keylist(const enkf_obs_type * enkf_obs, - const char * input_string) { - - stringlist_type * obs_keys = hash_alloc_stringlist( enkf_obs->obs_hash ); - - if (!input_string) - return obs_keys; - - stringlist_type * matching_keys = stringlist_alloc_new(); - char ** input_keys; - int num_keys; - int obs_keys_count = stringlist_get_size( obs_keys ); - - util_split_string( input_string , " " , &num_keys , &input_keys); - for (int i = 0; i < num_keys; i++) { - const char * input_key = input_keys[i]; - for (int j = 0; j < obs_keys_count; j++) { - const char * obs_key = stringlist_iget( obs_keys , j); - - if (util_string_match( obs_key , input_key) - && !stringlist_contains( matching_keys , obs_key )) - stringlist_append_copy( matching_keys , obs_key); - } - } - util_free_stringlist( input_keys , num_keys ); - stringlist_free( obs_keys ); - return matching_keys; -} - - -stringlist_type * enkf_obs_alloc_keylist(enkf_obs_type * enkf_obs ) { - stringlist_type * vars = stringlist_alloc_new(); - hash_iter_type * iter = hash_iter_alloc(enkf_obs->obs_hash); - const char * key = hash_iter_get_next_key(iter); - while ( key != NULL) { - stringlist_append_copy(vars , key); - key = hash_iter_get_next_key(iter); - } - hash_iter_free(iter); - return vars; -} - -/** - This function allocates a hash table which looks like this: - - {"OBS_KEY1": "STATE_KEY1", "OBS_KEY2": "STATE_KEY2", "OBS_KEY3": "STATE_KEY3", ....} - - where "OBS_KEY" represents the keys in the enkf_obs hash, and the - value they are pointing at are the enkf_state keywords they are - measuring. For instance if we have an observation with key "RFT_1A" - the entry in the table will be: ... "RFT_1A": "PRESSURE", .. - since an RFT observation observes the pressure. - - Let us consider the watercut in a well. Then the state_kw will - typically be WWCT:P1 for a well named 'P1'. Let us assume that this - well is observed both as a normal HISTORY observation from - SCHEDULE, and from two separator tests, called S1 and S2. Then the - hash table will look like this: - - "WWCT:P1": "WWCT:P1", - "S1" : "WWCT:P1", - "S2" : "WWCT:P1" - - - I.e. there are three different observations keys, all observing the - same state_kw. -*/ - - - -hash_type * enkf_obs_alloc_data_map(enkf_obs_type * enkf_obs) -{ - hash_type * map = hash_alloc(); - hash_iter_type * iter = hash_iter_alloc(enkf_obs->obs_hash); - const char * key = hash_iter_get_next_key(iter); - while ( key != NULL) { - obs_vector_type * obs_vector = hash_get( enkf_obs->obs_hash , key); - hash_insert_ref( map , key , obs_vector_get_state_kw(obs_vector)); - key = hash_iter_get_next_key(iter); - } - hash_iter_free( iter ); - return map; -} - - -hash_iter_type * enkf_obs_alloc_iter( const enkf_obs_type * enkf_obs ) { - return hash_iter_alloc(enkf_obs->obs_hash); -} - - - - - -/** - This function takes a string like this: "PRESSURE:1,4,7" - it - splits the string on ":" and tries to lookup a config object with - that key. For the general string A:B:C:D it will try consecutively - the keys: A, A:B, A:B:C, A:B:C:D. If a config object is found it is - returned, otherwise NULL is returned. - - The last argument is the pointer to a string which will be updated - with the node-spesific part of the full key. So for instance with - the example "PRESSURE:1,4,7", the index_key will contain - "1,4,7". If the full full_key is used to find an object index_key - will be NULL, that also applies if no object is found. -*/ - - - -const obs_vector_type * enkf_obs_user_get_vector(const enkf_obs_type * obs , const char * full_key, char ** index_key ) { - const obs_vector_type * vector = NULL; - char ** key_list; - int keys; - int key_length = 1; - int offset; - - *index_key = NULL; - util_split_string(full_key , ":" , &keys , &key_list); - while (vector == NULL && key_length <= keys) { - char * current_key = util_alloc_joined_string( (const char **) key_list , key_length , ":"); - if (enkf_obs_has_key(obs , current_key)) - vector = enkf_obs_get_vector(obs , current_key); - else - key_length++; - offset = strlen( current_key ); - free( current_key ); - } - if (vector != NULL) { - if (offset < strlen( full_key )) - *index_key = util_alloc_string_copy(&full_key[offset+1]); - } - - util_free_stringlist(key_list , keys); - return vector; -} - -/*****************************************************************/ - - -void enkf_obs_scale_std(enkf_obs_type * enkf_obs, double scale_factor) { - local_obsdata_type * local_obs = enkf_obs_alloc_all_active_local_obs( enkf_obs , "ALL-OBS"); - enkf_obs_local_scale_std( enkf_obs , local_obs , scale_factor ); - local_obsdata_free( local_obs ); -} - - -void enkf_obs_local_scale_std( const enkf_obs_type * enkf_obs , const local_obsdata_type * local_obsdata, double scale_factor) { - int num_nodes = local_obsdata_get_size( local_obsdata ); - int node_nr; - for (node_nr = 0; node_nr < num_nodes; node_nr++) { - const local_obsdata_node_type * node = local_obsdata_iget( local_obsdata , node_nr ); - obs_vector_type * obs_vector = enkf_obs_get_vector( enkf_obs , local_obsdata_node_get_key( node )); - obs_vector_scale_std( obs_vector , node , scale_factor ); - } -} - - -double enkf_obs_scale_correlated_std(const enkf_obs_type * enkf_obs, - enkf_fs_type * fs, - const int_vector_type * ens_active_list, - const local_obsdata_type * local_obsdata) { - bool_vector_type * ens_mask = int_vector_alloc_mask( ens_active_list ); - meas_data_type * meas_data = meas_data_alloc( ens_mask ); - obs_data_type * obs_data = obs_data_alloc( 1.0 ); - double scale_factor = 1.0; - - enkf_obs_get_obs_and_measure_data( enkf_obs , fs , local_obsdata , ens_active_list, - meas_data , obs_data ); - { - matrix_type * S = meas_data_allocS( meas_data ); - if (S) { - double truncation = 0.95; - int num_PC; - - obs_data_scale( obs_data , S , NULL , NULL , NULL , NULL ); - num_PC = enkf_linalg_num_PC( S , truncation ); - scale_factor = sqrt( obs_data_get_active_size( obs_data ) / num_PC ); - - matrix_free( S ); - enkf_obs_local_scale_std( enkf_obs , local_obsdata , scale_factor ); - } - } - meas_data_free( meas_data ); - obs_data_free( obs_data ); - bool_vector_free( ens_mask ); - return scale_factor; -} - - - -void enkf_obs_add_local_nodes_with_data(const enkf_obs_type * enkf_obs , local_obsdata_type * local_obs , enkf_fs_type *fs , const bool_vector_type * ens_mask) { - hash_iter_type * iter = hash_iter_alloc(enkf_obs->obs_hash); - while ( !hash_iter_is_complete( iter ) ) { - const char * key = hash_iter_get_next_key(iter); - obs_vector_type * obs_vector = hash_get( enkf_obs->obs_hash , key); - - if (obs_vector_has_data( obs_vector , ens_mask , fs )) { - local_obsdata_node_type * node = obs_vector_alloc_local_node( obs_vector ); - local_obsdata_add_node( local_obs , node ); - } - - } - hash_iter_free(iter); -} - - - -local_obsdata_type * enkf_obs_alloc_all_active_local_obs( const enkf_obs_type * enkf_obs , const char * key) { - local_obsdata_type * local_obs = local_obsdata_alloc( key ); - { - hash_iter_type * iter = hash_iter_alloc(enkf_obs->obs_hash); - while ( !hash_iter_is_complete( iter ) ) { - const char * key = hash_iter_get_next_key(iter); - obs_vector_type * obs_vector = hash_get( enkf_obs->obs_hash , key); - local_obsdata_node_type * node = obs_vector_alloc_local_node( obs_vector ); - local_obsdata_add_node( local_obs , node ); - } - hash_iter_free(iter); - } - return local_obs; -} diff --git a/ThirdParty/Ert/libenkf/src/enkf_plot_data.c b/ThirdParty/Ert/libenkf/src/enkf_plot_data.c deleted file mode 100644 index 45432ce28e..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_plot_data.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'enkf_plot_data.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - - -#define ENKF_PLOT_DATA_TYPE_ID 3331063 - -struct enkf_plot_data_struct { - UTIL_TYPE_ID_DECLARATION; - const enkf_config_node_type * config_node; - int size; - enkf_plot_tvector_type ** ensemble; - arg_pack_type ** work_arg; -}; - - - -static void enkf_plot_data_resize( enkf_plot_data_type * plot_data , int new_size ) { - if (new_size != plot_data->size) { - int iens; - - if (new_size < plot_data->size) { - for (iens = new_size; iens < plot_data->size; iens++) { - enkf_plot_tvector_free( plot_data->ensemble[iens] ); - arg_pack_free( plot_data->work_arg[iens] ); - } - } - - plot_data->ensemble = util_realloc( plot_data->ensemble , new_size * sizeof * plot_data->ensemble); - plot_data->work_arg = util_realloc( plot_data->work_arg , new_size * sizeof * plot_data->work_arg); - - if (new_size > plot_data->size) { - for (iens = plot_data->size; iens < new_size; iens++) { - plot_data->ensemble[iens] = enkf_plot_tvector_alloc( plot_data->config_node , iens); - plot_data->work_arg[iens] = arg_pack_alloc(); - } - } - plot_data->size = new_size; - } -} - - -static void enkf_plot_data_reset( enkf_plot_data_type * plot_data ) { - int iens; - for (iens = 0; iens < plot_data->size; iens++) { - enkf_plot_tvector_reset( plot_data->ensemble[iens] ); - arg_pack_clear( plot_data->work_arg[iens] ); - } -} - - -void enkf_plot_data_free( enkf_plot_data_type * plot_data ) { - int iens; - for (iens = 0; iens < plot_data->size; iens++) { - enkf_plot_tvector_free( plot_data->ensemble[iens] ); - arg_pack_free( plot_data->work_arg[iens]); - } - free( plot_data->work_arg ); - free( plot_data->ensemble ); - free( plot_data ); -} - -UTIL_IS_INSTANCE_FUNCTION( enkf_plot_data , ENKF_PLOT_DATA_TYPE_ID ) - - -enkf_plot_data_type * enkf_plot_data_alloc( const enkf_config_node_type * config_node ) { - enkf_plot_data_type * plot_data = util_malloc( sizeof * plot_data); - UTIL_TYPE_ID_INIT( plot_data , ENKF_PLOT_DATA_TYPE_ID ); - plot_data->config_node = config_node; - plot_data->size = 0; - plot_data->ensemble = NULL; - plot_data->work_arg = NULL; - return plot_data; -} - -enkf_plot_tvector_type * enkf_plot_data_iget( const enkf_plot_data_type * plot_data , int index) { - return plot_data->ensemble[index]; -} - - -int enkf_plot_data_get_size( const enkf_plot_data_type * plot_data ) { - return plot_data->size; -} - - - - -void enkf_plot_data_load( enkf_plot_data_type * plot_data , - enkf_fs_type * fs , - const char * index_key , - const bool_vector_type * input_mask) { - state_map_type * state_map = enkf_fs_get_state_map( fs ); - int ens_size = state_map_get_size( state_map ); - bool_vector_type * mask; - - if (input_mask) - mask = bool_vector_alloc_copy( input_mask ); - else - mask = bool_vector_alloc( ens_size , false ); - state_map_select_matching( state_map , mask , STATE_HAS_DATA ); - - enkf_plot_data_resize( plot_data , ens_size ); - enkf_plot_data_reset( plot_data ); - { - const int num_cpu = 4; - thread_pool_type * tp = thread_pool_alloc( num_cpu , true ); - for (int iens = 0; iens < ens_size ; iens++) { - if (bool_vector_iget( mask , iens)) { - enkf_plot_tvector_type * vector = enkf_plot_data_iget( plot_data , iens ); - arg_pack_type * work_arg = plot_data->work_arg[iens]; - - arg_pack_append_ptr( work_arg , vector ); - arg_pack_append_ptr( work_arg , fs ); - arg_pack_append_const_ptr( work_arg , index_key ); - - thread_pool_add_job( tp , enkf_plot_tvector_load__ , work_arg ); - } - } - thread_pool_join( tp ); - thread_pool_free( tp ); - } - bool_vector_free( mask ); -} - - diff --git a/ThirdParty/Ert/libenkf/src/enkf_plot_gen_kw.c b/ThirdParty/Ert/libenkf/src/enkf_plot_gen_kw.c deleted file mode 100644 index db066c9f75..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_plot_gen_kw.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_gen_kw.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - - -#define ENKF_PLOT_GEN_KW_TYPE_ID 88362063 - -struct enkf_plot_gen_kw_struct { - UTIL_TYPE_ID_DECLARATION; - const enkf_config_node_type * config_node; - int size; /* Number of ensembles. */ - enkf_plot_gen_kw_vector_type ** ensemble; /* One vector for each ensemble. */ -}; - - -UTIL_IS_INSTANCE_FUNCTION( enkf_plot_gen_kw , ENKF_PLOT_GEN_KW_TYPE_ID ) - - -enkf_plot_gen_kw_type * enkf_plot_gen_kw_alloc( const enkf_config_node_type * config_node ) { - if (enkf_config_node_get_impl_type( config_node ) == GEN_KW) { - enkf_plot_gen_kw_type * plot_gen_kw = util_malloc( sizeof * plot_gen_kw ); - UTIL_TYPE_ID_INIT( plot_gen_kw , ENKF_PLOT_GEN_KW_TYPE_ID ); - plot_gen_kw->config_node = config_node; - plot_gen_kw->size = 0; - plot_gen_kw->ensemble = NULL; - return plot_gen_kw; - } - else { - return NULL; - } -} - - -void enkf_plot_gen_kw_free( enkf_plot_gen_kw_type * plot_gen_kw ) { - int iens; - for (iens = 0 ; iens < plot_gen_kw->size ; ++iens) { - enkf_plot_gen_kw_vector_free( plot_gen_kw->ensemble[iens] ); - } - free( plot_gen_kw ); -} - - -int enkf_plot_gen_kw_get_size( const enkf_plot_gen_kw_type * plot_gen_kw ) { - return plot_gen_kw->size; -} - -enkf_plot_gen_kw_vector_type * enkf_plot_gen_kw_iget( const enkf_plot_gen_kw_type * plot_gen_kw , int iens) { - if ((iens < 0) || (iens >= plot_gen_kw->size)) - util_abort("%s: index:%d invalid. Valid interval: [0,%d>.\n",__func__ , iens , plot_gen_kw->size); - - return plot_gen_kw->ensemble[iens]; -} - - -static void enkf_plot_gen_kw_resize( enkf_plot_gen_kw_type * plot_gen_kw , int new_size ) { - if (new_size != plot_gen_kw->size) { - int iens; - - if (new_size < plot_gen_kw->size) { - for (iens = new_size; iens < plot_gen_kw->size; iens++) { - enkf_plot_gen_kw_vector_free( plot_gen_kw->ensemble[iens] ); - } - } - - plot_gen_kw->ensemble = util_realloc( plot_gen_kw->ensemble , new_size * sizeof * plot_gen_kw->ensemble); - - if (new_size > plot_gen_kw->size) { - for (iens = plot_gen_kw->size; iens < new_size; iens++) { - plot_gen_kw->ensemble[iens] = enkf_plot_gen_kw_vector_alloc( plot_gen_kw->config_node , iens ); - } - } - plot_gen_kw->size = new_size; - } -} - - - -void enkf_plot_gen_kw_load( enkf_plot_gen_kw_type * plot_gen_kw, - enkf_fs_type * fs, - bool transform_data , - int report_step, - const bool_vector_type * input_mask ) { - - state_map_type * state_map = enkf_fs_get_state_map( fs ); - int ens_size = state_map_get_size( state_map ); - bool_vector_type * mask; - - if (input_mask) - mask = bool_vector_alloc_copy( input_mask ); - else - mask = bool_vector_alloc( ens_size , true ); - - enkf_plot_gen_kw_resize( plot_gen_kw , ens_size ); - { - int iens; - for (iens = 0; iens < ens_size; ++iens) { - if (bool_vector_iget( mask , iens)) { - enkf_plot_gen_kw_vector_type * vector = enkf_plot_gen_kw_iget( plot_gen_kw , iens ); - enkf_plot_gen_kw_vector_load( vector , fs , transform_data , report_step ); - } - } - } -} - - - -const char * enkf_plot_gen_kw_iget_key( const enkf_plot_gen_kw_type * plot_gen_kw, int index) { - const gen_kw_config_type * gen_kw_config = enkf_config_node_get_ref( plot_gen_kw->config_node ); - return gen_kw_config_iget_name( gen_kw_config , index ); -} - -int enkf_plot_gen_kw_get_keyword_count( const enkf_plot_gen_kw_type * gen_kw ){ - const gen_kw_config_type * gen_kw_config = enkf_config_node_get_ref( gen_kw->config_node ); - return gen_kw_config_get_data_size(gen_kw_config); -} - -bool enkf_plot_gen_kw_should_use_log_scale(const enkf_plot_gen_kw_type * gen_kw , int index) { - const gen_kw_config_type * gen_kw_config = enkf_config_node_get_ref( gen_kw->config_node ); - return gen_kw_config_should_use_log_scale(gen_kw_config, index); -} diff --git a/ThirdParty/Ert/libenkf/src/enkf_plot_gen_kw_vector.c b/ThirdParty/Ert/libenkf/src/enkf_plot_gen_kw_vector.c deleted file mode 100644 index 59a1090659..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_plot_gen_kw_vector.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_gen_kw_vector.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -#define ENKF_PLOT_GEN_KW_VECTOR_TYPE_ID 88362064 - -struct enkf_plot_gen_kw_vector_struct { - UTIL_TYPE_ID_DECLARATION; - int iens; - double_vector_type * data; - const enkf_config_node_type * config_node; -}; - - -UTIL_IS_INSTANCE_FUNCTION( enkf_plot_gen_kw_vector , ENKF_PLOT_GEN_KW_VECTOR_TYPE_ID ) - - -enkf_plot_gen_kw_vector_type * enkf_plot_gen_kw_vector_alloc( const enkf_config_node_type * config_node , int iens ) { - enkf_plot_gen_kw_vector_type * vector = util_malloc( sizeof * vector ); - UTIL_TYPE_ID_INIT( vector , ENKF_PLOT_GEN_KW_VECTOR_TYPE_ID ); - vector->config_node = config_node; - vector->data = double_vector_alloc(0,0); - vector->iens = iens; - return vector; -} - - -void enkf_plot_gen_kw_vector_free( enkf_plot_gen_kw_vector_type * vector ) { - double_vector_free( vector->data ); - free( vector ); -} - - -int enkf_plot_gen_kw_vector_get_size( const enkf_plot_gen_kw_vector_type * vector ) { - return double_vector_size( vector->data ); -} - -double enkf_plot_gen_kw_vector_iget( const enkf_plot_gen_kw_vector_type * vector , int index ) { - return double_vector_iget( vector->data , index ); -} - - -void enkf_plot_gen_kw_vector_reset( enkf_plot_gen_kw_vector_type * vector ) { - double_vector_reset( vector->data ); -} - - -void enkf_plot_gen_kw_vector_load( enkf_plot_gen_kw_vector_type * vector , enkf_fs_type * fs , bool transform_data , int report_step ) { - enkf_plot_gen_kw_vector_reset( vector ); - { - node_id_type node_id = { .report_step = report_step , - .iens = vector->iens }; - - enkf_node_type * data_node = enkf_node_alloc( vector->config_node ); - - if (enkf_node_try_load( data_node , fs , node_id )) { - gen_kw_type * gen_kw = enkf_node_value_ptr( data_node ); - int n_kw = gen_kw_data_size( gen_kw ); - int i_kw; - - for (i_kw = 0 ; i_kw < n_kw ; ++i_kw) { - double_vector_append(vector->data , gen_kw_data_iget( gen_kw , i_kw , transform_data ) ); - } - } - - enkf_node_free( data_node ); - } -} diff --git a/ThirdParty/Ert/libenkf/src/enkf_plot_gendata.c b/ThirdParty/Ert/libenkf/src/enkf_plot_gendata.c deleted file mode 100644 index d0fddf5207..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_plot_gendata.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_gendata.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include - - -#include -#include -#include -#include - -#include -#include -#include -#include - - -#define ENKF_PLOT_GENDATA_TYPE_ID 377626666 - -struct enkf_plot_gendata_struct { - UTIL_TYPE_ID_DECLARATION; - int size; - const enkf_config_node_type * enkf_config_node; - enkf_plot_genvector_type ** ensemble; - arg_pack_type ** work_arg; - double_vector_type * max_values; - double_vector_type * min_values; -}; - -UTIL_IS_INSTANCE_FUNCTION( enkf_plot_gendata , ENKF_PLOT_GENDATA_TYPE_ID ) - -enkf_plot_gendata_type * enkf_plot_gendata_alloc( const enkf_config_node_type * enkf_config_node ) { - if (enkf_config_node_get_impl_type(enkf_config_node) == GEN_DATA ){ - enkf_plot_gendata_type * data = util_malloc(sizeof * data); - UTIL_TYPE_ID_INIT (data , ENKF_PLOT_GENDATA_TYPE_ID); - data->size = 0; - data->enkf_config_node = enkf_config_node; - data->work_arg = NULL; - data->ensemble = NULL; - - data->max_values = NULL; - data->min_values = NULL; - return data; - } else { - return NULL; - } - -} - - -enkf_plot_gendata_type * enkf_plot_gendata_alloc_from_obs_vector( const obs_vector_type * obs_vector ){ - return enkf_plot_gendata_alloc(obs_vector_get_config_node(obs_vector)); -} - -void enkf_plot_gendata_free( enkf_plot_gendata_type * data ){ - for (int iens = 0; iens < data->size; iens++) { - arg_pack_free( data->work_arg[iens] ); - enkf_plot_genvector_free( data->ensemble[iens] ); - } - - free( data->work_arg ); - free( data->ensemble ); - free( data ); - -} - -int enkf_plot_gendata_get_size( const enkf_plot_gendata_type * data ){ - return data->size; -} - -enkf_plot_genvector_type * enkf_plot_gendata_iget( const enkf_plot_gendata_type * plot_data , int index){ - if(index >=0 && index < plot_data->size){ - return plot_data->ensemble[index]; - } else { - return NULL; - } -} - -static void enkf_plot_gendata_resize( enkf_plot_gendata_type * plot_gendata , int new_size ){ - if (new_size != plot_gendata->size) { - int iens; - - if (new_size < plot_gendata->size) { - for (iens = new_size; iens < plot_gendata->size; iens++) { - enkf_plot_genvector_free( plot_gendata->ensemble[iens] ); - arg_pack_free( plot_gendata->work_arg[iens] ); - } - } - - plot_gendata->ensemble = util_realloc( plot_gendata->ensemble , new_size * sizeof * plot_gendata->ensemble); - plot_gendata->work_arg = util_realloc( plot_gendata->work_arg , new_size * sizeof * plot_gendata->work_arg); - - if (new_size > plot_gendata->size) { - for (iens = plot_gendata->size; iens < new_size; iens++) { - plot_gendata->ensemble[iens] = enkf_plot_genvector_alloc( plot_gendata->enkf_config_node , iens ); - plot_gendata->work_arg[iens] = arg_pack_alloc(); - } - } - plot_gendata->size = new_size; - } -} - -static void enkf_plot_gendata_reset( enkf_plot_gendata_type * plot_gendata , int report_step){ - int iens; - for (iens = 0; iens < plot_gendata->size; iens++){ - arg_pack_clear( plot_gendata->work_arg[iens] ); - } -} - - - -void enkf_plot_gendata_load( enkf_plot_gendata_type * plot_data , - enkf_fs_type * fs , - int report_step , - const bool_vector_type * input_mask){ - - state_map_type * state_map = enkf_fs_get_state_map( fs ); - int ens_size = state_map_get_size( state_map ); - bool_vector_type * mask; - - if (input_mask) - mask = bool_vector_alloc_copy( input_mask ); - else - mask = bool_vector_alloc( ens_size , false ); - - state_map_select_matching( state_map , mask , STATE_HAS_DATA ); - - enkf_plot_gendata_resize( plot_data , ens_size ); - enkf_plot_gendata_reset( plot_data , report_step ); - - { - const int num_cpu = 4; - thread_pool_type * tp = thread_pool_alloc( num_cpu , true ); - for (int iens = 0; iens < ens_size ; iens++) { - if (bool_vector_iget( mask , iens)) { - enkf_plot_genvector_type * vector = enkf_plot_gendata_iget( plot_data , iens ); - arg_pack_type * work_arg = plot_data->work_arg[iens]; - - arg_pack_append_ptr( work_arg , vector ); - arg_pack_append_ptr( work_arg , fs ); - arg_pack_append_int( work_arg , report_step); - - thread_pool_add_job( tp , enkf_plot_genvector_load__ , work_arg ); - } - } - thread_pool_join( tp ); - thread_pool_free( tp ); - } - - bool_vector_free( mask ); - -} - -void enkf_plot_gendata_find_min_max_values__(enkf_plot_gendata_type * plot_data){ - for (int iens = 0; iens < plot_data->size; iens++){ - enkf_plot_genvector_type * vector = enkf_plot_gendata_iget(plot_data, iens); - int size = enkf_plot_genvector_get_size(vector); - if(iens == 0) { - plot_data->min_values = double_vector_alloc(size, DBL_MAX); - plot_data->max_values = double_vector_alloc(size, -DBL_MAX); - } - for(int index = 0; index < size; index++){ - double value = enkf_plot_genvector_iget(vector, index); - double_vector_iset(plot_data->min_values, index, util_double_min(double_vector_iget(plot_data->min_values, index), value)); - double_vector_iset(plot_data->max_values, index, util_double_max(double_vector_iget(plot_data->max_values, index), value)); - } - } -} - -double_vector_type * enkf_plot_gendata_get_min_values(enkf_plot_gendata_type * plot_data) { - if(plot_data->min_values == NULL) { - enkf_plot_gendata_find_min_max_values__(plot_data); - } - return plot_data->min_values; -} - - - -double_vector_type * enkf_plot_gendata_get_max_values(enkf_plot_gendata_type * plot_data) { - if(plot_data->max_values == NULL) { - enkf_plot_gendata_find_min_max_values__(plot_data); - } - return plot_data->max_values; -} diff --git a/ThirdParty/Ert/libenkf/src/enkf_plot_genvector.c b/ThirdParty/Ert/libenkf/src/enkf_plot_genvector.c deleted file mode 100644 index 346d7b49b3..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_plot_genvector.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_genvector.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include - - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define ENKF_PLOT_GENVECTOR_TYPE_ID 66862669 - -struct enkf_plot_genvector_struct { - UTIL_TYPE_ID_DECLARATION; - int iens; - double_vector_type * data; - const enkf_config_node_type * config_node; -}; - -UTIL_IS_INSTANCE_FUNCTION( enkf_plot_genvector , ENKF_PLOT_GENVECTOR_TYPE_ID ) - -enkf_plot_genvector_type * enkf_plot_genvector_alloc( const enkf_config_node_type * config_node , int iens){ - enkf_plot_genvector_type * vector = util_malloc( sizeof * vector ); - UTIL_TYPE_ID_INIT( vector , ENKF_PLOT_GENVECTOR_TYPE_ID ); - vector->config_node = config_node; - vector->data = double_vector_alloc(0,0); - vector->iens = iens; - return vector; - -} - -void enkf_plot_genvector_free( enkf_plot_genvector_type * vector ){ - double_vector_free(vector->data); - free(vector); -} - -int enkf_plot_genvector_get_size( const enkf_plot_genvector_type * vector ){ - return double_vector_size( vector->data ); -} - - -double enkf_plot_genvector_iget( const enkf_plot_genvector_type * vector , int index){ - return double_vector_iget( vector->data , index ); -} - - -void enkf_plot_genvector_load( enkf_plot_genvector_type * vector , enkf_fs_type * fs , int report_step ) { - enkf_node_type * work_node = enkf_node_alloc( vector->config_node ); - - node_id_type node_id = { .report_step = report_step , - .iens = vector->iens }; - - if (enkf_node_try_load( work_node , fs , node_id )) { - gen_data_type * node = enkf_node_value_ptr( work_node ); - gen_data_copy_to_double_vector( node , vector->data ); - - } - enkf_node_free( work_node ); -} - - -void * enkf_plot_genvector_load__( void * arg ){ - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - enkf_plot_genvector_type * vector = arg_pack_iget_ptr( arg_pack , 0); - enkf_fs_type * fs = arg_pack_iget_ptr( arg_pack , 1 ); - int report_step = arg_pack_iget_int( arg_pack , 2 ); - - enkf_plot_genvector_load( vector , fs , report_step ); - return NULL; - -} diff --git a/ThirdParty/Ert/libenkf/src/enkf_plot_tvector.c b/ThirdParty/Ert/libenkf/src/enkf_plot_tvector.c deleted file mode 100644 index 009f28c710..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_plot_tvector.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'enkf_plot_tvector.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include - -#define ENKF_PLOT_TVECTOR_ID 6111861 - -struct enkf_plot_tvector_struct { - UTIL_TYPE_ID_DECLARATION; - double_vector_type * data; - double_vector_type * work; - time_t_vector_type * time; - bool_vector_type * mask; - const enkf_config_node_type * config_node; - int iens; - bool summary_mode; -}; - - - -UTIL_SAFE_CAST_FUNCTION( enkf_plot_tvector , ENKF_PLOT_TVECTOR_ID ) -UTIL_IS_INSTANCE_FUNCTION( enkf_plot_tvector , ENKF_PLOT_TVECTOR_ID ) - - - -void enkf_plot_tvector_reset( enkf_plot_tvector_type * plot_tvector ) { - double_vector_reset( plot_tvector->data ); - time_t_vector_reset( plot_tvector->time ); - bool_vector_reset( plot_tvector->mask ); -} - - -enkf_plot_tvector_type * enkf_plot_tvector_alloc( const enkf_config_node_type * config_node , int iens) { - enkf_plot_tvector_type * plot_tvector = util_malloc( sizeof * plot_tvector); - UTIL_TYPE_ID_INIT( plot_tvector , ENKF_PLOT_TVECTOR_ID ); - - plot_tvector->data = double_vector_alloc( 0 , 0 ); - plot_tvector->time = time_t_vector_alloc(-1 , 0); - plot_tvector->mask = bool_vector_alloc( false , 0 ); - plot_tvector->work = double_vector_alloc(0,0); - plot_tvector->iens = iens; - - plot_tvector->config_node = config_node; - if (enkf_config_node_get_impl_type( config_node ) == SUMMARY) - plot_tvector->summary_mode = true; - else - plot_tvector->summary_mode = false; - - return plot_tvector; -} - - -void enkf_plot_tvector_free( enkf_plot_tvector_type * plot_tvector ) { - double_vector_free( plot_tvector->data ); - double_vector_free( plot_tvector->work ); - time_t_vector_free( plot_tvector->time ); - bool_vector_free( plot_tvector->mask ); -} - - -bool enkf_plot_tvector_all_active( const enkf_plot_tvector_type * plot_tvector ) { - bool all_active = true; - for (int i=0; i < bool_vector_size( plot_tvector->mask ); i++) - all_active = all_active && bool_vector_iget(plot_tvector->mask , i ); - - return all_active; -} - - -int enkf_plot_tvector_size( const enkf_plot_tvector_type * plot_tvector ) { - return bool_vector_size( plot_tvector->mask ); -} - - -void enkf_plot_tvector_iset( enkf_plot_tvector_type * plot_tvector , int index , time_t time , double value) { - time_t_vector_iset( plot_tvector->time , index , time ); - bool active_value = true; - - /* This is to handle holes in the summary vector storage. */ - if (plot_tvector->summary_mode && !summary_active_value( value )) - active_value = false; - - if (active_value) { - double_vector_iset( plot_tvector->data , index , value ); - bool_vector_iset( plot_tvector->mask , index , true ); - } else - bool_vector_iset( plot_tvector->mask , index , false ); - -} - - - -double enkf_plot_tvector_iget_value( const enkf_plot_tvector_type * plot_tvector , int index) { - return double_vector_iget( plot_tvector->data , index); -} - -time_t enkf_plot_tvector_iget_time( const enkf_plot_tvector_type * plot_tvector , int index) { - return time_t_vector_iget( plot_tvector->time , index); -} - -bool enkf_plot_tvector_iget_active( const enkf_plot_tvector_type * plot_tvector , int index) { - return bool_vector_iget( plot_tvector->mask , index ); -} - - - - - - -void enkf_plot_tvector_load( enkf_plot_tvector_type * plot_tvector , - enkf_fs_type * fs , - const char * index_key) { - - time_map_type * time_map = enkf_fs_get_time_map( fs ); - int step1 = 0; - int step2 = time_map_get_last_step( time_map ); - enkf_node_type * work_node = enkf_node_alloc( plot_tvector->config_node ); - - if (enkf_node_vector_storage( work_node )) { - bool has_data = enkf_node_user_get_vector(work_node , fs , index_key , plot_tvector->iens , plot_tvector->work); - - if(has_data) { - for (int step = 0; step < double_vector_size( plot_tvector->work ); step++) - enkf_plot_tvector_iset( plot_tvector , - step , - time_map_iget( time_map , step ) , - double_vector_iget( plot_tvector->work , step )); - } - } else { - int step; - node_id_type node_id = {.iens = plot_tvector->iens, - .report_step = 0 }; - - for (step = step1 ; step <= step2; step++) { - double value; - node_id.report_step = step; - - if (enkf_node_user_get(work_node , fs , index_key , node_id , &value)) { - enkf_plot_tvector_iset( plot_tvector , - step , - time_map_iget( time_map , step ) , - value ); - } - } - } - enkf_node_free( work_node ); -} - - -void * enkf_plot_tvector_load__( void * arg ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - enkf_plot_tvector_type * tvector = arg_pack_iget_ptr( arg_pack , 0 ); - enkf_fs_type * fs = arg_pack_iget_ptr( arg_pack , 1 ); - const char * index_key = arg_pack_iget_ptr( arg_pack , 2 ); - - enkf_plot_tvector_load( tvector , fs , index_key ); - return NULL; -} - diff --git a/ThirdParty/Ert/libenkf/src/enkf_serialize.c b/ThirdParty/Ert/libenkf/src/enkf_serialize.c deleted file mode 100644 index 3532e8e03a..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_serialize.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_serialize.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include - -#include -#include -#include - -/** This is heavy shit ... */ - - -/** - This file handles serialization and deserialization of the - enkf_nodes. This is at the very core of the EnKF update - algorithm. The final update step is written: - - A' = XA - - i.e. it is linear algeabra, and we need(?) to write the various - objects in the form of an ensemble matrix, this is the process we - call serialization. Then the linear algebra update is performed, - and afterwards we must read the data back from the ensemble matrix - to the enkf_node object, this is deserialization. - - - - - =============== =============== - | PORO-1 | | PORO-2 | - |-------------- Member 2 |-------------- - | | ======== | | - | P0 ... P10 | Member 1 | | P0 ... P10 | - =============== ======== | =============== - /|\ | ----- /|\ - | | | | - | \|/ \|/ | - | | - | [ P0 P0 ] | - | [ P1 P1 ] | - ------------------>[ P2 P2 ]<------------------- - [ P3 P3 ] - [ P4 P4 ] - [ ··········] ============== - [ R1 R1 ] | RELPERM-2 | - ============== ------>[ R2 R2 ]<----------->|------------| - | RELPERM-1 | | [ R3 R3 ] | | - |------------|<---- [ ··········] | R0 ... R5 | - | | [ F2 F2 ] ============== - | R0 ... R5 | ---->[ F3 F3 ] - ============== | [ F4 F4 ]<----- - | [ F6 F6 ] | - | | - | | ============== - | | | FAULT-1 | - | ----------->|------------| - ============== | | | - | FAULT-1 | | | F0 ... F6 | - |------------|<------ ============== - | | - | F0 ... F6 | - ============== - - - -This figure shows the following: - - 1. Three different nodes called PORO, RELPERM and FAULT - respectively. The PORO node consists of eleven elements (P0 - ... P10), whereas the RELPERM and FAULT nodes contain six and - seven elements. - - 2. The ensemble consists of two members (i.e. there is PORO-1 and - PORO-2.). - - 3. The members have been serialized into a a large vector where - everything comes ordered. Observe that *NOT* all elements from the - members have been inserted into the large vector, i.e. for the - PORO fields we only have elements P0 .. P4; this is because (for - some reason) not all elements were active. - - -Each of the enkf_node functions have their own xxx_serialize and -xxx_deserialize functions, however these functions SHOULD call the -enkf_serialize() and enkf_deserialize() functions in this -file. (Rolling your own serialize / deserialize functions at the -lowest level is a SERIOUS CRIME.) - -The illustration above shows three different enkf_node objects which -have been COMPLETELY serialized. One of the reasons the code is so -complex is that it is supposed to handle situations where the serial -vector is to small to hold everything, and repeated calls to serialize -& deserialize must be performed to complete the thing. - - -About stride -============ -In the enkf update the ensemble matrix A is just that - a matrix, -however in this elegant high-level language it is of course -implemented as one long linear vector. The matrix is implemented such -that the 'member-direction' is fastest running index. Consider the -following ensemble matrix, consisting of five ensemble members: - - - - - - Member 5 - Member 2 --· | - | | - | | -Member 1 ----· | | - | | | - \|/ \|/ \|/ - [ P0 P0 P0 P0 P0 ] - [ P1 P1 P1 P1 P1 ] - [ P2 P2 P2 P2 P2 ] - [ P3 P3 P3 P3 P3 ] - [ R0 R0 R0 R0 R0 ] - A = [ R1 R1 R1 R1 R1 ] - [ R2 R2 R2 R2 R2 ] - [ F0 F0 F0 F0 F0 ] - [ F1 F1 F1 F1 F1 ] - [ F2 F2 F2 F2 F2 ] - [ F3 F3 F3 F3 F3 ] - - -The in memory the matrix will look like this: - - - Member 2 - | - ______________|______________ - / | \ - | | | - ______________|______________|______________|______________ - / | | | \ - | | | | | - | | | | | - \|/ \|/ \|/ \|/ \|/ ........... - A =[ P0 P0 P0 P0 P0 P1 P1 P1 P1 P1 P2 P2 P2 P2 P2 P3 P3 P3 P3 P3 R0 R0 R0 R0 R0 R1 R1 R1 R1 R1 R2 R2 R2 R2 R2 F0 F0 F0 F0 F0 F1 F1 F1 F1 F1 F2 F2 F2 F2 F2 F3 F3 F3 F3 F3 ...] - /|\ X1 /|\ X2 /|\ /|\ /|\ ........ - | | | | | - | | | | | - \______________|______________|______________|______________/ - | | | - | | | - \______________|______________/ - | - | - Member 1 - -The stride in the serial_vector_type object is the number of elements -between consecutive elements in the same member, i.e. it is five in -the vector above. (Starting at e.g. P0 for member three (marked with -X1 in the figure), P1 for the same member is five elements down in the -vector (marked with X2 above)). Now - that was clear ehhh? - -*****************************************************************/ - - - -/* - It will be very costly to make it thread-safe if we manipulate the - shape of the A matrix from here. -*/ - - -void enkf_matrix_serialize(const void * __node_data , - int node_size , - ecl_type_enum node_type , - const active_list_type * __active_list , - matrix_type * A , - int row_offset, - int column) { - - int active_size; - const int * active_list = active_list_get_active( __active_list ); - active_size = active_list_get_active_size( __active_list , node_size); - - if (node_type == ECL_DOUBLE_TYPE) { - const double * node_data = (const double *) __node_data; - if (active_size == node_size) /** All elements active */ - matrix_set_many_on_column( A , row_offset , node_size , node_data , column); - else { - int row_index; - int node_index; - for (row_index = 0; row_index < active_size; row_index++) { - node_index = active_list[ row_index ]; - matrix_iset( A , row_index + row_offset , column , node_data[node_index] ); - } - } - } else if (node_type == ECL_FLOAT_TYPE) { - const float * node_data = (const float *) __node_data; - int row_index; - if (active_size == node_size) {/** All elements active */ - for (row_index = 0; row_index < node_size; row_index++) - matrix_iset( A , row_index + row_offset , column , node_data[ row_index ]); /* Must have float -> double conversion; can not use memcpy() based approach */ - } else { - int row_index; - int node_index; - for (row_index = 0; row_index < active_size; row_index++) { - node_index = active_list[ row_index ]; - matrix_iset( A , row_index + row_offset , column , node_data[node_index] ); - } - } - } else - util_abort("%s: internal error: trying to serialize unserializable type:%s \n",__func__ , ecl_util_get_type_name( node_type )); -} - - -void enkf_matrix_deserialize(void * __node_data , - int node_size , - ecl_type_enum node_type , - const active_list_type * __active_list , - const matrix_type * A, - int row_offset, - int column) { - - int active_size; - const int * active_list = active_list_get_active( __active_list ); - active_size = active_list_get_active_size( __active_list , node_size ); - - if (node_type == ECL_DOUBLE_TYPE) { - double * node_data = (double *) __node_data; - - if (active_size == node_size) { /** All elements active */ - int row_index; - for (row_index = 0; row_index < active_size; row_index++) - node_data[row_index] = matrix_iget( A , row_index + row_offset , column); - } else { - int row_index; - int node_index; - for (row_index = 0; row_index < active_size; row_index++) { - node_index = active_list[ row_index ]; - node_data[node_index] = matrix_iget( A , row_index + row_offset , column); - } - } - - } else if (node_type == ECL_FLOAT_TYPE) { - float * node_data = (float *) __node_data; - - if (active_size == node_size) { /** All elements active */ - int row_index; - for (row_index = 0; row_index < active_size; row_index++) - node_data[row_index] = matrix_iget( A , row_index + row_offset , column); - } else { - int row_index; - int node_index; - for (row_index = 0; row_index < active_size; row_index++) { - node_index = active_list[ row_index ]; - node_data[node_index] = matrix_iget( A , row_index + row_offset , column); - } - } - } else - util_abort("%s: internal error: trying to serialize unserializable type:%s \n",__func__ , ecl_util_get_type_name( node_type )); -} - diff --git a/ThirdParty/Ert/libenkf/src/enkf_state.c b/ThirdParty/Ert/libenkf/src/enkf_state.c deleted file mode 100644 index f2a1afd0a3..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_state.c +++ /dev/null @@ -1,1654 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_state.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ENKF_STATE_TYPE_ID 78132 - - - - - -/** - This struct contains various objects which the enkf_state needs - during operation, which the enkf_state_object *DOES NOT* own. The - struct only contains pointers to objects owned by (typically) the - enkf_main object. - - If the enkf_state object writes to any of the objects in this - struct that can be considered a serious *BUG*. - - The elements in this struct should not change during the - application lifetime? -*/ - -typedef struct shared_info_struct { - model_config_type * model_config; /* .... */ - ext_joblist_type * joblist; /* The list of external jobs which are installed - and *how* they should be run (with Python code) */ - job_queue_type * job_queue; /* The queue handling external jobs. (i.e. LSF / TORQUE / rsh / local / ... )*/ - const site_config_type * site_config; - ert_templates_type * templates; - const ecl_config_type * ecl_config; -} shared_info_type; - - - - - - -/*****************************************************************/ - -struct enkf_state_struct { - UTIL_TYPE_ID_DECLARATION; - hash_type * node_hash; - subst_list_type * subst_list; /* This a list of key - value pairs which are used in a search-replace - operation on the ECLIPSE data file. Will at least contain the key INIT" - - which will describe initialization of ECLIPSE (EQUIL or RESTART).*/ - ensemble_config_type * ensemble_config; /* The config nodes for the enkf_node objects contained in node_hash. */ - - shared_info_type * shared_info; /* Pointers to shared objects which is needed by the enkf_state object (read only). */ - member_config_type * my_config; /* Private config information for this member; not updated during a simulation. */ - rng_type * rng; -}; - -/*****************************************************************/ - - -static UTIL_SAFE_CAST_FUNCTION( enkf_state , ENKF_STATE_TYPE_ID ) - - -static shared_info_type * shared_info_alloc(const site_config_type * site_config , model_config_type * model_config, const ecl_config_type * ecl_config , ert_templates_type * templates) { - shared_info_type * shared_info = util_malloc(sizeof * shared_info ); - - shared_info->joblist = site_config_get_installed_jobs( site_config ); - shared_info->job_queue = site_config_get_job_queue( site_config ); - shared_info->site_config = site_config; - shared_info->model_config = model_config; - shared_info->templates = templates; - shared_info->ecl_config = ecl_config; - return shared_info; -} - - -static void shared_info_free(shared_info_type * shared_info) { - /** - Adding something here is a BUG - this object does - not own anything. - */ - free( shared_info ); -} - - - - - -/*****************************************************************/ -/** Helper classes complete - starting on the enkf_state proper object. */ -/*****************************************************************/ - -void enkf_state_initialize(enkf_state_type * enkf_state , enkf_fs_type * fs , const stringlist_type * param_list, init_mode_type init_mode) { - if (init_mode != INIT_NONE) { - int iens = enkf_state_get_iens( enkf_state ); - state_map_type * state_map = enkf_fs_get_state_map( fs ); - realisation_state_enum current_state = state_map_iget(state_map, iens); - if ((current_state == STATE_PARENT_FAILURE) && (init_mode != INIT_FORCE)) - return; - else { - for (int ip = 0; ip < stringlist_get_size(param_list); ip++) { - enkf_node_type * param_node = enkf_state_get_node(enkf_state, stringlist_iget(param_list, ip)); - node_id_type node_id = { .report_step = 0, .iens = iens }; - bool has_data = enkf_node_has_data(param_node, fs, node_id); - - if ((init_mode == INIT_FORCE) || (has_data == false) || (current_state == STATE_LOAD_FAILURE)) { - if (enkf_node_initialize(param_node, iens, enkf_state->rng)) - enkf_node_store(param_node, fs, true, node_id); - } - } - state_map_update_matching(state_map , iens , STATE_UNDEFINED | STATE_LOAD_FAILURE , STATE_INITIALIZED); - enkf_fs_fsync(fs); - } - } -} - - - - - - - -/* - void enkf_state_set_iens(enkf_state_type * enkf_state , int iens) { - enkf_state->my_iens = iens; - } -*/ - -int enkf_state_get_iens(const enkf_state_type * enkf_state) { - return member_config_get_iens( enkf_state->my_config ); -} - -member_config_type * enkf_state_get_member_config(const enkf_state_type * enkf_state) { - return enkf_state->my_config; -} - - - -subst_list_type * enkf_state_get_subst_list( enkf_state_type * enkf_state ) { - return enkf_state->subst_list; -} - -void enkf_state_add_subst_kw(enkf_state_type * enkf_state , const char * kw , const char * value , const char * doc_string) { - char * tagged_key = util_alloc_sprintf( INTERNAL_DATA_KW_TAG_FORMAT , kw ); - subst_list_append_owned_ref(enkf_state->subst_list , tagged_key , util_alloc_string_copy(value) , doc_string); - free(tagged_key); -} - - - - - -/** - This function must be called each time the eclbase_fmt has been - updated. -*/ - -void enkf_state_update_eclbase( enkf_state_type * enkf_state ) { - const char * eclbase = member_config_update_eclbase( enkf_state->my_config , enkf_state->shared_info->ecl_config , enkf_state->subst_list); - const char * casename = member_config_get_casename( enkf_state->my_config ); /* Mostly NULL */ - { - enkf_state_add_subst_kw(enkf_state , "ECL_BASE" , eclbase , NULL); - enkf_state_add_subst_kw(enkf_state , "ECLBASE" , eclbase , NULL); - - if (casename == NULL) - enkf_state_add_subst_kw( enkf_state , "CASE" , eclbase , NULL); /* No CASE_TABLE loaded - using the eclbase as default. */ - else - enkf_state_add_subst_kw( enkf_state , "CASE" , casename , NULL); - } -} - - -void enkf_state_update_jobname( enkf_state_type * enkf_state ) { - member_config_update_jobname( enkf_state->my_config , - model_config_get_jobname_fmt( enkf_state->shared_info->model_config ) , - enkf_state->subst_list); -} - - -/** - Sets all the static subst keywords which will not change during the simulation. -*/ -static void enkf_state_set_static_subst_kw(enkf_state_type * enkf_state) { - - { - int iens = member_config_get_iens( enkf_state->my_config ); - char * iens_s = util_alloc_sprintf("%d" , iens); - char * iens4_s = util_alloc_sprintf("%04d" , iens); - char * iensp1_s = util_alloc_sprintf("%d" , iens + 1); - - enkf_state_add_subst_kw(enkf_state , "IENS" , iens_s , NULL); - enkf_state_add_subst_kw(enkf_state , "IENSP1" , iensp1_s , NULL); - enkf_state_add_subst_kw(enkf_state , "IENS4" , iens4_s , NULL); - - free(iensp1_s); - free(iens_s); - free(iens4_s); - } - enkf_state_update_eclbase( enkf_state ); -} - - -static void enkf_state_add_nodes( enkf_state_type * enkf_state, const ensemble_config_type * ensemble_config) { - stringlist_type * container_keys = stringlist_alloc_new(); - stringlist_type * keylist = ensemble_config_alloc_keylist(ensemble_config); - int keys = stringlist_get_size(keylist); - - // 1: Add all regular nodes - for (int ik = 0; ik < keys; ik++) { - const char * key = stringlist_iget(keylist, ik); - const enkf_config_node_type * config_node = ensemble_config_get_node(ensemble_config , key); - if (enkf_config_node_get_impl_type( config_node ) == CONTAINER) { - stringlist_append_ref( container_keys , key ); - } else - enkf_state_add_node(enkf_state , key , config_node); - } - - // 2: Add container nodes - must ensure that all other nodes have - // been added already (this implies that containers of containers - // will be victim of hash retrieval order problems .... - - for (int ik = 0; ik < stringlist_get_size( container_keys ); ik++) { - const char * key = stringlist_iget(container_keys, ik); - const enkf_config_node_type * config_node = ensemble_config_get_node(ensemble_config , key); - enkf_state_add_node( enkf_state , key , config_node ); - } - - stringlist_free(keylist); - stringlist_free( container_keys ); -} - - -/** - This variable is on a per-instance basis, but that is not really - supported. The exported functionality applies to all realizations. -*/ - -bool enkf_state_get_pre_clear_runpath( const enkf_state_type * enkf_state ) { - return member_config_pre_clear_runpath( enkf_state->my_config ); -} - - -void enkf_state_set_pre_clear_runpath( enkf_state_type * enkf_state , bool pre_clear_runpath ) { - member_config_set_pre_clear_runpath( enkf_state->my_config , pre_clear_runpath ); -} - - - -enkf_state_type * enkf_state_alloc(int iens, - rng_type * main_rng , - const char * casename , - bool pre_clear_runpath , - keep_runpath_type keep_runpath , - model_config_type * model_config, - ensemble_config_type * ensemble_config, - const site_config_type * site_config, - const ecl_config_type * ecl_config, - - ert_templates_type * templates, - subst_list_type * subst_parent) { - - enkf_state_type * enkf_state = util_malloc(sizeof *enkf_state ); - UTIL_TYPE_ID_INIT( enkf_state , ENKF_STATE_TYPE_ID ); - - enkf_state->ensemble_config = ensemble_config; - enkf_state->shared_info = shared_info_alloc(site_config , model_config , ecl_config , templates); - - enkf_state->node_hash = hash_alloc(); - enkf_state->subst_list = subst_list_alloc( subst_parent ); - enkf_state->rng = rng_alloc( rng_get_type( main_rng ) , INIT_DEFAULT ); - rng_rng_init( enkf_state->rng , main_rng ); /* <- Not thread safe */ - /* - The user MUST specify an INIT_FILE, and for the first timestep the - tag in the data file will be replaced by an - - INCLDUE - EQUIL_INIT_FILE - - statement. When considering the possibility of estimating EQUIL this - require a real understanding of the treatment of paths: - - * If not estimating the EQUIL contacts, all members should use the - same init_file. To ensure this the user must specify the ABSOLUTE - PATH to a file containing initialization information. - - * If the user is estimating initial contacts, the INIT_FILE must - point to the ecl_file of the EQUIL keyword, this must be a pure - filename without any path component (as it will be generated by - the EnKF program, and placed in the run_path directory). We could - let the EnKF program use the ecl_file of the EQUIL keyword if it - is present. - - The key is actually initialized in the - enkf_state_set_dynamic_subst_kw() function. - */ - - /** - Adding all the subst_kw keywords here, with description. Listing - all of them here in one go guarantees that we have control over - the ordering (which is interesting because the substititions are - done in a cascade like fashion). The user defined keywords are - added first, so that these can refer to the built in keywords. - */ - - enkf_state_add_subst_kw(enkf_state , "RUNPATH" , "---" , "The absolute path of the current forward model instance. "); - enkf_state_add_subst_kw(enkf_state , "IENS" , "---" , "The realisation number for this realization."); - enkf_state_add_subst_kw(enkf_state , "IENS4" , "---" , "The realization number for this realization - formated with %04d."); - enkf_state_add_subst_kw(enkf_state , "ECLBASE" , "---" , "The ECLIPSE basename for this realization."); - enkf_state_add_subst_kw(enkf_state , "ECL_BASE" , "---" , "Depreceated - use ECLBASE instead."); - enkf_state_add_subst_kw(enkf_state , "SMSPEC" , "---" , "The ECLIPSE SMSPEC file for this realization."); - enkf_state_add_subst_kw(enkf_state , "TSTEP1" , "---" , "The initial report step for this simulation."); - enkf_state_add_subst_kw(enkf_state , "TSTEP2" , "---" , "The final report step for this simulation."); - enkf_state_add_subst_kw(enkf_state , "TSTEP1_04" , "---" , "The initial report step for this simulation - formated with %04d."); - enkf_state_add_subst_kw(enkf_state , "TSTEP2_04" , "---" , "The final report step for this simulation - formated withh %04d."); - enkf_state_add_subst_kw(enkf_state , "RESTART_FILE1" , "---" , "The ECLIPSE restart file this simulation starts with."); - enkf_state_add_subst_kw(enkf_state , "RESTART_FILE2" , "---" , "The ECLIPSE restart file this simulation should end with."); - enkf_state_add_subst_kw(enkf_state , "RANDINT" , "---" , "Random integer value (depreceated: use __RANDINT__() instead)."); - enkf_state_add_subst_kw(enkf_state , "RANDFLOAT" , "---" , "Random float value (depreceated: use __RANDFLOAT__() instead)."); - enkf_state_add_subst_kw(enkf_state , "INIT" , "---" , "The code which will be inserted at the tag"); - if (casename != NULL) - enkf_state_add_subst_kw(enkf_state , "CASE" , casename , "The casename for this realization - as loaded from the CASE_TABLE file."); - else - enkf_state_add_subst_kw(enkf_state , "CASE" , "---" , "The casename for this realization - similar to ECLBASE."); - - enkf_state->my_config = member_config_alloc( iens , casename , pre_clear_runpath , keep_runpath , ecl_config , ensemble_config); - enkf_state_set_static_subst_kw( enkf_state ); - enkf_state_add_nodes( enkf_state , ensemble_config ); - - return enkf_state; -} - - - - -bool enkf_state_has_node(const enkf_state_type * enkf_state , const char * node_key) { - bool has_node = hash_has_key(enkf_state->node_hash , node_key); - return has_node; -} - - - -/** - The enkf_state inserts a reference to the node object. The - enkf_state object takes ownership of the node object, i.e. it will - free it when the game is over. - - Observe that if the node already exists the existing node will be - removed (freed and so on ... ) from the enkf_state object before - adding the new; this was previously considered a run-time error. -*/ - - -void enkf_state_add_node(enkf_state_type * enkf_state , const char * node_key , const enkf_config_node_type * config) { - if (enkf_state_has_node(enkf_state , node_key)) - enkf_state_del_node( enkf_state , node_key ); /* Deleting the old instance (if we had one). */ - { - enkf_node_type *enkf_node; - if (enkf_config_node_get_impl_type( config ) == CONTAINER) - enkf_node = enkf_node_alloc_shared_container( config , enkf_state->node_hash ); - else - enkf_node = enkf_node_alloc( config ); - - hash_insert_hash_owned_ref(enkf_state->node_hash , node_key , enkf_node, enkf_node_free__); - - /* Setting the global subst list so that the GEN_KW templates can contain e.g. and . */ - if (enkf_node_get_impl_type( enkf_node ) == GEN_KW) - gen_kw_set_subst_parent( enkf_node_value_ptr( enkf_node ) , enkf_state->subst_list ); - } -} - - -enkf_node_type * enkf_state_get_or_create_node(enkf_state_type * enkf_state, const enkf_config_node_type * config_node) { - const char * key = enkf_config_node_get_key(config_node); - if(!enkf_state_has_node(enkf_state, key)) { - enkf_state_add_node(enkf_state, key, config_node); - } - return enkf_state_get_node(enkf_state, key); -} - - - -void enkf_state_update_node( enkf_state_type * enkf_state , const char * node_key ) { - const enkf_config_node_type * config_node = ensemble_config_get_node( enkf_state->ensemble_config , node_key ); - if (!enkf_state_has_node( enkf_state , node_key)) - enkf_state_add_node( enkf_state , node_key , config_node ); /* Add a new node */ - else { - bool modified = true; /* ehhhh? */ - - if (modified) - enkf_state_add_node( enkf_state , node_key , config_node ); - } -} - - -const char * enkf_state_get_eclbase( const enkf_state_type * enkf_state ) { - return member_config_get_eclbase( enkf_state->my_config ); -} - - - - -static void enkf_state_log_GEN_DATA_load( const enkf_node_type * enkf_node , int report_step , forward_load_context_type * load_context) { - if (forward_load_context_accept_messages(load_context)) { - char * load_file = enkf_config_node_alloc_infile(enkf_node_get_config( enkf_node ) , report_step); - int data_size = gen_data_get_size( enkf_node_value_ptr( enkf_node )); - char * msg = util_alloc_sprintf("Loaded GEN_DATA:%s instance for step:%d from file:%s size:%d" , - enkf_node_get_key( enkf_node ) , - report_step , - load_file , - data_size); - - forward_load_context_add_message(load_context, msg); - - free( msg ); - free( load_file ); - } -} - - -static void enkf_state_log_custom_kw_load(const enkf_node_type * enkf_node, int report_step, forward_load_context_type * load_context) { - if (forward_load_context_accept_messages(load_context)) { - char * load_file = enkf_config_node_alloc_infile(enkf_node_get_config(enkf_node), report_step); - char * msg = util_alloc_sprintf("Loaded CUSTOM_KW: %s instance for step: %d from file: %s", - enkf_node_get_key(enkf_node), - report_step, - load_file); - - forward_load_context_add_message(load_context, msg); - - free(msg); - free(load_file); - } -} - -static bool enkf_state_report_step_compatible(const enkf_state_type * enkf_state, const ecl_sum_type * ecl_sum_simulated) { - bool ret = true; - - const model_config_type * model_config = enkf_state->shared_info->model_config; - const ecl_sum_type * ecl_sum_reference = model_config_get_refcase(model_config); - - if (ecl_sum_reference) //Can be NULL - ret = ecl_sum_report_step_compatible(ecl_sum_reference, ecl_sum_simulated); - - return ret; -} - - -static int_vector_type * __enkf_state_get_time_index(enkf_fs_type * result_fs, const ecl_sum_type * summary) { - time_map_type * time_map = enkf_fs_get_time_map( result_fs ); - time_map_summary_update( time_map , summary ); - return time_map_alloc_index_map( time_map , summary ); -} - - -/* - * Check if there are summary keys in the ensemble config that is not found in Eclipse. If this is the case, AND we - * have observations for this key, we have a problem. Otherwise, just print a message to the log. - */ -static void enkf_state_check_for_missing_eclipse_summary_data(const summary_key_matcher_type * matcher, const ecl_smspec_type * smspec, - const enkf_state_type * enkf_state, forward_load_context_type * load_context, const int iens ) { - - stringlist_type * keys = summary_key_matcher_get_keys(matcher); - - for (int i = 0; i < stringlist_get_size(keys); i++) { - - const char *key = stringlist_iget(keys, i); - - if (ecl_smspec_has_general_var(smspec, key) || !summary_key_matcher_summary_key_is_required(matcher, key)) - continue; - - if (!ensemble_config_has_key(enkf_state->ensemble_config, key)) - continue; - - const enkf_config_node_type *config_node = ensemble_config_get_node(enkf_state->ensemble_config, key); - if (enkf_config_node_get_num_obs(config_node) == 0) { - ert_log_add_fmt_message(3, NULL, "[%03d:----] Unable to find Eclipse data for summary key: %s, but have no observations either, so will continue.", - iens, key); - } else { - ert_log_add_fmt_message(1, NULL, "[%03d:----] Unable to find Eclipse data for summary key: %s, but have observation for this, job will fail.", - iens, key); - forward_load_context_update_result(load_context, LOAD_FAILURE); - if (forward_load_context_accept_messages(load_context)) { - char *msg = util_alloc_sprintf("Failed to load vector: %s", key); - forward_load_context_add_message(load_context, msg); - free(msg); - } - } - } - - stringlist_free(keys); -} - -static bool enkf_state_internalize_dynamic_eclipse_results(enkf_state_type * enkf_state , - forward_load_context_type * load_context , - const model_config_type * model_config) { - - bool load_summary = ensemble_config_has_impl_type(enkf_state->ensemble_config, SUMMARY); - const run_arg_type * run_arg = forward_load_context_get_run_arg( load_context ); - const summary_key_matcher_type * matcher = ensemble_config_get_summary_key_matcher(enkf_state->ensemble_config); - int matcher_size = summary_key_matcher_get_size(matcher); - - if (load_summary || matcher_size > 0) { - int load_start = run_arg_get_load_start( run_arg ); - - if (load_start == 0) { /* Do not attempt to load the "S0000" summary results. */ - load_start++; - } - - { - /* Looking for summary files on disk, and loading them. */ - const ecl_sum_type * summary = forward_load_context_get_ecl_sum( load_context ); - enkf_fs_type * result_fs = run_arg_get_result_fs( run_arg ); - /** OK - now we have actually loaded the ecl_sum instance, or ecl_sum == NULL. */ - if (summary) { - int_vector_type * time_index = __enkf_state_get_time_index(result_fs, summary); - - /* - Now there are two related / conflicting(?) systems for - checking summary time consistency, both internally in the - time_map and also through the - enkf_state_report_step_compatible() function. - */ - - /*Check the loaded summary against the reference ecl_sum_type */ - if (!enkf_state_report_step_compatible(enkf_state, summary)) - forward_load_context_update_result(load_context, REPORT_STEP_INCOMPATIBLE); - - - /* The actual loading internalizing - from ecl_sum -> enkf_node. */ - const int iens = member_config_get_iens( enkf_state->my_config ); - const int step2 = ecl_sum_get_last_report_step( summary ); /* Step2 is just taken from the number of steps found in the summary file. */ - - int_vector_iset_block( time_index , 0 , load_start , -1 ); - int_vector_resize( time_index , step2 + 1); - - const ecl_smspec_type * smspec = ecl_sum_get_smspec(summary); - - for(int i = 0; i < ecl_smspec_num_nodes(smspec); i++) { - const smspec_node_type * smspec_node = ecl_smspec_iget_node(smspec, i); - const char * key = smspec_node_get_gen_key1(smspec_node); - - if(summary_key_matcher_match_summary_key(matcher, key)) { - summary_key_set_type * key_set = enkf_fs_get_summary_key_set(result_fs); - summary_key_set_add_summary_key(key_set, key); - - enkf_config_node_type * config_node = ensemble_config_get_or_create_summary_node(enkf_state->ensemble_config, key); - enkf_node_type * node = enkf_state_get_or_create_node(enkf_state, config_node); - - enkf_node_try_load_vector( node , result_fs , iens ); // Ensure that what is currently on file is loaded before we update. - - enkf_node_forward_load_vector( node , load_context , time_index); - enkf_node_store_vector( node , result_fs , iens ); - } - } - - int_vector_free( time_index ); - - /* - Check if some of the specified keys are missing from the Eclipse data, and if there are observations for them. That is a problem. - */ - enkf_state_check_for_missing_eclipse_summary_data(matcher, smspec, enkf_state, load_context, iens); - - return true; - } else { - fprintf(stderr , "** Warning: could not load ECLIPSE summary data from %s - this will probably fail later ...\n" , run_arg_get_runpath( run_arg )); - return false; - } - } - } else { - return true; - } -} - - - - - - -static void enkf_state_internalize_custom_kw(enkf_state_type * enkf_state, - forward_load_context_type * load_context , - const model_config_type * model_config) { - - member_config_type * my_config = enkf_state->my_config; - const int iens = member_config_get_iens( my_config ); - stringlist_type * custom_kw_keys = ensemble_config_alloc_keylist_from_impl_type(enkf_state->ensemble_config, CUSTOM_KW); - const run_arg_type * run_arg = forward_load_context_get_run_arg( load_context ); - enkf_fs_type * result_fs = run_arg_get_result_fs(run_arg); - const int report_step = 0; - - custom_kw_config_set_type * config_set = enkf_fs_get_custom_kw_config_set(result_fs); - custom_kw_config_set_reset(config_set); - - for (int ikey=0; ikey < stringlist_get_size(custom_kw_keys); ikey++) { - const char* custom_kw_key = stringlist_iget(custom_kw_keys, ikey); - enkf_node_type * node = enkf_state_get_node(enkf_state, custom_kw_key); - - if (enkf_node_vector_storage(node)) { - util_abort("%s: Vector storage not correctly implemented for CUSTOM_KW\n", __func__); - } else { - if (enkf_node_internalize(node, report_step)) { - if (enkf_node_has_func(node, forward_load_func)) { - if (enkf_node_forward_load(node, load_context)) { - node_id_type node_id = {.report_step = report_step, .iens = iens }; - - enkf_node_store(node, result_fs, false, node_id); - - const enkf_config_node_type * config_node = enkf_node_get_config(node); - const custom_kw_config_type * custom_kw_config = (custom_kw_config_type*) enkf_config_node_get_ref(config_node); - custom_kw_config_set_add_config(config_set, custom_kw_config); - enkf_state_log_custom_kw_load(node, report_step, load_context); - } else { - forward_load_context_update_result(load_context, LOAD_FAILURE); - ert_log_add_fmt_message(1, stderr, "[%03d:%04d] Failed load data for CUSTOM_KW node: %s.", iens , report_step, enkf_node_get_key(node)); - - if (forward_load_context_accept_messages(load_context)) { - char * msg = util_alloc_sprintf("Failed to load: %s at step: %d", enkf_node_get_key(node), report_step); - forward_load_context_add_message(load_context , msg); - free( msg ); - } - } - } - } - } - } - - stringlist_free(custom_kw_keys); -} - - - -static void enkf_state_internalize_GEN_DATA(enkf_state_type * enkf_state , - forward_load_context_type * load_context , - const model_config_type * model_config , - int last_report) { - { - member_config_type * my_config = enkf_state->my_config; - const int iens = member_config_get_iens( my_config ); - stringlist_type * keylist_GEN_DATA = ensemble_config_alloc_keylist_from_impl_type(enkf_state->ensemble_config , GEN_DATA ); - const run_arg_type * run_arg = forward_load_context_get_run_arg( load_context ); - enkf_fs_type * result_fs = run_arg_get_result_fs( run_arg ); - - for (int ikey=0; ikey < stringlist_get_size( keylist_GEN_DATA ); ikey++) { - enkf_node_type * node = enkf_state_get_node( enkf_state , stringlist_iget( keylist_GEN_DATA , ikey)); - - for (int report_step = run_arg_get_load_start( run_arg ); report_step <= last_report; report_step++) { - if (enkf_node_internalize(node , report_step)) { - - if (enkf_node_has_func(node , forward_load_func)) { - forward_load_context_select_step(load_context, report_step); - if (enkf_node_forward_load(node , load_context )) { - node_id_type node_id = {.report_step = report_step , - .iens = iens }; - - enkf_node_store( node , result_fs, false , node_id ); - enkf_state_log_GEN_DATA_load( node , report_step , load_context); - } else { - forward_load_context_update_result(load_context, LOAD_FAILURE); - ert_log_add_fmt_message(1 , stderr , "[%03d:%04d] Failed load data for GEN_DATA node:%s.",iens , report_step , enkf_node_get_key( node )); - - if (forward_load_context_accept_messages(load_context)) { - char * msg = util_alloc_sprintf("Failed to load: %s at step:%d" , enkf_node_get_key( node ) , report_step); - forward_load_context_add_message(load_context, msg); - free( msg ); - } - } - } - } - } - } - stringlist_free( keylist_GEN_DATA ); - } -} - - -/** - This function loads the STATE from a forward simulation. In ECLIPSE - speak that means to load the solution vectors (PRESSURE/SWAT/..) - and the necessary static keywords. - - When the state has been loaded it goes straight to disk. -*/ - -static void enkf_state_internalize_eclipse_state(enkf_state_type * enkf_state , - forward_load_context_type * load_context, - const model_config_type * model_config , - int report_step , - bool store_vectors) { - - shared_info_type * shared_info = enkf_state->shared_info; - const ecl_config_type * ecl_config = shared_info->ecl_config; - const run_arg_type * run_arg = forward_load_context_get_run_arg( load_context ); - enkf_fs_type * result_fs = run_arg_get_result_fs( run_arg ); - if (ecl_config_active( ecl_config ) && model_config_internalize_state( model_config , report_step )) { - member_config_type * my_config = enkf_state->my_config; - const int iens = member_config_get_iens( my_config ); - const bool internalize_state = model_config_internalize_state( model_config , report_step ); - - forward_load_context_load_restart_file( load_context , report_step); - - /******************************************************************/ - /** - Starting on the enkf_node_forward_load() function calls. This - is where the actual loading is done. Observe that this loading - might involve other load functions than the ones used for - loading PRESSURE++ from ECLIPSE restart files (e.g. for - loading seismic results..) - */ - - { - hash_iter_type * iter = hash_iter_alloc(enkf_state->node_hash); - while ( !hash_iter_is_complete(iter) ) { - enkf_node_type * enkf_node = hash_iter_get_next_value(iter); - if (enkf_node_get_var_type(enkf_node) == DYNAMIC_STATE && - enkf_node_get_impl_type(enkf_node) == FIELD) { - - bool internalize_kw = internalize_state; - if (!internalize_kw) - internalize_kw = enkf_node_internalize(enkf_node , report_step); - - if (internalize_kw) { - if (enkf_node_has_func(enkf_node , forward_load_func)) { - if (enkf_node_forward_load(enkf_node , load_context)) { - node_id_type node_id = {.report_step = report_step , - .iens = iens }; - - enkf_node_store( enkf_node , result_fs, store_vectors , node_id ); - } else { - forward_load_context_update_result(load_context, LOAD_FAILURE); - ert_log_add_fmt_message( 1 , NULL , "[%03d:%04d] Failed load data for FIELD node:%s.",iens , report_step , enkf_node_get_key( enkf_node )); - - if (forward_load_context_accept_messages(load_context)) { - char * msg = util_alloc_sprintf("Failed to load: %s at step:%d" , enkf_node_get_key( enkf_node ) , report_step); - forward_load_context_add_message(load_context, msg); - free( msg ); - } - } - } - } - } - } - hash_iter_free(iter); - } - } -} - - - -static forward_load_context_type * enkf_state_alloc_load_context( const enkf_state_type * state , run_arg_type * run_arg, stringlist_type * messages) { - bool load_summary = ensemble_config_has_impl_type(state->ensemble_config, SUMMARY); - if (!load_summary) { - const summary_key_matcher_type * matcher = ensemble_config_get_summary_key_matcher(state->ensemble_config); - load_summary = (summary_key_matcher_get_size(matcher) > 0); - } - - { - forward_load_context_type * load_context; - const ecl_config_type * ecl_config = state->shared_info->ecl_config; - const char * eclbase = enkf_state_get_eclbase( state ); - - load_context = forward_load_context_alloc( run_arg, - load_summary, - ecl_config , - eclbase, - messages ); - return load_context; - } -} - - -/** - This function loads the results from a forward simulations from report_step1 - to report_step2. The details of what to load are in model_config and the - spesific nodes for special cases. - - Will mainly be called at the end of the forward model, but can also - be called manually from external scope. -*/ - - -static int enkf_state_internalize_results(enkf_state_type * enkf_state , run_arg_type * run_arg , stringlist_type * msg_list) { - model_config_type * model_config = enkf_state->shared_info->model_config; - forward_load_context_type * load_context = enkf_state_alloc_load_context( enkf_state , run_arg , msg_list); - int report_step; - - /* - The timing information - i.e. mainly what is the last report step - in these results are inferred from the loading of summary results, - hence we must load the summary results first. - */ - - enkf_state_internalize_dynamic_eclipse_results(enkf_state , - load_context , - model_config); - { - enkf_fs_type * result_fs = run_arg_get_result_fs( run_arg ); - int last_report = time_map_get_last_step( enkf_fs_get_time_map( result_fs )); - if (last_report < 0) - last_report = model_config_get_last_history_restart( enkf_state->shared_info->model_config); - - /* Ensure that the last step is internalized? */ - model_config_set_internalize_state( model_config , last_report); - - for (report_step = run_arg_get_load_start( run_arg ); report_step <= last_report; report_step++) { - bool store_vectors = (report_step == last_report) ? true : false; - if (model_config_load_state( model_config , report_step)) - enkf_state_internalize_eclipse_state(enkf_state , - load_context , - model_config , - report_step , - store_vectors); - } - - enkf_state_internalize_GEN_DATA(enkf_state , load_context , model_config , last_report); - enkf_state_internalize_custom_kw(enkf_state, load_context , model_config); - } - - - int result = forward_load_context_get_result(load_context); - forward_load_context_free( load_context ); - return result; -} - - -int enkf_state_forward_init(enkf_state_type * enkf_state , - run_arg_type * run_arg) { - - int result = 0; - if (run_arg_get_step1(run_arg) == 0) { - int iens = enkf_state_get_iens( enkf_state ); - hash_iter_type * iter = hash_iter_alloc( enkf_state->node_hash ); - while ( !hash_iter_is_complete(iter) ) { - enkf_node_type * node = hash_iter_get_next_value(iter); - if (enkf_node_use_forward_init(node)) { - enkf_fs_type * result_fs = run_arg_get_result_fs( run_arg ); - node_id_type node_id = {.report_step = 0 , - .iens = iens }; - - - /* - Will not reinitialize; i.e. it is essential that the - forward model uses the state given from the stored - instance, and not from the current run of e.g. RMS. - */ - - if (!enkf_node_has_data( node , result_fs , node_id)) { - if (enkf_node_forward_init(node , run_arg_get_runpath( run_arg ) , iens )) - enkf_node_store( node , result_fs , false , node_id ); - else { - char * init_file = enkf_config_node_alloc_initfile( enkf_node_get_config( node ) , run_arg_get_runpath(run_arg) , iens ); - - if (init_file && !util_file_exists( init_file )) - fprintf(stderr,"File not found: %s - failed to initialize node: %s\n", init_file , enkf_node_get_key( node )); - else - fprintf(stderr,"Failed to initialize node: %s\n", enkf_node_get_key( node )); - - util_safe_free( init_file ); - result |= LOAD_FAILURE; - } - } - - } - } - hash_iter_free( iter ); - } - return result; -} - - - -int enkf_state_load_from_forward_model(enkf_state_type * enkf_state , - run_arg_type * run_arg , - stringlist_type * msg_list) { - - int result = 0; - - if (ensemble_config_have_forward_init( enkf_state->ensemble_config )) - result |= enkf_state_forward_init( enkf_state , run_arg ); - - result |= enkf_state_internalize_results( enkf_state , run_arg , msg_list ); - { - state_map_type * state_map = enkf_fs_get_state_map( run_arg_get_result_fs( run_arg ) ); - int iens = member_config_get_iens( enkf_state->my_config ); - if (result & LOAD_FAILURE) - state_map_iset( state_map , iens , STATE_LOAD_FAILURE); - else - state_map_iset( state_map , iens , STATE_HAS_DATA); - } - - return result; -} - - -/** - Observe that this does not return the loadOK flag; it will load as - good as it can all the data it should, and be done with it. -*/ - -void * enkf_state_load_from_forward_model_mt( void * arg ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - enkf_state_type * enkf_state = enkf_state_safe_cast(arg_pack_iget_ptr( arg_pack , 0 )); - run_arg_type * run_arg = arg_pack_iget_ptr( arg_pack , 1 ); - stringlist_type * msg_list = arg_pack_iget_ptr( arg_pack , 2 ); - bool manual_load = arg_pack_iget_bool( arg_pack , 3 ); - int * result = arg_pack_iget_ptr( arg_pack , 4 ); - int iens = run_arg_get_iens( run_arg ); - - if (manual_load) - state_map_update_undefined(enkf_fs_get_state_map( run_arg_get_result_fs(run_arg) ) , iens , STATE_INITIALIZED); - - *result = enkf_state_load_from_forward_model( enkf_state , run_arg , msg_list ); - if (*result & REPORT_STEP_INCOMPATIBLE) { - // If refcase has been used for observations: crash and burn. - fprintf(stderr,"** Warning the timesteps in refcase and current simulation are not in accordance - something wrong with schedule file?\n"); - *result -= REPORT_STEP_INCOMPATIBLE; - } - - if (manual_load) { - printf("."); - fflush(stdout); - } - return NULL; -} - - - - - - - -/** - This function writes out all the files needed by an ECLIPSE simulation, this - includes the restart file, and the various INCLUDE files corresponding to - parameteres estimated by EnKF. - - The writing of restart file is delegated to enkf_state_write_restart_file(). -*/ - -void enkf_state_ecl_write(enkf_state_type * enkf_state, const run_arg_type * run_arg , enkf_fs_type * fs) { - { - /** - This iteration manipulates the hash (thorugh the enkf_state_del_node() call) - - ----------------------------------------------------------------------------------------- - T H I S W I L L D E A D L O C K I F T H E H A S H _ I T E R A P I I S U S E D. - ----------------------------------------------------------------------------------------- - */ - - const shared_info_type * shared_info = enkf_state->shared_info; - const model_config_type * model_config = shared_info->model_config; - int iens = enkf_state_get_iens( enkf_state ); - const char * base_name = model_config_get_gen_kw_export_file(model_config); - char * export_file_name = util_alloc_filename( run_arg_get_runpath( run_arg ) , base_name , NULL); - FILE * export_file = util_mkdir_fopen(export_file_name, "w"); - - - const int num_keys = hash_get_size(enkf_state->node_hash); - char ** key_list = hash_alloc_keylist(enkf_state->node_hash); - int ikey; - - for (ikey = 0; ikey < num_keys; ikey++) { - if (true) { - enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , key_list[ikey]); - bool forward_init = enkf_node_use_forward_init( enkf_node ); - - if ((run_arg_get_step1(run_arg) == 0) && (forward_init)) { - node_id_type node_id = {.report_step = 0, - .iens = iens }; - - if (enkf_node_has_data( enkf_node , fs , node_id)) - enkf_node_ecl_write(enkf_node , run_arg_get_runpath( run_arg ) , export_file , run_arg_get_step1(run_arg)); - } else - enkf_node_ecl_write(enkf_node , run_arg_get_runpath( run_arg ) , export_file , run_arg_get_step1(run_arg)); - } - } - util_free_stringlist(key_list , num_keys); - - fclose(export_file); - free(export_file_name); - } -} - - -/** - This function takes a report_step and a analyzed|forecast state as - input; the enkf_state instance is set accordingly and written to - disk. -*/ - - -void enkf_state_fwrite(const enkf_state_type * enkf_state , enkf_fs_type * fs , int mask , int report_step ) { - const member_config_type * my_config = enkf_state->my_config; - const int num_keys = hash_get_size(enkf_state->node_hash); - char ** key_list = hash_alloc_keylist(enkf_state->node_hash); - int ikey; - - for (ikey = 0; ikey < num_keys; ikey++) { - enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , key_list[ikey]); - if (enkf_node_include_type(enkf_node , mask)) { - node_id_type node_id = {.report_step = report_step , .iens = member_config_get_iens( my_config ) }; - enkf_node_store( enkf_node, fs , true , node_id ); - } - } - util_free_stringlist(key_list , num_keys); -} - - -void enkf_state_fread(enkf_state_type * enkf_state , enkf_fs_type * fs , int mask , int report_step ) { - const member_config_type * my_config = enkf_state->my_config; - const int num_keys = hash_get_size(enkf_state->node_hash); - char ** key_list = hash_alloc_keylist(enkf_state->node_hash); - int ikey; - - for (ikey = 0; ikey < num_keys; ikey++) { - enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , key_list[ikey]); - if (enkf_node_include_type(enkf_node , mask)) { - node_id_type node_id = {.report_step = report_step , - .iens = member_config_get_iens( my_config )}; - bool forward_init = enkf_node_use_forward_init( enkf_node ); - if (forward_init) - enkf_node_try_load(enkf_node , fs , node_id ); - else - enkf_node_load(enkf_node , fs , node_id); - } - } - util_free_stringlist(key_list , num_keys); -} - - -/** - This function will load all the nodes listed in the current - restart_kw_list; in addition to all other variable of type - DYNAMIC_STATE. Observe that for DYNAMIC state nodes it will try - firt analyzed state and then forecast state. -*/ - - -static void enkf_state_fread_state_nodes(enkf_state_type * enkf_state , enkf_fs_type * fs , int report_step ) { - const member_config_type * my_config = enkf_state->my_config; - const int iens = member_config_get_iens( my_config ); - - /* - First pass - load all the STATIC nodes. It is essential to use - the restart_kw_list when loading static nodes, otherwise static - nodes which were only present at e.g. step == 0 will create - problems: (They are in the enkf_state hash table because they - were seen at step == 0, but have not been seen subesquently and - the loading fails.) - */ - - /* Second pass - DYNAMIC state nodes. */ - { - const int num_keys = hash_get_size(enkf_state->node_hash); - char ** key_list = hash_alloc_keylist(enkf_state->node_hash); - int ikey; - - for (ikey = 0; ikey < num_keys; ikey++) { - enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , key_list[ikey]); - enkf_var_type var_type = enkf_node_get_var_type( enkf_node ); - node_id_type node_id = {.report_step = report_step , - .iens = iens }; - - if (var_type == DYNAMIC_STATE) { - /* - Here the enkf_node_try_load() function is used NOT because we accept - that the node is not present, but because the try_fread() - function accepts the BOTH state type. - */ - if (!enkf_node_try_load(enkf_node , fs , node_id)) - util_abort("%s: failed to load node:%s report_step:%d iens:%d \n",__func__ , key_list[ikey] , report_step , iens ); - } - } - util_free_stringlist(key_list , num_keys); - } -} - - - -/** - This is a special function which is only used to load the initial - state of dynamic_state nodes. It checks if the enkf_config_node has - set a valid value for input_file, in that case that means we should - also have an internalized representation of it, otherwise it will - just return (i.e. for PRESSURE / SWAT). -*/ - -static void enkf_state_fread_initial_state(enkf_state_type * enkf_state , enkf_fs_type * fs) { - const member_config_type * my_config = enkf_state->my_config; - const int num_keys = hash_get_size(enkf_state->node_hash); - char ** key_list = hash_alloc_keylist(enkf_state->node_hash); - int ikey; - - for (ikey = 0; ikey < num_keys; ikey++) { - enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , key_list[ikey]); - if (enkf_node_get_var_type(enkf_node) == DYNAMIC_STATE) { - const enkf_config_node_type * config_node = enkf_node_get_config( enkf_node ); - - /* Just checked for != NULL */ - char * load_file = enkf_config_node_alloc_infile( config_node , 0); - if (load_file != NULL) { - node_id_type node_id = {.report_step = 0 , - .iens = member_config_get_iens( my_config ) }; - enkf_node_load(enkf_node , fs , node_id); - } - - util_safe_free( load_file ); - } - } - util_free_stringlist(key_list , num_keys); -} - - -void enkf_state_free_nodes(enkf_state_type * enkf_state, int mask) { - const int num_keys = hash_get_size(enkf_state->node_hash); - char ** key_list = hash_alloc_keylist(enkf_state->node_hash); - int ikey; - - for (ikey = 0; ikey < num_keys; ikey++) { - enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , key_list[ikey]); - if (enkf_node_include_type(enkf_node , mask)) - enkf_state_del_node(enkf_state , enkf_node_get_key(enkf_node)); - } - util_free_stringlist(key_list , num_keys); -} - - - - - - -void enkf_state_free(enkf_state_type *enkf_state) { - rng_free( enkf_state->rng ); - hash_free(enkf_state->node_hash); - subst_list_free(enkf_state->subst_list); - member_config_free(enkf_state->my_config); - shared_info_free(enkf_state->shared_info); - free(enkf_state); -} - - - -enkf_node_type * enkf_state_get_node(const enkf_state_type * enkf_state , const char * node_key) { - if (hash_has_key(enkf_state->node_hash , node_key)) { - enkf_node_type * enkf_node = hash_get(enkf_state->node_hash , node_key); - return enkf_node; - } else { - util_abort("%s: node:[%s] not found in state object - aborting.\n",__func__ , node_key); - return NULL; /* Compiler shut up */ - } -} - - - -void enkf_state_del_node(enkf_state_type * enkf_state , const char * node_key) { - if (hash_has_key(enkf_state->node_hash , node_key)) - hash_del(enkf_state->node_hash , node_key); - else - fprintf(stderr,"%s: tried to remove node:%s which is not in state - internal error?? \n",__func__ , node_key); -} - - -/** - This function will set all the subst_kw key=value pairs which - change with report step. -*/ - -static void enkf_state_set_dynamic_subst_kw__(enkf_state_type * enkf_state , const char * run_path , int step1 , int step2) { - const ecl_config_type * ecl_config = enkf_state->shared_info->ecl_config; - const bool fmt_file = ecl_config_get_formatted( ecl_config ); - - - if (run_path != NULL) { - /** Make absolutely sure the path available as is absolute. */ - char * abs_runpath = util_alloc_realpath( run_path ); - enkf_state_add_subst_kw(enkf_state , "RUNPATH" , abs_runpath , NULL); - free( abs_runpath ); - } - - - /* Time step */ - { - char * step1_s = util_alloc_sprintf("%d" , step1); - char * step2_s = util_alloc_sprintf("%d" , step2); - char * step1_s04 = util_alloc_sprintf("%04d" , step1); - char * step2_s04 = util_alloc_sprintf("%04d" , step2); - - enkf_state_add_subst_kw(enkf_state , "TSTEP1" , step1_s , NULL); - enkf_state_add_subst_kw(enkf_state , "TSTEP2" , step2_s , NULL); - enkf_state_add_subst_kw(enkf_state , "TSTEP1_04" , step1_s04 , NULL); - enkf_state_add_subst_kw(enkf_state , "TSTEP2_04" , step2_s04 , NULL); - - free(step1_s); - free(step2_s); - free(step1_s04); - free(step2_s04); - } - - - /* Restart file names and RESTART keyword in datafile. */ - { - const char * eclbase = member_config_get_eclbase( enkf_state->my_config ); - if (eclbase != NULL) { - { - char * restart_file1 = ecl_util_alloc_filename(NULL , eclbase , ECL_RESTART_FILE , fmt_file , step1); - char * restart_file2 = ecl_util_alloc_filename(NULL , eclbase , ECL_RESTART_FILE , fmt_file , step2); - - enkf_state_add_subst_kw(enkf_state , "RESTART_FILE1" , restart_file1 , NULL); - enkf_state_add_subst_kw(enkf_state , "RESTART_FILE2" , restart_file2 , NULL); - - free(restart_file1); - free(restart_file2); - } - - if (step1 > 0) { - char * data_initialize = util_alloc_sprintf("RESTART\n \'%s\' %d /\n" , eclbase , step1); - enkf_state_add_subst_kw(enkf_state , "INIT" , data_initialize , NULL); - free(data_initialize); - } - } - } - - /** - The magic string: - */ - if (step1 == 0) { - const char * init_file = ecl_config_get_equil_init_file(ecl_config); - if (init_file != NULL) { - char * tmp_include = util_alloc_sprintf("INCLUDE\n \'%s\' /\n",init_file); - enkf_state_add_subst_kw(enkf_state , "INIT" , tmp_include , NULL); - free(tmp_include); - } /* - if init_file == NULL that means the user has not supplied the INIT_SECTION keyword, - and the EQUIL (or whatever) info to initialize the model is inlined in the datafile. - */ - } - - - { - /** - Adding keys for and - these are only - added for backwards compatibility, should be replaced with - prober function callbacks. - */ - char * randint_value = util_alloc_sprintf( "%u" , rng_forward( enkf_state->rng )); - char * randfloat_value = util_alloc_sprintf( "%12.10f" , rng_get_double( enkf_state->rng )); - - enkf_state_add_subst_kw( enkf_state , "RANDINT" , randint_value , NULL); - enkf_state_add_subst_kw( enkf_state , "RANDFLOAT" , randfloat_value , NULL); - - free( randint_value ); - free( randfloat_value ); - } -} - -static void enkf_state_set_dynamic_subst_kw(enkf_state_type * enkf_state , const run_arg_type * run_arg ) { - enkf_state_set_dynamic_subst_kw__( enkf_state , run_arg_get_runpath( run_arg ) , run_arg_get_step1( run_arg ) , run_arg_get_step2( run_arg )); -} - - - -void enkf_state_printf_subst_list(enkf_state_type * enkf_state , int step1 , int step2) { - int ikw; - const char * fmt_string = "%-16s %-40s :: %s\n"; - printf("\n\n"); - printf(fmt_string , "Key" , "Current value" , "Description"); - printf("------------------------------------------------------------------------------------------------------------------------\n"); - if (step1 >= 0) - enkf_state_set_dynamic_subst_kw__(enkf_state , NULL , step1 , step2 ); - - for (ikw = 0; ikw < subst_list_get_size( enkf_state->subst_list ); ikw++) { - const char * key = subst_list_iget_key( enkf_state->subst_list , ikw); - const char * value = subst_list_iget_value( enkf_state->subst_list , ikw); - const char * desc = subst_list_iget_doc_string( enkf_state->subst_list , ikw ); - - if (value != NULL) - printf(fmt_string , key , value , desc); - else - printf(fmt_string , key , "[Not set]" , desc); - } - printf("------------------------------------------------------------------------------------------------------------------------\n"); - -} - - - - -/** - init_step : The parameters are loaded from this EnKF/report step. - report_step1 : The simulation should start from this report step; - dynamic data are loaded from this step. - report_step2 : The simulation should stop at this report step. (unless run_mode == ENSEMBLE_PREDICTION - where it just runs til end.) - - For a normal EnKF run we well have init_step == report_step1, but - in the case where we want rerun from the beginning with updated - parameters, they will be different. If init_step != report_step1, - it is required that report_step1 == 0; otherwise the dynamic data - will become completely inconsistent. We just don't allow that! -*/ - - -void enkf_state_init_eclipse(enkf_state_type *enkf_state, const run_arg_type * run_arg ) { - const member_config_type * my_config = enkf_state->my_config; - const ecl_config_type * ecl_config = enkf_state->shared_info->ecl_config; - { - if (member_config_pre_clear_runpath( my_config )) - util_clear_directory( run_arg_get_runpath( run_arg ) , true , false ); - - util_make_path(run_arg_get_runpath( run_arg )); - { - if (ecl_config_get_schedule_target( ecl_config ) != NULL) { - - char * schedule_file_target = util_alloc_filename(run_arg_get_runpath( run_arg ) , ecl_config_get_schedule_target( ecl_config ) , NULL); - char * schedule_file_target_path = util_split_alloc_dirname(schedule_file_target); - util_make_path(schedule_file_target_path); - free(schedule_file_target_path); - - sched_file_fprintf( ecl_config_get_sched_file( ecl_config ) , schedule_file_target); - - free(schedule_file_target); - } - } - - - /** - For reruns of various kinds the parameters and the state are - generally loaded from different timesteps: - */ - { - enkf_fs_type * init_fs = run_arg_get_init_fs( run_arg ); - /* Loading parameter information: loaded from timestep: run_arg->init_step_parameters. */ - enkf_state_fread(enkf_state , init_fs , PARAMETER , 0); - - - /* Loading state information: loaded from timestep: run_arg->step1 */ - if (run_arg_get_step1(run_arg) == 0) - enkf_state_fread_initial_state(enkf_state , init_fs); - else - enkf_state_fread_state_nodes( enkf_state , init_fs , run_arg_get_step1(run_arg)); - - enkf_state_set_dynamic_subst_kw( enkf_state , run_arg ); - ert_templates_instansiate( enkf_state->shared_info->templates , run_arg_get_runpath( run_arg ) , enkf_state->subst_list ); - enkf_state_ecl_write( enkf_state , run_arg , init_fs); - - if (member_config_get_eclbase( my_config ) != NULL) { - - /* Writing the ECLIPSE data file. */ - if (ecl_config_get_data_file( ecl_config ) != NULL) { - char * data_file = ecl_util_alloc_filename(run_arg_get_runpath( run_arg ) , member_config_get_eclbase( my_config ) , ECL_DATA_FILE , true , -1); - subst_list_filter_file(enkf_state->subst_list , ecl_config_get_data_file(ecl_config) , data_file); - free( data_file ); - } - } - } - member_config_get_jobname( my_config ); - mode_t umask = site_config_get_umask(enkf_state->shared_info->site_config); - - - /* This is where the job script is created */ - forward_model_python_fprintf( model_config_get_forward_model( enkf_state->shared_info->model_config ) , - run_arg_get_runpath( run_arg ) , - enkf_state->subst_list, - umask); - } -} - - - - - - - -bool enkf_state_complete_forward_modelOK__(void * arg ); -bool enkf_state_complete_forward_modelEXIT__(void * arg ); -bool enkf_state_complete_forward_modelRETRY__(void * arg ); - - -/** - This function is called when: - - 1. The external queue system has said that everything is OK; BUT - the ert layer failed to load all the data. - - 2. The external queue system has seen the job fail. - - The parameter and state variables will be resampled before - retrying. And all random elements in templates+++ will be - resampled. -*/ - - - -static void enkf_state_internal_retry(enkf_state_type * enkf_state , run_arg_type * run_arg , bool load_failure) { - const member_config_type * my_config = enkf_state->my_config; - const shared_info_type * shared_info = enkf_state->shared_info; - const int iens = member_config_get_iens( my_config ); - - if (load_failure) - ert_log_add_fmt_message( 1 , NULL , "[%03d:%04d - %04d] Failed to load all data.",iens , run_arg_get_step1(run_arg) , run_arg_get_step2(run_arg)); - else - ert_log_add_fmt_message( 1 , NULL , "[%03d:%04d - %04d] Forward model failed.",iens, run_arg_get_step1(run_arg) , run_arg_get_step2(run_arg)); - - if (run_arg_can_retry( run_arg ) ) { - ert_log_add_fmt_message( 1 , NULL , "[%03d] Resampling and resubmitting realization." ,iens); - { - /* Reinitialization of the nodes */ - stringlist_type * init_keys = ensemble_config_alloc_keylist_from_var_type( enkf_state->ensemble_config , DYNAMIC_STATE + PARAMETER ); - for (int ikey=0; ikey < stringlist_get_size( init_keys ); ikey++) { - enkf_node_type * node = enkf_state_get_node( enkf_state , stringlist_iget( init_keys , ikey) ); - enkf_node_initialize( node , iens , enkf_state->rng ); - } - stringlist_free( init_keys ); - } - - enkf_state_init_eclipse( enkf_state , run_arg ); /* Possibly clear the directory and do a FULL rewrite of ALL the necessary files. */ - job_queue_iset_external_restart( shared_info->job_queue , run_arg_get_queue_index(run_arg) ); /* Here we inform the queue system that it should pick up this job and try again. */ - run_arg_increase_submit_count( run_arg ); - } -} - - - - - - - - - - - -static void enkf_state_clear_runpath( const enkf_state_type * enkf_state , run_arg_type * run_arg) { - const member_config_type * my_config = enkf_state->my_config; - keep_runpath_type keep_runpath = member_config_get_keep_runpath( my_config ); - - bool unlink_runpath; - if (keep_runpath == DEFAULT_KEEP) - unlink_runpath = false; /* For experiments the default is to keep the directories around. */ - else { - /* We have explcitly set a value for the keep_runpath variable - with either KEEP_RUNAPTH or DELETE_RUNPATH. */ - if (keep_runpath == EXPLICIT_KEEP) - unlink_runpath = false; - else if (keep_runpath == EXPLICIT_DELETE) - unlink_runpath = true; - else { - util_abort("%s: internal error \n",__func__); - unlink_runpath = false; /* Compiler .. */ - } - } - - if (unlink_runpath) - util_clear_directory(run_arg_get_runpath( run_arg ) , true , true); -} - - -/** - Observe that if run_arg == false, this routine will return with - job_completeOK == true, that might be a bit misleading. - - Observe that if an internal retry is performed, this function will - be called several times - MUST BE REENTRANT. -*/ - -static bool enkf_state_complete_forward_modelOK(enkf_state_type * enkf_state , run_arg_type * run_arg) { - const member_config_type * my_config = enkf_state->my_config; - const int iens = member_config_get_iens( my_config ); - int result; - - - /** - The queue system has reported that the run is OK, i.e. it has - completed and produced the targetfile it should. We then check - in this scope whether the results can be loaded back; if that - is OK the final status is updated, otherwise: restart. - */ - ert_log_add_fmt_message( 2 , NULL , "[%03d:%04d-%04d] Forward model complete - starting to load results." , iens , run_arg_get_step1(run_arg), run_arg_get_step2(run_arg)); - result = enkf_state_load_from_forward_model(enkf_state , run_arg , NULL); - - if (result & REPORT_STEP_INCOMPATIBLE) { - // If refcase has been used for observations: crash and burn. - fprintf(stderr,"** Warning the timesteps in refcase and current simulation are not in accordance - something wrong with schedule file?\n"); - result -= REPORT_STEP_INCOMPATIBLE; - } - - - if (result == 0) { - /* - The loading succeded - so this is a howling success! We set - the main status to JOB_QUEUE_ALL_OK and inform the queue layer - about the success. In addition we set the simple status - (should be avoided) to JOB_RUN_OK. - */ - run_arg_set_run_status( run_arg , JOB_RUN_OK); - ert_log_add_fmt_message( 2 , NULL , "[%03d:%04d-%04d] Results loaded successfully." , iens , run_arg_get_step1(run_arg), run_arg_get_step2(run_arg)); - - enkf_state_clear_runpath( enkf_state , run_arg ); - run_arg_complete_run(run_arg); /* free() on runpath */ - } - - return (result == 0) ? true : false; -} - - -bool enkf_state_complete_forward_modelOK__(void * arg ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - enkf_state_type * enkf_state = enkf_state_safe_cast( arg_pack_iget_ptr( arg_pack , 0 )); - run_arg_type * run_arg = run_arg_safe_cast( arg_pack_iget_ptr( arg_pack , 1 )); - - return enkf_state_complete_forward_modelOK( enkf_state , run_arg); -} - - - -static bool enkf_state_complete_forward_model_EXIT_handler__(enkf_state_type * enkf_state , run_arg_type * run_arg , bool is_retry) { - const member_config_type * my_config = enkf_state->my_config; - const int iens = member_config_get_iens( my_config ); - /* - The external queue system has said that the job failed - we - might give it another try from this scope, possibly involving a - resampling. - */ - - if (is_retry) { - if (run_arg_can_retry(run_arg)) { - enkf_state_internal_retry(enkf_state, run_arg , false); - return true; - } else { - return false; - } - } else { - ert_log_add_fmt_message( 1, NULL, "[%03d:%04d-%04d] FAILED COMPLETELY.", iens, run_arg_get_step1(run_arg), run_arg_get_step2(run_arg)); - - if (run_arg_get_run_status(run_arg) != JOB_LOAD_FAILURE) - run_arg_set_run_status( run_arg , JOB_RUN_FAILURE); - - state_map_type * state_map = enkf_fs_get_state_map(run_arg_get_result_fs( run_arg )); - int iens = member_config_get_iens(enkf_state->my_config); - state_map_iset(state_map, iens, STATE_LOAD_FAILURE); - return false; - } -} - -static bool enkf_state_complete_forward_model_EXIT_handler(void * arg, bool allow_retry ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - - enkf_state_type * enkf_state = enkf_state_safe_cast( arg_pack_iget_ptr( arg_pack , 0 ) ); - run_arg_type * run_arg = run_arg_safe_cast( arg_pack_iget_ptr( arg_pack , 1 ) ); - - return enkf_state_complete_forward_model_EXIT_handler__( enkf_state , run_arg , allow_retry ); -} - - -bool enkf_state_complete_forward_modelEXIT__(void * arg ) { - return enkf_state_complete_forward_model_EXIT_handler(arg, false ); -} - -bool enkf_state_complete_forward_modelRETRY__(void * arg ) { - return enkf_state_complete_forward_model_EXIT_handler(arg, true ); -} - - - -/*****************************************************************/ - - -rng_type * enkf_state_get_rng( const enkf_state_type * enkf_state ) { - return enkf_state->rng; -} - -unsigned int enkf_state_get_random( enkf_state_type * enkf_state ) { - return rng_forward( enkf_state->rng ); -} - - - -void enkf_state_set_keep_runpath( enkf_state_type * enkf_state , keep_runpath_type keep_runpath) { - member_config_set_keep_runpath( enkf_state->my_config , keep_runpath); -} - - -keep_runpath_type enkf_state_get_keep_runpath( const enkf_state_type * enkf_state ) { - return member_config_get_keep_runpath( enkf_state->my_config ); -} - - -const ensemble_config_type * enkf_state_get_ensemble_config( const enkf_state_type * enkf_state ) { - return enkf_state->ensemble_config; -} diff --git a/ThirdParty/Ert/libenkf/src/enkf_types.c b/ThirdParty/Ert/libenkf/src/enkf_types.c deleted file mode 100644 index d010cbfc96..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_types.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_types.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include - -#include - - -/*****************************************************************/ - - -const char * enkf_types_get_var_name(enkf_var_type var_type) { - switch(var_type) { - case(INVALID): - return "INVALID"; - break; - case PARAMETER: - return "PARAMETER"; - break; - case DYNAMIC_STATE: - return "DYNAMIC_STATE"; - break; - case DYNAMIC_RESULT: - return "DYNAMIC_RESULT"; - break; - default: - util_abort("%s: internal error - unrecognized var type: %d - aborting \n",__func__ , var_type); - return NULL; - } -} - - - -const char * enkf_types_get_impl_name(ert_impl_type impl_type) { - switch(impl_type) { - case(INVALID): - return "INVALID"; - break; - case FIELD: - return "FIELD"; - break; - case GEN_KW: - return "GEN_KW"; - break; - case SUMMARY: - return "SUMMARY"; - break; - case GEN_DATA: - return "GEN_DATA"; - break; - default: - util_abort("%s: internal error - unrecognized implementation type: %d - aborting \n",__func__ , impl_type); - return NULL; - } -} - - - -#define if_strcmp(s) if (strcmp(impl_type_string , #s) == 0) impl_type = s -static ert_impl_type enkf_types_get_impl_type__(const char * impl_type_string) { - ert_impl_type impl_type; - if_strcmp(SUMMARY); - else if_strcmp(FIELD); - else if_strcmp(GEN_KW); - else if_strcmp(GEN_DATA); - else impl_type = INVALID; - return impl_type; -} -#undef if_strcmp - - -ert_impl_type enkf_types_get_impl_type(const char * __impl_type_string) { - char * impl_type_string = util_alloc_string_copy(__impl_type_string); - util_strupr(impl_type_string); - ert_impl_type impl_type = enkf_types_get_impl_type__(impl_type_string); - if (impl_type == INVALID) - util_abort("%s: enkf_type: %s not recognized - aborting \n",__func__ , __impl_type_string); - - free(impl_type_string); - return impl_type; -} - - -/* - This will return INVALIID if given an invalid - input string - not fail. -*/ - -ert_impl_type enkf_types_check_impl_type(const char * impl_type_string) { - return enkf_types_get_impl_type__(impl_type_string); -} - - -/*****************************************************************/ -/* - These two functions update the truncation variable to ensure that - it applies truncate_min and truncate_max respectively. The somewhat - involved implementation is to ensure that the functions can be - called many times. -*/ - - -void enkf_types_set_truncate_min(truncation_type * __trunc) { - truncation_type trunc = *__trunc; - - if (!(trunc & TRUNCATE_MIN)) - trunc += TRUNCATE_MIN; - - *__trunc = trunc; -} - - -void enkf_types_set_truncate_max(truncation_type * __trunc) { - truncation_type trunc = *__trunc; - - if (!(trunc & TRUNCATE_MAX)) - trunc += TRUNCATE_MAX; - - *__trunc = trunc; -} - - - - - diff --git a/ThirdParty/Ert/libenkf/src/enkf_util.c b/ThirdParty/Ert/libenkf/src/enkf_util.c deleted file mode 100644 index bcd43dd87d..0000000000 --- a/ThirdParty/Ert/libenkf/src/enkf_util.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'enkf_util.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - - - - -double enkf_util_rand_normal(double mean , double std , rng_type * rng) { - const double pi = 3.141592653589; - double R1 = rng_get_double( rng ); - double R2 = rng_get_double( rng ); - - return mean + std * sqrt(-2.0 * log(R1)) * cos(2.0 * pi * R2); -} - -void enkf_util_rand_stdnormal_vector(int size , double *R, rng_type * rng) { - int i; - for (i = 0; i < size; i++) - R[i] = enkf_util_rand_normal(0.0 , 1.0 , rng); -} - -/** - Vector containing a random permutation of the integers 1,...,size -*/ - -void enkf_util_randperm( int * P , int size , rng_type * rng) { - int k, tmp; - - for (k = 0; k < size; k++) - P[k] = k; - - while (size > 1) { - k = rng_get_int( rng , size ); - size--; - tmp = P[size]; - P[size] = P[k]; - P[k] = tmp; - } -} - - - -/*****************************************************************/ - -#define TRUNCATE(type , void_data , size , min_ptr , max_ptr) \ -{ \ - type * data = (type *) void_data; \ - type min_value = *((type *) min_ptr); \ - type max_value = *((type *) max_ptr); \ - int i; \ - for (i=0; i < size; i++) { \ - if (data[i] < min_value) \ - data[i] = min_value; \ - else if (data[i] > max_value) \ - data[i] = max_value; \ - } \ -} - -void enkf_util_truncate(void * void_data , int size , ecl_type_enum ecl_type , void * min_ptr , void *max_ptr) { - if (ecl_type == ECL_DOUBLE_TYPE) - TRUNCATE(double , void_data , size , min_ptr , max_ptr) - else if (ecl_type == ECL_FLOAT_TYPE) - TRUNCATE(float , void_data , size , min_ptr , max_ptr) - else if (ecl_type == ECL_INT_TYPE) - TRUNCATE(int , void_data , size , min_ptr , max_ptr) - else - util_abort("%s: unrecognized type - aborting \n",__func__); -} -#undef TRUNCATE - - - - -void enkf_util_assert_buffer_type(buffer_type * buffer, ert_impl_type target_type) { - ert_impl_type file_type; - file_type = buffer_fread_int(buffer); - if (file_type != target_type) - util_abort("%s: wrong target type in file (expected:%d got:%d) - aborting \n",__func__ , target_type , file_type); - -} - - -void enkf_util_fread_assert_target_type_from_buffer(char ** ptr , ert_impl_type target_type) { - ert_impl_type file_type; - util_fread_from_buffer( &file_type , sizeof file_type , 1 , ptr); - if (file_type != target_type) - util_abort("%s: wrong target type in file (expected:%d got:%d) - aborting \n",__func__ , target_type , file_type); -} - - -void enkf_util_fwrite_target_type(FILE * stream , ert_impl_type target_type) { - util_fwrite_int(target_type , stream); -} - - -/* -size_t util_copy_strided_vector(const void * _src, size_t src_size , int src_stride , void * _target , int target_stride , size_t target_size , int type_size , bool * complete) { - const char * src = (const char *) _src; - char * target = (char *) _target; - - size_t src_index; - size_t target_index = 0; - - for (src_index = 0; src_index < src_size; src_index++) { - size_t src_adress = src_index * type_size * src_stride; - size_t target_adress = target_index * type_size * target_stride; - memcpy(&target[target_adress] , &src[src_adress] , type_size); - target_index++; - if (target_index == target_size) { - if (src_index < (src_size - 1)) *complete = false; - break; - } - } - return target_index; -} - -*/ - - - -/** - Prompts the user for a filename, and reads the filename from - stdin. - - If the parameter 'auto_mkdir' is true, the path part of the - filename is created automagically. If 'must_exist' is true, the - function will loop until the user gives an existing filename. - - The filename given by the user is returned - it is the - responibility of the calling scope to free this memory. - - The options parameter is an integer, which is a sum of the - following alternatives: - - EXISTING_FILE = 1 - NEW_FILE = 2 - AUTO_MKDIR = 4 -*/ - -//char * enkf_util_scanf_alloc_filename(const char * prompt , int options) { -// if ((options & EXISTING_FILE) && (options & NEW_FILE)) -// util_abort("%s: internal error - asking for both new and existing file - impossible \n", __func__); -// { -// bool OK = true; -// char * _path; -// char file[1024]; -// do { -// printf("%s",prompt); -// scanf("%s" , file); -// util_alloc_file_components(file , &_path , NULL , NULL); -// if (_path != NULL) { -// if (!util_is_directory(_path)) -// if (options & AUTO_MKDIR) -// util_make_path(_path); -// free(_path); -// } -// -// if ((options & EXISTING_FILE) && (!util_file_exists(file))) -// OK = false; -// else if ((options & NEW_FILE) && (util_file_exists(file))) -// OK = false; -// -// } while (!OK); -// return util_alloc_string_copy(file); -// } -//} - - - -/** - This function prints the entries in data to a file. - - data is assumed to be num_colums pointers to double vectors of length num_rows. - Note that this is not the conventional C style naming. - - If summarize is true, the mean and standard deviation of each column will be printed. -*/ -#define PRINT_LINE(n,c,stream) { int _i; for (_i = 0; _i < (n); _i++) fputc(c , stream); fprintf(stream,"\n"); } -void enkf_util_fprintf_data(const int * index_column , const double ** data, const char * index_name , const char ** column_names, int num_rows, int num_columns, const bool * active , - bool summarize, FILE * stream) { - const int float_width = 9; - const int float_precision = 4; - - int * width = util_calloc((num_columns + 1) , sizeof * width ); - int total_width; - - double * mean = util_calloc(num_columns , sizeof * mean ); - double * stddev = util_calloc(num_columns , sizeof * stddev); - - /* Check the column_names. */ - for(int column_nr = 0; column_nr < num_columns; column_nr++) - { - if (column_names[column_nr] == NULL) - util_abort("%s: Trying to dereference NULL pointer.\n", __func__); - } - - /* Calculate the width of each column and the total width. */ - width[0] = strlen(index_name) + 1; - total_width = width[0]; - for (int column_nr = 0; column_nr < num_columns; column_nr++) { - if (active[column_nr]) { - if(column_names[column_nr] != NULL) - width[column_nr + 1] = util_int_max(strlen(column_names[column_nr]), 2 * float_width + 5) + 1; /* Must accomodate A +/- B */ - width[column_nr + 1] += ( 1 - (width[column_nr + 1] & 1)); /* Ensure odd length */ - total_width += width[column_nr + 1] + 1; - } - } - - /* Calculate the mean and std dev of each column. */ - for(int column_nr = 0; column_nr < num_columns; column_nr++) { - if (active[column_nr]) { - mean [column_nr] = util_double_vector_mean( num_rows, data[column_nr]); - stddev[column_nr] = util_double_vector_stddev(num_rows, data[column_nr]); - } - } - - { - util_fprintf_string(index_name , width[0] - 1 , true , stream); fprintf(stream , "|"); - for (int column_nr = 0; column_nr < num_columns; column_nr++) { - if (active[column_nr]) { - util_fprintf_string(column_names[column_nr] , width[column_nr + 1] , center_pad , stream); - fprintf(stream , "|"); - } - } - fprintf(stream , "\n"); - PRINT_LINE(total_width , '=' , stream); - - - if(summarize) - { - util_fprintf_string("Mean" , width[0] - 1 , true , stream); - fprintf(stream , "|"); - { - for (int column_nr = 0; column_nr < num_columns; column_nr++) { - if (active[column_nr]) { - int w = (width[column_nr + 1] - 5) / 2; - util_fprintf_double(mean[column_nr] , w , float_precision , 'g' , stream); - fprintf(stream , " +/- "); - util_fprintf_double(stddev[column_nr] , w , float_precision , 'g' , stream); - fprintf(stream , "|"); - } - } - fprintf(stream , "\n"); - } - PRINT_LINE(total_width , '-' , stream); - } - - - for (int row_nr = 0; row_nr < num_rows; row_nr++) { - util_fprintf_int(index_column[row_nr], width[0] - 1 , stream); /* This +1 is not general */ - fprintf(stream , "|"); - - for (int column_nr = 0; column_nr < num_columns; column_nr++) { - if (active[column_nr]) { - util_fprintf_double(data[column_nr][row_nr] , width[column_nr + 1] , float_precision , 'g' , stream); - fprintf(stream , "|"); - } - } - fprintf(stream , "\n"); - } - PRINT_LINE(total_width , '=' , stream); - } - - free(stddev); - free(mean); - free(width); -} -#undef PRINT_LINE - - -char * enkf_util_alloc_tagged_string(const char * s) { - return util_alloc_sprintf("%s%s%s" , DEFAULT_START_TAG , s , DEFAULT_END_TAG); -} - -char * enkf_util_alloc_detagged_string( const char * tagged_string) { - const char * s = &tagged_string[ strlen( DEFAULT_START_TAG ) ]; - return util_alloc_substring_copy( s , 0 , strlen( s ) - strlen( DEFAULT_END_TAG )); -} - - - - -/** - This function will compare two (key) strings. The function is - intended to be used when sorting observation keys in summary tables - of misfit. First the string is split on ':' - then the subsequent - sorting is as follows: - - 1. The number of items is compared, with fewer items coming first. - - 2. A normal string compare is performed on the second item. - - 3. A normal string compare on the first item. - - 4. A normal string compare of the input key. - - The main point of this whole complexity is what is the items 2 & 3; - this will guarantee that the different summary keys related to the - same well, i.e. WWCT:OP1, WGOR:OP_1 and WBHP:OP_1 will come - together. - -*/ - - -int enkf_util_compare_keys( const char * key1 , const char * key2 ) { - int cmp; - { - stringlist_type * items1 = stringlist_alloc_from_split( key1 , SUMMARY_KEY_JOIN_STRING ); - stringlist_type * items2 = stringlist_alloc_from_split( key2 , SUMMARY_KEY_JOIN_STRING ); - - /* 1: Compare number of items. */ - cmp = stringlist_get_size( items1 ) - stringlist_get_size( items2 ); - if (cmp == 0) { - /* 2: String compare on second item */ - if (stringlist_get_size( items1 ) >= 2) - cmp = strcmp( stringlist_iget( items1 , 1) , stringlist_iget( items2 , 1)); - } - - /* 3: String compare on first item */ - if (cmp == 0) - cmp = strcmp( stringlist_iget( items1 , 0) , stringlist_iget( items2 , 0)); - - /* String compare of the whole god damn thing. */ - if (cmp == 0) - cmp = strcmp( key1 , key2 ); - - stringlist_free( items2 ); - stringlist_free( items1 ); - } - return cmp; -} - - -int enkf_util_compare_keys__( const void * __key1 , const void * __key2 ) { - const char * key1 = (const char *) __key1; - const char * key2 = (const char *) __key2; - - return enkf_util_compare_keys( key1 , key2 ); -} - - diff --git a/ThirdParty/Ert/libenkf/src/ensemble_config.c b/ThirdParty/Ert/libenkf/src/ensemble_config.c deleted file mode 100644 index 974c0cfd4a..0000000000 --- a/ThirdParty/Ert/libenkf/src/ensemble_config.c +++ /dev/null @@ -1,1002 +0,0 @@ -/* - copyright (c) 2011 statoil asa, norway. - - the file 'ensemble_config.c' is part of ert - ensemble based reservoir tool. - - ert 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. - - ert 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include /* must have rw locking on the config_nodes ... */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define ENSEMBLE_CONFIG_TYPE_ID 8825306 - -struct ensemble_config_struct { - UTIL_TYPE_ID_DECLARATION; - pthread_mutex_t mutex; - char * gen_kw_format_string; /* format string used when creating gen_kw search/replace strings. */ - hash_type * config_nodes; /* a hash of enkf_config_node instances - which again conatin pointers to e.g. field_config objects. */ - field_trans_table_type * field_trans_table; /* a table of the transformations which are available to apply on fields. */ - const ecl_sum_type * refcase; /* a ecl_sum reference instance - can be null (not owned by the ensemble - config). is only used to check that summary keys are valid when adding. */ - bool have_forward_init; - summary_key_matcher_type * summary_key_matcher; -}; - - -UTIL_IS_INSTANCE_FUNCTION( ensemble_config , ENSEMBLE_CONFIG_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION( ensemble_config , ENSEMBLE_CONFIG_TYPE_ID ) - - -/** - setting the format string used to 'mangle' the string in the gen_kw - template files. consider the following example: - - parameter file - -------------- - multpv logunif 0.0001 0.10 - - - template file - ------------- - box - 1 10 1 10 1 5 / - - multpv 500*__multpv__ - - here the parameter file defines a parameter named 'multpv', and the - template file uses the marker string '__multpv__' which should be - replaced with a numerical value. for the current example the - gen_kw_format_string should have the value '__%s__'. - - there are no rules for the format string, but it _must_ contain a - '%s' placeholder which will be replaced with the parameter name - (this is not checked for). the function call creating a search - string from a parameter name is: - - tagged_string = util_alloc_sprintf( gen_kw_format_string , parameter_name ); - -*/ - -void ensemble_config_set_gen_kw_format( ensemble_config_type * ensemble_config , const char * gen_kw_format_string) { - if (!util_string_equal( gen_kw_format_string , ensemble_config->gen_kw_format_string)) { - stringlist_type * gen_kw_keys = ensemble_config_alloc_keylist_from_impl_type( ensemble_config , GEN_KW ); - int i; - ensemble_config->gen_kw_format_string = util_realloc_string_copy( ensemble_config->gen_kw_format_string , gen_kw_format_string ); - for (i=0; i < stringlist_get_size( gen_kw_keys ); i++) { - enkf_config_node_type * config_node = ensemble_config_get_node( ensemble_config , stringlist_iget( gen_kw_keys , i )); - gen_kw_config_update_tag_format( enkf_config_node_get_ref( config_node ) , gen_kw_format_string ); - } - stringlist_free( gen_kw_keys ); - } -} - - -const char * ensemble_config_get_gen_kw_format( const ensemble_config_type * ensemble_config ) { - return ensemble_config->gen_kw_format_string; -} - - -void ensemble_config_set_refcase( ensemble_config_type * ensemble_config , const ecl_sum_type * refcase) { - ensemble_config->refcase = refcase; -} - - - - -ensemble_config_type * ensemble_config_alloc( ) { - ensemble_config_type * ensemble_config = util_malloc(sizeof * ensemble_config ); - - UTIL_TYPE_ID_INIT( ensemble_config , ENSEMBLE_CONFIG_TYPE_ID ); - ensemble_config->config_nodes = hash_alloc(); - ensemble_config->field_trans_table = field_trans_table_alloc(); - ensemble_config->refcase = NULL; - ensemble_config->gen_kw_format_string = util_alloc_string_copy( DEFAULT_GEN_KW_TAG_FORMAT ); - ensemble_config->have_forward_init = false; - ensemble_config->summary_key_matcher = summary_key_matcher_alloc(); - pthread_mutex_init( &ensemble_config->mutex , NULL); - - return ensemble_config; -} - - - -void ensemble_config_free(ensemble_config_type * ensemble_config) { - hash_free( ensemble_config->config_nodes ); - field_trans_table_free( ensemble_config->field_trans_table ); - summary_key_matcher_free(ensemble_config->summary_key_matcher); - free( ensemble_config->gen_kw_format_string ); - free( ensemble_config ); -} - - - - - - - -ert_impl_type ensemble_config_impl_type(const ensemble_config_type *ensemble_config, const char * ecl_kw_name) { - ert_impl_type impl_type = INVALID; - - if (hash_has_key(ensemble_config->config_nodes , ecl_kw_name)) { - enkf_config_node_type * node = hash_get(ensemble_config->config_nodes , ecl_kw_name); - impl_type = enkf_config_node_get_impl_type(node); - } else - util_abort("%s: internal error: asked for implementation type of unknown node:%s \n",__func__ , ecl_kw_name); - - return impl_type; -} - - -enkf_var_type ensemble_config_var_type(const ensemble_config_type *ensemble_config, const char * ecl_kw_name) { - enkf_var_type var_type = INVALID_VAR; - - if (hash_has_key(ensemble_config->config_nodes , ecl_kw_name)) { - enkf_config_node_type * node = hash_get(ensemble_config->config_nodes , ecl_kw_name); - var_type = enkf_config_node_get_var_type(node); - } else - util_abort("%s: internal error: asked for implementation type of unknown node:%s \n",__func__ , ecl_kw_name); - - return var_type; -} - - - -bool ensemble_config_has_key(const ensemble_config_type * ensemble_config , const char * key) { - return hash_has_key( ensemble_config->config_nodes , key); -} - - - -enkf_config_node_type * ensemble_config_get_node(const ensemble_config_type * ensemble_config, const char * key) { - if (hash_has_key(ensemble_config->config_nodes , key)) { - enkf_config_node_type * node = hash_get(ensemble_config->config_nodes , key); - return node; - } else { - util_abort("%s: ens node:\"%s\" does not exist \n",__func__ , key); - return NULL; /* compiler shut up */ - } -} - -enkf_config_node_type * ensemble_config_get_or_create_summary_node(ensemble_config_type * ensemble_config, const char * key) { - if (!hash_has_key(ensemble_config->config_nodes , key)) { - ensemble_config_add_summary(ensemble_config, key, LOAD_FAIL_SILENT); - } - - return ensemble_config_get_node(ensemble_config, key); -} - -/** - this will remove the config node indexed by key, it will use the - function hash_safe_del(), which is thread_safe, and will not fail - if the node has already been removed from the hash. - - however - it is extremely important to ensure that all storage - nodes (which point to the config nodes) have been deleted before - calling this function. that is only assured by using - enkf_main_del_node(). -*/ - - -void ensemble_config_del_node(ensemble_config_type * ensemble_config, const char * key) { - hash_safe_del(ensemble_config->config_nodes , key); -} - - -bool ensemble_config_have_forward_init( const ensemble_config_type * ensemble_config ) { - return ensemble_config->have_forward_init; -} - -void ensemble_config_add_node( ensemble_config_type * ensemble_config , enkf_config_node_type * node) { - if (node) { - const char * key = enkf_config_node_get_key( node ); - if (ensemble_config_has_key(ensemble_config , key)) - util_abort("%s: a configuration object:%s has already been added - aborting \n",__func__ , key); - - hash_insert_hash_owned_ref(ensemble_config->config_nodes , key , node , enkf_config_node_free__); - ensemble_config->have_forward_init |= enkf_config_node_use_forward_init( node ); - } else - util_abort("%s: internal error - tried to add NULL node to ensemble configuration \n",__func__); -} - - - - - -void ensemble_config_add_obs_key(ensemble_config_type * ensemble_config , const char * key, const char * obs_key) { - enkf_config_node_type * config_node = hash_get(ensemble_config->config_nodes , key); - enkf_config_node_add_obs_key(config_node , obs_key); -} - - -void ensemble_config_clear_obs_keys(ensemble_config_type * ensemble_config) { - hash_iter_type * iter = hash_iter_alloc( ensemble_config->config_nodes ); - while (!hash_iter_is_complete( iter )) { - enkf_config_node_type * config_node = hash_iter_get_next_value( iter ); - enkf_config_node_clear_obs_keys( config_node ); - } - hash_iter_free( iter ); -} - - - - - - -void ensemble_config_add_config_items(config_parser_type * config) { - config_schema_item_type * item; - - /** - the two fault types are just added to the config object only to - be able to print suitable messages before exiting. - */ - - item = config_add_schema_item(config , "HAVANA_FAULT" , false ); - config_schema_item_set_argc_minmax(item , 2 , 2); - - item = config_add_schema_item(config , "MULTFLT" , false ); - config_schema_item_set_argc_minmax(item , 3 , 3 ); - config_schema_item_iset_type( item , 2 , CONFIG_EXISTING_PATH ); - - - /*****************************************************************/ - - - item = config_add_schema_item(config , GEN_KW_KEY , false ); - config_schema_item_set_argc_minmax(item , 4 , 6); - config_schema_item_iset_type( item , 1 , CONFIG_EXISTING_PATH ); - config_schema_item_iset_type( item , 3 , CONFIG_EXISTING_PATH ); - - - - item = config_add_key_value( config , GEN_KW_TAG_FORMAT_KEY , false , CONFIG_STRING); - item = config_add_schema_item(config , SCHEDULE_PREDICTION_FILE_KEY , false ); - /* scedhule_prediction_file filename */ - config_schema_item_set_argc_minmax(item , 1 , 3 ); - config_schema_item_iset_type( item , 0 , CONFIG_EXISTING_PATH ); - - - - enkf_config_node_add_GEN_PARAM_config_schema( config ); - enkf_config_node_add_GEN_DATA_config_schema( config ); - enkf_config_node_add_CUSTOM_KW_config_schema( config ); - - item = config_add_schema_item(config , SUMMARY_KEY , false ); /* can have several summary keys on each line. */ - config_schema_item_set_argc_minmax(item , 1 , CONFIG_DEFAULT_ARG_MAX); - - item = config_add_schema_item(config , CONTAINER_KEY , false ); /* can have several summary keys on each line. */ - config_schema_item_set_argc_minmax(item , 2 , CONFIG_DEFAULT_ARG_MAX); - - item = config_add_schema_item( config , SURFACE_KEY , false ); - config_schema_item_set_argc_minmax(item , 4 , 5 ); - - /* - the way config info is entered for fields is unfortunate because - it is difficult/impossible to let the config system handle run - time validation of the input. - */ - - item = config_add_schema_item(config , FIELD_KEY , false ); - config_schema_item_set_argc_minmax(item , 2 , CONFIG_DEFAULT_ARG_MAX); - config_schema_item_add_required_children(item , GRID_KEY); /* if you are using a field - you must have a grid. */ -} - - - -/* - The var type parameter is determined by inspecting the - combination of input parameters. It is possible to specify an - invalid input combination; that should be identified with a call - to gen_data_config_is_valid() in the calling scope. - - - PARAMETER: init_file_fmt != NULL - enkf_outfile_fmt != NULL - enkf_infile_fmt == NULL - - DYNAMIC_STATE: init_file_fmt != NULL - enkf_outfile_fmt != NULL - enkf_infile_fmt != NULL - - DYNAMIC_RESULT: init_file_fmt == NULL - enkf_outfile_fmt == NULL - enkf_infile_fmt != NULL - -*/ - -void ensemble_config_init_GEN_DATA( ensemble_config_type * ensemble_config , const config_content_type * config) { - if (config_content_has_item(config , GEN_DATA_KEY)) { - const config_content_item_type * item = config_content_get_item( config , GEN_DATA_KEY ); - int i; - for (i=0; i < config_content_item_get_size(item); i++) { - const config_content_node_type * node = config_content_item_iget_node( item , i ); - enkf_config_node_type * config_node = enkf_config_node_alloc_GEN_DATA_from_config( node ); - if (config_node) - ensemble_config_add_node( ensemble_config , config_node ); - - } - } -} - - -void ensemble_config_init_GEN_PARAM( ensemble_config_type * ensemble_config , const config_content_type * config) { - /* gen_param - should be unified with the gen_data*/ - if (config_content_has_item(config , GEN_PARAM_KEY)) { - const config_content_item_type * item = config_content_get_item( config , GEN_PARAM_KEY ); - for (int i=0; i < config_content_item_get_size(item); i++) { - const config_content_node_type * node = config_content_item_iget_node( item , i ); - enkf_config_node_type * config_node = enkf_config_node_alloc_GEN_PARAM_from_config( node ); - if (config_node) - ensemble_config_add_node( ensemble_config , config_node ); - - } - } -} - - -void ensemble_config_init_GEN_KW( ensemble_config_type * ensemble_config , const config_content_type * config ) { - if (config_content_has_item(config , GEN_KW_KEY)) { - const config_content_item_type * gen_kw_item = config_content_get_item( config , GEN_KW_KEY ); - int i; - for (i=0; i < config_content_item_get_size( gen_kw_item ); i++) { - config_content_node_type * node = config_content_item_iget_node( gen_kw_item , i ); - - const char * key = config_content_node_iget( node , 0 ); - const char * template_file = config_content_node_iget_as_path( node , 1 ); - const char * enkf_outfile = config_content_node_iget( node , 2 ); - const char * parameter_file = config_content_node_iget_as_path( node , 3 ); - hash_type * opt_hash = hash_alloc(); - - config_content_node_init_opt_hash( node , opt_hash , 4 ); - { - const char * forward_string = hash_safe_get( opt_hash , FORWARD_INIT_KEY ); - enkf_config_node_type * config_node; - bool forward_init = false; - - if (forward_string) { - if (!util_sscanf_bool( forward_string , &forward_init)) - fprintf(stderr,"** Warning: parsing %s as bool failed - using FALSE \n",forward_string); - } - - config_node = ensemble_config_add_gen_kw( ensemble_config , key , forward_init); - enkf_config_node_update_gen_kw( config_node , - enkf_outfile , - template_file , - parameter_file , - hash_safe_get( opt_hash , MIN_STD_KEY ) , - hash_safe_get( opt_hash , INIT_FILES_KEY)); - } - hash_free( opt_hash ); - } - } -} - -void ensemble_config_init_CUSTOM_KW(ensemble_config_type * ensemble_config, const config_content_type * config) { - if (config_content_has_item(config, CUSTOM_KW_KEY)) { - const config_content_item_type * custom_kw_item = config_content_get_item(config, CUSTOM_KW_KEY); - - for (int i = 0; i < config_content_item_get_size(custom_kw_item); i++) { - config_content_node_type * node = config_content_item_iget_node(custom_kw_item, i); - - const char * key = config_content_node_iget(node, 0); - const char * result_file = config_content_node_iget_as_path(node, 1); - const char * output_file = NULL; - - if(config_content_node_get_size(node) > 2) { - output_file = config_content_node_iget_as_path(node, 2); - } - - enkf_config_node_type * config_node = ensemble_config_add_custom_kw(ensemble_config, key, result_file, output_file); - enkf_config_node_update_custom_kw(config_node, result_file, output_file); - enkf_config_node_set_internalize(config_node, 0); - } - } -} - -void ensemble_config_init_SURFACE( ensemble_config_type * ensemble_config , const config_content_type * config ) { - if (config_content_has_item(config , SURFACE_KEY)) { - const config_content_item_type * item = config_content_get_item( config , SURFACE_KEY ); - int i; - for (i=0; i < config_content_item_get_size( item ); i++) { - const config_content_node_type * node = config_content_item_iget_node( item , i ); - const char * key = config_content_node_iget( node , 0 ); - { - hash_type * options = hash_alloc(); /* INIT_FILE: OUTPUT_FILE: BASE_SURFACE: */ - - config_content_node_init_opt_hash( node , options , 1 ); - { - const char * init_file_fmt = hash_safe_get( options , INIT_FILES_KEY ); - const char * output_file = hash_safe_get( options , OUTPUT_FILE_KEY); - const char * base_surface = hash_safe_get( options , BASE_SURFACE_KEY); - const char * min_std_file = hash_safe_get( options , MIN_STD_KEY); - const char * forward_string = hash_safe_get( options , FORWARD_INIT_KEY ); - bool forward_init = false; - - if (forward_string) { - if (!util_sscanf_bool( forward_string , &forward_init)) - fprintf(stderr,"** Warning: parsing %s as bool failed - using FALSE \n",forward_string); - } - - if ((init_file_fmt == NULL) || (output_file == NULL) || (base_surface == NULL)) { - fprintf(stderr,"** error: when entering a surface you must provide arguments:\n"); - fprintf(stderr,"** %s:/path/to/input/files%%d \n",INIT_FILES_KEY); - fprintf(stderr,"** %s:name_of_output_file\n", OUTPUT_FILE_KEY); - fprintf(stderr,"** %s:base_surface_file\n",BASE_SURFACE_KEY); - exit(1); - } - - { - enkf_config_node_type * config_node = ensemble_config_add_surface( ensemble_config , key , forward_init); - enkf_config_node_update_surface( config_node , base_surface , init_file_fmt , output_file , min_std_file ); - } - } - hash_free( options ); - } - } - } -} - - -void ensemble_config_init_SUMMARY( ensemble_config_type * ensemble_config , const config_content_type * config , const ecl_sum_type * refcase) { - if (config_content_has_item(config , SUMMARY_KEY)) { - const config_content_item_type * item = config_content_get_item( config , SUMMARY_KEY ); - int i; - for (i=0; i < config_content_item_get_size( item ); i++) { - const config_content_node_type * node = config_content_item_iget_node( item , i ); - int j; - for (j= 0; j < config_content_node_get_size( node ); j++) { - const char * key = config_content_node_iget( node , j ); - summary_key_matcher_add_summary_key(ensemble_config->summary_key_matcher, key); - - if (util_string_has_wildcard( key )) { - //todo: DEPRECATED. In the Future the matcher should take care of this. - if (ensemble_config->refcase != NULL) { - int k; - stringlist_type * keys = stringlist_alloc_new ( ); - - ecl_sum_select_matching_general_var_list( ensemble_config->refcase , key , keys ); /* expanding the wildcard notation with help of the refcase. */ - for (k=0; k < stringlist_get_size( keys ); k++) - ensemble_config_add_summary(ensemble_config , stringlist_iget(keys , k) , LOAD_FAIL_SILENT ); - - stringlist_free( keys ); - } - } else - ensemble_config_add_summary(ensemble_config , key , LOAD_FAIL_SILENT); - } - } - } -} - - -void ensemble_config_init_FIELD( ensemble_config_type * ensemble_config , const config_content_type * config , ecl_grid_type * grid) { - if (config_content_has_item(config , FIELD_KEY)) { - const config_content_item_type * item = config_content_get_item( config , FIELD_KEY ); - int i; - for (i=0; i < config_content_item_get_size( item ); i++) { - const config_content_node_type * node = config_content_item_iget_node( item , i ); - const char * key = config_content_node_iget( node , 0 ); - const char * var_type_string = config_content_node_iget( node , 1 ); - enkf_config_node_type * config_node; - - { - hash_type * options = hash_alloc(); - - int truncation = TRUNCATE_NONE; - double value_min = -1; - double value_max = -1; - - config_content_node_init_opt_hash( node , options , 2 ); - if (hash_has_key( options , MIN_KEY)) { - truncation |= TRUNCATE_MIN; - value_min = atof(hash_get( options , MIN_KEY)); - } - - if (hash_has_key( options , MAX_KEY)) { - truncation |= TRUNCATE_MAX; - value_max = atof(hash_get( options , MAX_KEY)); - } - - - if (strcmp(var_type_string , DYNAMIC_KEY) == 0) { - config_node = ensemble_config_add_field( ensemble_config , key , grid , false); - enkf_config_node_update_state_field( config_node , truncation , value_min , value_max ); - } else if (strcmp(var_type_string , PARAMETER_KEY) == 0) { - const char * ecl_file = config_content_node_iget( node , 2 ); - const char * init_file_fmt = hash_safe_get( options , INIT_FILES_KEY ); - const char * init_transform = hash_safe_get( options , INIT_TRANSFORM_KEY ); - const char * output_transform = hash_safe_get( options , OUTPUT_TRANSFORM_KEY ); - const char * min_std_file = hash_safe_get( options , MIN_STD_KEY ); - const char * forward_string = hash_safe_get( options , FORWARD_INIT_KEY ); - bool forward_init = false; - - if (forward_string) { - if (!util_sscanf_bool( forward_string , &forward_init)) - fprintf(stderr,"** Warning: parsing %s as bool failed - using FALSE \n",forward_string); - } - config_node = ensemble_config_add_field( ensemble_config , key , grid , forward_init); - enkf_config_node_update_parameter_field( config_node, - ecl_file , - init_file_fmt , - min_std_file , - truncation , - value_min , - value_max , - init_transform , - output_transform ); - } else if (strcmp(var_type_string , GENERAL_KEY) == 0) { - /* General - not really interesting .. */ - const char * ecl_file = config_content_node_iget( node , 2 ); - const char * enkf_infile = config_content_node_iget( node , 3 ); - const char * init_file_fmt = hash_safe_get( options , INIT_FILES_KEY ); - const char * init_transform = hash_safe_get( options , INIT_TRANSFORM_KEY ); - const char * output_transform = hash_safe_get( options , OUTPUT_TRANSFORM_KEY ); - const char * input_transform = hash_safe_get( options , INPUT_TRANSFORM_KEY ); - const char * min_std_file = hash_safe_get( options , MIN_STD_KEY ); - const char * forward_string = hash_safe_get( options , FORWARD_INIT_KEY ); - bool forward_init = false; - - if (forward_string) { - if (!util_sscanf_bool( forward_string , &forward_init)) - fprintf(stderr,"** Warning: parsing %s as bool failed - using FALSE \n",forward_string); - } - - config_node = ensemble_config_add_field( ensemble_config , key , grid , forward_init); - enkf_config_node_update_general_field( config_node, - ecl_file , - enkf_infile , - init_file_fmt , - min_std_file , - truncation , value_min , value_max , - init_transform , - input_transform , - output_transform); - - - } else - util_abort("%s: field type: %s is not recognized\n",__func__ , var_type_string); - - hash_free( options ); - } - } - } -} - - - -/** - observe that if the user has not given a refcase with the refcase - key the refcase pointer will be NULL. in that case it will be - impossible to use wildcards when expanding summary variables. -*/ - -void ensemble_config_init(ensemble_config_type * ensemble_config , const config_content_type * config , ecl_grid_type * grid, const ecl_sum_type * refcase) { - int i; - ensemble_config_set_refcase( ensemble_config , refcase ); - - if (config_content_has_item( config , GEN_KW_TAG_FORMAT_KEY)) { - ensemble_config_set_gen_kw_format( ensemble_config , config_content_iget( config , GEN_KW_TAG_FORMAT_KEY , 0 , 0 )); - } - - ensemble_config_init_GEN_PARAM( ensemble_config , config ); - ensemble_config_init_GEN_DATA( ensemble_config , config ); - ensemble_config_init_CUSTOM_KW(ensemble_config, config); - ensemble_config_init_GEN_KW(ensemble_config , config ); - ensemble_config_init_SURFACE( ensemble_config , config ); - - ensemble_config_init_SUMMARY( ensemble_config , config , refcase ); - - ensemble_config_init_FIELD( ensemble_config , config , grid ); - - - /* Containers - this must come last, to ensure that the other nodes have been added. */ - { - for (i=0; i < config_content_get_occurences(config , CONTAINER_KEY ); i++) { - const stringlist_type * container_kw_list = config_content_iget_stringlist_ref(config , CONTAINER_KEY , i); - const char * container_key = stringlist_iget( container_kw_list , 0 ); - enkf_config_node_type * container_node = ensemble_config_add_container( ensemble_config , container_key ); - - for (int j= 1; j < stringlist_get_size( container_kw_list ); j++) { - const char * child_key = stringlist_iget( container_kw_list , j); - enkf_config_node_update_container( container_node , ensemble_config_get_node( ensemble_config , child_key )); - } - } - } - - /*****************************************************************/ -} - -/** - this function takes a string like this: "pressure:1,4,7" - it - splits the string on ":" and tries to lookup a config object with - that key. for the general string a:b:c:d it will try consecutively - the keys: a, a:b, a:b:c, a:b:c:d. if a config object is found it is - returned, otherwise NULL is returned. - - the last argument is the pointer to a string which will be updated - with the node-spesific part of the full key. so for instance with - the example "pressure:1,4,7", the index_key will contain - "1,4,7". if the full full_key is used to find an object index_key - will be NULL, that also applies if no object is found. -*/ - - -const enkf_config_node_type * ensemble_config_user_get_node(const ensemble_config_type * config , const char * full_key, char ** index_key ) { - const enkf_config_node_type * node = NULL; - char ** key_list; - int keys; - int key_length = 1; - int offset; - - *index_key = NULL; - util_split_string(full_key , USER_KEY_JOIN_STRING , &keys , &key_list); - while (node == NULL && key_length <= keys) { - char * current_key = util_alloc_joined_string( (const char **) key_list , key_length , USER_KEY_JOIN_STRING ); - if (ensemble_config_has_key(config , current_key)) - node = ensemble_config_get_node(config , current_key); - else - key_length++; - offset = strlen( current_key ); - free( current_key ); - } - if (node != NULL) { - if (offset < strlen( full_key )) - *index_key = util_alloc_string_copy(&full_key[offset+1]); - } - - util_free_stringlist(key_list , keys); - return node; -} - - - -stringlist_type * ensemble_config_alloc_keylist(const ensemble_config_type * config) { - return hash_alloc_stringlist( config->config_nodes ); -} - - -/** - observe that var_type here is an integer - naturally written as a - sum of enkf_var_type values: - - ensemble_config_alloc_keylist_from_var_type( config , parameter + dynamic_state); - -*/ - -stringlist_type * ensemble_config_alloc_keylist_from_var_type(const ensemble_config_type * config , int var_mask) { - stringlist_type * key_list = stringlist_alloc_new(); - hash_iter_type * iter = hash_iter_alloc(config->config_nodes); - - while (!hash_iter_is_complete( iter )) { - const char * key = hash_iter_get_next_key(iter); - enkf_var_type var_type = enkf_config_node_get_var_type( hash_get(config->config_nodes , key)); - - if (var_type & var_mask) - stringlist_append_copy( key_list , key ); - } - hash_iter_free(iter); - - return key_list; -} - - - -stringlist_type * ensemble_config_alloc_keylist_from_impl_type(const ensemble_config_type * config , ert_impl_type impl_type) { - stringlist_type * key_list = stringlist_alloc_new(); - hash_iter_type * iter = hash_iter_alloc(config->config_nodes); - while (!hash_iter_is_complete( iter )) { - const char * key = hash_iter_get_next_key(iter); - if (enkf_config_node_get_impl_type( hash_get(config->config_nodes , key)) == impl_type) - stringlist_append_copy( key_list , key ); - - } - hash_iter_free(iter); - return key_list; -} - - -bool ensemble_config_has_impl_type(const ensemble_config_type * config, const ert_impl_type impl_type) { - bool ret = false; - hash_iter_type * iter = hash_iter_alloc(config->config_nodes); - while (!hash_iter_is_complete( iter )) { - const char * key = hash_iter_get_next_key(iter); - if (enkf_config_node_get_impl_type( hash_get(config->config_nodes , key)) == impl_type) { - ret = true; - break; - } - } - hash_iter_free(iter); - return ret; -} - - - - - -/** - this function will look up the user_key in the ensemble_config. if - the corresponding config_node can not be found 0 will be returned, - otherwise enkf_config_node functions will be invoked. -*/ - - -int ensemble_config_get_observations( const ensemble_config_type * config , enkf_obs_type * enkf_obs , const char * user_key , int obs_count , time_t * obs_time , double * y , double * std) { - int num_obs = 0; - char * index_key; - const enkf_config_node_type * config_node = ensemble_config_user_get_node( config , user_key , &index_key); - if (config_node != NULL) { - num_obs = enkf_config_node_load_obs( config_node , enkf_obs , index_key , obs_count , obs_time , y , std); - util_safe_free( index_key ); - } - return num_obs; -} - - -/*****************************************************************/ - - -/* - the ensemble_config_add_xxx() functions below will create a new xxx - instance and add it to the ensemble_config; the return value from - the functions is the newly created config_node instances. - - the newly created enkf_config_node instances are __not__ fully - initialized, and a subsequent call to enkf_config_node_update_xxx() - is essential for proper operation. -*/ - -enkf_config_node_type * ensemble_config_add_field( ensemble_config_type * config , const char * key , ecl_grid_type * ecl_grid , bool forward_init) { - enkf_config_node_type * config_node = enkf_config_node_alloc_field( key , ecl_grid , config->field_trans_table , forward_init); - ensemble_config_add_node( config , config_node ); - return config_node; -} - - -enkf_config_node_type * ensemble_config_add_gen_kw( ensemble_config_type * config , const char * key , bool forward_init) { - enkf_config_node_type * config_node = enkf_config_node_new_gen_kw( key , config->gen_kw_format_string , forward_init); - ensemble_config_add_node( config , config_node ); - return config_node; -} - -enkf_config_node_type * ensemble_config_add_custom_kw(ensemble_config_type * config, const char * key, const char * result_file, const char * output_file) { - enkf_config_node_type * config_node = enkf_config_node_new_custom_kw(key, result_file, output_file); - ensemble_config_add_node(config, config_node); - return config_node; -} - -enkf_config_node_type * ensemble_config_add_defined_custom_kw(ensemble_config_type * config, const char * key, const hash_type * definition) { - enkf_config_node_type * config_node = enkf_config_node_new_defined_custom_kw(key, definition); - ensemble_config_add_node(config, config_node); - return config_node; -} - - - -void ensemble_config_update_custom_kw_config(ensemble_config_type * config, custom_kw_config_set_type * config_set) { - stringlist_type * keys = custom_kw_config_set_get_keys_alloc(config_set); - - for(int i = 0; i < stringlist_get_size(keys); i++) { - const char * key = stringlist_iget(keys, i); - if(!ensemble_config_has_key(config, key)) { - ensemble_config_add_custom_kw(config, key, NULL, NULL); - printf("[%s] CustomKW key: '%s' not in ensemble! Adding from storage.\n", __func__, key); - } - - enkf_config_node_type * config_node = ensemble_config_get_node(config, key); - custom_kw_config_type * custom_kw_config = (custom_kw_config_type*) enkf_config_node_get_ref(config_node); - - custom_kw_config_set_update_config(config_set, custom_kw_config); - } - - stringlist_free(keys); -} - - -/** - this function ensures that object contains a node with 'key' and - type == summary. - - if the @refcase pointer is different from NULL the key will be - validated. keys which do not exist in the refcase will be ignored, - a warning will be printed on stderr and the function will return - NULL. -*/ - -enkf_config_node_type * ensemble_config_add_summary(ensemble_config_type * ensemble_config , const char * key , load_fail_type load_fail) { - enkf_config_node_type * config_node = NULL; - - if (hash_has_key(ensemble_config->config_nodes, key)) { - config_node = hash_get(ensemble_config->config_nodes, key); - if (enkf_config_node_get_impl_type( config_node ) != SUMMARY) { - util_abort("%s: ensemble key:%s already exists - but it is not of summary type\n",__func__ , key); - } - - summary_config_type * summary_config = enkf_config_node_get_ref( config_node ); - summary_config_update_load_fail_mode( summary_config , load_fail ); - - } else { - config_node = enkf_config_node_alloc_summary( key , load_fail); - ensemble_config_add_node(ensemble_config , config_node ); - } - - return config_node; -} - -enkf_config_node_type * ensemble_config_add_summary_observation(ensemble_config_type * ensemble_config , const char * key , load_fail_type load_fail) { - enkf_config_node_type * config_node = ensemble_config_add_summary(ensemble_config, key, load_fail); - - summary_key_matcher_add_summary_key(ensemble_config->summary_key_matcher, key); - - return config_node; -} - - -enkf_config_node_type * ensemble_config_add_surface( ensemble_config_type * ensemble_config , const char * key , bool forward_init) { - enkf_config_node_type * config_node = enkf_config_node_new_surface( key , forward_init ); - ensemble_config_add_node( ensemble_config , config_node ); - return config_node; -} - - -/* - If key == NULL the function will create a random key. -*/ -enkf_config_node_type * ensemble_config_add_container( ensemble_config_type * ensemble_config , const char * key) { - char * local_key = (char *) key; - bool random_key = false; - if (key == NULL) { - local_key = util_calloc( 11 , sizeof * local_key ); - sprintf(local_key , "%ld" , random() % 10000000 ); - random_key = true; - } - - { - enkf_config_node_type * config_node = enkf_config_node_new_container( local_key ); - ensemble_config_add_node( ensemble_config , config_node ); - if (random_key) - free( local_key ); - return config_node; - } -} - - -const summary_key_matcher_type * ensemble_config_get_summary_key_matcher(const ensemble_config_type * ensemble_config) { - return ensemble_config->summary_key_matcher; -} - -/*****************************************************************/ - -void ensemble_config_fprintf_config( ensemble_config_type * ensemble_config , FILE * stream ) { - fprintf( stream , CONFIG_COMMENTLINE_FORMAT ); - fprintf( stream , CONFIG_COMMENT_FORMAT , "Here comes configuration information about the uncertain parameters and response variables in use."); - - fprintf( stream , CONFIG_KEY_FORMAT , GEN_KW_TAG_FORMAT_KEY ); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , ensemble_config->gen_kw_format_string); - - - /* Writing GEN_KW nodes. */ - { - stringlist_type * gen_kw_keys = ensemble_config_alloc_keylist_from_impl_type( ensemble_config , GEN_KW ); - stringlist_sort( gen_kw_keys , NULL ); - for (int i=0; i < stringlist_get_size( gen_kw_keys ); i++) { - const enkf_config_node_type * config_node = ensemble_config_get_node( ensemble_config , stringlist_iget( gen_kw_keys , i)); - enkf_config_node_fprintf_config( config_node , stream ); - } - if (stringlist_get_size( gen_kw_keys ) > 0) - fprintf(stream , "\n"); - stringlist_free( gen_kw_keys ); - } - - - /* Writing FIELD nodes. */ - { - stringlist_type * field_keys = ensemble_config_alloc_keylist_from_impl_type( ensemble_config , FIELD ); - stringlist_sort( field_keys , NULL ); - for (int i=0; i < stringlist_get_size( field_keys ); i++) { - const enkf_config_node_type * config_node = ensemble_config_get_node( ensemble_config , stringlist_iget( field_keys , i)); - enkf_config_node_fprintf_config( config_node , stream ); - } - if (stringlist_get_size( field_keys ) > 0) - fprintf(stream , "\n"); - stringlist_free( field_keys ); - } - - - /* Writing SUMMARY nodes. */ - { - stringlist_type * summary_keys = ensemble_config_alloc_keylist_from_impl_type( ensemble_config , SUMMARY ); - stringlist_sort( summary_keys , NULL ); - for (int i=0; i < stringlist_get_size( summary_keys ); i++) { - if (i == 0) - fprintf(stream , CONFIG_KEY_FORMAT , SUMMARY_KEY); - else if ((i % 8) == 0) { - fprintf(stream , "\n"); - fprintf(stream , CONFIG_KEY_FORMAT , SUMMARY_KEY); - } - fprintf(stream , CONFIG_SHORT_VALUE_FORMAT , stringlist_iget( summary_keys , i )); - } - fprintf(stream , "\n"); - stringlist_free( summary_keys ); - } - fprintf(stream , "\n"); - - - /* Writing GEN_DATA nodes. */ - { - stringlist_type * gen_data_keys = ensemble_config_alloc_keylist_from_impl_type( ensemble_config , GEN_DATA ); - stringlist_sort( gen_data_keys , NULL ); - for (int i=0; i < stringlist_get_size( gen_data_keys ); i++) { - const enkf_config_node_type * config_node = ensemble_config_get_node( ensemble_config , stringlist_iget( gen_data_keys , i)); - enkf_config_node_fprintf_config( config_node , stream ); - } - stringlist_free( gen_data_keys ); - } - fprintf(stream , "\n\n"); -} - - - -int ensemble_config_get_size(const ensemble_config_type * ensemble_config ) { - return hash_get_size( ensemble_config->config_nodes ); -} diff --git a/ThirdParty/Ert/libenkf/src/ert_init_context.c b/ThirdParty/Ert/libenkf/src/ert_init_context.c deleted file mode 100644 index 472f6508fb..0000000000 --- a/ThirdParty/Ert/libenkf/src/ert_init_context.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'ert_init_context.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -#define ERT_INIT_CONTEXT_TYPE_ID 555341328 - - -struct ert_init_context_struct { - UTIL_TYPE_ID_DECLARATION; - vector_type * run_args; - bool_vector_type * iactive; // This can be updated .... - init_mode_type init_mode; - int iter; - int_vector_type * iens_map; - -}; - - - - -char * ert_init_context_alloc_runpath( int iens , path_fmt_type * runpath_fmt , subst_list_type * subst_list , int iter) { - char * runpath; - { - char * first_pass = path_fmt_alloc_path(runpath_fmt , false , iens, iter); /* 1: Replace first %d with iens, if a second %d replace with iter */ - - if (subst_list) - runpath = subst_list_alloc_filtered_string( subst_list , first_pass ); /* 2: Filter out various magic strings like and . */ - else - runpath = util_alloc_string_copy( first_pass ); - - free( first_pass ); - } - return runpath; -} - - -stringlist_type * ert_init_context_alloc_runpath_list(const bool_vector_type * iactive , path_fmt_type * runpath_fmt , subst_list_type * subst_list , int iter) { - stringlist_type * runpath_list = stringlist_alloc_new(); - for (int iens = 0; iens < bool_vector_size( iactive ); iens++) { - - if (bool_vector_iget( iactive , iens )) - stringlist_append_owned_ref( runpath_list , ert_init_context_alloc_runpath(iens , runpath_fmt , subst_list , iter)); - else - stringlist_append_ref( runpath_list , NULL ); - - } - return runpath_list; -} - - -static ert_init_context_type * ert_init_context_alloc1(const bool_vector_type * iactive , init_mode_type init_mode, int iter) { - ert_init_context_type * context = util_malloc( sizeof * context ); - UTIL_TYPE_ID_INIT( context , ERT_INIT_CONTEXT_TYPE_ID ); - - context->iactive = bool_vector_alloc_copy( iactive ); - context->iens_map = bool_vector_alloc_active_index_list( iactive , -1 ); - context->run_args = vector_alloc_new(); - context->init_mode = init_mode; - context->iter = iter; - - return context; -} - -ert_init_context_type * ert_init_context_alloc(enkf_fs_type * init_fs , const bool_vector_type * iactive , - path_fmt_type * runpath_fmt , - subst_list_type * subst_list , - init_mode_type init_mode , - int iter) { - - ert_init_context_type * context = ert_init_context_alloc1( iactive , init_mode , iter ); - { - stringlist_type * runpath_list = ert_init_context_alloc_runpath_list( iactive , runpath_fmt , subst_list , iter ); - for (int iens = 0; iens < bool_vector_size( iactive ); iens++) { - if (bool_vector_iget( iactive , iens )) { - run_arg_type * arg = run_arg_alloc_INIT_ONLY( init_fs , iens , iter , stringlist_iget( runpath_list , iens)); - vector_append_owned_ref( context->run_args , arg , run_arg_free__); - } - } - stringlist_free( runpath_list ); - } - return context; -} - - - - -UTIL_IS_INSTANCE_FUNCTION( ert_init_context , ERT_INIT_CONTEXT_TYPE_ID ); - - - -void ert_init_context_free( ert_init_context_type * context ) { - - vector_free( context->run_args ); - bool_vector_free( context->iactive ); - int_vector_free( context->iens_map ); - free( context ); -} - - -int ert_init_context_get_size( const ert_init_context_type * context ) { - return vector_get_size( context->run_args ); -} - - - -init_mode_type ert_init_context_get_init_mode( const ert_init_context_type * context ) { - return context->init_mode; -} - - -bool_vector_type * ert_init_context_get_iactive( const ert_init_context_type * context ) { - return context->iactive; -} - - -run_arg_type * ert_init_context_iget_arg( const ert_init_context_type * context , int index) { - return vector_iget( context->run_args , index ); -} - - -run_arg_type * ert_init_context_iens_get_arg( const ert_init_context_type * context , int iens) { - int index = int_vector_iget( context->iens_map , iens ); - if (index >= 0) - return vector_iget( context->run_args , index ); - else - return NULL; -} diff --git a/ThirdParty/Ert/libenkf/src/ert_log.c b/ThirdParty/Ert/libenkf/src/ert_log.c deleted file mode 100644 index 629415f538..0000000000 --- a/ThirdParty/Ert/libenkf/src/ert_log.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'ert_log.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include - -#include -#include - - -static log_type * logh = NULL; /* Handle to an open log file. */ - -/** - * The logging uses log_level to determine if an incoming message is to be included in the log. - * A high log_level setting will include more messages. - */ -void ert_log_init_log( int log_level , const char * log_file_name, bool verbose){ - logh = log_open( NULL , DEFAULT_LOG_LEVEL ); - - log_set_level(logh, log_level); - if (log_file_name) - log_reopen( logh , log_file_name); - - if (verbose) - printf("Activity will be logged to ..............: %s \n",log_get_filename( logh )); - log_add_message(logh , 1 , NULL , "ert configuration loaded" , false); -} - -void ert_log_add_message_py(int message_level, char* message){ - ert_log_add_message(message_level, NULL, message, false); -} - -/** - * Adding a message with a given message_level. A low message_level means "more important", as only messages with - * message_level below the configured log_level will be included. - */ -void ert_log_add_message(int message_level , FILE * dup_stream , char* message, bool free_message) { - if(logh==NULL) - ert_log_init_log(1,NULL,true); - log_add_message(logh, message_level, dup_stream, message, free_message); -} - -/** - * Adding a message with a given message_level. A low message_level means "more important", as only messages with - * message_level below the configured log_level will be included. - */ -void ert_log_add_fmt_message(int message_level , FILE * dup_stream , const char * fmt , ...) { - if (log_include_message(logh,message_level)) { - char * message; - va_list ap; - va_start(ap , fmt); - message = util_alloc_sprintf_va( fmt , ap ); - log_add_message( logh , message_level , dup_stream , message , true); - va_end(ap); - } -} - -void ert_log_close(){ - if (log_is_open( logh )) - log_add_message( logh , false , NULL , "Exiting ert application normally - all is fine(?)" , false); - log_close( logh ); - logh = NULL; -} - -bool ert_log_is_open(){ - if(logh==NULL) - return false; - return log_is_open(logh); -} - -void ert_log_set_log_level(int log_level){ - if(logh==NULL) - ert_log_init_log(1,NULL,true); - log_set_level(logh, log_level); -} - -int ert_log_get_log_level(){ - if(logh==NULL) - ert_log_init_log(1,NULL,true); - return log_get_level(logh); -} - -const char * ert_log_get_filename() { - if(logh==NULL) - ert_log_init_log(1,NULL,true); - return log_get_filename(logh); -} - -log_type * ert_log_get_logh() { - if(logh==NULL) - ert_log_init_log(1,NULL,true); - return logh; -} - -void ert_log_open_empty(){ - logh = log_open(NULL, DEFAULT_LOG_LEVEL); -} diff --git a/ThirdParty/Ert/libenkf/src/ert_run_context.c b/ThirdParty/Ert/libenkf/src/ert_run_context.c deleted file mode 100644 index 655de27048..0000000000 --- a/ThirdParty/Ert/libenkf/src/ert_run_context.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'ert_run_context.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -#define ERT_RUN_CONTEXT_TYPE_ID 55534132 - - -struct ert_run_context_struct { - UTIL_TYPE_ID_DECLARATION; - vector_type * run_args; - - // Observe that the iactive mask is a shared reference which has - // lifetime longer than the ert_run_context instance. When - // simulations have failed elements in the iactive vector can be set - // to false during runtime. - bool_vector_type * iactive; - run_mode_type run_mode; - int iter; - int step1; - int step2; - int load_start; - int_vector_type * iens_map; - - enkf_fs_type * init_fs; - enkf_fs_type * result_fs; - enkf_fs_type * update_target_fs; -}; - - - - -char * ert_run_context_alloc_runpath( int iens , path_fmt_type * runpath_fmt , subst_list_type * subst_list , int iter) { - char * runpath; - { - char * first_pass = path_fmt_alloc_path(runpath_fmt , false , iens, iter); /* 1: Replace first %d with iens, if a second %d replace with iter */ - - if (subst_list) - runpath = subst_list_alloc_filtered_string( subst_list , first_pass ); /* 2: Filter out various magic strings like and . */ - else - runpath = util_alloc_string_copy( first_pass ); - - free( first_pass ); - } - return runpath; -} - - -stringlist_type * ert_run_context_alloc_runpath_list(const bool_vector_type * iactive , path_fmt_type * runpath_fmt , subst_list_type * subst_list , int iter) { - stringlist_type * runpath_list = stringlist_alloc_new(); - for (int iens = 0; iens < bool_vector_size( iactive ); iens++) { - - if (bool_vector_iget( iactive , iens )) - stringlist_append_owned_ref( runpath_list , ert_run_context_alloc_runpath(iens , runpath_fmt , subst_list , iter)); - else - stringlist_append_ref( runpath_list , NULL ); - - } - return runpath_list; -} - - -static ert_run_context_type * ert_run_context_alloc(bool_vector_type * iactive , run_mode_type run_mode , enkf_fs_type * init_fs , enkf_fs_type * result_fs , enkf_fs_type * update_target_fs , int iter) { - ert_run_context_type * context = util_malloc( sizeof * context ); - UTIL_TYPE_ID_INIT( context , ERT_RUN_CONTEXT_TYPE_ID ); - - context->iactive = iactive; - context->iens_map = bool_vector_alloc_active_index_list( iactive , -1 ); - context->run_args = vector_alloc_new(); - context->run_mode = run_mode; - context->iter = iter; - ert_run_context_set_init_fs(context, init_fs); - ert_run_context_set_result_fs(context, result_fs); - ert_run_context_set_update_target_fs(context, update_target_fs); - - context->step1 = 0; - context->step2 = 0; - return context; -} - - -ert_run_context_type * ert_run_context_alloc_ENSEMBLE_EXPERIMENT(enkf_fs_type * fs , bool_vector_type * iactive , - path_fmt_type * runpath_fmt , - subst_list_type * subst_list , - int iter) { - - ert_run_context_type * context = ert_run_context_alloc( iactive , ENSEMBLE_EXPERIMENT , fs , fs , NULL , iter); - { - stringlist_type * runpath_list = ert_run_context_alloc_runpath_list( iactive , runpath_fmt , subst_list , iter ); - for (int iens = 0; iens < bool_vector_size( iactive ); iens++) { - if (bool_vector_iget( iactive , iens )) { - run_arg_type * arg = run_arg_alloc_ENSEMBLE_EXPERIMENT( fs , iens , iter , stringlist_iget( runpath_list , iens)); - vector_append_owned_ref( context->run_args , arg , run_arg_free__); - } - } - stringlist_free( runpath_list ); - } - return context; -} - - - -ert_run_context_type * ert_run_context_alloc_SMOOTHER_RUN(enkf_fs_type * simulate_fs , enkf_fs_type * target_update_fs , - bool_vector_type * iactive , - path_fmt_type * runpath_fmt , - subst_list_type * subst_list , - int iter) { - - ert_run_context_type * context = ert_run_context_alloc( iactive , SMOOTHER_UPDATE , simulate_fs , simulate_fs , target_update_fs , iter); - { - stringlist_type * runpath_list = ert_run_context_alloc_runpath_list( iactive , runpath_fmt , subst_list , iter ); - for (int iens = 0; iens < bool_vector_size( iactive ); iens++) { - if (bool_vector_iget( iactive , iens )) { - run_arg_type * arg = run_arg_alloc_SMOOTHER_RUN( simulate_fs , target_update_fs , iens , iter , stringlist_iget( runpath_list , iens)); - vector_append_owned_ref( context->run_args , arg , run_arg_free__); - } - } - stringlist_free( runpath_list ); - } - return context; -} - - - - -UTIL_IS_INSTANCE_FUNCTION( ert_run_context , ERT_RUN_CONTEXT_TYPE_ID ); - - - -void ert_run_context_free( ert_run_context_type * context ) { - if (context->result_fs) { - enkf_fs_decrease_write_count(context->result_fs); - } - - if (context->update_target_fs) { - enkf_fs_decrease_write_count(context->update_target_fs); - } - - vector_free( context->run_args ); - int_vector_free( context->iens_map ); - free( context ); -} - - -int ert_run_context_get_size( const ert_run_context_type * context ) { - return vector_get_size( context->run_args ); -} - - - -run_mode_type ert_run_context_get_mode( const ert_run_context_type * context ) { - return context->run_mode; -} - - - - - -int ert_run_context_get_iter( const ert_run_context_type * context ) { - return context->iter; -} - -int ert_run_context_get_step1( const ert_run_context_type * context ) { - return context->step1; -} - - -int ert_run_context_get_load_start( const ert_run_context_type * context ) { - if (context->step1 == 0) - return 1; - else - return context->step1; -} - - -int ert_run_context_get_step2( const ert_run_context_type * context ) { - return context->step2; -} - - -bool_vector_type * ert_run_context_get_iactive( const ert_run_context_type * context ) { - return context->iactive; -} - - -run_arg_type * ert_run_context_iget_arg( const ert_run_context_type * context , int index) { - return vector_iget( context->run_args , index ); -} - - -run_arg_type * ert_run_context_iens_get_arg( const ert_run_context_type * context , int iens) { - int index = int_vector_iget( context->iens_map , iens ); - if (index >= 0) - return vector_iget( context->run_args , index ); - else - return NULL; -} - -enkf_fs_type * ert_run_context_get_init_fs(const ert_run_context_type * run_context) { - if (run_context->init_fs) - return run_context->init_fs; - else { - util_abort("%s: internal error - tried to access run_context->init_fs when init_fs == NULL\n",__func__); - return NULL; - } -} - - -enkf_fs_type * ert_run_context_get_result_fs(const ert_run_context_type * run_context) { - if (run_context->result_fs) - return run_context->result_fs; - else { - util_abort("%s: internal error - tried to access run_context->result_fs when result_fs == NULL\n",__func__); - return NULL; - } -} - - -enkf_fs_type * ert_run_context_get_update_target_fs(const ert_run_context_type * run_context) { - if (run_context->update_target_fs) - return run_context->update_target_fs; - else { - util_abort("%s: internal error - tried to access run_context->update_target_fs when update_target_fs == NULL\n",__func__); - return NULL; - } -} - -void ert_run_context_set_init_fs(ert_run_context_type * context, enkf_fs_type * init_fs) { - context->init_fs = (init_fs) ? init_fs : NULL; -} - -void ert_run_context_set_result_fs(ert_run_context_type * context, enkf_fs_type * result_fs) { - if (result_fs) { - context->result_fs = result_fs; - enkf_fs_increase_write_count(result_fs); - } else - context->result_fs = NULL; -} - -void ert_run_context_set_update_target_fs(ert_run_context_type * context, enkf_fs_type * update_target_fs) { - if (update_target_fs) { - context->update_target_fs = update_target_fs; - enkf_fs_increase_write_count(update_target_fs); - } else - context->update_target_fs = NULL; -} - - - -void ert_run_context_deactivate_realization( ert_run_context_type * context , int iens) { - bool_vector_iset( context->iactive , iens , false ); -} diff --git a/ThirdParty/Ert/libenkf/src/ert_template.c b/ThirdParty/Ert/libenkf/src/ert_template.c deleted file mode 100644 index 408ebe6820..0000000000 --- a/ThirdParty/Ert/libenkf/src/ert_template.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ert_template.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - - -#define ERT_TEMPLATE_TYPE_ID 7731963 -#define ERT_TEMPLATES_TYPE_ID 6677330 - -/* Singular - one template. */ -struct ert_template_struct { - UTIL_TYPE_ID_DECLARATION; - template_type * template; - char * target_file; -}; - - - -/* Plural - many templates. */ -struct ert_templates_struct { - UTIL_TYPE_ID_DECLARATION; - subst_list_type * parent_subst; - hash_type * templates; -}; - - - -void ert_template_set_target_file( ert_template_type * ert_template , const char * target_file ) { - ert_template->target_file = util_realloc_string_copy( ert_template->target_file , target_file ); -} - - -void ert_template_set_template_file( ert_template_type * ert_template , const char * template_file ) { - template_set_template_file( ert_template->template , template_file ); -} - - -const char * ert_template_get_template_file( const ert_template_type * ert_template) { - return template_get_template_file( ert_template->template ); -} - -const char * ert_template_get_target_file( const ert_template_type * ert_template) { - return ert_template->target_file; -} - -const char * ert_template_get_args_as_string( const ert_template_type * ert_template ) { - return template_get_args_as_string( ert_template->template ); -} - - - -ert_template_type * ert_template_alloc( const char * template_file , const char * target_file , subst_list_type * parent_subst) { - ert_template_type * template = util_malloc( sizeof * template); - UTIL_TYPE_ID_INIT(template , ERT_TEMPLATE_TYPE_ID); - template->template = template_alloc( template_file , false , parent_subst); /* The templates are instantiated with internalize_template == false; - this means that substitutions are performed on the filename of the - template itself .*/ - - template->target_file = NULL; - ert_template_set_target_file( template , target_file ); - return template; -} - - -void ert_template_free( ert_template_type * template ) { - util_safe_free( template->target_file ); - template_free( template->template ); - free( template ); -} - - -void ert_template_instantiate( ert_template_type * template , const char * path , const subst_list_type * arg_list) { - char * target_file = util_alloc_filename( path , template->target_file , NULL ); - template_instantiate( template->template , target_file , arg_list , true ); - free( target_file ); -} - - -void ert_template_add_arg( ert_template_type * template , const char * key , const char * value ) { - template_add_arg( template->template , key , value ); -} - -void ert_template_set_args_from_string( ert_template_type * template, const char * arg_string ) { - template_clear_args( template->template ); - template_add_args_from_string( template->template , arg_string ); -} - - -UTIL_SAFE_CAST_FUNCTION( ert_template , ERT_TEMPLATE_TYPE_ID ) - -void ert_template_free__(void * arg) { - ert_template_free( ert_template_safe_cast( arg )); -} - - -static void ert_template_fprintf_config( const ert_template_type * template , FILE * stream ) { - fprintf(stream , CONFIG_KEY_FORMAT , RUN_TEMPLATE_KEY ); - fprintf(stream , CONFIG_VALUE_FORMAT , ert_template_get_template_file( template )); - fprintf(stream , CONFIG_VALUE_FORMAT , template->target_file ); - { - const char * arg_string = ert_template_get_args_as_string( template ); - if (arg_string != NULL) - fprintf(stream , CONFIG_ENDVALUE_FORMAT , arg_string ); - else - fprintf(stream , "\n"); - } -} - - -/*****************************************************************/ - - -ert_templates_type * ert_templates_alloc( subst_list_type * parent_subst ) { - ert_templates_type * templates = util_malloc( sizeof * templates ); - UTIL_TYPE_ID_INIT( templates , ERT_TEMPLATES_TYPE_ID ); - templates->templates = hash_alloc(); - templates->parent_subst = parent_subst; - return templates; -} - - -void ert_templates_free( ert_templates_type * ert_templates ) { - hash_free( ert_templates->templates ); - free( ert_templates ); -} - - -void ert_templates_del_template( ert_templates_type * ert_templates , const char * key) { - hash_del( ert_templates->templates , key ); -} - - -ert_template_type * ert_templates_add_template( ert_templates_type * ert_templates , const char * key , const char * template_file , const char * target_file, const char * arg_string) { - ert_template_type * template = ert_template_alloc( template_file , target_file , ert_templates->parent_subst); - ert_template_set_args_from_string( template , arg_string ); /* Arg_string can be NULL */ - - /** - If key == NULL the function will generate a key after the following algorithm: - - 1. It tries with the basename of the template file. - 2. It tries with the basename of the template file, and a counter. - */ - - if (key == NULL) { - char * new_key = NULL; - char * base_name; - int counter = 1; - util_alloc_file_components( template_file , NULL , &base_name , NULL); - do { - if (counter == 1) - new_key = util_realloc_string_copy( new_key , base_name ); - else - new_key = util_realloc_sprintf( new_key , "%s.%d" , base_name , counter ); - counter++; - } while (hash_has_key( ert_templates->templates , new_key)); - hash_insert_hash_owned_ref( ert_templates->templates , new_key , template , ert_template_free__); - free( new_key ); - free( base_name ); - } else - hash_insert_hash_owned_ref( ert_templates->templates , key , template , ert_template_free__); - - return template; -} - - -void ert_templates_instansiate( ert_templates_type * ert_templates , const char * path , const subst_list_type * arg_list) { - hash_iter_type * iter = hash_iter_alloc( ert_templates->templates ); - while (!hash_iter_is_complete( iter )) { - ert_template_type * ert_template = hash_iter_get_next_value( iter ); - ert_template_instantiate( ert_template , path , arg_list); - } - hash_iter_free( iter ); -} - - - -void ert_templates_clear( ert_templates_type * ert_templates ) { - hash_clear( ert_templates->templates ); -} - -ert_template_type * ert_templates_get_template( ert_templates_type * ert_templates , const char * key) { - return hash_get( ert_templates->templates , key ); -} - -stringlist_type * ert_templates_alloc_list( ert_templates_type * ert_templates) { - return hash_alloc_stringlist( ert_templates->templates ); -} - - -void ert_templates_init( ert_templates_type * templates , const config_content_type * config ) { - if (config_content_has_item( config , RUN_TEMPLATE_KEY)) { - const config_content_item_type * template_item = config_content_get_item( config , RUN_TEMPLATE_KEY ); - for (int i=0; i < config_content_item_get_size( template_item ); i++) { - config_content_node_type * template_node = config_content_item_iget_node( template_item , i ); - const char * template_file = config_content_node_iget_as_path(template_node , 0 ); - const char * target_file = config_content_node_iget( template_node , 1 ); - - ert_template_type * template = ert_templates_add_template( templates , NULL , template_file , target_file , NULL); - - for (int iarg = 2; iarg < config_content_node_get_size( template_node ); iarg++) { - char * key , *value; - const char * key_value = config_content_node_iget( template_node , iarg ); - util_binary_split_string( key_value , "=:" , true , &key , &value); - - if (value != NULL) - ert_template_add_arg( template ,key , value ); - else - fprintf(stderr,"** Warning - failed to parse argument:%s as key:value - ignored \n",config_content_iget( config , "RUN_TEMPLATE" , i , iarg )); - - free( key ); - util_safe_free( value ); - } - } - } -} - - -void ert_templates_fprintf_config( const ert_templates_type * ert_templates , FILE * stream ) { - if (hash_get_size( ert_templates->templates ) > 0 ) { - fprintf( stream , CONFIG_COMMENTLINE_FORMAT ); - fprintf( stream , CONFIG_COMMENT_FORMAT , "Here comes configuration information about RUN-TIME templates instantiated by ERT."); - - { - hash_iter_type * iter = hash_iter_alloc( ert_templates->templates ); - while( !hash_iter_is_complete( iter )) { - const char * key = hash_iter_get_next_key( iter ); - const ert_template_type * template = hash_get( ert_templates->templates , key ); - ert_template_fprintf_config( template , stream ); - } - hash_iter_free( iter ); - } - fprintf( stream , "\n\n" ); - } -} diff --git a/ThirdParty/Ert/libenkf/src/ert_test_context.c b/ThirdParty/Ert/libenkf/src/ert_test_context.c deleted file mode 100644 index faeac2f0b3..0000000000 --- a/ThirdParty/Ert/libenkf/src/ert_test_context.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'ert_test_context.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - - -#define ERT_TEST_CONTEXT_TYPE_ID 99671055 -struct ert_test_context_struct { - UTIL_TYPE_ID_DECLARATION; - enkf_main_type * enkf_main; - test_work_area_type * work_area; - rng_type * rng; -}; - - -UTIL_IS_INSTANCE_FUNCTION( ert_test_context , ERT_TEST_CONTEXT_TYPE_ID ) - - -static ert_test_context_type * ert_test_context_alloc__( const char * test_name , const char * model_config , bool python_mode) { - ert_test_context_type * test_context = util_malloc( sizeof * test_context ); - UTIL_TYPE_ID_INIT( test_context , ERT_TEST_CONTEXT_TYPE_ID ); - - /* - This environment variable is set to ensure that test context will - parse the correct files when loading site config. - */ - if (python_mode) - setenv("ERT_UI_MODE" , "gui" , 1); - else - setenv("ERT_UI_MODE" , "tui" , 1); - - - if (util_file_exists(model_config)) { - test_context->work_area = test_work_area_alloc(test_name); - test_work_area_set_store( test_context->work_area , false ); - test_work_area_copy_parent_content(test_context->work_area , model_config ); - { - char * config_file = util_split_alloc_filename( model_config ); - test_context->enkf_main = enkf_main_bootstrap(config_file , true , false ); - free( config_file ); - } - test_context->rng = rng_alloc( MZRAN , INIT_DEV_URANDOM ); - } else { - test_context->enkf_main = NULL; - test_context->work_area = NULL; - test_context->rng = NULL; - } - return test_context; -} - -ert_test_context_type * ert_test_context_alloc( const char * test_name , const char * model_config) { - return ert_test_context_alloc__( test_name , model_config , false ); -} - - -ert_test_context_type * ert_test_context_alloc_python( const char * test_name , const char * model_config) { - return ert_test_context_alloc__( test_name , model_config , true ); -} - - - -enkf_main_type * ert_test_context_get_main( ert_test_context_type * test_context ) { - return test_context->enkf_main; -} - - -const char * ert_test_context_get_cwd( const ert_test_context_type * test_context ) { - return test_work_area_get_cwd( test_context->work_area ); -} - - - -void ert_test_context_free( ert_test_context_type * test_context ) { - - if (test_context->enkf_main) - enkf_main_free( test_context->enkf_main ); - - if (test_context->work_area) - test_work_area_free( test_context->work_area ); - - if (test_context->rng) - rng_free( test_context->rng ); - - free( test_context ); -} - - -bool ert_test_context_install_workflow_job( ert_test_context_type * test_context , const char * job_name , const char * job_file) { - if (util_file_exists( job_file )) { - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - ert_workflow_list_type * workflow_list = enkf_main_get_workflow_list( enkf_main ); - ert_workflow_list_add_job( workflow_list , job_name , job_file ); - return ert_workflow_list_has_job( workflow_list , job_name ); - } else - return false; -} - - -bool ert_test_context_install_workflow( ert_test_context_type * test_context , const char * workflow_name , const char * workflow_file) { - if (util_file_exists( workflow_file )) { - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - ert_workflow_list_type * workflow_list = enkf_main_get_workflow_list( enkf_main ); - ert_workflow_list_add_workflow( workflow_list , workflow_file , workflow_name ); - return ert_workflow_list_has_workflow( workflow_list , workflow_name); - } else - return false; -} - - -void ert_test_context_fwrite_workflow_job( FILE * stream , const char * job_name , const stringlist_type * args) { - fprintf(stream , "%s " , job_name); - stringlist_fprintf(args , " ", stream); - fprintf(stream , "\n"); -} - - -bool ert_test_context_run_worklow( ert_test_context_type * test_context , const char * workflow_name) { - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - ert_workflow_list_type * workflow_list = enkf_main_get_workflow_list( enkf_main ); - - if (ert_workflow_list_has_workflow( workflow_list , workflow_name )){ - bool result = ert_workflow_list_run_workflow_blocking( workflow_list , workflow_name , enkf_main ); - return result; - } - else{ - return false; - } -} - - - -bool ert_test_context_run_worklow_job( ert_test_context_type * test_context , const char * job_name, const stringlist_type * args) { - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - ert_workflow_list_type * workflow_list = enkf_main_get_workflow_list( enkf_main ); - - if (ert_workflow_list_has_job( workflow_list , job_name )) { - bool status; - { - char * workflow = util_alloc_sprintf("WORKFLOW-%06d" , rng_get_int( test_context->rng , 1000000)); - { - FILE * stream = util_fopen( workflow , "w"); - ert_test_context_fwrite_workflow_job( stream , job_name , args ); - fclose(stream); - } - ert_test_context_install_workflow( test_context , workflow , workflow); - status = ert_test_context_run_worklow( test_context , workflow ); - free(workflow); - } - return status; - } else - return false; -} - - -void ert_test_context_set_store( ert_test_context_type * test_context , bool store) { - test_work_area_set_store( test_context->work_area , store ); -} diff --git a/ThirdParty/Ert/libenkf/src/ert_users.c b/ThirdParty/Ert/libenkf/src/ert_users.c deleted file mode 100644 index 5458fcbddf..0000000000 --- a/ThirdParty/Ert/libenkf/src/ert_users.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ert_users.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - - -int main (int argc , char ** argv) { - char hostname[256]; - const char * executable = argv[1]; - - gethostname( hostname , 255 ); - printf("%s : " , hostname); - { - set_type * user_set = set_alloc_empty(); - enkf_main_list_users( user_set , executable ); - - if (set_get_size( user_set ) > 0) - set_fprintf(user_set , " " , stdout ); - else - printf("No users."); - - printf("\n"); - - set_free( user_set ); - } -} - - - - diff --git a/ThirdParty/Ert/libenkf/src/ert_workflow_list.c b/ThirdParty/Ert/libenkf/src/ert_workflow_list.c deleted file mode 100644 index ca78f76bc0..0000000000 --- a/ThirdParty/Ert/libenkf/src/ert_workflow_list.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'ert_workflow_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - - -#define ERT_WORKFLOW_LIST_TYPE_ID 8856275 - -struct ert_workflow_list_struct { - UTIL_TYPE_ID_DECLARATION; - stringlist_type * path_list; - hash_type * workflows; - hash_type * alias_map; - workflow_joblist_type * joblist; - const subst_list_type * context; - const config_error_type * last_error; - bool verbose; -}; - - - -ert_workflow_list_type * ert_workflow_list_alloc(const subst_list_type * context) { - ert_workflow_list_type * workflow_list = util_malloc( sizeof * workflow_list ); - UTIL_TYPE_ID_INIT( workflow_list , ERT_WORKFLOW_LIST_TYPE_ID ); - workflow_list->path_list = stringlist_alloc_new(); - workflow_list->workflows = hash_alloc(); - workflow_list->alias_map = hash_alloc(); - workflow_list->joblist = workflow_joblist_alloc(); - workflow_list->context = context; - workflow_list->last_error = NULL; - ert_workflow_list_set_verbose( workflow_list , DEFAULT_WORKFLOW_VERBOSE ); - return workflow_list; -} - - - -UTIL_IS_INSTANCE_FUNCTION( ert_workflow_list , ERT_WORKFLOW_LIST_TYPE_ID ) - -void ert_workflow_list_set_verbose( ert_workflow_list_type * workflow_list , bool verbose) { - workflow_list->verbose = verbose; -} - - -const subst_list_type * ert_workflow_list_get_context(const ert_workflow_list_type * workflow_list) { - return workflow_list->context; -} - -void ert_workflow_list_free( ert_workflow_list_type * workflow_list ) { - hash_free( workflow_list->workflows ); - hash_free( workflow_list->alias_map ); - stringlist_free( workflow_list->path_list ); - workflow_joblist_free( workflow_list->joblist ); - free( workflow_list ); -} - - - -workflow_type * ert_workflow_list_add_workflow( ert_workflow_list_type * workflow_list , const char * workflow_file , const char * workflow_name) { - if (util_file_exists( workflow_file )) { - workflow_type * workflow = workflow_alloc( workflow_file , workflow_list->joblist ); - char * name; - - if (workflow_name == NULL) - util_alloc_file_components( workflow_file , NULL , &name , NULL ); - else - name = (char *) workflow_name; - - - hash_insert_hash_owned_ref( workflow_list->workflows , name , workflow , workflow_free__); - if (hash_has_key( workflow_list->alias_map , name)) - hash_del( workflow_list->alias_map , name); - - if (workflow_name == NULL) - free( name ); - - return workflow; - } else - return NULL; -} - - - -void ert_workflow_list_add_alias( ert_workflow_list_type * workflow_list , const char * real_name , const char * alias) { - if (!util_string_equal( real_name , alias)) - hash_insert_ref( workflow_list->alias_map , alias , real_name ); -} - - -void ert_workflow_list_add_job( ert_workflow_list_type * workflow_list , const char * job_name , const char * config_file ) { - char * name = (char *) job_name; - - if (job_name == NULL) - util_alloc_file_components( config_file , NULL , &name , NULL ); - - if (!workflow_joblist_add_job_from_file( workflow_list->joblist , name , config_file )) - fprintf(stderr,"** Warning: failed to add workflow job:%s from:%s \n",name , config_file ); - - if (job_name == NULL) - free(name); -} - - -bool ert_workflow_list_has_job( const ert_workflow_list_type * workflow_list , const char * job_name) { - return workflow_joblist_has_job( workflow_list->joblist , job_name ); -} - - -const workflow_job_type * ert_workflow_list_get_job( const ert_workflow_list_type * workflow_list , const char * job_name) { - return workflow_joblist_get_job(workflow_list->joblist, job_name); -} - -/** - This function will create the most specific matching filename - corresponding to the @root_name input. I.e. it will look for - filename in this order: - - ROOT@X.Y.Z, ROOT@X.Y, ROOT@X, ROOT - - And return the first name corresponding to an existing file. If no - file can be found the function will return NULL. -*/ - -static char * ert_workflow_list_alloc_version_name( const char * path , const char * root_name ) { - char * full_path = util_alloc_sprintf( "%s%s%s@%d.%d.%s" , path , UTIL_PATH_SEP_STRING , root_name , - version_get_major_ert_version(), - version_get_minor_ert_version(), - version_get_micro_ert_version()); - if (util_is_file( full_path )) - return full_path; - else - free( full_path ); - - /*****************************************************************/ - - full_path = util_alloc_sprintf( "%s%s%s@%d.%d" , path , UTIL_PATH_SEP_STRING , root_name , - version_get_major_ert_version(), - version_get_minor_ert_version()); - - if (util_is_file( full_path )) - return full_path; - else - free( full_path ); - - /*****************************************************************/ - - full_path = util_alloc_sprintf( "%s%s%s@%d" , path , UTIL_PATH_SEP_STRING , root_name , - version_get_major_ert_version()); - - if (util_is_file( full_path )) - return full_path; - else - free( full_path ); - - - /*****************************************************************/ - - full_path = util_alloc_sprintf( "%s%s%s" , path , UTIL_PATH_SEP_STRING , root_name); - - if (util_is_file( full_path )) - return full_path; - else - free( full_path ); - - return NULL; -} - - - -void ert_workflow_list_add_jobs_in_directory( ert_workflow_list_type * workflow_list , const char * path ) { - DIR * dirH = opendir( path ); - set_type * names = set_alloc( 0 , NULL ); - if (dirH) { - while (true) { - struct dirent * entry = readdir( dirH ); - if (entry != NULL) { - if ((strcmp(entry->d_name , ".") != 0) && (strcmp(entry->d_name , "..") != 0)) { - char * root_name, * version; - util_binary_split_string( entry->d_name , "@" , false , &root_name , &version); - if (!set_has_key( names , root_name)) { - char * full_path = ert_workflow_list_alloc_version_name( path , root_name ); - - if (full_path) { - set_add_key( names , root_name ); - if (ert_log_is_open()) - ert_log_add_message( 1 , NULL , util_alloc_sprintf("Adding workflow job:%s " , full_path ), true); - - ert_workflow_list_add_job( workflow_list , root_name , full_path ); - } - - free( full_path ); - } - free( root_name ); - free( version ); - } - } else - break; - } - closedir( dirH ); - } else - fprintf(stderr, "** Warning: failed to open workflow/jobs directory: %s\n", path); - - set_free( names ); -} - - -stringlist_type * ert_workflow_list_get_job_names(const ert_workflow_list_type * workflow_list) { - return workflow_joblist_get_job_names(workflow_list->joblist); -} - - -void ert_workflow_list_init( ert_workflow_list_type * workflow_list , config_content_type * config ) { - /* Adding jobs */ - { - if (config_content_has_item( config , WORKFLOW_JOB_DIRECTORY_KEY)) { - const config_content_item_type * jobpath_item = config_content_get_item( config , WORKFLOW_JOB_DIRECTORY_KEY); - for (int i=0; i < config_content_item_get_size( jobpath_item ); i++) { - config_content_node_type * path_node = config_content_item_iget_node( jobpath_item , i ); - - for (int j=0; j < config_content_node_get_size( path_node ); j++) - ert_workflow_list_add_jobs_in_directory( workflow_list , config_content_node_iget_as_abspath( path_node , j ) ); - } - } - } - - { - if (config_content_has_item( config , LOAD_WORKFLOW_JOB_KEY)) { - const config_content_item_type * job_item = config_content_get_item( config , LOAD_WORKFLOW_JOB_KEY); - for (int i=0; i < config_content_item_get_size( job_item ); i++) { - config_content_node_type * job_node = config_content_item_iget_node( job_item , i ); - const char * config_file = config_content_node_iget_as_path( job_node , 0 ); - const char * job_name = config_content_node_safe_iget( job_node , 1 ); - ert_workflow_list_add_job( workflow_list , job_name , config_file); - } - } - } - - - /* Adding workflows */ - { - if (config_content_has_item( config , LOAD_WORKFLOW_KEY)) { - const config_content_item_type * workflow_item = config_content_get_item( config , LOAD_WORKFLOW_KEY); - for (int i=0; i < config_content_item_get_size( workflow_item ); i++) { - config_content_node_type * workflow_node = config_content_item_iget_node( workflow_item , i ); - const char * workflow_file = config_content_node_iget_as_path( workflow_node , 0 ); - const char * workflow_name = config_content_node_safe_iget( workflow_node , 1 ); - - ert_workflow_list_add_workflow( workflow_list , workflow_file , workflow_name ); - } - } - } -} - - -void ert_workflow_list_add_config_items( config_parser_type * config ) { - config_schema_item_type * item = config_add_schema_item( config , WORKFLOW_JOB_DIRECTORY_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , CONFIG_PATH ); - - item = config_add_schema_item( config , LOAD_WORKFLOW_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 2 ); - config_schema_item_iset_type( item , 0 , CONFIG_EXISTING_PATH ); - - item = config_add_schema_item( config , LOAD_WORKFLOW_JOB_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 2 ); - config_schema_item_iset_type( item , 0 , CONFIG_EXISTING_PATH ); -} - - - -workflow_type * ert_workflow_list_get_workflow(ert_workflow_list_type * workflow_list , const char * workflow_name ) { - const char * lookup_name = workflow_name; - - if (hash_has_key( workflow_list->alias_map , workflow_name)) - lookup_name = hash_get( workflow_list->alias_map , workflow_name ); - - return hash_get( workflow_list->workflows , lookup_name ); -} - -bool ert_workflow_list_has_workflow(ert_workflow_list_type * workflow_list , const char * workflow_name ) { - return - hash_has_key( workflow_list->workflows , workflow_name ) || - hash_has_key( workflow_list->alias_map , workflow_name); -} - - -bool ert_workflow_list_run_workflow__(ert_workflow_list_type * workflow_list, workflow_type * workflow, bool verbose , void * self) { - bool runOK = workflow_run( workflow, self , verbose , workflow_list->context); - if (runOK) - workflow_list->last_error = NULL; - else - workflow_list->last_error = workflow_get_last_error( workflow ); - - return runOK; -} - - -bool ert_workflow_list_run_workflow_blocking(ert_workflow_list_type * workflow_list , const char * workflow_name , void * self) { - workflow_type * workflow = ert_workflow_list_get_workflow( workflow_list , workflow_name ); - bool result = ert_workflow_list_run_workflow__( workflow_list, workflow , workflow_list->verbose , self); - return result; -} - - -bool ert_workflow_list_run_workflow(ert_workflow_list_type * workflow_list, const char * workflow_name , void * self) { - workflow_type * workflow = ert_workflow_list_get_workflow( workflow_list , workflow_name ); - return ert_workflow_list_run_workflow__( workflow_list, workflow , workflow_list->verbose , self); -} - - -/*****************************************************************/ - -stringlist_type * ert_workflow_list_alloc_namelist( ert_workflow_list_type * workflow_list ) { - return hash_alloc_stringlist( workflow_list->workflows ); -} - - -const config_error_type * ert_workflow_list_get_last_error( const ert_workflow_list_type * workflow_list) { - return workflow_list->last_error; -} - - -int ert_workflow_list_get_size( const ert_workflow_list_type * workflow_list) { - return hash_get_size( workflow_list->workflows ) + hash_get_size( workflow_list->alias_map); -} diff --git a/ThirdParty/Ert/libenkf/src/field.c b/ThirdParty/Ert/libenkf/src/field.c deleted file mode 100644 index 5fa6eccdb9..0000000000 --- a/ThirdParty/Ert/libenkf/src/field.c +++ /dev/null @@ -1,1564 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'field.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -GET_DATA_SIZE_HEADER(field); - - -/*****************************************************************/ - -/** - The field data type contains for "something" which is distributed - over the full grid, i.e. permeability or pressure. All configuration - information is stored in the config object, which is of type - field_config_type. Observe the following: - - * The field **only** contains the active cells - the config object - has a reference to actnum information. - - * The data is stored in a char pointer; the real underlying data can - be (at least) of the types int, float and double. -*/ - -struct field_struct { - int __type_id; - const field_config_type * config; /* The field config object - containing information of active cells++ */ - bool private_config; - char *data; /* The actual storage for the field - suitabley casted to int/float/double on use*/ - - bool shared_data; /* If the data is shared - i.e. managed (xalloc & free) from another scope. */ - int shared_byte_size; /* The size of the shared buffer (if it is shared). */ - char *export_data; /* IFF an output transform should be applied this pointer will hold the transformed data. */ - char *__data; /* IFF an output transform, this pointer will hold the original data during the transform and export. */ -}; - - - -#define EXPORT_MACRO \ -{ \ - int nx,ny,nz; \ - field_config_get_dims(field->config , &nx , &ny , &nz); \ - int i,j,k; \ - for (k=0; k < nz; k++) { \ - for (j=0; j < ny; j++) { \ - for (i=0; i < nx; i++) { \ - bool active_cell = field_config_active_cell(config, i, j, k); \ - bool use_initial_value = false; \ - \ - if (init_file && !active_cell) \ - use_initial_value = true; \ - \ - int source_index = 0; \ - if (use_initial_value) \ - source_index = field_config_global_index(config , i , j , k); \ - else \ - source_index = field_config_active_index(config, i, j, k); \ - \ - int target_index; \ - if (rms_index_order) \ - target_index = rms_util_global_index_from_eclipse_ijk(nx,ny,nz,i,j,k); \ - else \ - target_index = i + j * nx + k* nx*ny; \ - \ - if (use_initial_value) \ - target_data[target_index] = initial_src_data[source_index]; \ - else if (active_cell) \ - target_data[target_index] = src_data[source_index]; \ - else \ - memcpy(&target_data[target_index] , fill_value , sizeof_ctype_target); \ - } \ - } \ - } \ -} \ - - -void field_export3D(const field_type * field , - void *_target_data , - bool rms_index_order , - ecl_type_enum target_type , - void *fill_value, - const char * init_file) { - - const field_config_type * config = field->config; - ecl_type_enum ecl_type = field_config_get_ecl_type( config ); - int sizeof_ctype_target = ecl_util_get_sizeof_ctype(target_type); - - field_type * initial_field = NULL; - field_config_type * initial_field_config = NULL; - if (init_file) { - ecl_grid_type * grid = field_config_get_grid(config); - bool global_size = true; - initial_field_config = field_config_alloc_empty(field_config_get_key(config), grid, NULL, global_size); - initial_field = field_alloc(initial_field_config); - - field_fload_keep_inactive(initial_field, init_file); - } - - switch(ecl_type) { - case(ECL_DOUBLE_TYPE): - { - const double * src_data = (const double *) field->data; - const double * initial_src_data = initial_field ? (const double *) initial_field->data : NULL; - - if (target_type == ECL_FLOAT_TYPE) { - float *target_data = (float *) _target_data; - EXPORT_MACRO; - } else if (target_type == ECL_DOUBLE_TYPE) { - double *target_data = (double *) _target_data; - EXPORT_MACRO; - } else { - fprintf(stderr,"%s: double field can only export to double/float\n",__func__); - abort(); - } - } - break; - case(ECL_FLOAT_TYPE): - { - const float * src_data = (const float *) field->data; - const float * initial_src_data = initial_field ? (const float *) initial_field->data : NULL; - if (target_type == ECL_FLOAT_TYPE) { - float *target_data = (float *) _target_data; - EXPORT_MACRO; - } else if (target_type == ECL_DOUBLE_TYPE) { - double *target_data = (double *) _target_data; - EXPORT_MACRO; - } else { - fprintf(stderr,"%s: float field can only export to double/float\n",__func__); - abort(); - } - } - break; - case(ECL_INT_TYPE): - { - const int * src_data = (const int *) field->data; - const int * initial_src_data = initial_field ? (const int *) initial_field->data : NULL; - if (target_type == ECL_FLOAT_TYPE) { - float *target_data = (float *) _target_data; - EXPORT_MACRO; - } else if (target_type == ECL_DOUBLE_TYPE) { - double *target_data = (double *) _target_data; - EXPORT_MACRO; - } else if (target_type == ECL_INT_TYPE) { - int *target_data = (int *) _target_data; - EXPORT_MACRO; - } else { - fprintf(stderr,"%s: int field can only export to int/double/float\n",__func__); - abort(); - } - } - break; - default: - fprintf(stderr,"%s: Sorry field has unexportable type ... \n",__func__); - break; - } - - if (initial_field) { - field_config_free(initial_field_config); - field_free(initial_field); - } -} -#undef EXPORT_MACRO - - -/*****************************************************************/ -#define IMPORT_MACRO \ -{ \ - int i,j,k; \ - int nx,ny,nz; \ - field_config_get_dims(field->config , &nx , &ny , &nz); \ - for (k=0; k < nz; k++) { \ - for (j=0; j < ny; j++) { \ - for (i=0; i < nx; i++) { \ - int target_index = keep_inactive_cells ? field_config_global_index(config, i, j, k) : field_config_active_index(config, i, j, k); \ - \ - if (target_index >= 0) { \ - int source_index; \ - if (rms_index_order) \ - source_index = rms_util_global_index_from_eclipse_ijk(nx,ny,nz,i,j,k); \ - else \ - source_index = i + j * nx + k* nx*ny; \ - \ - target_data[target_index] = src_data[source_index] ; \ - } \ - } \ - } \ - } \ -} \ - - - -/** - The main function of the field_import3D and field_export3D - functions are to skip the inactive cells (field_import3D) and - distribute inactive cells (field_export3D). - When the flag keep_inactive_cells is set for field_import3D, - the values for the inactive cells are kept. The field argument - must have been allocated with flag global_size = true for this - to work. - When field_export3D is called with argument INIT_FILE, the - exported values for inactive cells are read from the INIT_FILE. - - In addition we can reorganize input/output according to the - RMS Roff index convention, and also perform float <-> double - conversions. - - Observe that these functions only import/export onto memory - buffers, the actual reading and writing of files is done in other - functions (calling these). -*/ - -static void field_import3D(field_type * field , - const void *_src_data , - bool rms_index_order , - bool keep_inactive_cells, - ecl_type_enum src_type) { - const field_config_type * config = field->config; - ecl_type_enum ecl_type = field_config_get_ecl_type(config); - - switch(ecl_type) { - case(ECL_DOUBLE_TYPE): - { - double * target_data = (double *) field->data; - if (src_type == ECL_FLOAT_TYPE) { - float *src_data = (float *) _src_data; - IMPORT_MACRO; - } else if (src_type == ECL_DOUBLE_TYPE) { - double *src_data = (double *) _src_data; - IMPORT_MACRO; - } else if (src_type == ECL_INT_TYPE) { - int *src_data = (int *) _src_data; - IMPORT_MACRO; - } else { - fprintf(stderr,"%s: double field can only import from int/double/float\n",__func__); - abort(); - } - } - break; - case(ECL_FLOAT_TYPE): - { - float * target_data = (float *) field->data; - if (src_type == ECL_FLOAT_TYPE) { - float *src_data = (float *) _src_data; - IMPORT_MACRO; - } else if (src_type == ECL_DOUBLE_TYPE) { - double *src_data = (double *) _src_data; - IMPORT_MACRO; - } else if (src_type == ECL_INT_TYPE) { - int *src_data = (int *) _src_data; - IMPORT_MACRO; - } else { - fprintf(stderr,"%s: double field can only import from int/double/float\n",__func__); - abort(); - } - } - break; - case(ECL_INT_TYPE): - { - int * target_data = (int *) field->data; - if (src_type == ECL_INT_TYPE) { - int *src_data = (int *) _src_data; - IMPORT_MACRO; - } else { - fprintf(stderr,"%s: int field can only import from int\n",__func__); - abort(); - } - } - break; - default: - fprintf(stderr,"%s: Sorry field has unimportable type ... \n",__func__); - break; - } -} -#undef IMPORT_MACRO - - -/*****************************************************************/ - -#define CLEAR_MACRO(d,s) { int k; for (k=0; k < (s); k++) (d)[k] = 0; } -void field_clear(field_type * field) { - const ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - const int data_size = field_config_get_data_size(field->config ); - - switch (ecl_type) { - case(ECL_DOUBLE_TYPE): - { - double * data = (double *) field->data; - CLEAR_MACRO(data , data_size); - break; - } - case(ECL_FLOAT_TYPE): - { - float * data = (float *) field->data; - CLEAR_MACRO(data , data_size); - break; - } - case(ECL_INT_TYPE): - { - int * data = (int *) field->data; - CLEAR_MACRO(data , data_size); - break; - } - default: - util_abort("%s: not implemeneted for data_type: %d \n",__func__ , ecl_type); - } -} -#undef CLEAR_MACRO - - - - -static field_type * __field_alloc(const field_config_type * field_config , void * shared_data , int shared_byte_size) { - field_type * field = util_malloc(sizeof *field); - field->config = field_config; - field->private_config = false; - if (shared_data == NULL) { - field->shared_data = false; - field->data = util_calloc(field_config_get_byte_size(field->config) , sizeof * field->data ); - } else { - field->data = shared_data; - field->shared_data = true; - field->shared_byte_size = shared_byte_size; - if (shared_byte_size < field_config_get_byte_size(field->config)) - util_abort("%s: the shared buffer is to small to hold the input field - aborting \n",__func__); - - } - field->export_data = NULL; /* This NULL is checked for in the revert_output_transform() */ - field->__type_id = FIELD; - return field; -} - - - -field_type * field_alloc(const field_config_type * field_config) { - return __field_alloc(field_config , NULL , 0); -} - - -field_type * field_alloc_shared(const field_config_type * field_config, void * shared_data , int shared_byte_size) { - return __field_alloc(field_config , shared_data , shared_byte_size); -} - - - -void field_copy(const field_type *src , field_type * target ) { - if (src->config == target->config) - memcpy(target->data , src->data , field_config_get_byte_size(src->config)); - else - util_abort("%s: instances do not share config \n",__func__); -} - - - -void field_read_from_buffer(field_type * field , buffer_type * buffer, enkf_fs_type * fs, int report_step) { - int byte_size = field_config_get_byte_size( field->config ); - enkf_util_assert_buffer_type(buffer , FIELD); - buffer_fread_compressed(buffer , buffer_get_remaining_size( buffer ) , field->data , byte_size); -} - - - -static void * __field_alloc_3D_data(const field_type * field , - int data_size , - bool rms_index_order , - ecl_type_enum ecl_type , - ecl_type_enum target_type, - const char * init_file) { - void * data = util_calloc(data_size , ecl_util_get_sizeof_ctype(target_type) ); - if (ecl_type == ECL_DOUBLE_TYPE) { - double fill; - if (rms_index_order) - fill = RMS_INACTIVE_DOUBLE; - else - fill = 0; - field_export3D(field , data , rms_index_order , target_type , &fill, init_file); - } else if (ecl_type == ECL_FLOAT_TYPE) { - float fill; - if (rms_index_order) - fill = RMS_INACTIVE_FLOAT; - else - fill = 0; - field_export3D(field , data , rms_index_order , target_type , &fill, init_file); - } else if (ecl_type == ECL_INT_TYPE) { - int fill; - if (rms_index_order) - fill = RMS_INACTIVE_INT; - else - fill = 0; - field_export3D(field , data , rms_index_order , target_type , &fill, init_file); - } else - util_abort("%s: trying to export type != int/float/double - aborting \n",__func__); - return data; -} - - -/** - A general comment about writing fields to disk: - - The writing of fields to disk can be done in **MANY** different ways: - - o The native function field_fwrite() will save the field in the - format most suitable for use with enkf. This function will only - save the active cells, and compress the field if the variable - write_compressed is true. Most of the configuration information - is with the field_config object, and not saved with the field. - - o Export as ECLIPSE input. This again has three subdivisions: - - * The function field_ecl_grdecl_export() will write the field to - disk in a format suitable for ECLIPSE INCLUDE statements. This - means that both active and inactive cells are written, with a - zero fill for the inactive. If the argument init_file is set, - the value for the inactive cells are read from this file. - - * The functions field_xxxx_fortio() writes the field in the - ECLIPSE restart format. The function field_ecl_write3D_fortio() - writes all the cells - with zero filling for inactive - cells. This is suitable for IMPORT of e.g. PORO. - - The function field_ecl_write1D_fortio() will write only the - active cells in an ECLIPSE restart file. This is suitable for - e.g. the pressure. - - Observe that the function field_ecl_write() should get config - information and automatically select the right way to export to - eclipse format. - - o Export in RMS ROFF format. -*/ - - - -/** - This function exports *one* field instance to the rms_file - instance. It is the responsibility of the field_ROFF_export() - function to initialize and close down the rms_file instance. -*/ - -static void field_ROFF_export__(const field_type * field , rms_file_type * rms_file, const char * init_file) { - const int data_size = field_config_get_volume(field->config); - const ecl_type_enum target_type = field_config_get_ecl_type(field->config); /* Could/should in principle be input */ - const ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - - void *data = __field_alloc_3D_data(field , data_size , true , ecl_type , target_type, init_file); - rms_tagkey_type * data_key = rms_tagkey_alloc_complete("data" , data_size , rms_util_convert_ecl_type(target_type) , data , true); - rms_tag_fwrite_parameter(field_config_get_ecl_kw_name(field->config) , data_key , rms_file_get_FILE(rms_file)); - rms_tagkey_free(data_key); - free(data); -} - - -static rms_file_type * field_init_ROFF_export(const field_type * field, const char * filename) { - rms_file_type * rms_file = rms_file_alloc(filename , false); - rms_file_fopen_w(rms_file); - rms_file_init_fwrite(rms_file , "parameter"); /* Version / byteswap ++ */ - { - int nx,ny,nz; - field_config_get_dims(field->config , &nx , &ny , &nz); - rms_tag_fwrite_dimensions(nx , ny , nz , rms_file_get_FILE(rms_file)); /* Dimension header */ - } - return rms_file; -} - - -static void field_complete_ROFF_export(const field_type * field , rms_file_type * rms_file) { - rms_file_complete_fwrite(rms_file); - rms_file_fclose(rms_file); - rms_file_free(rms_file); -} - - - - -/** - This function exports the data of a field as a parameter to an RMS - roff file. The export process is divided in three parts: - - 1. The rms_file is opened, and initialized with some basic data - for dimensions++ - 2. The field is written to file. - 3. The file is completed / closed. - - The reason for doing it like this is that it should be easy to - export several fields (of the same dimension+++) with repeated - calls to 2 (i.e. field_ROFF_export__()) - that is currently not - implemented. -*/ - -void field_ROFF_export(const field_type * field , const char * export_filename, const char * init_file) { - rms_file_type * rms_file = field_init_ROFF_export(field , export_filename); - field_ROFF_export__(field , rms_file, init_file); /* Should now be possible to several calls to field_ROFF_export__() */ - field_complete_ROFF_export(field , rms_file); -} - - - -bool field_write_to_buffer(const field_type * field , buffer_type * buffer , int report_step) { - int byte_size = field_config_get_byte_size( field->config ); - buffer_fwrite_int( buffer , FIELD ); - buffer_fwrite_compressed( buffer , field->data , byte_size ); - return true; -} - - - -void field_ecl_write1D_fortio(const field_type * field , fortio_type * fortio) { - const int data_size = field_config_get_data_size(field->config ); - const ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - - ecl_kw_fwrite_param_fortio(fortio , field_config_get_ecl_kw_name(field->config), ecl_type , data_size , field->data); -} - - -void field_ecl_write3D_fortio(const field_type * field , fortio_type * fortio, const char * init_file ) { - const int data_size = field_config_get_volume(field->config); - const ecl_type_enum target_type = field_config_get_ecl_type(field->config); /* Could/should in principle be input */ - const ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - void *data = __field_alloc_3D_data(field , data_size , false ,ecl_type , target_type, init_file); - - ecl_kw_fwrite_param_fortio(fortio , field_config_get_ecl_kw_name(field->config), ecl_type , data_size , data); - free(data); -} - - -static ecl_kw_type * field_alloc_ecl_kw_wrapper__(const field_type * field, void * data) { - const int data_size = field_config_get_volume(field->config); - const ecl_type_enum target_type = field_config_get_ecl_type(field->config); /* Could/should in principle be input */ - - ecl_kw_type * ecl_kw = ecl_kw_alloc_new_shared(field_config_get_ecl_kw_name(field->config) , data_size , target_type , data); - - return ecl_kw; -} - - -void field_ecl_grdecl_export(const field_type * field , FILE * stream, const char * init_file) { - const int data_size = field_config_get_volume(field->config); - const ecl_type_enum target_type = field_config_get_ecl_type(field->config); /* Could/should in principle be input */ - const ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - void *data = __field_alloc_3D_data(field , data_size , false , ecl_type , target_type, init_file ); - ecl_kw_type * ecl_kw = field_alloc_ecl_kw_wrapper__(field , data); - ecl_kw_fprintf_grdecl(ecl_kw , stream); - ecl_kw_free(ecl_kw); - free(data); -} - - -/** - This allocates a ecl_kw instance representing the field. The - size/header/type are copied from the field. whereas the data is - *SHARED* with the field->data. - - The ecl_kw instance knows that the data is only shared, and it is - safe to call ecl_kw_free() on it. -*/ - -ecl_kw_type * field_alloc_ecl_kw_wrapper(const field_type * field) { - ecl_kw_type * ecl_kw = field_alloc_ecl_kw_wrapper__(field , field->data); - return ecl_kw; -} - - -static void field_apply(field_type * field , field_func_type * func) { - field_config_assert_unary(field->config , __func__); - { - const int data_size = field_config_get_data_size( field->config ); - const ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - - if (ecl_type == ECL_FLOAT_TYPE) { - float * data = (float *) field->data; - for (int i=0; i < data_size; i++) - data[i] = func(data[i]); - } else if (ecl_type == ECL_DOUBLE_TYPE) { - double * data = (double *) field->data; - for (int i=0; i < data_size; i++) - data[i] = func(data[i]); - } - } -} - - -static bool field_check_finite( const field_type * field) { - const int data_size = field_config_get_data_size( field->config ); - const ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - bool ok = true; - - if (ecl_type == ECL_FLOAT_TYPE) { - float * data = (float *) field->data; - for (int i=0; i < data_size; i++) - if (!isfinite( data[i] )) - ok = false; - } else if (ecl_type == ECL_DOUBLE_TYPE) { - double * data = (double *) field->data; - for (int i=0; i < data_size; i++) - if (!isfinite( data[i] )) - ok = false; - } - return ok; -} - - - -void field_inplace_output_transform(field_type * field ) { - field_func_type * output_transform = field_config_get_output_transform(field->config); - if (output_transform != NULL) - field_apply(field , output_transform); -} - - - -#define TRUNCATE_MACRO(s , d , t , min , max) \ -for (int i=0; i < s; i++) { \ - if ( t & TRUNCATE_MIN ) \ - if (d[i] < min) \ - d[i] = min; \ - if ( t & TRUNCATE_MAX ) \ - if (d[i] > max) \ - d[i] = max; \ -} - - -static void field_apply_truncation(field_type * field) { - truncation_type truncation = field_config_get_truncation_mode( field->config ); - if (truncation != TRUNCATE_NONE) { - double min_value = field_config_get_truncation_min( field->config ); - double max_value = field_config_get_truncation_max( field->config ); - - const int data_size = field_config_get_data_size(field->config ); - const ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - if (ecl_type == ECL_FLOAT_TYPE) { - float * data = (float *) field->data; - TRUNCATE_MACRO(data_size , data , truncation , min_value , max_value); - } else if (ecl_type == ECL_DOUBLE_TYPE) { - double * data = (double *) field->data; - TRUNCATE_MACRO(data_size , data , truncation , min_value , max_value); - } else - util_abort("%s: Field type not supported for truncation \n",__func__); - } -} - - -/** - Does both the explicit output transform *AND* the truncation. -*/ - -static void field_output_transform(field_type * field) { - field_func_type * output_transform = field_config_get_output_transform(field->config); - truncation_type truncation = field_config_get_truncation_mode( field->config ); - if ((output_transform != NULL) || (truncation != TRUNCATE_NONE)) { - field->export_data = util_alloc_copy(field->data , field_config_get_byte_size(field->config) ); - field->__data = field->data; /* Storing a pointer to the original data. */ - field->data = field->export_data; - - if (output_transform != NULL) - field_inplace_output_transform(field); - - field_apply_truncation(field); - } -} - - -static void field_revert_output_transform(field_type * field) { - if (field->export_data != NULL) { - free(field->export_data); - field->export_data = NULL; - field->data = field->__data; /* Recover the original pointer. */ - } -} - - -/** - This is the generic "export field to eclipse" function. It will - check up the config object to determine how to export the field, - and then call the appropriate function. The alternatives are: - - * Restart format - only active cells (field_ecl_write1D_fortio). - * Restart format - all cells (field_ecl_write3D_fortio). - * GRDECL format (field_ecl_grdecl_export) - - Observe that the output transform is hooked in here, that means - that if you call e.g. the ROFF export function directly, the output - transform will *NOT* be applied. -*/ - -void field_export(const field_type * __field, - const char * file , - fortio_type * restart_fortio , - field_file_format_type file_type, - bool output_transform, - const char * init_file) { - field_type * field = (field_type *) __field; /* Net effect is no change ... but */ - - if (output_transform) field_output_transform(field); - { - - /* Writes the field to in ecl_kw format to a new file. */ - if ((file_type == ECL_KW_FILE_ALL_CELLS) || (file_type == ECL_KW_FILE_ACTIVE_CELLS)) { - fortio_type * fortio; - bool fmt_file = false; /* For formats which support both formatted and unformatted output this is hardwired to unformatted. */ - - fortio = fortio_open_writer(file , fmt_file , ECL_ENDIAN_FLIP); - - if (file_type == ECL_KW_FILE_ALL_CELLS) - field_ecl_write3D_fortio(field , fortio, init_file); - else - field_ecl_write1D_fortio(field , fortio); - - fortio_fclose(fortio); - } else if (file_type == ECL_GRDECL_FILE) { - /* Writes the field to a new grdecl file. */ - FILE * stream = util_mkdir_fopen(file , "w"); - field_ecl_grdecl_export(field , stream, init_file); - fclose(stream); - } else if (file_type == RMS_ROFF_FILE) - /* Roff export */ - field_ROFF_export(field , file, init_file); - else if (file_type == ECL_FILE) - /* This entry point is used by the ecl_write() function to write to an ALREADY OPENED eclipse restart file. */ - field_ecl_write1D_fortio( field , restart_fortio); - else - util_abort("%s: internal error file_type = %d - aborting \n",__func__ , file_type); - } - if (output_transform) field_revert_output_transform(field); -} - - -/** - Observe that the output transform is hooked in here, that means - that if you call e.g. the ROFF export function directly, the output - transform will *NOT* be applied. - - Observe that the output transform is done one a copy of the data - - not in place. When the export is complete the field->data will be - unchanged. -*/ - -void field_ecl_write(const field_type * field , const char * run_path , const char * file , void * filestream) { - field_file_format_type export_format = field_config_get_export_format(field->config); - - if (export_format == ECL_FILE) { - fortio_type * restart_fortio = fortio_safe_cast(filestream); - field_export(field , NULL , restart_fortio , export_format , true, NULL); - } - else { - char * full_path = util_alloc_filename( run_path , file , NULL); - if (util_is_link(full_path)) { - util_unlink_existing(full_path); - } - field_export(field , full_path , NULL , export_format , true, NULL); - free( full_path ); - } -} - - - -bool field_initialize(field_type *field , int iens , const char * init_file , rng_type * rng) { - bool ret = false; - if (init_file) { - if (field_fload(field , init_file )) { - field_func_type * init_transform = field_config_get_init_transform(field->config); - /* - Doing the input transform - observe that this is done inplace on - the data, not as the output transform which is done on a copy of - prior to export. - */ - if (init_transform) { - field_apply(field , init_transform); - if (!field_check_finite( field )) - util_exit("Sorry: after applying the init transform field:%s contains nan/inf or similar malformed values.\n" , field_config_get_key( field->config )); - } - ret = true; - } - } - - return ret; -} - - -void field_free(field_type *field) { - if (!field->shared_data) { - free(field->data); - field->data = NULL; - } - free(field); -} - - - -void field_serialize(const field_type * field , node_id_type node_id , const active_list_type * active_list , matrix_type * A , int row_offset , int column) { - const field_config_type *config = field->config; - const int data_size = field_config_get_data_size(config ); - ecl_type_enum ecl_type = field_config_get_ecl_type(config); - - enkf_matrix_serialize( field->data , data_size , ecl_type , active_list , A , row_offset , column); -} - - -void field_deserialize(field_type * field , node_id_type node_id , const active_list_type * active_list , const matrix_type * A , int row_offset , int column) { - const field_config_type *config = field->config; - const int data_size = field_config_get_data_size(config ); - ecl_type_enum ecl_type = field_config_get_ecl_type(config); - - enkf_matrix_deserialize( field->data , data_size , ecl_type , active_list , A , row_offset , column); -} - -static int __get_index(const field_type * field, int i, int j, int k) { - return field_config_keep_inactive_cells(field->config) ? field_config_global_index(field->config , i , j , k) : field_config_active_index(field->config , i , j , k); -} - - -void field_ijk_get(const field_type * field , int i , int j , int k , void * value) { - int index = __get_index(field, i, j, k); - int sizeof_ctype = field_config_get_sizeof_ctype(field->config); - memcpy(value , &field->data[index * sizeof_ctype] , sizeof_ctype); -} - - - -double field_ijk_get_double(const field_type * field, int i , int j , int k) { - int index = __get_index(field, i, j, k); - return field_iget_double( field , index ); -} - - -float field_ijk_get_float(const field_type * field, int i , int j , int k) { - int index = __get_index(field, i, j, k); - return field_iget_float( field , index ); -} - - -/** - Takes an active or global index as input, and returns a double. -*/ -double field_iget_double(const field_type * field , int index) { - ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - int sizeof_ctype = field_config_get_sizeof_ctype(field->config); - char buffer[8]; /* Enough to hold one double */ - memcpy(buffer , &field->data[index * sizeof_ctype] , sizeof_ctype); - if ( ecl_type == ECL_DOUBLE_TYPE ) - return *((double *) buffer); - else if (ecl_type == ECL_FLOAT_TYPE) { - double double_value; - float float_value; - - float_value = *((float *) buffer); - double_value = float_value; - - return double_value; - } else { - util_abort("%s: failed - wrong internal type \n",__func__); - return -1; - } -} - - -/** - Takes an active or global index as input, and returns a double. -*/ -float field_iget_float(const field_type * field , int index) { - ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - int sizeof_ctype = field_config_get_sizeof_ctype(field->config); - char buffer[8]; /* Enough to hold one double */ - memcpy(buffer , &field->data[index * sizeof_ctype] , sizeof_ctype); - if ( ecl_type == ECL_FLOAT_TYPE ) - return *((float *) buffer); - else if (ecl_type == ECL_DOUBLE_TYPE) { - double double_value; - float float_value; - - double_value = *((double *) buffer); - float_value = double_value; - - return float_value; - } else { - util_abort("%s: failed - wrong internal type \n",__func__); - return -1; - } -} - - - - -double field_iget(const field_type * field, int index) { - return field_iget_double(field , index); -} - - - -void field_ijk_set(field_type * field , int i , int j , int k , const void * value) { - int index = __get_index(field, i, j, k); - int sizeof_ctype = field_config_get_sizeof_ctype(field->config); - memcpy(&field->data[index * sizeof_ctype] , value , sizeof_ctype); -} - - -#define INDEXED_UPDATE_MACRO(t,s,n,index,add) \ -{ \ - int i; \ - if (add) \ - for (i=0; i < (n); i++) \ - (t)[index[i]] += (s)[i]; \ - else \ - for (i=0; i < (n); i++) \ - (t)[index[i]] = (s)[i]; \ -} - - - -static void field_indexed_update(field_type * field, ecl_type_enum src_type , int len , const int * index_list , const void * value , bool add) { - ecl_type_enum target_type = field_config_get_ecl_type(field->config); - - switch (target_type) { - case(ECL_FLOAT_TYPE): - { - float * field_data = (float *) field->data; - if (src_type == ECL_DOUBLE_TYPE) { - double * src_data = (double *) value; - INDEXED_UPDATE_MACRO(field_data , src_data , len , index_list , add); - } else if (src_type == ECL_FLOAT_TYPE) { - float * src_data = (float *) value; - INDEXED_UPDATE_MACRO(field_data , src_data , len , index_list , add); - } else - util_abort("%s both existing field - and indexed values must be float / double - aborting\n",__func__); - } - break; - case(ECL_DOUBLE_TYPE): - { - double * field_data = (double *) field->data; - if (src_type == ECL_DOUBLE_TYPE) { - double * src_data = (double *) value; - INDEXED_UPDATE_MACRO(field_data , src_data , len , index_list , add); - } else if (src_type == ECL_FLOAT_TYPE) { - float * src_data = (float *) value; - INDEXED_UPDATE_MACRO(field_data , src_data , len , index_list , add); - } else - util_abort("%s both existing field - and indexed values must be float / double - aborting\n",__func__); - } - break; - default: - util_abort("%s existing field must be of type float/double - aborting \n",__func__); - } -} - - -void field_indexed_set(field_type * field, ecl_type_enum src_type , int len , const int * index_list , const void * value) { - field_indexed_update(field , src_type , len , index_list , value , false); -} - - -void field_indexed_add(field_type * field, ecl_type_enum src_type , int len , const int * index_list , const void * value) { - field_indexed_update(field , src_type , len , index_list , value , true); -} - - - -double * field_indexed_get_alloc(const field_type * field, int len, const int * index_list) -{ - double * export_data = util_calloc(len , sizeof * export_data); - ecl_type_enum src_type = field_config_get_ecl_type(field->config); - - if(src_type == ECL_DOUBLE_TYPE) { - /* double -> double */ - double * field_data = (double *) field->data; - for (int i=0; i double */ - float * field_data = (float *) field->data; - for (int i=0; i=0) - return true; - else - return false; -} - - -void field_ijk_get_if_valid(const field_type * field , int i , int j , int k , void * value , bool * valid) { - int index = __get_index(field, i, j, k); - if (index >=0) { - *valid = true; - field_ijk_get(field , i , j , k , value); - } else - *valid = false; -} - - -int field_get_active_index(const field_type * field , int i , int j , int k) { - return field_config_active_index(field->config , i , j , k); -} - -int field_get_global_index(const field_type * field , int i , int j , int k) { - return field_config_global_index(field->config , i , j , k); -} - - - -/** - Copying data from a (PACKED) ecl_kw instance down to a fields data. -*/ - -void field_copy_ecl_kw_data(field_type * field , const ecl_kw_type * ecl_kw) { - const field_config_type * config = field->config; - const int data_size = field_config_get_data_size(config ); - ecl_type_enum field_type = field_config_get_ecl_type(field->config); - ecl_type_enum kw_type = ecl_kw_get_type(ecl_kw); - - if (data_size != ecl_kw_get_size(ecl_kw)) { - fprintf(stderr,"\n"); - fprintf(stderr," ** Fatal error - the number of active cells has changed \n"); - fprintf(stderr," ** Grid:%s has %d active cells. \n",field_config_get_grid_name( config ) , data_size); - fprintf(stderr," ** %s loaded from file has %d active cells.\n",field_config_get_key(config), ecl_kw_get_size(ecl_kw)); - fprintf(stderr," ** MINPV / MINPVV problem?? \n"); - util_abort("%s: Aborting \n",__func__ ); - } - - ecl_util_memcpy_typed_data(field->data , ecl_kw_get_void_ptr(ecl_kw) , field_type , kw_type , ecl_kw_get_size(ecl_kw)); -} - - - -/*****************************************************************/ - -bool field_fload_rms(field_type * field , const char * filename, bool keep_inactive) { - { - FILE * stream = util_fopen__( filename , "r"); - if (!stream) - return false; - - fclose( stream ); - } - - { - const char * key = field_config_get_ecl_kw_name(field->config); - ecl_type_enum ecl_type; - rms_file_type * rms_file = rms_file_alloc(filename , false); - rms_tagkey_type * data_tag; - if (field_config_enkf_mode(field->config)) - data_tag = rms_file_fread_alloc_data_tagkey(rms_file , "parameter" , "name" , key); - else { - /** - Setting the key - purely to support converting between - different types of files, without knowing the key. A usable - feature - but not really well defined. - */ - - rms_tag_type * rms_tag = rms_file_fread_alloc_tag(rms_file , "parameter" , NULL , NULL); - const char * parameter_name = rms_tag_get_namekey_name(rms_tag); - field_config_set_key( (field_config_type *) field->config , parameter_name ); - data_tag = rms_tagkey_copyc( rms_tag_get_key(rms_tag , "data") ); - rms_tag_free(rms_tag); - } - - ecl_type = rms_tagkey_get_ecl_type(data_tag); - if (rms_tagkey_get_size(data_tag) != field_config_get_volume(field->config)) - util_abort("%s: trying to import rms_data_tag from:%s with wrong size - aborting \n",__func__ , filename); - - field_import3D(field , rms_tagkey_get_data_ref(data_tag) , true , keep_inactive, ecl_type); - rms_tagkey_free(data_tag); - rms_file_free(rms_file); - } - return true; -} - - - -static bool field_fload_ecl_kw(field_type * field , const char * filename, bool keep_inactive) { - const char * key = field_config_get_ecl_kw_name(field->config); - ecl_kw_type * ecl_kw = NULL; - - { - bool fmt_file; - - if (ecl_util_fmt_file( filename , &fmt_file)) { - fortio_type * fortio = fortio_open_reader(filename , fmt_file , ECL_ENDIAN_FLIP); - if (fortio) { - ecl_kw_fseek_kw(key , true , true , fortio); - ecl_kw = ecl_kw_fread_alloc( fortio ); - fortio_fclose(fortio); - - if (field_config_get_volume(field->config) == ecl_kw_get_size(ecl_kw)) - field_import3D(field , ecl_kw_get_void_ptr(ecl_kw) , false , keep_inactive, ecl_kw_get_type(ecl_kw)); - else - /* Keyword is already packed - e.g. from a restart file. Size is - verified in the _copy function.*/ - field_copy_ecl_kw_data(field , ecl_kw); - - ecl_kw_free(ecl_kw); - return true; - } - } else - util_abort("%s: could not determine formatted/unformatted status of file:%s \n",filename); - } - return false; -} - - - -/* No type translation possible */ -static bool field_fload_ecl_grdecl(field_type * field , const char * filename, bool keep_inactive ) { - const char * key = field_config_get_ecl_kw_name(field->config); - int size = field_config_get_volume(field->config); - ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - ecl_kw_type * ecl_kw = NULL; - { - FILE * stream = util_fopen__(filename , "r"); - if (stream) { - if (ecl_kw_grdecl_fseek_kw(key , false , stream)) - ecl_kw = ecl_kw_fscanf_alloc_grdecl_data(stream , size , ecl_type); - else - util_exit("%s: Can not locate %s keyword in %s \n",__func__ , key , filename); - fclose(stream); - - field_import3D(field , ecl_kw_get_void_ptr(ecl_kw) , false , keep_inactive, ecl_kw_get_type(ecl_kw)); - ecl_kw_free(ecl_kw); - return true; - } - } - return false; -} - - - - -bool field_fload_typed(field_type * field , const char * filename , field_file_format_type file_type, bool keep_inactive) { - bool loadOK = false; - switch (file_type) { - case(RMS_ROFF_FILE): - loadOK = field_fload_rms(field , filename, keep_inactive ); - break; - case(ECL_KW_FILE): - loadOK = field_fload_ecl_kw(field , filename, keep_inactive ); - break; - case(ECL_GRDECL_FILE): - loadOK = field_fload_ecl_grdecl(field , filename, keep_inactive); - break; - default: - util_abort("%s: file_type:%d not recognized - aborting \n",__func__ , file_type); - } - return loadOK; -} - - -static bool field_fload_custom__(field_type * field , const char * filename , bool keep_inactive) { - if (util_file_readable( filename )) { - field_file_format_type file_type = field_config_guess_file_type( filename ); - if (file_type == UNDEFINED_FORMAT) - file_type = field_config_manual_file_type(filename , true); - - return field_fload_typed(field , filename , file_type, keep_inactive); - } else - return false; -} - - -bool field_fload(field_type * field , const char * filename) { - bool keep_inactive = false; - return field_fload_custom__(field, filename, keep_inactive); -} - - -bool field_fload_keep_inactive(field_type * field , const char * filename) { - bool keep_inactive = true; - return field_fload_custom__(field , filename , keep_inactive); -} - - -bool field_fload_auto(field_type * field , const char * filename, bool keep_inactive ) { - field_file_format_type file_type = field_config_guess_file_type(filename); - return field_fload_typed(field , filename , file_type, keep_inactive); -} - - - -/** - This function compares two fields, and return true if they are - equal. Observe that the config comparison is done with plain - pointer comparison, i.e. the actual content of the config objects - is not compared. If the two fields point to different config - objects, the comparision will fail immediately - without checking the - content of the fields. -*/ - -bool field_cmp(const field_type * f1 , const field_type * f2) { - if (f1->config != f2->config) { - fprintf(stderr,"The two fields have different config objects - and the comparison fails trivially.\n"); - return false; - } else { - const int byte_size = field_config_get_byte_size(f1->config); - if (memcmp( f1->data , f2->data , byte_size) != 0) - return false; - else - return true; - } -} - - -/*****************************************************************/ - - - - -/** - This function loads a field from a complete forward run. The - original implementation is to load e.g. pressure and saturations - from a block of restart data. Current implementation can only - handle that, but in principle other possibilities should be - possible. - - Observe that forward_load loads from a (already loaded) restart_block, - and not from a file. -*/ - - -static bool field_forward_load(field_type * field , - const char * ecl_file_name , - const forward_load_context_type * load_context) { - bool keep_inactive = false; - bool loadOK = true; - field_file_format_type import_format = field_config_get_import_format(field->config); - - if (import_format == ECL_FILE) { - const ecl_file_type * restart_file = forward_load_context_get_restart_file( load_context ); - if (restart_file != NULL) { - ecl_kw_type * field_kw = ecl_file_iget_named_kw(restart_file , field_config_get_ecl_kw_name(field->config) , 0); - field_copy_ecl_kw_data(field , field_kw); - } else - loadOK = false; - //util_abort("%s: fatal error when loading: %s - no restart information has been loaded \n",__func__ , field_config_get_key( field->config )); - } else - /* Loading from unique file - currently this only applies to the modelerror implementation. */ - field_fload_typed(field , ecl_file_name , import_format, keep_inactive); - - - if (loadOK) { - field_func_type * input_transform = field_config_get_input_transform(field->config); - /* The input transform is done in-place. */ - if (input_transform != NULL) - field_apply(field , input_transform); - - } - return loadOK; -} - - - -void field_get_dims(const field_type * field, int *nx, int *ny , int *nz) { - field_config_get_dims(field->config , nx , ny ,nz); -} - - - - - - - - -void field_iadd(field_type * field1, const field_type * field2) { - field_config_assert_binary(field1->config , field2->config , __func__); - { - const int data_size = field_config_get_data_size( field1->config ); - const ecl_type_enum ecl_type = field_config_get_ecl_type( field1->config ); - int i; - - if (ecl_type == ECL_FLOAT_TYPE) { - float * data1 = (float *) field1->data; - const float * data2 = (const float *) field2->data; - for (i = 0; i < data_size; i++) - data1[i] += data2[i]; - } else if (ecl_type == ECL_DOUBLE_TYPE) { - double * data1 = (double *) field1->data; - const double * data2 = (const double *) field2->data; - for (i = 0; i < data_size; i++) - data1[i] += data2[i]; - } - } -} - - -void field_imul(field_type * field1, const field_type * field2) { - field_config_assert_binary(field1->config , field2->config , __func__); - { - const int data_size = field_config_get_data_size(field1->config ); - const ecl_type_enum ecl_type = field_config_get_ecl_type(field1->config); - int i; - - if (ecl_type == ECL_FLOAT_TYPE) { - float * data1 = (float *) field1->data; - const float * data2 = (const float *) field2->data; - for (i = 0; i < data_size; i++) - data1[i] *= data2[i]; - } else if (ecl_type == ECL_DOUBLE_TYPE) { - double * data1 = (double *) field1->data; - const double * data2 = (const double *) field2->data; - for (i = 0; i < data_size; i++) - data1[i] *= data2[i]; - } - } -} - - -void field_iaddsqr(field_type * field1, const field_type * field2) { - field_config_assert_binary(field1->config , field2->config , __func__); - { - const int data_size = field_config_get_data_size(field1->config ); - const ecl_type_enum ecl_type = field_config_get_ecl_type(field1->config); - int i; - - if (ecl_type == ECL_FLOAT_TYPE) { - float * data1 = (float *) field1->data; - const float * data2 = (const float *) field2->data; - for (i = 0; i < data_size; i++) - data1[i] += data2[i] * data2[i]; - } else if (ecl_type == ECL_DOUBLE_TYPE) { - double * data1 = (double *) field1->data; - const double * data2 = (const double *) field2->data; - for (i = 0; i < data_size; i++) - data1[i] += data2[i] * data2[i]; - } - } -} - - -void field_scale(field_type * field, double scale_factor) { - field_config_assert_unary(field->config, __func__); - { - const int data_size = field_config_get_data_size(field->config ); - const ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - int i; - - if (ecl_type == ECL_FLOAT_TYPE) { - float * data = (float *) field->data; - for (i = 0; i < data_size; i++) - data[i] *= scale_factor; - } else if (ecl_type == ECL_DOUBLE_TYPE) { - double * data = (double *) field->data; - for (i = 0; i < data_size; i++) - data[i] *= scale_factor; - } - } -} - - -static inline float __sqr(float x) { return x*x; } - -void field_isqr(field_type * field) { - field_apply(field , __sqr); -} - - -void field_isqrt(field_type * field) { - field_apply(field , sqrtf); -} - -void field_imul_add(field_type * field1 , double factor , const field_type * field2) { - field_config_assert_binary(field1->config , field2->config , __func__); - { - const int data_size = field_config_get_data_size(field1->config ); - const ecl_type_enum ecl_type = field_config_get_ecl_type(field1->config); - int i; - - if (ecl_type == ECL_FLOAT_TYPE) { - float * data1 = (float *) field1->data; - const float * data2 = (const float *) field2->data; - for (i = 0; i < data_size; i++) - data1[i] += factor * data2[i]; - } else if (ecl_type == ECL_DOUBLE_TYPE) { - double * data1 = (double *) field1->data; - const double * data2 = (const double *) field2->data; - for (i = 0; i < data_size; i++) - data1[i] += factor * data2[i]; - } - } -} - - -void field_update_sum(field_type * sum , field_type * field , double lower_limit , double upper_limit) { - field_output_transform( field ); - { - const int data_size = field_config_get_data_size(field->config ); - const ecl_type_enum ecl_type = field_config_get_ecl_type(field->config); - int i; - - if (ecl_type == ECL_FLOAT_TYPE) { - float * data = (float *) field->data; - float * sum_data = (float *) sum->data; - for (i = 0; i < data_size; i++) { - if (data[i] >= lower_limit) - if (data[i] < upper_limit) - sum_data[i] += 1; - } - } else if (ecl_type == ECL_DOUBLE_TYPE) { - double * data = (double *) field->data; - double * sum_data = (double *) sum->data; - for (i = 0; i < data_size; i++) { - if (data[i] >= lower_limit) - if (data[i] < upper_limit) - sum_data[i] += 1; - } - } - } - field_revert_output_transform( field ); -} - - - -/** - Here, index_key is i a tree digit string with the i, j and k indicies of - the requested block separated by comma. E.g., 1,1,1. - - The string is supposed to contain indices in the range [1...nx] , - [1..ny] , [1...nz], they are immediately converted to C-based zero - offset indices. -*/ -bool field_user_get(const field_type * field, const char * index_key, int report_step , double * value) -{ - const bool internal_value = false; - bool valid; - int i,j,k; - int parse_user_key = field_config_parse_user_key(field->config , index_key , &i, &j , &k); - - - if (parse_user_key == 0) { - int active_index = field_config_active_index(field->config , i,j,k); - *value = field_iget_double(field, active_index); - valid = true; - } else { - if (parse_user_key == 1) - fprintf(stderr,"Failed to parse \"%s\" as three integers \n",index_key); - else if (parse_user_key == 2) - fprintf(stderr," ijk: %d , %d, %d is invalid \n",i+1 , j + 1 , k + 1); - else if (parse_user_key == 3) - fprintf(stderr," ijk: %d , %d, %d is an inactive cell. \n",i+1 , j + 1 , k + 1); - else - util_abort("%s: internal error -invalid value:%d \n",__func__ , parse_user_key); - *value = 0.0; - valid = false; - } - - if (!internal_value && valid) { - field_func_type * output_transform = field_config_get_output_transform(field->config); - if (output_transform != NULL) - *value = output_transform( *value ); - /* Truncation - ignored for now */ - } - return valid; -} - - - -#define INFLATE(inf,std,min) \ -{ \ - for (int i=0; i < data_size; i++) { \ - if (std_data[i] > 0) \ - inflation_data[i] = util_float_max( 1.0 , min_std_data[i] / std_data[i]); \ - else \ - inflation_data[i] = 1.0; \ - } \ -} - - -void field_set_inflation(field_type * inflation , const field_type * std , const field_type * min_std) { - const field_config_type * config = inflation->config; - ecl_type_enum ecl_type = field_config_get_ecl_type( config ); - const int data_size = field_config_get_data_size( config ); - - if (ecl_type == ECL_FLOAT_TYPE) { - float * inflation_data = (float *) inflation->data; - const float * std_data = (const float *) std->data; - const float * min_std_data = (const float *) min_std->data; - - INFLATE(inflation_data , std_data , min_std_data ); - - } else if (ecl_type == ECL_DOUBLE_TYPE) { - double * inflation_data = (double *) inflation->data; - const double * std_data = (const double *) std->data; - const double * min_std_data = (const double *) min_std->data; - - INFLATE(inflation_data , std_data , min_std_data ); - } -} -#undef INFLATE - - - -/******************************************************************/ -/* Anonumously generated functions used by the enkf_node object */ -/******************************************************************/ - -/* - These two functions assume float/double storage; will not work with - field which is internally based on char *. - - MATH_OPS(field) -*/ -UTIL_SAFE_CAST_FUNCTION(field , FIELD) -UTIL_SAFE_CAST_FUNCTION_CONST(field , FIELD) -UTIL_IS_INSTANCE_FUNCTION(field , FIELD) -VOID_ALLOC(field) -VOID_FREE(field) -VOID_ECL_WRITE (field) -VOID_FORWARD_LOAD(field) -VOID_COPY (field) -VOID_INITIALIZE(field); -VOID_USER_GET(field) -VOID_READ_FROM_BUFFER(field) -VOID_WRITE_TO_BUFFER(field) -VOID_CLEAR(field) -VOID_SERIALIZE(field) -VOID_DESERIALIZE(field) -VOID_SET_INFLATION(field) -VOID_IADD(field) -VOID_SCALE(field) -VOID_IADDSQR(field) -VOID_IMUL(field) -VOID_ISQRT(field) -VOID_FLOAD(field) diff --git a/ThirdParty/Ert/libenkf/src/field_config.c b/ThirdParty/Ert/libenkf/src/field_config.c deleted file mode 100644 index 6f14da7dc5..0000000000 --- a/ThirdParty/Ert/libenkf/src/field_config.c +++ /dev/null @@ -1,1048 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'field_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/** - About transformations and truncations - ------------------------------------- - - The values of the fields data can be automagically manipulated through two methods: - - * You can specify a min and a max value which will serve as truncation. - - * You can specify transformation functions which are applied to the field as follows: - - init_transform: This function is applied to the field when the - field is loaded the first time, i.e. initialized. It is *NOT* - applied under subsequent loads of dynamic fields during the - execution. - - output_transform: This function is applied to the field before it - is exported to eclipse. - - input_transform: This function is applied each time a field is - loaded in from the forward model; i.e. this transformation - applies to dynamic fields. - - - - _______________________________ ___ - / \ /|\ - | Forward model (i.e. ECLIPSE) | | - | generates dynamic fields like | | - | PRESSURE and SATURATIONS | | - \_______________________________/ | This code is run - | | every time a field - | | is loaded FROM the - \|/ | forward model into - | | EnKF. - ________|_________ | - / \ | - | Input transform | | - \__________________/ | - | | - | | - \|/ | - | | - ________________|__________________ _\|/_ -_______________ ___________ / \ - \ / \ | The internal representation | - Geo Modelling | | init- | | of the field. This (should) | - creates a |==>===============>==| transform |===>===| be a normally distributed | - realization | | | | variable suitable for updates | -_______________/ \___________/ | with EnKF. | - \___________________________________/ ___ -|<---- This path is ONLY executed during INIT ------->| | /|\ - Observe that there is no truncation \|/ | - on load. _________|__________ | - / \ | This code is run - | Output transform | | every time a field - \____________________/ | is exported from - | | enkf to the forward - \|/ | model - i.e. ECLIPSE. - _________|__________ | - / \ | - | Truncate min/max | | - \____________________/ | - | | - \|/ | - _________|__________ | - / \ | - | FORWARD MODEL | | - \____________________/ _\|/_ - - - - - - -*/ - -/*Observe the following convention: - - global_index: [0 , nx*ny*nz) - active_index: [0 , nactive) -*/ - -#define FIELD_CONFIG_ID 78269 - -struct field_config_struct { - UTIL_TYPE_ID_DECLARATION; - - char * ecl_kw_name; /* Name/key ... */ - int data_size , nx,ny,nz; /* The number of elements in the three directions. */ - bool keep_inactive_cells; /* Whether the data contains only active cells or active and inactive cells */ - ecl_grid_type * grid; /* A shared reference to the grid this field is defined on. */ - bool private_grid; - - int truncation; /* How the field should be trunacted before exporting for simulation, and for the inital import. OR'd combination of truncation_type from enkf_types.h*/ - double min_value; /* The min value used in truncation. */ - double max_value; /* The maximum value used in truncation. */ - - field_file_format_type export_format; - field_file_format_type import_format; - int sizeof_ctype; - ecl_type_enum internal_ecl_type; - ecl_type_enum export_ecl_type; - bool __enkf_mode; /* See doc of functions field_config_set_key() / field_config_enkf_OFF() */ - bool write_compressed; - - field_type_enum type; - field_type * min_std; - /*****************************************************************/ - field_trans_table_type * trans_table; /* Internalize a (pointer to) a table of the available transformation functions. */ - field_func_type * output_transform; /* Function to apply to the data before they are exported - NULL: no transform. */ - field_func_type * init_transform; /* Function to apply on the data when they are loaded the first time - i.e. initialized. NULL : no transform*/ - field_func_type * input_transform; /* Function to apply on the data when they are loaded from the forward model - i.e. for dynamic data. */ - - char * output_transform_name; - char * init_transform_name; - char * input_transform_name; -}; - - -UTIL_IS_INSTANCE_FUNCTION(field_config , FIELD_CONFIG_ID) - -/*****************************************************************/ - - -void field_config_set_ecl_kw_name(field_config_type * config , const char * ecl_kw_name) { - config->ecl_kw_name = util_realloc_string_copy(config->ecl_kw_name , ecl_kw_name); -} - - - -void field_config_set_ecl_type(field_config_type * config , ecl_type_enum ecl_type) { - config->internal_ecl_type = ecl_type; - config->sizeof_ctype = ecl_util_get_sizeof_ctype(ecl_type); -} - - - -static const char * field_config_file_type_string(field_file_format_type file_type) { - switch (file_type) { - case(RMS_ROFF_FILE): - return "Binary ROFF file from RMS"; - break; - case(ECL_KW_FILE): - return "ECLIPSE file in restart format"; - break; - case(ECL_KW_FILE_ALL_CELLS): - return "ECLIPSE file in restart format (all cells)"; - break; - case(ECL_KW_FILE_ACTIVE_CELLS): - return "ECLIPSE file in restart format (active cells)"; - break; - case(ECL_GRDECL_FILE): - return "ECLIPSE file in grdecl format"; - break; - default: - fprintf(stderr,"%s: invalid file type \n",__func__); - abort(); - } -} - - - -/** - This function takes a field_file_format_type variable, and returns - a string containing a default extension for files of this type. For - ecl_kw_file it will return NULL, i.e. no default extension. - - rms_roff_file => ROFF - ecl_grdecl_file => GRDECL - ecl_kw_file_xxx => NULL - - It will return UPPERCASE or lowercase depending on the value of the - second argument. -*/ - - -const char * field_config_default_extension(field_file_format_type file_type, bool upper_case) { - if (file_type == RMS_ROFF_FILE) { - if (upper_case) - return "ROFF"; - else - return "roff"; - } else if (file_type == ECL_GRDECL_FILE) { - if (upper_case) - return "GRDECL"; - else - return "grdecl"; - } else - return NULL; -} - - - - -static bool field_config_valid_file_type(field_file_format_type file_type, bool import) { - if (import) { - if (file_type == RMS_ROFF_FILE || file_type == ECL_KW_FILE || file_type == ECL_GRDECL_FILE) - return true; - else - return false; - } else { - if (file_type == RMS_ROFF_FILE || file_type == ECL_KW_FILE_ACTIVE_CELLS || file_type == ECL_KW_FILE_ALL_CELLS || file_type == ECL_GRDECL_FILE) - return true; - else - return false; - } -} - - -field_file_format_type field_config_default_export_format(const char * filename) { - field_file_format_type export_format = FILE_FORMAT_NULL; - if (filename != NULL) { - export_format = ECL_KW_FILE_ALL_CELLS; /* Suitable for PERMX/PORO/... ; when this export format is - used IMPORT must be used in the datafile instead of - INCLUDE. This gives faster ECLIPSE startup time, but is - (unfortunately) quite unstandard. */ - - char * extension; - util_alloc_file_components(filename , NULL,NULL,&extension); - if (extension != NULL) { - util_strupr(extension); - if (strcmp(extension , "GRDECL") == 0) - export_format = ECL_GRDECL_FILE; - else if (strcmp(extension , "ROFF") == 0) - export_format = RMS_ROFF_FILE; - - free(extension); - } - - } - return export_format; -} - - - - - - -/** - This function prompts the user for a file type. - - If the parameter 'import' is true we provide the alternative - ecl_kw_file (in that case the program itself will determine - whether) the file contains all cells (i.e. PERMX) or only active - cells (i.e. pressure). - - If the parameter 'import' is false the user must specify whether we - are considering all cells, or only active cells. -*/ - -field_file_format_type field_config_manual_file_type(const char * prompt , bool import) { - int int_file_type; - printf("\n%s\n",prompt); - printf("----------------------------------------------------------------\n"); - printf(" %3d: %s.\n" , RMS_ROFF_FILE , field_config_file_type_string(RMS_ROFF_FILE)); - if (import) - printf(" %3d: %s.\n" , ECL_KW_FILE , field_config_file_type_string(ECL_KW_FILE)); - else { - printf(" %3d: %s.\n" , ECL_KW_FILE_ACTIVE_CELLS , field_config_file_type_string(ECL_KW_FILE_ACTIVE_CELLS)); - printf(" %3d: %s.\n" , ECL_KW_FILE_ALL_CELLS , field_config_file_type_string(ECL_KW_FILE_ALL_CELLS)); - } - printf(" %3d: %s.\n" , ECL_GRDECL_FILE , field_config_file_type_string(ECL_GRDECL_FILE)); - printf("----------------------------------------------------------------\n"); - do { - int_file_type = util_scanf_int("" , 2); - if (!field_config_valid_file_type(int_file_type, import)) - int_file_type = UNDEFINED_FORMAT; - } while(int_file_type == UNDEFINED_FORMAT); - return int_file_type; -} - - - - -/** -This function takes in a filename and tries to guess the type of the -file. It can determine the following three types of files: - - ecl_kw_file: This is a file containg ecl_kw instances in the form found - in eclipse restart files. - - rms_roff_file: An rms roff file - obviously. - - ecl_grdecl_file: This is a file containing a parameter of the form - found in eclipse grid declaration files, i.e. formatted, one - keyword and all elements (active and not). - - The latter test is the weakest. Observe that the function will - happily return unkown_file if none of these types are recognized, - i.e. it is *essential* to check the return value. - -*/ -field_file_format_type field_config_guess_file_type(const char * filename ) { - bool fmt_file = util_fmt_bit8(filename ); - FILE * stream = util_fopen(filename , "r"); - fortio_type * fortio = fortio_alloc_FILE_wrapper(NULL , ECL_ENDIAN_FLIP , fmt_file , false , stream); - field_file_format_type file_type; - - if (ecl_kw_is_kw_file(fortio)) - file_type = ECL_KW_FILE; - else if (rms_file_is_roff(stream)) - file_type = RMS_ROFF_FILE; - else if (ecl_kw_grdecl_fseek_next_kw(stream)) /* This is the weakest test - and should be last in a cascading if / else hierarchy. */ - file_type = ECL_GRDECL_FILE; - else - file_type = UNDEFINED_FORMAT; /* MUST Check on this return value */ - - fortio_free_FILE_wrapper( fortio ); - fclose(stream); - return file_type; -} - - - -field_type * field_config_get_min_std( const field_config_type * field_config ) { - return field_config->min_std; -} - - -field_file_format_type field_config_get_export_format(const field_config_type * field_config) { - return field_config->export_format; -} - -field_file_format_type field_config_get_import_format(const field_config_type * field_config) { - return field_config->import_format; -} - -/** - Will return the name of the init_transform function, or NULL if no - init_transform function has been registered. -*/ - - -const char * field_config_get_init_transform_name( const field_config_type * field_config ) { - return field_config->init_transform_name; -} - -const char * field_config_get_input_transform_name( const field_config_type * field_config ) { - return field_config->input_transform_name; -} - -const char * field_config_get_output_transform_name( const field_config_type * field_config ) { - return field_config->output_transform_name; -} - - -/** - IFF the @private_grid parameter is true, the field_config instance - will take ownership of grid, i.e. freeing it in - field_config_free(). - - The field_config object exports a field_config_set_grid() function, - but that is actually quite misleading. If this function is called - during a run there are many other dependencies which must also be - updated, which are not handled. -*/ - - -void field_config_set_grid(field_config_type * config, ecl_grid_type * grid , bool private_grid) { - if ((config->private_grid) && (config->grid != NULL)) - ecl_grid_free( config->grid ); - - config->grid = grid; - config->private_grid = private_grid; - - ecl_grid_get_dims(grid , &config->nx , &config->ny , &config->nz , NULL); - config->data_size = field_config_get_data_size_from_grid(config); -} - - - - -const char * field_config_get_grid_name( const field_config_type * config) { - return ecl_grid_get_name( config->grid ); -} - - - -/* - The return value from this function is hardly usable. -*/ -field_config_type * field_config_alloc_empty( const char * ecl_kw_name , ecl_grid_type * ecl_grid , field_trans_table_type * trans_table, bool keep_inactive_cells ) { - - field_config_type * config = util_malloc(sizeof *config); - UTIL_TYPE_ID_INIT( config , FIELD_CONFIG_ID); - - config->keep_inactive_cells = keep_inactive_cells; - config->ecl_kw_name = util_alloc_string_copy( ecl_kw_name ); - config->private_grid = false; - config->__enkf_mode = true; - config->grid = NULL; - config->write_compressed = true; - config->type = UNKNOWN_FIELD_TYPE; - - config->output_transform = NULL; - config->input_transform = NULL; - config->init_transform = NULL; - config->output_transform_name = NULL; - config->input_transform_name = NULL; - config->init_transform_name = NULL; - - config->truncation = TRUNCATE_NONE; - config->min_std = NULL; - config->trans_table = trans_table; - - field_config_set_grid(config , ecl_grid , false); /* The grid is (currently) set on allocation and can NOT be updated afterwards. */ - field_config_set_ecl_type( config , ECL_FLOAT_TYPE ); /* This is the internal type - currently not exported any API to change it. */ - return config; -} - - - - -static void field_config_set_init_transform( field_config_type * config , const char * __init_transform_name ) { - const char * init_transform_name = NULL; - if (field_trans_table_has_key( config->trans_table , __init_transform_name)) - init_transform_name = __init_transform_name; - else if (__init_transform_name != NULL) { - fprintf(stderr , "Sorry: the field transformation function:%s is not recognized \n\n",__init_transform_name); - field_trans_table_fprintf(config->trans_table , stderr); - util_exit("Exiting ... \n"); - } - - config->init_transform_name = util_realloc_string_copy( config->init_transform_name , init_transform_name ); - if (init_transform_name != NULL) - config->init_transform = field_trans_table_lookup( config->trans_table , init_transform_name); - else - config->init_transform = NULL; -} - - -static void field_config_set_output_transform( field_config_type * config , const char * __output_transform_name ) { - const char * output_transform_name = NULL; - if (field_trans_table_has_key( config->trans_table , __output_transform_name)) - output_transform_name = __output_transform_name; - else if (__output_transform_name) { - fprintf(stderr , "Sorry: the field transformation function:%s is not recognized \n\n",__output_transform_name); - field_trans_table_fprintf(config->trans_table , stderr); - util_exit("Exiting ... \n"); - } - - config->output_transform_name = util_realloc_string_copy( config->output_transform_name , output_transform_name ); - if (output_transform_name != NULL) - config->output_transform = field_trans_table_lookup( config->trans_table , output_transform_name); - else - config->output_transform = NULL; -} - - -static void field_config_set_input_transform( field_config_type * config , const char * __input_transform_name ) { - const char * input_transform_name = NULL; - if (field_trans_table_has_key( config->trans_table , __input_transform_name)) - input_transform_name = __input_transform_name; - else if (__input_transform_name != NULL) { - fprintf(stderr , "Sorry: the field transformation function:%s is not recognized \n\n",__input_transform_name); - field_trans_table_fprintf(config->trans_table , stderr); - util_exit("Exiting ... \n"); - } - - - config->input_transform_name = util_realloc_string_copy( config->input_transform_name , input_transform_name ); - if (input_transform_name != NULL) - config->input_transform = field_trans_table_lookup( config->trans_table , input_transform_name); - else - config->input_transform = NULL; -} - - - -void field_config_update_state_field( field_config_type * config, int truncation, double min_value , double max_value) { - field_config_set_truncation( config ,truncation , min_value , max_value ); - config->type = ECLIPSE_RESTART; - - /* Setting all the defaults for state_fields, i.e. PRESSURE / SGAS / SWAT ... */ - config->import_format = ECL_FILE; - config->export_format = ECL_FILE; - - field_config_set_output_transform( config , NULL ); - field_config_set_input_transform( config , NULL ); - field_config_set_init_transform( config , NULL ); -} - - - - -void field_config_update_parameter_field( field_config_type * config , int truncation, double min_value , double max_value, - field_file_format_type export_format , /* This can be guessed with the field_config_default_export_format( ecl_file ) function. */ - const char * init_transform , const char * output_transform ) { - field_config_set_truncation( config , truncation , min_value , max_value ); - config->type = ECLIPSE_PARAMETER; - - config->export_format = export_format; - config->import_format = UNDEFINED_FORMAT; /* Guess from filename when loading. */ - - config->input_transform = NULL; - - field_config_set_input_transform( config , NULL ); - field_config_set_init_transform( config , init_transform ); - field_config_set_output_transform( config , output_transform ); -} - - -void field_config_update_general_field( field_config_type * config , int truncation, double min_value , double max_value, - field_file_format_type export_format , /* This can be guessed with the field_config_default_export_format( ecl_file ) function. */ - const char * init_transform , - const char * input_transform , - const char * output_transform ) { - field_config_set_truncation( config , truncation , min_value , max_value ); - config->type = GENERAL; - - config->export_format = export_format; - config->import_format = UNDEFINED_FORMAT; /* Guess from filename when loading. */ - - field_config_set_input_transform( config , input_transform ); - field_config_set_init_transform( config , init_transform ); - field_config_set_output_transform( config , output_transform ); -} - - -/** - Requirements: - - ECLIPSE_PARAMETER: export_format != UNDEFINED_FORMAT - - ECLIPSE_RESTART : Validation can be finalized at the enkf_config_node level. - - GENERAL : export_format != UNDEFINED_FORMAT -*/ - -bool field_config_is_valid( const field_config_type * field_config ) { - bool valid = true; - - switch( field_config->type ) { - case ECLIPSE_PARAMETER: - if (field_config->export_format == UNDEFINED_FORMAT) - valid = false; - break; - case ECLIPSE_RESTART: - break; - case GENERAL: - if (field_config->export_format == UNDEFINED_FORMAT) - valid = false; - break; - default: - util_abort("%s: internal fuckup \n",__func__); - } - return valid; - -} - - -field_type_enum field_config_get_type( const field_config_type * config) { - return config->type; -} - - -/* - Observe that the indices are zero-based, in contrast to those used - by eclipse which are based on one. - - This function will return an index in the interval: [0...nactive), - and -1 if i,j,k correspond to an inactive cell. -*/ - - -inline int field_config_active_index(const field_config_type * config , int i , int j , int k) { - return ecl_grid_get_active_index3( config->grid , i,j,k); -} - -inline int field_config_global_index(const field_config_type * config, int i, int j, int k) { - return ecl_grid_get_global_index3( config->grid , i,j,k); -} - - -/** - This function checks that i,j,k are in the intervals [0..nx), - [0..ny) and [0..nz). It does *NOT* check if the corresponding - index is active. -*/ - -bool field_config_ijk_valid(const field_config_type * config , int i , int j , int k) { - return ecl_grid_ijk_valid(config->grid , i,j,k); -} - - -/** - This function checks that i,j,k are in the intervals [0..nx), - [0..ny) and [0..nz) AND that the corresponding cell is active. If - the function returns false it is impossible to differentiate - between (i,j,k) values which are out of bounds and an inactive - cell. -*/ - -bool field_config_ijk_active(const field_config_type * config , int i , int j , int k) { - if (ecl_grid_ijk_valid(config->grid , i,j,k)) { - int active_index = ecl_grid_get_active_index3( config->grid , i , j , k); - - if (active_index >= 0) - return true; - else - return false; - } else - return false; -} - - - - -void field_config_get_ijk( const field_config_type * config , int active_index , int *i , int * j , int * k) { - ecl_grid_get_ijk1A( config->grid , active_index , i,j,k); -} - - -bool field_config_write_compressed(const field_config_type * config) { return config->write_compressed; } - - - -void field_config_set_truncation(field_config_type * config , int truncation, double min_value, double max_value) { - config->truncation = truncation; - config->min_value = min_value; - config->max_value = max_value; -} - - - - -int field_config_get_truncation_mode(const field_config_type * config ) { - return config->truncation; -} - -double field_config_get_truncation_min( const field_config_type * config ) { - return config->min_value; -} - -double field_config_get_truncation_max( const field_config_type * config ) { - return config->max_value; -} - - - -void field_config_free(field_config_type * config) { - util_safe_free(config->ecl_kw_name); - util_safe_free(config->input_transform_name); - util_safe_free(config->output_transform_name); - util_safe_free(config->init_transform_name); - if ((config->private_grid) && (config->grid != NULL)) ecl_grid_free( config->grid ); - free(config); -} - - - -int field_config_get_volume(const field_config_type * config) { - return config->nx * config->ny * config->nz; -} - - - -rms_type_enum field_config_get_rms_type(const field_config_type * config) { - return rms_util_convert_ecl_type(config->internal_ecl_type); -} - - - -ecl_type_enum field_config_get_ecl_type(const field_config_type * config) { - return config->internal_ecl_type; -} - - - -int field_config_get_data_size_from_grid(const field_config_type * config) { - return config->keep_inactive_cells ? ecl_grid_get_global_size(config->grid) : ecl_grid_get_active_size(config->grid); -} - -int field_config_get_byte_size(const field_config_type * config) { - int num_cells = field_config_get_data_size_from_grid(config); - return num_cells * config->sizeof_ctype; -} - - -int field_config_get_sizeof_ctype(const field_config_type * config) { return config->sizeof_ctype; } - - - -/** - Returns true / false whether a cell is active. -*/ -bool field_config_active_cell(const field_config_type * config , int i , int j , int k) { - int active_index = field_config_active_index(config , i,j,k); - if (active_index >= 0) - return true; - else - return false; -} - - - - void field_config_get_dims(const field_config_type * config , int *nx , int *ny , int *nz) { - *nx = config->nx; - *ny = config->ny; - *nz = config->nz; -} - - -int field_config_get_nx(const field_config_type * config ) { - return config->nx; -} - -int field_config_get_ny(const field_config_type * config ) { - return config->ny; -} - -int field_config_get_nz(const field_config_type * config ) { - return config->nz; -} - - - - - -/** - This function reads a string with i,j,k from the user. All - characters in the constant sep_set are allowed to separate the - integers. The function will loop until: - - * Three integers have been succesfully parsed. - * All numbers are in the (1-nx,1-ny,1-nz) intervals. - * IFF active_only - only active cells wll be allowed. - - i,j,k and global_index are returned by reference. All pointers can - be NULL, if you are not interested. An invald global_index is - returned as -1 (if active_only == false). - - Observe that the user is expected to enter numbers in the interval - [1..nx],[1..ny],[1..nz], but internaly they are immediately - converted to zero offset. -*/ - - -void field_config_scanf_ijk(const field_config_type * config , bool active_only , const char * _prompt , int prompt_len , int *_i , int *_j , int *_k , int * _global_index) { - const char * sep_set = " ,.:"; - char * prompt = util_alloc_sprintf("%s (%d,%d,%d)" , _prompt , config->nx , config->ny , config->nz); - bool OK; - int i,j,k,global_index; - global_index = -1; /* Keep the compiler happy. */ - - do { - char *input; - const char *current_ptr; - util_printf_prompt(prompt , prompt_len , '=' , "=> "); - input = util_alloc_stdin_line(); - - - i = -1; - j = -1; - k = -1; - - OK = true; - current_ptr = input; - current_ptr = util_parse_int(current_ptr , &i , &OK); - current_ptr = util_skip_sep(current_ptr , sep_set , &OK); - current_ptr = util_parse_int(current_ptr , &j , &OK); - current_ptr = util_skip_sep(current_ptr , sep_set , &OK); - current_ptr = util_parse_int(current_ptr , &k , &OK); - if (OK) - if (current_ptr[0] != '\0') OK = false; /* There was something more at the end */ - - /* Now we have three valid integers. */ - - if (OK) { - if (i <= 0 || i > config->nx) OK = false; - if (j <= 0 || j > config->ny) OK = false; - if (k <= 0 || k > config->nz) OK = false; - i--; j--; k--; - } - /* Now we have three integers in the right interval. */ - - - if (OK) { - global_index = field_config_active_index(config , i,j,k); - if (active_only) { - if (global_index < 0) { - OK = false; - printf("Sorry the point: (%d,%d,%d) corresponds to an inactive cell\n" , i + 1 , j+ 1 , k + 1); - } - } - } - free(input); - } while (!OK); - - if (_i != NULL) *_i = i; - if (_j != NULL) *_j = j; - if (_k != NULL) *_k = k; - if (_global_index != NULL) *_global_index = global_index; - - free(prompt); -} - - - - -/** - The field_config and field objects are mainly written for use in - the enkf application. In that setting a field instance is *NOT* - allowed to write on it's field_config object. - - However, when used in a stand-alone application, i.e. in the - field_convert program, it is desirable for the field object to be - allowed to write to / update the field_config object. In an attempt - to make this reasonably safe you must first call - field_config_enkf_OFF() to signal that you know what you are doing. - - After you have called field_config_enkf_OFF() you can subsequently - call field_config_set_key() to change the key of the field_config - object. This will typically be interesting when an unknown file is - loaded. - - Currently only the roff loader supports set operations on the - key. Also it is essential to observe that this will break **HARD** - is the file contains several parameters - so maybe this whole thing - is stupid? -*/ - - -void field_config_set_key(field_config_type * config , const char *key) { - if (config->__enkf_mode) - util_abort("%s: internal error - must call field_config_enkf_OFF() prior to calling: %s()\n",__func__ , __func__); - /* - Should be locked to protect against concurrent access. - */ - config->ecl_kw_name = util_realloc_string_copy(config->ecl_kw_name , key); -} - -const char * field_config_get_key(const field_config_type * field_config) { - return field_config->ecl_kw_name; -} - -bool field_config_keep_inactive_cells(const field_config_type * config) { - return config->keep_inactive_cells; -} - -void field_config_enkf_OFF(field_config_type * config) { - if (config->__enkf_mode) - fprintf(stderr , "** Warning: turning off EnKF mode for field:%s - you better know what you are doing! **\n",config->ecl_kw_name); - config->__enkf_mode = false; -} - - -bool field_config_enkf_mode(const field_config_type * config) { return config->__enkf_mode; } - - -field_func_type * field_config_get_output_transform(const field_config_type * config) { - return config->output_transform; -} - -field_func_type * field_config_get_input_transform(const field_config_type * config) { - return config->input_transform; -} - -field_func_type * field_config_get_init_transform(const field_config_type * config) { - return config->init_transform; -} - - -/* - This function asserts that a unary function can be applied - to the field - i.e. that the underlying data_type is ecl_float or ecl_double. -*/ -void field_config_assert_unary( const field_config_type * field_config , const char * caller) { - const ecl_type_enum ecl_type = field_config_get_ecl_type(field_config); - if (ecl_type == ECL_FLOAT_TYPE || ecl_type == ECL_DOUBLE_TYPE) - return; - else - util_abort("%s: error in:%s unary functions can only be applied on fields of type ecl_float / ecl_double \n",__func__ , caller); -} - - -/* - Asserts that two fields can be combined in a binary operation. -*/ -void field_config_assert_binary( const field_config_type * config1 , const field_config_type * config2 , const char * caller) { - field_config_assert_unary(config1 , caller); - const ecl_type_enum ecl_type1 = config1->internal_ecl_type; - const ecl_type_enum ecl_type2 = config2->internal_ecl_type; - const int size1 = config1->data_size; - const int size2 = config2->data_size; - - if ((ecl_type1 == ecl_type2) && (size1 == size2)) - return; - else - util_abort("%s: fields not equal enough - failure in:%s \n",__func__ , caller); -} - - - - - - -/** - Parses a string of the type "1,5,6", and returns the indices i,j,k - by reference. The return value of the function as a whole is - whether the string constitutes a valid cell: - - 0: All is OK. - 1: The string could not pe parsed to three valid integers. - 2: ijk are not in the grid. - 3: ijk correspond to an inactive cell. - - In cases 2 & 3 the i,j,k are valid (in the string-parsing sense). - The input string is assumed to have offset one, and the return - values (by reference) are offset zero. -*/ - - -bool field_config_parse_user_key__( const char * index_key , int *i , int *j , int *k) { - int length; - { - int_vector_type * indices = string_util_alloc_value_list( index_key ); - length = int_vector_size( indices ); - - if (length == 3) { - *i = int_vector_iget( indices , 0) - 1; - *j = int_vector_iget( indices , 1) - 1; - *k = int_vector_iget( indices , 2) - 1; - } - - int_vector_free( indices ); - } - if (length == 3) - return true; - else - return false; -} - - - -int field_config_parse_user_key(const field_config_type * config, const char * index_key , int *i , int *j , int *k) { - int return_value = 0; - - if (field_config_parse_user_key__( index_key , i , j , k)) { - if(field_config_ijk_valid(config, *i, *j, *k)) { - int active_index = field_config_active_index(config , *i,*j,*k); - if (active_index < 0) - return_value = 3; /* ijk corresponds to an inactive cell. */ - } else - return_value = 2; /* ijk is outside the grid. */ - } else - return_value = 1; /* Could not be parsed to three integers. */ - - return return_value; -} - - - -ecl_grid_type * field_config_get_grid(const field_config_type * config) { return config->grid; } - - -void field_config_fprintf_config( const field_config_type * config , - enkf_var_type var_type , - const char * outfile , - const char * infile , - const char * min_std_file , - FILE * stream) { - - if (var_type == PARAMETER) { - fprintf( stream , CONFIG_VALUE_FORMAT , PARAMETER_KEY ); - fprintf( stream , CONFIG_VALUE_FORMAT , outfile ); - } else { - if (true) - /* This is an ECLIPSE dynamic field. */ - fprintf( stream , CONFIG_VALUE_FORMAT , DYNAMIC_KEY ); - else { - /* Dynamic fields which are not ECLIPSE solution fields - not really very well supported. */ - fprintf( stream , CONFIG_VALUE_FORMAT , GENERAL_KEY ); - fprintf( stream , CONFIG_VALUE_FORMAT , outfile ); - fprintf( stream , CONFIG_VALUE_FORMAT , infile ); - } - } - - if (config->init_transform != NULL) - fprintf( stream , CONFIG_OPTION_FORMAT , INIT_TRANSFORM_KEY , config->init_transform_name ); - - if (config->output_transform != NULL) - fprintf( stream , CONFIG_OPTION_FORMAT , OUTPUT_TRANSFORM_KEY , config->output_transform_name ); - - if (config->input_transform != NULL) - fprintf( stream , CONFIG_OPTION_FORMAT , INPUT_TRANSFORM_KEY , config->input_transform_name ); - - if (min_std_file != NULL) - fprintf( stream , CONFIG_OPTION_FORMAT , MIN_STD_KEY , min_std_file ); - - if (config->truncation & TRUNCATE_MIN) - fprintf( stream , CONFIG_FLOAT_OPTION_FORMAT , MIN_KEY , config->min_value ); - - if (config->truncation & TRUNCATE_MAX) - fprintf( stream , CONFIG_FLOAT_OPTION_FORMAT , MAX_KEY , config->max_value ); -} - - -/*****************************************************************/ -UTIL_SAFE_CAST_FUNCTION(field_config , FIELD_CONFIG_ID) -UTIL_SAFE_CAST_FUNCTION_CONST(field_config , FIELD_CONFIG_ID) -CONFIG_GET_ECL_KW_NAME(field); -GET_DATA_SIZE(field) -VOID_GET_DATA_SIZE(field) -VOID_FREE(field_config) - - diff --git a/ThirdParty/Ert/libenkf/src/field_convert.c b/ThirdParty/Ert/libenkf/src/field_convert.c deleted file mode 100644 index 6530ea9008..0000000000 --- a/ThirdParty/Ert/libenkf/src/field_convert.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'field_convert.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - - -void usage(const char * cmd) { - printf("%s: GRID_FILE OUTPATH field1 field2 field3 ....\n",cmd); - exit(1); -} - - -int main(int argc , char ** argv) { - if (argc < 4) usage(argv[0]); - { - const char * grid_file = argv[1]; - const char * out_path = argv[2]; - const char ** file_list = (const char **) &argv[3]; - int num_files = argc - 3; - int ifile; - field_file_format_type file_type; - - ecl_grid_type * ecl_grid = ecl_grid_alloc(grid_file , true); - field_config_type *field_config = field_config_alloc_dynamic("XX" , NULL , NULL , ecl_grid); - field_type * field = field_alloc(field_config); - field_config_enkf_OFF(field_config); - - util_make_path(out_path); - file_type = field_config_manual_file_type("Export files to type: " , false); - printf("num_files:%d \n",num_files); - for (ifile = 0; ifile < num_files; ifile++) { - char * base_name; - char * target_file; - util_alloc_file_components(file_list[ifile] , NULL , &base_name , NULL); - target_file = util_alloc_filename(out_path , base_name , field_config_default_extension(file_type , true)); - field_fload(field , file_list[ifile] , true); - printf("Converting: %s -> %s \n",file_list[ifile] , target_file); - field_export(field , target_file , file_type); - free(target_file); - free(base_name); - } - - - field_free(field); - field_config_free(field_config); - ecl_grid_free(ecl_grid); - } - - -} diff --git a/ThirdParty/Ert/libenkf/src/field_test.c b/ThirdParty/Ert/libenkf/src/field_test.c deleted file mode 100644 index 93fca096c8..0000000000 --- a/ThirdParty/Ert/libenkf/src/field_test.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'field_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - - -int main (int argc , char **argv) { - const char * config_file = "../../librms/src/Testing/PERMX_%d"; - const char *EGRID_file = "../../librms/src/Testing/GRANE.EGRID"; - int nx , ny , nz , active_size; - - field_config_type * field_config; - field_type * field1 , *field2; - - ecl_grid_type * ecl_grid = ecl_grid_alloc(EGRID_file , true); - ecl_grid_get_dims(ecl_grid , &nx , &ny , &nz , &active_size); - - - field_config = field_config_alloc_parameter("PERMX" , nx , ny , nz , active_size , ecl_grid_get_index_map_ref(ecl_grid) , 0 , load_unique , 1 , (const char **) &config_file); - field1 = field_alloc(field_config); - field2 = field_alloc(field_config); - - field_fload(field1 , "../../librms/src/Testing/PERMX_1" , true); - field_ROFF_export(field1 , "Testing/PERMX_1"); - - field_fload(field2 , "Testing/PERMX_1" , true); - field_ROFF_export(field2 , "Testing/PERMX_2"); - - if (field_cmp(field1 , field2)) - printf("EQUAL\n"); - else - printf("DIFFERENT\n"); - - - field_config_free(field_config); - ecl_grid_free(ecl_grid); -} diff --git a/ThirdParty/Ert/libenkf/src/field_trans.c b/ThirdParty/Ert/libenkf/src/field_trans.c deleted file mode 100644 index 0ce78f84ec..0000000000 --- a/ThirdParty/Ert/libenkf/src/field_trans.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'field_trans.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/* - This file implements a number of functions used for init and output - transformations of fields. The prototype for these functions is very - simple: "one float in - one float out". - - It is mainly implemented in this file, so that it will be easy to - adde new transformation functions without diving into the the full - field / field_config complexity. - - Documentation on how to add a new transformation function is at the - bottom of the file. -*/ -#include -#include -#include - -#include -#include - -#include -/*****************************************************************/ - -struct field_trans_table_struct { - bool case_sensitive; - hash_type * function_table; -}; - - - -typedef struct { - char * key; - char * description; - field_func_type * func; -} field_func_node_type; - -/*****************************************************************/ - -static field_func_node_type * field_func_node_alloc(const char * key , const char * description , field_func_type * func) { - field_func_node_type * node = util_malloc( sizeof * node ); - - node->key = util_alloc_string_copy( key ); - node->description = util_alloc_string_copy( description ); - node->func = func; - - return node; -} - - -static void field_func_node_free(field_func_node_type * node) { - free(node->key); - util_safe_free( node->description ); - free(node); -} - - -static void field_func_node_free__(void * node) { - field_func_node_free( (field_func_node_type *) node); -} - - -static void field_func_node_fprintf(const field_func_node_type * node , FILE * stream) { - if (node->description != NULL) - fprintf(stream , "%16s: %s \n",node->key , node->description); - else - fprintf(stream , "%16s: No description \n",node->key ); -} - - - - - - -/*****************************************************************/ - -void field_trans_table_add(field_trans_table_type * table , const char * _key , const char * description , field_func_type * func) { - char * key; - - if (table->case_sensitive) - key = util_alloc_string_copy( _key ); - else - key = util_alloc_strupr_copy( _key ); - - { - field_func_node_type * node = field_func_node_alloc( key , description , func ); - hash_insert_hash_owned_ref(table->function_table , key , node , field_func_node_free__); - } - free(key); -} - - -void field_trans_table_fprintf(const field_trans_table_type * table , FILE * stream) { - hash_iter_type * iter = hash_iter_alloc(table->function_table); - const char * key = hash_iter_get_next_key(iter); - fprintf(stream,"==========================================================================================\n"); - fprintf(stream,"Available transformations: \n"); - while (key != NULL) { - field_func_node_type * func_node = hash_get(table->function_table , key); - field_func_node_fprintf(func_node , stream); - key = hash_iter_get_next_key(iter); - } - fprintf(stream,"==========================================================================================\n"); - hash_iter_free(iter); -} - - - -/* - This function takes a key input, and returns a pointer to the - corresponding function. The function will fail if the key is not - recognized. -*/ - - -field_func_type * field_trans_table_lookup(field_trans_table_type * table , const char * _key) { - field_func_type * func; - char * key; - - if (table->case_sensitive) - key = util_alloc_string_copy(_key); - else - key = util_alloc_strupr_copy(_key); - - if (hash_has_key(table->function_table , key)) { - field_func_node_type * func_node = hash_get(table->function_table , key); - func = func_node->func; - } else { - fprintf(stderr , "Sorry: the field transformation function:%s is not recognized \n\n",key); - field_trans_table_fprintf(table , stderr); - util_exit("Exiting ... \n"); - func = NULL; /* Compiler shut up. */ - } - free( key ); - return func; -} - - -/** - Will return false if _key == NULL -*/ -bool field_trans_table_has_key(field_trans_table_type * table , const char * _key) { - bool has_key = false; - - if (_key != NULL) { - char * key; - if (table->case_sensitive) - key = util_alloc_string_copy(_key); - else - key = util_alloc_strupr_copy(_key); - - has_key = hash_has_key( table->function_table , key); - free(key); - } - - return has_key; -} - - -void field_trans_table_free(field_trans_table_type * table ) { - hash_free( table->function_table ); - free( table ); -} - - - - -/*****************************************************************/ -/*****************************************************************/ -/* Here comes the actual functions. To add a new function: */ -/* */ -/* 1. Write the function - as a float in - float out. */ -/* 2. Register the function in field_trans_table_alloc(). */ -/* */ -/*****************************************************************/ - -/*****************************************************************/ -/* Rubakumar specials: start */ -#define PERMX_MEAN 100 -#define PERMX_STD 1 - -#define PERMZ_MEAN 100 -#define PERMZ_STD 1 - -#define PORO_MEAN 100 -#define PORO_STD 1 - - -static float normalize(float x , float mean , float std) { - return (x - mean) / std; -} - -static float denormalize(float x , float mean , float std) { - return (x * std) + mean; -} - -static float normalize_permx(float x) { - return normalize(x , PERMX_MEAN , PERMX_STD); -} - -static float denormalize_permx(float x) { - return denormalize(x , PERMX_MEAN , PERMX_STD); -} - -static float normalize_permz(float x) { - return normalize(x , PERMZ_MEAN , PERMZ_STD); -} - -static float denormalize_permz(float x) { - return denormalize(x , PERMZ_MEAN , PERMZ_STD); -} - -static float normalize_poro(float x) { - return normalize(x , PORO_MEAN , PORO_STD); -} - -static float denormalize_poro(float x) { - return denormalize(x , PORO_MEAN , PORO_STD); -} - -/* Rubakumar specials: end */ -/*****************************************************************/ - - -static float field_trans_pow10(float x) { - return powf(10.0 , x); -} - - -static float trunc_pow10f(float x) { - return util_float_max(powf(10.0 , x) , 0.001); -} - -#define LN_SHIFT 0.0000001 -static float field_trans_ln0( float x ) { - return logf( x + LN_SHIFT ); -} - -static float field_trans_exp0( float x ) { - return expf( x ) - LN_SHIFT; -} -#undef LN_SHIFT - - - -field_trans_table_type * field_trans_table_alloc() { - field_trans_table_type * table = util_malloc( sizeof * table); - table->function_table = hash_alloc(); - field_trans_table_add( table , "POW10" , "This function will raise x to the power of 10: y = 10^x." , field_trans_pow10); - field_trans_table_add( table , "TRUNC_POW10" , "This function will raise x to the power of 10 - and truncate lower values at 0.001." , trunc_pow10f); - field_trans_table_add( table , "LOG" , "This function will take the NATURAL logarithm of x: y = ln(x)" , logf); - field_trans_table_add( table , "LN" , "This function will take the NATURAL logarithm of x: y = ln(x)" , logf); - field_trans_table_add( table , "LOG10" , "This function will take the log10 logarithm of x: y = log10(x)" , log10f); - field_trans_table_add( table , "EXP" , "This function will calculate y = exp(x) " , expf); - field_trans_table_add( table , "LN0" , "This function will calculate y = ln(x + 0.000001)" , field_trans_ln0); - field_trans_table_add( table , "EXP0" , "This function will calculate y = exp(x) - 0.000001" , field_trans_exp0); - - //----------------------------------------------------------------- - // Rubakumar specials: - field_trans_table_add( table , "NORMALIZE_PERMX" , "..." , normalize_permx); - field_trans_table_add( table , "DENORMALIZE_PERMX" , "..." , denormalize_permx); - - field_trans_table_add( table , "NORMALIZE_PERMZ" , "..." , normalize_permz); - field_trans_table_add( table , "DENORMALIZE_PERMZ" , "..." , denormalize_permz); - - field_trans_table_add( table , "NORMALIZE_PORO" , "..." , normalize_poro); - field_trans_table_add( table , "DENORMALIZE_PORO" , "..." , denormalize_poro); - //----------------------------------------------------------------- - - table->case_sensitive = false; - return table; -} - diff --git a/ThirdParty/Ert/libenkf/src/forward_load_context.c b/ThirdParty/Ert/libenkf/src/forward_load_context.c deleted file mode 100644 index 7ccf65892a..0000000000 --- a/ThirdParty/Ert/libenkf/src/forward_load_context.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'forward_load_context.c.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include -#include - - -#define FORWARD_LOAD_CONTEXT_TYPE_ID 644239127 - -struct forward_load_context_struct { - UTIL_TYPE_ID_DECLARATION; - // Everyuthing can be NULL here ... - when created from gen_data. - - ecl_sum_type * ecl_sum; - ecl_file_type * restart_file; - const run_arg_type * run_arg; - char * eclbase; - const ecl_config_type * ecl_config; // Can be NULL - - int step1; - int step2; - stringlist_type * messages; // This is managed by external scope - can be NULL - - - /* The variables below are updated during the load process. */ - int load_step; - int load_result; -}; - -UTIL_IS_INSTANCE_FUNCTION( forward_load_context , FORWARD_LOAD_CONTEXT_TYPE_ID) - - - -static void forward_load_context_load_ecl_sum(forward_load_context_type * load_context) { - ecl_sum_type * summary = NULL; - - if (ecl_config_active( load_context->ecl_config )) { - const run_arg_type * run_arg = forward_load_context_get_run_arg(load_context); - const char * run_path = run_arg_get_runpath( run_arg ); - const char * eclbase = load_context->eclbase; - - const bool fmt_file = ecl_config_get_formatted(load_context->ecl_config); - char * header_file = ecl_util_alloc_exfilename(run_path , eclbase , ECL_SUMMARY_HEADER_FILE , fmt_file , -1); - char * unified_file = ecl_util_alloc_exfilename(run_path , eclbase , ECL_UNIFIED_SUMMARY_FILE , fmt_file , -1); - stringlist_type * data_files = stringlist_alloc_new(); - - /* Should we load from a unified summary file, or from several non-unified files? */ - if (unified_file != NULL) - /* Use unified file: */ - stringlist_append_ref( data_files , unified_file); - else { - /* Use several non unified files. */ - /* Bypassing the query to model_config_load_results() */ - int report_step = run_arg_get_load_start( run_arg ); - if (report_step == 0) - report_step++; // Ignore looking for the .S0000 summary file (it does not exist). - while (true) { - char * summary_file = ecl_util_alloc_exfilename(run_arg_get_runpath( run_arg ) , eclbase , ECL_SUMMARY_FILE , fmt_file , report_step); - - if (summary_file != NULL) - stringlist_append_owned_ref( data_files , summary_file); - else - /* - We stop the loading at first 'hole' in the series of summary files; - the internalize layer must report failure if we are missing data. - */ - break; - - report_step++; - } - } - - if ((header_file != NULL) && (stringlist_get_size(data_files) > 0)) { - summary = ecl_sum_fread_alloc(header_file , data_files , SUMMARY_KEY_JOIN_STRING ); - { - time_t end_time = ecl_config_get_end_date( load_context->ecl_config ); - if (end_time > 0) { - if (ecl_sum_get_end_time( summary ) < end_time) { - /* The summary vector was shorter than expected; we interpret this as - a simulation failure and discard the current summary instance. */ - - if (forward_load_context_accept_messages(load_context)) { - int end_day,end_month,end_year; - int sum_day,sum_month,sum_year; - - util_set_date_values_utc( end_time , &end_day , &end_month , &end_year ); - util_set_date_values_utc( ecl_sum_get_end_time( summary ) , &sum_day , &sum_month , &sum_year ); - { - char * msg = util_alloc_sprintf("Summary ended at %02d/%02d/%4d - expected at least END_DATE: %02d/%02d/%4d" , - sum_day , sum_month , sum_year , - end_day , end_month , end_year ); - forward_load_context_add_message( load_context , msg ); - free( msg ); - } - } - - } - ecl_sum_free( summary ); - summary = NULL; - } - } - } - stringlist_free( data_files ); - util_safe_free( header_file ); - util_safe_free( unified_file ); - } - - if (summary) - load_context->ecl_sum = summary; - else - forward_load_context_update_result(load_context, LOAD_FAILURE); -} - - - - -forward_load_context_type * forward_load_context_alloc( const run_arg_type * run_arg , bool load_summary , const ecl_config_type * ecl_config , const char * eclbase , stringlist_type * messages) { - forward_load_context_type * load_context = util_malloc( sizeof * load_context ); - UTIL_TYPE_ID_INIT( load_context , FORWARD_LOAD_CONTEXT_TYPE_ID ); - - load_context->ecl_sum = NULL; - load_context->restart_file = NULL; - load_context->run_arg = run_arg; - load_context->load_step = -1; // Invalid - must call forward_load_context_select_step() - load_context->load_result = 0; - load_context->messages = messages; - load_context->ecl_config = ecl_config; - load_context->eclbase = util_alloc_string_copy( eclbase ); - - if (load_summary) - forward_load_context_load_ecl_sum(load_context); - - return load_context; -} - - - -bool forward_load_context_accept_messages( const forward_load_context_type * load_context ) { - if (load_context->messages) - return true; - else - return false; -} - - -/* - The messages can be NULL; in which case the message is completely ignored. -*/ - -void forward_load_context_add_message( forward_load_context_type * load_context , const char * message ) { - if (load_context->messages) - stringlist_append_copy( load_context->messages , message ); -} - - -int forward_load_context_get_result( const forward_load_context_type * load_context ) { - return load_context->load_result; -} - -void forward_load_context_update_result( forward_load_context_type * load_context , int flags) { - load_context->load_result |= flags; -} - - -void forward_load_context_free( forward_load_context_type * load_context ) { - if (load_context->restart_file) - ecl_file_close( load_context->restart_file ); - - if (load_context->ecl_sum) - ecl_sum_free( load_context->ecl_sum ); - - util_safe_free( load_context->eclbase ); - free( load_context ); -} - -bool forward_load_context_load_restart_file( forward_load_context_type * load_context, int report_step) { - if (load_context->ecl_config) { - const bool unified = ecl_config_get_unified_restart( load_context->ecl_config ); - if (unified) - util_abort("%s: sorry - unified restart files are not supported \n",__func__); - - forward_load_context_select_step(load_context, report_step); - { - const bool fmt_file = ecl_config_get_formatted( load_context->ecl_config ); - char * filename = ecl_util_alloc_exfilename( run_arg_get_runpath(load_context->run_arg) , - load_context->eclbase, - ECL_RESTART_FILE , - fmt_file , - load_context->load_step ); - - if (load_context->restart_file) - ecl_file_close( load_context->restart_file ); - load_context->restart_file = NULL; - - if (filename) { - load_context->restart_file = ecl_file_open( filename , 0 ); - free(filename); - } - - if (load_context->restart_file) - return true; - else - return false; - } - } else { - util_abort("%s: internal error - tried to load restart with load_context with ecl_config==NULL \n",__func__); - return false; - } -} - - - - -const ecl_sum_type * forward_load_context_get_ecl_sum( const forward_load_context_type * load_context) { - return load_context->ecl_sum; -} - -const ecl_file_type * forward_load_context_get_restart_file( const forward_load_context_type * load_context) { - return load_context->restart_file; -} - -const run_arg_type * forward_load_context_get_run_arg( const forward_load_context_type * load_context ) { - return load_context->run_arg; -} - -const char * forward_load_context_get_run_path( const forward_load_context_type * load_context ) { - return run_arg_get_runpath( load_context->run_arg ); -} - - -enkf_fs_type * forward_load_context_get_result_fs( const forward_load_context_type * load_context ) { - return run_arg_get_result_fs( load_context->run_arg ); -} - - -void forward_load_context_select_step( forward_load_context_type * load_context , int report_step) { - load_context->load_step = report_step; -} - -int forward_load_context_get_load_step(const forward_load_context_type * load_context) { - if (load_context->load_step < 0) - util_abort("%s: this looks like an internal error - missing call to forward_load_context_select_step() \n",__func__); - - return load_context->load_step; -} - - - - diff --git a/ThirdParty/Ert/libenkf/src/fs_driver.c b/ThirdParty/Ert/libenkf/src/fs_driver.c deleted file mode 100644 index ed1c95aefd..0000000000 --- a/ThirdParty/Ert/libenkf/src/fs_driver.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'fs_driver.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include - -/* - The underlying base types (abstract - with no accompanying - implementation); these two type ID's are not exported outside this - file. They are not stored to disk, and only used in an attempt - yo verify run-time casts. -*/ -#define FS_DRIVER_ID 10 - - -/*****************************************************************/ -/* This fs driver implemenatition is common to both dynamic and - parameter info. */ - -void fs_driver_init(fs_driver_type * driver) { - driver->type_id = FS_DRIVER_ID; - - driver->load_node = NULL; - driver->save_node = NULL; - driver->has_node = NULL; - driver->unlink_node = NULL; - - driver->load_vector = NULL; - driver->save_vector = NULL; - driver->has_vector = NULL; - driver->unlink_vector = NULL; - - driver->free_driver = NULL; - driver->fsync_driver = NULL; -} - -void fs_driver_assert_cast(const fs_driver_type * driver) { - if (driver->type_id != FS_DRIVER_ID) - util_abort("%s: internal error - incorrect cast() - aborting \n" , __func__); -} - - -fs_driver_type * fs_driver_safe_cast(void * __driver) { - fs_driver_type * driver = (fs_driver_type *) __driver; - if (driver->type_id != FS_DRIVER_ID) - util_abort("%s: runtime cast failed. \n",__func__); - return driver; -} - -/*****************************************************************/ - - -void fs_driver_init_fstab( FILE * stream, fs_driver_impl driver_id) { - util_fwrite_long( FS_MAGIC_ID , stream ); - util_fwrite_int ( CURRENT_FS_VERSION , stream ); - util_fwrite_int ( driver_id , stream ); -} - - - -/** - Will open fstab stream and return it. The semantics with respect to - existing/not existnig fstab file depends on the value of the - @create parameter: - - @create = True: If the fstab file exists the function will return - NULL, otherwise it will return a stream opened for writing to the - fstab file. - - @create = False: If the fstab file exists the the function will - return a stream opened for reading of the fstab file, otherwise - it will return NULL. - -*/ - -char * fs_driver_alloc_fstab_file( const char * path ) { - return util_alloc_filename( path , "ert_fstab" , NULL); -} - - -FILE * fs_driver_open_fstab( const char * path , bool create) { - FILE * stream = NULL; - char * fstab_file = fs_driver_alloc_fstab_file( path ); - if (create) - util_make_path( path ); - - if (util_file_exists( fstab_file ) != create) { - if (create) - stream = util_fopen( fstab_file , "w"); - else - stream = util_fopen( fstab_file , "r"); - } - free( fstab_file ); - return stream; -} - - -void fs_driver_assert_magic( FILE * stream ) { - long fs_magic = util_fread_long( stream ); - if (fs_magic != FS_MAGIC_ID) - util_abort("%s: WTF - fstab magic marker incorrect \n",__func__); -} - - - -void fs_driver_assert_version( FILE * stream , const char * mount_point) { - int file_version = util_fread_int( stream ); - - if (file_version < MIN_SUPPORTED_FS_VERSION ) - util_exit("%s: The file system you are trying to access is created with a very old version of ert - sorry.\n",__func__); - - if (file_version > CURRENT_FS_VERSION) - util_exit("%s: The file system you are trying to access has been created with a newer version of ert - sorry.\n",__func__); - - if (file_version < CURRENT_FS_VERSION) { - if ((file_version == 105) && (CURRENT_FS_VERSION == 106)) - fprintf(stderr,"%s: The file system you are accessing has been written with an older version of ert - STATIC information ignored. \n",__func__); - else - util_exit("%s: The file system you are trying to access has been created with an old version of ert - sorry.\n",__func__); - } - - -} - - -fs_driver_impl fs_driver_fread_type( FILE * stream ) { - fs_driver_impl impl = util_fread_int( stream ); - return impl; -} - - -int fs_driver_fread_version( FILE * stream ) { - long fs_magic = util_fread_long( stream ); - if (fs_magic != FS_MAGIC_ID) - return -1; - else { - int file_version = util_fread_int( stream ); - return file_version; - } -} - - -/*****************************************************************/ - - diff --git a/ThirdParty/Ert/libenkf/src/fs_types.c b/ThirdParty/Ert/libenkf/src/fs_types.c deleted file mode 100644 index 454e726bc1..0000000000 --- a/ThirdParty/Ert/libenkf/src/fs_types.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'fs_types.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include - -#include - - - -fs_driver_impl fs_types_lookup_string_name(const char * driver_name) { - if (strcmp(driver_name , "PLAIN") == 0) - return PLAIN_DRIVER_ID; - else if (strcmp(driver_name , "BLOCK_FS") == 0) - return BLOCK_FS_DRIVER_ID; - else { - util_abort("%s: could not determine driver type for input:%s \n",__func__ , driver_name); - return INVALID_DRIVER_ID; - } -} - - - -const char * fs_types_get_driver_name(fs_driver_enum driver_type) { - switch( driver_type ) { - case(DRIVER_PARAMETER): - return "PARAMETER"; - break; - case(DRIVER_DYNAMIC_FORECAST): - return "FORECAST"; - break; - case(DRIVER_INDEX): - return "INDEX"; - break; - default: - util_abort("%s: driver_id:%d not recognized. \n",__func__ , driver_type ); - return NULL; - } -} - - -/* - The driver type DRIVER_STATIC has been removed completely as of - December 2015, but there will still be many mount map files with - this enum value around on disk. This function is a minor convenience - to handle that. - - The driver type DRIVER_DYNAMIC_ANALYZED was removed ~april 2016. -*/ - -bool fs_types_valid( fs_driver_enum driver_type) { - if ((driver_type == DRIVER_STATIC) || (driver_type == DRIVER_DYNAMIC_ANALYZED)) - return false; - else - return true; -} diff --git a/ThirdParty/Ert/libenkf/src/gen_common.c b/ThirdParty/Ert/libenkf/src/gen_common.c deleted file mode 100644 index f7a45852c7..0000000000 --- a/ThirdParty/Ert/libenkf/src/gen_common.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_common.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include - -#include -#include - -#include -#include - -/** - This file implements some (very basic) functionality which is used - by both the gen_data and gen_obs objects. -*/ - - -void * gen_common_fscanf_alloc(const char * file , ecl_type_enum load_type , int * size) { - FILE * stream = util_fopen(file , "r"); - int sizeof_ctype = ecl_util_get_sizeof_ctype(load_type); - int buffer_elements = *size; - int current_size = 0; - int fscanf_return = 1; /* To keep the compiler happy .*/ - void * buffer; - - if (buffer_elements == 0) - buffer_elements = 100; - - buffer = util_calloc( buffer_elements , sizeof_ctype ); - { - do { - if (load_type == ECL_FLOAT_TYPE) { - float * float_buffer = (float *) buffer; - fscanf_return = fscanf(stream , "%g" , &float_buffer[current_size]); - } else if (load_type == ECL_DOUBLE_TYPE) { - double * double_buffer = (double *) buffer; - fscanf_return = fscanf(stream , "%lg" , &double_buffer[current_size]); - } else if (load_type == ECL_INT_TYPE) { - int * int_buffer = (int *) buffer; - fscanf_return = fscanf(stream , "%d" , &int_buffer[current_size]); - } else - util_abort("%s: god dammit - internal error \n",__func__); - - if (fscanf_return == 1) - current_size += 1; - - if (current_size == buffer_elements) { - buffer_elements *= 2; - buffer = util_realloc( buffer , buffer_elements * sizeof_ctype ); - } - } while (fscanf_return == 1); - } - if (fscanf_return != EOF) - util_abort("%s: scanning of %s terminated before EOF was reached -- fix your file.\n" , __func__ , file); - - fclose(stream); - *size = current_size; - return buffer; -} - - - -void * gen_common_fread_alloc(const char * file , ecl_type_enum load_type , int * size) { - const int max_read_size = 100000; - FILE * stream = util_fopen(file , "r"); - int sizeof_ctype = ecl_util_get_sizeof_ctype(load_type); - int read_size = 4096; /* Shot in the wild */ - int current_size = 0; - int buffer_elements; - int fread_return; - char * buffer; - - - buffer_elements = read_size; - buffer = util_calloc( buffer_elements , sizeof_ctype ); - { - do { - fread_return = fread( &buffer[ current_size * sizeof_ctype] , sizeof_ctype , read_size , stream); - current_size += fread_return; - - if (!feof(stream)) { - /* Allocate more elements. */ - if (current_size == buffer_elements) { - read_size *= 2; - read_size = util_int_min(read_size , max_read_size); - buffer_elements += read_size; - buffer = util_realloc( buffer , buffer_elements * sizeof_ctype ); - } else - util_abort("%s: internal error ?? \n",__func__); - } - } while (!feof(stream)); - } - *size = current_size; - return buffer; -} - - -/* - If the load_format is binary_float or binary_double, the ASCII_type - is *NOT* consulted. The load_type is set to float/double depending - on what was actually used when the data was loaded. -*/ - -void * gen_common_fload_alloc(const char * file , gen_data_file_format_type load_format , ecl_type_enum ASCII_type , ecl_type_enum * load_type , int * size) { - void * buffer = NULL; - - if (load_format == ASCII) { - *load_type = ASCII_type; - buffer = gen_common_fscanf_alloc(file , ASCII_type , size); - } else if (load_format == BINARY_FLOAT) { - *load_type = ECL_FLOAT_TYPE; - buffer = gen_common_fread_alloc(file , ECL_FLOAT_TYPE , size); - } else if (load_format == BINARY_DOUBLE) { - *load_type = ECL_DOUBLE_TYPE; - buffer = gen_common_fread_alloc(file , ECL_DOUBLE_TYPE , size); - } else - util_abort("%s: trying to load with unsupported format:%s... \n" , load_format); - - return buffer; -} diff --git a/ThirdParty/Ert/libenkf/src/gen_data.c b/ThirdParty/Ert/libenkf/src/gen_data.c deleted file mode 100644 index 7e57b9aa22..0000000000 --- a/ThirdParty/Ert/libenkf/src/gen_data.c +++ /dev/null @@ -1,745 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_data.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/** - The file implements a general data type which can be used to update - arbitrary data which the EnKF system has *ABSOLUTELY NO IDEA* of - how is organised; how it should be used in the forward model and so - on. Similarly to the field objects, the gen_data objects can be - treated both as parameters and as dynamic data. - - Whether the forward_load function should be called (i.e. it is dynamic - data) is determined at the enkf_node level, and no busissiness of - the gen_data implementation. -*/ - - - - -struct gen_data_struct { - int __type_id; - gen_data_config_type * config; /* Thin config object - mainly contains filename for remote load */ - char * data; /* Actual storage - will be casted to double or float on use. */ - int current_report_step; /* Need this to look up the correct size in the config object. */ - bool_vector_type * active_mask; /* Mask of active/not active - loaded from a "_active" file created by the forward model. Not used when used as parameter*/ -}; - - - -void gen_data_assert_size( gen_data_type * gen_data , int size , int report_step) { - gen_data_config_assert_size(gen_data->config , size , report_step); - gen_data->current_report_step = report_step; -} - -gen_data_config_type * gen_data_get_config(const gen_data_type * gen_data) { return gen_data->config; } - -int gen_data_get_size( const gen_data_type * gen_data ) { - return gen_data_config_get_data_size( gen_data->config , gen_data->current_report_step ); -} - -/** - It is a bug to call this before some function has set the size. -*/ -void gen_data_realloc_data(gen_data_type * gen_data) { - int byte_size = gen_data_config_get_byte_size(gen_data->config , gen_data->current_report_step ); - gen_data->data = util_realloc(gen_data->data , byte_size ); -} - - - -gen_data_type * gen_data_alloc(const gen_data_config_type * config) { - gen_data_type * gen_data = util_malloc(sizeof * gen_data); - gen_data->config = (gen_data_config_type *) config; - gen_data->data = NULL; - gen_data->__type_id = GEN_DATA; - gen_data->active_mask = bool_vector_alloc( 0 , true ); - gen_data->current_report_step = -1; /* God - if you ever read this .... */ - return gen_data; -} - - -void gen_data_copy(const gen_data_type * src , gen_data_type * target) { - if (src->config == target->config) { - target->current_report_step = src->current_report_step; - - if (src->data != NULL) { - int byte_size = gen_data_config_get_byte_size( src->config , src->current_report_step ); - target->data = util_realloc_copy(target->data , src->data , byte_size ); - } - } else - util_abort("%s: do not share config object \n",__func__); -} - - - -void gen_data_free(gen_data_type * gen_data) { - util_safe_free(gen_data->data); - bool_vector_free( gen_data->active_mask ); - free(gen_data); -} - - - - -/** - Observe that this function writes parameter size to disk, that is - special. The reason is that the config object does not know the - size (on allocation). - - The function currently writes an empty file (with only a report - step and a size == 0) in the case where it does not have data. This - is controlled by the value of the variable write_zero_size; if this - is changed to false some semantics in the load code must be - changed. -*/ - - -bool gen_data_write_to_buffer(const gen_data_type * gen_data , buffer_type * buffer , int report_step) { - const bool write_zero_size = true; /* true:ALWAYS write a file false:only write files with size > 0. */ - { - bool write = write_zero_size; - int size = gen_data_config_get_data_size( gen_data->config , report_step ); - if (size > 0) - write = true; - - if (write) { - int byte_size = gen_data_config_get_byte_size( gen_data->config , report_step ); - buffer_fwrite_int( buffer , GEN_DATA ); - buffer_fwrite_int( buffer , size ); - buffer_fwrite_int( buffer , report_step); /* Why the heck do I need to store this ???? It was a mistake ...*/ - - buffer_fwrite_compressed( buffer , gen_data->data , byte_size); - return true; - } else - return false; /* When false is returned - the (empty) file will be removed */ - } -} - - - -void gen_data_read_from_buffer(gen_data_type * gen_data , buffer_type * buffer , enkf_fs_type * fs, int report_step) { - int size; - enkf_util_assert_buffer_type(buffer , GEN_DATA); - size = buffer_fread_int(buffer); - buffer_fskip_int( buffer ); /* Skipping report_step from the buffer - was a mistake to store it - I think ... */ - { - size_t byte_size = size * ecl_util_get_sizeof_ctype( gen_data_config_get_internal_type ( gen_data->config )); - size_t compressed_size = buffer_get_remaining_size( buffer ); - gen_data->data = util_realloc( gen_data->data , byte_size ); - buffer_fread_compressed( buffer , compressed_size , gen_data->data , byte_size ); - } - gen_data_assert_size( gen_data , size , report_step ); - - if (gen_data_config_is_dynamic(gen_data->config)) { - gen_data_config_load_active( gen_data->config , fs, report_step , false ); - } -} - - - - - - - - -void gen_data_serialize(const gen_data_type * gen_data , node_id_type node_id , const active_list_type * active_list , matrix_type * A , int row_offset , int column) { - const gen_data_config_type *config = gen_data->config; - const int data_size = gen_data_config_get_data_size( gen_data->config , gen_data->current_report_step ); - ecl_type_enum ecl_type = gen_data_config_get_internal_type( config ); - - enkf_matrix_serialize( gen_data->data , data_size , ecl_type , active_list , A , row_offset , column ); -} - - -void gen_data_deserialize(gen_data_type * gen_data , node_id_type node_id , const active_list_type * active_list , const matrix_type * A , int row_offset , int column) { - { - const gen_data_config_type *config = gen_data->config; - const int data_size = gen_data_config_get_data_size( gen_data->config , gen_data->current_report_step ); - ecl_type_enum ecl_type = gen_data_config_get_internal_type(config); - - enkf_matrix_deserialize( gen_data->data , data_size , ecl_type , active_list , A , row_offset , column); - } -} - - - - -/* - This function sets the data field of the gen_data instance after the - data has been loaded from file. -*/ - -static void gen_data_set_data__(gen_data_type * gen_data , int size, const forward_load_context_type * load_context, ecl_type_enum load_type , const void * data) { - gen_data_assert_size(gen_data , size, forward_load_context_get_load_step( load_context )); - if (gen_data_config_is_dynamic( gen_data->config )) - gen_data_config_update_active( gen_data->config , load_context , gen_data->active_mask); - - gen_data_realloc_data(gen_data); - - if (size > 0) { - ecl_type_enum internal_type = gen_data_config_get_internal_type( gen_data->config ); - int byte_size = ecl_util_get_sizeof_ctype( internal_type ) * size ; - - if (load_type == internal_type) - memcpy(gen_data->data , data , byte_size ); - else { - if (load_type == ECL_FLOAT_TYPE) - util_float_to_double((double *) gen_data->data , data , size); - else - util_double_to_float((float *) gen_data->data , data , size); - } - } -} - - - -static bool gen_data_fload_active__(gen_data_type * gen_data, const char * filename, int size) { - /* - Look for file @filename_active - if that file is found it is - interpreted as a an active|inactive mask created by the forward - model. - - The file is assumed to be an ASCII file with integers, 0 - indicates inactive elements and 1 active elements. The file - should of course be as long as @filename. - - If the file is not found the gen_data->active_mask is set to - all-true (i.e. the default true value is invoked). - */ - bool file_exists = false; - if (gen_data_config_is_dynamic( gen_data->config )) { - bool_vector_reset( gen_data->active_mask ); - bool_vector_iset( gen_data->active_mask , size - 1, true ); - { - char * active_file = util_alloc_sprintf("%s_active" , filename ); - if (util_file_exists( active_file )) { - file_exists = true; - FILE * stream = util_fopen( active_file , "r"); - int active_int; - for (int index=0; index < size; index++) { - if (fscanf( stream , "%d" , &active_int) == 1) { - if (active_int == 1) - bool_vector_iset( gen_data->active_mask , index , true); - else if (active_int == 0) - bool_vector_iset( gen_data->active_mask , index , false); - else - util_abort("%s: error when loading active mask from:%s only 0 and 1 allowed \n",__func__ , active_file); - } else - util_abort("%s: error when loading active mask from:%s - file not long enough.\n",__func__ , active_file ); - } - fclose( stream ); - } - free( active_file ); - } - } - return file_exists; -} - - -/** - This functions loads data from file. Observe that there is *NO* - header information in this file - the size is determined by seeing - how much can be successfully loaded. - - The file is loaded with the gen_common_fload_alloc() function, and - can be in formatted ASCII or binary_float / binary_double. - - When the read is complete it is checked/verified with the config - object that this file was as long as the others we have loaded for - other members; it is perfectly OK for the file to not exist. In - which case a size of zero is set, for this report step. - - Return value is whether file was found or was empty - - might have to check this in calling scope. -*/ - -bool gen_data_fload_with_report_step( gen_data_type * gen_data , const char * filename , const forward_load_context_type * load_context) { - bool file_exists = util_file_exists(filename); - void * buffer = NULL; - ecl_type_enum load_type; - - if ( file_exists ) { - ecl_type_enum internal_type = gen_data_config_get_internal_type(gen_data->config); - gen_data_file_format_type input_format = gen_data_config_get_input_format( gen_data->config ); - int size = 0; - buffer = gen_common_fload_alloc( filename , input_format , internal_type , &load_type , &size); - if (size > 0) { - gen_data_fload_active__(gen_data, filename, size); - } else { - bool_vector_reset( gen_data->active_mask ); - } - gen_data_set_data__(gen_data , size , load_context , load_type , buffer ); - util_safe_free(buffer); - } - return file_exists; -} - - - - - -bool gen_data_forward_load(gen_data_type * gen_data , const char * ecl_file , const forward_load_context_type * load_context) { - return gen_data_fload_with_report_step( gen_data , ecl_file , load_context); -} - - - -/** - This function initializes the parameter. This is based on loading a - file. The name of the file is derived from a path_fmt instance - owned by the config object. Observe that there is *NO* header - information in this file. We just read floating point numbers until - we reach EOF. - - When the read is complete it is checked/verified with the config - object that this file was as long as the files we have loaded for - other members. - - If gen_data_config_alloc_initfile() returns NULL that means that - the gen_data instance does not have any init function - that is OK. -*/ - - - -bool gen_data_initialize(gen_data_type * gen_data , int iens , const char * init_file , rng_type * rng) { - bool ret = false; - if (init_file) { - forward_load_context_type * load_context = forward_load_context_alloc( NULL , false , NULL , NULL , NULL ); - - forward_load_context_select_step(load_context, 0); - if (!gen_data_fload_with_report_step(gen_data , init_file , load_context)) - util_abort("%s: could not find file:%s \n",__func__ , init_file); - ret = true; - - forward_load_context_free( load_context ); - } - return ret; -} - - - - -static void gen_data_ecl_write_ASCII(const gen_data_type * gen_data , const char * file , gen_data_file_format_type export_format) { - FILE * stream = util_fopen(file , "w"); - char * template_buffer; - int template_data_offset, template_buffer_size , template_data_skip; - - if (export_format == ASCII_TEMPLATE) { - gen_data_config_get_template_data( gen_data->config , &template_buffer , &template_data_offset , &template_buffer_size , &template_data_skip); - util_fwrite( template_buffer , 1 , template_data_offset , stream , __func__); - } - - { - ecl_type_enum internal_type = gen_data_config_get_internal_type(gen_data->config); - const int size = gen_data_config_get_data_size( gen_data->config , gen_data->current_report_step ); - int i; - if (internal_type == ECL_FLOAT_TYPE) { - float * float_data = (float *) gen_data->data; - for (i=0; i < size; i++) - fprintf(stream , "%g\n",float_data[i]); - } else if (internal_type == ECL_DOUBLE_TYPE) { - double * double_data = (double *) gen_data->data; - for (i=0; i < size; i++) - fprintf(stream , "%lg\n",double_data[i]); - } else - util_abort("%s: internal error - wrong type \n",__func__); - } - - if (export_format == ASCII_TEMPLATE) { - int new_offset = template_data_offset + template_data_skip; - util_fwrite( &template_buffer[new_offset] , 1 , template_buffer_size - new_offset , stream , __func__); - } - fclose(stream); -} - - - -static void gen_data_ecl_write_binary(const gen_data_type * gen_data , const char * file , ecl_type_enum export_type) { - FILE * stream = util_fopen(file , "w"); - int sizeof_ctype = ecl_util_get_sizeof_ctype( export_type ); - util_fwrite( gen_data->data , sizeof_ctype , gen_data_config_get_data_size( gen_data->config , gen_data->current_report_step) , stream , __func__); - fclose(stream); -} - - -gen_data_file_format_type gen_data_guess_export_type( const gen_data_type * gen_data ) { - gen_data_file_format_type export_type = gen_data_config_get_output_format( gen_data->config ); - if (export_type == GEN_DATA_UNDEFINED) - export_type = gen_data_config_get_input_format( gen_data->config ); - - if (export_type == GEN_DATA_UNDEFINED) - util_abort("%s: both input_format and output_format are set to UNDEFINED \n",__func__); - return export_type; -} - - -void gen_data_export(const gen_data_type * gen_data , const char * full_path , gen_data_file_format_type export_type , fortio_type * fortio) { - switch (export_type) { - case(ASCII): - gen_data_ecl_write_ASCII(gen_data , full_path , export_type); - break; - case(ASCII_TEMPLATE): - gen_data_ecl_write_ASCII(gen_data , full_path , export_type); - break; - case(BINARY_DOUBLE): - gen_data_ecl_write_binary(gen_data , full_path , ECL_DOUBLE_TYPE); - break; - case(BINARY_FLOAT): - gen_data_ecl_write_binary(gen_data , full_path , ECL_FLOAT_TYPE); - break; - default: - util_abort("%s: internal error - export type is not set.\n",__func__); - } -} - -/** - It is the enkf_node layer which knows whether the node actually - has any data to export. If it is not supposed to write data to the - forward model, i.e. it is of enkf_type 'dynamic_result' that is - signaled down here with eclfile == NULL. -*/ - - -void gen_data_ecl_write(const gen_data_type * gen_data , const char * run_path , const char * eclfile , void * filestream) { - if (eclfile != NULL) { - char * full_path = util_alloc_filename( run_path , eclfile , NULL); - - gen_data_file_format_type export_type = gen_data_config_get_output_format( gen_data->config ); - gen_data_export( gen_data , full_path , export_type , filestream ); - free( full_path ); - } -} - - -static void gen_data_assert_index(const gen_data_type * gen_data, int index) { - int current_size = gen_data_config_get_data_size( gen_data->config , gen_data->current_report_step ); - if ((index < 0) || (index >= current_size )) - util_abort("%s: index:%d invalid. Valid range: [0,%d) \n",__func__ , index , current_size); -} - - -double gen_data_iget_double(const gen_data_type * gen_data, int index) { - gen_data_assert_index(gen_data , index); - { - ecl_type_enum internal_type = gen_data_config_get_internal_type(gen_data->config); - if (internal_type == ECL_DOUBLE_TYPE) { - double * data = (double *) gen_data->data; - return data[index]; - } else { - float * data = (float *) gen_data->data; - return data[index]; - } - } -} - - - -void gen_data_iset_double(gen_data_type * gen_data, int index, double value) { - gen_data_assert_index(gen_data , index); - { - ecl_type_enum internal_type = gen_data_config_get_internal_type(gen_data->config); - if (internal_type == ECL_DOUBLE_TYPE) { - double * data = (double *) gen_data->data; - data[index] = value; - } else { - float * data = (float *) gen_data->data; - data[index] = value; - } - } -} - - - -void gen_data_export_data(const gen_data_type * gen_data , double_vector_type * export_data) { - ecl_type_enum internal_type = gen_data_config_get_internal_type(gen_data->config); - if (internal_type == ECL_DOUBLE_TYPE) - double_vector_memcpy_from_data( export_data , (const double *) gen_data->data , gen_data_get_size( gen_data )); - else { - double_vector_reset( export_data ); - float * float_data = (float *) gen_data->data; - for (int i = 0; i < gen_data_get_size( gen_data ); i++) - double_vector_iset( export_data , i , float_data[i]); - } -} - - - -/** - The filesystem will (currently) store gen_data instances which do - not hold any data. Therefor it will be quite common to enter this - function with an empty instance, we therefor just set valid => - false, and return silently in that case. -*/ - -bool gen_data_user_get(const gen_data_type * gen_data, const char * index_key, int report_step , double * value) -{ - int index; - *value = 0.0; - - if (index_key != NULL) { - if (util_sscanf_int(index_key , &index)) { - if (index < gen_data_config_get_data_size( gen_data->config , gen_data->current_report_step )) { - *value = gen_data_iget_double( gen_data , index ); - return true; - } - } - } - - return false; -} - - -const char * gen_data_get_key( const gen_data_type * gen_data) { - return gen_data_config_get_key( gen_data->config ); -} - - -void gen_data_clear( gen_data_type * gen_data ) { - const gen_data_config_type * config = gen_data->config; - ecl_type_enum internal_type = gen_data_config_get_internal_type( config ); - const int data_size = gen_data_config_get_data_size( gen_data->config , gen_data->current_report_step ); - - if (internal_type == ECL_FLOAT_TYPE) { - float * data = (float * ) gen_data->data; - for (int i = 0; i < data_size; i++) - data[i] = 0; - } else if (internal_type == ECL_DOUBLE_TYPE) { - double * data = (double * ) gen_data->data; - for (int i = 0; i < data_size; i++) - data[i] = 0; - } -} - - - -void gen_data_isqrt(gen_data_type * gen_data) { - const int data_size = gen_data_config_get_data_size( gen_data->config , gen_data->current_report_step ); - const ecl_type_enum internal_type = gen_data_config_get_internal_type(gen_data->config); - - if (internal_type == ECL_FLOAT_TYPE) { - float * data = (float *) gen_data->data; - for (int i=0; i < data_size; i++) - data[i] = sqrtf( data[i] ); - } else if (internal_type == ECL_DOUBLE_TYPE) { - double * data = (double *) gen_data->data; - for (int i=0; i < data_size; i++) - data[i] = sqrt( data[i] ); - } -} - - - - -void gen_data_iadd(gen_data_type * gen_data1, const gen_data_type * gen_data2) { - //gen_data_config_assert_binary(gen_data1->config , gen_data2->config , __func__); - { - const int data_size = gen_data_config_get_data_size( gen_data1->config , gen_data1->current_report_step ); - const ecl_type_enum internal_type = gen_data_config_get_internal_type(gen_data1->config); - int i; - - if (internal_type == ECL_FLOAT_TYPE) { - float * data1 = (float *) gen_data1->data; - const float * data2 = (const float *) gen_data2->data; - for (i = 0; i < data_size; i++) - data1[i] += data2[i]; - } else if (internal_type == ECL_DOUBLE_TYPE) { - double * data1 = (double *) gen_data1->data; - const double * data2 = (const double *) gen_data2->data; - for (i = 0; i < data_size; i++) { - data1[i] += data2[i]; - } - } - } -} - - -void gen_data_imul(gen_data_type * gen_data1, const gen_data_type * gen_data2) { - //gen_data_config_assert_binary(gen_data1->config , gen_data2->config , __func__); - { - const int data_size = gen_data_config_get_data_size( gen_data1->config , gen_data1->current_report_step ); - const ecl_type_enum internal_type = gen_data_config_get_internal_type(gen_data1->config); - int i; - - if (internal_type == ECL_FLOAT_TYPE) { - float * data1 = (float *) gen_data1->data; - const float * data2 = (const float *) gen_data2->data; - for (i = 0; i < data_size; i++) - data1[i] *= data2[i]; - } else if (internal_type == ECL_DOUBLE_TYPE) { - double * data1 = (double *) gen_data1->data; - const double * data2 = (const double *) gen_data2->data; - for (i = 0; i < data_size; i++) - data1[i] *= data2[i]; - } - } -} - - -void gen_data_iaddsqr(gen_data_type * gen_data1, const gen_data_type * gen_data2) { - //gen_data_config_assert_binary(gen_data1->config , gen_data2->config , __func__); - { - const int data_size = gen_data_config_get_data_size( gen_data1->config , gen_data1->current_report_step ); - const ecl_type_enum internal_type = gen_data_config_get_internal_type(gen_data1->config); - int i; - - if (internal_type == ECL_FLOAT_TYPE) { - float * data1 = (float *) gen_data1->data; - const float * data2 = (const float *) gen_data2->data; - for (i = 0; i < data_size; i++) - data1[i] += data2[i] * data2[i]; - } else if (internal_type == ECL_DOUBLE_TYPE) { - double * data1 = (double *) gen_data1->data; - const double * data2 = (const double *) gen_data2->data; - for (i = 0; i < data_size; i++) - data1[i] += data2[i] * data2[i]; - } - } -} - - -void gen_data_scale(gen_data_type * gen_data, double scale_factor) { - //gen_data_config_assert_unary(gen_data->config, __func__); - { - const int data_size = gen_data_config_get_data_size( gen_data->config , gen_data->current_report_step ); - const ecl_type_enum internal_type = gen_data_config_get_internal_type(gen_data->config); - int i; - - if (internal_type == ECL_FLOAT_TYPE) { - float * data = (float *) gen_data->data; - for (i = 0; i < data_size; i++) - data[i] *= scale_factor; - } else if (internal_type == ECL_DOUBLE_TYPE) { - double * data = (double *) gen_data->data; - for (i = 0; i < data_size; i++) - data[i] *= scale_factor; - } - } -} - - -const bool_vector_type * gen_data_get_forward_mask( const gen_data_type * gen_data ) { - return gen_data_config_get_active_mask( gen_data->config ); -} - -void gen_data_copy_to_double_vector(const gen_data_type * gen_data , double_vector_type * vector){ - const ecl_type_enum internal_type = gen_data_config_get_internal_type(gen_data->config); - int size = gen_data_get_size( gen_data ); - if (internal_type == ECL_FLOAT_TYPE) { - float * data = (float *) gen_data->data; - double_vector_reset(vector); - for (int i = 0; i < size; i++){ - double_vector_append(vector , data[i]); - } - } else if (internal_type == ECL_DOUBLE_TYPE) { - double * data = (double *) gen_data->data; - double_vector_memcpy_from_data( vector , data , size ); - } - - -} - -#define INFLATE(inf,std,min) \ -{ \ - for (int i=0; i < data_size; i++) { \ - if (std_data[i] > 0) \ - inflation_data[i] = util_float_max( 1.0 , min_std_data[i] / std_data[i]); \ - else \ - inflation_data[i] = 1.0; \ - } \ -} - - -/** - If the size changes during the simulation this will go 100% belly - up. -*/ - -void gen_data_set_inflation(gen_data_type * inflation , const gen_data_type * std , const gen_data_type * min_std) { - const gen_data_config_type * config = inflation->config; - ecl_type_enum ecl_type = gen_data_config_get_internal_type( config ); - const int data_size = gen_data_config_get_data_size( std->config , std->current_report_step ); - - if (ecl_type == ECL_FLOAT_TYPE) { - float * inflation_data = (float *) inflation->data; - const float * std_data = (const float *) std->data; - const float * min_std_data = (const float *) min_std->data; - - INFLATE(inflation_data , std_data , min_std_data ); - - } else { - double * inflation_data = (double *) inflation->data; - const double * std_data = (const double *) std->data; - const double * min_std_data = (const double *) min_std->data; - - INFLATE(inflation_data , std_data , min_std_data ); - } -} -#undef INFLATE - - -/******************************************************************/ -/* Anonumously generated functions used by the enkf_node object */ -/******************************************************************/ -UTIL_SAFE_CAST_FUNCTION_CONST(gen_data , GEN_DATA) -UTIL_SAFE_CAST_FUNCTION(gen_data , GEN_DATA) -VOID_USER_GET(gen_data) -VOID_ALLOC(gen_data) -VOID_FREE(gen_data) -VOID_COPY (gen_data) -VOID_INITIALIZE(gen_data) -VOID_ECL_WRITE(gen_data) -VOID_FORWARD_LOAD(gen_data) -VOID_READ_FROM_BUFFER(gen_data); -VOID_WRITE_TO_BUFFER(gen_data); -VOID_SERIALIZE(gen_data) -VOID_DESERIALIZE(gen_data) -VOID_SET_INFLATION(gen_data) -VOID_CLEAR(gen_data) -VOID_SCALE(gen_data) -VOID_IMUL(gen_data) -VOID_IADD(gen_data) -VOID_IADDSQR(gen_data) -VOID_ISQRT(gen_data) diff --git a/ThirdParty/Ert/libenkf/src/gen_data_config.c b/ThirdParty/Ert/libenkf/src/gen_data_config.c deleted file mode 100644 index a37139a78b..0000000000 --- a/ThirdParty/Ert/libenkf/src/gen_data_config.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_data_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/** - About deactivating by the forward model - --------------------------------------- - - For the gen_data instances the forward model has the capability to - deactivate elements in a gen_data vector. This is implemented in - the function gen_data_ecl_load which will look for a file with - extension "_data" and then activate / deactivate elements - accordingly. -*/ - - - - -#define GEN_DATA_CONFIG_ID 90051 -struct gen_data_config_struct { - UTIL_TYPE_ID_DECLARATION; - char * key; /* The key this gen_data instance is known under - needed for debugging. */ - ecl_type_enum internal_type; /* The underlying type (float | double) of the data in the corresponding gen_data instances. */ - char * template_file; - char * template_buffer; /* Buffer containing the content of the template - read and internalized at boot time. */ - char * template_key; - int template_data_offset; /* The offset into the template buffer before the data should come. */ - int template_data_skip; /* The length of data identifier in the template.*/ - int template_buffer_size; /* The total size (bytes) of the template buffer .*/ - gen_data_file_format_type input_format; /* The format used for loading gen_data instances when the forward model has completed *AND* for loading the initial files.*/ - gen_data_file_format_type output_format; /* The format used when gen_data instances are written to disk for the forward model. */ - int_vector_type * data_size_vector; /* Data size, i.e. number of elements , indexed with report_step */ - int_vector_type * active_report_steps; /* The report steps where we expect to load data for this instance. */ - pthread_mutex_t update_lock; - /*****************************************************************/ - /* All the fields below this line are related to the capability of - the forward model to deactivate elements in a gen_data - instance. See documentation above. - */ - bool dynamic; - enkf_fs_type * last_read_fs; /* NBNB This will be NULL in the case of instances which are used as parameters. */ - int ens_size; - bool mask_modified; - bool_vector_type * active_mask; - int active_report_step; -}; - - -/*****************************************************************/ - -UTIL_IS_INSTANCE_FUNCTION(gen_data_config , GEN_DATA_CONFIG_ID) -UTIL_SAFE_CAST_FUNCTION(gen_data_config , GEN_DATA_CONFIG_ID) -UTIL_SAFE_CAST_FUNCTION_CONST(gen_data_config , GEN_DATA_CONFIG_ID) - -gen_data_file_format_type gen_data_config_get_input_format ( const gen_data_config_type * config) { return config->input_format; } -gen_data_file_format_type gen_data_config_get_output_format( const gen_data_config_type * config) { return config->output_format; } - - -ecl_type_enum gen_data_config_get_internal_type(const gen_data_config_type * config) { - return config->internal_type; -} - - -/** - If current_size as queried from config->data_size_vector == -1 - (i.e. not set); we seek through -*/ - -int gen_data_config_get_data_size__( const gen_data_config_type * config , int report_step) { - int current_size = int_vector_safe_iget( config->data_size_vector , report_step ); - return current_size; -} - -int gen_data_config_get_data_size( const gen_data_config_type * config , int report_step) { - int current_size = gen_data_config_get_data_size__(config , report_step); - if (current_size < 0) - util_abort("%s: Size not set for object:%s report_step:%d - internal error: \n",__func__ , config->key , report_step); - return current_size; -} - - - -int gen_data_config_get_initial_size( const gen_data_config_type * config ) { - int initial_size = int_vector_safe_iget( config->data_size_vector , 0); - if (initial_size < 0) - initial_size = 0; - - return initial_size; -} - - - -int gen_data_config_get_byte_size( const gen_data_config_type * config , int report_step) { - int byte_size = gen_data_config_get_data_size( config , report_step ) * ecl_util_get_sizeof_ctype( config->internal_type ); - return byte_size; -} - - - -static void gen_data_config_reset_template( gen_data_config_type * config ) { - util_safe_free( config->template_buffer ); - util_safe_free( config->template_key ); - util_safe_free( config->template_file ); - - config->template_file = NULL; - config->template_buffer = NULL; - config->template_key = NULL; - config->template_data_offset = 0; - config->template_data_skip = 0; - config->template_buffer_size = 0; -} - - - -static gen_data_config_type * gen_data_config_alloc( const char * key , bool dynamic ) { - gen_data_config_type * config = util_malloc(sizeof * config ); - UTIL_TYPE_ID_INIT( config , GEN_DATA_CONFIG_ID); - - config->key = util_alloc_string_copy( key ); - - config->template_file = NULL; - config->template_key = NULL; - config->template_buffer = NULL; - gen_data_config_reset_template( config ); - - config->internal_type = ECL_DOUBLE_TYPE; - config->input_format = GEN_DATA_UNDEFINED; - config->output_format = GEN_DATA_UNDEFINED; - config->data_size_vector = int_vector_alloc( 0 , -1 ); /* The default value: -1 - indicates "NOT SET" */ - config->active_report_steps= int_vector_alloc( 0 , 0 ); - config->active_mask = bool_vector_alloc(0 , true ); /* Elements are explicitly set to FALSE - this MUST default to true. */ - config->active_report_step = -1; - config->ens_size = -1; - config->last_read_fs = NULL; - config->dynamic = dynamic; - pthread_mutex_init( &config->update_lock , NULL ); - - - return config; -} - -gen_data_config_type * gen_data_config_alloc_GEN_PARAM( const char * key , gen_data_file_format_type output_format , gen_data_file_format_type input_format) { - gen_data_config_type * config = gen_data_config_alloc( key , false ); - - if (input_format == ASCII_TEMPLATE) - util_abort("%s: Sorry can not use INPUT_FORMAT:ASCII_TEMPLATE\n",__func__); - - if (output_format == GEN_DATA_UNDEFINED || input_format == GEN_DATA_UNDEFINED) - util_abort("%s: Sorry must specify valid values for both input and output format\n",__func__); - - config->output_format = output_format; - config->input_format = input_format; - return config; -} - - -gen_data_config_type * gen_data_config_alloc_GEN_DATA_result( const char * key , gen_data_file_format_type input_format) { - gen_data_config_type * config = gen_data_config_alloc( key , true ); - - if (input_format == ASCII_TEMPLATE) - util_abort("%s: Sorry can not use INPUT_FORMAT:ASCII_TEMPLATE\n",__func__); - - if (input_format == GEN_DATA_UNDEFINED) - util_abort("%s: Sorry must specify valid values for input format.\n",__func__); - - config->input_format = input_format; - return config; -} - -gen_data_config_type * gen_data_config_alloc_GEN_DATA_state( const char * key , gen_data_file_format_type output_format , gen_data_file_format_type input_format) { - gen_data_config_type * config = gen_data_config_alloc( key , true ); - - if (input_format == ASCII_TEMPLATE) - util_abort("%s: Sorry can not use INPUT_FORMAT:ASCII_TEMPLATE\n",__func__); - - if (output_format == GEN_DATA_UNDEFINED || input_format == GEN_DATA_UNDEFINED) - util_abort("%s: Sorry must specify valid values for both input and output format\n",__func__); - - config->output_format = output_format; - config->input_format = input_format; - return config; -} - - -const bool_vector_type * gen_data_config_get_active_mask( const gen_data_config_type * config ) { - if (config->dynamic) - return config->active_mask; - else - return NULL; /* GEN_PARAM instance will never be deactivated by the forward model. */ -} - - - - - -bool gen_data_config_set_template( gen_data_config_type * config , const char * template_ecl_file , const char * template_data_key ) { - char * template_buffer = NULL; - bool template_valid = true; - int template_buffer_size; - - if (template_ecl_file) { - if (util_file_readable( template_ecl_file )) { - template_buffer = util_fread_alloc_file_content( template_ecl_file , &template_buffer_size); - if (template_data_key) { - if (strstr(template_buffer , template_data_key) == NULL) - template_valid = false; - } - } else - template_valid = false; - } - - if (template_valid) { - - gen_data_config_reset_template(config); - if (template_ecl_file != NULL) { - char *data_ptr; - config->template_buffer = template_buffer; - config->template_buffer_size = template_buffer_size; - if (template_data_key != NULL) { - data_ptr = strstr(config->template_buffer , template_data_key); - if (data_ptr == NULL) - util_abort("%s: template:%s can not be used - could not find data key:%s \n",__func__ , template_ecl_file , template_data_key); - else { - config->template_data_offset = data_ptr - config->template_buffer; - config->template_data_skip = strlen( template_data_key ); - } - } else { /* We are using a template without a template_data_key - the - data is assumed to come at the end of the template. */ - config->template_data_offset = strlen( config->template_buffer ); - config->template_data_skip = 0; - } - - config->template_file = util_realloc_string_copy( config->template_file , template_ecl_file ); - config->template_key = util_realloc_string_copy( config->template_key , template_data_key ); - - if (config->output_format != ASCII_TEMPLATE) - fprintf(stderr,"**WARNING: The template settings will ignored for key:%s - use OUTPUT_FORMAT:ASCII_TEMPLATE to get template behaviour\n", config->key); - } - - } - return template_valid; -} - - -const char * gen_data_config_get_template_file( const gen_data_config_type * config ) { - return config->template_file; -} - -const char * gen_data_config_get_template_key( const gen_data_config_type * config ) { - return config->template_key; -} - - - - - - - - - -/** - This function takes a string representation of one of the - gen_data_file_format_type values, and returns the corresponding - integer value. - - Will return gen_data_undefined if the string is not recognized, - calling scope must check on this return value. -*/ - - -gen_data_file_format_type gen_data_config_check_format( const void * format_string ) { - gen_data_file_format_type type = GEN_DATA_UNDEFINED; - - if (format_string != NULL) { - - if (strcmp(format_string , "ASCII") == 0) - type = ASCII; - else if (strcmp(format_string , "ASCII_TEMPLATE") == 0) - type = ASCII_TEMPLATE; - else if (strcmp(format_string , "BINARY_DOUBLE") == 0) - type = BINARY_DOUBLE; - else if (strcmp(format_string , "BINARY_FLOAT") == 0) - type = BINARY_FLOAT; - - } - - return type; -} - - -/** - The valid options are: - - INPUT_FORMAT:(ASCII|ASCII_TEMPLATE|BINARY_DOUBLE|BINARY_FLOAT) - OUTPUT_FORMAT:(ASCII|ASCII_TEMPLATE|BINARY_DOUBLE|BINARY_FLOAT) - TEMPLATE:/some/template/file - KEY: - ECL_FILE: Forward model> (In the case of gen_param - this is extracted in the calling scope). - RESULT_FILE: - -*/ - - - - -void gen_data_config_free(gen_data_config_type * config) { - int_vector_free( config->data_size_vector ); - int_vector_free( config->active_report_steps ); - - util_safe_free( config->key ); - util_safe_free( config->template_buffer ); - util_safe_free( config->template_file ); - util_safe_free( config->template_key ); - bool_vector_free( config->active_mask ); - - free(config); -} - - - - -/** - This function gets a size (from a gen_data) instance, and verifies - that the size agrees with the currently stored size and - report_step. If the report_step is new we just record the new info, - otherwise it will break hard. -*/ - - -/** - Does not work properly with: - - 1. keep_run_path - the load_file will be left hanging around - and loaded again and again. - 2. Doing forward several steps - how to (time)index the files? - -*/ - - -void gen_data_config_assert_size(gen_data_config_type * config , int data_size, int report_step) { - pthread_mutex_lock( &config->update_lock ); - { - int current_size = int_vector_safe_iget( config->data_size_vector , report_step ); - if (current_size < 0) { - int_vector_iset( config->data_size_vector , report_step , data_size ); - current_size = data_size; - } - - if (current_size != data_size) { - util_abort("%s: Size mismatch when loading:%s from file - got %d elements - expected:%d [report_step:%d] \n", - __func__ , - gen_data_config_get_key( config ), - data_size , - current_size , - report_step); - } - } - pthread_mutex_unlock( &config->update_lock ); -} - -/** - When the forward model is creating results for GEN_DATA instances, - it can optionally signal that not all elements in the gen_data - should be active (i.e. the forward model failed in some way); that - is handled through this function. When all ensemble members have - called this function the mask config->active_mask should be true - ONLY for the elements which are true for all members. - - This MUST be called after gen_data_config_assert_size(). -*/ - -void gen_data_config_update_active(gen_data_config_type * config, const forward_load_context_type * load_context, const bool_vector_type * data_mask) { - pthread_mutex_lock( &config->update_lock ); - { - int report_step = forward_load_context_get_load_step( load_context ); - if ( int_vector_iget( config->data_size_vector , report_step ) > 0) { - if (config->active_report_step != report_step) { - /* This is the first ensemeble member loading for this - particular report_step. */ - bool_vector_reset( config->active_mask ); - bool_vector_iset( config->active_mask , int_vector_iget( config->data_size_vector , report_step ) - 1 , true ); - config->mask_modified = true; - } - - { - int i; - for (i=0; i < bool_vector_size( data_mask ); i++) { - if (!bool_vector_iget( data_mask , i )) { - bool_vector_iset( config->active_mask , i , false ); - config->mask_modified = true; - } - } - } - - if (config->mask_modified) { - /** - The global mask has been modified after the last load; - i.e. we update the on-disk representation. - */ - char * filename = util_alloc_sprintf("%s_active" , config->key ); - FILE * stream = enkf_fs_open_case_tstep_file( forward_load_context_get_result_fs( load_context ) , - filename , - report_step , - "w"); - - bool_vector_fwrite( config->active_mask , stream ); - - fclose( stream ); - free( filename ); - config->mask_modified = false; - } - } - config->active_report_step = report_step; - } - pthread_mutex_unlock( &config->update_lock ); -} - - -bool gen_data_config_has_active_mask( const gen_data_config_type * config , enkf_fs_type * fs , int report_step) { - bool has_mask; - { - char * filename = util_alloc_sprintf("%s_active" , config->key ); - FILE * stream = enkf_fs_open_excase_tstep_file( fs , filename , report_step); - - if (stream == NULL) - has_mask = false; - else { - has_mask = true; - fclose( stream ); - } - - free( filename ); - } - return has_mask; -} - - -/** - This function will load an active map from the enkf_fs filesystem. -*/ -void gen_data_config_load_active( gen_data_config_type * config , enkf_fs_type * fs, int report_step , bool force_load) { - if (!config->dynamic) - return; /* This is used as a GEN_PARAM instance - and the loading of mask is not an option. */ - - { - bool fs_changed = false; - if (fs != config->last_read_fs) { - config->last_read_fs = fs; - fs_changed = true; - } - - pthread_mutex_lock( &config->update_lock ); - { - if ( force_load || (int_vector_iget( config->data_size_vector , report_step ) > 0)) { - if (config->active_report_step != report_step || fs_changed) { - char * filename = util_alloc_sprintf("%s_active" , config->key ); - FILE * stream = enkf_fs_open_excase_tstep_file( fs , filename , report_step); - - if (stream != NULL) { - bool_vector_fread( config->active_mask , stream ); - fclose( stream ); - } else { - int gen_data_size = int_vector_safe_iget( config->data_size_vector, report_step ); - if (gen_data_size < 0) { - fprintf(stderr,"** Fatal internal error in function:%s \n",__func__); - fprintf(stderr,"\n"); - fprintf(stderr," 1: The active mask file:%s was not found \n",filename); - fprintf(stderr," 2: The size of the gen_data vectors has not been set\n"); - fprintf(stderr,"\n"); - fprintf(stderr,"We can not create a suitable active_mask. Code should call gen_data_config_has_active_mask()\n\n"); - - util_abort("%s: fatal internal error - could not create a suitable active_mask \n",__func__); - } else { - fprintf(stdout,"** Info: could not locate active data elements file %s, filling active vector with true all elements active \n",filename); - bool_vector_reset( config->active_mask ); - bool_vector_iset( config->active_mask, gen_data_size - 1, true); - } - } - free( filename ); - } - } - config->active_report_step = report_step; - } - pthread_mutex_unlock( &config->update_lock ); - } -} - -int gen_data_config_num_report_step( const gen_data_config_type * config ) { - return int_vector_size( config->active_report_steps ); -} - -bool gen_data_config_has_report_step( const gen_data_config_type * config , int report_step) { - return int_vector_contains_sorted( config->active_report_steps , report_step ); -} - -void gen_data_config_add_report_step( gen_data_config_type * config , int report_step) { - if (config->dynamic) { - if (!gen_data_config_has_report_step( config , report_step)) { - int_vector_append( config->active_report_steps , report_step ); - int_vector_sort( config->active_report_steps ); - } - } -} - -int gen_data_config_iget_report_step( const gen_data_config_type *config , int index) { - return int_vector_iget( config->active_report_steps , index ); -} - -void gen_data_config_set_active_report_steps_from_string( gen_data_config_type *config , const char * range_string) { - if (config->dynamic) { - int_vector_reset( config->active_report_steps ); - string_util_update_active_list(range_string , config->active_report_steps ); - } -} - - -const int_vector_type * gen_data_config_get_active_report_steps( const gen_data_config_type *config) { - return config->active_report_steps; -} - -void gen_data_config_set_ens_size( gen_data_config_type * config , int ens_size) { - config->ens_size = ens_size; -} - - -bool gen_data_config_is_dynamic( const gen_data_config_type * config ) { - return config->dynamic; -} - -void gen_data_config_get_template_data( const gen_data_config_type * config , - char ** template_buffer , - int * template_data_offset , - int * template_buffer_size , - int * template_data_skip) { - - *template_buffer = config->template_buffer; - *template_data_offset = config->template_data_offset; - *template_buffer_size = config->template_buffer_size; - *template_data_skip = config->template_data_skip; - -} - - -bool gen_data_config_valid_result_format(const char * result_file_fmt) { - if (result_file_fmt) { - if (util_is_abs_path( result_file_fmt )) - return false; - else { - if (util_int_format_count(result_file_fmt) == 1) - return true; - else - return false; - } - } else - return false; -} - - -const char * gen_data_config_get_key( const gen_data_config_type * config) { - return config->key; -} - -static const char * gen_data_config_format_name( gen_data_file_format_type format_type) { - switch (format_type ) { - case GEN_DATA_UNDEFINED: - return "UNDEFINED"; - break; - case ASCII: - return "ASCII"; - break; - case ASCII_TEMPLATE: - return "ASCII_TEMPLATE"; - break; - case BINARY_FLOAT: - return "BINARY_FLOAT"; - break; - case BINARY_DOUBLE: - return "BINARY_DOUBLE"; - break; - default: - util_abort("%s: What the f.. \n",__func__); - return NULL; - } -} - - -void gen_data_config_fprintf_config( const gen_data_config_type * config , enkf_var_type var_type , const char * outfile , const char * infile , - const char * min_std_file , FILE * stream) { - if (var_type == PARAMETER) - fprintf( stream , CONFIG_VALUE_FORMAT , outfile ); - else - fprintf( stream , CONFIG_OPTION_FORMAT , ECL_FILE_KEY , outfile ); - - if (min_std_file != NULL) - fprintf( stream , CONFIG_OPTION_FORMAT , MIN_STD_KEY , min_std_file ); - - if (config->template_file != NULL) - fprintf( stream , CONFIG_OPTION_FORMAT , TEMPLATE_KEY , config->template_file ); - - if (config->template_key != NULL) - fprintf( stream , CONFIG_OPTION_FORMAT , KEY_KEY , config->template_key ); - - if (infile != NULL) - fprintf( stream , CONFIG_OPTION_FORMAT , RESULT_FILE_KEY , infile ); - - if (config->input_format != GEN_DATA_UNDEFINED) - fprintf( stream , CONFIG_OPTION_FORMAT , INPUT_FORMAT_KEY , gen_data_config_format_name( config->input_format )); - - if (config->output_format != GEN_DATA_UNDEFINED) - fprintf( stream , CONFIG_OPTION_FORMAT , OUTPUT_FORMAT_KEY , gen_data_config_format_name( config->output_format )); -} - - - -/*****************************************************************/ - -VOID_FREE(gen_data_config) diff --git a/ThirdParty/Ert/libenkf/src/gen_kw.c b/ThirdParty/Ert/libenkf/src/gen_kw.c deleted file mode 100644 index 2399da9b97..0000000000 --- a/ThirdParty/Ert/libenkf/src/gen_kw.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_kw.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -GET_DATA_SIZE_HEADER(gen_kw); - - -struct gen_kw_struct { - int __type_id; - const gen_kw_config_type * config; - double * data; - subst_list_type * subst_list; -}; - -/*****************************************************************/ - - - -void gen_kw_free(gen_kw_type *gen_kw) { - util_safe_free( gen_kw->data ); - subst_list_free( gen_kw->subst_list ); - free(gen_kw); -} - - - - - -gen_kw_type * gen_kw_alloc(const gen_kw_config_type * config) { - gen_kw_type * gen_kw = util_malloc(sizeof *gen_kw ); - gen_kw->__type_id = GEN_KW; - gen_kw->config = config; - gen_kw->subst_list = subst_list_alloc( NULL ); - gen_kw->data = util_calloc( gen_kw_config_get_data_size( config ) , sizeof * gen_kw->data ); - return gen_kw; -} - - -void gen_kw_clear(gen_kw_type * gen_kw) { - int i; - for (i=0; i < gen_kw_config_get_data_size( gen_kw->config ); i++) - gen_kw->data[i] = 0.0; -} - - - -void gen_kw_copy(const gen_kw_type * src , gen_kw_type * target) { - if (src->config == target->config) { - int buffer_size = gen_kw_config_get_data_size( src->config ) * sizeof src->data; - memcpy( target->data , src->data , buffer_size ); - } else - util_abort("%s: two elements do not share config object \n",__func__); -} - - - -int gen_kw_data_size( gen_kw_type * gen_kw ) { - return gen_kw_config_get_data_size( gen_kw->config ); -} - - - -double gen_kw_data_iget( gen_kw_type * gen_kw, int index , bool do_transform ) -{ - double value; - int size = gen_kw_config_get_data_size( gen_kw->config ); - if (( index < 0 ) || ( index >= size )) - util_abort( "%s: index:%d invalid. Valid interval: [0,%d>.\n" , __func__ , index , size ); - - if (do_transform) { - value = gen_kw_config_transform(gen_kw->config, index, gen_kw->data[index]); - } - else { - value = gen_kw->data[index]; - } - - return value; -} - - -void gen_kw_data_set_vector( gen_kw_type * gen_kw, const double_vector_type * values ) { - int size = gen_kw_config_get_data_size( gen_kw->config ); - if (size == double_vector_size( values )) { - for (int index = 0; index < size; index++) - gen_kw->data[index] = double_vector_iget( values , index); - } else - util_abort( "%s: Invalid size for vector:%d gen_Kw:%d \n",__func__ , double_vector_size( values ) , size); -} - - - -void gen_kw_data_iset( gen_kw_type * gen_kw, int index , double value ) -{ - int size = gen_kw_config_get_data_size( gen_kw->config ); - if (( index < 0 ) || ( index >= size )) - util_abort( "%s: index:%d invalid. Valid interval: [0,%d>.\n" , __func__ , index , size ); - - gen_kw->data[index] = value; -} - - -double gen_kw_data_get( gen_kw_type * gen_kw, const char * subkey, bool do_transform ) -{ - int index = gen_kw_config_get_index(gen_kw->config, subkey); - return gen_kw_data_iget(gen_kw, index, do_transform); -} - -void gen_kw_data_set( gen_kw_type * gen_kw, const char * subkey, double value ) -{ - int index = gen_kw_config_get_index(gen_kw->config, subkey); - return gen_kw_data_iset(gen_kw, index, value); -} - - -bool gen_kw_data_has_key( gen_kw_type * gen_kw, const char * subkey ) -{ - int index = gen_kw_config_get_index(gen_kw->config, subkey); - bool has_key = ((0 <= index) && (gen_kw_data_size(gen_kw) > index))? true : false; - return has_key; -} - -bool gen_kw_write_to_buffer(const gen_kw_type *gen_kw , buffer_type * buffer, int report_step) { - const int data_size = gen_kw_config_get_data_size( gen_kw->config ); - buffer_fwrite_int( buffer , GEN_KW ); - buffer_fwrite(buffer , gen_kw->data , sizeof *gen_kw->data , data_size); - return true; -} - - - - -/** - As of 17/03/09 (svn 1811) MULTFLT has been depreceated, and GEN_KW - has been inserted as a 'drop-in-replacement'. This implies that - existing storage labeled with implemantation type 'MULTFLT' should - be silently 'upgraded' to 'GEN_KW'. -*/ - - -#define MULTFLT 102 -void gen_kw_read_from_buffer(gen_kw_type * gen_kw , buffer_type * buffer, enkf_fs_type * fs, int report_step) { - const int data_size = gen_kw_config_get_data_size( gen_kw->config ); - ert_impl_type file_type; - file_type = buffer_fread_int(buffer); - if ((file_type == GEN_KW) || (file_type == MULTFLT)) - buffer_fread(buffer , gen_kw->data , sizeof *gen_kw->data , data_size); -} -#undef MULTFLT - - -void gen_kw_truncate(gen_kw_type * gen_kw) { - return ; -} - - - -bool gen_kw_initialize(gen_kw_type *gen_kw , int iens , const char * init_file , rng_type * rng ) { - if (!init_file && !rng) - util_abort("%s internal error: both init_file and rng are NULL", __func__); - - bool ret = false; - - if (init_file) - ret = gen_kw_fload(gen_kw , init_file ); - else { - const double mean = 0.0; /* Mean and std are hardcoded - the variability should be in the transformation. */ - const double std = 1.0; - const int data_size = gen_kw_config_get_data_size( gen_kw->config ); - int i; - - for (i=0; i < data_size; i++) - gen_kw->data[i] = enkf_util_rand_normal(mean , std , rng); - - ret = true; - } - return ret; -} - - - - - -void gen_kw_serialize(const gen_kw_type *gen_kw , node_id_type node_id , const active_list_type * active_list , matrix_type * A , int row_offset , int column) { - const int data_size = gen_kw_config_get_data_size( gen_kw->config ); - enkf_matrix_serialize( gen_kw->data , data_size , ECL_DOUBLE_TYPE , active_list , A , row_offset , column); -} - - -void gen_kw_deserialize(gen_kw_type *gen_kw , node_id_type node_id , const active_list_type * active_list , const matrix_type * A , int row_offset , int column) { - const int data_size = gen_kw_config_get_data_size( gen_kw->config ); - enkf_matrix_deserialize( gen_kw->data , data_size , ECL_DOUBLE_TYPE , active_list , A , row_offset , column); -} - - - -void gen_kw_filter_file(const gen_kw_type * gen_kw , const char * target_file) { - const char * template_file = gen_kw_config_get_template_file(gen_kw->config); - if (template_file != NULL) { - const int size = gen_kw_config_get_data_size(gen_kw->config ); - int ikw; - - for (ikw = 0; ikw < size; ikw++) { - const char * key = gen_kw_config_get_tagged_name(gen_kw->config , ikw); - subst_list_append_owned_ref(gen_kw->subst_list , key , util_alloc_sprintf("%g" , gen_kw_config_transform( gen_kw->config , ikw , gen_kw->data[ikw] )) , NULL); - } - - /* - If the target_file already exists as a symbolic link the - symbolic link is removed before creating the target file. The is - to ensure against existing symlinks pointing to a common file - outside the realization root. - */ - if (util_is_link( target_file )) - remove( target_file ); - - subst_list_filter_file( gen_kw->subst_list , template_file , target_file); - } else - util_abort("%s: internal error - tried to filter gen_kw instance without template file.\n",__func__); -} - - -void gen_kw_write_export_file(const gen_kw_type * gen_kw, FILE * filestream) { - const int size = gen_kw_config_get_data_size(gen_kw->config ); - int ikw; - - for (ikw = 0; ikw < size; ++ikw) { - const char * key = gen_kw_config_get_key(gen_kw->config); - const char * parameter = gen_kw_config_iget_name(gen_kw->config , ikw); - int width = 60 - (strlen(key) + strlen(parameter) + 1); - double transformed_value = gen_kw_config_transform( gen_kw->config , ikw , gen_kw->data[ikw] ); - { - char * print_string = util_alloc_sprintf("%s:%s %g\n", key, parameter, width, transformed_value); - fprintf(filestream, "%s", print_string); - free( print_string ); - } - - if (gen_kw_config_should_use_log_scale(gen_kw->config, ikw)) { - double log_transformed_value = log10(transformed_value); - char * print_log_string = util_alloc_sprintf("LOG10_%s:%s %g\n", key, parameter, width, log_transformed_value); - fprintf(filestream, "%s", print_log_string); - free( print_log_string ); - } - } -} - -void gen_kw_ecl_write_template(const gen_kw_type * gen_kw , const char * file_name){ - gen_kw_filter_file(gen_kw , file_name); -} - - -void gen_kw_ecl_write(const gen_kw_type * gen_kw , const char * run_path , const char * base_file , void * filestream) { - if (fortio_is_instance(filestream)) { - util_abort("%s: Called with fortio instance, aborting\n", __func__); - } else { - if (filestream) - gen_kw_write_export_file(gen_kw, filestream); - { - char * target_file; - if (run_path) - target_file = util_alloc_filename( run_path , base_file , NULL); - else - target_file = util_alloc_string_copy( base_file ); - - gen_kw_filter_file(gen_kw , target_file); - - free( target_file ); - } - } -} - - - -const char * gen_kw_get_name(const gen_kw_type * gen_kw, int kw_nr) { - return gen_kw_config_iget_name(gen_kw->config , kw_nr); -} - - -/** - This function will load values for gen_kw instance from file. The - file should be formatted as either: - - ------- - Value1 - Value2 - Value3 - .... - ValueN - ------- - - Or - - ------------ - Key3 Value3 - Key5 Value5 - Key1 Value1 - ..... - ------------ - - I.e. you can either just dump in all the numbers in one long - vector, or you can interlace numbers and keys. In the latter case - the ordering is arbitrary. - - Observe the following: - - 1. All values must be specified. - 2. The values are in the N(0,1) domain, i.e. the untransformed variables. - -*/ - -bool gen_kw_fload(gen_kw_type * gen_kw , const char * filename) { - FILE * stream = util_fopen__( filename , "r"); - if (stream) { - const int size = gen_kw_config_get_data_size(gen_kw->config ); - bool readOK = true; - - /* First try reading all the data as one long vector. */ - { - int index = 0; - while ((index < size) && readOK) { - double value; - if (fscanf(stream,"%lg" , &value) == 1) - gen_kw->data[index] = value; - else - readOK = false; - index++; - } - } - - /* - OK - rewind and try again with interlaced key + value - pairs. Observe that we still require that ALL the elements in the - gen_kw instance are set, i.e. it is not allowed to read only some - of the keywords; but the ordering is not relevant. - - The code will be fooled (and give undefined erronous results) if - the same key appears several times. Be polite! - */ - - if (!readOK) { - int counter = 0; - readOK = true; - util_fseek( stream , 0 , SEEK_SET ); - - while ((counter < size) && readOK) { - char key[128]; - double value; - int fscanf_return = fscanf(stream , "%s %lg" , key , &value); - - if (fscanf_return == 2) { - int index = gen_kw_config_get_index(gen_kw->config , key); - if (index >= 0) - gen_kw->data[index] = value; - else - util_abort("%s: key:%s not recognized as part of GEN_KW instance - error when reading file:%s \n",__func__ , key , filename); - counter++; - } else { - util_abort("%s: failed to read (key,value) pair at line:%d in file:%s \n",__func__ , util_get_current_linenr( stream ) , filename); - readOK = false; - } - } - } - - if (!readOK) - util_abort("%s: failed loading from file:%s \n",__func__ , filename); - - fclose(stream); - return true; - } else - return false; -} - - - -/** - Will return 0.0 on invalid input, and set valid -> false. It is the - responsibility of the calling scope to check valid. -*/ -bool gen_kw_user_get(const gen_kw_type * gen_kw, const char * key , int report_step , double * value) { - int index = gen_kw_config_get_index(gen_kw->config , key); - - if (index >= 0) { - *value = gen_kw_config_transform(gen_kw->config , index , gen_kw->data[ index ] ); - return true; - } else { - *value = 0.0; - fprintf(stderr,"** Warning:could not lookup key:%s in gen_kw instance \n",key); - return false; - } -} - - -void gen_kw_set_subst_parent(gen_kw_type * gen_kw , const subst_list_type * subst_parent) { - subst_list_set_parent( gen_kw->subst_list , subst_parent ); -} - - -void gen_kw_set_inflation(gen_kw_type * inflation , const gen_kw_type * std , const gen_kw_type * min_std) { - const int data_size = gen_kw_config_get_data_size(std->config ); - const double * std_data = std->data; - const double * min_std_data = min_std->data; - double * inflation_data = inflation->data; - - { - for (int i=0; i < data_size; i++) { - if (std_data[i] > 0) - inflation_data[i] = util_double_max( 1.0 , min_std_data[i] / std_data[i]); - else - inflation_data[i] = 1; - } - } -} - - -void gen_kw_iadd( gen_kw_type * gen_kw , const gen_kw_type * delta) { - const int data_size = gen_kw_config_get_data_size( gen_kw->config ); - for(int i=0; i < data_size; i++) - gen_kw->data[i] += delta->data[i]; -} - -void gen_kw_iaddsqr( gen_kw_type * gen_kw , const gen_kw_type * delta) { - const int data_size = gen_kw_config_get_data_size( gen_kw->config ); - for(int i=0; i < data_size; i++) - gen_kw->data[i] += (delta->data[i] * delta->data[i]); -} - -void gen_kw_imul( gen_kw_type * gen_kw , const gen_kw_type * delta) { - const int data_size = gen_kw_config_get_data_size( gen_kw->config ); - for(int i=0; i < data_size; i++) - gen_kw->data[i] *= delta->data[i]; -} - -void gen_kw_scale( gen_kw_type * gen_kw , double scale_factor) { - const int data_size = gen_kw_config_get_data_size( gen_kw->config ); - for(int i=0; i < data_size; i++) - gen_kw->data[i] *= scale_factor; -} - -void gen_kw_isqrt( gen_kw_type * gen_kw ) { - const int data_size = gen_kw_config_get_data_size( gen_kw->config ); - for(int i=0; i < data_size; i++) - gen_kw->data[i] = sqrt( gen_kw->data[i] ); -} - - -/******************************************************************/ -/* Anonumously generated functions used by the enkf_node object */ -/******************************************************************/ -UTIL_SAFE_CAST_FUNCTION(gen_kw , GEN_KW); -UTIL_SAFE_CAST_FUNCTION_CONST(gen_kw , GEN_KW); -VOID_ALLOC(gen_kw); -VOID_INITIALIZE(gen_kw); -VOID_COPY(gen_kw) -VOID_FREE(gen_kw) -VOID_ECL_WRITE(gen_kw) -VOID_USER_GET(gen_kw) -VOID_WRITE_TO_BUFFER(gen_kw) -VOID_READ_FROM_BUFFER(gen_kw) -VOID_SERIALIZE(gen_kw) -VOID_DESERIALIZE(gen_kw) -VOID_SET_INFLATION(gen_kw) -VOID_CLEAR(gen_kw) -VOID_IADD(gen_kw) -VOID_SCALE(gen_kw) -VOID_IMUL(gen_kw) -VOID_IADDSQR(gen_kw) -VOID_ISQRT(gen_kw) -VOID_FLOAD(gen_kw) diff --git a/ThirdParty/Ert/libenkf/src/gen_kw_config.c b/ThirdParty/Ert/libenkf/src/gen_kw_config.c deleted file mode 100644 index 65c475d09e..0000000000 --- a/ThirdParty/Ert/libenkf/src/gen_kw_config.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_kw_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define GEN_KW_CONFIG_TYPE_ID 550761 -#define GEN_KW_PARAMETER_TYPE_ID 886201 - - -typedef struct { - UTIL_TYPE_ID_DECLARATION; - char * name; - char * tagged_name; - trans_func_type * trans_func; -} gen_kw_parameter_type; - - - -struct gen_kw_config_struct { - UTIL_TYPE_ID_DECLARATION; - char * key; - vector_type * parameters; /* Vector of gen_kw_parameter_type instances. */ - char * template_file; - char * parameter_file; - const char * tag_fmt; /* Pointer to the tag_format owned by the ensemble config object. */ -}; - - -/*****************************************************************/ - -UTIL_SAFE_CAST_FUNCTION( gen_kw_parameter , GEN_KW_PARAMETER_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION_CONST( gen_kw_parameter , GEN_KW_PARAMETER_TYPE_ID ) - - -UTIL_SAFE_CAST_FUNCTION( gen_kw_config , GEN_KW_CONFIG_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION_CONST( gen_kw_config , GEN_KW_CONFIG_TYPE_ID ) - -static void gen_kw_parameter_update_tagged_name( gen_kw_parameter_type * parameter , const char * tag_fmt) { - if (tag_fmt != NULL) - parameter->tagged_name = util_realloc_sprintf( parameter->tagged_name , tag_fmt , parameter->name ); -} - - -static gen_kw_parameter_type * gen_kw_parameter_alloc( const char * parameter_name , const char * tag_fmt ) { - gen_kw_parameter_type * parameter = util_malloc( sizeof * parameter ); - UTIL_TYPE_ID_INIT( parameter , GEN_KW_PARAMETER_TYPE_ID); - parameter->name = util_alloc_string_copy( parameter_name ); - parameter->tagged_name = NULL; - parameter->trans_func = NULL; - gen_kw_parameter_update_tagged_name( parameter , tag_fmt ); - return parameter; -} - - -static void gen_kw_parameter_free( gen_kw_parameter_type * parameter ) { - util_safe_free( parameter->name ); - util_safe_free( parameter->tagged_name ); - if (parameter->trans_func != NULL) - trans_func_free( parameter->trans_func ); - free( parameter ); -} - - -static void gen_kw_parameter_free__( void * __parameter ) { - gen_kw_parameter_type * parameter = gen_kw_parameter_safe_cast( __parameter ); - gen_kw_parameter_free( parameter ); -} - - -static void gen_kw_parameter_set_trans_func( gen_kw_parameter_type * parameter , trans_func_type * trans_func ) { - if (parameter->trans_func != NULL) - trans_func_free( parameter->trans_func ); - parameter->trans_func = trans_func; -} - - - -/*****************************************************************/ - - -const char * gen_kw_config_get_template_file(const gen_kw_config_type * config) { - return config->template_file; -} - - -/* - The input template file must point to an existing file. -*/ -void gen_kw_config_set_template_file( gen_kw_config_type * config , const char * template_file ) { - if (template_file != NULL) { - if (!util_file_exists(template_file)) - util_abort("%s: the template_file:%s does not exist - aborting.\n",__func__ , template_file); - } - - config->template_file = util_realloc_string_copy( config->template_file , template_file ); -} - - - -void gen_kw_config_set_parameter_file( gen_kw_config_type * config , const char * parameter_file ) { - config->parameter_file = util_realloc_string_copy( config->parameter_file , parameter_file ); - vector_clear( config->parameters ); - if (parameter_file != NULL) { - FILE * stream = util_fopen(parameter_file , "r"); - - while (true) { - char parameter_name[256]; - int fscanf_return; - - fscanf_return = fscanf(stream , "%s" , parameter_name); - if (fscanf_return == 1) { - gen_kw_parameter_type * parameter = gen_kw_parameter_alloc( parameter_name , config->tag_fmt); - trans_func_type * trans_func = trans_func_fscanf_alloc( stream, parameter_file ); - gen_kw_parameter_set_trans_func( parameter , trans_func ); - - vector_append_owned_ref( config->parameters , parameter , gen_kw_parameter_free__ ); - } else - break; /* OK - we are ate EOF. */ - } - - fclose( stream ); - } -} - - - - -const char * gen_kw_config_get_parameter_file( const gen_kw_config_type * config ) { - return config->parameter_file; -} - - -/** - Unfortunately the GUI makes it necessary(??) to be able to create - halfways initialized gen_kw_config objects; and we then have to be - able to query the gen_kw_config object if it is valid. Observe that - some of the required config information will be owned by the - enkf_config_node itself, this function should therefor NOT be - called directly, only through the enkf_config_node_is_valid() - function. - - Requirements: - ------------- - * template_file != NULL - * parameter_file != NULL (this means that the special schedule_prediction_file keyword will be invalid). - -*/ - -bool gen_kw_config_is_valid( const gen_kw_config_type * config ) { - if (config->template_file != NULL && config->parameter_file != NULL) - return true; - else - return false; -} - - -/** - A call to gen_kw_config_update_tag_format() must be called - afterwards, otherwise all tagged strings will just be NULL. -*/ -gen_kw_config_type * gen_kw_config_alloc_empty( const char * key , const char * tag_fmt ) { - gen_kw_config_type *gen_kw_config = util_malloc(sizeof *gen_kw_config); - UTIL_TYPE_ID_INIT(gen_kw_config , GEN_KW_CONFIG_TYPE_ID); - - gen_kw_config->key = NULL; - gen_kw_config->template_file = NULL; - gen_kw_config->parameter_file = NULL; - gen_kw_config->parameters = vector_alloc_new(); - gen_kw_config->tag_fmt = tag_fmt; - gen_kw_config->key = util_alloc_string_copy( key ); - - return gen_kw_config; -} - - - -void gen_kw_config_update( gen_kw_config_type * config , const char * template_file , const char * parameter_file ) { - gen_kw_config_set_template_file( config , template_file); - gen_kw_config_set_parameter_file( config , parameter_file ); -} - - - -double gen_kw_config_transform(const gen_kw_config_type * config , int index, double x) { - const gen_kw_parameter_type * parameter = vector_iget_const( config->parameters , index ); - return trans_func_eval( parameter->trans_func , x); -} - -bool gen_kw_config_should_use_log_scale(const gen_kw_config_type * config, int index) { - const gen_kw_parameter_type * parameter = vector_iget_const( config->parameters , index ); - return trans_func_use_log_scale( parameter->trans_func); -} - -void gen_kw_config_free(gen_kw_config_type * gen_kw_config) { - util_safe_free( gen_kw_config->key ); - util_safe_free( gen_kw_config->template_file ); - util_safe_free( gen_kw_config->parameter_file ); - - vector_free( gen_kw_config->parameters ); - free(gen_kw_config); -} - - - -int gen_kw_config_get_data_size(const gen_kw_config_type * gen_kw_config) { - return vector_get_size(gen_kw_config->parameters); -} - - - -const char * gen_kw_config_get_key(const gen_kw_config_type * config ) { - return config->key; -} - - -char * gen_kw_config_alloc_user_key(const gen_kw_config_type * config , int kw_nr) { - char * user_key = util_alloc_sprintf("%s:%s" , config->key ,gen_kw_config_iget_name( config , kw_nr )); - return user_key; -} - - -const char * gen_kw_config_iget_name(const gen_kw_config_type * config, int kw_nr) { - const gen_kw_parameter_type * parameter = vector_iget( config->parameters , kw_nr ); - return parameter->name; -} - - - - -const char * gen_kw_config_get_tagged_name(const gen_kw_config_type * config, int kw_nr) { - const gen_kw_parameter_type * parameter = vector_iget( config->parameters , kw_nr ); - return parameter->tagged_name; -} - - -void gen_kw_config_update_tag_format(gen_kw_config_type * config , const char * tag_format) { - int i; - - config->tag_fmt = tag_format; - for (i=0; i < vector_get_size( config->parameters ); i++) - gen_kw_parameter_update_tagged_name( vector_iget( config->parameters , i ) , config->tag_fmt); -} - - -stringlist_type * gen_kw_config_alloc_name_list( const gen_kw_config_type * config ) { - - stringlist_type * name_list = stringlist_alloc_new(); - int i; - for (i=0; i < vector_get_size( config->parameters ); i++) { - const gen_kw_parameter_type * parameter = vector_iget_const( config->parameters , i ); - stringlist_append_ref( name_list , parameter->name ); /* If the underlying parameter goes out scope - whom bang .. */ - } - - return name_list; -} - - - - - -/** - Will return -1 if the index is invalid. -*/ -int gen_kw_config_get_index(const gen_kw_config_type * config , const char * key) { - const int size = gen_kw_config_get_data_size(config); - bool have_key = false; - int index = 0; - - while (index < size && !have_key) { - const gen_kw_parameter_type * parameter = vector_iget_const( config->parameters , index ); - if (strcmp(parameter->name , key) == 0) - have_key = true; - else - index++; - } - - if (have_key) - return index; - else - return -1; -} - - - -void gen_kw_config_fprintf_config( const gen_kw_config_type * config , const char * outfile , const char * min_std_file , FILE * stream ) { - fprintf(stream , CONFIG_VALUE_FORMAT , config->template_file ); - fprintf(stream , CONFIG_VALUE_FORMAT , outfile ); - fprintf(stream , CONFIG_VALUE_FORMAT , config->parameter_file ); - - if (min_std_file != NULL) - fprintf( stream , CONFIG_OPTION_FORMAT , MIN_STD_KEY , min_std_file); - -} - - -/*****************************************************************/ - -VOID_FREE(gen_kw_config) -VOID_GET_DATA_SIZE(gen_kw) diff --git a/ThirdParty/Ert/libenkf/src/gen_obs.c b/ThirdParty/Ert/libenkf/src/gen_obs.c deleted file mode 100644 index f407713f43..0000000000 --- a/ThirdParty/Ert/libenkf/src/gen_obs.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_obs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/** - See the overview documentation of the observation system in - enkf_obs.c -*/ -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/** - This file implemenets a structure for general observations. A - general observation is just a vector of numbers - where EnKF has no - understanding whatsover of the type of these data. The actual data - is supposed to be found in a file. - - Currently it can only observe gen_data instances - but that should - be generalized. -*/ - -/* - The std_scaling field of the xxx_obs structure can be used to scale - the standard deviation used for the observations, either to support - workflows with multiple data assimilation or to reduce the effect of - observation correlations. - - When querying for the observation standard deviation using - gen_obs_iget_std() the user input value of standard deviation will - be returned, whereas when the function gen_obs_measure() is used the - std_scaling will be incorporated in the result. -*/ - -#define GEN_OBS_TYPE_ID 77619 - -struct gen_obs_struct { - UTIL_TYPE_ID_DECLARATION; - int obs_size; /* This is the total size of the observation vector. */ - int * data_index_list; /* The indexes which are observed in the corresponding gen_data instance - of length obs_size. */ - bool observe_all_data; /* Flag which indiactes whether all data in the gen_data instance should be observed - in that case we must do a size comparizon-check at use time. */ - - double * obs_data; /* The observed data. */ - double * obs_std; /* The observed standard deviation. */ - double * std_scaling; /* Scaling factor for the standard deviation */ - - char * obs_key; /* The key this observation is held by - in the enkf_obs structur (only for debug messages). */ - gen_data_file_format_type obs_format; /* The format, i.e. ASCII, binary_double or binary_float, of the observation file. */ - matrix_type * error_covar; - gen_data_config_type * data_config; -}; - -/******************************************************************/ - - -static UTIL_SAFE_CAST_FUNCTION_CONST(gen_obs , GEN_OBS_TYPE_ID) -static UTIL_SAFE_CAST_FUNCTION(gen_obs , GEN_OBS_TYPE_ID) - -void gen_obs_free(gen_obs_type * gen_obs) { - util_safe_free(gen_obs->obs_data); - util_safe_free(gen_obs->obs_std); - util_safe_free(gen_obs->data_index_list); - util_safe_free(gen_obs->obs_key); - util_safe_free(gen_obs->std_scaling); - if (gen_obs->error_covar != NULL) - matrix_free( gen_obs->error_covar ); - - free(gen_obs); -} - - -static double IGET_SCALED_STD(const gen_obs_type * gen_obs, int index) { - return gen_obs->obs_std[index] * gen_obs->std_scaling[index]; -} - - -/** - This function loads the actual observations from disk, and - initializes the obs_data and obs_std pointers with the - observations. It also sets the obs_size field of the gen_obs - instance. - - The file with observations should be a long vector of 2N elements, - where the first N elements are data values, and the last N values - are the corresponding standard deviations. - - The file is loaded with the gen_common_fload_alloc() function, and - can be in formatted ASCII or binary_float / binary_double. Observe - that there is *NO* header information in this file. -*/ - - -static void gen_obs_set_data(gen_obs_type * gen_obs, int buffer_size , const double * buffer) { - gen_obs->obs_size = buffer_size / 2; - gen_obs->obs_data = util_realloc(gen_obs->obs_data , gen_obs->obs_size * sizeof * gen_obs->obs_data ); - gen_obs->obs_std = util_realloc(gen_obs->obs_std , gen_obs->obs_size * sizeof * gen_obs->obs_std ); - gen_obs->std_scaling = util_realloc(gen_obs->std_scaling , gen_obs->obs_size * sizeof * gen_obs->std_scaling ); - gen_obs->data_index_list = util_realloc(gen_obs->data_index_list , gen_obs->obs_size * sizeof * gen_obs->data_index_list ); - { - int iobs; - double * double_buffer = (double * ) buffer; - for (iobs = 0; iobs < gen_obs->obs_size; iobs++) { - gen_obs->obs_data[iobs] = double_buffer[2*iobs]; - gen_obs->obs_std[iobs] = double_buffer[2*iobs + 1]; - gen_obs->std_scaling[iobs] = 1.0; - gen_obs->data_index_list[iobs] = iobs; - - } - } -} - - -void gen_obs_load_observation(gen_obs_type * gen_obs, const char * obs_file) { - ecl_type_enum load_type; - void * buffer; - int buffer_size = 0; - buffer = gen_common_fload_alloc(obs_file , gen_obs->obs_format , ECL_DOUBLE_TYPE , &load_type , &buffer_size); - - /** Ensure that the data is of type double. */ - if (load_type == ECL_FLOAT_TYPE) { - double * double_data = util_calloc(gen_obs->obs_size , sizeof * double_data ); - util_float_to_double(double_data , (const float *) buffer , buffer_size); - free(buffer); - buffer = double_data; - } - - gen_obs_set_data( gen_obs , buffer_size , buffer ); - free(buffer); -} - - - -void gen_obs_set_scalar( gen_obs_type * gen_obs , double scalar_value , double scalar_std) { - double buffer[2] = { scalar_value , scalar_std }; - gen_obs_set_data( gen_obs , 2 , buffer ); -} - -void gen_obs_attach_data_index( gen_obs_type * obs , const int_vector_type * data_index ) { - util_safe_free( obs->data_index_list ); - obs->data_index_list = int_vector_alloc_data_copy( data_index ); - obs->observe_all_data = false; -} - - -void gen_obs_load_data_index( gen_obs_type * obs , const char * data_index_file) { - /* Parsing an a file with integers. */ - util_safe_free( obs->data_index_list ); - obs->data_index_list = gen_common_fscanf_alloc( data_index_file , ECL_INT_TYPE , &obs->obs_size); - obs->observe_all_data = false; -} - - -void gen_obs_parse_data_index( gen_obs_type * obs , const char * data_index_string) { - /* Parsing a string of the type "1,3,5,9-100,200,202,300-1000" */ - int_vector_type * index_list = string_util_alloc_active_list( data_index_string ); - int_vector_shrink( index_list ); - gen_obs_attach_data_index( obs , index_list ); - int_vector_free( index_list ); -} - - - -gen_obs_type * gen_obs_alloc__(gen_data_config_type * data_config , const char * obs_key) { - gen_obs_type * obs = util_malloc(sizeof * obs); - UTIL_TYPE_ID_INIT( obs , GEN_OBS_TYPE_ID ); - obs->obs_data = NULL; - obs->obs_std = NULL; - obs->std_scaling = NULL; - obs->data_index_list = NULL; - obs->obs_format = ASCII; /* Hardcoded for now. */ - obs->obs_key = util_alloc_string_copy( obs_key ); - obs->data_config = data_config; - obs->observe_all_data = true; - obs->error_covar = NULL; - return obs; -} - - -/** - data_index_file is the name of a file with indices which should be - observed, data_inde_string is the same, in the form of a - "1,2,3,4-10, 17,19,22-100" string. Only one of these items can be - != NULL. If both are NULL it is assumed that all the indices of the - gen_data instance should be observed. - - @error_covar_file is the name of file which contains a matrix of - error-covariance. The file data will be read with the function - matrix_fscanf_data(), i.e. it should consist of formatted - numbers. Since the matrix is symmetric it does not matter whether - it is represented in row-major or column-major order; newlines for - pretty reading can be inserted but are not necessary. - - The error_covar_file should contain NO header information. -*/ - - -gen_obs_type * gen_obs_alloc(gen_data_config_type * data_config , const char * obs_key , const char * obs_file , double scalar_value , double scalar_error , const char * data_index_file , const char * data_index_string , const char * error_covar_file) { - gen_obs_type * obs = gen_obs_alloc__( data_config , obs_key ); - if (obs_file) - gen_obs_load_observation(obs , obs_file ); /* The observation data is loaded - and internalized at boot time - even though it might not be needed for a long time. */ - else - gen_obs_set_scalar( obs , scalar_value , scalar_error ); - - - if (data_index_file) - gen_obs_load_data_index( obs , data_index_file ); - else if (data_index_string) - gen_obs_parse_data_index( obs , data_index_string ); - - - if (error_covar_file != NULL) { - FILE * stream = util_fopen( error_covar_file , "r"); - - obs->error_covar = matrix_alloc( obs->obs_size , obs->obs_size ); - matrix_fscanf_data( obs->error_covar , false , stream ); - - fclose( stream ); - } else - obs->error_covar = NULL; - - return obs; -} - - - -static void gen_obs_assert_data_size(const gen_obs_type * gen_obs, const gen_data_type * gen_data) { - if (gen_obs->observe_all_data) { - int data_size = gen_data_get_size( gen_data ); - if (gen_obs->obs_size != data_size) - util_abort("%s: size mismatch: Observation: %s:%d Data: %s:%d \n" , __func__ , gen_obs->obs_key , gen_obs->obs_size , gen_data_get_key( gen_data ) , data_size); - - } - /* - Else the user has explicitly entered indices to observe in the - gen_data instances, and we just have to trust them (however the - gen_data_iget() does a range check. - */ -} - - -double gen_obs_chi2(const gen_obs_type * gen_obs , const gen_data_type * gen_data, node_id_type node_id) { - gen_obs_assert_data_size(gen_obs , gen_data); - { - const bool_vector_type * forward_model_active = gen_data_config_get_active_mask( gen_obs->data_config ); - double sum_chi2 = 0; - for (int iobs = 0; iobs < gen_obs->obs_size; iobs++) { - int data_index = gen_obs->data_index_list[iobs]; - if (forward_model_active && (bool_vector_iget( forward_model_active , data_index ) == false)) - continue; /* Forward model has deactivated this index - just continue. */ - { - double d = gen_data_iget_double( gen_data , data_index); - double x = (d - gen_obs->obs_data[iobs]) / gen_obs->obs_std[iobs]; - sum_chi2 += x*x; - } - } - return sum_chi2; - } -} - - - -void gen_obs_measure(const gen_obs_type * gen_obs , const gen_data_type * gen_data , node_id_type node_id , meas_data_type * meas_data, const active_list_type * __active_list) { - gen_obs_assert_data_size(gen_obs , gen_data); - { - int active_size = active_list_get_active_size( __active_list , gen_obs->obs_size ); - meas_block_type * meas_block = meas_data_add_block( meas_data , gen_obs->obs_key , node_id.report_step , active_size ); - active_mode_type active_mode = active_list_get_mode( __active_list ); - const bool_vector_type * forward_model_active = gen_data_config_get_active_mask( gen_obs->data_config ); - - int iobs; - if (active_mode == ALL_ACTIVE) { - for (iobs = 0; iobs < gen_obs->obs_size; iobs++) { - int data_index = gen_obs->data_index_list[iobs] ; - - if (forward_model_active != NULL) { - if (!bool_vector_iget( forward_model_active , data_index )) - continue; /* Forward model has deactivated this index - just continue. */ - } - - meas_block_iset( meas_block , node_id.iens , iobs , gen_data_iget_double( gen_data , data_index )); - } - } else if ( active_mode == PARTLY_ACTIVE) { - const int * active_list = active_list_get_active( __active_list ); - int index; - - for (index = 0; index < active_size; index++) { - iobs = active_list[ index ]; - int data_index = gen_obs->data_index_list[iobs] ; - if (forward_model_active != NULL) { - if (!bool_vector_iget( forward_model_active , data_index )) - continue; /* Forward model has deactivated this index - just continue. */ - } - meas_block_iset( meas_block , node_id.iens , index , gen_data_iget_double( gen_data , data_index )); - } - } - } -} - - - -void gen_obs_get_observations(gen_obs_type * gen_obs , obs_data_type * obs_data, enkf_fs_type * fs, int report_step , const active_list_type * __active_list) { - const bool_vector_type * forward_model_active = NULL; - if (gen_data_config_has_active_mask( gen_obs->data_config , fs, report_step)) { - gen_data_config_load_active( gen_obs->data_config , fs, report_step , true); - forward_model_active = gen_data_config_get_active_mask( gen_obs->data_config ); - } - - { - active_mode_type active_mode = active_list_get_mode( __active_list ); - int active_size = active_list_get_active_size( __active_list , gen_obs->obs_size ); - obs_block_type * obs_block = obs_data_add_block( obs_data , gen_obs->obs_key , active_size , NULL , false); - - if (active_mode == ALL_ACTIVE) { - for (int iobs = 0; iobs < gen_obs->obs_size; iobs++) - obs_block_iset( obs_block , iobs , gen_obs->obs_data[iobs] , IGET_SCALED_STD( gen_obs , iobs )); - - /* Setting some of the elements as missing, i.e. deactivated by the forward model. */ - if (forward_model_active != NULL) { - for (int iobs = 0; iobs < gen_obs->obs_size; iobs++) { - int data_index = gen_obs->data_index_list[ iobs ]; - if (!bool_vector_iget( forward_model_active , data_index )) - obs_block_iset_missing( obs_block , iobs ); - } - } - } else if (active_mode == PARTLY_ACTIVE) { - const int * active_list = active_list_get_active( __active_list ); - int active_size = active_list_get_active_size( __active_list , gen_obs->obs_size); - /* - There are three different indices active at the same time here: - - active_index : [0 ... active_size> - running over the size of - the current local observation. - - iobs : [0 ... size(obs)> - running over the complete size of - the observation node. - - data_index : The index in the data space corresponding to - the observation index iobs. - - */ - - for (int active_index = 0; active_index < active_size; active_index++) { - int iobs = active_list[active_index]; - obs_block_iset( obs_block , active_index , gen_obs->obs_data[iobs] , IGET_SCALED_STD( gen_obs , iobs )); - { - int data_index = gen_obs->data_index_list[ iobs ]; - if ((forward_model_active != NULL) && (!bool_vector_iget( forward_model_active , data_index ))) - obs_block_iset_missing( obs_block , active_index ); - } - } - } - } -} - - - -/** - In general the gen_obs observation vector can be smaller than the - gen_data field it is observing, i.e. we can have a situation like - this: - - Data Obs - ---- --- - - [ 6.0 ] ----\ - [ 2.0 ] \---> [ 6.3 ] - [ 3.0 ] ---------> [ 2.8 ] - [ 2.0 ] /---> [ 4.3 ] - [ 4.5 ] ----/ - - The situation here is as follows: - - 1. We have a gen data vector with five elements. - - 2. We have an observation vector of three elements, which observes - three of the elements in the gen_data vector, in this particular - case the data_index_list of the observation equals: [0 , 2 , 4]. - - Now when we want to look at the match of observation quality of the - last element in the observation vector it would be natural to use - the user_get key: "obs_key:2" - however this is an observation of - data element number 4, i.e. as seen from data context (when adding - observations to an ensemble plot) the natural indexing would be: - "data_key:4". - - - The function gen_obs_user_get_with_data_index() will do the - translation from data based indexing to observation based indexing, i.e. - - gen_obs_user_get_with_data_index("4") - - will do an inverse lookup of the '4' and further call - - gen_obs_user_get("2") - -*/ - - -void gen_obs_user_get(const gen_obs_type * gen_obs , const char * index_key , double * value , double * std , bool * valid) { - int index; - *valid = false; - - if (util_sscanf_int( index_key , &index)) { - if ((index >= 0) && (index < gen_obs->obs_size)) { - *valid = true; - *value = gen_obs->obs_data[ index ]; - *std = gen_obs->obs_std[ index ]; - } - } -} - - - -void gen_obs_user_get_with_data_index(const gen_obs_type * gen_obs , const char * index_key , double * value , double * std , bool * valid) { - if (gen_obs->observe_all_data) - /* The observation and data vectors are equally long - no reverse lookup necessary. */ - gen_obs_user_get(gen_obs , index_key , value , std , valid); - else { - *valid = false; - int data_index; - if (util_sscanf_int( index_key , &data_index )) { - int obs_index = 0; - do { - if (gen_obs->data_index_list[ obs_index ] == data_index) - /* Found it - will use the 'obs_index' value. */ - break; - - obs_index++; - } while (obs_index < gen_obs->obs_size); - if (obs_index < gen_obs->obs_size) { /* The reverse lookup succeeded. */ - *valid = true; - *value = gen_obs->obs_data[ obs_index ]; - *std = gen_obs->obs_std[ obs_index ]; - } - } - } -} - -void gen_obs_update_std_scale(gen_obs_type * gen_obs, double std_multiplier, const active_list_type * active_list) { - if (active_list_get_mode( active_list ) == ALL_ACTIVE) { - for (int i = 0; i < gen_obs->obs_size; i++) - gen_obs->std_scaling[i] = std_multiplier; - } else { - const int * active_index = active_list_get_active( active_list ); - int size = active_list_get_active_size( active_list , gen_obs->obs_size ); - for (int i=0; i < size; i++) { - int obs_index = active_index[i]; - gen_obs->std_scaling[ obs_index ] = std_multiplier; - } - } -} - - - -int gen_obs_get_size(const gen_obs_type * gen_obs){ - return gen_obs->obs_size; -} - -double gen_obs_iget_std(const gen_obs_type * gen_obs, int index){ - return gen_obs->obs_std[index]; -} - -double gen_obs_iget_std_scaling(const gen_obs_type * gen_obs, int index) { - return gen_obs->std_scaling[index]; -} - - -double gen_obs_iget_value(const gen_obs_type * gen_obs, int index){ - return gen_obs->obs_data[index]; -} - -int gen_obs_get_obs_index(const gen_obs_type * gen_obs, int index){ - if(index < 0 || index >= gen_obs->obs_size){ - util_abort("[Gen_Obs] Index out of bounds %d [0, %d]", index, gen_obs->obs_size - 1); - } - - if (gen_obs->observe_all_data){ - return index; - } else { - return gen_obs->data_index_list[index]; - } -} - - - -/*****************************************************************/ -UTIL_IS_INSTANCE_FUNCTION(gen_obs , GEN_OBS_TYPE_ID) -VOID_FREE(gen_obs) -VOID_GET_OBS(gen_obs) -VOID_MEASURE(gen_obs , gen_data) -VOID_USER_GET_OBS(gen_obs) -VOID_CHI2(gen_obs , gen_data) -VOID_UPDATE_STD_SCALE(gen_obs) diff --git a/ThirdParty/Ert/libenkf/src/gen_test.c b/ThirdParty/Ert/libenkf/src/gen_test.c deleted file mode 100644 index 6418c70160..0000000000 --- a/ThirdParty/Ert/libenkf/src/gen_test.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gen_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - - - - -int main(int argc , char **argv) { -} diff --git a/ThirdParty/Ert/libenkf/src/hook_manager.c b/ThirdParty/Ert/libenkf/src/hook_manager.c deleted file mode 100644 index f21254cb8e..0000000000 --- a/ThirdParty/Ert/libenkf/src/hook_manager.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'hook_manager.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include - -#define HOOK_MANAGER_NAME "HOOK MANAGER" -#define RUNPATH_LIST_FILE ".ert_runpath_list" -#define QC_WORKFLOW_NAME "QC WORKFLOW" -#define RUN_MODE_PRE_SIMULATION_NAME "PRE_SIMULATION" -#define RUN_MODE_POST_SIMULATION_NAME "POST_SIMULATION" -#define RUN_MODE_PRE_UPDATE_NAME "PRE_UPDATE" -#define RUN_MODE_POST_UPDATE_NAME "POST_UPDATE" - -struct hook_manager_struct { - vector_type * hook_workflow_list; /* vector of hook_workflow_type instances */ - runpath_list_type * runpath_list; - ert_workflow_list_type * workflow_list; - hash_type * input_context; - - - /* Deprecated stuff */ - hook_workflow_type * post_hook_workflow; /* This is the good old QC workflow, kept for backward compatibility, obsolete */ -}; - -hook_manager_type * hook_manager_alloc( ert_workflow_list_type * workflow_list ) { - hook_manager_type * hook_manager = util_malloc( sizeof * hook_manager ); - hook_manager->hook_workflow_list = vector_alloc_new(); - - hook_manager->workflow_list = workflow_list; - - hook_manager->runpath_list = runpath_list_alloc( NULL ); - hook_manager_set_runpath_list_file( hook_manager, NULL, RUNPATH_LIST_FILE ); - - hook_manager->input_context = hash_alloc(); - - return hook_manager; -} - - -void hook_manager_free( hook_manager_type * hook_manager ) { - runpath_list_free( hook_manager->runpath_list ); - vector_free( hook_manager->hook_workflow_list ); - hash_free( hook_manager->input_context ); - free( hook_manager ); -} - - - -void hook_manager_add_input_context( hook_manager_type * hook_manager, const char * key , const char * value) { - hash_insert_hash_owned_ref(hook_manager->input_context, key, util_alloc_string_copy(value), free); -} - - - -runpath_list_type * hook_manager_get_runpath_list( hook_manager_type * hook_manager ) { - return hook_manager->runpath_list; -} - - -static void hook_manager_add_workflow( hook_manager_type * hook_manager , const char * workflow_name , hook_run_mode_enum run_mode) { - if (ert_workflow_list_has_workflow( hook_manager->workflow_list , workflow_name) ){ - workflow_type * workflow = ert_workflow_list_get_workflow( hook_manager->workflow_list , workflow_name); - hook_workflow_type * hook = hook_workflow_alloc( workflow , run_mode ); - vector_append_owned_ref(hook_manager->hook_workflow_list, hook , hook_workflow_free__); - } - else { - fprintf(stderr, "** Warning: While hooking workflow: %s not recognized among the list of loaded workflows.", workflow_name); - } -} - - - -void hook_manager_init( hook_manager_type * hook_manager , const config_content_type * config_content) { - - /* Old stuff explicitly prefixed with QC */ - { - if (config_content_has_item( config_content , QC_WORKFLOW_KEY)) { - char * workflow_name; - const char * file_name = config_content_get_value_as_path(config_content , QC_WORKFLOW_KEY); - util_alloc_file_components( file_name , NULL , &workflow_name , NULL ); - workflow_type * workflow = ert_workflow_list_add_workflow( hook_manager->workflow_list , file_name , workflow_name); - if (workflow != NULL) { - hook_workflow_type * hook = hook_workflow_alloc( workflow , POST_SIMULATION ); - vector_append_owned_ref(hook_manager->hook_workflow_list, hook , hook_workflow_free__); - } - } - } - - - - if (config_content_has_item( config_content , HOOK_WORKFLOW_KEY)) { - for (int ihook = 0; ihook < config_content_get_occurences(config_content , HOOK_WORKFLOW_KEY); ihook++) { - const char * workflow_name = config_content_iget( config_content , HOOK_WORKFLOW_KEY, ihook , 0 ); - hook_run_mode_enum run_mode = hook_workflow_run_mode_from_name(config_content_iget(config_content , HOOK_WORKFLOW_KEY , ihook , 1)); - hook_manager_add_workflow( hook_manager , workflow_name , run_mode ); - } - } - - - if (config_content_has_item( config_content , RUNPATH_FILE_KEY)) - hook_manager_set_runpath_list_file( hook_manager, NULL, config_content_get_value( config_content , RUNPATH_FILE_KEY)); -} - - - -void hook_manager_add_config_items( config_parser_type * config ) { - config_schema_item_type * item; - - /* Old stuff - explicitly prefixed with QC. */ - { - item = config_add_schema_item( config , QC_PATH_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - config_install_message( config , QC_PATH_KEY , "The \'QC_PATH\' keyword is ignored."); - - - item = config_add_schema_item( config , QC_WORKFLOW_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , CONFIG_EXISTING_PATH ); - - config_install_message( config , QC_WORKFLOW_KEY , "The \'QC_WORKFLOW\' keyword is deprecated - use \'HOOK_WORKFLOW\' instead"); - } - - item = config_add_schema_item( config , HOOK_WORKFLOW_KEY , false ); - config_schema_item_set_argc_minmax(item , 2 , 2 ); - config_schema_item_iset_type( item , 0 , CONFIG_STRING ); - config_schema_item_iset_type( item , 1 , CONFIG_STRING ); - { - char ** argv = util_malloc( 4 * sizeof * argv ); - - argv[0] = RUN_MODE_PRE_SIMULATION_NAME; - argv[1] = RUN_MODE_POST_SIMULATION_NAME; - argv[2] = RUN_MODE_PRE_UPDATE_NAME; - argv[3] = RUN_MODE_POST_UPDATE_NAME; - config_schema_item_set_indexed_selection_set(item, 1, 4, (const char **) argv); - - free( argv ); - } - - item = config_add_schema_item( config , RUNPATH_FILE_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); -} - - -void hook_manager_export_runpath_list( const hook_manager_type * hook_manager ) { - runpath_list_fprintf( hook_manager->runpath_list ); -} - -const char * hook_manager_get_runpath_list_file( const hook_manager_type * hook_manager) { - return runpath_list_get_export_file( hook_manager->runpath_list ); -} - -static void hook_manager_set_runpath_list_file__( hook_manager_type * hook_manager , const char * runpath_list_file) { - runpath_list_set_export_file( hook_manager->runpath_list , runpath_list_file ); -} - -void hook_manager_set_runpath_list_file( hook_manager_type * hook_manager , const char * basepath, const char * filename) { - if (filename && util_is_abs_path( filename )) - hook_manager_set_runpath_list_file__( hook_manager , filename ); - else { - const char * file = RUNPATH_LIST_FILE; - - if (filename != NULL) - file = filename; - - char * file_with_path_prefix = NULL; - if (basepath != NULL) { - file_with_path_prefix = util_alloc_filename(basepath, file, NULL); - } - else - file_with_path_prefix = util_alloc_string_copy(file); - - { - char * absolute_path = util_alloc_abs_path(file_with_path_prefix); - hook_manager_set_runpath_list_file__( hook_manager , absolute_path ); - free( absolute_path ); - } - - free(file_with_path_prefix); - } -} - - -void hook_manager_run_workflows( const hook_manager_type * hook_manager , hook_run_mode_enum run_mode , void * self ) -{ - bool verbose = false; - for (int i=0; i < vector_get_size( hook_manager->hook_workflow_list ); i++) { - hook_workflow_type * hook_workflow = vector_iget( hook_manager->hook_workflow_list , i ); - if (hook_workflow_get_run_mode(hook_workflow) == run_mode) { - workflow_type * workflow = hook_workflow_get_workflow( hook_workflow ); - workflow_run( workflow, self , verbose , ert_workflow_list_get_context( hook_manager->workflow_list )); - /* - The workflow_run function will return a bool to indicate - success/failure, and in the case of error the function - workflow_get_last_error() can be used to get a config_error - object. - */ - } - } -} - -const hook_workflow_type * hook_manager_iget_hook_workflow(const hook_manager_type * hook_manager, int index){ - return vector_iget(hook_manager->hook_workflow_list, index); -} - -int hook_manager_get_size(const hook_manager_type * hook_manager){ - return vector_get_size(hook_manager->hook_workflow_list); -} - - -/*****************************************************************/ -/* Deprecated stuff */ -/*****************************************************************/ - - - -bool hook_manager_run_post_hook_workflow( const hook_manager_type * hook_manager , void * self) { - const char * export_file = runpath_list_get_export_file( hook_manager->runpath_list ); - if (!util_file_exists( export_file )) - fprintf(stderr,"** Warning: the file:%s with a list of runpath directories was not found - workflow will probably fail.\n" , export_file); - - return hook_workflow_run_workflow(hook_manager->post_hook_workflow, hook_manager->workflow_list, self); -} - - - diff --git a/ThirdParty/Ert/libenkf/src/hook_workflow.c b/ThirdParty/Ert/libenkf/src/hook_workflow.c deleted file mode 100644 index 227f038a70..0000000000 --- a/ThirdParty/Ert/libenkf/src/hook_workflow.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'hook_workflow.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include - -#include - -#include - -#include -#include - -#define RUN_MODE_PRE_SIMULATION_NAME "PRE_SIMULATION" -#define RUN_MODE_POST_SIMULATION_NAME "POST_SIMULATION" -#define RUN_MODE_PRE_UPDATE_NAME "PRE_UPDATE" -#define RUN_MODE_POST_UPDATE_NAME "POST_UPDATE" - -#define HOOK_WORKFLOW_TYPE_ID 7321780 - -struct hook_workflow_struct { - UTIL_TYPE_ID_DECLARATION; - hook_run_mode_enum run_mode; - workflow_type * workflow; -}; - - -static UTIL_SAFE_CAST_FUNCTION( hook_workflow , HOOK_WORKFLOW_TYPE_ID); - -hook_workflow_type * hook_workflow_alloc( workflow_type * workflow , hook_run_mode_enum run_mode ) { - hook_workflow_type * hook_workflow = util_malloc( sizeof * hook_workflow ); - UTIL_TYPE_ID_INIT( hook_workflow , HOOK_WORKFLOW_TYPE_ID); - hook_workflow->run_mode = run_mode; - hook_workflow->workflow = workflow; - return hook_workflow; -} - -void hook_workflow_free( hook_workflow_type * hook_workflow ) { - free( hook_workflow ); -} - -void hook_workflow_free__( void * arg ) { - hook_workflow_type * hook_workflow = hook_workflow_safe_cast( arg ); - hook_workflow_free( hook_workflow ); -} - - - -workflow_type* hook_workflow_get_workflow( const hook_workflow_type * hook_workflow ) { - return hook_workflow->workflow; -} - - -bool hook_workflow_run_workflow( const hook_workflow_type * hook_workflow, ert_workflow_list_type * workflow_list, void * self) { - bool verbose = false; - if (hook_workflow->workflow != NULL ) { - bool result = ert_workflow_list_run_workflow__( workflow_list, hook_workflow->workflow , verbose , self); - return result; - } - else - return false; -} - - -hook_run_mode_enum hook_workflow_run_mode_from_name( const char * run_mode ) { - hook_run_mode_enum mode; - if (strcmp( run_mode , RUN_MODE_PRE_SIMULATION_NAME) == 0) - mode = PRE_SIMULATION; - else if (strcmp( run_mode , RUN_MODE_POST_SIMULATION_NAME) == 0) - mode = POST_SIMULATION; - else if (strcmp( run_mode , RUN_MODE_PRE_UPDATE_NAME) == 0) - mode = PRE_UPDATE; - else if (strcmp( run_mode , RUN_MODE_POST_UPDATE_NAME) == 0) - mode = POST_UPDATE; - else { - util_abort("%s: unrecognized run mode :%s \n",__func__ , run_mode); - mode = -1; /* Dummy */ - } - return mode; -} - - -hook_run_mode_enum hook_workflow_get_run_mode( const hook_workflow_type * hook_workflow ){ - return hook_workflow->run_mode; -} - diff --git a/ThirdParty/Ert/libenkf/src/local_config.c b/ThirdParty/Ert/libenkf/src/local_config.c deleted file mode 100644 index 256216f5a9..0000000000 --- a/ThirdParty/Ert/libenkf/src/local_config.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/******************************************************************/ - -/* - - +-------------------------- local_updatestep_type ---------------------------------------+ - | | - | | - | +----------------- local_ministep_type --------------------------------------+ | - | | | | - | | / +--- local_dataset_type ---+ | | - | | | | PRESSURE | | | - | | | | SWAT | | | - | | | | SGAS | | | - | | | +--------------------------+ | | - | | +-- local_obsset_type ---+ | | | - | | | WWCT:OP_2 | | +--- local_dataset_type ---+ | | - | | | WGOR:OP_1 | | | MULTFLT1 | | | - | | | RFT:WELL1 | <------| | MULTFLT2 | | | - | | | RFT:WELL3 | | | MULTFLT3 | | | - | | | WWCT:WELLX | | +--------------------------+ | | - | | +------------------------+ | | | - | | | +--- local_dataset_type ---+ | | - | | | | RELPERM1 | | | - | | | | RELPERM2 | | | - | | | | RELPERM3 | | | - | | \ +--------------------------+ | | - | | | | - | +----------------------------------------------------------------------------+ | - | | - | | - | +----------------- local_ministep_type --------------------------------------+ | - | | | | - | | / +--- local_dataset_type ---+ | | - | | +-- local_obsset_type ---+ | | PERMX PORO | | | - | | | 4D Seismic | | | PRESSURE SWAT | | | - | | | Gravimetri | | | SGAS | | | - | | | | <------| +--------------------------+ | | - | | | | | | | - | | | | | +--- local_dataset_type ---+ | | - | | +------------------------+ | | MULTFLT1 | | | - | | | | MULTFLT2 | | | - | | | | MULTFLT3 | | | - | | \ +--------------------------+ | | - | | | | - | +----------------------------------------------------------------------------+ | - | | - +----------------------------------------------------------------------------------------+ - -This figure illustrates the different objects when configuring local -analysis: - -local_updatestep_type: This is is the top level configuration of the - updating at one timestep. In principle you can have different - updatestep configurations at the different timesteps, but it will - typically be identical for all the time steps. Observe that the - update at one time step can typically conist of several enkf - updates, this is handled by using several local_ministep. - -local_ministep_type: The ministep defines a collection of observations - and state/parameter variables which are mutually dependant on - eachother and should be updated together. The local_ministep will - consist of *ONE* local_obsset of observations, and one or more - local_dataset of data which should be updated. - -local_obsset_type: This is a collection of observation data; there is - exactly one local_obsset for each local_ministep. - -local_dataset_type: This is a collection of data/parameters which - should be updated together in the EnKF updating. - - -How the local_dataset_type is configured is quite important for the -core EnKF updating: - - 1. All the members in one local_dataset instance are serialized and - packed in the A-matrix together; i.e. in the example above the - parameters RELPERM1,RELPERM2 and RELPERM3 are updated in one go. - - 2. When using the standard EnKF the X matrix is calculated using - the actual data vectors, and the results will be identical if we - use one large local_dataset instance or several small. However - when using more advanced techniques where the A matrix is used - explicitly when calculating the update this will matter. - - 3. If you have not entered a local configuration explicitly the - default ALL_ACTIVE local configuration will be used. -*/ - - -struct local_config_struct { - local_updatestep_type * default_updatestep; /* A default report step returned if no particular report step has been installed for this time index. */ - hash_type * updatestep_storage; /* These three hash tables are the 'holding area' for the local_updatestep, */ - hash_type * ministep_storage; /* local_ministep instances. */ - hash_type * dataset_storage; - hash_type * obsdata_storage; -}; - - -/** - Instances of local_updatestep and local_ministep are allocated from - the local_config object, and then subsequently manipulated from the calling scope. -*/ - -static local_updatestep_type * local_config_alloc_updatestep( local_config_type * local_config , const char * key ) { - local_updatestep_type * updatestep = local_updatestep_alloc( key ); - hash_insert_hash_owned_ref( local_config->updatestep_storage , key , updatestep , local_updatestep_free__); - return updatestep; -} - - - -void local_config_clear( local_config_type * local_config ) { - local_config->default_updatestep = NULL; - hash_clear( local_config->updatestep_storage ); - hash_clear( local_config->ministep_storage ); - hash_clear( local_config->dataset_storage ); - hash_clear( local_config->obsdata_storage ); - local_config->default_updatestep = local_config_alloc_updatestep(local_config, "DEFAULT"); -} - - - - -local_config_type * local_config_alloc( ) { - local_config_type * local_config = util_malloc( sizeof * local_config ); - - local_config->default_updatestep = NULL; - local_config->updatestep_storage = hash_alloc(); - local_config->ministep_storage = hash_alloc(); - local_config->dataset_storage = hash_alloc(); - local_config->obsdata_storage = hash_alloc(); - - local_config_clear( local_config ); - return local_config; -} - - -void local_config_free(local_config_type * local_config) { - hash_free( local_config->updatestep_storage ); - hash_free( local_config->ministep_storage); - hash_free( local_config->dataset_storage); - hash_free( local_config->obsdata_storage); - free( local_config ); -} - -local_ministep_type * local_config_alloc_ministep( local_config_type * local_config , const char * key, analysis_module_type* analysis_module) { - local_ministep_type * ministep = local_ministep_alloc( key, analysis_module ); - hash_insert_hash_owned_ref( local_config->ministep_storage , key , ministep , local_ministep_free__); - return ministep; -} - -local_obsdata_type * local_config_alloc_obsdata( local_config_type * local_config , const char * obsdata_name ) { - if (local_config_has_obsdata(local_config, obsdata_name)) - util_abort("%s: tried to add existing obsdata node key:%s \n",__func__ , obsdata_name); - - local_obsdata_type * obsdata = local_obsdata_alloc( obsdata_name ); - hash_insert_hash_owned_ref( local_config->obsdata_storage , obsdata_name , obsdata , local_obsdata_free__); - return obsdata; -} - -bool local_config_has_obsdata( const local_config_type * local_config , const char * key) { - return hash_has_key( local_config->obsdata_storage , key ); -} - - -local_dataset_type * local_config_alloc_dataset( local_config_type * local_config , const char * key ) { - if (local_config_has_dataset(local_config, key)) - util_abort("%s: tried to add existing dataset node key:%s \n",__func__ , key); - - local_dataset_type * dataset = local_dataset_alloc( key ); - hash_insert_hash_owned_ref( local_config->dataset_storage , key , dataset , local_dataset_free__); - return dataset; -} - -bool local_config_has_dataset( const local_config_type * local_config , const char * key) { - return hash_has_key( local_config->dataset_storage , key ); -} - - -local_dataset_type * local_config_alloc_dataset_copy( local_config_type * local_config , const char * src_key , const char * target_key) { - local_dataset_type * src_dataset = hash_get( local_config->dataset_storage , src_key ); - local_dataset_type * copy_dataset = local_dataset_alloc_copy( src_dataset , target_key ); - - hash_insert_hash_owned_ref( local_config->dataset_storage , target_key , copy_dataset , local_dataset_free__); - return copy_dataset; -} - - -local_obsdata_type * local_config_alloc_obsdata_copy( local_config_type * local_config , const char * src_key , const char * target_key) { - local_obsdata_type * src_obsdata = hash_get( local_config->obsdata_storage , src_key ); - local_obsdata_type * copy_obsdata = local_obsdata_alloc_copy( src_obsdata , target_key ); - - hash_insert_hash_owned_ref( local_config->obsdata_storage , target_key , copy_obsdata , local_obsdata_free__); - return copy_obsdata; -} - - -local_ministep_type * local_config_get_ministep( const local_config_type * local_config , const char * key) { - local_ministep_type * ministep = hash_get( local_config->ministep_storage , key ); - return ministep; -} - - -local_obsdata_type * local_config_get_obsdata( const local_config_type * local_config , const char * key) { - local_obsdata_type * obsdata = hash_get( local_config->obsdata_storage , key ); - return obsdata; -} - -local_dataset_type * local_config_get_dataset( const local_config_type * local_config , const char * key) { - local_dataset_type * dataset = hash_get( local_config->dataset_storage , key ); - return dataset; -} - -local_ministep_type * local_config_alloc_ministep_copy( local_config_type * local_config , const char * src_key , const char * new_key) { - local_ministep_type * src_step = hash_get( local_config->ministep_storage , src_key ); - local_ministep_type * new_step = local_ministep_alloc_copy( src_step , new_key ); - hash_insert_hash_owned_ref( local_config->ministep_storage , new_key , new_step , local_ministep_free__); - return new_step; -} - - - -local_updatestep_type * local_config_get_updatestep( const local_config_type * local_config) { - local_updatestep_type * updatestep = local_config->default_updatestep; - - if (updatestep == NULL) - util_exit("%s: fatal error. No report step information for step:%d - and no default \n",__func__ , index); - - return updatestep; -} - - -void local_config_summary_fprintf( const local_config_type * local_config , const char * config_file) { - - FILE * stream = util_mkdir_fopen( config_file , "w"); - - const local_updatestep_type * updatestep = local_config_get_updatestep( local_config ); // There is only one update step, the default - { - hash_iter_type * hash_iter = hash_iter_alloc( local_config->ministep_storage ); - - while (!hash_iter_is_complete( hash_iter )) { - const local_ministep_type * ministep = hash_iter_get_next_value( hash_iter ); - - fprintf(stream , "UPDATE_STEP:%s,", local_updatestep_get_name(updatestep)); - - local_ministep_summary_fprintf( ministep , stream); - - } - - hash_iter_free( hash_iter ); - } - - fclose( stream ); -} diff --git a/ThirdParty/Ert/libenkf/src/local_context.c b/ThirdParty/Ert/libenkf/src/local_context.c deleted file mode 100644 index bb2ac13648..0000000000 --- a/ThirdParty/Ert/libenkf/src/local_context.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_context.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include - -#include -#include -#include - -#include - -#include - -struct local_context_struct { - hash_type * ecl_regions; - hash_type * files; - hash_type * polygons; - hash_type * grids; - hash_type * surfaces; - hash_type * surface_regions; -}; - - - -local_context_type * local_context_alloc( const ecl_grid_type * ecl_grid ) { - local_context_type * context = util_malloc( sizeof * context ); - context->surface_regions = hash_alloc(); - context->ecl_regions = hash_alloc(); - context->files = hash_alloc(); - context->polygons = hash_alloc(); - context->grids = hash_alloc(); - context->surfaces = hash_alloc(); - - hash_insert_ref( context->grids , GLOBAL_GRID , ecl_grid ); - return context; -} - - -void local_context_free( local_context_type * context) { - hash_free( context->ecl_regions ); - hash_free( context->files ); - hash_free( context->polygons ); - hash_free( context->grids ); - hash_free( context->surfaces ); - hash_free( context->surface_regions ); -} - - - -ecl_region_type * local_context_get_ecl_region( local_context_type * context , const char * region_name) { - return hash_get( context->ecl_regions , region_name ); -} - -void local_context_create_ecl_region( local_context_type * context , const char * grid_name , const char * region_name , bool preselect ) { - ecl_grid_type * grid = hash_get( context->grids , grid_name); - ecl_region_type * new_region = ecl_region_alloc( grid , preselect ); - hash_insert_hash_owned_ref( context->ecl_regions , region_name , new_region , ecl_region_free__ ); -} - -/*************************/ - -geo_region_type * local_context_get_surface_region( local_context_type * context , const char * region_name) { - return hash_get( context->surface_regions , region_name ); -} - -void local_context_create_surface_region( local_context_type * context , const char * surface_name , const char * region_name , bool preselect ) { - geo_surface_type * base_surface = hash_get( context->surfaces , surface_name ); - geo_region_type * new_region = geo_region_alloc( geo_surface_get_pointset( base_surface ) , preselect ); - hash_insert_hash_owned_ref( context->surface_regions , region_name , new_region , geo_region_free__ ); -} - -/*************************/ - -void local_context_load_file( local_context_type * context , const char * filename , const char * file_key ) { - ecl_file_type * ecl_file = ecl_file_open( filename , 0); - hash_insert_hash_owned_ref( context->files , file_key , ecl_file , ecl_file_free__); -} - - -ecl_file_type * local_context_get_file( local_context_type * context , const char * file_key ) { - return hash_get( context->files , file_key ); -} - -/*************************/ - -static void local_context_add_polygon__( local_context_type * context , const char * polygon_name , geo_polygon_type * polygon) { - hash_insert_hash_owned_ref( context->polygons , polygon_name , polygon , geo_polygon_free__); -} - -void local_context_add_polygon( local_context_type * context , const char * polygon_name ) { - geo_polygon_type * polygon = geo_polygon_alloc( polygon_name ); - local_context_add_polygon__(context , polygon_name , polygon ); -} - -void local_context_load_polygon( local_context_type * context , const char * polygon_name , const char * polygon_file) { - geo_polygon_type * polygon = geo_polygon_fload_alloc_irap( polygon_file ); - hash_insert_hash_owned_ref( context->polygons , polygon_name , polygon , geo_polygon_free__); -} - - -geo_polygon_type * local_context_get_polygon( local_context_type * context , const char * polygon_name ) { - return hash_get( context->polygons , polygon_name ); -} - -/*************************/ - -void local_context_load_surface( local_context_type * context , const char * surface_name , const char * surface_file) { - geo_surface_type * surface = geo_surface_fload_alloc_irap( surface_file , true ); - hash_insert_hash_owned_ref( context->surfaces , surface_name , surface , geo_surface_free__); -} - -geo_surface_type * local_context_get_surface( local_context_type * context , const char * surface_name) { - return hash_get( context->surfaces , surface_name ); -} diff --git a/ThirdParty/Ert/libenkf/src/local_dataset.c b/ThirdParty/Ert/libenkf/src/local_dataset.c deleted file mode 100644 index a6f44bb4a3..0000000000 --- a/ThirdParty/Ert/libenkf/src/local_dataset.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_dataset.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - - -#define LOCAL_DATASET_TYPE_ID 6615409 - -struct local_dataset_struct { - UTIL_TYPE_ID_DECLARATION; - char * name; - hash_type * nodes; /* A hash table indexed by node keys - each element is an active_list instance. */ -}; - - - -UTIL_SAFE_CAST_FUNCTION(local_dataset , LOCAL_DATASET_TYPE_ID) -UTIL_IS_INSTANCE_FUNCTION(local_dataset , LOCAL_DATASET_TYPE_ID) - - -local_dataset_type * local_dataset_alloc( const char * name ) { - local_dataset_type * dataset = util_malloc( sizeof * dataset); - - UTIL_TYPE_ID_INIT( dataset , LOCAL_DATASET_TYPE_ID ); - dataset->nodes = hash_alloc(); - dataset->name = util_alloc_string_copy( name ); - - return dataset; -} - -local_dataset_type * local_dataset_alloc_copy( local_dataset_type * src_dataset , const char * copy_name ) { - local_dataset_type * copy_dataset = local_dataset_alloc( copy_name ); - hash_iter_type * node_iter = hash_iter_alloc( src_dataset->nodes ); - - while (!hash_iter_is_complete( node_iter )) { - const char * key = hash_iter_get_next_key( node_iter ); - active_list_type * active_list = active_list_alloc_copy( hash_get( src_dataset->nodes , key ) ); - hash_insert_hash_owned_ref( copy_dataset->nodes , key , active_list , active_list_free__); - } - - hash_iter_free( node_iter ); - return copy_dataset; -} - - -void local_dataset_free( local_dataset_type * dataset ) { - util_safe_free(dataset->name); - hash_free( dataset->nodes ); - free( dataset ); -} - -void local_dataset_free__( void * arg ) { - local_dataset_type * local_dataset = local_dataset_safe_cast( arg ); - local_dataset_free( local_dataset ); -} - -const char * local_dataset_get_name( const local_dataset_type * dataset) { - return dataset->name; -} - - - -void local_dataset_add_node(local_dataset_type * dataset, const char *node_key) { - if (hash_has_key( dataset->nodes , node_key )) - util_abort("%s: tried to add existing node key:%s \n",__func__ , node_key); - - hash_insert_hash_owned_ref( dataset->nodes , node_key , active_list_alloc( ALL_ACTIVE ) , active_list_free__); -} - -bool local_dataset_has_key(const local_dataset_type * dataset, const char * key) { - return hash_has_key( dataset->nodes , key ); -} - - -void local_dataset_del_node( local_dataset_type * dataset , const char * node_key) { - hash_del( dataset->nodes , node_key ); -} - - -void local_dataset_clear( local_dataset_type * dataset) { - hash_clear( dataset->nodes ); -} - - -active_list_type * local_dataset_get_node_active_list(const local_dataset_type * dataset , const char * node_key ) { - return hash_get( dataset->nodes , node_key ); /* Fails hard if you do not have the key ... */ -} - -stringlist_type * local_dataset_alloc_keys( const local_dataset_type * dataset ) { - return hash_alloc_stringlist( dataset->nodes ); -} - -void local_dataset_summary_fprintf( const local_dataset_type * dataset , FILE * stream) { -{ - hash_iter_type * data_iter = hash_iter_alloc( dataset->nodes ); - while (!hash_iter_is_complete( data_iter )) { - const char * data_key = hash_iter_get_next_key( data_iter ); - fprintf(stream , "NAME OF DATA:%s,", data_key ); - - active_list_type * active_list = hash_get( dataset->nodes , data_key ); - active_list_summary_fprintf( active_list , local_dataset_get_name(dataset) , data_key , stream); - } - hash_iter_free( data_iter ); - } -} - - -int local_dataset_get_size( const local_dataset_type * dataset ) { - return hash_get_size( dataset->nodes ); -} - diff --git a/ThirdParty/Ert/libenkf/src/local_ministep.c b/ThirdParty/Ert/libenkf/src/local_ministep.c deleted file mode 100644 index 500ee47eaa..0000000000 --- a/ThirdParty/Ert/libenkf/src/local_ministep.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_ministep.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -/** - This file implements a 'ministep' configuration for active / - inactive observations and parameters for ONE enkf update. Observe - that the updating at one report step can consist of several - socalled ministeps, i.e. first the northern part of the field with - the relevant observations, and then the southern part. - - The implementation, in local_ministep_type, is quite simple, it - only contains the keys for the observations and nodes, with an - accompanying pointer to an active_list instance which denotes the - active indices. Observe that this implementation offers no access - to the internals of the underlying enkf_node / obs_node objects. -*/ - - -#define LOCAL_MINISTEP_TYPE_ID 661066 - - - - -struct local_ministep_struct { - UTIL_TYPE_ID_DECLARATION; - char * name; /* A name used for this ministep - string is also used as key in a hash table holding this instance. */ - hash_type * datasets; /* A hash table of local_dataset_type instances - indexed by the name of the datasets. */ - local_obsdata_type * observations; - analysis_module_type * analysis_module; -}; - - -/** - Observe there is no link between the instances here and the real - observations/nodes (apart from the key in the hash). -*/ - -UTIL_SAFE_CAST_FUNCTION(local_ministep , LOCAL_MINISTEP_TYPE_ID) -UTIL_IS_INSTANCE_FUNCTION(local_ministep , LOCAL_MINISTEP_TYPE_ID) - -local_ministep_type * local_ministep_alloc(const char * name, analysis_module_type* analysis_module) { - local_ministep_type * ministep = util_malloc( sizeof * ministep ); - - ministep->name = util_alloc_string_copy( name ); - - char* obsdata_name = "OBSDATA_"; - char* result = malloc(strlen(obsdata_name)+strlen(name)+1); - strcpy(result, obsdata_name); - strcat(result, name); - ministep->observations = local_obsdata_alloc(result); - - - ministep->datasets = hash_alloc(); - ministep->analysis_module = analysis_module; - UTIL_TYPE_ID_INIT( ministep , LOCAL_MINISTEP_TYPE_ID); - - return ministep; -} - - -local_ministep_type * local_ministep_alloc_copy( const local_ministep_type * src , const char * name) { - //local_ministep_type * new = local_ministep_alloc( name ); - //{ - // hash_iter_type * obs_iter = hash_iter_alloc( src->observations ); - // while (!hash_iter_is_complete( obs_iter )) { - // const char * obs_key = hash_iter_get_next_key( obs_iter ); - // active_list_type * active_list_copy = active_list_alloc_copy( hash_get( src->observations , obs_key) ); - // hash_insert_hash_owned_ref( new->observations , obs_key , active_list_copy , active_list_free__); - // } - //} - // - //{ - // hash_iter_type * nodeset_iter = hash_iter_alloc( src->datasets ); - // while (!hash_iter_is_complete( nodeset_iter )) { - // const char * nodeset_key = hash_iter_get_next_key( nodeset_iter ); - // local_nodeset_type * new_nodeset = local_nodeset_alloc_copy( hash_get( src->datasets , nodeset_key )); - // hash_insert_ref( new->datasets , nodeset_key , new_nodeset ); - // } - //} - // - //return new; - return NULL; -} - - - -void local_ministep_free(local_ministep_type * ministep) { - free(ministep->name); - hash_free( ministep->datasets ); - local_obsdata_free(ministep->observations); - free( ministep ); -} - - -void local_ministep_free__(void * arg) { - local_ministep_type * ministep = local_ministep_safe_cast( arg ); - local_ministep_free( ministep ); -} - - - - - -/** - When adding observations and update nodes here observe the following: - - 1. The thing will fail hard if you try to add a node/obs which is - already in the hash table. - - 2. The newly added elements will be assigned an active_list - instance with mode ALL_ACTIVE. -*/ - - - -void local_ministep_add_dataset( local_ministep_type * ministep , const local_dataset_type * dataset) { - hash_insert_ref( ministep->datasets , local_dataset_get_name( dataset ) , dataset ); -} - -void local_ministep_add_obsdata( local_ministep_type * ministep , local_obsdata_type * obsdata) { - if (ministep->observations == NULL) - ministep->observations = obsdata; - else { // Add nodes from input observations to existing observations - int iobs; - for (iobs = 0; iobs < local_obsdata_get_size( obsdata ); iobs++) { - local_obsdata_node_type * obs_node = local_obsdata_iget( obsdata , iobs ); - local_obsdata_node_type * new_node = local_obsdata_node_alloc_copy(obs_node); - local_ministep_add_obsdata_node(ministep, new_node); - } - } -} - -void local_ministep_add_obsdata_node( local_ministep_type * ministep , local_obsdata_node_type * obsdatanode) { - local_obsdata_type * obsdata = local_ministep_get_obsdata(ministep); - local_obsdata_add_node(obsdata, obsdatanode); -} - -bool local_ministep_has_dataset( const local_ministep_type * ministep, const char * dataset_name) { - return hash_has_key( ministep->datasets, dataset_name ); -} - -int local_ministep_get_num_dataset( const local_ministep_type * ministep ) { - return hash_get_size( ministep->datasets ); -} - -local_dataset_type * local_ministep_get_dataset( const local_ministep_type * ministep, const char * dataset_name) { - return hash_get( ministep->datasets, dataset_name ); -} - -local_obsdata_type * local_ministep_get_obsdata( const local_ministep_type * ministep ) { - return ministep->observations; -} - -const char * local_ministep_get_name( const local_ministep_type * ministep ) { - return ministep->name; -} - -/*****************************************************************/ - -hash_iter_type * local_ministep_alloc_dataset_iter( const local_ministep_type * ministep ) { - return hash_iter_alloc( ministep->datasets ); -} - -/*****************************************************************/ - -/* - The keys referenced in the local_ministep_alloc_data_keys() and - local_ministep_has_data_key() are the underlying *enkf_node* keys - - not the keys used to index the local_datasets managed by this - local_ministep. -*/ - -stringlist_type * local_ministep_alloc_data_keys( const local_ministep_type * ministep ) { - stringlist_type * keys = stringlist_alloc_new(); - { - hash_iter_type * dataset_iter = hash_iter_alloc( ministep->datasets ); - while (!hash_iter_is_complete( dataset_iter )) { - const local_dataset_type * dataset = hash_iter_get_next_value( dataset_iter ); - stringlist_type * node_keys = local_dataset_alloc_keys( dataset ); - for (int i=0; i < stringlist_get_size( node_keys ); i++) { - const char * data_key = stringlist_iget( node_keys , i ); - if (!stringlist_contains(keys , data_key )) - stringlist_append_copy( keys , data_key ); - } - stringlist_free( node_keys ); - } - hash_iter_free( dataset_iter ); - } - return keys; -} - - -bool local_ministep_has_data_key(const local_ministep_type * ministep , const char * key) { - bool has_key = false; - { - hash_iter_type * dataset_iter = hash_iter_alloc( ministep->datasets ); - - while (true) { - const local_dataset_type * dataset = hash_iter_get_next_value( dataset_iter ); - if (dataset) { - if (local_dataset_has_key( dataset , key)) { - has_key = true; - break; - } - } else - break; - } - - hash_iter_free( dataset_iter ); - } - return has_key; -} - -bool local_ministep_has_analysis_module( const local_ministep_type * ministep){ - return ministep->analysis_module != NULL; -} - -analysis_module_type* local_ministep_get_analysis_module( const local_ministep_type * ministep ){ - return ministep->analysis_module; -} - -void local_ministep_summary_fprintf( const local_ministep_type * ministep , FILE * stream) { - - fprintf(stream , "MINISTEP:%s,", ministep->name); - - { - /* Dumping all the DATASET instances. */ - { - hash_iter_type * dataset_iter = hash_iter_alloc( ministep->datasets ); - while (!hash_iter_is_complete( dataset_iter )) { - const local_dataset_type * dataset = hash_iter_get_next_value( dataset_iter ); - local_dataset_summary_fprintf(dataset, stream); - } - hash_iter_free( dataset_iter ); - } - - /* Only one OBSDATA */ - local_obsdata_type * obsdata = local_ministep_get_obsdata(ministep); - local_obsdata_summary_fprintf( obsdata , stream); - fprintf(stream, "\n"); - } -} - - diff --git a/ThirdParty/Ert/libenkf/src/local_obsdata.c b/ThirdParty/Ert/libenkf/src/local_obsdata.c deleted file mode 100644 index 4b20d242f8..0000000000 --- a/ThirdParty/Ert/libenkf/src/local_obsdata.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'local_obsdata.c' - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include -#include -#include -#include - -#include -#include - - -#define LOCAL_OBSDATA_TYPE_ID 86331309 - -struct local_obsdata_struct { - UTIL_TYPE_ID_DECLARATION; - hash_type * nodes_map; - vector_type * nodes_list; - char * name; -}; - - - -UTIL_IS_INSTANCE_FUNCTION( local_obsdata , LOCAL_OBSDATA_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION( local_obsdata , LOCAL_OBSDATA_TYPE_ID ) - -local_obsdata_type * local_obsdata_alloc( const char * name) { - local_obsdata_type * data = util_malloc( sizeof * data ); - UTIL_TYPE_ID_INIT( data , LOCAL_OBSDATA_TYPE_ID ); - data->nodes_list = vector_alloc_new(); - data->nodes_map = hash_alloc(); - data->name = util_alloc_string_copy( name ); - return data; -} - - - -local_obsdata_type * local_obsdata_alloc_wrapper( local_obsdata_node_type * node ) { - local_obsdata_type * data = local_obsdata_alloc( local_obsdata_node_get_key( node )); - local_obsdata_add_node( data , node ); - return data; -} - - -local_obsdata_type * local_obsdata_alloc_copy( const local_obsdata_type * src, const char * target_key) { - local_obsdata_type * target = local_obsdata_alloc( target_key ); - int i; - for (i=0; i < local_obsdata_get_size( src ); i++ ) { - const local_obsdata_node_type * src_node = local_obsdata_iget( src , i ); - local_obsdata_node_type * target_node = local_obsdata_node_alloc_copy( src_node ); - local_obsdata_add_node( target , target_node ); - } - return target; -} - - - -void local_obsdata_free( local_obsdata_type * data ) { - vector_free( data->nodes_list ); - hash_free( data->nodes_map ); - free( data->name ); - free( data ); -} - -void local_obsdata_free__( void * arg) { - local_obsdata_type * data = local_obsdata_safe_cast( arg ); - return local_obsdata_free( data ); -} - - -const char * local_obsdata_get_name( const local_obsdata_type * data) { - return data->name; -} - - -int local_obsdata_get_size( const local_obsdata_type * data ) { - return vector_get_size( data->nodes_list ); -} - -/* - The @data instance will assume ownership of the node; i.e. calling - scope should NOT call local_obsdata_node_free(). -*/ - -bool local_obsdata_add_node( local_obsdata_type * data , local_obsdata_node_type * node ) { - const char * key = local_obsdata_node_get_key( node ); - if (local_obsdata_has_node(data , key)) - return false; - else { - vector_append_owned_ref( data->nodes_list , node , local_obsdata_node_free__ ); - hash_insert_ref( data->nodes_map , key , node ); - return true; - } -} - - void local_obsdata_del_node( local_obsdata_type * data , const char * key) { - local_obsdata_node_type * node = local_obsdata_get( data , key ); - int index = vector_find( data->nodes_list , node ); - - hash_del( data->nodes_map , key ); - vector_idel( data->nodes_list , index ); -} - - - void local_obsdata_clear( local_obsdata_type * data ) { - hash_clear( data->nodes_map ); - vector_clear( data->nodes_list ); - } - - -local_obsdata_node_type * local_obsdata_iget( const local_obsdata_type * data , int index) { - return vector_iget( data->nodes_list , index ); -} - - -local_obsdata_node_type * local_obsdata_get( const local_obsdata_type * data , const char * key) { - return hash_get( data->nodes_map , key ); -} - - -bool local_obsdata_has_node( const local_obsdata_type * data , const char * key) { - return hash_has_key( data->nodes_map , key ); -} - -void local_obsdata_reset_tstep_list( local_obsdata_type * data , const int_vector_type * step_list) { - int i; - for (i=0; i < local_obsdata_get_size( data ); i++ ) { - local_obsdata_node_type * node = local_obsdata_iget( data , i ); - local_obsdata_node_reset_tstep_list(node, step_list); - } -} - -active_list_type * local_obsdata_get_node_active_list(const local_obsdata_type * obsdata , const char * obs_key ) { - local_obsdata_node_type * obsdata_node = local_obsdata_get( obsdata , obs_key ); - active_list_type * active_list = local_obsdata_node_get_active_list( obsdata_node ); - return active_list; -} - -void local_obsdata_summary_fprintf( const local_obsdata_type * obsdata , FILE * stream) { - - fprintf(stream , "LOCAL OBSDATA NAME:%s,LOCAL OBSDATA SIZE:%d,", local_obsdata_get_name(obsdata), local_obsdata_get_size(obsdata) ); - - int i; - for (i = 0; i < local_obsdata_get_size( obsdata ); i++ ) { - local_obsdata_node_type * node = local_obsdata_iget( obsdata , i ); - const char * obs_key = local_obsdata_node_get_key(node); - fprintf(stream , "OBSERVATION:%s,", obs_key ); - } -} diff --git a/ThirdParty/Ert/libenkf/src/local_obsdata_node.c b/ThirdParty/Ert/libenkf/src/local_obsdata_node.c deleted file mode 100644 index ba4e207212..0000000000 --- a/ThirdParty/Ert/libenkf/src/local_obsdata_node.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'local_obsdata_node.c' - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include -#include -#include - -#include - -#define LOCAL_OBSDATA_NODE_TYPE_ID 84441309 - -struct local_obsdata_node_struct { - UTIL_TYPE_ID_DECLARATION; - char * obs_key; - active_list_type * active_list; - int_vector_type * tstep_list; - bool all_timestep_active; -}; - - - -UTIL_IS_INSTANCE_FUNCTION( local_obsdata_node , LOCAL_OBSDATA_NODE_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION( local_obsdata_node , LOCAL_OBSDATA_NODE_TYPE_ID ) - -static local_obsdata_node_type * local_obsdata_node_alloc__( const char * obs_key , bool all_timestep_active) { - local_obsdata_node_type * node = util_malloc( sizeof * node ); - UTIL_TYPE_ID_INIT( node , LOCAL_OBSDATA_NODE_TYPE_ID ); - node->obs_key = util_alloc_string_copy( obs_key ); - node->active_list = NULL; - node->tstep_list = NULL; - node->all_timestep_active = all_timestep_active; - return node; -} - - -local_obsdata_node_type * local_obsdata_node_alloc( const char * obs_key , bool all_timestep_active ) { - local_obsdata_node_type * node = local_obsdata_node_alloc__(obs_key , all_timestep_active); - - node->active_list = active_list_alloc( ); - node->tstep_list = int_vector_alloc(0,0); - - return node; -} - - -local_obsdata_node_type * local_obsdata_node_alloc_copy( const local_obsdata_node_type * src) { - local_obsdata_node_type * target = local_obsdata_node_alloc__( src->obs_key , src->all_timestep_active ); - - target->active_list = active_list_alloc_copy( src->active_list ); - target->tstep_list = int_vector_alloc_copy( src->tstep_list ); - - return target; -} - - - -void local_obsdata_node_copy_active_list( local_obsdata_node_type * node , const active_list_type * active_list) { - active_list_copy( node->active_list , active_list ); -} - - -const char * local_obsdata_node_get_key( const local_obsdata_node_type * node ) { - return node->obs_key; -} - - - -void local_obsdata_node_free( local_obsdata_node_type * node ) { - if (node->active_list) - active_list_free( node->active_list ); - - if (node->tstep_list) - int_vector_free( node->tstep_list ); - - free( node->obs_key ); - free( node ); -} - - - -void local_obsdata_node_free__( void * arg ) { - local_obsdata_node_type * node = local_obsdata_node_safe_cast( arg ); - local_obsdata_node_free( node ); -} - - -active_list_type * local_obsdata_node_get_active_list( const local_obsdata_node_type * node ) { - return node->active_list; -} - - -bool local_obsdata_node_tstep_active( const local_obsdata_node_type * node , int tstep ) { - if (node->all_timestep_active) - return true; - else - return local_obsdata_node_has_tstep( node , tstep ); -} - - - -/* - This a temporarary function to support the change local_obsset -> - local_obsdata; should eventually be removed. -*/ - -void local_obsdata_node_reset_tstep_list( local_obsdata_node_type * node , const int_vector_type * step_list) { - int_vector_free(node->tstep_list); - node->tstep_list = int_vector_alloc_copy( step_list ); - node->all_timestep_active = false; -} - - -bool local_obsdata_node_all_timestep_active( const local_obsdata_node_type * node) { - return node->all_timestep_active; -} - -/** - Observe that this function check for explicitly added timestep, - i.e. if the all_timestep_active flag is set to true this will - return false. -*/ - -bool local_obsdata_node_has_tstep( const local_obsdata_node_type * node , int tstep) { - const int_vector_type * tstep_list = node->tstep_list; - if (int_vector_index_sorted( tstep_list , tstep) == -1) - return false; - else - return true; -} - - -void local_obsdata_node_add_tstep( local_obsdata_node_type * node, int tstep) { - if (!local_obsdata_node_has_tstep( node , tstep)) { - - if (int_vector_size( node->tstep_list )) { - int last = int_vector_get_last( node->tstep_list ); - int_vector_append( node->tstep_list , tstep ); - if (tstep < last) - int_vector_sort( node->tstep_list); - } else - int_vector_append( node->tstep_list , tstep ); - - node->all_timestep_active = false; - } -} - - - - -void local_obsdata_node_add_range( local_obsdata_node_type * node, int step1 , int step2) { - int tstep; - for (tstep = step1; tstep <= step2; tstep++) - local_obsdata_node_add_tstep( node , tstep ); -} - -void local_obsdata_node_set_all_timestep_active( local_obsdata_node_type * node, bool flag) { - node->all_timestep_active = flag; -} diff --git a/ThirdParty/Ert/libenkf/src/local_updatestep.c b/ThirdParty/Ert/libenkf/src/local_updatestep.c deleted file mode 100644 index ba0f8eba19..0000000000 --- a/ThirdParty/Ert/libenkf/src/local_updatestep.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_updatestep.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include - -/** - One enkf update is described/configured by the data structure in - local_ministep.c. This file implements a local report_step, which - is a collection of ministeps - in many cases a local_updatestep will - only consist of one single local_ministep; but in principle it can - contain several. -*/ - -#define LOCAL_UPDATESTEP_TYPE_ID 77159 - -struct local_updatestep_struct { - UTIL_TYPE_ID_DECLARATION; - char * name; - vector_type * ministep; -}; - - - -UTIL_SAFE_CAST_FUNCTION(local_updatestep , LOCAL_UPDATESTEP_TYPE_ID) - - -local_updatestep_type * local_updatestep_alloc( const char * name ) { - local_updatestep_type * updatestep = util_malloc( sizeof * updatestep ); - - UTIL_TYPE_ID_INIT( updatestep , LOCAL_UPDATESTEP_TYPE_ID ); - updatestep->name = util_alloc_string_copy( name ); - updatestep->ministep = vector_alloc_new(); - - return updatestep; -} - - -bool local_updatestep_has_data_key( const local_updatestep_type * update_step , const char * key) { - bool has_key = false; - for (int i = 0; i < vector_get_size( update_step->ministep ); i++) { - const local_ministep_type * ministep = vector_iget_const( update_step->ministep , i ); - if (local_ministep_has_data_key(ministep, key)) - has_key = true; - } - return has_key; -} - -/** - Observe that use_count values are not copied. -*/ -local_updatestep_type * local_updatestep_alloc_copy( const local_updatestep_type * src , const char * name ) { - local_updatestep_type * new = local_updatestep_alloc( name ); - for (int i = 0; i < vector_get_size(src->ministep ); i++) - local_updatestep_add_ministep( new , vector_iget( src->ministep , i) ); - return new; -} - - -void local_updatestep_free( local_updatestep_type * updatestep) { - free( updatestep->name ); - vector_free( updatestep->ministep ); - free( updatestep ); -} - - -void local_updatestep_free__(void * arg) { - local_updatestep_type * updatestep = local_updatestep_safe_cast( arg ); - local_updatestep_free( updatestep ); -} - - -void local_updatestep_add_ministep( local_updatestep_type * updatestep , local_ministep_type * ministep) { - vector_append_ref( updatestep->ministep , ministep ); /* Observe that the vector takes NO ownership */ -} - - - -local_ministep_type * local_updatestep_iget_ministep( const local_updatestep_type * updatestep , int index) { - return vector_iget( updatestep->ministep , index ); -} - - -local_obsdata_type * local_updatestep_iget_obsdata( const local_updatestep_type * updatestep , int index) { - return local_ministep_get_obsdata( vector_iget( updatestep->ministep , index ) ); -} - - -int local_updatestep_get_num_ministep( const local_updatestep_type * updatestep) { - return vector_get_size( updatestep->ministep ); -} - -const char * local_updatestep_get_name( const local_updatestep_type * updatestep ) { - return updatestep->name; -} - - diff --git a/ThirdParty/Ert/libenkf/src/meas_data.c b/ThirdParty/Ert/libenkf/src/meas_data.c deleted file mode 100644 index 7abdf6b182..0000000000 --- a/ThirdParty/Ert/libenkf/src/meas_data.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'meas_data.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/** - See the file README.obs for ducumentation of the varios datatypes - involved with observations/measurement/+++. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#define MEAS_BLOCK_TYPE_ID 661936407 -#define MEAS_DATA_TYPE_ID 561000861 - - -struct meas_data_struct { - UTIL_TYPE_ID_DECLARATION; - int active_ens_size; - vector_type * data; - pthread_mutex_t data_mutex; - hash_type * blocks; - bool_vector_type * ens_mask; -}; - - -struct meas_block_struct { - UTIL_TYPE_ID_DECLARATION; - int active_ens_size; - int obs_size; - int ens_stride; - int obs_stride; - int data_size; - char * obs_key; - double * data; - bool * active; - bool stat_calculated; - const bool_vector_type * ens_mask; - int_vector_type * index_map; -}; - - -UTIL_SAFE_CAST_FUNCTION( meas_block , MEAS_BLOCK_TYPE_ID ) - - -/** - Observe that meas_block instance must be allocated with a correct - value for obs_size; it can not grow during use, and it does also - not count the number of elements added. - - Observe that the input argument @obs_size should be the total size - of the observation; if parts of the observation have been excluded - due to local analysis it should still be included in the @obs_size - value. -*/ - -meas_block_type * meas_block_alloc( const char * obs_key , const bool_vector_type * ens_mask , int obs_size) { - meas_block_type * meas_block = util_malloc( sizeof * meas_block ); - UTIL_TYPE_ID_INIT( meas_block , MEAS_BLOCK_TYPE_ID ); - meas_block->active_ens_size = bool_vector_count_equal( ens_mask , true ); - meas_block->ens_mask = ens_mask; - meas_block->obs_size = obs_size; - meas_block->obs_key = util_alloc_string_copy( obs_key ); - meas_block->data = util_calloc( (meas_block->active_ens_size + 2) * obs_size , sizeof * meas_block->data ); - meas_block->active = util_calloc( obs_size , sizeof * meas_block->active ); - meas_block->ens_stride = 1; - meas_block->obs_stride = meas_block->active_ens_size + 2; - meas_block->data_size = (meas_block->active_ens_size + 2) * obs_size; - meas_block->index_map = bool_vector_alloc_active_index_list( meas_block->ens_mask , -1); - { - int i; - for (i=0; i < obs_size; i++) - meas_block->active[i] = false; - } - meas_block->stat_calculated = false; - return meas_block; -} - -static void meas_block_fprintf( const meas_block_type * meas_block , FILE * stream) { - int iens; - int iobs; - for (iobs = 0; iobs < meas_block->obs_size; iobs++) { - for (iens = 0; iens < meas_block->active_ens_size; iens++) { - int index = iens * meas_block->ens_stride + iobs * meas_block->obs_stride; - fprintf(stream , " %10.2f ", meas_block->data[ index ]); - } - fprintf(stream , "\n"); - } -} - - -void meas_block_free( meas_block_type * meas_block ) { - free( meas_block->obs_key ); - free( meas_block->data ); - free( meas_block->active ); - int_vector_free( meas_block->index_map ); - free( meas_block ); -} - - -static void meas_block_free__( void * arg ) { - meas_block_type * meas_block = meas_block_safe_cast( arg ); - meas_block_free( meas_block ); -} - - - -static void meas_block_initS( const meas_block_type * meas_block , matrix_type * S, int * __obs_offset) { - int obs_offset = *__obs_offset; - for (int iobs =0; iobs < meas_block->obs_size; iobs++) { - if (meas_block->active[iobs]) { - for (int iens =0; iens < meas_block->active_ens_size; iens++) { - int obs_index = iens * meas_block->ens_stride + iobs* meas_block->obs_stride; - - matrix_iset( S , obs_offset, iens , meas_block->data[ obs_index ]); - } - obs_offset++; - } - } - *__obs_offset = obs_offset; -} - -bool meas_block_iens_active( const meas_block_type * meas_block , int iens) { - return bool_vector_iget( meas_block->ens_mask , iens); -} - - -/* -static void meas_data_assign_block( meas_block_type * target_block , const meas_block_type * src_block , int target_iens , int src_iens ) { - int iobs; - for (iobs =0; iobs < target_block->obs_size; iobs++) { - int target_index = target_iens * target_block->ens_stride + iobs * target_block->obs_stride; - int src_index = src_iens * src_block->ens_stride + iobs * src_block->obs_stride; - target_block->data[ target_index ] = src_block->data[ src_index ]; - } - target_block->stat_calculated = false; -} -*/ - -static void meas_block_calculate_ens_stats( meas_block_type * meas_block ) { - bool include_inactive = true; - int iobs , iens; - for (iobs =0; iobs < meas_block->obs_size; iobs++) { - if (meas_block->active[iobs] || include_inactive) { - double M1 = 0; - double M2 = 0; - for (iens =0; iens < meas_block->active_ens_size; iens++) { - int index = iens * meas_block->ens_stride + iobs * meas_block->obs_stride; - M1 += meas_block->data[ index ]; - M2 += meas_block->data[ index ] * meas_block->data[ index ]; - } - { - int mean_index = (meas_block->active_ens_size + 0) * meas_block->ens_stride + iobs * meas_block->obs_stride; - int std_index = (meas_block->active_ens_size + 1) * meas_block->ens_stride + iobs * meas_block->obs_stride; - double mean = M1 / meas_block->active_ens_size; - double var = M2 / meas_block->active_ens_size - mean * mean; - meas_block->data[ mean_index ] = mean; - meas_block->data[ std_index ] = sqrt( util_double_max( 0.0 , var)); - } - } - } - meas_block->stat_calculated = true; -} - - -static void meas_block_assert_ens_stat( meas_block_type * meas_block ) { - if (!meas_block->stat_calculated) - meas_block_calculate_ens_stats( meas_block ); -} - - -static void meas_block_assert_iens_active( const meas_block_type * meas_block , int iens) { - if (!bool_vector_iget( meas_block->ens_mask , iens )) - util_abort("%s: fatal error - trying to access inactive ensemble member:%d \n",__func__ , iens); -} - - -void meas_block_iset( meas_block_type * meas_block , int iens , int iobs , double value) { - meas_block_assert_iens_active( meas_block , iens ); - { - int active_iens = int_vector_iget( meas_block->index_map , iens ); - int index = active_iens * meas_block->ens_stride + iobs * meas_block->obs_stride; - meas_block->data[ index ] = value; - if (!meas_block->active[ iobs ]) - meas_block->active[ iobs ] = true; - - meas_block->stat_calculated = false; - } -} - - -double meas_block_iget( const meas_block_type * meas_block , int iens , int iobs) { - meas_block_assert_iens_active( meas_block , iens ); - { - int active_iens = int_vector_iget( meas_block->index_map , iens ); - int index = active_iens * meas_block->ens_stride + iobs * meas_block->obs_stride; - return meas_block->data[ index ]; - } -} - - -static int meas_block_get_active_obs_size( const meas_block_type * meas_block ) { - int obs_size = 0; - int i; - - for (i=0; i < meas_block->obs_size; i++) - if (meas_block->active[i]) - obs_size++; - - return obs_size; -} - - -double meas_block_iget_ens_std( meas_block_type * meas_block , int iobs) { - meas_block_assert_ens_stat( meas_block ); - { - int std_index = (meas_block->active_ens_size + 1) * meas_block->ens_stride + iobs * meas_block->obs_stride; - return meas_block->data[ std_index ]; - } -} - - -double meas_block_iget_ens_mean( meas_block_type * meas_block , int iobs) { - meas_block_assert_ens_stat( meas_block ); - { - int mean_index = meas_block->active_ens_size * meas_block->ens_stride + iobs * meas_block->obs_stride; - return meas_block->data[ mean_index ]; - } -} - - -bool meas_block_iget_active( const meas_block_type * meas_block , int iobs) { - return meas_block->active[ iobs ]; -} - - -void meas_block_deactivate( meas_block_type * meas_block , int iobs ) { - if (meas_block->active[ iobs ]) - meas_block->active[ iobs ] = false; - meas_block->stat_calculated = false; -} - - -int meas_block_get_total_obs_size( const meas_block_type * meas_block ) { - return meas_block->obs_size; -} - - -int meas_block_get_active_ens_size( const meas_block_type * meas_block ) { - return meas_block->active_ens_size; -} - - -int meas_block_get_total_ens_size( const meas_block_type * meas_block ) { - return bool_vector_size( meas_block->ens_mask ); -} - - - - - - -/*****************************************************************/ - -UTIL_IS_INSTANCE_FUNCTION( meas_data , MEAS_DATA_TYPE_ID ) - -meas_data_type * meas_data_alloc( const bool_vector_type * ens_mask ) { - meas_data_type * meas = util_malloc(sizeof * meas ); - UTIL_TYPE_ID_INIT( meas , MEAS_DATA_TYPE_ID ); - - meas->data = vector_alloc_new(); - meas->blocks = hash_alloc(); - meas->ens_mask = bool_vector_alloc_copy( ens_mask ); - meas->active_ens_size = bool_vector_count_equal( ens_mask , true ); - pthread_mutex_init( &meas->data_mutex , NULL ); - - return meas; -} - - - -void meas_data_free(meas_data_type * matrix) { - vector_free( matrix->data ); - hash_free( matrix->blocks ); - bool_vector_free( matrix->ens_mask ); - free( matrix ); -} - - - -void meas_data_reset(meas_data_type * matrix) { - hash_clear( matrix->blocks ); - vector_clear( matrix->data ); /* Will dump and discard all the meas_block instances. */ -} - - -/* - The obs_key is not alone unique over different report steps. -*/ -static char * meas_data_alloc_key( const char * obs_key , int report_step) { - return util_alloc_sprintf( "%s-%d" , obs_key , report_step ); -} - -/** - The code actually adding new blocks to the vector must be run in single-thread mode. -*/ - -meas_block_type * meas_data_add_block( meas_data_type * matrix , const char * obs_key , int report_step , int obs_size) { - char * lookup_key = meas_data_alloc_key( obs_key , report_step ); - pthread_mutex_lock( &matrix->data_mutex ); - { - if (!hash_has_key( matrix->blocks , lookup_key )) { - meas_block_type * new_block = meas_block_alloc(obs_key , matrix->ens_mask , obs_size); - vector_append_owned_ref( matrix->data , new_block , meas_block_free__ ); - hash_insert_ref( matrix->blocks , lookup_key , new_block ); - } - } - pthread_mutex_unlock( &matrix->data_mutex ); - free( lookup_key ); - return vector_get_last( matrix->data ); -} - - -/* - Observe that the key should compare with the keys created by meas_data_alloc_key(). -*/ -bool meas_data_has_block( const meas_data_type * matrix , const char * lookup_key) { - return hash_has_key( matrix->blocks , lookup_key); -} - -meas_block_type * meas_data_get_block( const meas_data_type * matrix , const char * lookup_key) { - return hash_get( matrix->blocks , lookup_key ); -} - - -meas_block_type * meas_data_iget_block( const meas_data_type * matrix , int block_nr) { - return vector_iget( matrix->data , block_nr); -} - - -const meas_block_type * meas_data_iget_block_const( const meas_data_type * matrix , int block_nr) { - return vector_iget_const( matrix->data , block_nr); -} - - -int meas_data_get_active_obs_size( const meas_data_type * matrix ) { - int obs_size = 0; - - for (int block_nr = 0; block_nr < vector_get_size( matrix->data ); block_nr++) { - const meas_block_type * meas_block = vector_iget_const( matrix->data , block_nr); - obs_size += meas_block_get_active_obs_size( meas_block ); - } - - return obs_size; -} - - - -/* - Observe that this can return NULL is there is no data/observations. -*/ - -matrix_type * meas_data_allocS(const meas_data_type * matrix) { - int obs_offset = 0; - matrix_type * S = matrix_alloc( meas_data_get_active_obs_size( matrix ) , matrix->active_ens_size); - if (S) { - for (int block_nr = 0; block_nr < vector_get_size( matrix->data ); block_nr++) { - const meas_block_type * meas_block = vector_iget_const( matrix->data , block_nr); - meas_block_initS( meas_block , S , &obs_offset); - } - - matrix_set_name( S , "S"); - matrix_assert_finite( S ); - } - return S; -} - - - -int meas_data_get_nrobs( const meas_data_type * meas_data ) { - return -1; -} - - -int meas_data_get_active_ens_size( const meas_data_type * meas_data ) { - return meas_data->active_ens_size; -} - - -int meas_data_get_total_ens_size( const meas_data_type * meas_data ) { - return bool_vector_size( meas_data->ens_mask ); -} - - -int meas_data_get_num_blocks( const meas_data_type * meas_data ) { - return vector_get_size( meas_data->data ); -} - - - -/* -void meas_data_assign_vector(meas_data_type * target_matrix, const meas_data_type * src_matrix , int target_index , int src_index) { - if (target_matrix->active_ens_size != src_matrix->active_ens_size) - util_abort("%s: size mismatch \n",__func__); - - for (int block_nr = 0; block_nr < vector_get_size( target_matrix->data ); block_nr++) { - meas_block_type * target_block = meas_data_iget_block( target_matrix , block_nr ); - const meas_block_type * src_block = meas_data_iget_block_const( src_matrix , block_nr ); - - meas_data_assign_block( target_block , src_block , target_index , src_index ); - } -} -*/ - - - -void meas_data_fprintf( const meas_data_type * matrix , FILE * stream ) { - fprintf(stream , "-----------------------------------------------------------------\n"); - for (int block_nr = 0; block_nr < vector_get_size( matrix->data ); block_nr++) { - const meas_block_type * block = meas_data_iget_block_const( matrix , block_nr ); - meas_block_fprintf( block , stream ); - fprintf(stream , "\n"); - } - fprintf(stream , "-----------------------------------------------------------------\n"); -} diff --git a/ThirdParty/Ert/libenkf/src/member_config.c b/ThirdParty/Ert/libenkf/src/member_config.c deleted file mode 100644 index 1fefd908ec..0000000000 --- a/ThirdParty/Ert/libenkf/src/member_config.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'member_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - - -/** - This struct contains information which is private to this - member. It is initialized at object boot time, and (typically) not - changed during the simulation. [In principle it could change during - the simulation, but the current API does not support that.] -*/ - - -struct member_config_struct { - int iens; /* The ensemble member number of this member. */ - char * casename; /* The name of this case - will mostly be NULL. */ - keep_runpath_type keep_runpath; /* Should the run-path directory be left around (for this member)*/ - bool pre_clear_runpath; /* Should the runpath directory be cleared before starting? */ - char * jobname; /* The jobname used for this job when submitting to the queue system. */ - char * eclbase; /* The ECLBASE string used for simulations of this member. */ -}; - - -/*****************************************************************/ -/* - Observe that there is a potential for conflict between the fields - pre_clear_runpath and keep_runpath when running normal EnKF. If both - are set to true the former will win. -*/ - - - -/******************************************************************/ -/** Implementation of the member_config struct. All of this implementation - is private - however some of it is exported through the enkf_state object, - and it should be perfectly safe to export more of it. -*/ - - -const char * member_config_update_jobname(member_config_type * member_config , const char * jobname_fmt , const subst_list_type * subst_list) { - if (jobname_fmt != NULL) { - util_safe_free( member_config->jobname ); - { - char * tmp = util_alloc_sprintf( jobname_fmt , member_config->iens); - member_config->jobname = subst_list_alloc_filtered_string( subst_list , tmp ); - free( tmp ); - } - } - return member_config->jobname; -} - - - -const char * member_config_update_eclbase(member_config_type * member_config , const ecl_config_type * ecl_config , const subst_list_type * subst_list) { - util_safe_free( member_config->eclbase ); - { - const path_fmt_type * eclbase_fmt = ecl_config_get_eclbase_fmt(ecl_config); - if (eclbase_fmt != NULL) { - { - char * tmp = path_fmt_alloc_path(eclbase_fmt , false , member_config->iens); - member_config->eclbase = subst_list_alloc_filtered_string( subst_list , tmp ); - free( tmp ); - } - } - } - - return member_config->eclbase; -} - - -int member_config_get_iens( const member_config_type * member_config ) { - return member_config->iens; -} - - - -void member_config_free(member_config_type * member_config) { - util_safe_free(member_config->eclbase); - util_safe_free(member_config->casename ); - free(member_config); -} - - - -void member_config_set_keep_runpath(member_config_type * member_config , keep_runpath_type keep_runpath) { - member_config->keep_runpath = keep_runpath; -} - - -keep_runpath_type member_config_get_keep_runpath(const member_config_type * member_config) { - return member_config->keep_runpath; -} - -bool member_config_pre_clear_runpath(const member_config_type * member_config) { - return member_config->pre_clear_runpath; -} - - -void member_config_set_pre_clear_runpath(member_config_type * member_config , bool pre_clear_runpath) { - member_config->pre_clear_runpath = pre_clear_runpath; -} - - - - - -const char * member_config_get_eclbase( const member_config_type * member_config ) { - return member_config->eclbase; -} - - -const char * member_config_get_jobname( const member_config_type * member_config ) { - if (member_config->jobname != NULL) - return member_config->jobname; - else { - if (member_config->eclbase != NULL) - return member_config->eclbase; - else { - util_abort("%s: sorry can not submit JOB - must specify name with JOBNAME or ECLBASE config keys\n",__func__); - return NULL; - } - } -} - - -const char * member_config_get_casename( const member_config_type * member_config ) { - return member_config->casename; -} - - -member_config_type * member_config_alloc(int iens , - const char * casename , - bool pre_clear_runpath , - keep_runpath_type keep_runpath , - const ecl_config_type * ecl_config , - const ensemble_config_type * ensemble_config) { - - - member_config_type * member_config = util_malloc( sizeof * member_config ); - member_config->casename = util_alloc_string_copy( casename ); - member_config->iens = iens; /* Can only be changed in the allocater. */ - member_config->eclbase = NULL; - member_config->jobname = NULL; - member_config->pre_clear_runpath = pre_clear_runpath; - member_config_set_keep_runpath(member_config , keep_runpath); - return member_config; -} diff --git a/ThirdParty/Ert/libenkf/src/migrate_bfs.c b/ThirdParty/Ert/libenkf/src/migrate_bfs.c deleted file mode 100644 index 5a01ace37b..0000000000 --- a/ThirdParty/Ert/libenkf/src/migrate_bfs.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'migrate_bfs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include - - - -static void migrate_file( const char * src_case, int num_src_drivers , const char * target_case, int num_target_drivers, const char * file, int block_size , msg_type * msg) { - block_fs_type ** target_fs = util_calloc( num_target_drivers , sizeof * target_fs ); - int itarget; - for (itarget = 0; itarget < num_target_drivers; itarget++) { - char * path = util_alloc_sprintf("%s/mod_%d" , target_case , itarget ); - char * mount_file = util_alloc_sprintf("%s/mod_%d/%s.mnt" , target_case , itarget , file ); - util_make_path( path ); - - target_fs[itarget] = block_fs_mount( mount_file , 16 , 0 , 1.0, 0 , false , false ); - free( mount_file ); - free( path ); - } - - { - int isrc; - buffer_type * buffer = buffer_alloc(1024); - for (isrc = 0; isrc < num_src_drivers; isrc++) { - char * mount_file = util_alloc_sprintf("%s/mod_%d/%s.mnt" , src_case , isrc , file ); - block_fs_type * src_fs = block_fs_mount( mount_file , 16 , 1024 , 1.0 , 0 , true , true ); - vector_type * file_list = block_fs_alloc_filelist( src_fs , NULL , NO_SORT , false ); - int ifile; - msg_update( msg , mount_file ); - for (ifile = 0; ifile < vector_get_size( file_list ); ifile++) { - const file_node_type * node = vector_iget_const( file_list , ifile ); - const char * filename = file_node_get_filename( node ); - int report_step , iens; - char * key; - if (block_fs_sscanf_key( filename , &key , &report_step , &iens )) { - block_fs_fread_realloc_buffer( src_fs , filename , buffer); - block_fs_fwrite_buffer( target_fs[(iens % num_target_drivers)] , filename , buffer ); - free( key ); - } else - util_abort("%s: All hell is loose - failed to parse:%s \n",__func__ , filename); - } - - vector_free( file_list ); - block_fs_close(src_fs , false); - } - buffer_free( buffer ); - } - - - for (itarget = 0; itarget < num_target_drivers; itarget++) - block_fs_close( target_fs[itarget] , false); - free( target_fs ); -} - - -static void copy_index( const char * src_case , const char * target_case) { - char * mount_src = util_alloc_filename(src_case , "INDEX" , "mnt"); - char * mount_target = util_alloc_filename(target_case , "INDEX" , "mnt"); - char * data_src = util_alloc_filename(src_case , "INDEX" , "data_0"); - char * data_target = util_alloc_filename(target_case , "INDEX" , "data_0"); - - util_copy_file( mount_src , mount_target ); - util_copy_file( data_src , data_target ); - - free( mount_src ); - free( mount_target ); - free( data_src ); - free( data_target ); -} - - -static void usage() { - printf("Use:\n"); - printf("bash%% migrate_bfs case\n"); - exit(1); -} - -int main(int argc, char ** argv) { - int num_src_drivers = 10; - int num_target_drivers = 32; - if (argc != 4) - usage(); - - { - char * src_path = argv[1] ; - char * target_path = argv[2] ; - char * dir = argv[3] ; - - util_make_path( target_path ); - if (util_same_file( src_path , target_path)) { - fprintf(stderr,"The two directories:%s and %s point to the same location \n" , src_path , target_path ); - exit(1); - } - - { - char * src_case = util_alloc_sprintf("%s/%s" , src_path , dir ); - char * target_case = util_alloc_sprintf("%s/%s" , target_path , dir ); - - msg_type * msg = msg_alloc("Copying from: " , false); - msg_show( msg ); - migrate_file(src_case , num_src_drivers , target_case , num_target_drivers , "ANALYZED" , 32 , msg); - migrate_file(src_case , num_src_drivers , target_case , num_target_drivers , "FORECAST" , 32 , msg); - migrate_file(src_case , num_src_drivers , target_case , num_target_drivers , "PARAMETER" , 32 , msg); - migrate_file(src_case , num_src_drivers , target_case , num_target_drivers , "STATIC" , 32 , msg); - copy_index( src_case , target_case ); - free( src_case); - free( target_case ); - msg_free( msg , true ); - } - } -} diff --git a/ThirdParty/Ert/libenkf/src/misfit_ensemble.c b/ThirdParty/Ert/libenkf/src/misfit_ensemble.c deleted file mode 100644 index 0ade82b860..0000000000 --- a/ThirdParty/Ert/libenkf/src/misfit_ensemble.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'misfit_ensemble.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -/** - This file implements a type misfit_ensemble which is used to rank the - different realization according to various criteria. - - The top level datastructure in this file is the misfit_ensemble, and - that is the only exported datatype, but in addition there are the - misfit_member which is the misfit for one ensemble member, and - misfit_ts which is the misfit for one ensemble member / one - observation key. -*/ - - - - - -#define MISFIT_ENSEMBLE_TYPE_ID 441066 - -struct misfit_ensemble_struct { - UTIL_TYPE_ID_DECLARATION; - bool initialized; - int history_length; - vector_type * ensemble; /* Vector of misfit_member_type instances - one for each ensemble member. */ -}; - - -/*****************************************************************/ - -static double ** __2d_malloc(int rows , int columns) { - double ** d = util_calloc( rows , sizeof * d ); - for (int i =0; i < rows; i++) - d[i] = util_calloc( columns , sizeof * d[i]); - return d; -} - -static void __2d_free(double ** d , int rows) { - for (int i =0; i < rows; i++) - free(d[i]); - free(d); -} - - -void misfit_ensemble_initialize( misfit_ensemble_type * misfit_ensemble , - const ensemble_config_type * ensemble_config , - const enkf_obs_type * enkf_obs , - enkf_fs_type * fs , - int ens_size , - int history_length, - bool force_init) { - - if (force_init || !misfit_ensemble->initialized) { - misfit_ensemble_clear( misfit_ensemble ); - - msg_type * msg = msg_alloc("Evaluating misfit for observation: " , false); - double ** chi2_work = __2d_malloc( history_length + 1 , ens_size ); - bool_vector_type * iens_valid = bool_vector_alloc( ens_size , true ); - - hash_iter_type * obs_iter = enkf_obs_alloc_iter( enkf_obs ); - const char * obs_key = hash_iter_get_next_key( obs_iter ); - - misfit_ensemble->history_length = history_length; - misfit_ensemble_set_ens_size( misfit_ensemble , ens_size ); - - msg_show( msg ); - while (obs_key != NULL) { - obs_vector_type * obs_vector = enkf_obs_get_vector( enkf_obs , obs_key ); - msg_update( msg , obs_key ); - - bool_vector_reset( iens_valid ); - bool_vector_iset( iens_valid , ens_size - 1 , true ); - obs_vector_ensemble_chi2( obs_vector , - fs , - iens_valid , - 0 , - misfit_ensemble->history_length, - 0 , - ens_size , - chi2_work); - - /** - Internalizing the results from the chi2_work table into the misfit structure. - */ - for (int iens = 0; iens < ens_size; iens++) { - misfit_member_type * node = misfit_ensemble_iget_member( misfit_ensemble , iens ); - if (bool_vector_iget( iens_valid , iens)) - misfit_member_update( node , obs_key , misfit_ensemble->history_length , iens , (const double **) chi2_work); - } - obs_key = hash_iter_get_next_key( obs_iter ); - } - - bool_vector_free( iens_valid ); - msg_free(msg , true ); - hash_iter_free( obs_iter ); - - __2d_free( chi2_work , misfit_ensemble->history_length + 1); - misfit_ensemble->initialized = true; - } -} - - -void misfit_ensemble_fwrite( const misfit_ensemble_type * misfit_ensemble , FILE * stream ) { - int ens_size = vector_get_size( misfit_ensemble->ensemble); - util_fwrite_int( misfit_ensemble->history_length , stream ); - util_fwrite_int( vector_get_size( misfit_ensemble->ensemble ) , stream); - - /* Writing the nodes - one for each ensemble member */ - { - int iens; - for (iens = 0; iens < ens_size; iens++) - misfit_member_fwrite( vector_iget( misfit_ensemble->ensemble , iens ) , stream ); - } - -} - - - - -/** - Observe that the object is NOT in a valid state when leaving this function, - must finalize in either misfit_ensemble_alloc() or misfit_ensemble_fread_alloc(). -*/ - -static misfit_ensemble_type * misfit_ensemble_alloc_empty() { - misfit_ensemble_type * table = util_malloc( sizeof * table ); - - table->initialized = false; - table->ensemble = vector_alloc_new(); - - return table; -} - - -/** - This funcion is a feeble attempt at allowing the ensemble size to - change runtime. If the new ensemble size is larger than the current - ensemble size ALL the currently internalized misfit information is - dropped on the floor; if the the ensemble is shrinked only the the - last elements of the misfit table are discarded (NOT exactly battle-tested). - -*/ -void misfit_ensemble_set_ens_size( misfit_ensemble_type * misfit_ensemble , int ens_size) { - int iens; - if (ens_size > vector_get_size( misfit_ensemble->ensemble )) { - /* The new ensemble is larger than what we have currently internalized, - we drop everything and add empty misfit_member instances. */ - vector_clear( misfit_ensemble->ensemble ); - for (iens = 0; iens < ens_size; iens++) - vector_append_owned_ref( misfit_ensemble->ensemble , misfit_member_alloc( iens ) , misfit_member_free__); - - } else - /* We shrink the vector by removing the last elements. */ - vector_shrink( misfit_ensemble->ensemble , ens_size); -} - - -void misfit_ensemble_fread( misfit_ensemble_type * misfit_ensemble , FILE * stream ) { - misfit_ensemble_clear( misfit_ensemble ); - { - int ens_size; - - misfit_ensemble->history_length = util_fread_int( stream ); - ens_size = util_fread_int( stream ); - misfit_ensemble_set_ens_size( misfit_ensemble , ens_size ); - { - for (int iens = 0; iens < ens_size; iens++) { - misfit_member_type * node = misfit_member_fread_alloc( stream ); - vector_iset_owned_ref( misfit_ensemble->ensemble , iens , node , misfit_member_free__); - } - } - - } -} - - - -misfit_ensemble_type * misfit_ensemble_alloc( ) { - misfit_ensemble_type * table = misfit_ensemble_alloc_empty( ); - return table; -} - - - -misfit_member_type * misfit_ensemble_iget_member( const misfit_ensemble_type * table , int iens) { - return vector_iget( table->ensemble , iens); -} - - - - -void misfit_ensemble_clear( misfit_ensemble_type * table) { - vector_clear( table->ensemble ); - table->initialized = false; -} - - -void misfit_ensemble_free(misfit_ensemble_type * table ) { - vector_free( table->ensemble ); - free( table ); -} - - -bool misfit_ensemble_initialized( const misfit_ensemble_type * misfit_ensemble ) { - return misfit_ensemble->initialized; -} - - -/*****************************************************************/ - - -int misfit_ensemble_get_ens_size( const misfit_ensemble_type * misfit_ensemble ) { - return vector_get_size( misfit_ensemble->ensemble ); -} diff --git a/ThirdParty/Ert/libenkf/src/misfit_member.c b/ThirdParty/Ert/libenkf/src/misfit_member.c deleted file mode 100644 index 90afdc20c3..0000000000 --- a/ThirdParty/Ert/libenkf/src/misfit_member.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'misfit_member.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include - -#include - - -#define MISFIT_MEMBER_TYPE_ID 541066 - -struct misfit_member_struct { - UTIL_TYPE_ID_DECLARATION; - int my_iens; - hash_type *obs; /* hash table of misfit_ts_type instances - indexed by observation keys. The structure - of this hash table is duplicated for each ensemble member.*/ -}; - - - -static UTIL_SAFE_CAST_FUNCTION(misfit_member , MISFIT_MEMBER_TYPE_ID); - - -static void misfit_member_free( misfit_member_type * node ) { - hash_free( node->obs ); - free( node ); -} - - -void misfit_member_free__( void * node ) { - misfit_member_free( misfit_member_safe_cast( node )); -} - - -misfit_member_type * misfit_member_alloc(int iens) { - misfit_member_type * node = util_malloc( sizeof * node ); - UTIL_TYPE_ID_INIT( node , MISFIT_MEMBER_TYPE_ID); - node->my_iens = iens; - node->obs = hash_alloc(); - return node; -} - - -static void misfit_member_install_vector( misfit_member_type * node , const char * key , misfit_ts_type * vector ) { - hash_insert_hash_owned_ref( node->obs, key , vector , misfit_ts_free__ ); -} - - -static misfit_ts_type * misfit_member_safe_get_vector( misfit_member_type * node , const char * obs_key , int history_length) { - if (!hash_has_key( node->obs , obs_key )) - misfit_member_install_vector(node , obs_key , misfit_ts_alloc( history_length ) ); - return hash_get( node->obs , obs_key ); -} - - -misfit_ts_type * misfit_member_get_ts( const misfit_member_type * node , const char * obs_key ) { - return hash_get( node->obs , obs_key ); -} - -bool misfit_member_has_ts( const misfit_member_type * node , const char * obs_key ) { - return hash_has_key( node->obs , obs_key ); -} - - -void misfit_member_update( misfit_member_type * node , const char * obs_key , int history_length , int iens , const double ** work_chi2) { - misfit_ts_type * vector = misfit_member_safe_get_vector( node , obs_key , history_length ); - for (int step = 0; step <= history_length; step++) - misfit_ts_iset( vector , step , work_chi2[step][iens]); -} - - -void misfit_member_fwrite( const misfit_member_type * node , FILE * stream) { - util_fwrite_int( node->my_iens , stream); - util_fwrite_int( hash_get_size( node->obs ) , stream); - { - hash_iter_type * obs_iter = hash_iter_alloc( node->obs ); - while ( !hash_iter_is_complete( obs_iter )) { - const char * key = hash_iter_get_next_key( obs_iter ); - misfit_ts_type * misfit_ts = hash_get( node->obs , key ); - util_fwrite_string( key , stream ); - misfit_ts_fwrite( misfit_ts , stream); - } - hash_iter_free( obs_iter ); - } -} - - -misfit_member_type * misfit_member_fread_alloc( FILE * stream ) { - int my_iens = util_fread_int( stream ); - misfit_member_type * node = misfit_member_alloc( my_iens ); - int hash_size = util_fread_int( stream ); - { - int iobs; - for (iobs = 0; iobs < hash_size; iobs++) { - char * key = util_fread_alloc_string( stream ); - misfit_ts_type * misfit_ts = misfit_ts_fread_alloc( stream ); - misfit_member_install_vector( node , key , misfit_ts ); - free( key ); - } - } - return node; -} - diff --git a/ThirdParty/Ert/libenkf/src/misfit_ranking.c b/ThirdParty/Ert/libenkf/src/misfit_ranking.c deleted file mode 100644 index 1b49ff16a7..0000000000 --- a/ThirdParty/Ert/libenkf/src/misfit_ranking.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'misfit_ranking.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/** - This struct contains the misfits & sort keys for one particular - misfit_ranking. I.e. all the RFT measurements. -*/ - - - -#define MISFIT_RANKING_TYPE_ID 671108 - -struct misfit_ranking_struct { - UTIL_TYPE_ID_DECLARATION; - vector_type * ensemble; /* An ensemble of hash instances. Each hash instance is populated like this: hash_insert_double(hash , "WGOR" , 1.09); */ - double_vector_type * total; /* An enemble of total misfit values (for this misfit_ranking). */ - perm_vector_type * sort_permutation; /* This is how the ens members should be permuted to be sorted under this misfit_ranking. */ - int ens_size; -}; - -UTIL_SAFE_CAST_FUNCTION( misfit_ranking , MISFIT_RANKING_TYPE_ID ) -UTIL_IS_INSTANCE_FUNCTION( misfit_ranking , MISFIT_RANKING_TYPE_ID) - -void misfit_ranking_display( const misfit_ranking_type * misfit_ranking , FILE * stream) { - const int ens_size = double_vector_size( misfit_ranking->total ); - const perm_vector_type * permutations = misfit_ranking->sort_permutation; - hash_type * obs_hash = NULL; - { - // The ensemble vector can contain invalid nodes with NULL. - int index = 0; - while ((obs_hash == NULL) && (index < vector_get_size( misfit_ranking->ensemble))) { - obs_hash = vector_iget( misfit_ranking->ensemble , index ); - index++; - } - if (obs_hash == NULL) { - fprintf(stderr,"Sorry: no valid results loaded for this misfit_ranking - returning\n"); - return; - } - } - - { - int i; - double summed_up = 0.0; - stringlist_type * obs_keys = hash_alloc_stringlist( obs_hash ); - int num_obs = stringlist_get_size( obs_keys ); - int num_obs_total = num_obs * ens_size; // SHould not count failed/missing members ... - - fprintf(stream,"\n\n"); - fprintf(stream," # Realization Normalized misfit Total misfit\n"); - fprintf(stream,"-------------------------------------------------------\n"); - for (i = 0; i < ens_size; i++) { - int iens = perm_vector_iget( permutations, i ); - double total_misfit = double_vector_iget( misfit_ranking->total , iens ); - double normalized_misfit = sqrt(total_misfit / num_obs_total); - summed_up = summed_up+total_misfit; - fprintf(stream,"%3d %3d %10.3f %10.3f \n",i,iens,normalized_misfit,total_misfit); - } - - { - double normalized_summed_up = sqrt(summed_up / (num_obs_total * ens_size)); - fprintf(stream," All %10.3f %10.3f \n",normalized_summed_up,summed_up); - } - fprintf(stream,"-------------------------------------------------------\n"); - } - -} - - - -void misfit_ranking_fprintf( const misfit_ranking_type * misfit_ranking , const char * filename) { - FILE * stream = util_mkdir_fopen( filename , "w"); - const int ens_size = misfit_ranking->ens_size; - const perm_vector_type * permutations = misfit_ranking->sort_permutation; - double summed_up = 0.0; - { - // All this whitespace is finely tuned and highly significant .... - const char * key_fmt = " %18s "; - const char * value_fmt = " %10.3f %8.3f"; - const char * start_fmt = " %2d %3d %7.3f %8.3f"; - - hash_type * obs_hash = vector_iget( misfit_ranking->ensemble , 0); - stringlist_type * obs_keys = hash_alloc_stringlist( obs_hash ); - int num_obs = stringlist_get_size( obs_keys ); - int iobs; - int num_obs_total = num_obs * ens_size; - - stringlist_sort( obs_keys , enkf_util_compare_keys__ ); - fprintf(stream , " Overall "); - for (iobs =0; iobs < num_obs; iobs++) - fprintf(stream , key_fmt , stringlist_iget( obs_keys , iobs )); - - fprintf(stream , "\n"); - fprintf(stream , " # Realization Norm Total"); - for (iobs =0; iobs < num_obs; iobs++) - fprintf(stream , " Norm Total"); - - fprintf(stream , "\n"); - for (int i = 0; i < ens_size; i++) { - int iens = perm_vector_iget( permutations , i ); - hash_type * obs_hash = vector_iget( misfit_ranking->ensemble , iens ); - double total_value = double_vector_iget( misfit_ranking->total , iens ); - double normalized_misfit = sqrt(total_value / num_obs_total); - summed_up = summed_up+total_value; - fprintf(stream , start_fmt , i , iens , normalized_misfit , total_value); - for (iobs =0; iobs < num_obs; iobs++){ - double single_value = hash_get_double( obs_hash , stringlist_iget( obs_keys , iobs )); - double single_value_normalized = sqrt(single_value / (num_obs_total)); - fprintf(stream , value_fmt , single_value_normalized , single_value); - } - fprintf(stream , "\n"); - } - double summed_up_normalized = sqrt(summed_up / (num_obs_total * ens_size)); - fprintf(stream , " All %7.3f %8.3f" , summed_up_normalized , summed_up); - for (iobs = 0; iobs < num_obs; iobs++){ - double single_value_summed_up = 0.0; - for (int i = 0; i < ens_size; i++) { - single_value_summed_up = single_value_summed_up + hash_get_double( obs_hash , stringlist_iget( obs_keys , iobs )); - } - double single_value_summed_up_normalized=sqrt(single_value_summed_up / (num_obs_total * ens_size)); - fprintf(stream , value_fmt , single_value_summed_up_normalized , single_value_summed_up); - } - fprintf(stream , "\n"); - } - fclose( stream ); -} - - -static misfit_ranking_type * misfit_ranking_alloc_empty( int ens_size ) { - misfit_ranking_type * misfit_ranking = util_malloc( sizeof * misfit_ranking ); - UTIL_TYPE_ID_INIT( misfit_ranking , MISFIT_RANKING_TYPE_ID ); - misfit_ranking->sort_permutation = NULL; - misfit_ranking->ensemble = vector_alloc_new(); - misfit_ranking->total = double_vector_alloc( 0 , INVALID_RANKING_VALUE ); - misfit_ranking->ens_size = ens_size; - return misfit_ranking; -} - - -/** - Step and step2 are inclusive. The time direction is flattened. -*/ - -misfit_ranking_type * misfit_ranking_alloc(const misfit_ensemble_type * misfit_ensemble , const stringlist_type * sort_keys , const int_vector_type * steps, const char * ranking_key) { - const int ens_size = misfit_ensemble_get_ens_size( misfit_ensemble ); - int iens; - misfit_ranking_type * ranking = misfit_ranking_alloc_empty(ens_size); - - for (iens = 0; iens < ens_size; iens++) { - const misfit_member_type * misfit_member = misfit_ensemble_iget_member( misfit_ensemble , iens ); /* Lookup in the master ensemble. */ - - { - double iens_valid = true; - double total = 0; - hash_type * obs_hash = hash_alloc(); - for (int ikey = 0; ikey < stringlist_get_size( sort_keys ); ikey++) { - const char * obs_key = stringlist_iget( sort_keys , ikey ); - if (misfit_member_has_ts( misfit_member , obs_key )) { - misfit_ts_type * ts = misfit_member_get_ts( misfit_member , obs_key ); - double value = misfit_ts_eval( ts , steps ); /* Sum up the misfit for this key - and these timesteps. */ - hash_insert_double( obs_hash , obs_key , value); - total += value; - } else - iens_valid = true; - } - if (iens_valid) - misfit_ranking_iset( ranking , iens , obs_hash , total ); - else - misfit_ranking_iset_invalid( ranking , iens ); - } - } - ranking->sort_permutation = double_vector_alloc_sort_perm( ranking->total ); - - return ranking; -} - - - - - -void misfit_ranking_free( misfit_ranking_type * misfit_ranking ) { - vector_free( misfit_ranking->ensemble ); - double_vector_free( misfit_ranking->total ); - - if (misfit_ranking->sort_permutation) - perm_vector_free( misfit_ranking->sort_permutation ); - - free( misfit_ranking ); -} - - - -void misfit_ranking_free__( void * arg ) { - misfit_ranking_type * misfit_ranking = misfit_ranking_safe_cast( arg ); - misfit_ranking_free( misfit_ranking ); -} - - - -void misfit_ranking_iset( misfit_ranking_type * misfit_ranking , int iens , hash_type * obs_hash , double total_misfit) { - if (iens > vector_get_size(misfit_ranking->ensemble)) - vector_grow_NULL( misfit_ranking->ensemble , iens ); - - if (obs_hash != NULL) - vector_iset_owned_ref( misfit_ranking->ensemble , iens , obs_hash , hash_free__ ); - else - vector_iset_ref( misfit_ranking->ensemble , iens , NULL ); - - double_vector_iset( misfit_ranking->total , iens , total_misfit ); -} - - -void misfit_ranking_iset_invalid( misfit_ranking_type * misfit_ranking , int iens ) { - misfit_ranking_iset( misfit_ranking , iens , NULL , INVALID_RANKING_VALUE ); -} - - -const perm_vector_type * misfit_ranking_get_permutation( const misfit_ranking_type * misfit_ranking ) { - return misfit_ranking->sort_permutation; -} diff --git a/ThirdParty/Ert/libenkf/src/misfit_ts.c b/ThirdParty/Ert/libenkf/src/misfit_ts.c deleted file mode 100644 index e0b4655387..0000000000 --- a/ThirdParty/Ert/libenkf/src/misfit_ts.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'misfit_ts.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include - -#include - - -#define MISFIT_TS_TYPE_ID 641066 - -struct misfit_ts_struct { - UTIL_TYPE_ID_DECLARATION; - double_vector_type * data; /* A double vector of length 'history_length' with actual misfit values. */ -}; - -static UTIL_SAFE_CAST_FUNCTION(misfit_ts , MISFIT_TS_TYPE_ID); - -/******************************************************************/ -/* - Implementation of the misfit_ts type. Contains the full - timeseries of misfit for one member/one observation key. -*/ - -misfit_ts_type * misfit_ts_alloc(int history_length) { - misfit_ts_type * misfit_ts = util_malloc( sizeof * misfit_ts ); - UTIL_TYPE_ID_INIT(misfit_ts , MISFIT_TS_TYPE_ID); - - if (history_length > 0) - misfit_ts->data = double_vector_alloc( history_length + 1 , 0 ); - else - misfit_ts->data = NULL; /* Used by the xxx_fread_alloc() function below. */ - - return misfit_ts; -} - - -misfit_ts_type * misfit_ts_fread_alloc( FILE * stream ) { - misfit_ts_type * misfit_ts = misfit_ts_alloc( 0 ); - if (misfit_ts->data == NULL) - misfit_ts->data = double_vector_fread_alloc( stream ); - return misfit_ts; -} - - -void misfit_ts_fwrite( const misfit_ts_type * misfit_ts , FILE * stream ) { - double_vector_fwrite( misfit_ts->data , stream ); -} - - - - -static void misfit_ts_free( misfit_ts_type * misfit_ts) { - double_vector_free( misfit_ts->data ); - free( misfit_ts ); -} - - -void misfit_ts_free__( void * vector ) { - misfit_ts_free( misfit_ts_safe_cast( vector )); -} - - - - -void misfit_ts_iset( misfit_ts_type * vector , int time_index , double value ) { - double_vector_iset( vector->data , time_index , value ); -} - -/** Step2 is inclusive - what a fucking mess. */ -double misfit_ts_eval( const misfit_ts_type * vector , const int_vector_type * steps) { - double misfit_sum = 0; - int step; - - for (int i = 0; i < int_vector_size(steps); ++i) { - step = int_vector_iget(steps, i); - misfit_sum += double_vector_iget(vector->data , step ); - } - - return misfit_sum; -} - diff --git a/ThirdParty/Ert/libenkf/src/model_config.c b/ThirdParty/Ert/libenkf/src/model_config.c deleted file mode 100644 index 9891449ef4..0000000000 --- a/ThirdParty/Ert/libenkf/src/model_config.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'model_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -/** - This struct contains configuration which is specific to this - particular model/run. Such of the information is actually accessed - directly through the enkf_state object; but this struct is the - owner of the information, and responsible for allocating/freeing - it. - - Observe that the distinction of what goes in model_config, and what - goes in ecl_config is not entirely clear; ECLIPSE is unfortunately - not (yet ??) exactly 'any' reservoir simulator in this context. - -*/ - - -/* - The runpath format is governed by a hash table where new runpaths - are added with model_config_add_runpath() and then current runpath - is selected with model_config_select_runpath(). However this - implementation is quite different from the way manipulation of the - runpath is exposed to the user: The runpath is controlled through - the RUNPATH config key (key DEFAULT_RUNPATH_KEY in the hash table) - This semantically predefined runpath is the only option visible to the user. - */ - -#define MODEL_CONFIG_TYPE_ID 661053 -struct model_config_struct { - UTIL_TYPE_ID_DECLARATION; - stringlist_type * case_names; /* A list of "iens -> name" mappings - can be NULL. */ - char * case_table_file; - forward_model_type * forward_model; /* The forward_model - as loaded from the config file. Each enkf_state object internalizes its private copy of the forward_model. */ - time_map_type * external_time_map; - history_type * history; /* The history object. */ - path_fmt_type * current_runpath; /* path_fmt instance for runpath - runtime the call gets arguments: (iens, report_step1 , report_step2) - i.e. at least one %d must be present.*/ - char * current_path_key; - hash_type * runpath_map; - char * jobname_fmt; /* Format string with one '%d' for the jobname - can be NULL in which case the eclbase name will be used. */ - char * enspath; - char * rftpath; - fs_driver_impl dbase_type; - bool has_prediction; - int max_internal_submit; /* How many times to retry if the load fails. */ - history_source_type history_source; - const ecl_sum_type * refcase; /* A pointer to the refcase - can be NULL. Observe that this ONLY a pointer - to the ecl_sum instance owned and held by the ecl_config object. */ - char * gen_kw_export_file_name; - - /** The results are always loaded. */ - bool_vector_type * internalize_state; /* Should the (full) state be internalized (at this report_step). */ - bool_vector_type * __load_eclipse_restart; /* Internal variable: is it necessary to load the state? */ -}; - - - -const char * model_config_get_jobname_fmt( const model_config_type * model_config ) { - return model_config->jobname_fmt; -} - -void model_config_set_jobname_fmt( model_config_type * model_config , const char * jobname_fmt) { - model_config->jobname_fmt = util_realloc_string_copy( model_config->jobname_fmt , jobname_fmt ); -} - - -path_fmt_type * model_config_get_runpath_fmt(const model_config_type * model_config) { - return model_config->current_runpath; -} - -const char * model_config_get_runpath_as_char( const model_config_type * model_config ) { - return path_fmt_get_fmt( model_config->current_runpath ); -} - -bool model_config_runpath_requires_iter( const model_config_type * model_config ) { - if (util_int_format_count( model_config_get_runpath_as_char( model_config)) > 1 ) - return true; - else - return false; -} - - -const char * model_config_get_case_table_file( const model_config_type * model_config ) { - return model_config->case_table_file; -} - -void model_config_set_case_table( model_config_type * model_config , int ens_size , const char * case_table_file ) { - if (model_config->case_table_file != NULL) { /* Clear the current selection */ - free( model_config->case_table_file ); - stringlist_free( model_config->case_names ); - - model_config->case_table_file = NULL; - model_config->case_names = NULL; - } - - if (case_table_file != NULL) { - bool atEOF = false; - char casename[128]; - int case_size = 0; - FILE * stream = util_fopen( case_table_file , "r"); - model_config->case_names = stringlist_alloc_new(); - while (!atEOF) { - if (fscanf( stream , "%s" , casename) == 1) { - stringlist_append_copy( model_config->case_names , casename ); - case_size++; - } else - atEOF = true; - } - fclose( stream ); - - if (case_size < ens_size) { - for (int i = case_size; i < ens_size; i++) - stringlist_append_owned_ref( model_config->case_names , util_alloc_sprintf("case_%04d" , i)); - fprintf(stderr, "** Warning: mismatch between NUM_REALIZATIONS:%d and size of CASE_TABLE:%d - using \'case_nnnn\' for the last cases %d.\n", ens_size , case_size , ens_size - case_size); - } else if (case_size > ens_size) - fprintf(stderr, "** Warning: mismatch between NUM_REALIZATIONS:%d and CASE_TABLE:%d - only the %d realizations will be used.\n", ens_size , case_size , ens_size); - - } -} - - -void model_config_add_runpath( model_config_type * model_config , const char * path_key , const char * fmt) { - path_fmt_type * path_fmt = path_fmt_alloc_directory_fmt( fmt ); - hash_insert_hash_owned_ref( model_config->runpath_map , path_key , path_fmt , path_fmt_free__ ); -} - - -/* - If the path_key does not exists it will return false and stay - silent. -*/ - -bool model_config_select_runpath( model_config_type * model_config , const char * path_key) { - if (hash_has_key( model_config->runpath_map , path_key )) { - model_config->current_runpath = hash_get( model_config->runpath_map , path_key ); - model_config->current_path_key = util_realloc_string_copy( model_config->current_path_key , path_key); - return true; - } else { - if (model_config->current_runpath != NULL) // OK - we already have a valid selection - stick to that and return False. - return false; - else { - util_abort("%s: path_key:%s does not exist - and currently no valid runpath selected \n",__func__ , path_key); - return false; - } - } -} - - -void model_config_set_runpath(model_config_type * model_config , const char * fmt) { - if (model_config->current_path_key) { - model_config_add_runpath(model_config , model_config->current_path_key , fmt); - model_config_select_runpath( model_config , model_config->current_path_key ); - } else - util_abort("%s: current path has not been set \n",__func__); -} - - - -void model_config_set_gen_kw_export_file( model_config_type * model_config, const char * file_name) { - model_config->gen_kw_export_file_name = util_realloc_string_copy( model_config->gen_kw_export_file_name , file_name ); -} - -const char * model_config_get_gen_kw_export_file( const model_config_type * model_config) { - return model_config->gen_kw_export_file_name; -} - - - - void model_config_set_enspath( model_config_type * model_config , const char * enspath) { - model_config->enspath = util_realloc_string_copy( model_config->enspath , enspath ); - } - - void model_config_set_rftpath( model_config_type * model_config , const char * rftpath) { - model_config->rftpath = util_realloc_string_copy( model_config->rftpath , rftpath ); - } - - void model_config_set_dbase_type( model_config_type * model_config , const char * dbase_type_string) { - model_config->dbase_type = fs_types_lookup_string_name( dbase_type_string ); - if (model_config->dbase_type == INVALID_DRIVER_ID) - util_abort("%s: did not recognize driver_type:%s \n",__func__ , dbase_type_string); - } - - - const char * model_config_get_enspath( const model_config_type * model_config) { - return model_config->enspath; - } - -const char * model_config_get_rftpath( const model_config_type * model_config) { - return model_config->rftpath; -} - -fs_driver_impl model_config_get_dbase_type(const model_config_type * model_config ) { - return model_config->dbase_type; -} - -const ecl_sum_type * model_config_get_refcase( const model_config_type * model_config ) { - return model_config->refcase; -} - -void * model_config_get_dbase_args( const model_config_type * model_config ) { - return NULL; -} - - -void model_config_set_refcase( model_config_type * model_config , const ecl_sum_type * refcase ) { - model_config->refcase = refcase; -} - - -history_source_type model_config_get_history_source( const model_config_type * model_config ) { - return model_config->history_source; -} - - - -void model_config_select_schedule_history( model_config_type * model_config , const sched_file_type * sched_file) { - if (model_config->history != NULL) - history_free( model_config->history ); - - if (sched_file != NULL) { - model_config->history = history_alloc_from_sched_file( SUMMARY_KEY_JOIN_STRING , sched_file); - model_config->history_source = SCHEDULE; - } else - util_abort("%s: internal error - trying to select HISTORY_SOURCE:SCHEDULE - but no Schedule file has been loaded.\n",__func__); -} - - -void model_config_select_refcase_history( model_config_type * model_config , const ecl_sum_type * refcase , bool use_history) { - if (model_config->history != NULL) - history_free( model_config->history ); - - if (refcase != NULL) { - model_config->history = history_alloc_from_refcase( refcase , use_history ); - model_config->history_source = SCHEDULE; - } else - util_abort("%s: internal error - trying to load history from REFCASE - but no REFCASE has been loaded.\n",__func__); -} - - -int model_config_get_max_internal_submit( const model_config_type * config ) { - return config->max_internal_submit; -} - -void model_config_set_max_internal_submit( model_config_type * model_config , int max_resample ) { - model_config->max_internal_submit = max_resample; -} - - -UTIL_IS_INSTANCE_FUNCTION( model_config , MODEL_CONFIG_TYPE_ID) - -model_config_type * model_config_alloc() { - model_config_type * model_config = util_malloc(sizeof * model_config ); - /** - There are essentially three levels of initialisation: - - 1. Initialize to NULL / invalid. - 2. Initialize with default values. - 3. Initialize with user supplied values. - - */ - UTIL_TYPE_ID_INIT(model_config , MODEL_CONFIG_TYPE_ID); - model_config->case_names = NULL; - model_config->enspath = NULL; - model_config->rftpath = NULL; - model_config->dbase_type = INVALID_DRIVER_ID; - model_config->current_runpath = NULL; - model_config->current_path_key = NULL; - model_config->case_table_file = NULL; - model_config->history = NULL; - model_config->jobname_fmt = NULL; - model_config->forward_model = NULL; - model_config->external_time_map = NULL; - model_config->internalize_state = bool_vector_alloc( 0 , false ); - model_config->__load_eclipse_restart = bool_vector_alloc( 0 , false ); - model_config->history_source = HISTORY_SOURCE_INVALID; - model_config->runpath_map = hash_alloc(); - model_config->gen_kw_export_file_name = NULL; - model_config->refcase = NULL; - - model_config_set_enspath( model_config , DEFAULT_ENSPATH ); - model_config_set_rftpath( model_config , DEFAULT_RFTPATH ); - model_config_set_dbase_type( model_config , DEFAULT_DBASE_TYPE ); - model_config_set_max_internal_submit( model_config , DEFAULT_MAX_INTERNAL_SUBMIT); - model_config_add_runpath( model_config , DEFAULT_RUNPATH_KEY , DEFAULT_RUNPATH); - model_config_select_runpath( model_config , DEFAULT_RUNPATH_KEY ); - model_config_set_gen_kw_export_file(model_config, DEFAULT_GEN_KW_EXPORT_FILE); - - return model_config; -} - - -bool model_config_select_history( model_config_type * model_config , history_source_type source_type, const sched_file_type * sched_file , const ecl_sum_type * refcase) { - bool selectOK = false; - - if (source_type == SCHEDULE && sched_file != NULL) { - model_config_select_schedule_history( model_config , sched_file ); - selectOK = true; - } - - if (((source_type == REFCASE_HISTORY) || (source_type == REFCASE_SIMULATED)) && refcase != NULL) { - if (source_type == REFCASE_HISTORY) - model_config_select_refcase_history( model_config , refcase , true); - else - model_config_select_refcase_history( model_config , refcase , false); - selectOK = true; - } - - return selectOK; -} - - -static bool model_config_select_any_history( model_config_type * model_config , const sched_file_type * sched_file , const ecl_sum_type * refcase) { - bool selectOK = false; - - if (sched_file != NULL) { - model_config_select_schedule_history( model_config , sched_file ); - selectOK = true; - } else if ( refcase != NULL ) { - model_config_select_refcase_history( model_config , refcase , true); - selectOK = true; - } - - return selectOK; -} - - - - -void model_config_init(model_config_type * model_config , - const config_content_type * config , - int ens_size , - const ext_joblist_type * joblist , - int last_history_restart , - const sched_file_type * sched_file , - const ecl_sum_type * refcase) { - - model_config->forward_model = forward_model_alloc( joblist ); - model_config_set_refcase( model_config , refcase ); - - - if (config_content_has_item( config , FORWARD_MODEL_KEY )) { - char * config_string = config_content_alloc_joined_string( config , FORWARD_MODEL_KEY , " "); - forward_model_parse_init( model_config->forward_model , config_string ); - free(config_string); - } - - if (config_content_has_item( config, RUNPATH_KEY)) { - model_config_add_runpath( model_config , DEFAULT_RUNPATH_KEY , config_content_get_value(config , RUNPATH_KEY) ); - model_config_select_runpath( model_config , DEFAULT_RUNPATH_KEY ); - } - - { - history_source_type source_type = DEFAULT_HISTORY_SOURCE; - - if (config_content_has_item( config , HISTORY_SOURCE_KEY)) { - const char * history_source = config_content_iget(config , HISTORY_SOURCE_KEY, 0,0); - source_type = history_get_source_type( history_source ); - } - - if (!model_config_select_history( model_config , source_type , sched_file , refcase )) - if (!model_config_select_history( model_config , DEFAULT_HISTORY_SOURCE , sched_file , refcase )) - if (!model_config_select_any_history( model_config , sched_file , refcase)) - fprintf(stderr,"** Warning:: Do not have enough information to select a history source \n"); - - } - - if (model_config->history != NULL) { - int num_restart = model_config_get_last_history_restart(model_config); - bool_vector_iset( model_config->internalize_state , num_restart - 1 , false ); - bool_vector_iset( model_config->__load_eclipse_restart , num_restart - 1 , false ); - } - - if (config_content_has_item( config , TIME_MAP_KEY)) { - const char * filename = config_content_get_value_as_path( config , TIME_MAP_KEY); - time_map_type * time_map = time_map_alloc(); - if (time_map_fscanf( time_map , filename)) - model_config->external_time_map = time_map; - else { - time_map_free( time_map ); - fprintf(stderr,"** ERROR: Loading external time map from:%s failed \n", filename); - } - } - - - - /* - The full treatment of the SCHEDULE_PREDICTION_FILE keyword is in - the ensemble_config file, because the functionality is implemented - as (quite) plain GEN_KW instance. Here we just check if it is - present or not. - */ - - if (config_content_has_item(config , SCHEDULE_PREDICTION_FILE_KEY)) - model_config->has_prediction = true; - else - model_config->has_prediction = false; - - - if (config_content_has_item(config , CASE_TABLE_KEY)) - model_config_set_case_table( model_config , ens_size , config_content_iget( config , CASE_TABLE_KEY , 0,0)); - - if (config_content_has_item( config , ENSPATH_KEY)) - model_config_set_enspath( model_config , config_content_get_value(config , ENSPATH_KEY)); - - if (config_content_has_item( config , JOBNAME_KEY)) - model_config_set_jobname_fmt( model_config , config_content_get_value(config , JOBNAME_KEY)); - - if (config_content_has_item( config , RFTPATH_KEY)) - model_config_set_rftpath( model_config , config_content_get_value(config , RFTPATH_KEY)); - - if (config_content_has_item( config , DBASE_TYPE_KEY)) - model_config_set_dbase_type( model_config , config_content_get_value(config , DBASE_TYPE_KEY)); - - if (config_content_has_item( config , MAX_RESAMPLE_KEY)) - model_config_set_max_internal_submit( model_config , config_content_get_value_as_int( config , MAX_RESAMPLE_KEY )); - - - { - const char * export_file_name; - if (config_content_has_item( config , GEN_KW_EXPORT_FILE_KEY)) - export_file_name = config_content_get_value(config, GEN_KW_EXPORT_FILE_KEY); - else - export_file_name = DEFAULT_GEN_KW_EXPORT_FILE; - - model_config_set_gen_kw_export_file(model_config, export_file_name); - } -} - - -const char * model_config_iget_casename( const model_config_type * model_config , int index) { - if (model_config->case_names == NULL) - return NULL; - else - return stringlist_iget( model_config->case_names , index ); -} - - - -void model_config_free(model_config_type * model_config) { - free( model_config->enspath ); - free( model_config->rftpath ); - util_safe_free( model_config->jobname_fmt ); - util_safe_free( model_config->case_table_file ); - util_safe_free( model_config->current_path_key); - util_safe_free( model_config->gen_kw_export_file_name); - - if (model_config->history) - history_free(model_config->history); - - if (model_config->forward_model) - forward_model_free(model_config->forward_model); - - if (model_config->external_time_map) - time_map_free( model_config->external_time_map ); - - - bool_vector_free(model_config->internalize_state); - bool_vector_free(model_config->__load_eclipse_restart); - hash_free(model_config->runpath_map); - - if (model_config->case_names) - stringlist_free( model_config->case_names ); - free(model_config); -} - - - -bool model_config_has_history(const model_config_type * config) { - if (config->history != NULL) - return true; - else - return false; -} - - -history_type * model_config_get_history(const model_config_type * config) { - return config->history; -} - -/** - Will be NULL unless the user has explicitly loaded an external time - map with the TIME_MAP config option. -*/ - -time_map_type * model_config_get_external_time_map( const model_config_type * config) { - return config->external_time_map; -} - -int model_config_get_last_history_restart(const model_config_type * config) { - if (config->history) - return history_get_last_restart( config->history ); - else { - if (config->external_time_map) - return time_map_get_last_step( config->external_time_map); - else { - fprintf(stderr,"** Warning: Trying to get the last restart number - no history/time_map object has been registered.\n"); - return 0; - } - } -} - - -bool model_config_has_prediction(const model_config_type * config) { - return config->has_prediction; -} - - -forward_model_type * model_config_get_forward_model( const model_config_type * config) { - return config->forward_model; -} - - -/*****************************************************************/ - -/* Setting everything back to the default value: false. */ -void model_config_init_internalization( model_config_type * config ) { - bool_vector_reset(config->internalize_state); - bool_vector_reset(config->__load_eclipse_restart); -} - - -/** - This function sets the internalize_state flag to true for - report_step. Because of the coupling to the __load_eclipse_restart variable - this function can __ONLY__ be used to set internalize to true. -*/ - -void model_config_set_internalize_state( model_config_type * config , int report_step) { - bool_vector_iset(config->internalize_state , report_step , true); - bool_vector_iset(config->__load_eclipse_restart , report_step , true); -} - - -void model_config_set_load_state( model_config_type * config , int report_step) { - bool_vector_iset(config->__load_eclipse_restart , report_step , true); -} - - - -/* Query functions. */ - -bool model_config_internalize_state( const model_config_type * config , int report_step) { - return bool_vector_iget(config->internalize_state , report_step); -} - -/*****************************************************************/ - -bool model_config_load_state( const model_config_type * config , int report_step) { - return bool_vector_iget(config->__load_eclipse_restart , report_step); -} - - - - - -void model_config_fprintf_config( const model_config_type * model_config , int ens_size , FILE * stream ) { - fprintf( stream , CONFIG_COMMENTLINE_FORMAT ); - fprintf( stream , CONFIG_COMMENT_FORMAT , "Here comes configuration information related to this model."); - - if (model_config->case_table_file != NULL) { - fprintf( stream , CONFIG_KEY_FORMAT , CASE_TABLE_KEY ); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , model_config->case_table_file ); - } - fprintf( stream , CONFIG_KEY_FORMAT , FORWARD_MODEL_KEY); - forward_model_fprintf( model_config->forward_model , stream ); - - fprintf( stream , CONFIG_KEY_FORMAT , RUNPATH_KEY ); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , path_fmt_get_fmt( model_config->current_runpath )); - - fprintf( stream , CONFIG_KEY_FORMAT , ENSPATH_KEY ); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , model_config->enspath ); - - fprintf( stream , CONFIG_KEY_FORMAT , RFTPATH_KEY ); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , model_config->rftpath ); - - fprintf( stream , CONFIG_KEY_FORMAT , MAX_RESAMPLE_KEY ); - { - char max_retry_string[16]; - sprintf( max_retry_string , "%d" ,model_config->max_internal_submit); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , max_retry_string); - } - - fprintf(stream , CONFIG_KEY_FORMAT , HISTORY_SOURCE_KEY); - fprintf(stream , CONFIG_ENDVALUE_FORMAT , history_get_source_string( model_config->history_source )); - - fprintf(stream , CONFIG_KEY_FORMAT , NUM_REALIZATIONS_KEY); - fprintf(stream , CONFIG_INT_FORMAT , ens_size); - fprintf(stream , "\n\n"); - -} diff --git a/ThirdParty/Ert/libenkf/src/obs_data.c b/ThirdParty/Ert/libenkf/src/obs_data.c deleted file mode 100644 index 0e2f0bd758..0000000000 --- a/ThirdParty/Ert/libenkf/src/obs_data.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'obs_data.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/** -See the file README.obs for ducumentation of the varios datatypes -involved with observations/measurement/+++. - - -The file contains two different variables holding the number of -observations, nrobs_total and nrobs_active. The first holds the total -number of observations at this timestep, and the second holds the -number of active measurements at this timestep; the inactive -measurements have been deactivated the obs_data_deactivate_outliers() -function. - -The flow is as follows: - - 1. All the observations have been collected in an obs_data instance, - and all the corresponding measurements of the state have been - collected in a meas_data instance - we are ready for analysis. - - 2. The functions meas_data_alloc_stats() is called to calculate - the ensemble mean and std of all the measurements. - - 3. The function obs_data_deactivate_outliers() is called to compare - the ensemble mean and std with the observations, in the case of - outliers the number obs_active flag of the obs_data instance is - set to false. - - 4. The remaining functions (and matrices) now refer to the number of - active observations, however the "raw" observations found in the - obs_data instance are in a vector with nrobs_total observations; - i.e. we must handle two indices and two total lengths. A bit - messy. - - -Variables of size nrobs_total: ------------------------------- - o obs->value / obs->std / obs->obs_active - o meanS , innov, stdS - - -variables of size nrobs_active: -------------------------------- -Matrices: S, D, E and various internal variables. -*/ - - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#define OBS_BLOCK_TYPE_ID 995833 - -struct obs_block_struct { - UTIL_TYPE_ID_DECLARATION; - char * obs_key; - int size; - double * value; - double * std; - - active_type * active_mode; - int active_size; - matrix_type * error_covar; - bool error_covar_owner; /* If true the error_covar matrix is free'd when construction of the R matrix is complete. */ - double global_std_scaling; -}; - - - -struct obs_data_struct { - vector_type * data; /* vector with obs_block instances. */ - double global_std_scaling; -}; - - - -static UTIL_SAFE_CAST_FUNCTION(obs_block , OBS_BLOCK_TYPE_ID ) - -obs_block_type * obs_block_alloc( const char * obs_key , int obs_size , matrix_type * error_covar , bool error_covar_owner, double global_std_scaling) { - obs_block_type * obs_block = util_malloc( sizeof * obs_block ); - - UTIL_TYPE_ID_INIT( obs_block , OBS_BLOCK_TYPE_ID ); - obs_block->size = obs_size; - obs_block->obs_key = util_alloc_string_copy( obs_key ); - obs_block->value = util_calloc( obs_size , sizeof * obs_block->value ); - obs_block->std = util_calloc( obs_size , sizeof * obs_block->std ); - obs_block->active_mode = util_calloc( obs_size , sizeof * obs_block->active_mode ); - obs_block->error_covar = error_covar; - obs_block->error_covar_owner = error_covar_owner; - obs_block->global_std_scaling = global_std_scaling; - { - for (int iobs = 0; iobs < obs_size; iobs++) - obs_block->active_mode[iobs] = LOCAL_INACTIVE; - } - obs_block->active_size = 0; - return obs_block; -} - - - -void obs_block_free( obs_block_type * obs_block ) { - free( obs_block->obs_key ); - free( obs_block->value ); - free( obs_block->std ); - free( obs_block->active_mode ); - free( obs_block ); -} - - -static void obs_block_free__( void * arg ) { - obs_block_type * obs_block = obs_block_safe_cast( arg ); - obs_block_free( obs_block ); -} - - -static void obs_block_fprintf( const obs_block_type * obs_block , FILE * stream ) { - for (int iobs=0; iobs < obs_block->size; iobs++) - fprintf(stream , "[ %12.5f +/- %12.5f ] \n" , obs_block->value[iobs] , obs_block->std[iobs]); -} - - -void obs_block_deactivate( obs_block_type * obs_block , int iobs , bool verbose , const char * msg) { - if (obs_block->active_mode[ iobs ] == ACTIVE) { - if (verbose) - printf("Deactivating: %s(%d) : %s \n",obs_block->obs_key , iobs , msg); - obs_block->active_mode[ iobs ] = DEACTIVATED; - obs_block->active_size--; - } -} - - -const char * obs_block_get_key( const obs_block_type * obs_block) { return obs_block->obs_key; } - -void obs_block_iset( obs_block_type * obs_block , int iobs , double value , double std) { - obs_block->value[ iobs ] = value; - obs_block->std[ iobs ] = std; - if (obs_block->active_mode[ iobs ] != ACTIVE) { - obs_block->active_mode[iobs] = ACTIVE; - obs_block->active_size++; - } -} - -void obs_block_iset_missing( obs_block_type * obs_block , int iobs ) { - if (obs_block->active_mode[ iobs ] == ACTIVE) - obs_block->active_size--; - obs_block->active_mode[iobs] = MISSING; -} - - -double obs_block_iget_std( const obs_block_type * obs_block , int iobs) { - return obs_block->std[ iobs ] * obs_block->global_std_scaling; -} - - -double obs_block_iget_value( const obs_block_type * obs_block , int iobs) { - return obs_block->value[ iobs ]; -} - - -active_type obs_block_iget_active_mode( const obs_block_type * obs_block , int iobs) { - return obs_block->active_mode[ iobs ]; -} - - - -int obs_block_get_size( const obs_block_type * obs_block ) { - return obs_block->size; -} - - -int obs_block_get_active_size( const obs_block_type * obs_block ) { - return obs_block->active_size; -} - - - - -/*Function that sets each element of the scaling factor equal to 1 divided by the prior standard deviation (from the - obs_data input file. -*/ -static void obs_block_init_scaling( const obs_block_type * obs_block , double * scale_factor , int * __obs_offset) { - int obs_offset = *__obs_offset; - int iobs; - for (iobs =0; iobs < obs_block->size; iobs++) { - if (obs_block->active_mode[iobs] == ACTIVE) { - scale_factor[ obs_offset ] = 1.0 / obs_block_iget_std(obs_block, iobs); - obs_offset++; - } - } - *__obs_offset = obs_offset; -} - - -/* -static void obs_block_init_innov( const obs_block_type * obs_block , const meas_block_type * meas_block , matrix_type * innov , int * __obs_offset) { - int obs_offset = *__obs_offset; - int iobs; - for (iobs =0; iobs < obs_block->size; iobs++) { - if (obs_block->active_mode[iobs] == ACTIVE) { - matrix_iset( innov , obs_offset , 0 , obs_block->value[ iobs ] - meas_block_iget_ens_mean( meas_block , iobs )); - obs_offset++; - } - } - *__obs_offset = obs_offset; -} -*/ - -static void obs_block_initdObs( const obs_block_type * obs_block , matrix_type * dObs , int * __obs_offset) { - int obs_offset = *__obs_offset; - int iobs; - for (iobs =0; iobs < obs_block->size; iobs++) { - if (obs_block->active_mode[iobs] == ACTIVE) { - matrix_iset( dObs , obs_offset , 0 , obs_block->value[ iobs ]); - matrix_iset( dObs , obs_offset , 1 , obs_block->std[ iobs ]); - obs_offset++; - } - } - *__obs_offset = obs_offset; -} - - - - - - -static void obs_block_initR( const obs_block_type * obs_block , matrix_type * R, int * __obs_offset) { - int obs_offset = *__obs_offset; - if (obs_block->error_covar == NULL) { - int iobs; - int iactive = 0; - for (iobs =0; iobs < obs_block->size; iobs++) { - if (obs_block->active_mode[iobs] == ACTIVE) { - double var = obs_block_iget_std(obs_block, iobs) * obs_block_iget_std(obs_block, iobs); - matrix_iset_safe(R , obs_offset + iactive, obs_offset + iactive, var); - iactive++; - } - } - } else { - int row_active = 0; /* We have a covar matrix */ - for (int row = 0; row < obs_block->size; row++) { - if (obs_block->active_mode[row] == ACTIVE) { - int col_active = 0; - for (int col = 0; col < obs_block->size; col++) { - if (obs_block->active_mode[col] == ACTIVE) { - matrix_iset_safe(R , obs_offset + row_active , obs_offset + col_active , matrix_iget( obs_block->error_covar , row , col )); - col_active++; - } - } - row_active++; - } - } - } - - *__obs_offset = obs_offset + obs_block->active_size; - if ((obs_block->error_covar_owner) && (obs_block->error_covar != NULL)) - matrix_free( obs_block->error_covar ); -} - - - -static void obs_block_initE( const obs_block_type * obs_block , matrix_type * E, const double * pert_var , int * __obs_offset) { - int ens_size = matrix_get_columns( E ); - int obs_offset = *__obs_offset; - int iobs; - for (iobs =0; iobs < obs_block->size; iobs++) { - if (obs_block->active_mode[iobs] == ACTIVE) { - double factor = obs_block_iget_std(obs_block, iobs) * sqrt( ens_size / pert_var[ obs_offset ]); - for (int iens = 0; iens < ens_size; iens++) - matrix_imul(E , obs_offset , iens , factor ); - - obs_offset++; - } - } - - *__obs_offset = obs_offset; -} - - -static void obs_block_initE_non_centred( const obs_block_type * obs_block , matrix_type * E, int * __obs_offset) { - int ens_size = matrix_get_columns( E ); - int obs_offset = *__obs_offset; - int iobs; - for (iobs =0; iobs < obs_block->size; iobs++) { - if (obs_block->active_mode[iobs] == ACTIVE) { - double factor = obs_block_iget_std(obs_block, iobs); - for (int iens = 0; iens < ens_size; iens++) - matrix_imul(E , obs_offset , iens , factor ); - - obs_offset++; - } - } - - *__obs_offset = obs_offset; -} - - - -static void obs_block_initD( const obs_block_type * obs_block , matrix_type * D, int * __obs_offset) { - int ens_size = matrix_get_columns( D ); - int obs_offset = *__obs_offset; - int iobs; - for (iobs =0; iobs < obs_block->size; iobs++) { - if (obs_block->active_mode[iobs] == ACTIVE) { - for (int iens = 0; iens < ens_size; iens++) - matrix_iadd(D , obs_offset , iens , obs_block->value[ iobs ]); - - obs_offset++; - } - } - - *__obs_offset = obs_offset; -} - - -/*****************************************************************/ - - -obs_data_type * obs_data_alloc(double global_std_scaling) { - obs_data_type * obs_data = util_malloc(sizeof * obs_data ); - obs_data->data = vector_alloc_new(); - obs_data->global_std_scaling = global_std_scaling; - obs_data_reset(obs_data); - return obs_data; -} - - - -void obs_data_reset(obs_data_type * obs_data) { - vector_clear( obs_data->data ); -} - - -obs_block_type * obs_data_add_block( obs_data_type * obs_data , const char * obs_key , int obs_size , matrix_type * error_covar, bool error_covar_owner) { - obs_block_type * new_block = obs_block_alloc( obs_key , obs_size , error_covar , error_covar_owner, obs_data->global_std_scaling); - vector_append_owned_ref( obs_data->data , new_block , obs_block_free__ ); - return new_block; -} - - -obs_block_type * obs_data_iget_block( obs_data_type * obs_data , int index ) { - return vector_iget( obs_data->data , index); -} - - -const obs_block_type * obs_data_iget_block_const( const obs_data_type * obs_data , int index ) { - return vector_iget_const( obs_data->data , index ); -} - - -void obs_data_free(obs_data_type * obs_data) { - vector_free( obs_data->data ); - free(obs_data); -} - - - -matrix_type * obs_data_allocE(const obs_data_type * obs_data , rng_type * rng , int active_ens_size ) { - double *pert_mean , *pert_var; - matrix_type * E; - int iens, iobs_active; - int active_obs_size = obs_data_get_active_size( obs_data ); - - E = matrix_alloc( active_obs_size , active_ens_size); - - pert_mean = util_calloc(active_obs_size , sizeof * pert_mean ); - pert_var = util_calloc(active_obs_size , sizeof * pert_var ); - { - double * tmp = util_calloc( active_obs_size * active_ens_size , sizeof * tmp ); - int i,j; - int k = 0; - - enkf_util_rand_stdnormal_vector(active_obs_size * active_ens_size , tmp , rng); - for (j=0; j < active_ens_size; j++) { - for (i=0; i < active_obs_size; i++) { - matrix_iset( E , i , j , tmp[k]); - k++; - } - } - free(tmp); - } - - for (iobs_active = 0; iobs_active < active_obs_size; iobs_active++) { - pert_mean[iobs_active] = 0; - pert_var[iobs_active] = 0; - } - - for (iens = 0; iens < active_ens_size; iens++) - for (iobs_active = 0; iobs_active < active_obs_size; iobs_active++) - pert_mean[iobs_active] += matrix_iget(E , iobs_active , iens); - - - for (iobs_active = 0; iobs_active < active_obs_size; iobs_active++) - pert_mean[iobs_active] /= active_ens_size; - - for (iens = 0; iens < active_ens_size; iens++) { - for (iobs_active = 0; iobs_active < active_obs_size; iobs_active++) { - double tmp; - matrix_iadd(E , iobs_active , iens , -pert_mean[iobs_active]); - tmp = matrix_iget(E , iobs_active , iens); - pert_var[iobs_active] += tmp * tmp; - } - } - - /* - The actual observed data are not accessed before this last block. - */ - { - int obs_offset = 0; - for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { - const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr); - obs_block_initE( obs_block , E , pert_var , &obs_offset); - } - } - - free(pert_mean); - free(pert_var); - - matrix_set_name( E , "E"); - matrix_assert_finite( E ); - return E; -} - - -/* Function that returns a matrix of independent, normal distributed random vector having mean zero, - and variance (covariance) specified in the input (obs_data) file. NOTICE THE DIFFERENCE WITH allocE, WHERE THE - RETURNED MATRIX IS CENTRED -*/ - - -matrix_type * obs_data_allocE_non_centred(const obs_data_type * obs_data , rng_type * rng , int ens_size) { - matrix_type * E; - int active_size = obs_data_get_active_size( obs_data ); - E = matrix_alloc( active_size , ens_size); - - { - double * tmp = util_calloc( active_size * ens_size , sizeof * tmp ); - int i,j; - int k = 0; - - enkf_util_rand_stdnormal_vector(active_size * ens_size , tmp , rng); - for (j=0; j < ens_size; j++) { - for (i=0; i < active_size; i++) { - matrix_iset( E , i , j , tmp[k]); - k++; - } - } - free(tmp); - } - - - /* - The actual observed data are not accessed before this last block. - */ - { - int obs_offset = 0; - for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { - const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr); - obs_block_initE_non_centred( obs_block , E , &obs_offset); - } - } - - - matrix_set_name( E , "E"); - matrix_assert_finite( E ); - return E; -} - -matrix_type * obs_data_allocD(const obs_data_type * obs_data , const matrix_type * E , const matrix_type * S) { - matrix_type * D = matrix_alloc_copy( E ); - matrix_inplace_sub( D , S ); - - { - int obs_offset = 0; - for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { - const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr); - obs_block_initD( obs_block , D , &obs_offset); - } - } - - matrix_set_name( D , "D"); - matrix_assert_finite( D ); - return D; -} - - - - -matrix_type * obs_data_allocR(const obs_data_type * obs_data) { - int active_size = obs_data_get_active_size( obs_data ); - matrix_type * R = matrix_alloc( active_size , active_size ); - { - int obs_offset = 0; - for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { - const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr); - obs_block_initR( obs_block , R , &obs_offset); - } - } - - matrix_set_name( R , "R"); - matrix_assert_finite( R ); - return R; -} - -/* -matrix_type * obs_data_alloc_innov(const obs_data_type * obs_data , const meas_data_type * meas_data , int active_size) { - matrix_type * innov = matrix_alloc( active_size , 1 ); - { - int obs_offset = 0; - for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { - const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr ); - const meas_block_type * meas_block = meas_data_iget_block_const( meas_data , block_nr ); - - obs_block_init_innov( obs_block , meas_block , innov , &obs_offset); - } - } - return innov; -} -*/ - -matrix_type * obs_data_allocdObs(const obs_data_type * obs_data ) { - int active_size = obs_data_get_active_size( obs_data ); - matrix_type * dObs = matrix_alloc( active_size , 2 ); - { - int obs_offset = 0; - for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { - const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr ); - - obs_block_initdObs( obs_block , dObs , &obs_offset); - } - } - return dObs; -} - - -static void obs_data_scale_matrix__(matrix_type * m , const double * scale_factor) { - const int rows = matrix_get_rows( m ); - const int columns = matrix_get_columns( m ); - int i, j; - - for (i = 0; i < columns; i++) - for (j = 0; j < rows; j++) - matrix_imul(m , j,i, scale_factor[j]); - -} - - -static void obs_data_scale_Rmatrix__( matrix_type * R , const double * scale_factor) { - int nrobs_active = matrix_get_rows( R ); - - /* Scale the error covariance matrix*/ - for (int i=0; i < nrobs_active; i++) - for (int j=0; j < nrobs_active; j++) - matrix_imul(R , i , j , scale_factor[i] * scale_factor[j]); -} - - -static double * obs_data_alloc_scale_factor(const obs_data_type * obs_data ) { - int nrobs_active = obs_data_get_active_size( obs_data ); - double * scale_factor = util_calloc(nrobs_active , sizeof * scale_factor ); - int obs_offset = 0; - for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { - const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr ); - - /* Init. the scaling factor ( 1/std(dObs) ) */ - obs_block_init_scaling( obs_block , scale_factor , &obs_offset); - } - - return scale_factor; -} - - -void obs_data_scale_matrix(const obs_data_type * obs_data , matrix_type * matrix) { - double * scale_factor = obs_data_alloc_scale_factor( obs_data ); - obs_data_scale_matrix__( matrix , scale_factor ); - free( scale_factor ); -} - - -void obs_data_scale_Rmatrix(const obs_data_type * obs_data , matrix_type * R) { - double * scale_factor = obs_data_alloc_scale_factor( obs_data ); - obs_data_scale_Rmatrix__( R , scale_factor ); - free( scale_factor ); -} - - -void obs_data_scale(const obs_data_type * obs_data , matrix_type *S , matrix_type *E , matrix_type *D , matrix_type *R , matrix_type * dObs) { - double * scale_factor = obs_data_alloc_scale_factor( obs_data ); - - /* Scale the forecasted data so that they (in theory) have the same variance - (if the prior distribution for the observation errors is correct) */ - obs_data_scale_matrix__( S , scale_factor ); - - /* Scale the combined data matrix: D = DObs + E - S, where DObs is the iobs_active times ens_size matrix where - each column contains a copy of the observed data - */ - if (D != NULL) - obs_data_scale_matrix__( D , scale_factor ); - - /* Same with E (used for low rank representation of the error covariance matrix*/ - if (E != NULL) - obs_data_scale_matrix__( E , scale_factor ); - - if (dObs != NULL) - obs_data_scale_matrix__( dObs , scale_factor ); - - if (R != NULL) - obs_data_scale_Rmatrix__(R , scale_factor); - - free(scale_factor); -} - - -void obs_data_scale_kernel(const obs_data_type * obs_data , matrix_type *S , matrix_type *E , matrix_type *D , double *dObs) { - const int nrobs_active = matrix_get_rows( S ); - const int ens_size = matrix_get_columns( S ); - double * scale_factor = util_calloc(nrobs_active , sizeof * scale_factor ); - int iens, iobs_active; - - { - int obs_offset = 0; - for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { - const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr ); - - /* Init. the scaling factor ( 1/std(dObs) ) */ - obs_block_init_scaling( obs_block , scale_factor , &obs_offset); - } - } - - - for (iens = 0; iens < ens_size; iens++) { - for (iobs_active = 0; iobs_active < nrobs_active; iobs_active++) { - - /* Scale the forecasted data so that they (in theory) have the same variance - (if the prior distribution for the observation errors is correct) */ - matrix_imul(S , iobs_active , iens , scale_factor[iobs_active]); - - if (D != NULL) - /* Scale the combined data matrix: D = DObs + E - S, where DObs is the iobs_active times ens_size matrix where - each column contains a copy of the observed data - */ - matrix_imul(D , iobs_active , iens , scale_factor[iobs_active]); - - if (E != NULL) - /* Same with E (used for low rank representation of the error covariance matrix*/ - matrix_imul(E , iobs_active , iens , scale_factor[iobs_active]); - } - } - - /* Scale the vector of observed data*/ - if (dObs != NULL) { - for (iobs_active = 0; iobs_active < nrobs_active; iobs_active++) - dObs[iobs_active] *= scale_factor[iobs_active]; - } - - - free(scale_factor); -} - - - - -int obs_data_get_active_size( const obs_data_type * obs_data ) { - int active_size = 0; - for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { - const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr ); - active_size += obs_block->active_size; - } - - return active_size; -} - - -int obs_data_get_num_blocks( const obs_data_type * obs_data ) { - return vector_get_size( obs_data->data ); -} - - - -int obs_data_get_total_size( const obs_data_type * obs_data ) { - int total_size = 0; - for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { - const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr ); - total_size += obs_block->size; - } - return total_size; -} - - -static const obs_block_type * obs_data_lookup_block( const obs_data_type * obs_data, int total_index , int * block_offset) { - if (total_index < obs_data_get_total_size( obs_data )) { - const obs_block_type * obs_block; - int total_offset = 0; - int block_index = 0; - int block_size; - - - while (true) { - obs_block = vector_iget_const( obs_data->data , block_index ); - block_size = obs_block->size; - if ((block_size + total_offset) > total_index) - break; - - total_offset += block_size; - block_index++; - } - *block_offset = total_offset; - return obs_block; - } else { - util_abort("%s: could not lookup obs-block \n",__func__); - return NULL; - } -} - - -double obs_data_iget_value( const obs_data_type * obs_data , int total_index ) { - int total_offset; - const obs_block_type * obs_block = obs_data_lookup_block( obs_data , total_index , &total_offset ); - return obs_block_iget_value( obs_block , total_index - total_offset ); -} - - -double obs_data_iget_std( const obs_data_type * obs_data , int total_index ) { - int total_offset; - const obs_block_type * obs_block = obs_data_lookup_block( obs_data , total_index , &total_offset ); - return obs_block_iget_std( obs_block , total_index - total_offset ); -} - - -void obs_data_fprintf( const obs_data_type * obs_data , FILE * stream) { - fprintf(stream , "\n"); - for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) { - const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr ); - obs_block_fprintf( obs_block , stream ); - } - fprintf(stream , "\n"); -} diff --git a/ThirdParty/Ert/libenkf/src/obs_vector.c b/ThirdParty/Ert/libenkf/src/obs_vector.c deleted file mode 100644 index 6420c6899b..0000000000 --- a/ThirdParty/Ert/libenkf/src/obs_vector.c +++ /dev/null @@ -1,1118 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'obs_vector.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/** - See the overview documentation of the observation system in enkf_obs.c -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define OBS_VECTOR_TYPE_ID 120086 - -struct obs_vector_struct { - UTIL_TYPE_ID_DECLARATION; - obs_free_ftype *freef; /* Function used to free an observation node. */ - obs_get_ftype *get_obs; /* Function used to build the 'd' vector. */ - obs_meas_ftype *measure; /* Function used to measure on the state, and add to to the S matrix. */ - obs_user_get_ftype *user_get; /* Function to get an observation based on KEY:INDEX input from user.*/ - obs_chi2_ftype *chi2; /* Function to evaluate chi-squared for an observation. */ - obs_update_std_scale_ftype *update_std_scale; /* Function to scale the standard deviation with a given factor */ - - vector_type * nodes; - char * obs_key; /* The key this observation vector has in the enkf_obs layer. */ - enkf_config_node_type * config_node; /* The config_node of the node type we are observing - shared reference */ - obs_impl_type obs_type; - int num_active; /* The total number of timesteps where this observation is active (i.e. nodes[ ] != NULL) */ - int_vector_type * step_list; -}; - - -UTIL_IS_INSTANCE_FUNCTION(obs_vector , OBS_VECTOR_TYPE_ID) -UTIL_SAFE_CAST_FUNCTION(obs_vector , OBS_VECTOR_TYPE_ID) - -/*****************************************************************/ - - -static void obs_vector_prefer_RESTART_warning() { - fprintf(stderr," -------------------------------------------------------------------------------\n"); - fprintf(stderr," Warning: For GEN_OBS observations it is highly recommended to use the RESTART \n"); - fprintf(stderr," keyword to denote the time of the observation. The RESTART value \n"); - fprintf(stderr," should be matched with the report step embedded as part of the \n"); - fprintf(stderr," GEN_DATA result file created by the forward model. \n"); - fprintf(stderr,"\n"); - fprintf(stderr," In the future use OF DATE and DAYS will not be possible for GEN_OBS \n"); - fprintf(stderr," -------------------------------------------------------------------------------\n"); - fprintf(stderr,"\n"); - fprintf(stderr,"\n"); -} - - - -static int __conf_instance_get_restart_nr(const conf_instance_type * conf_instance, const char * obs_key , time_map_type * time_map , bool prefer_restart) { - int obs_restart_nr = -1; /* To shut up compiler warning. */ - - if(conf_instance_has_item(conf_instance, "RESTART")) { - obs_restart_nr = conf_instance_get_item_value_int(conf_instance, "RESTART"); - if (obs_restart_nr > time_map_get_last_step( time_map)) - util_abort("%s: Observation %s occurs at restart %i, but history file has only %i restarts.\n", __func__, obs_key, obs_restart_nr, time_map_get_last_step( time_map )); - } else { - time_t obs_time = time_map_get_start_time( time_map ); - - if(conf_instance_has_item(conf_instance, "DATE")) { - obs_time = conf_instance_get_item_value_time_t(conf_instance, "DATE" ); - if (prefer_restart) - obs_vector_prefer_RESTART_warning(); - } else if (conf_instance_has_item(conf_instance, "DAYS")) { - double days = conf_instance_get_item_value_double(conf_instance, "DAYS"); - util_inplace_forward_days_utc( &obs_time , days ); - if (prefer_restart) - obs_vector_prefer_RESTART_warning(); - } else if (conf_instance_has_item(conf_instance, "HOURS")) { - double hours = conf_instance_get_item_value_double(conf_instance, "HOURS"); - util_inplace_forward_seconds_utc( &obs_time , hours * 3600 ); - if (prefer_restart) - obs_vector_prefer_RESTART_warning(); - } else - util_abort("%s: Internal error. Invalid conf_instance?\n", __func__); - - obs_restart_nr = time_map_lookup_time_with_tolerance( time_map , obs_time , 30 , 30 ); - } - if (obs_restart_nr < 0) - util_abort("%s: Failed to look up restart nr correctly \n",__func__); - - return obs_restart_nr; -} - - - -/*****************************************************************/ - - -static void obs_vector_resize(obs_vector_type * vector , int new_size) { - int current_size = vector_get_size( vector->nodes ); - int i; - - for (i=current_size; i < new_size; i++) - vector_append_ref( vector->nodes , NULL); - -} - - -obs_vector_type * obs_vector_alloc(obs_impl_type obs_type , const char * obs_key , enkf_config_node_type * config_node, int num_reports) { - obs_vector_type * vector = util_malloc(sizeof * vector ); - - UTIL_TYPE_ID_INIT( vector , OBS_VECTOR_TYPE_ID); - vector->freef = NULL; - vector->measure = NULL; - vector->get_obs = NULL; - vector->user_get = NULL; - vector->chi2 = NULL; - vector->update_std_scale = NULL; - vector->step_list = int_vector_alloc(0,0); - - switch (obs_type) { - case(SUMMARY_OBS): - vector->freef = summary_obs_free__; - vector->measure = summary_obs_measure__; - vector->get_obs = summary_obs_get_observations__; - vector->user_get = summary_obs_user_get__; - vector->chi2 = summary_obs_chi2__; - vector->update_std_scale = summary_obs_update_std_scale__; - break; - case(BLOCK_OBS): - vector->freef = block_obs_free__; - vector->measure = block_obs_measure__; - vector->get_obs = block_obs_get_observations__; - vector->user_get = block_obs_user_get__; - vector->chi2 = block_obs_chi2__; - vector->update_std_scale = block_obs_update_std_scale__; - break; - case(GEN_OBS): - vector->freef = gen_obs_free__; - vector->measure = gen_obs_measure__; - vector->get_obs = gen_obs_get_observations__; - vector->user_get = gen_obs_user_get__; - vector->chi2 = gen_obs_chi2__; - vector->update_std_scale = gen_obs_update_std_scale__; - break; - default: - util_abort("%s: internal error - obs_type:%d not recognized \n",__func__ , obs_type); - } - - vector->obs_type = obs_type; - vector->config_node = config_node; - vector->obs_key = util_alloc_string_copy( obs_key ); - vector->num_active = 0; - vector->nodes = vector_alloc_new(); - obs_vector_resize(vector , num_reports + 1); /* +1 here ?? Ohh - these +/- problems. */ - - return vector; -} - -obs_impl_type obs_vector_get_impl_type(const obs_vector_type * obs_vector) { - return obs_vector->obs_type; -} - - -/** - This is the key for the enkf_node which this observation is - 'looking at'. I.e. if this observation is an RFT pressure - measurement, this function will return "PRESSURE". -*/ - -const char * obs_vector_get_state_kw(const obs_vector_type * obs_vector) { - return enkf_config_node_get_key( obs_vector->config_node ); -} - - -const char * obs_vector_get_key(const obs_vector_type * obs_vector) { - return obs_vector->obs_key; -} - - -enkf_config_node_type * obs_vector_get_config_node(const obs_vector_type * obs_vector) { - return obs_vector->config_node; -} - - - -void obs_vector_free(obs_vector_type * obs_vector) { - vector_free( obs_vector->nodes ); - free(obs_vector->obs_key); - int_vector_free(obs_vector->step_list); - free(obs_vector); -} - - -static void obs_vector_assert_node_type( const obs_vector_type * obs_vector , const void * node ) { - bool type_OK; - switch (obs_vector->obs_type) { - case(SUMMARY_OBS): - type_OK = summary_obs_is_instance( node ); - break; - case(BLOCK_OBS): - type_OK = block_obs_is_instance( node ); - break; - case(GEN_OBS): - type_OK = gen_obs_is_instance( node ); - break; - default: - util_abort("%s: Error in type check: \n",__func__); - type_OK = false; - } - if (!type_OK) - util_abort("%s: Type mismatch when trying to add observation node to observation vector \n",__func__); -} - - - - -void obs_vector_del_node(obs_vector_type * obs_vector , int index) { - if (vector_iget_const( obs_vector->nodes , index ) != NULL) { - vector_iset_ref( obs_vector->nodes , index , NULL); /* Clear current content. */ - obs_vector->num_active--; - } -} - -/** - This function will clear (and free) all the summary_obs / gen_obs / - field_obs instances which have been installed in the vector; - however the vector itself is retained with keys, function pointers - and so on. -*/ - -void obs_vector_clear_nodes( obs_vector_type * obs_vector ) { - vector_clear( obs_vector->nodes ); - obs_vector->num_active = 0; -} - - - -void obs_vector_install_node(obs_vector_type * obs_vector , int index , void * node) { - obs_vector_assert_node_type( obs_vector , node ); - { - if (vector_iget_const( obs_vector->nodes , index ) == NULL) { - obs_vector->num_active++; - int_vector_append( obs_vector->step_list , index ); - int_vector_sort( obs_vector->step_list ); - } - - vector_iset_owned_ref( obs_vector->nodes , index , node , obs_vector->freef ); - } -} - -/** - Observe that @summary_key is the key used to look up the - corresponding simulated value in the ensemble, and not the - observation key - the two can be different. -*/ - -static void obs_vector_add_summary_obs( obs_vector_type * obs_vector , int obs_index , const char * summary_key , const char * obs_key , double value , double std , const char * auto_corrf_name , double auto_corrf_param) { - summary_obs_type * summary_obs = summary_obs_alloc( summary_key , obs_key , value , std , auto_corrf_name , auto_corrf_param); - obs_vector_install_node( obs_vector , obs_index , summary_obs ); -} - - -/*****************************************************************/ - -int obs_vector_get_num_active(const obs_vector_type * vector) { - return vector->num_active; -} - - -/** - IFF - only one - report step is active this function will return - that report step. If more than report step is active, the function - is ambiguous, and will fail HARD. Check with get_num_active first! -*/ - -int obs_vector_get_active_report_step(const obs_vector_type * vector) { - if (vector->num_active == 1) { - int active_step = -1; - int i; - for (i=0; i < vector_get_size(vector->nodes); i++) { - void * obs_node = vector_iget( vector->nodes , i); - if (obs_node != NULL) { - if (active_step >= 0) - util_abort("%s: internal error - mismatch in obs_vector->nodes and obs_vector->num_active \n",__func__); - active_step = i; - } - } - if (active_step < 0) - util_abort("%s: internal error - mismatch in obs_vector->nodes and obs_vector->num_active \n",__func__); - - return active_step; - } else { - util_abort("%s: when calling this function the number of active report steps MUST BE 1 - you had: %d \n",__func__ , vector->num_active); - return 0; /* Comiler shut up. */ - } -} - - -const int_vector_type * obs_vector_get_step_list(const obs_vector_type * vector) { - return vector->step_list; -} - - -bool obs_vector_iget_active(const obs_vector_type * vector, int index) { - /* We accept this ... */ - if (index >= vector_get_size( vector->nodes )) - return false; - - { - void * obs_data = vector_iget( vector->nodes , index ); - if (obs_data != NULL) - return true; - else - return false; - } -} - - -/* - Will happily return NULL if index is not active. -*/ -void * obs_vector_iget_node(const obs_vector_type * vector, int index) { - return vector_iget( vector->nodes , index ); -} - - - - -void obs_vector_user_get(const obs_vector_type * obs_vector , const char * index_key , int report_step , double * value , double * std , bool * valid) { - void * obs_node = obs_vector_iget_node( obs_vector , report_step ); - obs_vector->user_get(obs_node , index_key , value , std , valid); -} - -/* - This function returns the next active (i.e. node != NULL) report - step, starting with 'prev_step + 1'. If no more active steps are - found, it will return -1. -*/ - -int obs_vector_get_next_active_step(const obs_vector_type * obs_vector , int prev_step) { - if (prev_step >= (vector_get_size(obs_vector->nodes) - 1)) - return -1; - else { - int size = vector_get_size( obs_vector->nodes ); - int next_step = prev_step + 1; - while (( next_step < size) && (obs_vector_iget_node(obs_vector , next_step) == NULL)) - next_step++; - - if (next_step == size) - return -1; /* No more active steps. */ - else - return next_step; - } -} - - -int obs_vector_get_last_active_step(const obs_vector_type * obs_vector) { - int step = vector_get_size( obs_vector->nodes ) - 1; - while (true) { - const void * obs_node = vector_iget_const( obs_vector->nodes , step ); - if (obs_node) - break; - - step--; - if (step < 0) - break; - } - return step; -} - - - -/*****************************************************************/ -/** - All the obs_vector_load_from_XXXX() functions can safely return - NULL, in which case no observation is added to enkf_obs observation - hash table. -*/ - - -void obs_vector_load_from_SUMMARY_OBSERVATION(obs_vector_type * obs_vector , const conf_instance_type * conf_instance , time_map_type * obs_time , ensemble_config_type * ensemble_config) { - if(!conf_instance_is_of_class(conf_instance, "SUMMARY_OBSERVATION")) - util_abort("%s: internal error. expected \"SUMMARY_OBSERVATION\" instance, got \"%s\".\n", - __func__, conf_instance_get_class_name_ref(conf_instance) ); - - { - double obs_value = conf_instance_get_item_value_double(conf_instance, "VALUE" ); - double obs_error = conf_instance_get_item_value_double(conf_instance, "ERROR" ); - double min_error = conf_instance_get_item_value_double(conf_instance, "ERROR_MIN"); - const char * error_mode = conf_instance_get_item_value_ref( conf_instance, "ERROR_MODE"); - const char * sum_key = conf_instance_get_item_value_ref( conf_instance, "KEY" ); - const char * obs_key = conf_instance_get_name_ref(conf_instance); - int obs_restart_nr = __conf_instance_get_restart_nr(conf_instance , obs_key , obs_time , false); - - if (obs_restart_nr == 0) { - int day,month,year; - time_t start_time = time_map_iget( obs_time , 0 ); - util_set_date_values_utc( start_time , &day , &month , &year); - - fprintf(stderr,"** ERROR: It is unfortunately not possible to use summary observations from the\n"); - fprintf(stderr," start of the simulation. Problem with observation:%s at %02d/%02d/%4d\n",obs_key , day,month,year); - exit(1); - } - { - if (strcmp( error_mode , "REL") == 0) - obs_error *= obs_value; - else if (strcmp( error_mode , "RELMIN") == 0) - obs_error = util_double_max( min_error , obs_error * obs_value ); - - obs_vector_add_summary_obs( obs_vector , obs_restart_nr , sum_key , obs_key , obs_value , obs_error , NULL , 0); - } - } -} - - - - -obs_vector_type * obs_vector_alloc_from_GENERAL_OBSERVATION(const conf_instance_type * conf_instance , time_map_type * obs_time , const ensemble_config_type * ensemble_config) { - if(!conf_instance_is_of_class(conf_instance, "GENERAL_OBSERVATION")) - util_abort("%s: internal error. expected \"GENERAL_OBSERVATION\" instance, got \"%s\".\n", - __func__, conf_instance_get_class_name_ref(conf_instance) ); - const char * obs_key = conf_instance_get_name_ref(conf_instance); - const char * state_kw = conf_instance_get_item_value_ref( conf_instance, "DATA" ); - if (ensemble_config_has_key( ensemble_config , state_kw )) { - const char * obs_key = conf_instance_get_name_ref(conf_instance); - int obs_restart_nr = __conf_instance_get_restart_nr(conf_instance , obs_key , obs_time , true); - const char * index_file = NULL; - const char * index_list = NULL; - const char * obs_file = NULL; - const char * error_covar_file = NULL; - - if (conf_instance_has_item(conf_instance , "INDEX_FILE")) - index_file = conf_instance_get_item_value_ref( conf_instance, "INDEX_FILE" ); - - if (conf_instance_has_item(conf_instance , "INDEX_LIST")) - index_list = conf_instance_get_item_value_ref( conf_instance, "INDEX_LIST" ); - - if (conf_instance_has_item(conf_instance , "OBS_FILE")) - obs_file = conf_instance_get_item_value_ref( conf_instance, "OBS_FILE" ); - - if (conf_instance_has_item(conf_instance , "ERROR_COVAR")) - error_covar_file = conf_instance_get_item_value_ref( conf_instance, "ERROR_COVAR" ); - - { - obs_vector_type * obs_vector = NULL; - const enkf_config_node_type * config_node = ensemble_config_get_node( ensemble_config , state_kw); - - if (enkf_config_node_get_impl_type(config_node) == GEN_DATA) { - double scalar_error = -1; - double scalar_value = -1; - gen_obs_type * gen_obs ; - const gen_data_config_type * config = enkf_config_node_get_ref( config_node ); - - if (gen_data_config_has_report_step( config , obs_restart_nr)) { - obs_vector = obs_vector_alloc( GEN_OBS , obs_key , ensemble_config_get_node(ensemble_config , state_kw ), time_map_get_last_step( obs_time )); - if (conf_instance_has_item(conf_instance , "VALUE")) { - scalar_value = conf_instance_get_item_value_double(conf_instance , "VALUE"); - scalar_error = conf_instance_get_item_value_double(conf_instance , "ERROR"); - } - - /** The config system has ensured that we have either OBS_FILE or (VALUE and ERROR). */ - gen_obs = gen_obs_alloc( enkf_config_node_get_ref( config_node ) , obs_key , obs_file , scalar_value , scalar_error , index_file , index_list , error_covar_file); - obs_vector_install_node( obs_vector , obs_restart_nr , gen_obs ); - } else - fprintf(stderr,"** ERROR: The GEN_DATA node:%s is not configured to load from report step:%d - the observation:%s will be ignored\n", state_kw , obs_restart_nr , obs_key); - } else { - ert_impl_type impl_type = enkf_config_node_get_impl_type(config_node); - fprintf(stderr,"** ERROR: %s: %s has implementation type:\'%s\' - expected:\'%s\' - observation:%s ignored.\n", - __func__ , state_kw , enkf_types_get_impl_name(impl_type) , enkf_types_get_impl_name(GEN_DATA) , obs_key); - } - return obs_vector; - - } - } else { - fprintf(stderr,"** Warning the ensemble key:%s does not exist - observation:%s not added \n", state_kw , obs_key); - return NULL; - } -} - - - -// Should check the refcase for key - if it is != NULL. - -bool obs_vector_load_from_HISTORY_OBSERVATION(obs_vector_type * obs_vector , - const conf_instance_type * conf_instance , - time_map_type * obs_time , - const history_type * history , - ensemble_config_type * ensemble_config, - double std_cutoff ) { - - if(!conf_instance_is_of_class(conf_instance, "HISTORY_OBSERVATION")) - util_abort("%s: internal error. expected \"HISTORY_OBSERVATION\" instance, got \"%s\".\n",__func__, conf_instance_get_class_name_ref(conf_instance) ); - - { - bool initOK = false; - int size , restart_nr; - double_vector_type * value = double_vector_alloc(0,0); - double_vector_type * std = double_vector_alloc(0,0); - bool_vector_type * valid = bool_vector_alloc(0 , false); - - /* The auto_corrf parameters can not be "segmentized" */ - double auto_corrf_param = -1; - const char * auto_corrf_name = NULL; - - - double error = conf_instance_get_item_value_double(conf_instance, "ERROR" ); - double error_min = conf_instance_get_item_value_double(conf_instance, "ERROR_MIN" ); - const char * error_mode = conf_instance_get_item_value_ref( conf_instance, "ERROR_MODE"); - const char * sum_key = conf_instance_get_name_ref( conf_instance ); - - if(conf_instance_has_item(conf_instance, "AUTO_CORRF")) { - auto_corrf_name = conf_instance_get_item_value_ref( conf_instance , "AUTO_CORRF"); - auto_corrf_param = conf_instance_get_item_value_double(conf_instance, "AUTO_CORRF_PARAM"); - if(conf_instance_has_item(conf_instance, "AUTO_CORRF_PARAM")) - auto_corrf_param = conf_instance_get_item_value_double(conf_instance, "AUTO_CORRF_PARAM"); - else - util_abort("%s: When specifying AUTO_CORRF you must also give a vlaue for AUTO_CORRF_PARAM",__func__); - } - - - // Get time series data from history object and allocate - size = time_map_get_last_step( obs_time ); - if (history_init_ts( history , sum_key , value , valid )) { - - // Create the standard deviation vector - if(strcmp(error_mode, "ABS") == 0) { - for( restart_nr = 0; restart_nr < size; restart_nr++) - double_vector_iset( std , restart_nr , error ); - } else if(strcmp(error_mode, "REL") == 0) { - for( restart_nr = 0; restart_nr < size; restart_nr++) - double_vector_iset( std , restart_nr , error * abs( double_vector_iget( value , restart_nr ))); - } else if(strcmp(error_mode, "RELMIN") == 0) { - for(restart_nr = 0; restart_nr < size; restart_nr++) { - double tmp_std = util_double_max( error_min , error * abs( double_vector_iget( value , restart_nr ))); - double_vector_iset( std , restart_nr , tmp_std); - } - } else - util_abort("%s: Internal error. Unknown error mode \"%s\"\n", __func__, error_mode); - - - // Handle SEGMENTs which can be used to customize the observation error. */ - { - stringlist_type * segment_keys = conf_instance_alloc_list_of_sub_instances_of_class_by_name(conf_instance, "SEGMENT"); - stringlist_sort( segment_keys , NULL ); - - int num_segments = stringlist_get_size(segment_keys); - - for(int segment_nr = 0; segment_nr < num_segments; segment_nr++) - { - const char * segment_name = stringlist_iget(segment_keys, segment_nr); - const conf_instance_type * segment_conf = conf_instance_get_sub_instance_ref(conf_instance, segment_name); - - int start = conf_instance_get_item_value_int( segment_conf, "START" ); - int stop = conf_instance_get_item_value_int( segment_conf, "STOP" ); - double error_segment = conf_instance_get_item_value_double(segment_conf, "ERROR" ); - double error_min_segment = conf_instance_get_item_value_double(segment_conf, "ERROR_MIN" ); - const char * error_mode_segment = conf_instance_get_item_value_ref( segment_conf, "ERROR_MODE"); - - if(start < 0) - { - printf("%s: WARNING - Segment out of bounds. Truncating start of segment to 0.\n", __func__); - start = 0; - } - - if(stop >= size) - { - printf("%s: WARNING - Segment out of bounds. Truncating end of segment to %d.\n", __func__, size - 1); - stop = size -1; - } - - if(start > stop) - { - printf("%s: WARNING - Segment start after stop. Truncating end of segment to %d.\n", __func__, start ); - stop = start; - } - - // Create the standard deviation vector - if(strcmp(error_mode_segment, "ABS") == 0) { - for( restart_nr = start; restart_nr <= stop; restart_nr++) - double_vector_iset( std , restart_nr , error_segment) ; - } else if(strcmp(error_mode_segment, "REL") == 0) { - for( restart_nr = start; restart_nr <= stop; restart_nr++) - double_vector_iset( std , restart_nr , error_segment * abs(double_vector_iget( value , restart_nr))); - } else if(strcmp(error_mode_segment, "RELMIN") == 0) { - for(restart_nr = start; restart_nr <= stop ; restart_nr++) { - double tmp_std = util_double_max( error_min_segment , error_segment * abs( double_vector_iget( value , restart_nr ))); - double_vector_iset( std , restart_nr , tmp_std); - } - } else - util_abort("%s: Internal error. Unknown error mode \"%s\"\n", __func__, error_mode); - } - stringlist_free(segment_keys); - } - - - /* - This is where the summary observations are finally added. - */ - for (restart_nr = 0; restart_nr < size; restart_nr++) { - if (bool_vector_safe_iget( valid , restart_nr)) { - if (double_vector_iget( std , restart_nr) > std_cutoff) { - obs_vector_add_summary_obs( obs_vector , restart_nr , sum_key , sum_key , - double_vector_iget( value ,restart_nr) , double_vector_iget( std , restart_nr ) , - auto_corrf_name , auto_corrf_param); - } else - fprintf(stderr,"** Warning: to small observation error in observation %s:%d - ignored. \n", sum_key , restart_nr); - } - } - initOK = true; - } - double_vector_free(std); - double_vector_free(value); - bool_vector_free(valid); - return initOK; - } -} - -void obs_vector_scale_std(obs_vector_type * obs_vector, const local_obsdata_node_type * local_node , double std_multiplier) { - const active_list_type * active_list = local_obsdata_node_get_active_list( local_node ); - int tstep = -1; - - while (true) { - tstep = obs_vector_get_next_active_step( obs_vector , tstep ); - if (tstep < 0) - break; - - if (local_obsdata_node_tstep_active(local_node, tstep)) { - void * observation = obs_vector_iget_node(obs_vector, tstep); - if (observation) - obs_vector->update_std_scale(observation, std_multiplier , active_list); - } - } - -} - - -static const char * __summary_kw( const char * field_name ) { - if (strcmp( field_name , "PRESSURE") == 0) - return "BPR"; - else if (strcmp( field_name , "SWAT") == 0) - return "BSWAT"; - else if (strcmp( field_name , "SGAS") == 0) - return "BSGAS"; - else { - util_abort("%s: sorry - could not \'translate\' field:%s to block summary variable\n",__func__ , field_name); - return NULL; - } -} - - -obs_vector_type * obs_vector_alloc_from_BLOCK_OBSERVATION(const conf_instance_type * conf_instance , - const ecl_grid_type * grid , - time_map_type * obs_time , - const ecl_sum_type * refcase , - ensemble_config_type * ensemble_config) { - - if(!conf_instance_is_of_class(conf_instance, "BLOCK_OBSERVATION")) - util_abort("%s: internal error. expected \"BLOCK_OBSERVATION\" instance, got \"%s\".\n", - __func__, conf_instance_get_class_name_ref(conf_instance) ); - - block_obs_source_type source_type = SOURCE_SUMMARY; - const char * obs_label = conf_instance_get_name_ref(conf_instance); - const char * source_string = conf_instance_get_item_value_ref(conf_instance , "SOURCE"); - const char * field_name = conf_instance_get_item_value_ref(conf_instance , "FIELD"); - const char * sum_kw = NULL; - bool OK = true; - - if (strcmp(source_string , "FIELD") == 0) { - source_type = SOURCE_FIELD; - if (!ensemble_config_has_key( ensemble_config , field_name)) { - OK = false; - fprintf(stderr,"** Warning the ensemble key:%s does not exist - observation:%s not added \n", field_name , obs_label); - } - } else if (strcmp( source_string , "SUMMARY") == 0) { - source_type = SOURCE_SUMMARY; - sum_kw = __summary_kw( field_name ); - } else - util_abort("%s: internal error \n",__func__); - - if (OK) { - obs_vector_type * obs_vector = NULL; - int size = time_map_get_last_step( obs_time ); - int obs_restart_nr ; - - stringlist_type * summary_keys = stringlist_alloc_new(); - stringlist_type * obs_pt_keys = conf_instance_alloc_list_of_sub_instances_of_class_by_name(conf_instance, "OBS"); - int num_obs_pts = stringlist_get_size(obs_pt_keys); - - double * obs_value = util_calloc(num_obs_pts , sizeof * obs_value); - double * obs_std = util_calloc(num_obs_pts , sizeof * obs_std ); - int * obs_i = util_calloc(num_obs_pts , sizeof * obs_i ); - int * obs_j = util_calloc(num_obs_pts , sizeof * obs_j ); - int * obs_k = util_calloc(num_obs_pts , sizeof * obs_k ); - - obs_restart_nr = __conf_instance_get_restart_nr(conf_instance , obs_label , obs_time , false); - - /** Build the observation. */ - for(int obs_pt_nr = 0; obs_pt_nr < num_obs_pts; obs_pt_nr++) { - const char * obs_key = stringlist_iget(obs_pt_keys, obs_pt_nr); - const conf_instance_type * obs_instance = conf_instance_get_sub_instance_ref(conf_instance, obs_key); - const char * error_mode = conf_instance_get_item_value_ref(obs_instance, "ERROR_MODE"); - double error = conf_instance_get_item_value_double(obs_instance, "ERROR"); - double value = conf_instance_get_item_value_double(obs_instance, "VALUE"); - double min_error = conf_instance_get_item_value_double(obs_instance, "ERROR_MIN"); - - if (strcmp( error_mode , "REL") == 0) - error *= value; - else if (strcmp( error_mode , "RELMIN") == 0) - error = util_double_max( error * value , min_error ); - - obs_value[obs_pt_nr] = value; - obs_std [obs_pt_nr] = error; - - /** - The input values i,j,k come from the user, and are offset 1. They - are immediately shifted with -1 to become C-based offset zero. - */ - obs_i[obs_pt_nr] = conf_instance_get_item_value_int( obs_instance, "I") - 1; - obs_j[obs_pt_nr] = conf_instance_get_item_value_int( obs_instance, "J") - 1; - obs_k[obs_pt_nr] = conf_instance_get_item_value_int( obs_instance, "K") - 1; - - if (source_type == SOURCE_SUMMARY) { - char * summary_key = smspec_alloc_block_ijk_key( SUMMARY_KEY_JOIN_STRING , sum_kw , - obs_i[obs_pt_nr] + 1 , - obs_j[obs_pt_nr] + 1 , - obs_k[obs_pt_nr] + 1 ); - - stringlist_append_owned_ref( summary_keys , summary_key ); - } - } - - - if (source_type == SOURCE_FIELD) { - const enkf_config_node_type * config_node = ensemble_config_get_node( ensemble_config , field_name); - const field_config_type * field_config = enkf_config_node_get_ref( config_node ); - block_obs_type * block_obs = block_obs_alloc_complete(obs_label, source_type , NULL , field_config , grid , num_obs_pts, obs_i, obs_j, obs_k, obs_value, obs_std); - - if (block_obs != NULL) { - obs_vector = obs_vector_alloc( BLOCK_OBS , obs_label , ensemble_config_get_node(ensemble_config , field_name), size ); - obs_vector_install_node( obs_vector , obs_restart_nr , block_obs); - } - } else if (source_type == SOURCE_SUMMARY) { - OK = true; - if (refcase != NULL) { - for (int i=0; i < stringlist_get_size( summary_keys ); i++) { - const char * sum_key = stringlist_iget( summary_keys , i ); - if (!ecl_sum_has_key(refcase , sum_key)) { - /* - If the - */ - fprintf(stderr,"** Warning missing summary %s for cell: (%d,%d,%d) in refcase - make sure that \"BPR %d %d %d\" is included in ECLIPSE summary specification \n" , - sum_key , obs_i[i]+1 , obs_j[i]+1 , obs_k[i]+1 , obs_i[i]+1 , obs_j[i]+1 , obs_k[i]+1 ); - //OK = false; - } - } - } - if (OK) { - // We can create the container node and add the summary nodes. - enkf_config_node_type * container_config = ensemble_config_add_container( ensemble_config , NULL ); - - for (int i=0; i < stringlist_get_size( summary_keys ); i++) { - const char * sum_key = stringlist_iget( summary_keys , i ); - enkf_config_node_type * child_node = ensemble_config_add_summary_observation( ensemble_config , sum_key , LOAD_FAIL_WARN ); - enkf_config_node_update_container( container_config , child_node ); - } - - { - block_obs_type * block_obs = block_obs_alloc_complete(obs_label, source_type , summary_keys , enkf_config_node_get_ref(container_config) , - grid , num_obs_pts, obs_i, obs_j, obs_k, obs_value, obs_std); - if (block_obs != NULL) { - obs_vector = obs_vector_alloc( BLOCK_OBS , obs_label , container_config, size ); - obs_vector_install_node( obs_vector , obs_restart_nr , block_obs); - } - } - } - } else - util_abort("%s: invalid source value \n",__func__); - - free(obs_value); - free(obs_std); - free(obs_i); - free(obs_j); - free(obs_k); - stringlist_free(obs_pt_keys); - stringlist_free(summary_keys); - - return obs_vector; - } else { - fprintf(stderr,"** Warning the ensemble key:%s does not exist - observation:%s not added \n", field_name , obs_label); - return NULL; - } -} -/*****************************************************************/ - -void obs_vector_iget_observations(const obs_vector_type * obs_vector, int report_step , obs_data_type * obs_data, const active_list_type * active_list, enkf_fs_type * fs) { - void * obs_node = vector_iget( obs_vector->nodes , report_step ); - if ( obs_node != NULL) - obs_vector->get_obs(obs_node , obs_data , fs, report_step , active_list); -} - - -void obs_vector_measure(const obs_vector_type * obs_vector , - enkf_fs_type * fs , - int report_step , - const int_vector_type * ens_active_list , - meas_data_type * meas_data , - const active_list_type * active_list) { - - void * obs_node = vector_iget( obs_vector->nodes , report_step ); - if ( obs_node != NULL ) { - enkf_node_type * enkf_node = enkf_node_deep_alloc( obs_vector->config_node ); - - node_id_type node_id = { .report_step = report_step , - .iens = 0 }; - - int vec_size = int_vector_size( ens_active_list ); - for (int active_iens_index = 0; active_iens_index < vec_size; active_iens_index++) { - node_id.iens = int_vector_iget( ens_active_list , active_iens_index ); - - enkf_node_load(enkf_node , fs , node_id); - obs_vector->measure(obs_node , enkf_node_value_ptr(enkf_node) , node_id , meas_data , active_list); - } - - enkf_node_free( enkf_node ); - } -} - - -static bool obs_vector_has_data_at_report_step( const obs_vector_type * obs_vector , const bool_vector_type * active_mask , enkf_fs_type * fs, int report_step) { - void * obs_node = vector_iget( obs_vector->nodes , report_step ); - if ( obs_node ) { - node_id_type node_id = {.report_step = report_step }; - for (int iens = 0; iens < bool_vector_size( active_mask ); iens++) { - if (bool_vector_iget( active_mask , iens)) { - node_id.iens = iens; - if (! enkf_config_node_has_node(obs_vector->config_node , fs , node_id )) - return false; - } - } - } - - /* - Will return true unconditionally if we do not have observation data at this report step; - or alternatively if the active_mask is all false. - */ - return true; -} - - -/* - The has_vector_data() function will only check that we have a vector - stored, and not the actual length of the vector. This means we can - be fooled if the stored vector is shorter than what the observation - requires. - - Should ideally check that the vector is long enough, but that - requires changes in the enkf_node api for vector storage. -*/ - -static bool obs_vector_has_vector_data( const obs_vector_type * obs_vector , const bool_vector_type * active_mask , enkf_fs_type * fs) { - int vec_size = bool_vector_size( active_mask ); - - for (int iens = 0; iens < vec_size; iens++) { - const enkf_config_node_type * data_config = obs_vector->config_node; - if (bool_vector_iget( active_mask , iens )) { - if (!enkf_config_node_has_vector(data_config , fs , iens)) { - return false; - } - } - } - - return true; -} - - - -bool obs_vector_has_data( const obs_vector_type * obs_vector , const bool_vector_type * active_mask , enkf_fs_type * fs) { - const enkf_config_node_type * data_config = obs_vector->config_node; - if (enkf_config_node_vector_storage( data_config )) - return obs_vector_has_vector_data( obs_vector , active_mask , fs ); - - int vec_size = vector_get_size( obs_vector->nodes ); - for (int report_step = 0; report_step < vec_size; report_step++) { - if (!obs_vector_has_data_at_report_step( obs_vector , active_mask , fs, report_step)) - return false; - } - return true; -} - - - -/*****************************************************************/ -/** Here comes many different functions for misfit calculations. */ - -/** - This is the lowest level function: - - * It is checked that the obs_vector is active for the actual report - step; if it is not active 0.0 is returned without any further - ado. - - * It is assumed the enkf_node_instance contains valid data for this - report_step. This is not checked in this function, and is the - responsability of the calling scope. - - * The underlying chi2 function will do a type-check of node - and - fail hard if it is not correct. - -*/ - - -static double obs_vector_chi2__(const obs_vector_type * obs_vector , int report_step , const enkf_node_type * node, node_id_type node_id) { - void * obs_node = vector_iget( obs_vector->nodes , report_step ); - - if (obs_node) - return obs_vector->chi2( obs_node , enkf_node_value_ptr( node ), node_id); - else - return 0.0; /* Observation not active for this report step. */ - -} - - - - - -double obs_vector_chi2(const obs_vector_type * obs_vector , enkf_fs_type * fs , node_id_type node_id) { - enkf_node_type * enkf_node = enkf_node_alloc( obs_vector->config_node ); - double chi2 = 0; - - if (enkf_node_try_load( enkf_node , fs , node_id)) - chi2 = obs_vector_chi2__(obs_vector , node_id.report_step , enkf_node , node_id); - - enkf_node_free( enkf_node ); - return chi2; -} - - - - -/** - This function will evaluate the chi2 for the ensemble members - [iens1,iens2) and report steps [step1,step2). - - Observe that the chi2 pointer is assumed to be allocated for the - complete ensemble, altough this function only operates on part of - it. -*/ - - -//This will not work for container observations ..... - -void obs_vector_ensemble_chi2(const obs_vector_type * obs_vector , - enkf_fs_type * fs, - bool_vector_type * valid , - int step1 , - int step2 , - int iens1 , - int iens2 , - double ** chi2) { - - int step; - enkf_node_type * enkf_node = enkf_node_alloc( obs_vector->config_node ); - node_id_type node_id; - for (step = step1; step <= step2; step++) { - int iens; - node_id.report_step = step; - { - void * obs_node = vector_iget( obs_vector->nodes , step); - - if (obs_node == NULL) { - for (iens = iens1; iens < iens2; iens++) - chi2[step][iens] = 0; - } else { - for (iens = iens1; iens < iens2; iens++) { - node_id.iens = iens; - if (enkf_node_try_load( enkf_node , fs , node_id)) - chi2[step][iens] = obs_vector_chi2__(obs_vector , step , enkf_node , node_id); - else { - chi2[step][iens] = 0; - // Missing data - this member will be marked as invalid in the misfit calculations. - bool_vector_iset( valid , iens , false ); - } - } - } - } - } - enkf_node_free( enkf_node ); -} - - - -/** - This function will evaluate the total chi2 for one ensemble member - (i.e. sum over report steps). -*/ - - -double obs_vector_total_chi2(const obs_vector_type * obs_vector , enkf_fs_type * fs , int iens) { - double sum_chi2 = 0; - enkf_node_type * enkf_node = enkf_node_deep_alloc( obs_vector->config_node ); - node_id_type node_id = {.report_step = 0, .iens = iens }; - - int vec_size = vector_get_size( obs_vector->nodes ); - for (int report_step = 0; report_step < vec_size; report_step++) { - if (vector_iget(obs_vector->nodes , report_step) != NULL) { - node_id.report_step = report_step; - - if (enkf_node_try_load( enkf_node , fs , node_id)) - sum_chi2 += obs_vector_chi2__(obs_vector , report_step , enkf_node, node_id); - - } - } - enkf_node_free( enkf_node ); - return sum_chi2; -} - - -/** - This function will sum up all timesteps of the obs_vector, for all ensemble members. -*/ - -void obs_vector_ensemble_total_chi2(const obs_vector_type * obs_vector , enkf_fs_type * fs , int ens_size , double * sum_chi2) { - const bool verbose = true; - msg_type * msg; - int report_step; - int iens; - char * msg_text = NULL; - - for (iens = 0; iens < ens_size; iens++) - sum_chi2[iens] = 0; - - if (verbose) { - msg = msg_alloc("Observation: " , false); - msg_show(msg); - } - - { - node_id_type node_id = {.report_step = 0, .iens = iens }; - enkf_node_type * enkf_node = enkf_node_alloc( obs_vector->config_node ); - int vec_size = vector_get_size( obs_vector->nodes); - for (report_step = 0; report_step < vec_size; report_step++) { - if (verbose) { - msg_text = util_realloc_sprintf( msg_text , "%s[%03d]" , obs_vector->obs_key , report_step); - msg_update(msg , msg_text); - } - if (vector_iget(obs_vector->nodes , report_step) != NULL) { - node_id.report_step = report_step; - for (iens = 0; iens < ens_size; iens++) { - node_id.iens = iens; - - if (enkf_node_try_load( enkf_node , fs , node_id)) - sum_chi2[iens] += obs_vector_chi2__(obs_vector , report_step , enkf_node, node_id); - - } - } - } - enkf_node_free( enkf_node ); - } - - if (verbose) { - msg_free(msg , true); - util_safe_free( msg_text ); - } -} - -const char * obs_vector_get_obs_key( const obs_vector_type * obs_vector) { - return obs_vector->obs_key; -} - - -local_obsdata_node_type * obs_vector_alloc_local_node(const obs_vector_type * obs_vector) { - local_obsdata_node_type * obs_node = local_obsdata_node_alloc( obs_vector->obs_key , false ); - local_obsdata_node_reset_tstep_list(obs_node, obs_vector->step_list ); - return obs_node; -} - - -/*****************************************************************/ - - -VOID_FREE(obs_vector) - diff --git a/ThirdParty/Ert/libenkf/src/pca_plot_data.c b/ThirdParty/Ert/libenkf/src/pca_plot_data.c deleted file mode 100644 index ef9b33df20..0000000000 --- a/ThirdParty/Ert/libenkf/src/pca_plot_data.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - The file 'pca_plot_data.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include - -#include -#include -#include -#include - -#include -#include - -#define PCA_PLOT_DATA_TYPE_ID 61442098 - -struct pca_plot_data_struct { - UTIL_TYPE_ID_DECLARATION; - char * name; - vector_type * pca_vectors; - double_vector_type * singular_values; - int ens_size; -}; - - -UTIL_IS_INSTANCE_FUNCTION( pca_plot_data , PCA_PLOT_DATA_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION( pca_plot_data , PCA_PLOT_DATA_TYPE_ID ) - -static void pca_plot_data_add_vectors(pca_plot_data_type * plot_data , const matrix_type * PC , const matrix_type * PC_obs, const double_vector_type * singular_values) { - int component; - for (component = 0; component < matrix_get_rows( PC ); component++) { - pca_plot_vector_type * vector = pca_plot_vector_alloc( component , PC , PC_obs , singular_values); - vector_append_owned_ref( plot_data->pca_vectors , vector , pca_plot_vector_free__); - } -} - - -pca_plot_data_type * pca_plot_data_alloc( const char * name, - const matrix_type * PC , - const matrix_type * PC_obs, - const double_vector_type * singular_values) { - pca_plot_data_type * plot_data = NULL; - - if (pca_plot_assert_input( PC , PC_obs , singular_values)) { - plot_data = util_malloc( sizeof * plot_data ); - UTIL_TYPE_ID_INIT( plot_data , PCA_PLOT_DATA_TYPE_ID ); - plot_data->name = util_alloc_string_copy( name ); - plot_data->pca_vectors = vector_alloc_new(); - plot_data->ens_size = matrix_get_columns( PC ); - plot_data->singular_values = double_vector_alloc_copy( singular_values ); - pca_plot_data_add_vectors( plot_data , PC , PC_obs , singular_values); - } - return plot_data; -} - - - - - -void pca_plot_data_free( pca_plot_data_type * plot_data ) { - vector_free( plot_data->pca_vectors ); - double_vector_free( plot_data->singular_values ); - free( plot_data->name ); - free( plot_data ); -} - -void pca_plot_data_free__( void * arg ) { - pca_plot_data_type * plot_data = pca_plot_data_safe_cast( arg ); - pca_plot_data_free( plot_data ); -} - -int pca_plot_data_get_size( const pca_plot_data_type * plot_data ) { - return vector_get_size( plot_data->pca_vectors ); -} - - -int pca_plot_data_get_ens_size( const pca_plot_data_type * plot_data ) { - return plot_data->ens_size; -} - -const pca_plot_vector_type * pca_plot_data_iget_vector( const pca_plot_data_type * plot_data , int ivec) { - return vector_iget_const( plot_data->pca_vectors , ivec ); -} - - -const char * pca_plot_data_get_name( const pca_plot_data_type * plot_data ) { - return plot_data->name; -} - - -const double_vector_type * pca_plot_data_get_singular_values( const pca_plot_data_type * plot_data ) { - return plot_data->singular_values; -} diff --git a/ThirdParty/Ert/libenkf/src/pca_plot_vector.c b/ThirdParty/Ert/libenkf/src/pca_plot_vector.c deleted file mode 100644 index b6f497d942..0000000000 --- a/ThirdParty/Ert/libenkf/src/pca_plot_vector.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - The file 'pca_plot_vector.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include - -#include -#include -#include - -#include - -#define PCA_PLOT_VECTOR_TYPE_ID 61743098 - -struct pca_plot_vector_struct { - UTIL_TYPE_ID_DECLARATION; - int size; - double singular_value; - double obs_value; - double * sim_data; -}; - - -UTIL_IS_INSTANCE_FUNCTION( pca_plot_vector , PCA_PLOT_VECTOR_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION( pca_plot_vector , PCA_PLOT_VECTOR_TYPE_ID ) - -bool pca_plot_assert_input( const matrix_type * PC, const matrix_type * PC_obs, const double_vector_type * singular_values) { - if ((matrix_get_rows(PC) == matrix_get_rows( PC_obs )) && - (matrix_get_columns(PC_obs) == 1) && - (double_vector_size( singular_values ) >= matrix_get_rows(PC))) - return true; - else - return false; -} - -static void pca_plot_vector_init_data( pca_plot_vector_type * plot_vector , int component, const matrix_type * PC , const matrix_type * PC_obs, const double_vector_type * singular_values) { - int iens; - - for (iens = 0; iens < matrix_get_columns( PC ); iens++) - plot_vector->sim_data[iens] = matrix_iget( PC, component , iens ); - - plot_vector->obs_value = matrix_iget( PC_obs , component , 0 ); - plot_vector->singular_value = double_vector_iget( singular_values , component ); -} - -pca_plot_vector_type * pca_plot_vector_alloc( int component , - const matrix_type * PC , - const matrix_type * PC_obs, - const double_vector_type * singular_values) { - pca_plot_vector_type * plot_vector = NULL; - - if (pca_plot_assert_input( PC , PC_obs , singular_values ) && (component < matrix_get_rows( PC ))) { - - plot_vector = util_malloc( sizeof * plot_vector ); - UTIL_TYPE_ID_INIT( plot_vector , PCA_PLOT_VECTOR_TYPE_ID ); - plot_vector->obs_value = matrix_iget( PC_obs , component , 0 ); - plot_vector->size = matrix_get_columns( PC ); - plot_vector->sim_data = util_calloc( plot_vector->size , sizeof * plot_vector->sim_data ); - pca_plot_vector_init_data( plot_vector , component , PC , PC_obs , singular_values); - } - - return plot_vector; -} - - - -void pca_plot_vector_free( pca_plot_vector_type * plot_vector ) { - free( plot_vector->sim_data ); - free( plot_vector ); -} - - -void pca_plot_vector_free__( void * arg ) { - pca_plot_vector_type * vector = pca_plot_vector_safe_cast( arg ); - pca_plot_vector_free( vector ); -} - - -int pca_plot_vector_get_size( const pca_plot_vector_type * vector ) { - return vector->size; -} - -double pca_plot_vector_get_obs_value( const pca_plot_vector_type * vector ) { - return vector->obs_value; -} - -double pca_plot_vector_get_singular_value( const pca_plot_vector_type * vector ) { - return vector->singular_value; -} - - -double pca_plot_vector_iget_sim_value( const pca_plot_vector_type * vector , int sim_index) { - return vector->sim_data[ sim_index ]; -} diff --git a/ThirdParty/Ert/libenkf/src/plain_driver.c b/ThirdParty/Ert/libenkf/src/plain_driver.c deleted file mode 100644 index 56e738617e..0000000000 --- a/ThirdParty/Ert/libenkf/src/plain_driver.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'plain_driver.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - - -/** - The actual path to a stored node can be divided in three parts: - - - /some/path/in/the/filesystem/CurrentDirectory/%03d/mem%03d/Analyzed/%s - |<--------- 1 ------------->|<----- 2 ------>|<-------- 3 ---------->| - - 1: This is root path of the enkf_fs filesystem. This is the path - specified with the ENS_PATH configuration variable in the - enkf_config system. - - 2: The "directory" is a sub indexing under the root path. Typicall - use of this is to differentiate between the enkf assimalition, - various forward runs, smoother solutions and so on. - - 3. The part with the %d variables in is the final storage - hierarchy, where the first the replacement (%d,%d,%s) -> - (report_step , iens, key) is done on run_time. - -*/ - - -struct plain_driver_struct { - FS_DRIVER_FIELDS; - int __id; - path_fmt_type * node_path; - path_fmt_type * vector_path; - /* ---------------------------*/ - char * mount_point; - char * node_fmt; - char * vector_fmt; -}; - - - -static void plain_driver_assert_cast(plain_driver_type * plain_driver) { - if (plain_driver->__id != PLAIN_DRIVER_ID) - util_abort("%s: internal error - cast failed - aborting \n",__func__); -} - - -static plain_driver_type * plain_driver_safe_cast( void * __driver) { - plain_driver_type * driver = (plain_driver_type *) __driver; - plain_driver_assert_cast(driver); - return driver; -} - - -static void plain_driver_load_node(void * _driver , const char * node_key, int report_step , int iens , buffer_type * buffer) { - plain_driver_type * driver = plain_driver_safe_cast( _driver ); - { - char * filename = path_fmt_alloc_file(driver->node_path , false , report_step , iens , node_key); - - buffer_fread_realloc( buffer , filename ); - free(filename); - } -} - - -static void plain_driver_load_vector(void * _driver , const char * node_key, int iens , buffer_type * buffer) { - plain_driver_type * driver = plain_driver_safe_cast( _driver ); - { - char * filename = path_fmt_alloc_file(driver->vector_path , false , iens , node_key); - - buffer_fread_realloc( buffer , filename ); - free(filename); - } -} - - - - -static void plain_driver_save_node(void * _driver , const char * node_key , int report_step , int iens , buffer_type * buffer) { - plain_driver_type * driver = (plain_driver_type *) _driver; - plain_driver_assert_cast(driver); - { - char * filename = path_fmt_alloc_file(driver->node_path , true , report_step , iens , node_key); - buffer_store( buffer , filename ); - free(filename); - } -} - - -static void plain_driver_save_vector(void * _driver , const char * node_key , int iens , buffer_type * buffer) { - plain_driver_type * driver = (plain_driver_type *) _driver; - plain_driver_assert_cast(driver); - { - char * filename = path_fmt_alloc_file(driver->vector_path , true , iens , node_key); - buffer_store( buffer , filename ); - free(filename); - } -} - - - -void plain_driver_unlink_node(void * _driver , const char * node_key , int report_step , int iens ) { - plain_driver_type * driver = (plain_driver_type *) _driver; - plain_driver_assert_cast(driver); - { - char * filename = path_fmt_alloc_file(driver->node_path , true , report_step , iens , node_key ); - util_unlink_existing(filename); - free(filename); - } -} - -void plain_driver_unlink_vector(void * _driver , const char * node_key , int iens ) { - plain_driver_type * driver = (plain_driver_type *) _driver; - plain_driver_assert_cast(driver); - { - char * filename = path_fmt_alloc_file(driver->vector_path , true , iens , node_key ); - util_unlink_existing(filename); - free(filename); - } -} - - -/** - Observe that the semantics is fundamentally different between - plain_driver_paramater_has_node, and plain_driver_load_node: - - * When (trying to) load a node the function will try previous report steps - all the way back to the first report step. - - * The has_node function will _not_ go back to earlier report steps, but - instead return false if the report_step we ask for is not present. -*/ - -bool plain_driver_has_node(void * _driver , const char * node_key , int report_step , int iens ) { - plain_driver_type * driver = (plain_driver_type *) _driver; - plain_driver_assert_cast(driver); - { - bool has_node; - char * filename = path_fmt_alloc_file(driver->node_path , true , report_step , iens , node_key); - if (util_file_exists(filename)) - has_node = true; - else - has_node = false; - free(filename); - return has_node; - } -} - - -bool plain_driver_has_vector(void * _driver , const char * node_key , int iens ) { - plain_driver_type * driver = (plain_driver_type *) _driver; - plain_driver_assert_cast(driver); - { - bool has_node; - char * filename = path_fmt_alloc_file(driver->vector_path , true , iens , node_key); - if (util_file_exists(filename)) - has_node = true; - else - has_node = false; - free(filename); - return has_node; - } -} - - - - -void plain_driver_free(void *_driver) { - plain_driver_type * driver = (plain_driver_type *) _driver; - plain_driver_assert_cast(driver); - - path_fmt_free(driver->node_path); - path_fmt_free(driver->vector_path); - - free( driver->vector_fmt ); - free( driver->node_fmt ); - util_safe_free( driver->mount_point ); - free(driver); -} - - - - -/** - The driver takes a copy of the path object, i.e. it can be deleted - in the calling scope after calling plain_driver_alloc(). - - This is where the various function pointers are initialized. -*/ - -void * plain_driver_alloc(const char * mount_point , const char * node_fmt, const char * vector_fmt) { - plain_driver_type * driver = util_malloc(sizeof * driver ); - { - fs_driver_type * fs_driver = (fs_driver_type *) driver; - fs_driver_init(fs_driver); - } - - driver->load_node = plain_driver_load_node; - driver->save_node = plain_driver_save_node; - driver->unlink_node = plain_driver_unlink_node; - driver->has_node = plain_driver_has_node; - - driver->load_vector = plain_driver_load_vector; - driver->save_vector = plain_driver_save_vector; - driver->unlink_vector = plain_driver_unlink_vector; - driver->has_vector = plain_driver_has_vector; - - driver->fsync_driver = NULL; - driver->free_driver = plain_driver_free; - driver->mount_point = util_alloc_string_copy( mount_point ); - driver->node_fmt = util_alloc_sprintf( "%s%c%s" , mount_point , UTIL_PATH_SEP_CHAR , node_fmt ); - driver->vector_fmt = util_alloc_sprintf( "%s%c%s" , mount_point , UTIL_PATH_SEP_CHAR , vector_fmt ); - - driver->node_path = path_fmt_alloc_directory_fmt( driver->node_fmt ); - driver->vector_path = path_fmt_alloc_directory_fmt( driver->vector_fmt ); - driver->__id = PLAIN_DRIVER_ID; - return driver; -} - - -void plain_driver_create_fs( FILE * stream , fs_driver_enum driver_type , const char * node_fmt , const char * vector_fmt) { - util_fwrite_int(driver_type , stream ); - util_fwrite_string(node_fmt , stream); - util_fwrite_string(vector_fmt , stream); -} - - -/** - The two integers from the mount info have already been read at the enkf_fs level. -*/ -void * plain_driver_open(FILE * fstab_stream , const char * mount_point) { - char * node_fmt = util_fread_alloc_string( fstab_stream ); - char * vector_fmt = util_fread_alloc_string( fstab_stream ); - plain_driver_type * driver = plain_driver_alloc( mount_point , node_fmt , vector_fmt ); - free(node_fmt); - free(vector_fmt); - return driver; -} - - - -void plain_driver_fskip(FILE * fstab_stream ) { - char * node_fmt = util_fread_alloc_string( fstab_stream ); - char * vector_fmt = util_fread_alloc_string( fstab_stream ); - free(node_fmt); - free(vector_fmt); -} diff --git a/ThirdParty/Ert/libenkf/src/plain_driver_obs.c b/ThirdParty/Ert/libenkf/src/plain_driver_obs.c deleted file mode 100644 index e6029d0324..0000000000 --- a/ThirdParty/Ert/libenkf/src/plain_driver_obs.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'plain_driver_obs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include - - - -struct plain_driver_obs_struct { - BASIC_OBS_DRIVER_FIELDS; - int __id; - path_fmt_type * path; /* With one embedded %d format character which is replaced with report_step on runtime. */ -}; - - - - - - - -static plain_driver_obs_type * plain_driver_obs_safe_cast(void * _driver) { - plain_driver_obs_type * driver = (plain_driver_obs_type *) _driver; - - if (driver->__id != PLAIN_DRIVER_OBS_ID) - util_abort("%s: internal error - cast failed - aborting \n",__func__); - - return driver; -} - - - - -static char * plain_driver_obs_alloc_filename(const plain_driver_obs_type * driver , int report_step , const char * key, bool auto_mkdir) { - return path_fmt_alloc_file(driver->path , auto_mkdir , report_step , key); -} - - - -void plain_driver_obs_load_node(void * _driver , int report_step , obs_node_type * node) { - plain_driver_obs_type * driver = plain_driver_obs_safe_cast(_driver); - { - char * filename = plain_driver_obs_alloc_filename(driver , report_step , obs_node_get_key(node) , false); - FILE * stream = util_fopen(filename , "r"); - - obs_node_fread(node , stream , report_step); - - fclose(stream); - free(filename); - } -} - - -void plain_driver_obs_unlink_node(void * _driver , int report_step , obs_node_type * node) { - plain_driver_obs_type * driver = plain_driver_obs_safe_cast(_driver); - { - char * filename = plain_driver_obs_alloc_filename(driver , report_step , obs_node_get_key(node) , false); - util_unlink_existing(filename); - free(filename); - } -} - - -void plain_driver_obs_save_node(void * _driver , int report_step , obs_node_type * node) { - plain_driver_obs_type * driver = plain_driver_obs_safe_cast(_driver); - { - char * filename = plain_driver_obs_alloc_filename(driver , report_step , obs_node_get_key(node) , true); - FILE * stream = util_fopen(filename , "w"); - bool data_written = obs_node_fwrite(node , stream , report_step); - fclose(stream); - if (!data_written) - util_unlink_existing( filename ); /* remove empty files. */ - free(filename); - } -} - - -/** - Return true if we have a on-disk representation of the node. -*/ - -bool plain_driver_obs_has_node(void * _driver , int report_step , const char * key) { - plain_driver_obs_type * driver = plain_driver_obs_safe_cast(_driver); - { - bool has_node; - char * filename = plain_driver_obs_alloc_filename(driver , report_step , key , false); - if (util_file_exists(filename)) - has_node = true; - else - has_node = false; - free(filename); - return has_node; - } -} - - - - -void plain_driver_obs_free(void *_driver) { - plain_driver_obs_type * driver = plain_driver_obs_safe_cast(_driver); - path_fmt_free(driver->path); - free(driver); -} - - - -void plain_driver_obs_README(const char * root_path) { - char * README_file = util_alloc_full_path(root_path , "README.txt"); - util_make_path(root_path); - { - FILE * stream = util_fopen(README_file , "w"); - fprintf(stream,"This is the root directory of the EnKF ensemble filesystem. All files contain one enkf_node \n"); - fprintf(stream,"instance. The files are binary, and compressed with zlib (util_fwrite_compressed).\n"); - fclose(stream); - } - free(README_file); -} - - -/* - The driver takes a copy of the path object, i.e. it can be deleted - in the calling scope after calling plain_driver_obs_alloc(). -*/ -void * plain_driver_obs_alloc(const char * root_path , const char * obs_path ) { - plain_driver_obs_type * driver = util_malloc(sizeof * driver ); - driver->load = plain_driver_obs_load_node; - driver->save = plain_driver_obs_save_node; - driver->has_node = plain_driver_obs_has_node; - driver->free_driver = plain_driver_obs_free; - driver->unlink_node = plain_driver_obs_unlink_node; - { - char *path; - - if (root_path != NULL) - path = util_alloc_full_path(root_path , obs_path); - else - path = util_alloc_string_copy(obs_path); - - driver->path = path_fmt_alloc_directory_fmt( path ); - free(path); - } - driver->__id = PLAIN_DRIVER_OBS_ID; - { - basic_obs_driver_type * basic_driver = (basic_obs_driver_type *) driver; - basic_obs_driver_init(basic_driver); - return basic_driver; - } -} - - -void plain_driver_obs_fwrite_mount_info(FILE * stream , const char * obs_fmt ) { - util_fwrite_int(OBS_DRIVER , stream); - util_fwrite_int(PLAIN_DRIVER_OBS_ID , stream); - util_fwrite_string(obs_fmt , stream); - -} - -/** - The two integers from the mount info have already been read at the enkf_fs level. -*/ -plain_driver_obs_type * plain_driver_obs_fread_alloc(const char * root_path , FILE * stream) { - char * obs_fmt = util_fread_alloc_string( stream ); - plain_driver_obs_type * driver = plain_driver_obs_alloc(root_path , obs_fmt); - free(obs_fmt); - return driver; -} - diff --git a/ThirdParty/Ert/libenkf/src/plot_settings.c b/ThirdParty/Ert/libenkf/src/plot_settings.c deleted file mode 100644 index e23f971b52..0000000000 --- a/ThirdParty/Ert/libenkf/src/plot_settings.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'plot_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#define TRUE_STRING "True" -#define FALSE_STRING "False" - -#define PATH_KEY "PATH" -#define SHOW_REFCASE_KEY "SHOW_REFCASE" -#define SHOW_HISTORY_KEY "SHOW_HISTORY" - -#define DEFAULT_PLOT_PATH "plots" -#define DEFAULT_SHOW_REFCASE FALSE_STRING -#define DEFAULT_SHOW_HISTORY FALSE_STRING - - -void plot_settings_init(config_settings_type * settings) { - - config_settings_add_setting(settings , PATH_KEY , CONFIG_STRING , DEFAULT_PLOT_PATH ); - config_settings_add_setting(settings , SHOW_REFCASE_KEY , CONFIG_BOOL , DEFAULT_SHOW_REFCASE ); - config_settings_add_setting(settings , SHOW_HISTORY_KEY , CONFIG_BOOL , DEFAULT_SHOW_HISTORY ); - -} - - -void plot_settings_add_config_items( config_parser_type * config ) { - config_settings_init_parser__( PLOT_SETTING_KEY , config , false ); - - config_add_key_value(config , PLOT_PATH_KEY , false , CONFIG_STRING); - { - char * msg = util_alloc_sprintf( "The keyword %s has been deprecated - use %s %s ", PLOT_PATH_KEY , PLOT_SETTING_KEY , PATH_KEY ); - config_parser_deprecate( config , PLOT_PATH_KEY , msg); - free( msg ); - } -} - - diff --git a/ThirdParty/Ert/libenkf/src/ranking_table.c b/ThirdParty/Ert/libenkf/src/ranking_table.c deleted file mode 100644 index f7801c0474..0000000000 --- a/ThirdParty/Ert/libenkf/src/ranking_table.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'ranking_table.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - - -#define RANKING_TABLE_TYPE_ID 78420651 - -struct ranking_table_struct { - UTIL_TYPE_ID_DECLARATION; - int ens_size; // Will not really handle ensemble resize events - hash_type * ranking_table; -}; - - - -void ranking_table_free( ranking_table_type * table ) { - hash_free( table->ranking_table ); - free( table ); -} - - - -void ranking_table_set_ens_size( ranking_table_type * table, int ens_size) { - table->ens_size = ens_size; -} - -ranking_table_type * ranking_table_alloc( int ens_size ) { - ranking_table_type * table = util_malloc( sizeof * table ); - table->ranking_table = hash_alloc(); - return table; -} - - -void ranking_table_add_data_ranking( ranking_table_type * ranking_table , bool sort_increasing , const char * ranking_key , const char * user_key , const char * key_index , - enkf_fs_type * fs , const enkf_config_node_type * config_node , int step) { - - data_ranking_type * ranking = data_ranking_alloc( sort_increasing , ranking_table->ens_size , user_key , key_index , fs , config_node , step ); - hash_insert_hash_owned_ref( ranking_table->ranking_table , ranking_key , ranking, data_ranking_free__ ); -} - - - -void ranking_table_add_misfit_ranking( ranking_table_type * ranking_table , const misfit_ensemble_type * misfit_ensemble , const stringlist_type * obs_keys , const int_vector_type * steps , const char * ranking_key) { - misfit_ranking_type * ranking = misfit_ranking_alloc( misfit_ensemble , obs_keys , steps , ranking_key ); - hash_insert_hash_owned_ref( ranking_table->ranking_table , ranking_key , ranking , misfit_ranking_free__ ); -} - - - -bool ranking_table_has_ranking( const ranking_table_type * ranking_table , const char * ranking_key ) { - return hash_has_key( ranking_table->ranking_table , ranking_key ); -} - - -int ranking_table_get_size( const ranking_table_type * ranking_table ) { - return hash_get_size( ranking_table->ranking_table ); -} - - - -bool ranking_table_display_ranking( const ranking_table_type * ranking_table , const char * ranking_key ) { - if (hash_has_key( ranking_table->ranking_table , ranking_key)) { - void * ranking = hash_get( ranking_table->ranking_table , ranking_key ); - - if (data_ranking_is_instance( ranking )) { - data_ranking_type * data_ranking = data_ranking_safe_cast( ranking ); - data_ranking_display( data_ranking , stdout ); - } else if (misfit_ranking_is_instance( ranking )) { - misfit_ranking_type * misfit_ranking = misfit_ranking_safe_cast( ranking ); - misfit_ranking_display( misfit_ranking , stdout ); - } else - util_abort("%s: internal error \n",__func__); - - - return true; - } else - return false; -} - - -bool ranking_table_fwrite_ranking( const ranking_table_type * ranking_table , const char * ranking_key, const char * filename ) { - if (hash_has_key( ranking_table->ranking_table , ranking_key)) { - void * ranking = hash_get( ranking_table->ranking_table , ranking_key ); - - FILE * file = util_mkdir_fopen(filename, "w"); - - if (data_ranking_is_instance( ranking )) { - data_ranking_type * data_ranking = data_ranking_safe_cast( ranking ); - data_ranking_display( data_ranking , file ); - } else if (misfit_ranking_is_instance( ranking )) { - misfit_ranking_type * misfit_ranking = misfit_ranking_safe_cast( ranking ); - misfit_ranking_display( misfit_ranking , file ); - } else - util_abort("%s: internal error \n",__func__); - - util_fclose(file); - - return true; - } else - return false; -} - - - - -const perm_vector_type * ranking_table_get_permutation( const ranking_table_type * ranking_table , const char * ranking_key) { - if (hash_has_key( ranking_table->ranking_table , ranking_key)) { - void * ranking = hash_get( ranking_table->ranking_table , ranking_key ); - - if (data_ranking_is_instance( ranking )) { - data_ranking_type * data_ranking = data_ranking_safe_cast( ranking ); - return data_ranking_get_permutation( data_ranking ); - } else if (misfit_ranking_is_instance( ranking )) { - misfit_ranking_type * misfit_ranking = misfit_ranking_safe_cast( ranking ); - return misfit_ranking_get_permutation( misfit_ranking ); - } else { - util_abort("%s: internal error \n"); - return NULL; - } - - } else - return NULL; -} - - - - diff --git a/ThirdParty/Ert/libenkf/src/readme.overview b/ThirdParty/Ert/libenkf/src/readme.overview deleted file mode 100644 index 5b3c3dff52..0000000000 --- a/ThirdParty/Ert/libenkf/src/readme.overview +++ /dev/null @@ -1,55 +0,0 @@ -The EnKF functionality is organized in xxx libraries with different -functionalities. The different libraries depend on eachother, and the -libraries must be built in correct order. The dependencies is as -follows: - -libhash : -libutil : libhash -libecl : libhash libutil -librms : libecl libutil libhash -libsched : libecl linutil libhash -libenkf : libecl libsched librm linutil libhash - - -libhash: This library implements the classes hash_type, set_type and - list_type. - -libutil: This library is a collection utility routines. Observe that - this library only implements routines, and not statefull - objects. - -libecl: This library implements functions for reading/writing ECLIPSE - restart/summary/init/grid files. - -libsched: This library implements a basic SCHEDULE file parser. - -librms: This library implements (basic) reader and writer for binary - RMS ROFF files. - -libenkf: This library implements various high level objects for EnKF - functionality. - ------------------------------------------------------------------ - -All the makefiles start with the statement: - -include "path_config" - -The file path_config is *not* under version control, this is on -purpose because every user can/should have a private confiiguration of -paths. The file path_config should define make-variables for the -location of all the libraries, this is an example of a valid -path-config file: - - LIBHASH_HOME = /h/a152128/EnKF/EnKF/libhash - LIBUTIL_HOME = /h/a152128/EnKF/EnKF/libutil - LIBSCHED_HOME = /h/a152128/EnKF/EnKF/libsched - LIBRMS_HOME = /h/a152128/EnKF/EnKF/librms - LIBECL_HOME = /h/a152128/EnKF/EnKF/libecl - LIBENKF_HOME = /h/a152128/EnKF/EnKF/libenkf - -In this example all libraries have a common path prefix, that is not -a requirement. - - - diff --git a/ThirdParty/Ert/libenkf/src/rng_config.c b/ThirdParty/Ert/libenkf/src/rng_config.c deleted file mode 100644 index b5a0af25ea..0000000000 --- a/ThirdParty/Ert/libenkf/src/rng_config.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rng_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - - -struct rng_config_struct { - rng_alg_type type; - char * seed_load_file; /* NULL: Do not store the seed. */ - char * seed_store_file; /* NULL: Do not load a seed from file. */ -}; - - - -void rng_config_set_type( rng_config_type * rng_config , rng_alg_type type) { - rng_config->type = type; -} - -rng_alg_type rng_config_get_type(const rng_config_type * rng_config ) { - return rng_config->type; -} - -const char * rng_config_get_seed_load_file( const rng_config_type * rng_config ) { - return rng_config->seed_load_file; -} - -void rng_config_set_seed_load_file( rng_config_type * rng_config , const char * seed_load_file) { - rng_config->seed_load_file = util_realloc_string_copy( rng_config->seed_load_file , seed_load_file); -} - -const char * rng_config_get_seed_store_file( const rng_config_type * rng_config ) { - return rng_config->seed_store_file; -} - -void rng_config_set_seed_store_file( rng_config_type * rng_config , const char * seed_store_file) { - rng_config->seed_store_file = util_realloc_string_copy( rng_config->seed_store_file , seed_store_file); -} - - -rng_config_type * rng_config_alloc( ) { - rng_config_type * rng_config = util_malloc( sizeof * rng_config); - - rng_config_set_type( rng_config , MZRAN ); /* Only type ... */ - rng_config->seed_store_file = NULL; - rng_config->seed_load_file = NULL; - - return rng_config; -} - - - -void rng_config_free( rng_config_type * rng) { - util_safe_free( rng->seed_load_file ); - util_safe_free( rng->seed_store_file ); - free( rng ); -} - -rng_type * rng_config_init_rng__(const rng_config_type * rng_config, rng_type * rng) { - const char * seed_load = rng_config_get_seed_load_file( rng_config ); - const char * seed_store = rng_config_get_seed_store_file( rng_config ); - - if (seed_load != NULL) { - if (util_file_exists( seed_load)) - rng_load_state( rng , seed_load ); - else { - /* - In the special case that seed_load == seed_store; we accept a - seed_load argument pointing to a non-existant file. - */ - if (seed_store) { - if (util_string_equal( seed_store , seed_load)) - rng_init( rng , INIT_DEV_URANDOM ); - else - util_abort("%s: tried to load random seed from non-existing file:%s \n",__func__ , seed_load); - } - } - } else - rng_init( rng , INIT_DEV_URANDOM ); - - - if (seed_store != NULL) - rng_save_state( rng , seed_store ); - - return rng; -} - -rng_type * rng_config_alloc_init_rng( const rng_config_type * rng_config ) { - rng_type * rng = rng_alloc(rng_config_get_type(rng_config) , INIT_DEFAULT); - return rng_config_init_rng__(rng_config, rng); -} - - -void rng_config_init_rng( const rng_config_type * rng_config, rng_type * rng ) { - rng_config_init_rng__(rng_config, rng); -} - - - -/*****************************************************************/ - -void rng_config_add_config_items( config_parser_type * config ) { - config_schema_item_type * item; - - item= config_add_schema_item( config , STORE_SEED_KEY , false); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , CONFIG_PATH ); - - item = config_add_schema_item( config , LOAD_SEED_KEY , false ); - config_schema_item_set_argc_minmax(item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , CONFIG_PATH ); -} - - -void rng_config_init( rng_config_type * rng_config , config_content_type * config ) { - if (config_content_has_item( config , STORE_SEED_KEY )) - rng_config_set_seed_store_file( rng_config , config_content_iget(config , STORE_SEED_KEY ,0,0)); - - if (config_content_has_item( config , LOAD_SEED_KEY )) - rng_config_set_seed_load_file( rng_config , config_content_iget(config , LOAD_SEED_KEY ,0,0)); -} - - -void rng_config_fprintf_config( rng_config_type * rng_config , FILE * stream ) { - if (rng_config->seed_load_file != NULL) { - fprintf( stream , CONFIG_KEY_FORMAT , LOAD_SEED_KEY ); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , rng_config->seed_load_file); - } - - if (rng_config->seed_store_file != NULL) { - fprintf( stream , CONFIG_KEY_FORMAT , STORE_SEED_KEY ); - fprintf( stream , CONFIG_ENDVALUE_FORMAT , rng_config->seed_store_file); - } -} diff --git a/ThirdParty/Ert/libenkf/src/run_arg.c b/ThirdParty/Ert/libenkf/src/run_arg.c deleted file mode 100644 index e873aef6af..0000000000 --- a/ThirdParty/Ert/libenkf/src/run_arg.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'run_arg.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include - -#include -#include -#include - - -#define RUN_ARG_TYPE_ID 66143287 -#define INVALID_QUEUE_INDEX -99 - - -struct run_arg_struct { - UTIL_TYPE_ID_DECLARATION; - int iens; - int max_internal_submit; /* How many times the enkf_state object should try to resubmit when the queueu has said everything is OK - but the load fails. */ - int num_internal_submit; - int load_start; /* When loading back results - start at this step. */ - int step1; /* The forward model is integrated: step1 -> step2 */ - int step2; - int iter; - char * run_path; /* The currently used runpath - is realloced / freed for every step. */ - run_mode_type run_mode; /* What type of run this is */ - int queue_index; /* The job will in general have a different index in the queue than the iens number. */ - - enkf_fs_type * init_fs; - enkf_fs_type * result_fs; - enkf_fs_type * update_target_fs; - - /******************************************************************/ - /* Return value - set by the called routine!! */ - run_status_type run_status; -}; - - -UTIL_SAFE_CAST_FUNCTION( run_arg , RUN_ARG_TYPE_ID ) -UTIL_IS_INSTANCE_FUNCTION( run_arg , RUN_ARG_TYPE_ID ) - - -static run_arg_type * run_arg_alloc(enkf_fs_type * init_fs , - enkf_fs_type * result_fs , - enkf_fs_type * update_target_fs , - int iens , - run_mode_type run_mode , - int step1 , - int step2 , - int iter , - const char * runpath) { - if ((result_fs != NULL) && (result_fs == update_target_fs)) - util_abort("%s: internal error - can not have result_fs == update_target_fs \n",__func__); - { - run_arg_type * run_arg = util_malloc(sizeof * run_arg ); - UTIL_TYPE_ID_INIT(run_arg , RUN_ARG_TYPE_ID); - - run_arg->init_fs = init_fs; - run_arg->result_fs = result_fs; - run_arg->update_target_fs = update_target_fs; - - run_arg->iens = iens; - run_arg->run_mode = run_mode; - run_arg->step1 = step1; - run_arg->step2 = step2; - run_arg->iter = iter; - run_arg->run_path = util_alloc_abs_path( runpath ); - run_arg->num_internal_submit = 0; - run_arg->queue_index = INVALID_QUEUE_INDEX; - run_arg->run_status = JOB_NOT_STARTED; - - if (step1 == 0) - run_arg->load_start = 1; - else - run_arg->load_start = step1; - - return run_arg; - } -} - - - - - -run_arg_type * run_arg_alloc_ENSEMBLE_EXPERIMENT(enkf_fs_type * fs , int iens , int iter , const char * runpath) { - return run_arg_alloc(fs , fs , NULL , iens , ENSEMBLE_EXPERIMENT , 0 , 0 , iter , runpath); -} - - -run_arg_type * run_arg_alloc_INIT_ONLY(enkf_fs_type * init_fs , int iens , int iter , const char * runpath) { - return run_arg_alloc(init_fs , NULL , NULL , iens , INIT_ONLY , 0 , 0 , iter , runpath); -} - - -run_arg_type * run_arg_alloc_SMOOTHER_RUN(enkf_fs_type * simulate_fs , enkf_fs_type * update_target_fs , int iens , int iter , const char * runpath) { - return run_arg_alloc(simulate_fs , simulate_fs , update_target_fs , iens , ENSEMBLE_EXPERIMENT , 0 , 0 , iter , runpath); -} - - - -void run_arg_free(run_arg_type * run_arg) { - util_safe_free(run_arg->run_path); - free(run_arg); -} - - -void run_arg_free__(void * arg) { - run_arg_type * run_arg = run_arg_safe_cast( arg ); - run_arg_free( run_arg ); -} - - -void run_arg_complete_run(run_arg_type * run_arg) { - if (run_arg->run_status == JOB_RUN_OK) { - util_safe_free(run_arg->run_path); - run_arg->run_path = NULL; - } -} - - - -void run_arg_increase_submit_count( run_arg_type * run_arg ) { - run_arg->num_internal_submit++; -} - - -void run_arg_set_queue_index( run_arg_type * run_arg , int queue_index) { - if (run_arg->queue_index == INVALID_QUEUE_INDEX) - run_arg->queue_index = queue_index; - else - util_abort("%s: attempt to reset run_arg->queue_index. These objects should not be recycled\n",__func__); -} - - - -const char * run_arg_get_runpath( const run_arg_type * run_arg) { - return run_arg->run_path; -} - - - - -int run_arg_get_iter( const run_arg_type * run_arg ) { - return run_arg->iter; -} - - -int run_arg_get_iens( const run_arg_type * run_arg ) { - return run_arg->iens; -} - - -int run_arg_get_load_start( const run_arg_type * run_arg ) { - return run_arg->load_start; -} - - -int run_arg_get_step2( const run_arg_type * run_arg ) { - return run_arg->step2; -} - -bool run_arg_can_retry( const run_arg_type * run_arg ) { - if (run_arg->num_internal_submit < run_arg->max_internal_submit) - return true; - else - return false; -} - - -int run_arg_get_step1( const run_arg_type * run_arg ) { - return run_arg->step1; -} - - -run_mode_type run_arg_get_run_mode( const run_arg_type * run_arg ) { - return run_arg->run_mode; -} - - -int run_arg_get_queue_index( const run_arg_type * run_arg ) { - if (run_arg->queue_index == INVALID_QUEUE_INDEX) - util_abort("%s: sorry internal error - asking for the queue_index in a not-initialized run_arg object.\n" , __func__); - - return run_arg->queue_index; -} - -bool run_arg_is_submitted( const run_arg_type * run_arg ) { - if (run_arg->queue_index == INVALID_QUEUE_INDEX) - return false; - else - return true; -} - - -run_status_type run_arg_get_run_status( const run_arg_type * run_arg) { - return run_arg->run_status; -} - - -void run_arg_set_run_status( run_arg_type * run_arg , run_status_type run_status) { - run_arg->run_status = run_status; -} - - - -enkf_fs_type * run_arg_get_init_fs(const run_arg_type * run_arg) { - if (run_arg->init_fs) - return run_arg->init_fs; - else { - util_abort("%s: internal error - tried to access run_arg->init_fs when init_fs == NULL\n",__func__); - return NULL; - } -} - - -enkf_fs_type * run_arg_get_result_fs(const run_arg_type * run_arg) { - if (run_arg->result_fs) - return run_arg->result_fs; - else { - util_abort("%s: internal error - tried to access run_arg->result_fs when result_fs == NULL\n",__func__); - return NULL; - } -} - - -enkf_fs_type * run_arg_get_update_target_fs(const run_arg_type * run_arg) { - if (run_arg->update_target_fs) - return run_arg->update_target_fs; - else { - util_abort("%s: internal error - tried to access run_arg->update_target_fs when update_target_fs == NULL\n",__func__); - return NULL; - } -} diff --git a/ThirdParty/Ert/libenkf/src/runpath_list.c b/ThirdParty/Ert/libenkf/src/runpath_list.c deleted file mode 100644 index 75e621231d..0000000000 --- a/ThirdParty/Ert/libenkf/src/runpath_list.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - The file 'runpath_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include - -#include -#include -#include - -#include - -typedef struct runpath_node_struct runpath_node_type; - - -struct runpath_list_struct { - pthread_rwlock_t lock; - vector_type * list; - char * line_fmt; // Format string : Values are in the order: (iens , runpath , basename) - char * export_file; -}; - - -#define RUNPATH_NODE_TYPE_ID 661400541 -struct runpath_node_struct { - UTIL_TYPE_ID_DECLARATION; - int iens; - int iter; - char * runpath; - char * basename; -}; - - -/*****************************************************************/ - - UTIL_SAFE_CAST_FUNCTION( runpath_node , RUNPATH_NODE_TYPE_ID ) - UTIL_SAFE_CAST_FUNCTION_CONST( runpath_node , RUNPATH_NODE_TYPE_ID ) - - static runpath_node_type * runpath_node_alloc( int iens, int iter, const char * runpath , const char * basename) { - runpath_node_type * node = util_malloc( sizeof * node ); - UTIL_TYPE_ID_INIT( node , RUNPATH_NODE_TYPE_ID ); - - node->iens = iens; - node->iter = iter; - node->runpath = util_alloc_string_copy( runpath ); - node->basename = util_alloc_string_copy( basename ); - - return node; - } - - -static void runpath_node_free( runpath_node_type * node ) { - free(node->basename); - free(node->runpath); - free(node); -} - - -static void runpath_node_free__( void * arg ) { - runpath_node_type * node = runpath_node_safe_cast( arg ); - runpath_node_free( node ); -} - - -/* - The comparison is first based on iteration number and then on iens. -*/ - -static int runpath_node_cmp( const void * arg1 , const void * arg2) { - const runpath_node_type * node1 = runpath_node_safe_cast_const( arg1 ); - const runpath_node_type * node2 = runpath_node_safe_cast_const( arg2 ); - { - if (node1->iter > node2->iter) - return 1; - else if (node1->iter < node2->iter) - return -1; - else { - /* Iteration number is the same */ - if (node1->iens > node2->iens) - return 1; - else if (node1->iens < node2->iens) - return -1; - else - return 0; - } - } -} - - -static void runpath_node_fprintf( const runpath_node_type * node , const char * line_fmt , FILE * stream) { - fprintf(stream , line_fmt , node->iens, node->runpath , node->basename, node->iter); -} - - -/*****************************************************************/ - - -runpath_list_type * runpath_list_alloc(const char * export_file) { - runpath_list_type * list = util_malloc( sizeof * list ); - list->list = vector_alloc_new(); - list->line_fmt = NULL; - list->export_file = util_alloc_string_copy( export_file ); - pthread_rwlock_init( &list->lock , NULL ); - return list; -} - - -void runpath_list_free( runpath_list_type * list ) { - vector_free( list->list ); - util_safe_free( list->line_fmt ); - util_safe_free( list->export_file); - free( list ); -} - - -int runpath_list_size( const runpath_list_type * list ) { - return vector_get_size( list->list ); -} - - -void runpath_list_add( runpath_list_type * list , int iens , int iter, const char * runpath , const char * basename) { - runpath_node_type * node = runpath_node_alloc( iens , iter, runpath , basename ); - - pthread_rwlock_wrlock( &list->lock ); - { - vector_append_owned_ref( list->list , node , runpath_node_free__ ); - } - pthread_rwlock_unlock( &list->lock ); -} - - -void runpath_list_clear( runpath_list_type * list ) { - pthread_rwlock_wrlock( &list->lock ); - { - vector_clear( list->list ); - } - pthread_rwlock_unlock( &list->lock ); -} - -/*****************************************************************/ - -void runpath_list_set_line_fmt( runpath_list_type * list , const char * line_fmt ) { - list->line_fmt = util_realloc_string_copy( list->line_fmt , line_fmt ); -} - - -const char * runpath_list_get_line_fmt( const runpath_list_type * list ) { - if (list->line_fmt == NULL) - return RUNPATH_LIST_DEFAULT_LINE_FMT; - else - return list->line_fmt; -} - -/*****************************************************************/ - - -static const runpath_node_type * runpath_list_iget_node__( const runpath_list_type * list , int index) { - return vector_iget_const( list->list , index ); -} - - - -static const runpath_node_type * runpath_list_iget_node( runpath_list_type * list , int index) { - const runpath_node_type * node; - { - pthread_rwlock_rdlock( &list->lock ); - node = runpath_list_iget_node__( list , index ); - pthread_rwlock_unlock( &list->lock ); - } - return node; -} - - -int runpath_list_iget_iens( runpath_list_type * list , int index) { - const runpath_node_type * node = runpath_list_iget_node( list , index ); - return node->iens; -} - -int runpath_list_iget_iter( runpath_list_type * list , int index) { - const runpath_node_type * node = runpath_list_iget_node( list , index ); - return node->iter; -} - - -char * runpath_list_iget_runpath( runpath_list_type * list , int index) { - const runpath_node_type * node = runpath_list_iget_node( list , index ); - return node->runpath; -} - -char * runpath_list_iget_basename( runpath_list_type * list , int index) { - const runpath_node_type * node = runpath_list_iget_node( list , index ); - return node->basename; -} - -void runpath_list_fprintf(runpath_list_type * list ) { - pthread_rwlock_rdlock( &list->lock ); - { - FILE * stream = util_mkdir_fopen( list->export_file , "w"); - const char * line_fmt = runpath_list_get_line_fmt( list ); - int index; - vector_sort( list->list , runpath_node_cmp ); - for (index =0; index < vector_get_size( list->list ); index++) { - const runpath_node_type * node = runpath_list_iget_node__( list , index ); - runpath_node_fprintf( node , line_fmt , stream ); - } - fclose( stream ); - } - pthread_rwlock_unlock( &list->lock ); -} - - -const char * runpath_list_get_export_file( const runpath_list_type * list ) { - return list->export_file; -} - - -void runpath_list_set_export_file( runpath_list_type * list , const char * export_file ) { - list->export_file = util_realloc_string_copy( list->export_file , export_file ); -} diff --git a/ThirdParty/Ert/libenkf/src/scalar_config.c b/ThirdParty/Ert/libenkf/src/scalar_config.c deleted file mode 100644 index 27ff8c09ef..0000000000 --- a/ThirdParty/Ert/libenkf/src/scalar_config.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'scalar_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SCALAR_CONFIG_TYPE_ID 877065 - -struct scalar_config_struct { - UTIL_TYPE_ID_DECLARATION; - int data_size; - active_list_type * active_list; - - trans_func_type ** transform; -}; - - - - -scalar_config_type * scalar_config_alloc_empty(int size) { - scalar_config_type *scalar_config = util_malloc(sizeof *scalar_config); - UTIL_TYPE_ID_INIT( scalar_config , SCALAR_CONFIG_TYPE_ID ); - scalar_config->data_size = size; - scalar_config->active_list = active_list_alloc( ); - - scalar_config->transform = util_calloc(scalar_config->data_size , sizeof * scalar_config->transform ); - return scalar_config; -} - - - -void scalar_config_transform(const scalar_config_type * config , const double * input_data , double *output_data) { - int index; - for (index = 0; index < config->data_size; index++) - output_data[index] = trans_func_eval( config->transform[index] , input_data[index] ); -} - - - - - - -void scalar_config_fscanf_line(scalar_config_type * config , int line_nr , FILE * stream) { - config->transform[line_nr] = trans_func_fscanf_alloc( stream ); -} - - - -void scalar_config_free(scalar_config_type * scalar_config) { - int i; - active_list_free(scalar_config->active_list); - for (i=0; i < scalar_config->data_size; i++) - trans_func_free( scalar_config->transform[i] ); - - util_safe_free( scalar_config->transform ); - free(scalar_config); -} - - - -/*****************************************************************/ - -SAFE_CAST(scalar_config , SCALAR_CONFIG_TYPE_ID) -GET_DATA_SIZE(scalar); -GET_ACTIVE_LIST(scalar); -VOID_FREE(scalar_config); diff --git a/ThirdParty/Ert/libenkf/src/site_config.c b/ThirdParty/Ert/libenkf/src/site_config.c deleted file mode 100644 index d520ed6319..0000000000 --- a/ThirdParty/Ert/libenkf/src/site_config.c +++ /dev/null @@ -1,987 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'site_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -/** - This struct contains information which is specific to the site - where this enkf instance is running. Pointers to the fields in this - structure are passed on to e.g. the enkf_state->shared_info object, - but this struct is the *OWNER* of this information, and hence - responsible for booting and deleting these objects. - - The settings held by the site_config object are by default set in - the site-wide configuration file, but they can also be overridden - in the users configuration file. This makes both parsing, - validating and also storing the configuration information a bit - more tricky: - - Parsing: - -------- - When parsing the user configuration file all settings are optional, - that means that the required validation of the config system, can - not be used, instead every get must be preceeded by: - - if (config_content_has_item(config , KEY)) ... - - Furthermore everything is done twice; first with config as a - site-config instance, and later as user-config instance. - - - Saving: - ------- - A setting which originates from the site_config file should not be - stored in the user's config file, but additions/overrides from the - user's config file should of course be saved. This is 'solved' with - many fields having a xxx_site duplicate, where the xxx_site is only - updated during the initial parsing of the site-config file; when - the flag user_mode is set to true the xxx_site fields are not - updated. When saving only fields which are different from their - xxx_site counterpart are stored. - */ - -#define LSF_DRIVER_NAME "LSF" -#define LOCAL_DRIVER_NAME "LOCAL" -#define RSH_DRIVER_NAME "RSH" -#define TORQUE_DRIVER_NAME "TORQUE" - -struct site_config_struct { - ext_joblist_type * joblist; /* The list of external jobs which have been installed. - These jobs will be the parts of the forward model. */ - hash_type * env_variables_user; /* The environment variables set in the user config file. */ - hash_type * env_variables_site; /* The environment variables set in site_config file - not exported. */ - - mode_t umask; - - char * license_root_path; /* The license_root_path value set by the user. */ - char * license_root_path_site; /* The license_root_path value set by the site. */ - char * __license_root_path; /* The license_root_path value actually used - includes a user/pid subdirectory. */ - - hash_type * path_variables_site; /* We store this so we can roll back when all user settings are cleared. */ - stringlist_type * path_variables_user; /* We can update the same path variable several times - i.e. it can not be a hash table. */ - stringlist_type * path_values_user; - - int max_running_lsf_site; - char * lsf_queue_name_site; - char * lsf_request_site; - - int max_running_rsh_site; - char * rsh_command_site; - - int max_running_local_site; - - job_driver_type driver_type; - job_driver_type driver_type_site; - int max_submit; - int max_submit_site; - char * job_script; - char * job_script_site; - - char * manual_url; - char * default_browser; - - queue_driver_type * current_driver; - hash_type * queue_drivers; - - job_queue_type * job_queue; /* The queue instance which will run the external jobs. */ - bool user_mode; - bool search_path; -}; - -void site_config_set_umask(site_config_type * site_config, mode_t new_mask) { - umask(new_mask); - site_config->umask = new_mask; -} - -mode_t site_config_get_umask(const site_config_type * site_config) { - return site_config->umask; -} - -static void site_config_add_queue_driver(site_config_type * site_config, const char * driver_name, queue_driver_type * driver) { - hash_insert_hash_owned_ref(site_config->queue_drivers, driver_name, driver, queue_driver_free__); -} - -bool site_config_has_queue_driver(const site_config_type * site_config, const char * driver_name) { - return hash_has_key(site_config->queue_drivers, driver_name); -} - -queue_driver_type * site_config_get_queue_driver(const site_config_type * site_config, const char * driver_name) { - return hash_get(site_config->queue_drivers, driver_name); -} - -static void site_config_create_queue_drivers(site_config_type * site_config) { - site_config_add_queue_driver(site_config, LSF_DRIVER_NAME, queue_driver_alloc_LSF(NULL, NULL, NULL)); - site_config_add_queue_driver(site_config, TORQUE_DRIVER_NAME, queue_driver_alloc_TORQUE()); - site_config_add_queue_driver(site_config, RSH_DRIVER_NAME, queue_driver_alloc_RSH(NULL, NULL)); - site_config_add_queue_driver(site_config, LOCAL_DRIVER_NAME, queue_driver_alloc_local()); -} - -static void site_config_set_queue_option(site_config_type * site_config, const char * driver_name, const char * option_key, const char * option_value) { - if (site_config_has_queue_driver(site_config, driver_name)) { - queue_driver_type * driver = site_config_get_queue_driver(site_config, driver_name); - if (!queue_driver_set_option(driver, option_key, option_value)) - fprintf(stderr, "** Warning: Option:%s or its value is not recognized by driver:%s- ignored \n", option_key, driver_name); - } else - fprintf(stderr, "** Warning: Driver:%s not recognized - ignored \n", driver_name); -} - -/** - This site_config object is not really ready for prime time. - */ -site_config_type * site_config_alloc_empty() { - site_config_type * site_config = util_malloc(sizeof * site_config); - - site_config->joblist = ext_joblist_alloc(); - site_config->queue_drivers = hash_alloc(); - - site_config->lsf_queue_name_site = NULL; - site_config->lsf_request_site = NULL; - site_config->rsh_command_site = NULL; - site_config->license_root_path = NULL; - site_config->license_root_path_site = NULL; - site_config->__license_root_path = NULL; - site_config->job_script = NULL; - site_config->job_script_site = NULL; - site_config->manual_url = NULL; - site_config->default_browser = NULL; - site_config->user_mode = false; - site_config->driver_type = NULL_DRIVER; - - site_config->job_queue = job_queue_alloc(DEFAULT_MAX_SUBMIT, "OK", "STATUS", "ERROR"); - site_config->env_variables_user = hash_alloc(); - site_config->env_variables_site = hash_alloc(); - - site_config->path_variables_user = stringlist_alloc_new(); - site_config->path_values_user = stringlist_alloc_new(); - site_config->path_variables_site = hash_alloc(); - - /* Some hooops to get the current umask. */ - site_config->umask = umask(0); - site_config_set_umask(site_config, site_config->umask); - site_config_set_manual_url(site_config, DEFAULT_MANUAL_URL); - site_config_set_default_browser(site_config, DEFAULT_BROWSER); - site_config_set_max_submit(site_config, DEFAULT_MAX_SUBMIT); - site_config->search_path = false; - return site_config; -} - -const char * site_config_get_license_root_path(const site_config_type * site_config) { - return site_config->license_root_path; -} - -/** - Observe that this variable can not "really" be set to different - values during a simulation, when creating ext_job instances they - will store a pointer to this variable on creation, if the variable - is later changed they will be left with a dangling copy. That is - not particularly elegant, however it should nonetheless work. - */ - -void site_config_set_license_root_path(site_config_type * site_config, const char * license_root_path) { - util_make_path(license_root_path); - { - char * full_license_root_path = util_alloc_realpath(license_root_path); - { - /** - Appending /user/pid to the license root path. Everything - including the pid is removed when exiting (gracefully ...). - - Dangling license directories after a crash can just be removed. - */ - site_config->license_root_path = util_realloc_string_copy(site_config->license_root_path, full_license_root_path); - site_config->__license_root_path = util_realloc_sprintf(site_config->__license_root_path, "%s%c%s%c%d", full_license_root_path, UTIL_PATH_SEP_CHAR, getenv("USER"), UTIL_PATH_SEP_CHAR, getpid()); - - if (!site_config->user_mode) - site_config->license_root_path_site = util_realloc_string_copy(site_config->license_root_path_site, full_license_root_path); - } - free(full_license_root_path); - } -} - -void site_config_init_user_mode(site_config_type * site_config) { - site_config->user_mode = true; -} - -/** - Will return 0 if the job is added correctly, and a non-zero (not - documented ...) error code if the job is not added. - */ - -int site_config_install_job(site_config_type * site_config, const char * job_name, const char * install_file) { - ext_job_type * new_job = ext_job_fscanf_alloc(job_name, site_config->__license_root_path, site_config->user_mode, install_file, site_config->search_path); - if (new_job != NULL) { - ext_joblist_add_job(site_config->joblist, job_name, new_job); - return 0; - } else - return 1; /* Some undocumented error condition - the job is NOT added. */ -} - -/** - Will NOT remove shared jobs. - */ -bool site_config_del_job(site_config_type * site_config, const char * job_name) { - return ext_joblist_del_job(site_config->joblist, job_name); -} - -static void site_config_add_jobs(site_config_type * site_config, const config_content_type * config) { - if (config_content_has_item(config, INSTALL_JOB_KEY)) { - const config_content_item_type * content_item = config_content_get_item(config, INSTALL_JOB_KEY); - int num_jobs = config_content_item_get_size(content_item); - for (int job_nr = 0; job_nr < num_jobs; job_nr++) { - config_content_node_type * node = config_content_item_iget_node(content_item, job_nr); - const char * job_key = config_content_node_iget(node, 0); - const char * description_file = config_content_node_iget_as_abspath(node, 1); - - site_config_install_job(site_config, job_key, description_file); - } - } - if (config_content_has_item(config, INSTALL_JOB_DIRECTORY_KEY)) { - const config_content_item_type * content_item = config_content_get_item(config, INSTALL_JOB_DIRECTORY_KEY); - int num_dirs = config_content_item_get_size(content_item); - for (int dir_nr = 0; dir_nr < num_dirs; dir_nr++) { - config_content_node_type * node = config_content_item_iget_node(content_item, dir_nr); - const char * directory = config_content_node_iget_as_abspath(node, 0); - - ext_joblist_add_jobs_in_directory(site_config->joblist , directory, site_config->__license_root_path, site_config->user_mode, site_config->search_path ); - } - } - -} - -hash_type * site_config_get_env_hash(const site_config_type * site_config) { - return site_config->env_variables_user; -} - -/** - Will only return the user-set variables. The variables set in the - site config are hidden. - */ - -stringlist_type * site_config_get_path_variables(const site_config_type * site_config) { - return site_config->path_variables_user; -} - -stringlist_type * site_config_get_path_values(const site_config_type * site_config) { - return site_config->path_values_user; -} - -/** - Observe that the value inserted in the internal hash tables is the - interpolated value returned from util_interp_setenv(), where $VAR - expressions have been expanded. - */ - -void site_config_setenv(site_config_type * site_config, const char * variable, const char * __value) { - const char * value = util_interp_setenv(variable, __value); - - if (site_config->user_mode) { - /* In the table meant for user-export we store the literal $var strings. */ - hash_insert_hash_owned_ref(site_config->env_variables_user, variable, util_alloc_string_copy(__value), free); - - if (!hash_has_key(site_config->env_variables_site, variable)) - hash_insert_ref(site_config->env_variables_site, variable, NULL); /* We insert a NULL so we can recover a unsetenv() in _clear_env(). */ - } else - hash_insert_hash_owned_ref(site_config->env_variables_site, variable, util_alloc_string_copy(value), free); -} - -/** - Clears all the environment variables set by the user. This is done - is follows: - - 1. Iterate through the table config->env_variables_user and call - unsetenv() on all of them - - 2. Iterate through the table config->env_variables_site and call - setenv() on all of them. - - This way the environment should be identical to what it is after - the site parsing is completed. - */ - - -void site_config_clear_env(site_config_type * site_config) { - /* 1: Clearing the user_set variables. */ - { - hash_iter_type * hash_iter = hash_iter_alloc(site_config->env_variables_user); - while (!hash_iter_is_complete(hash_iter)) { - const char * var = hash_iter_get_next_key(hash_iter); - util_unsetenv(var); - } - hash_iter_free(hash_iter); - hash_clear(site_config->env_variables_user); - } - - - /* 2: Recovering the site_set variables. */ - { - hash_iter_type * hash_iter = hash_iter_alloc(site_config->env_variables_site); - while (!hash_iter_is_complete(hash_iter)) { - const char * var = hash_iter_get_next_key(hash_iter); - const char * value = hash_get(site_config->env_variables_site, var); - util_interp_setenv(var, value); /* Will call unsetenv if value == NULL */ - } - hash_iter_free(hash_iter); - } -} - -void site_config_clear_pathvar(site_config_type * site_config) { - stringlist_clear(site_config->path_variables_user); - stringlist_clear(site_config->path_values_user); - { - /* Recover the original values. */ - hash_iter_type * hash_iter = hash_iter_alloc(site_config->path_variables_site); - while (!hash_iter_is_complete(hash_iter)) { - const char * var = hash_iter_get_next_key(hash_iter); - const char * site_value = hash_get(site_config->path_variables_site, var); - - if (site_value == NULL) - util_unsetenv(var); - else - util_setenv(var, site_value); - } - } -} - -void site_config_update_pathvar(site_config_type * site_config, const char * pathvar, const char * value) { - if (site_config->user_mode) { - stringlist_append_copy(site_config->path_variables_user, pathvar); - stringlist_append_copy(site_config->path_values_user, value); - - if (!hash_has_key(site_config->path_variables_site, pathvar)) - hash_insert_ref(site_config->path_variables_site, pathvar, NULL); /* This path variable has not been touched in the - site_config. We store a NULL, so can roll back - (i.e. call unsetenv()). */ - } - util_update_path_var(pathvar, value, false); -} - -static void site_config_select_job_driver(site_config_type * site_config, const char * driver_name) { - queue_driver_type * driver = site_config_get_queue_driver(site_config, driver_name); - site_config->current_driver = driver; - job_queue_set_driver(site_config->job_queue, site_config->current_driver); -} - -/** - These functions can be called repeatedly if you should want to - change driver characteristics run-time. - */ -static void site_config_select_LOCAL_job_queue(site_config_type * site_config) { - site_config_select_job_driver(site_config, LOCAL_DRIVER_NAME); -} - -static void site_config_select_RSH_job_queue(site_config_type * site_config) { - site_config_select_job_driver(site_config, RSH_DRIVER_NAME); -} - -static void site_config_select_LSF_job_queue(site_config_type * site_config) { - site_config_select_job_driver(site_config, LSF_DRIVER_NAME); -} - -static void site_config_select_TORQUE_job_queue(site_config_type * site_config) { - site_config_select_job_driver(site_config, TORQUE_DRIVER_NAME); -} - -/*****************************************************************/ - -/*****************************************************************/ -static int site_config_get_queue_max_running_option(queue_driver_type * driver) { - const char * max_running_string = queue_driver_get_option(driver, MAX_RUNNING); - int max_running = 0; - if(!util_sscanf_int(max_running_string, &max_running)) { - fprintf(stderr, "** Warning: String:%s for max_running is not parsable as int, using 0\n", max_running_string); - } - return max_running; -} - - -static void site_config_set_queue_max_running_option(site_config_type * site_config, const char* driver_name, int max_running) { - char* max_running_string = util_alloc_sprintf("%d", max_running); - site_config_set_queue_option(site_config, driver_name, MAX_RUNNING, max_running_string); - free(max_running_string); -} - -void site_config_set_max_running_lsf(site_config_type * site_config, int max_running_lsf) { - site_config_set_queue_max_running_option(site_config, LSF_DRIVER_NAME, max_running_lsf); - if (!site_config->user_mode) - site_config->max_running_lsf_site = max_running_lsf; -} - -int site_config_get_max_running_lsf(const site_config_type * site_config) { - queue_driver_type * lsf_driver = site_config_get_queue_driver(site_config, LSF_DRIVER_NAME); - return site_config_get_queue_max_running_option(lsf_driver); -} - -void site_config_set_max_running_rsh(site_config_type * site_config, int max_running_rsh) { - site_config_set_queue_max_running_option(site_config, RSH_DRIVER_NAME, max_running_rsh); - - if (!site_config->user_mode) - site_config->max_running_rsh_site = max_running_rsh; -} - -int site_config_get_max_running_rsh(const site_config_type * site_config) { - queue_driver_type * rsh_driver = site_config_get_queue_driver(site_config, RSH_DRIVER_NAME); - return site_config_get_queue_max_running_option(rsh_driver); -} - -void site_config_set_max_running_local(site_config_type * site_config, int max_running_local) { - site_config_set_queue_max_running_option(site_config, LOCAL_DRIVER_NAME, max_running_local); - - if (!site_config->user_mode) - site_config->max_running_local_site = max_running_local; -} - -int site_config_get_max_running_local(const site_config_type * site_config) { - queue_driver_type * local_driver = site_config_get_queue_driver(site_config, LOCAL_DRIVER_NAME); - return site_config_get_queue_max_running_option(local_driver); -} - -/*****************************************************************/ - -/*****************************************************************/ - -void site_config_clear_rsh_host_list(site_config_type * site_config) { - queue_driver_type * rsh_driver = site_config_get_queue_driver(site_config, RSH_DRIVER_NAME); - queue_driver_set_option(rsh_driver, RSH_CLEAR_HOSTLIST, NULL); -} - -hash_type * site_config_get_rsh_host_list(const site_config_type * site_config) { - queue_driver_type * rsh_driver = site_config_get_queue_driver(site_config, RSH_DRIVER_NAME); - return (hash_type *) queue_driver_get_option(rsh_driver, RSH_HOSTLIST); -} - -void site_config_add_rsh_host_from_string(site_config_type * site_config, const char * host_string) { - queue_driver_type * rsh_driver = site_config_get_queue_driver(site_config, RSH_DRIVER_NAME); - queue_driver_set_option(rsh_driver, RSH_HOST, host_string); -} - -void site_config_add_rsh_host(site_config_type * site_config, const char * rsh_host, int max_running) { - char * host_max_running = util_alloc_sprintf("%s:%d", rsh_host, max_running); - site_config_add_rsh_host_from_string(site_config, host_max_running); - free(host_max_running); -} - -void site_config_set_rsh_command(site_config_type * site_config, const char * rsh_command) { - queue_driver_type * rsh_driver = site_config_get_queue_driver(site_config, RSH_DRIVER_NAME); - queue_driver_set_option(rsh_driver, RSH_CMD, rsh_command); -} - -const char * site_config_get_rsh_command(const site_config_type * site_config) { - queue_driver_type * rsh_driver = site_config_get_queue_driver(site_config, RSH_DRIVER_NAME); - return queue_driver_get_option(rsh_driver, RSH_CMD); -} - -/*****************************************************************/ - -void site_config_set_lsf_queue(site_config_type * site_config, const char * lsf_queue) { - queue_driver_type * lsf_driver = site_config_get_queue_driver(site_config, LSF_DRIVER_NAME); - if (!site_config->user_mode) - site_config->lsf_queue_name_site = util_realloc_string_copy(site_config->lsf_queue_name_site, lsf_queue); - - queue_driver_set_option(lsf_driver, LSF_QUEUE, lsf_queue); -} - -const char * site_config_get_lsf_queue(const site_config_type * site_config) { - queue_driver_type * lsf_driver = site_config_get_queue_driver(site_config, LSF_DRIVER_NAME); - return queue_driver_get_option(lsf_driver, LSF_QUEUE); -} - -void site_config_set_lsf_server(site_config_type * site_config, const char * lsf_server) { - queue_driver_type * lsf_driver = site_config_get_queue_driver(site_config, LSF_DRIVER_NAME); - queue_driver_set_option(lsf_driver, LSF_SERVER, lsf_server); -} - -void site_config_set_lsf_request(site_config_type * site_config, const char * lsf_request) { - queue_driver_type * lsf_driver = site_config_get_queue_driver(site_config, LSF_DRIVER_NAME); - queue_driver_set_option(lsf_driver, LSF_RESOURCE, lsf_request); - if (!site_config->user_mode) - site_config->lsf_request_site = util_realloc_string_copy(site_config->lsf_request_site, lsf_request); -} - -const char * site_config_get_lsf_request(const site_config_type * site_config) { - queue_driver_type * lsf_driver = site_config_get_queue_driver(site_config, LSF_DRIVER_NAME); - return queue_driver_get_option(lsf_driver, LSF_RESOURCE); -} - -/*****************************************************************/ - - -const char * site_config_get_queue_name(const site_config_type * site_config) { - return queue_driver_get_name(site_config->current_driver); -} - -static void site_config_set_job_queue__(site_config_type * site_config, job_driver_type driver_type) { - site_config->driver_type = driver_type; - if (site_config->job_queue != NULL) { - switch (driver_type) { - case(LSF_DRIVER): - site_config_select_LSF_job_queue(site_config); - break; - case(TORQUE_DRIVER): - site_config_select_TORQUE_job_queue(site_config); - break; - case(RSH_DRIVER): - site_config_select_RSH_job_queue(site_config); - break; - case(LOCAL_DRIVER): - site_config_select_LOCAL_job_queue(site_config); - break; - default: - util_abort("%s: internal error \n", __func__); - } - } - if (!site_config->user_mode) - site_config->driver_type_site = driver_type; -} - -bool site_config_queue_is_running(const site_config_type * site_config) { - return job_queue_is_running(site_config->job_queue); -} - -/** - The job_script might be a relative path, and the cwd changes during - execution, i.e. it is essential to get hold of the full path. -*/ - -bool site_config_set_job_script(site_config_type * site_config, const char * job_script) { - if (util_is_executable(job_script)) { - char * job_script_full_path = util_alloc_realpath(job_script); - { - site_config->job_script = util_realloc_string_copy(site_config->job_script, job_script_full_path); - if (!site_config->user_mode) - site_config->job_script_site = util_realloc_string_copy(site_config->job_script_site, site_config->job_script); - } - free(job_script_full_path); - return true; - } else - return false; -} - - -bool site_config_has_job_script( const site_config_type * site_config ) { - if (site_config->job_script) - return true; - else - return false; -} - - -const char * site_config_get_job_script(const site_config_type * site_config) { - return site_config->job_script; -} - -const char * site_config_get_manual_url(const site_config_type * site_config) { - return site_config->manual_url; -} - -void site_config_set_manual_url(site_config_type * site_config, const char * manual_url) { - site_config->manual_url = util_realloc_string_copy(site_config->manual_url, manual_url); -} - -const char * site_config_get_default_browser(const site_config_type * site_config) { - return site_config->default_browser; -} - -void site_config_set_default_browser(site_config_type * site_config, const char * default_browser) { - site_config->default_browser = util_realloc_string_copy(site_config->default_browser, default_browser); -} - -void site_config_set_max_submit(site_config_type * site_config, int max_submit) { - site_config->max_submit = max_submit; - if (!site_config->user_mode) - site_config->max_submit_site = max_submit; - job_queue_set_max_submit(site_config->job_queue, max_submit); -} - -int site_config_get_max_submit(const site_config_type * site_config) { - return job_queue_get_max_submit(site_config->job_queue); -} - -static void site_config_install_job_queue(site_config_type * site_config) { - /* - All the various driver options are set, unconditionally of which - driver is actually selected in the end. - */ - if (site_config->driver_type != NULL_DRIVER) - site_config_set_job_queue__(site_config, site_config->driver_type); -} - -void site_config_init_env(site_config_type * site_config, const config_content_type * config) { - { - if (config_content_has_item( config , SETENV_KEY)) { - config_content_item_type * setenv_item = config_content_get_item(config, SETENV_KEY); - int i; - for (i = 0; i < config_content_item_get_size(setenv_item); i++) { - const config_content_node_type * setenv_node = config_content_item_iget_node(setenv_item, i); - const char * var = config_content_node_iget(setenv_node, 0); - const char * value = config_content_node_iget(setenv_node, 1); - - site_config_setenv(site_config, var, value); - } - } - } - - { - if (config_content_has_item( config , UPDATE_PATH_KEY)) { - config_content_item_type * path_item = config_content_get_item(config, UPDATE_PATH_KEY); - int i; - for (i = 0; i < config_content_item_get_size(path_item); i++) { - const config_content_node_type * path_node = config_content_item_iget_node(path_item, i); - const char * path = config_content_node_iget(path_node, 0); - const char * value = config_content_node_iget(path_node, 1); - - site_config_update_pathvar(site_config, path, value); - } - } - } -} - -/** - This function will be called twice, first when the config instance - is an internalization of the site-wide configuration file, and - secondly when config is an internalisation of the user's - configuration file. The @user_config parameter will be true in the - latter case. - */ - - -bool site_config_init(site_config_type * site_config, const config_content_type * config) { - site_config_add_jobs(site_config, config); - site_config_init_env(site_config, config); - - /* - When LSF is used several enviroment variables must be set (by the - site wide file) - i.e. the calls to SETENV must come first. - */ - if (!site_config->user_mode) - site_config_create_queue_drivers(site_config); - - /* - Set the umask for all file creation. A value of '0' will ensure - that all files and directories are created with 'equal rights' - for everyone - might be handy if you are helping someone... The - default statoil value is 0022, i.e. write access is removed from - group and others. - - The string is supposed to be in OCTAL representation (without any - prefix characters). - */ - - if (config_content_has_item(config, UMASK_KEY)) { - const char * string_mask = config_content_get_value(config, UMASK_KEY); - mode_t umask_value; - if (util_sscanf_octal_int(string_mask, &umask_value)) - site_config_set_umask(site_config, umask_value); - else - util_abort("%s: failed to parse:\"%s\" as a valid octal literal \n", __func__, string_mask); - } - - if (config_content_has_item(config, MAX_SUBMIT_KEY)) - site_config_set_max_submit(site_config, config_content_get_value_as_int(config, MAX_SUBMIT_KEY)); - - - /* LSF options */ - { - if (config_content_has_item(config, LSF_QUEUE_KEY)) - site_config_set_lsf_queue(site_config, config_content_get_value(config, LSF_QUEUE_KEY)); - - if (config_content_has_item(config, LSF_RESOURCES_KEY)) { - char * lsf_resource_request = config_content_alloc_joined_string(config, LSF_RESOURCES_KEY, " "); - site_config_set_lsf_request(site_config, lsf_resource_request); - free(lsf_resource_request); - } - - if (config_content_has_item(config, MAX_RUNNING_LSF_KEY)) - site_config_set_max_running_lsf(site_config, config_content_get_value_as_int(config, MAX_RUNNING_LSF_KEY)); - - if (config_content_has_item(config, LSF_SERVER_KEY)) - site_config_set_lsf_server(site_config, config_content_get_value(config, LSF_SERVER_KEY)); - } - - - /* RSH options */ - { - if (config_content_has_item(config, RSH_COMMAND_KEY)) - site_config_set_rsh_command(site_config, config_content_get_value(config, RSH_COMMAND_KEY)); - - if (config_content_has_item(config, MAX_RUNNING_RSH_KEY)) - site_config_set_max_running_rsh(site_config, config_content_get_value_as_int(config, MAX_RUNNING_RSH_KEY)); - - /* Parsing the "host1:4" strings. */ - if (config_content_has_item( config , RSH_HOST_KEY)) { - stringlist_type * rsh_host_list = config_content_alloc_complete_stringlist(config, RSH_HOST_KEY); - int i; - for (i = 0; i < stringlist_get_size(rsh_host_list); i++) - site_config_add_rsh_host_from_string(site_config, stringlist_iget(rsh_host_list, i)); - - stringlist_free(rsh_host_list); - } - } - - - if (config_content_has_item(config, QUEUE_SYSTEM_KEY)) { - job_driver_type driver_type; - { - const char * queue_system = config_content_get_value(config, QUEUE_SYSTEM_KEY); - if (strcmp(queue_system, LSF_DRIVER_NAME) == 0) { - driver_type = LSF_DRIVER; - } else if (strcmp(queue_system, RSH_DRIVER_NAME) == 0) - driver_type = RSH_DRIVER; - else if (strcmp(queue_system, LOCAL_DRIVER_NAME) == 0) - driver_type = LOCAL_DRIVER; - else if (strcmp(queue_system, TORQUE_DRIVER_NAME) == 0) - driver_type = TORQUE_DRIVER; - else { - util_abort("%s: queue system :%s not recognized \n", __func__, queue_system); - driver_type = NULL_DRIVER; - } - } - site_config_set_job_queue__(site_config, driver_type); - } - - /* Parsing local options */ - if (config_content_has_item(config, MAX_RUNNING_LOCAL_KEY)) - site_config_set_max_running_local(site_config, config_content_iget_as_int(config, MAX_RUNNING_LOCAL_KEY, 0, 0)); - - if (config_content_has_item(config, JOB_SCRIPT_KEY)) - site_config_set_job_script(site_config, config_content_get_value_as_abspath(config, JOB_SCRIPT_KEY)); - - if (config_content_has_item(config, LICENSE_PATH_KEY)) - site_config_set_license_root_path(site_config, config_content_get_value_as_abspath(config, LICENSE_PATH_KEY)); - - site_config_install_job_queue(site_config); - - if (config_content_has_item(config, EXT_JOB_SEARCH_PATH_KEY)){ - site_config_set_ext_job_search_path(site_config, config_content_get_value_as_bool(config, EXT_JOB_SEARCH_PATH_KEY)); - } - - - /* Setting QUEUE_OPTIONS */ - { - int i; - for (i = 0; i < config_content_get_occurences(config, QUEUE_OPTION_KEY); i++) { - const stringlist_type * tokens = config_content_iget_stringlist_ref(config, QUEUE_OPTION_KEY, i); - const char * driver_name = stringlist_iget(tokens, 0); - const char * option_key = stringlist_iget(tokens, 1); - char * option_value = stringlist_alloc_joined_substring(tokens, 2, stringlist_get_size(tokens), " "); - /* - If it is desirable to keep the exact number of spaces in the - option_value it should be quoted with "" in the configuration - file. - */ - site_config_set_queue_option(site_config, driver_name, option_key, option_value); - free( option_value ); - } - } - return true; -} - -void site_config_set_ext_job_search_path(site_config_type * site_config, bool search_path){ - site_config->search_path = search_path; -} - - -void site_config_free(site_config_type * site_config) { - ext_joblist_free(site_config->joblist); - job_queue_free(site_config->job_queue); - - hash_free(site_config->queue_drivers); - - stringlist_free(site_config->path_variables_user); - stringlist_free(site_config->path_values_user); - hash_free(site_config->path_variables_site); - - hash_free(site_config->env_variables_site); - hash_free(site_config->env_variables_user); - - if (site_config->__license_root_path != NULL) - util_clear_directory(site_config->__license_root_path, true, true); - - util_safe_free(site_config->manual_url); - util_safe_free(site_config->default_browser); - util_safe_free(site_config->license_root_path); - util_safe_free(site_config->license_root_path_site); - util_safe_free(site_config->__license_root_path); - util_safe_free(site_config->job_script); - util_safe_free(site_config->job_script_site); - util_safe_free(site_config->rsh_command_site); - util_safe_free(site_config->lsf_queue_name_site); - util_safe_free(site_config->lsf_request_site); - free(site_config); -} - -ext_joblist_type * site_config_get_installed_jobs(const site_config_type * site_config) { - return site_config->joblist; -} - -job_queue_type * site_config_get_job_queue(const site_config_type * site_config) { - return site_config->job_queue; -} - -void site_config_set_ens_size(site_config_type * site_config, int ens_size) { - //job_queue_set_size( site_config->job_queue , ens_size ); -} - -/*****************************************************************/ - - -void site_config_add_queue_config_items(config_parser_type * config, bool site_mode) { - config_schema_item_type * item = config_add_schema_item(config, QUEUE_SYSTEM_KEY, site_mode); - config_schema_item_set_argc_minmax(item, 1, 1); - - item = config_add_schema_item(config, MAX_SUBMIT_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_INT); -} - -void site_config_add_config_items(config_parser_type * config, bool site_mode) { - config_schema_item_type * item; - ert_workflow_list_add_config_items(config); - site_config_add_queue_config_items(config, site_mode); - - - /* - You can set environment variables which will be applied to the - run-time environment. Can unfortunately not use constructions - like PATH=$PATH:/some/new/path, use the UPDATE_PATH function instead. - */ - item = config_add_schema_item(config, SETENV_KEY, false); - config_schema_item_set_argc_minmax(item, 2, 2); - config_schema_item_set_envvar_expansion(item, false); /* Do not expand $VAR expressions (that is done in util_interp_setenv()). */ - - item = config_add_schema_item(config, UMASK_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - - /** - UPDATE_PATH LD_LIBRARY_PATH /path/to/some/funky/lib - - Will prepend "/path/to/some/funky/lib" at the front of LD_LIBRARY_PATH. - */ - item = config_add_schema_item(config, UPDATE_PATH_KEY, false); - config_schema_item_set_argc_minmax(item, 2, 2); - config_schema_item_set_envvar_expansion(item, false); /* Do not expand $VAR expressions (that is done in util_interp_setenv()). */ - - if (!site_mode) { - item = config_add_schema_item(config, LICENSE_PATH_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_PATH); - } - - - /*****************************************************************/ - /* Items related to running jobs with lsf/rsh/local ... */ - - /* These must be set IFF QUEUE_SYSTEM == LSF */ - item = config_add_schema_item(config, LSF_QUEUE_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - - item = config_add_schema_item(config, LSF_RESOURCES_KEY, false); - config_schema_item_set_argc_minmax(item, 1, CONFIG_DEFAULT_ARG_MAX); - - item = config_add_schema_item(config, MAX_RUNNING_LSF_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_INT); - - item = config_add_schema_item(config, LSF_SERVER_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - - /* These must be set IFF QUEUE_SYSTEM == RSH */ - if (!site_mode) - config_add_schema_item(config, RSH_HOST_KEY, false); /* Only added when user parse. */ - item = config_add_schema_item(config, RSH_COMMAND_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_EXECUTABLE); - - item = config_add_schema_item(config, MAX_RUNNING_RSH_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_INT); - - /* These must be set IFF QUEUE_SYSTEM == LOCAL */ - item = config_add_schema_item(config, MAX_RUNNING_LOCAL_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_INT); - - - /*****************************************************************/ - item = config_add_schema_item(config, QUEUE_OPTION_KEY, false); - config_schema_item_set_argc_minmax(item, 3, CONFIG_DEFAULT_ARG_MAX); - - item = config_add_schema_item(config, JOB_SCRIPT_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_EXISTING_PATH); - - item = config_add_schema_item(config, INSTALL_JOB_KEY, false); - config_schema_item_set_argc_minmax(item, 2, 2); - config_schema_item_iset_type(item, 1, CONFIG_EXISTING_PATH); - - item = config_add_schema_item(config, INSTALL_JOB_DIRECTORY_KEY, false); - config_schema_item_set_argc_minmax(item, 1, 1); - config_schema_item_iset_type(item, 0, CONFIG_PATH); - - item = config_add_schema_item( config , ANALYSIS_LOAD_KEY , false ); - config_schema_item_set_argc_minmax( item , 2 , 2); -} - -const char * site_config_get_location() { - const char * site_config = NULL; - - #ifdef SITE_CONFIG_FILE - site_config = SITE_CONFIG_FILE; - #endif - - const char * env_site_config = getenv("ERT_SITE_CONFIG"); - - if(env_site_config != NULL) { - if (util_file_exists(env_site_config)) { - site_config = env_site_config; - } else { - fprintf(stderr, "The environment variable ERT_SITE_CONFIG points to non-existing file: %s - ignored\n", env_site_config); - } - } - - if (site_config == NULL) { - fprintf(stderr, "**WARNING** main enkf_config file is not set. Use environment variable \"ERT_SITE_CONFIG\" - or recompile.\n"); - } - - return site_config; -} diff --git a/ThirdParty/Ert/libenkf/src/state_map.c b/ThirdParty/Ert/libenkf/src/state_map.c deleted file mode 100644 index dbe51e7b85..0000000000 --- a/ThirdParty/Ert/libenkf/src/state_map.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - The file 'state_map.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */ -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - - -#define STATE_MAP_TYPE_ID 500672132 - -struct state_map_struct { - UTIL_TYPE_ID_DECLARATION; - int_vector_type * state; - pthread_rwlock_t rw_lock; - bool read_only; -}; - - -UTIL_IS_INSTANCE_FUNCTION( state_map , STATE_MAP_TYPE_ID ) - - -state_map_type * state_map_alloc( ) { - state_map_type * map = util_malloc( sizeof * map ); - UTIL_TYPE_ID_INIT( map , STATE_MAP_TYPE_ID ); - map->state = int_vector_alloc( 0 , STATE_UNDEFINED ); - pthread_rwlock_init( &map->rw_lock , NULL); - map->read_only = false; - return map; -} - - -state_map_type * state_map_fread_alloc( const char * filename ) { - state_map_type * map = state_map_alloc(); - if (util_file_exists( filename )) { - FILE * stream = util_fopen( filename , "r"); - int_vector_fread( map->state , stream ); - fclose( stream ); - } - return map; -} - -state_map_type * state_map_fread_alloc_readonly( const char * filename ) { - state_map_type * map = state_map_fread_alloc(filename); - map->read_only = true; - return map; -} - - -state_map_type * state_map_alloc_copy( state_map_type * map ) { - state_map_type * copy = state_map_alloc(); - pthread_rwlock_rdlock( &map->rw_lock ); - { - int_vector_memcpy( copy->state , map->state ); - } - pthread_rwlock_unlock( &map->rw_lock ); - return copy; -} - - -void state_map_free( state_map_type * map ) { - int_vector_free( map->state ); - free( map ); -} - - -int state_map_get_size( state_map_type * map) { - int size; - pthread_rwlock_rdlock( &map->rw_lock ); - { - size = int_vector_size( map->state ); - } - pthread_rwlock_unlock( &map->rw_lock ); - return size; -} - - -bool state_map_equal( state_map_type * map1 , state_map_type * map2) { - bool equal = true; - pthread_rwlock_rdlock( &map1->rw_lock ); - pthread_rwlock_rdlock( &map2->rw_lock ); - { - if (int_vector_size( map1->state) != int_vector_size( map2->state)) - equal = false; - - if (equal) - equal = int_vector_equal( map1->state , map2->state ); - } - pthread_rwlock_unlock( &map1->rw_lock ); - pthread_rwlock_unlock( &map2->rw_lock ); - return equal; -} - - -realisation_state_enum state_map_iget( state_map_type * map , int index) { - realisation_state_enum state; - pthread_rwlock_rdlock( &map->rw_lock ); - { - state = int_vector_safe_iget( map->state , index ); - } - pthread_rwlock_unlock( &map->rw_lock ); - return state; -} - -bool state_map_legal_transition( realisation_state_enum state1 , realisation_state_enum state2) { - int target_mask = 0; - - if (state1 == STATE_UNDEFINED) - target_mask = STATE_INITIALIZED | STATE_PARENT_FAILURE; - else if (state1 == STATE_INITIALIZED) - target_mask = STATE_LOAD_FAILURE | STATE_HAS_DATA | STATE_INITIALIZED | STATE_PARENT_FAILURE; - else if (state1 == STATE_HAS_DATA) - target_mask = STATE_INITIALIZED | STATE_LOAD_FAILURE | STATE_HAS_DATA | STATE_PARENT_FAILURE; - else if (state1 == STATE_LOAD_FAILURE) - target_mask = STATE_HAS_DATA | STATE_INITIALIZED | STATE_LOAD_FAILURE; - else if (state1 == STATE_PARENT_FAILURE) - target_mask = STATE_INITIALIZED | STATE_PARENT_FAILURE; - - if (state2 & target_mask) - return true; - else - return false; -} - -static void state_map_assert_writable( const state_map_type * map) { - if (map->read_only) - util_abort("%s: tried to modify read_only state_map - aborting \n",__func__); -} - -static void state_map_iset__( state_map_type * map , int index , realisation_state_enum new_state) { - realisation_state_enum current_state = int_vector_safe_iget( map->state , index ); - - if (state_map_legal_transition( current_state , new_state )) - int_vector_iset( map->state , index , new_state); - else - util_abort("%s: illegal state transition for realisation:%d %d -> %d \n" , __func__ , index , current_state , new_state ); -} - -void state_map_iset( state_map_type * map ,int index , realisation_state_enum state) { - state_map_assert_writable(map); - pthread_rwlock_wrlock( &map->rw_lock ); - { - state_map_iset__( map , index , state ); - } - pthread_rwlock_unlock( &map->rw_lock ); -} - - -void state_map_update_matching( state_map_type * map , int index , int state_mask , realisation_state_enum new_state) { - realisation_state_enum current_state = state_map_iget( map , index ); - if (current_state & state_mask) - state_map_iset( map , index , new_state ); -} - - -void state_map_update_undefined( state_map_type * map , int index , realisation_state_enum new_state) { - state_map_update_matching( map , index , STATE_UNDEFINED , new_state ); -} - - - - -void state_map_fwrite( state_map_type * map , const char * filename) { - pthread_rwlock_rdlock( &map->rw_lock ); - { - FILE * stream = util_mkdir_fopen( filename , "w"); - if (stream) { - int_vector_fwrite( map->state , stream ); - fclose( stream ); - } else - util_abort("%s: failed to open:%s for writing \n",__func__ , filename ); - } - pthread_rwlock_unlock( &map->rw_lock ); -} - - - -bool state_map_fread( state_map_type * map , const char * filename) { - bool file_exists = false; - pthread_rwlock_wrlock( &map->rw_lock ); - { - if (util_file_exists( filename )) { - FILE * stream = util_fopen( filename , "r"); - if (stream) { - int_vector_fread( map->state , stream ); - fclose( stream ); - } else - util_abort("%s: failed to open:%s for reading \n",__func__ , filename ); - file_exists = true; - } else - int_vector_reset( map->state ); - } - pthread_rwlock_unlock( &map->rw_lock ); - return file_exists; -} - - -static void state_map_select_matching__( state_map_type * map , bool_vector_type * select_target , int select_mask , bool select) { - state_map_assert_writable(map); - pthread_rwlock_rdlock( &map->rw_lock ); - { - { - const int * map_ptr = int_vector_get_ptr( map->state ); - int size = util_int_min(int_vector_size( map->state ), bool_vector_size(select_target)); - for (int i=0; i < size; i++) { - int state_value = map_ptr[i]; - if (state_value & select_mask) - bool_vector_iset( select_target , i , select); - } - } - pthread_rwlock_unlock( &map->rw_lock ); - } -} - - -void state_map_select_matching( state_map_type * map , bool_vector_type * select_target , int select_mask) { - state_map_select_matching__(map , select_target , select_mask , true ); -} - - - - void state_map_deselect_matching( state_map_type * map , bool_vector_type * select_target , int select_mask) { - state_map_select_matching__(map , select_target , select_mask , false ); -} - - -static void state_map_set_from_mask__( state_map_type * map , const bool_vector_type * mask , realisation_state_enum state, bool invert) { - const bool * mask_ptr = bool_vector_get_ptr(mask); - for (int i=0; i < bool_vector_size( mask); i++) { - if (mask_ptr[i] != invert) - state_map_iset(map , i , state); - } -} - -void state_map_set_from_inverted_mask( state_map_type * state_map , const bool_vector_type * mask , realisation_state_enum state) { - state_map_set_from_mask__(state_map , mask , state , true); -} - -void state_map_set_from_mask( state_map_type * state_map , const bool_vector_type * mask , realisation_state_enum state) { - state_map_set_from_mask__(state_map , mask , state , false); -} - -bool state_map_is_readonly(const state_map_type * state_map) { - return state_map->read_only; -} - - -int state_map_count_matching( state_map_type * state_map , int mask) { - int count = 0; - pthread_rwlock_rdlock( &state_map->rw_lock ); - { - const int * map_ptr = int_vector_get_ptr(state_map->state); - for (int i=0; i < int_vector_size( state_map->state ); i++) { - int state_value = map_ptr[i]; - if (state_value & mask) - count++; - } - } - pthread_rwlock_unlock(&state_map->rw_lock); - return count; - } - diff --git a/ThirdParty/Ert/libenkf/src/summary.c b/ThirdParty/Ert/libenkf/src/summary.c deleted file mode 100644 index 3c0cf3b6f5..0000000000 --- a/ThirdParty/Ert/libenkf/src/summary.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'summary.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/*****************************************************************/ - -#define SUMMARY_UNDEF -9999 - -struct summary_struct { - int __type_id; /* Only used for run_time checking. */ - summary_config_type * config; /* Can not be NULL - var_type is set on first load. */ - double_vector_type * data_vector; -}; - - -/*****************************************************************/ - - - -static double SUMMARY_GET_VALUE( const summary_type * summary , int report_step) { - return double_vector_iget( summary->data_vector , report_step ); -} - - -static void SUMMARY_SET_VALUE( summary_type * summary , int report_step , double value) { - double_vector_iset( summary->data_vector , report_step , value); -} - -/*****************************************************************/ - - - -void summary_clear(summary_type * summary) { - double_vector_reset( summary->data_vector ); -} - - -summary_type * summary_alloc(const summary_config_type * summary_config) { - summary_type * summary = util_malloc(sizeof *summary ); - summary->__type_id = SUMMARY; - summary->config = (summary_config_type *) summary_config; - summary->data_vector = double_vector_alloc(0 , SUMMARY_UNDEF); - return summary; -} - - - -bool summary_active_value( double value ) { - - if (value == SUMMARY_UNDEF) - return false; - - return true; -} - - -void summary_copy(const summary_type *src , summary_type * target) { - if (src->config == target->config) - double_vector_memcpy( target->data_vector , src->data_vector ); - else - util_abort("%s: do not share config objects \n",__func__); -} - - - - -void summary_read_from_buffer(summary_type * summary , buffer_type * buffer, enkf_fs_type * fs, int report_step) { - enkf_util_assert_buffer_type( buffer , SUMMARY ); - double_vector_buffer_fread( summary->data_vector , buffer ); -} - - -bool summary_write_to_buffer(const summary_type * summary , buffer_type * buffer, int report_step) { - buffer_fwrite_int( buffer , SUMMARY ); - double_vector_buffer_fwrite( summary->data_vector , buffer ); - return true; -} - - -bool summary_has_data( const summary_type * summary , int report_step) { - return (double_vector_size( summary->data_vector ) > report_step) ? true : false; -} - - -void summary_free(summary_type *summary) { - double_vector_free( summary->data_vector ); - free(summary); -} - - - - - - -void summary_serialize(const summary_type * summary , node_id_type node_id , const active_list_type * active_list , matrix_type * A , int row_offset , int column) { - double value = SUMMARY_GET_VALUE( summary , node_id.report_step ); - enkf_matrix_serialize( &value , 1 , ECL_DOUBLE_TYPE , active_list , A , row_offset , column); -} - - -void summary_deserialize(summary_type * summary , node_id_type node_id , const active_list_type * active_list , const matrix_type * A , int row_offset , int column) { - double value; - enkf_matrix_deserialize( &value , 1 , ECL_DOUBLE_TYPE , active_list , A , row_offset , column); - SUMMARY_SET_VALUE( summary , node_id.report_step , value ); -} - -int summary_length(const summary_type * summary) { - return double_vector_size(summary->data_vector); -} - -double summary_get(const summary_type * summary, int report_step) { - return SUMMARY_GET_VALUE( summary , report_step ); -} - - -bool summary_user_get(const summary_type * summary , const char * index_key , int report_step , double * value) { - if (double_vector_size( summary->data_vector ) > report_step) { - *value = double_vector_iget( summary->data_vector , report_step); - return true; - } else { - *value = -1; - return false; - } -} - - - -void summary_user_get_vector(const summary_type * summary , const char * index_key , double_vector_type * value) { - double_vector_memcpy( value , summary->data_vector); -} - - - -/** - There are three typical reasons why the node data can not be loaded: - - 1. The ecl_sum instance is equal to NULL. - 2. The ecl_sum instance does not have the report step we are asking for. - 3. The ecl_sum instance does not have the variable we are asking for. - - In the two first cases the function will return false, ultimately - signaling that the simulation has failed. In the last case we check - the required flag of the variable, and if this is set to false we - return true. This is done because this is a typical situation for - e.g. a well which has not yet opened. -*/ - -bool summary_forward_load(summary_type * summary , const char * ecl_file_name , const forward_load_context_type * load_context) { - bool loadOK = false; - double load_value; - int report_step = forward_load_context_get_load_step( load_context ); - const ecl_sum_type * ecl_sum = forward_load_context_get_ecl_sum( load_context ); - if (ecl_sum != NULL) { - const char * var_key = summary_config_get_var(summary->config); - load_fail_type load_fail_action = summary_config_get_load_fail_mode(summary->config ); - - /* Check if the ecl_sum instance has this report step. */ - if (ecl_sum_has_report_step( ecl_sum , report_step )) { - int last_report_index = ecl_sum_iget_report_end( ecl_sum , report_step ); - - if (ecl_sum_has_general_var(ecl_sum , var_key)) { - load_value = ecl_sum_get_general_var(ecl_sum , last_report_index ,var_key ); - loadOK = true; - } else { - load_value = 0; - /* - The summary object does not have this variable - probably - meaning that it is a well/group which has not yet - opened. When required == false we do not signal load - failure in this situation. - - If the user has misspelled the name, we will go through - the whole simulation without detecting that error. - */ - if (load_fail_action == LOAD_FAIL_EXIT) - loadOK = false; - else { - loadOK = true; - if (load_fail_action == LOAD_FAIL_WARN) - fprintf(stderr,"** WARNING ** Failed summary:%s does not have key:%s \n",ecl_sum_get_case( ecl_sum ) , var_key); - } - } - } else { - load_value = 0; - if (report_step == 0) - loadOK = true; - /* - We do not signal load failure if we do not have the S0000 - summary file - which does not contain any useful information - anyway. - - Hmmm - there is a "if (report_step > 0)" check in the - enkf_state_internalize_x() function as well. - */ - else { - if (load_fail_action == LOAD_FAIL_EXIT) - loadOK = false; - else { - loadOK = true; - if (load_fail_action == LOAD_FAIL_WARN) - fprintf(stderr,"** WARNING ** Failed summary:%s does not have report_step:%d \n",ecl_sum_get_case( ecl_sum ) , report_step); - } - } - } - } - - if (loadOK) - SUMMARY_SET_VALUE( summary , report_step , load_value ); - - return loadOK; -} - - - -bool summary_forward_load_vector(summary_type * summary , - const char * ecl_file_name , - const forward_load_context_type * load_context , - const int_vector_type * time_index) { - bool loadOK = false; - - const ecl_sum_type * ecl_sum = forward_load_context_get_ecl_sum( load_context ); - if (ecl_sum != NULL) { - const char * var_key = summary_config_get_var(summary->config); - load_fail_type load_fail_action = summary_config_get_load_fail_mode(summary->config ); - bool normal_load = false; - - - if (load_fail_action != LOAD_FAIL_EXIT) { - /* - The load will always ~succeed - but if we do not have the data; - we will fill the vector with zeros. - */ - - if (!ecl_sum_has_general_var(ecl_sum , var_key)) { - for (int step = 0; step < int_vector_size( time_index ); step++) { - int summary_step = int_vector_iget( time_index , step ); - if (summary_step >= 0) - double_vector_iset( summary->data_vector , summary_step , 0); - } - loadOK = true; - - if (load_fail_action == LOAD_FAIL_WARN) - fprintf(stderr,"** WARNING ** Failed summary:%s does not have key:%s \n",ecl_sum_get_case( ecl_sum ) , var_key); - } else - normal_load = true; - - } - - - if (normal_load) { - int key_index = ecl_sum_get_general_var_params_index( ecl_sum , var_key ); - - for (int store_index = 0; store_index < int_vector_size( time_index ); store_index++) { - int summary_index = int_vector_iget( time_index , store_index ); - - if (summary_index >= 0) { - if (ecl_sum_has_report_step( ecl_sum , summary_index )) { - int last_ministep_index = ecl_sum_iget_report_end( ecl_sum , summary_index ); - double_vector_iset( summary->data_vector , store_index , ecl_sum_iget(ecl_sum , last_ministep_index , key_index )); - } - } - - } - loadOK = true; - } - } - - return loadOK; -} - - - - - - - - - - -/******************************************************************/ -/* Anonumously generated functions used by the enkf_node object */ -/******************************************************************/ -UTIL_SAFE_CAST_FUNCTION(summary , SUMMARY) -UTIL_SAFE_CAST_FUNCTION_CONST(summary , SUMMARY) -VOID_ALLOC(summary) -VOID_FREE(summary) -VOID_COPY (summary) -VOID_FORWARD_LOAD(summary) -VOID_FORWARD_LOAD_VECTOR(summary) -VOID_USER_GET(summary) -VOID_USER_GET_VECTOR(summary) -VOID_WRITE_TO_BUFFER(summary) -VOID_READ_FROM_BUFFER(summary) -VOID_SERIALIZE(summary) -VOID_DESERIALIZE(summary) -VOID_CLEAR(summary) -VOID_HAS_DATA(summary) diff --git a/ThirdParty/Ert/libenkf/src/summary_config.c b/ThirdParty/Ert/libenkf/src/summary_config.c deleted file mode 100644 index 9ccc39107e..0000000000 --- a/ThirdParty/Ert/libenkf/src/summary_config.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'summary_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include - - -#define SUMMARY_CONFIG_TYPE_ID 63106 - -struct summary_config_struct { - int __type_id; - load_fail_type load_fail; - ecl_smspec_var_type var_type; /* The type of the variable - according to ecl_summary nomenclature. */ - char * var; /* This is ONE variable of summary.x format - i.e. WOPR:OP_2, RPR:4, ... */ - set_type * obs_set; /* Set of keys (which fit in enkf_obs) which are observations of this node. */ -}; - - -/*****************************************************************/ - -UTIL_IS_INSTANCE_FUNCTION(summary_config , SUMMARY_CONFIG_TYPE_ID) - -const char * summary_config_get_var(const summary_config_type * config) { - return config->var; -} - - -ecl_smspec_var_type summary_config_get_var_type(summary_config_type * config , const ecl_sum_type * ecl_sum) { - return config->var_type; -} - - -load_fail_type summary_config_get_load_fail_mode( const summary_config_type * config) { - return config->load_fail; -} - -/** - Unfortunately it is a bit problematic to set the required flag to - TRUE for well and group variables because they do not exist in the - summary results before the well has actually opened, i.e. for a - partial summary case the results will not be there, and the loader - will incorrectly(?) signal failure. -*/ - -void summary_config_set_load_fail_mode( summary_config_type * config , load_fail_type load_fail) { - if ((config->var_type == ECL_SMSPEC_WELL_VAR) || (config->var_type == ECL_SMSPEC_GROUP_VAR)) - // For well and group variables load_fail will be LOAD_FAIL_SILENT anyway. - config->load_fail = LOAD_FAIL_SILENT; - else - config->load_fail = load_fail; -} - - -/** - This can only be used to increase the load_fail strictness. -*/ - -void summary_config_update_load_fail_mode( summary_config_type * config , load_fail_type load_fail) { - if (load_fail > config->load_fail) - summary_config_set_load_fail_mode( config , load_fail ); -} - - -summary_config_type * summary_config_alloc(const char * var , load_fail_type load_fail) { - summary_config_type * config = util_malloc(sizeof *config ); - config->__type_id = SUMMARY_CONFIG_TYPE_ID; - config->var = util_alloc_string_copy( var ); - config->var_type = ecl_smspec_identify_var_type( var ); - config->obs_set = set_alloc_empty(); - summary_config_set_load_fail_mode( config , load_fail); - return config; -} - - -void summary_config_add_obs_key(summary_config_type * config, const char * obs_key) { - set_add_key(config->obs_set , obs_key); -} - - - -void summary_config_free(summary_config_type * config) { - free(config->var); - set_free(config->obs_set); - free(config); -} - - - -int summary_config_get_byte_size(const summary_config_type * config) { - return sizeof(double); -} - - -int summary_config_get_data_size( const summary_config_type * config) { - return 1; -} - - - - - - -/*****************************************************************/ -UTIL_SAFE_CAST_FUNCTION(summary_config , SUMMARY_CONFIG_TYPE_ID) -UTIL_SAFE_CAST_FUNCTION_CONST(summary_config , SUMMARY_CONFIG_TYPE_ID) -VOID_GET_DATA_SIZE(summary) -VOID_CONFIG_FREE(summary) - diff --git a/ThirdParty/Ert/libenkf/src/summary_key_matcher.c b/ThirdParty/Ert/libenkf/src/summary_key_matcher.c deleted file mode 100644 index 3e7e4dcdbf..0000000000 --- a/ThirdParty/Ert/libenkf/src/summary_key_matcher.c +++ /dev/null @@ -1,77 +0,0 @@ -#include - -#include -#include - -#include -#include -#include -#include - -#include - - - -#define SUMMARY_KEY_MATCHER_TYPE_ID 700672137 - -struct summary_key_matcher_struct { - UTIL_TYPE_ID_DECLARATION; - hash_type * key_set; -}; - - -UTIL_IS_INSTANCE_FUNCTION( summary_key_matcher , SUMMARY_KEY_MATCHER_TYPE_ID ) - - -summary_key_matcher_type * summary_key_matcher_alloc() { - summary_key_matcher_type * matcher = util_malloc(sizeof * matcher); - UTIL_TYPE_ID_INIT( matcher , SUMMARY_KEY_MATCHER_TYPE_ID); - matcher->key_set = hash_alloc(); - return matcher; -} - -void summary_key_matcher_free(summary_key_matcher_type * matcher) { - hash_free(matcher->key_set); - free(matcher); -} - -int summary_key_matcher_get_size(const summary_key_matcher_type * matcher) { - return hash_get_size( matcher->key_set ); -} - -void summary_key_matcher_add_summary_key(summary_key_matcher_type * matcher, const char * summary_key) { - if(!hash_has_key(matcher->key_set, summary_key)) { - hash_insert_int(matcher->key_set, summary_key, !util_string_has_wildcard(summary_key)); - } -} - -bool summary_key_matcher_match_summary_key(const summary_key_matcher_type * matcher, const char * summary_key) { - stringlist_type * keys = hash_alloc_stringlist(matcher->key_set); - bool has_key = false; - - for (int i = 0; i < stringlist_get_size(keys); i++) { - const char * pattern = stringlist_iget(keys, i); - if(util_fnmatch(pattern, summary_key) == 0) { - has_key = true; - break; - } - } - - stringlist_free(keys); - - return has_key; -} - -stringlist_type * summary_key_matcher_get_keys(const summary_key_matcher_type * matcher) { - return hash_alloc_stringlist(matcher->key_set); -} - -bool summary_key_matcher_summary_key_is_required(const summary_key_matcher_type * matcher, const char * summary_key) { - bool is_required = false; - - if(!util_string_has_wildcard(summary_key) && hash_has_key(matcher->key_set, summary_key)) { - is_required = (bool) hash_get_int(matcher->key_set, summary_key); - } - - return is_required; -} \ No newline at end of file diff --git a/ThirdParty/Ert/libenkf/src/summary_key_set.c b/ThirdParty/Ert/libenkf/src/summary_key_set.c deleted file mode 100644 index 97a6d4de93..0000000000 --- a/ThirdParty/Ert/libenkf/src/summary_key_set.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - The file 'state_map.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */ -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - - -#define SUMMARY_KEY_SET_TYPE_ID 700672133 - -struct summary_key_set_struct { - UTIL_TYPE_ID_DECLARATION; - hash_type * key_set; - pthread_rwlock_t rw_lock; - bool read_only; -}; - - -UTIL_IS_INSTANCE_FUNCTION( summary_key_set , SUMMARY_KEY_SET_TYPE_ID ) - - -summary_key_set_type * summary_key_set_alloc() { - summary_key_set_type * set = util_malloc(sizeof * set); - UTIL_TYPE_ID_INIT( set , SUMMARY_KEY_SET_TYPE_ID); - set->key_set = hash_alloc(); - pthread_rwlock_init( &set->rw_lock , NULL); - set->read_only = false; - return set; -} - -summary_key_set_type * summary_key_set_alloc_from_file(const char * filename, bool read_only) { - summary_key_set_type * set = summary_key_set_alloc(); - summary_key_set_fread(set, filename); - set->read_only = read_only; - return set; -} - -void summary_key_set_free(summary_key_set_type * set) { - hash_free(set->key_set); - free(set); -} - -int summary_key_set_get_size(summary_key_set_type * set) { - int size; - pthread_rwlock_rdlock( &set->rw_lock ); - { - size = hash_get_size( set->key_set ); - } - pthread_rwlock_unlock( &set->rw_lock ); - return size; -} - - -bool summary_key_set_add_summary_key(summary_key_set_type * set, const char * summary_key) { - bool writable_and_non_existent = true; - - pthread_rwlock_wrlock( &set->rw_lock); - { - - if(hash_has_key(set->key_set, summary_key)) { - writable_and_non_existent = false; - } - - if(set->read_only) { - writable_and_non_existent = false; - } - - if(writable_and_non_existent) { - hash_insert_int(set->key_set, summary_key, 1); - } - } - pthread_rwlock_unlock( &set->rw_lock ); - - return writable_and_non_existent; -} - -bool summary_key_set_has_summary_key(summary_key_set_type * set, const char * summary_key) { - bool has_key = false; - - pthread_rwlock_rdlock( &set->rw_lock ); - { - has_key = hash_has_key(set->key_set, summary_key); - } - pthread_rwlock_unlock( &set->rw_lock ); - - return has_key; -} - -stringlist_type * summary_key_set_alloc_keys(summary_key_set_type * set) { - stringlist_type * keys; - - pthread_rwlock_rdlock( &set->rw_lock ); - { - keys = hash_alloc_stringlist(set->key_set); - } - pthread_rwlock_unlock( &set->rw_lock ); - - return keys; -} - - -bool summary_key_set_is_read_only(const summary_key_set_type * set) { - return set->read_only; -} - -void summary_key_set_fwrite(summary_key_set_type * set, const char * filename) { - pthread_rwlock_rdlock( &set->rw_lock ); - { - FILE * stream = util_mkdir_fopen(filename , "w"); - if (stream) { - stringlist_type * keys = hash_alloc_stringlist(set->key_set); - stringlist_fwrite(keys, stream); - stringlist_free(keys); - fclose( stream ); - } else { - util_abort("%s: failed to open: %s for writing \n", __func__, filename); - } - } - pthread_rwlock_unlock( &set->rw_lock ); -} - -bool summary_key_set_fread(summary_key_set_type * set, const char * filename) { - bool file_exists = false; - pthread_rwlock_wrlock( &set->rw_lock ); - { - hash_clear(set->key_set); - - if (util_file_exists(filename)) { - FILE * stream = util_fopen(filename, "r"); - if (stream) { - stringlist_type * key_set = stringlist_fread_alloc(stream); - - for (int i = 0; i < stringlist_get_size(key_set); i++) { - hash_insert_int(set->key_set, stringlist_iget(key_set, i), 1); - } - stringlist_free(key_set); - fclose( stream ); - } else { - util_abort("%s: failed to open: %s for reading \n",__func__ , filename ); - } - file_exists = true; - } - } - pthread_rwlock_unlock( &set->rw_lock ); - return file_exists; -} diff --git a/ThirdParty/Ert/libenkf/src/summary_obs.c b/ThirdParty/Ert/libenkf/src/summary_obs.c deleted file mode 100644 index 933090a57a..0000000000 --- a/ThirdParty/Ert/libenkf/src/summary_obs.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'summary_obs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/** - See the overview documentation of the observation system in enkf_obs.c -*/ -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - - -#define SUMMARY_OBS_TYPE_ID 66103 -#define OBS_SIZE 1 - -struct summary_obs_struct { - UTIL_TYPE_ID_DECLARATION; - char * summary_key; /** The observation, in summary.x syntax, e.g. GOPR:FIELD. */ - char * obs_key; - - double value; /** Observation value. */ - double std; /** Standard deviation of observation. */ - double std_scaling; - - auto_corrf_ftype * auto_corrf; - double auto_corrf_param; -}; - - - -static double auto_corrf_exp( double tlag , double param ) { - return exp(-fabs(tlag) / param ); -} - -static double auto_corrf_gauss( double tlag , double param ) { - double x = tlag / param; - return exp(-0.5 * x * x); -} - - - -static auto_corrf_ftype * summary_obs_lookup_auto_corrf( const char * fname ) { - if (fname == NULL) - return NULL; - else { - if (strcmp( fname , AUTO_CORRF_EXP) == 0) - return auto_corrf_exp; - else if (strcmp( fname , AUTO_CORRF_GAUSS) == 0) - return auto_corrf_gauss; - else { - util_abort("%s: correlation function:%s not recognized \n",__func__ , fname); - return NULL; /* Compiler shut up. */ - } - } -} - - - - -/** - This function allocates a summary_obs instance. The summary_key - string should be of the format used by the summary.x program. - E.g., WOPR:P4 would condition on WOPR in well P4. - - Observe that this format is currently *not* checked before the actual - observation time. - - TODO - Should check summary_key on alloc. -*/ -summary_obs_type * summary_obs_alloc(const char * summary_key, - const char * obs_key , - double value , - double std , - const char * auto_corrf_name , - double auto_corrf_param) { - - summary_obs_type * obs = util_malloc(sizeof * obs ); - UTIL_TYPE_ID_INIT( obs , SUMMARY_OBS_TYPE_ID ) - - obs->summary_key = util_alloc_string_copy( summary_key ); - obs->obs_key = util_alloc_string_copy( obs_key ); - obs->value = value; - obs->std = std; - obs->std_scaling = 1.0; - obs->auto_corrf = summary_obs_lookup_auto_corrf( auto_corrf_name ); - obs->auto_corrf_param = auto_corrf_param; - - return obs; -} - - -static UTIL_SAFE_CAST_FUNCTION_CONST(summary_obs , SUMMARY_OBS_TYPE_ID); -static UTIL_SAFE_CAST_FUNCTION(summary_obs , SUMMARY_OBS_TYPE_ID); -UTIL_IS_INSTANCE_FUNCTION(summary_obs , SUMMARY_OBS_TYPE_ID); - - -void summary_obs_free(summary_obs_type * summary_obs) { - free(summary_obs->summary_key); - free(summary_obs->obs_key); - free(summary_obs); -} - - - - - -auto_corrf_ftype * summary_obs_get_auto_corrf( const summary_obs_type * summary_obs ) { - return summary_obs->auto_corrf; -} - -double summary_obs_get_auto_corrf_param( const summary_obs_type * summary_obs ) { - return summary_obs->auto_corrf_param; -} - - - - - -const char * summary_obs_get_summary_key(const summary_obs_type * summary_obs) -{ - return summary_obs->summary_key; -} - - -/** - Hardcodes an assumption that the size of summary data|observations - is always one; i.e. PARTLY_ACTIVE and ALL_ACTIVE are treated in the - same manner. -*/ -void summary_obs_get_observations(const summary_obs_type * summary_obs, - obs_data_type * obs_data, - enkf_fs_type * fs, - int report_step , - const active_list_type * __active_list) { - - int active_size = active_list_get_active_size( __active_list , OBS_SIZE ); - if (active_size == 1) { - obs_block_type * obs_block = obs_data_add_block( obs_data , summary_obs->obs_key , OBS_SIZE , NULL , false); - obs_block_iset( obs_block , 0 , summary_obs->value , summary_obs->std * summary_obs->std_scaling); - } -} - - - -void summary_obs_measure(const summary_obs_type * obs, const summary_type * summary, node_id_type node_id , meas_data_type * meas_data , const active_list_type * __active_list) { - int active_size = active_list_get_active_size( __active_list , OBS_SIZE ); - if (active_size == 1) { - meas_block_type * meas_block = meas_data_add_block( meas_data , obs->obs_key , node_id.report_step , active_size ); - meas_block_iset( meas_block , node_id.iens , 0 , summary_get(summary, node_id.report_step )); - } -} - - - -double summary_obs_chi2(const summary_obs_type * obs, - const summary_type * summary, - node_id_type node_id) { - double x = (summary_get(summary , node_id.report_step) - obs->value) / obs->std; - return x*x; -} - - - -void summary_obs_user_get(const summary_obs_type * summary_obs , const char * index_key , double * value , double * std, bool * valid) { - *valid = true; - *value = summary_obs->value; - *std = summary_obs->std; -} - - - -double summary_obs_get_value( const summary_obs_type * summary_obs ) { - return summary_obs->value; -} - -double summary_obs_get_std( const summary_obs_type * summary_obs ) { - return summary_obs->std; -} - -double summary_obs_get_std_scaling( const summary_obs_type * summary_obs ) { - return summary_obs->std_scaling; -} - - -void summary_obs_update_std_scale(summary_obs_type * summary_obs, double std_multiplier , const active_list_type * active_list) { - if (active_list_get_mode( active_list ) == ALL_ACTIVE) - summary_obs->std_scaling = std_multiplier; - else { - int size = active_list_get_active_size( active_list , OBS_SIZE ); - if (size > 0) - summary_obs->std_scaling = std_multiplier; - } -} - - -/*****************************************************************/ - -VOID_FREE(summary_obs) -VOID_GET_OBS(summary_obs) -VOID_USER_GET_OBS(summary_obs) -VOID_MEASURE(summary_obs , summary) -VOID_CHI2(summary_obs , summary) -VOID_UPDATE_STD_SCALE(summary_obs); diff --git a/ThirdParty/Ert/libenkf/src/surface.c b/ThirdParty/Ert/libenkf/src/surface.c deleted file mode 100644 index 38b225a4e0..0000000000 --- a/ThirdParty/Ert/libenkf/src/surface.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'surface.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - - -/*****************************************************************/ - - -struct surface_struct { - int __type_id; /* Only used for run_time checking. */ - surface_config_type * config; /* Can not be NULL - var_type is set on first load. */ - double * data; /* Size is always one - but what the fuck ... */ -}; - - - - -void surface_clear(surface_type * surface) { - const int data_size = surface_config_get_data_size( surface->config ); - for (int k=0; k < data_size; k++) - surface->data[k] = 0; -} - -bool surface_fload( surface_type * surface , const char * filename ) { - bool ret = false; - if (filename) { - const geo_surface_type * base_surface = surface_config_get_base_surface( surface->config ); - ret = geo_surface_fload_irap_zcoord( base_surface , filename , surface->data ); - } - return ret; -} - - - -bool surface_initialize(surface_type *surface , int iens , const char * filename , rng_type * rng) { - return surface_fload(surface , filename ); -} - - -surface_type * surface_alloc(const surface_config_type * surface_config) { - surface_type * surface = util_malloc(sizeof *surface); - surface->__type_id = SURFACE; - surface->config = (surface_config_type *) surface_config; - { - const int data_size = surface_config_get_data_size( surface_config ); - surface->data = util_calloc( data_size , sizeof * surface->data ); - } - return surface; -} - - - - -void surface_copy(const surface_type *src , surface_type * target) { - if (src->config == target->config) { - const int data_size = surface_config_get_data_size( src->config ); - for (int k=0; k < data_size; k++) - target->data[k] = src->data[k]; - } else - util_abort("%s: do not share config objects \n",__func__); -} - - - - -void surface_read_from_buffer(surface_type * surface , buffer_type * buffer, enkf_fs_type * fs, int report_step) { - int size = surface_config_get_data_size( surface->config ); - enkf_util_assert_buffer_type( buffer , SURFACE ); - buffer_fread( buffer , surface->data , sizeof * surface->data , size); -} - - - - - - -bool surface_write_to_buffer(const surface_type * surface , buffer_type * buffer, int report_step) { - int size = surface_config_get_data_size( surface->config ); - buffer_fwrite_int( buffer , SURFACE ); - buffer_fwrite( buffer , surface->data , sizeof * surface->data , size); - return true; -} - - -void surface_free(surface_type *surface) { - free(surface->data); - free(surface); -} - - - - -void surface_serialize(const surface_type * surface , node_id_type node_id , const active_list_type * active_list , matrix_type * A , int row_offset , int column) { - const surface_config_type *config = surface->config; - const int data_size = surface_config_get_data_size(config ); - - enkf_matrix_serialize( surface->data , data_size , ECL_DOUBLE_TYPE , active_list , A , row_offset , column); -} - - - -void surface_deserialize(surface_type * surface , node_id_type node_id , const active_list_type * active_list , const matrix_type * A , int row_offset , int column) { - const surface_config_type *config = surface->config; - const int data_size = surface_config_get_data_size(config ); - - enkf_matrix_deserialize( surface->data , data_size , ECL_DOUBLE_TYPE , active_list , A , row_offset , column); -} - - -void surface_ecl_write(const surface_type * surface , const char * run_path , const char * base_file , void * filestream) { - char * target_file = util_alloc_filename( run_path , base_file , NULL); - surface_config_ecl_write( surface->config , target_file , surface->data ); - free( target_file ); -} - - -bool surface_user_get(const surface_type * surface , const char * index_key , int report_step , double * value) { - const int data_size = surface_config_get_data_size( surface->config ); - int index; - - *value = 0.0; - - if (util_sscanf_int( index_key , &index)) - if ((index >= 0) && (index < data_size)) { - *value = surface->data[index]; - return true; - } - - // Not valid - return false; -} - - - -void surface_set_inflation(surface_type * inflation , const surface_type * std , const surface_type * min_std) { - int size = 1; - for (int i = 0; i < size; i++) - inflation->data[i] = util_double_max( 1.0 , min_std->data[i] / std->data[i]); -} - - -void surface_iadd( surface_type * surface , const surface_type * delta) { - int size = 1; - for (int i = 0; i < size; i++) - surface->data[i] += delta->data[i]; -} - - -void surface_iaddsqr( surface_type * surface , const surface_type * delta) { - int size = 1; - for (int i = 0; i < size; i++) - surface->data[i] += delta->data[i] * delta->data[i]; -} - - -void surface_imul( surface_type * surface , const surface_type * delta) { - int size = 1; - for (int i = 0; i < size; i++) - surface->data[i] *= delta->data[i]; -} - -void surface_scale( surface_type * surface , double scale_factor) { - int size = 1; - for (int i = 0; i < size; i++) - surface->data[i] *= scale_factor; -} - -void surface_isqrt( surface_type * surface ) { - int size = 1; - for (int i = 0; i < size; i++) - surface->data[i] = sqrt( surface->data[i] ); -} - - - - - -/******************************************************************/ -/* Anonumously generated functions used by the enkf_node object */ -/******************************************************************/ -UTIL_SAFE_CAST_FUNCTION(surface , SURFACE) -UTIL_SAFE_CAST_FUNCTION_CONST(surface , SURFACE) -VOID_ALLOC(surface) -VOID_FREE(surface) -VOID_ECL_WRITE(surface) -VOID_COPY(surface) -VOID_USER_GET(surface) -VOID_WRITE_TO_BUFFER(surface) -VOID_READ_FROM_BUFFER(surface) -VOID_SERIALIZE(surface) -VOID_DESERIALIZE(surface) -VOID_INITIALIZE(surface) -VOID_SET_INFLATION(surface) -VOID_CLEAR(surface) -VOID_IADD(surface) -VOID_SCALE(surface) -VOID_IMUL(surface) -VOID_IADDSQR(surface) -VOID_ISQRT(surface) -VOID_FLOAD(surface) diff --git a/ThirdParty/Ert/libenkf/src/surface_config.c b/ThirdParty/Ert/libenkf/src/surface_config.c deleted file mode 100644 index 0d494f056a..0000000000 --- a/ThirdParty/Ert/libenkf/src/surface_config.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'surface_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include - -#include - -#include -#include -#include - -#define SURFACE_CONFIG_TYPE_ID 853317 - -struct surface_config_struct { - UTIL_TYPE_ID_DECLARATION; - geo_surface_type * base_surface; -}; - - - -surface_config_type * surface_config_alloc_empty( ) { - surface_config_type * config = util_malloc( sizeof * config ); - UTIL_TYPE_ID_INIT( config , SURFACE_CONFIG_TYPE_ID ); - config->base_surface = NULL; - return config; -} - - - -void surface_config_free( surface_config_type * config ) { - if (config->base_surface != NULL) - geo_surface_free( config->base_surface ); - - free( config ); -} - - -void surface_config_set_base_surface( surface_config_type * config , const char * base_surface ) { - if (config->base_surface != NULL) - geo_surface_free( config->base_surface ); - config->base_surface = geo_surface_fload_alloc_irap( base_surface , false ); -} - - -const geo_surface_type * surface_config_get_base_surface( const surface_config_type * config ) { - return config->base_surface; -} - - -int surface_config_get_data_size( const surface_config_type * config ) { - return geo_surface_get_size( config->base_surface ); -} - -void surface_config_ecl_write( const surface_config_type * config , const char * filename , const double * zcoord) { - geo_surface_fprintf_irap_external_zcoord( config->base_surface , filename , zcoord ); -} - - -/*****************************************************************/ -UTIL_SAFE_CAST_FUNCTION(surface_config , SURFACE_CONFIG_TYPE_ID) -UTIL_SAFE_CAST_FUNCTION_CONST(surface_config , SURFACE_CONFIG_TYPE_ID) -VOID_GET_DATA_SIZE(surface) -VOID_CONFIG_FREE(surface) - - diff --git a/ThirdParty/Ert/libenkf/src/test.c b/ThirdParty/Ert/libenkf/src/test.c deleted file mode 100644 index bf1d8fd9c8..0000000000 --- a/ThirdParty/Ert/libenkf/src/test.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -int main(void) { -} - - - diff --git a/ThirdParty/Ert/libenkf/src/time_map.c b/ThirdParty/Ert/libenkf/src/time_map.c deleted file mode 100644 index 4c7e37fdaf..0000000000 --- a/ThirdParty/Ert/libenkf/src/time_map.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - The file 'time_map.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */ -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -#define DEFAULT_TIME -1 - -static time_t time_map_iget__( const time_map_type * map , int step ); -static void time_map_update_abort( time_map_type * map , int step , time_t time); -static void time_map_summary_update_abort( time_map_type * map , const ecl_sum_type * ecl_sum); - -#define TIME_MAP_TYPE_ID 7751432 -struct time_map_struct { - UTIL_TYPE_ID_DECLARATION; - time_t_vector_type * map; - pthread_rwlock_t rw_lock; - bool modified; - bool read_only; - bool strict; - const ecl_sum_type * refcase; -}; - - -UTIL_SAFE_CAST_FUNCTION( time_map , TIME_MAP_TYPE_ID ) -UTIL_IS_INSTANCE_FUNCTION( time_map , TIME_MAP_TYPE_ID ) - - -time_map_type * time_map_alloc( ) { - time_map_type * map = util_malloc( sizeof * map ); - UTIL_TYPE_ID_INIT( map , TIME_MAP_TYPE_ID ); - - map->map = time_t_vector_alloc(0 , DEFAULT_TIME ); - map->modified = false; - map->read_only = false; - map->strict = true; - map->refcase = NULL; - pthread_rwlock_init( &map->rw_lock , NULL); - return map; -} - -bool time_map_is_strict( const time_map_type * time_map ){ - return time_map->strict; -} - -/** - The refcase will only be attached if it is consistent with the - current time map; we will accept attaching a refcase which is - shorter than the current case. -*/ -bool time_map_attach_refcase( time_map_type * time_map , const ecl_sum_type * refcase) { - bool attach_ok = true; - pthread_rwlock_rdlock( &time_map->rw_lock ); - - { - int step; - int max_step = util_int_min( time_map_get_size(time_map) , ecl_sum_get_last_report_step( refcase ) + 1); - - for (step = 0; step < max_step; step++) { - time_t current_time = time_map_iget__( time_map , step ); - time_t sim_time = ecl_sum_get_report_time( refcase , step ); - - if (current_time != sim_time) { - attach_ok = false; - break; - } - } - - if (attach_ok) - time_map->refcase = refcase; - } - pthread_rwlock_unlock( &time_map->rw_lock ); - - return attach_ok; -} - -bool time_map_has_refcase( const time_map_type * time_map ) { - if (time_map->refcase) - return true; - else - return false; -} - - -void time_map_set_strict( time_map_type * time_map , bool strict) { - time_map->strict = strict; -} - - -time_map_type * time_map_fread_alloc_readonly( const char * filename) { - time_map_type * tm = time_map_alloc(); - - if (util_file_exists(filename)) - time_map_fread( tm , filename ); - tm->read_only = true; - - return tm; -} - - -bool time_map_fscanf(time_map_type * map , const char * filename) { - bool fscanf_ok = true; - if (util_is_file( filename )) { - time_t_vector_type * time_vector = time_t_vector_alloc(0,0); - - { - FILE * stream = util_fopen(filename , "r"); - time_t last_date = 0; - while (true) { - char date_string[128]; - if (fscanf(stream , "%s" , date_string) == 1) { - time_t date; - if (util_sscanf_date_utc(date_string , &date)) { - if (date > last_date) - time_t_vector_append( time_vector , date ); - else { - fprintf(stderr,"** ERROR: The dates in %s must be in stricly increasing order\n",filename); - fscanf_ok = false; - break; - } - } else { - fprintf(stderr,"** ERROR: The string \'%s\' was not correctly parsed as a date (format: DD/MM/YYYY) ",date_string); - fscanf_ok = false; - break; - } - last_date = date; - } else - break; - } - fclose( stream ); - - if (fscanf_ok) { - int i; - time_map_clear( map ); - for (i=0; i < time_t_vector_size( time_vector ); i++) - time_map_update( map , i , time_t_vector_iget( time_vector , i )); - } - - } - time_t_vector_free( time_vector ); - } else - fscanf_ok = false; - - return fscanf_ok; -} - - -bool time_map_equal( const time_map_type * map1 , const time_map_type * map2) { - return time_t_vector_equal( map1->map , map2->map ); -} - - -void time_map_free( time_map_type * map ) { - time_t_vector_free( map->map ); - free( map ); -} - - -bool time_map_is_readonly( const time_map_type * tm) { - return tm->read_only; -} - - - -/** - Must hold the write lock. When a refcase is supplied we gurantee - that all values written into the map agree with the refcase - values. However the time map is not preinitialized with the refcase - values. -*/ - -static bool time_map_update__( time_map_type * map , int step , time_t update_time) { - bool updateOK = true; - time_t current_time = time_t_vector_safe_iget( map->map , step); - - if (current_time == DEFAULT_TIME) { - if (map->refcase) { - if (step <= ecl_sum_get_last_report_step( map->refcase )) { - time_t ref_time = ecl_sum_get_report_time( map->refcase , step ); - - if (ref_time != update_time) { - updateOK = false; - ert_log_add_message( 1 , NULL , "Tried to load data where report step/data is incompatible with refcase - ignored" , false); - } - } - } - } else if (current_time != update_time) - updateOK = false; - - - if (updateOK) { - map->modified = true; - time_t_vector_iset( map->map , step , update_time ); - } - - return updateOK; -} - - -static bool time_map_summary_update__( time_map_type * map , const ecl_sum_type * ecl_sum) { - bool updateOK = true; - int first_step = ecl_sum_get_first_report_step( ecl_sum ); - int last_step = ecl_sum_get_last_report_step( ecl_sum ); - int step; - - for (step = first_step; step <= last_step; step++) { - if (ecl_sum_has_report_step(ecl_sum , step)) { - time_t sim_time = ecl_sum_get_report_time( ecl_sum , step ); - - updateOK = (updateOK && time_map_update__( map , step , sim_time )); - } - } - - updateOK = (updateOK && time_map_update__(map , 0 , ecl_sum_get_start_time( ecl_sum ))); - return updateOK; -} - - -static time_t time_map_iget__( const time_map_type * map , int step ) { - return time_t_vector_safe_iget( map->map , step ); -} - - -/*****************************************************************/ - -double time_map_iget_sim_days( time_map_type * map , int step ) { - double days; - - pthread_rwlock_rdlock( &map->rw_lock ); - { - time_t start_time = time_map_iget__( map , 0 ); - time_t sim_time = time_map_iget__( map , step ); - - if (sim_time >= start_time) - days = 1.0 * (sim_time - start_time) / (3600 * 24); - else - days = -1; - } - pthread_rwlock_unlock( &map->rw_lock ); - - return days; -} - - -time_t time_map_iget( time_map_type * map , int step ) { - time_t t; - - pthread_rwlock_rdlock( &map->rw_lock ); - t = time_map_iget__( map , step ); - pthread_rwlock_unlock( &map->rw_lock ); - - return t; -} - -static void time_map_assert_writable( const time_map_type * map) { - if (map->read_only) - util_abort("%s: attempt to modify read-only time-map. \n",__func__); -} - - -/** - Observe that the locking is opposite of the function name; i.e. - the time_map_fwrite() function reads the time_map and takes the - read lock, whereas the time_map_fread() function takes the write - lock. -*/ - -void time_map_fwrite( time_map_type * map , const char * filename ) { - pthread_rwlock_rdlock( &map->rw_lock ); - { - if (map->modified) { - FILE * stream = util_mkdir_fopen(filename , "w"); - time_t_vector_fwrite( map->map , stream ); - fclose( stream ); - } - map->modified = false; - } - pthread_rwlock_unlock( &map->rw_lock ); -} - - -void time_map_fread( time_map_type * map , const char * filename) { - time_map_assert_writable( map ); - pthread_rwlock_wrlock( &map->rw_lock ); - { - if (util_file_exists( filename )) { - FILE * stream = util_fopen( filename , "r"); - time_t_vector_type * file_map = time_t_vector_fread_alloc( stream ); - - for (int step=0; step < time_t_vector_size( file_map ); step++) - time_map_update__( map , step , time_t_vector_iget( file_map , step )); - - time_t_vector_free( file_map ); - fclose( stream ); - } - } - pthread_rwlock_unlock( &map->rw_lock ); - time_map_get_last_step( map ); - map->modified = false; -} - - - - - -/* - Observe that the return value from this function is an inclusive - value; i.e. it should be permissible to ask for results at this report - step. -*/ - -int time_map_get_last_step( time_map_type * map) { - int last_step; - - pthread_rwlock_rdlock( &map->rw_lock ); - last_step = time_t_vector_size( map->map ) - 1; - pthread_rwlock_unlock( &map->rw_lock ); - - return last_step; -} - -int time_map_get_size( time_map_type * map) { - return time_map_get_last_step( map ) + 1; -} - -time_t time_map_get_start_time( time_map_type * map) { - return time_map_iget( map , 0 ); -} - - -time_t time_map_get_end_time( time_map_type * map) { - int last_step = time_map_get_last_step( map ); - return time_map_iget( map , last_step ); -} - -double time_map_get_end_days( time_map_type * map) { - int last_step = time_map_get_last_step( map ); - return time_map_iget_sim_days( map , last_step ); -} - -/*****************************************************************/ - - -bool time_map_update( time_map_type * map , int step , time_t time) { - bool updateOK = time_map_try_update( map , step , time ); - if (!updateOK) { - if (map->strict) - time_map_update_abort(map , step , time); - else - ert_log_add_message(1 , NULL , "Report step/true time inconsistency - data will be ignored" , false); - } - return updateOK; -} - - -bool time_map_try_update( time_map_type * map , int step , time_t time) { - bool updateOK; - time_map_assert_writable( map ); - pthread_rwlock_wrlock( &map->rw_lock ); - { - updateOK = time_map_update__( map , step , time ); - } - pthread_rwlock_unlock( &map->rw_lock ); - return updateOK; -} - - - -bool time_map_summary_update( time_map_type * map , const ecl_sum_type * ecl_sum) { - bool updateOK = time_map_try_summary_update( map , ecl_sum ); - - if (!updateOK) { - if (map->strict) - time_map_summary_update_abort( map , ecl_sum ); - else - ert_log_add_message(1 , NULL , "Report step/true time inconsistency - data will be ignored" , false); - } - - return updateOK; -} - - -bool time_map_try_summary_update( time_map_type * map , const ecl_sum_type * ecl_sum) { - bool updateOK; - - time_map_assert_writable( map ); - pthread_rwlock_wrlock( &map->rw_lock ); - { - updateOK = time_map_summary_update__( map , ecl_sum ); - } - pthread_rwlock_unlock( &map->rw_lock ); - - return updateOK; -} - - -int time_map_lookup_time( time_map_type * map , time_t time) { - int index = -1; - pthread_rwlock_rdlock( &map->rw_lock ); - { - int current_index = 0; - while (true) { - if (current_index >= time_t_vector_size( map->map )) - break; - - if (time_map_iget__( map , current_index ) == time) { - index = current_index; - break; - } - - current_index++; - } - } - pthread_rwlock_unlock( &map->rw_lock ); - return index; -} - -static bool time_map_valid_time__(const time_map_type * map , time_t time) { - if (time_t_vector_size( map->map ) > 0) { - if ((time >= time_map_iget__(map , 0)) && - (time <= time_map_iget__(map , time_t_vector_size( map->map ) - 1))) - return true; - else - return false; - } else - return false; -} - - - -int time_map_lookup_time_with_tolerance( time_map_type * map , time_t time , int seconds_before_tolerance, int seconds_after_tolerance) { - int nearest_index = -1; - pthread_rwlock_rdlock( &map->rw_lock ); - { - if (time_map_valid_time__( map , time )) { - time_t nearest_diff = 999999999999; - int current_index = 0; - while (true) { - time_t diff = time - time_map_iget__( map , current_index ); - if (diff == 0) { - nearest_index = current_index; - break; - } - - if (abs(diff) < nearest_diff) { - bool inside_tolerance = true; - if (seconds_after_tolerance >= 0) { - if (diff >= seconds_after_tolerance) - inside_tolerance = false; - } - - if (seconds_before_tolerance >= 0) { - if (diff <= -seconds_before_tolerance) - inside_tolerance = false; - } - - if (inside_tolerance) { - nearest_diff = diff; - nearest_index = current_index; - } - } - - current_index++; - - if (current_index >= time_t_vector_size( map->map )) - break; - } - } - } - pthread_rwlock_unlock( &map->rw_lock ); - return nearest_index; -} - - - -int time_map_lookup_days( time_map_type * map , double sim_days) { - int index = -1; - pthread_rwlock_rdlock( &map->rw_lock ); - { - if (time_t_vector_size( map->map ) > 0) { - time_t time = time_map_iget__(map , 0 ); - util_inplace_forward_days_utc( &time , sim_days ); - index = time_map_lookup_time( map , time ); - } - } - pthread_rwlock_unlock( &map->rw_lock ); - return index; -} - - -void time_map_clear( time_map_type * map ) { - time_map_assert_writable( map ); - pthread_rwlock_wrlock( &map->rw_lock ); - { - time_t_vector_reset( map->map ); - map->modified = true; - } - pthread_rwlock_unlock( &map->rw_lock ); -} - - -/* - This is a function specifically written to upgrade an on-disk - time_map which is using localtime (fs_version <= 106) to a utc based - time_map (fs_version >= 107). -*/ - -void time_map_summary_upgrade107( time_map_type * map , const ecl_sum_type * ecl_sum) { - int first_step = ecl_sum_get_first_report_step( ecl_sum ); - int last_step = ecl_sum_get_last_report_step( ecl_sum ); - - time_t_vector_resize( map->map , last_step + 1); - time_t_vector_iset_block( map->map , 0 , first_step , DEFAULT_TIME); - for (int step=first_step; step <= last_step; step++) { - if (ecl_sum_has_report_step(ecl_sum , step)) { - time_t sim_time = ecl_sum_get_report_time( ecl_sum , step ); - time_t_vector_iset( map->map , step , sim_time); - } - } - map->modified = true; -} - - -/*****************************************************************/ - -static void time_map_update_abort( time_map_type * map , int step , time_t time) { - time_t current_time = time_map_iget__( map , step ); - int current[3]; - int new[3]; - - util_set_date_values_utc( current_time , ¤t[0] , ¤t[1] , ¤t[2]); - util_set_date_values_utc( time , &new[0] , &new[1] , &new[2]); - - util_abort("%s: time mismatch for step:%d New: %02d/%02d/%04d existing: %02d/%02d/%04d \n",__func__ , step , - new[0] , new[1] , new[2] , - current[0] , current[1] , current[2]); -} - - -static void time_map_summary_update_abort( time_map_type * map , const ecl_sum_type * ecl_sum) { - /* - If the normal summary update fails we just play through all - time steps to pinpoint exactly the step where the update fails. - */ - - int first_step = ecl_sum_get_first_report_step( ecl_sum ); - int last_step = ecl_sum_get_last_report_step( ecl_sum ); - int step; - - for (step = first_step; step <= last_step; step++) { - if (ecl_sum_has_report_step(ecl_sum , step)) { - time_t time = ecl_sum_get_report_time( ecl_sum , step ); - - if (map->refcase) { - if (ecl_sum_get_last_report_step( ecl_sum ) >= step) { - time_t ref_time = ecl_sum_get_report_time( map->refcase , step ); - if (ref_time != time) { - int ref[3]; - int new[3]; - - util_set_date_values_utc( time , &new[0] , &new[1] , &new[2]); - util_set_date_values_utc( ref_time , &ref[0] , &ref[1] , &ref[2]); - - fprintf(stderr," Time mismatch for step:%d New: %02d/%02d/%04d refcase: %02d/%02d/%04d \n", step , - new[0] , new[1] , new[2] , - ref[0] , ref[1] , ref[2]); - } - } - } - - { - time_t current_time = time_map_iget__( map , step ); - int current[3]; - int new[3]; - - util_set_date_values_utc( current_time , ¤t[0] , ¤t[1] , ¤t[2]); - util_set_date_values_utc( time , &new[0] , &new[1] , &new[2]); - - fprintf(stderr,"Time mismatch for step:%d New: %02d/%02d/%04d existing: %02d/%02d/%04d \n",step , - new[0] , new[1] , new[2] , - current[0] , current[1] , current[2]); - } - } - } - - util_abort("%s: inconsistency when updating time map \n",__func__); -} - - - -/*****************************************************************/ - - -/* - This function creates an integer index mapping from the time map - into the summary case. In general the time <-> report step mapping - of the summary data should coincide exactly with the one maintained - in the time_map, however we allow extra timesteps in the summary - instance. The extra timesteps will be ignored, holes in the summary - timestep is not allowed - that will lead to a hard crash. - - time map Summary - ------------------------------------------------- - 0: 01/01/2000 <------- 0: 01/01/2000 - - 1: 01/02/2000 <------- 1: 01/02/2000 - - 2: 01/03/2000 <-\ 2: 02/02/2000 (Ignored) - \ - \-- 3: 01/03/2000 - - 3: 01/04/2000 <------- 4: 01/04/2000 - - - index_map = { 0 , 1 , 3 , 4 } - - Observe that the time_map_update_summary() must be called prior to - calling this function, to ensure that the time_map is sufficiently - long. If timesteps are missing from the summary case we crash hard: - - - time map Summary - ------------------------------------------------- - 0: 01/01/2000 <------- 0: 01/01/2000 - - 1: 01/02/2000 <------- 1: 01/02/2000 - - 2: 01/03/2000 ## ERROR -> util_abort() - - 3: 01/04/2000 <------- 2: 01/04/2000 - -*/ - - - -int_vector_type * time_map_alloc_index_map( time_map_type * map , const ecl_sum_type * ecl_sum ) { - int_vector_type * index_map = int_vector_alloc(0 , -1 ); - pthread_rwlock_rdlock( &map->rw_lock ); - { - int time_map_index = 0; - int sum_index = 0; - - while (true) { - time_t map_time = time_map_iget__( map , time_map_index); - if (map_time == DEFAULT_TIME) - break; - - { - time_t sum_time; - - while (true) { - sum_time = ecl_sum_get_report_time( ecl_sum , sum_index ); - - if (sum_time > map_time) { - int day,month,year; - util_set_date_values_utc( map_time , &day , &month , &year); - util_abort("%s: The eclipse summary cases is missing data for date:%02d/%02d/%4d - aborting\n", __func__ , day , month , year); - } else if (sum_time < map_time) { - sum_index++; - if (sum_index > ecl_sum_get_last_report_step( ecl_sum )) - break; - } else - break; - - } - - if (sum_time == map_time) - int_vector_iset( index_map , time_map_index , sum_index); - else { - ert_log_add_message(1 , NULL , "Inconsistency in time_map - data will be ignored" , false); - break; - } - - - time_map_index++; - if (time_map_index == time_map_get_size( map )) - break; - - } - } - } - pthread_rwlock_unlock( &map->rw_lock ); - - return index_map; -} - - - diff --git a/ThirdParty/Ert/libenkf/src/trans_errf.m b/ThirdParty/Ert/libenkf/src/trans_errf.m deleted file mode 100644 index f88965d8ad..0000000000 --- a/ThirdParty/Ert/libenkf/src/trans_errf.m +++ /dev/null @@ -1,3 +0,0 @@ -function y = trans_errf(x , min , max , skewness , width) - -y = min + (max - min) * 0.5*(1 + erf((x + skewness)/(width * sqrt(2.0)))); diff --git a/ThirdParty/Ert/libenkf/src/trans_func.c b/ThirdParty/Ert/libenkf/src/trans_func.c deleted file mode 100644 index bb6dbe499d..0000000000 --- a/ThirdParty/Ert/libenkf/src/trans_func.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'trans_func.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include - -#include - - - - - - -struct trans_func_struct { - char * name; /* The name this function is registered as. */ - arg_pack_type * params; /* The parameter values registered for this function. */ - transform_ftype * func; /* A pointer to the actual transformation function. */ - validate_ftype * validate; /* A pointer to a a function which can be used to validate the parameters - can be NULL. */ - stringlist_type * param_names; /* A list of the parameter names. */ - bool use_log; -}; - - - - - - -/** - Width = 1 => uniform - Width > 1 => unimodal peaked - Width < 1 => bimoal peaks - - - Skewness < 0 => shifts towards the left - Skewness = 0 => symmetric - Skewness > 0 => Shifts towards the right - - The width is a relavant scale for the value of skewness. -*/ - -static double trans_errf(double x, const arg_pack_type * arg) { - double min = arg_pack_iget_double(arg , 0); - double max = arg_pack_iget_double(arg , 1); - double skewness = arg_pack_iget_double(arg , 2); - double width = arg_pack_iget_double(arg , 3); - double y; - - y = 0.5*(1 + erf((x + skewness)/(width * sqrt(2.0)))); - return min + y * (max - min); -} - - - - -static double trans_const(double x , const arg_pack_type * arg) { - return arg_pack_iget_double(arg , 0); -} - - -static double trans_raw(double x , const arg_pack_type * arg) { - return x; -} - - - -/* Observe that the argument of the shift should be "+" */ -static double trans_derrf(double x , const arg_pack_type * arg) { - int steps = arg_pack_iget_int(arg , 0); - double min = arg_pack_iget_double(arg , 1); - double max = arg_pack_iget_double(arg , 2); - double skewness = arg_pack_iget_double(arg , 3); - double width = arg_pack_iget_double(arg , 4); - double y; - - y = floor( steps * 0.5*(1 + erf((x + skewness)/(width * sqrt(2.0)))) / (steps - 1) ); - return min + y * (max - min); -} - - - - - -static double trans_unif(double x , const arg_pack_type * arg) { - double y; - double min = arg_pack_iget_double(arg , 0); - double max = arg_pack_iget_double(arg , 1); - y = 0.5*(1 + erf(x/sqrt(2.0))); /* 0 - 1 */ - return y * (max - min) + min; -} - - - -static double trans_dunif(double x , const arg_pack_type * arg) { - double y; - int steps = arg_pack_iget_int(arg , 0); - double min = arg_pack_iget_double(arg , 1); - double max = arg_pack_iget_double(arg , 2); - - y = 0.5*(1 + erf(x/sqrt(2.0))); /* 0 - 1 */ - return (floor( y * steps) / (steps - 1)) * (max - min) + min; -} - - - - -static double trans_normal(double x , const arg_pack_type * arg) { - double mu , std; - mu = arg_pack_iget_double(arg , 0 ); - std = arg_pack_iget_double(arg , 1 ); - return x * std + mu; -} - - -static double trans_truncated_normal(double x , const arg_pack_type * arg) { - double mu , std , min , max; - - mu = arg_pack_iget_double(arg , 0 ); - std = arg_pack_iget_double(arg , 1 ); - min = arg_pack_iget_double(arg , 2 ); - max = arg_pack_iget_double(arg , 3 ); - - { - double y = x * std + mu; - util_clamp_double( &y , min , max ); - return y; - } -} - - - - -static double trans_lognormal(double x, const arg_pack_type * arg) { - double mu, std; - mu = arg_pack_iget_double(arg , 0 ); /* The expectation of log( y ) */ - std = arg_pack_iget_double(arg , 1 ); - return exp(x * std + mu); -} - - - -/** - Used to sample values between min and max - BUT it is the logarithm - of y which is uniformly distributed. Relates to the uniform - distribution in the same manner as the lognormal distribution - relates to the normal distribution. -*/ -static double trans_logunif(double x , const arg_pack_type * arg) { - double log_min = log(arg_pack_iget_double(arg , 0)); - double log_max = log(arg_pack_iget_double(arg , 1)); - double log_y; - { - double tmp = 0.5*(1 + erf(x/sqrt(2.0))); /* 0 - 1 */ - log_y = log_min + tmp * (log_max - log_min); /* Shift according to max / min */ - } - return exp(log_y); -} - - - -/*****************************************************************/ - -static trans_func_type * trans_func_alloc_empty( const char * func_name ) { - trans_func_type * trans_func = util_malloc( sizeof * trans_func ); - - - trans_func->params = arg_pack_alloc(); - trans_func->func = NULL; - trans_func->validate = NULL; - trans_func->name = util_alloc_string_copy( func_name ); - trans_func->param_names = stringlist_alloc_new(); - trans_func->use_log = false; - - return trans_func; -} - - -const char * trans_func_get_name( const trans_func_type * trans_func ) { - return trans_func->name; -} - - -const stringlist_type * trans_func_get_param_names( const trans_func_type * trans_func ) { - return trans_func->param_names; -} - -node_ctype trans_func_iget_param_ctype( const trans_func_type * trans_func , int param_index) { - return arg_pack_iget_ctype( trans_func->params , param_index); -} - - -void trans_func_iset_double_param(trans_func_type * trans_func , int param_index , double value ) { - if (arg_pack_iget_ctype( trans_func->params , param_index) == CTYPE_DOUBLE_VALUE) - arg_pack_iset_double( trans_func->params , param_index , value ); - else - util_abort("%s: type mismatch - the does not expect double as argument:%d \n",__func__ , param_index ); -} - -/** - Return true if the _set operation suceeded (i.e. the name was - recognized), and false otherwise. -*/ -bool trans_func_set_double_param( trans_func_type * trans_func , const char * param_name , double value ) { - int param_index = stringlist_find_first( trans_func->param_names , param_name); - if (param_index >= 0) { - arg_pack_iset_double( trans_func->params , param_index , value ); - return true; - } else - return false; -} - - -void trans_func_iset_int_param(trans_func_type * trans_func , int param_index , int value ) { - if (arg_pack_iget_ctype( trans_func->params , param_index) == CTYPE_INT_VALUE) - arg_pack_iset_int( trans_func->params , param_index , value ); - else - util_abort("%s: type mismatch - the does not expect int as argument:%d \n",__func__ , param_index ); -} - -/** - Return true if the _set operation suceeded (i.e. the name was - recognized), and false otherwise. -*/ -bool trans_func_set_int_param( trans_func_type * trans_func , const char * param_name , int value ) { - int param_index = stringlist_find_first( trans_func->param_names , param_name); - if (param_index >= 0) { - arg_pack_iset_int( trans_func->params , param_index , value ); - return true; - } else - return false; -} - - - -void trans_func_free( trans_func_type * trans_func ) { - stringlist_free( trans_func->param_names ); - arg_pack_free( trans_func->params ); - util_safe_free( trans_func->name ); - free( trans_func ); -} - - - - -/** - It is import to append all the parameters (with arbitrary values), - to ensure that the arg_pack registers the right type. -*/ - - -trans_func_type * trans_func_alloc( const char * func_name ) { - trans_func_type * trans_func = trans_func_alloc_empty( func_name ); - { - if (util_string_equal(func_name , "NORMAL")) { - stringlist_append_ref( trans_func->param_names , "MEAN"); - stringlist_append_ref( trans_func->param_names , "STD" ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - trans_func->func = trans_normal; - } - - if (util_string_equal( func_name , "LOGNORMAL")) { - stringlist_append_ref( trans_func->param_names , "MEAN"); - stringlist_append_ref( trans_func->param_names , "STD" ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - trans_func->func = trans_lognormal; - trans_func->use_log = true; - } - - if (util_string_equal( func_name , "TRUNCATED_NORMAL")) { - stringlist_append_ref( trans_func->param_names , "MEAN"); - stringlist_append_ref( trans_func->param_names , "STD" ); - stringlist_append_ref( trans_func->param_names , "MIN"); - stringlist_append_ref( trans_func->param_names , "MAX" ); - - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - trans_func->func = trans_truncated_normal; - } - - - if (util_string_equal( func_name , "UNIFORM")) { - stringlist_append_ref( trans_func->param_names , "MIN"); - stringlist_append_ref( trans_func->param_names , "MAX" ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - trans_func->func = trans_unif; - } - - - if (util_string_equal( func_name , "DUNIF")) { - stringlist_append_ref( trans_func->param_names , "STEPS"); - stringlist_append_ref( trans_func->param_names , "MIN"); - stringlist_append_ref( trans_func->param_names , "MAX" ); - arg_pack_append_int( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - - trans_func->func = trans_dunif; - } - - - if (util_string_equal( func_name , "ERRF")) { - stringlist_append_ref( trans_func->param_names , "MIN"); - stringlist_append_ref( trans_func->param_names , "MAX" ); - stringlist_append_ref( trans_func->param_names , "SKEWNESS"); - stringlist_append_ref( trans_func->param_names , "WIDTH" ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - - trans_func->func = trans_errf; - } - - - if (util_string_equal( func_name , "DERRF")) { - stringlist_append_ref( trans_func->param_names , "STEPS"); - stringlist_append_ref( trans_func->param_names , "MIN"); - stringlist_append_ref( trans_func->param_names , "MAX" ); - stringlist_append_ref( trans_func->param_names , "SKEWNESS"); - stringlist_append_ref( trans_func->param_names , "WIDTH" ); - arg_pack_append_int( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - - trans_func->func = trans_derrf; - } - - - if (util_string_equal( func_name , "LOGUNIF")) { - stringlist_append_ref( trans_func->param_names , "MIN"); - stringlist_append_ref( trans_func->param_names , "MAX" ); - - arg_pack_append_double( trans_func->params , 0 ); - arg_pack_append_double( trans_func->params , 0 ); - trans_func->func = trans_logunif; - trans_func->use_log = true; - } - - - if (util_string_equal( func_name , "CONST")) { - stringlist_append_ref( trans_func->param_names , "VALUE"); - arg_pack_append_double( trans_func->params , 0 ); - trans_func->func = trans_const; - } - - - if (util_string_equal( func_name , "RAW")) { - trans_func->func = trans_raw; - } - - - if (trans_func->func == NULL) - util_exit("%s: Sorry: function name:%s not recognized \n",__func__ , func_name); - } - return trans_func; -} - - - -double trans_func_eval( const trans_func_type * trans_func , double x) { - double y = trans_func->func( x , trans_func->params ); - return y; -} - -bool trans_func_use_log_scale(const trans_func_type * trans_func) { - return trans_func->use_log; -} - - - -trans_func_type * trans_func_fscanf_alloc( FILE * stream, const char * filename ) { - trans_func_type * trans_func; - char * func_name; - - func_name = util_fscanf_alloc_token(stream); - - - if (func_name == NULL) { - fprintf(stderr,"Problem at file:line: %s:%d \n", filename, util_get_current_linenr( stream )); - util_abort("%s: could not locate name of transformation - aborting \n",__func__); - } - - trans_func = trans_func_alloc( func_name ); - arg_pack_fscanf( trans_func->params , stream, filename ); - - free( func_name ); - return trans_func; -} - diff --git a/ThirdParty/Ert/libenkf/src/trans_test.m b/ThirdParty/Ert/libenkf/src/trans_test.m deleted file mode 100644 index 83ff575003..0000000000 --- a/ThirdParty/Ert/libenkf/src/trans_test.m +++ /dev/null @@ -1,12 +0,0 @@ -%% This is matlab file used to test/vizualize the various -%% distributions in trans_func.c - -N = 100000; -x = random('normal',0 , 1 , N ,1); - - - -y = trans_errf(x , 0.1 , 15 , -3 , 2.0); - -disp(sprintf(' = %g' , mean(y))); -hist(y , sqrt(N)) diff --git a/ThirdParty/Ert/libenkf/tests/CMakeLists.txt b/ThirdParty/Ert/libenkf/tests/CMakeLists.txt deleted file mode 100644 index 4f220dc920..0000000000 --- a/ThirdParty/Ert/libenkf/tests/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -include( tests.cmake ) -if (STATOIL_TESTDATA_ROOT) - include( statoil_tests.cmake ) -endif() diff --git a/ThirdParty/Ert/libenkf/tests/data/config/analysis_load_config b/ThirdParty/Ert/libenkf/tests/data/config/analysis_load_config deleted file mode 100644 index 657ba148c3..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/analysis_load_config +++ /dev/null @@ -1 +0,0 @@ -NUM_REALIZATIONS 3 diff --git a/ThirdParty/Ert/libenkf/tests/data/config/analysis_load_site_config b/ThirdParty/Ert/libenkf/tests/data/config/analysis_load_site_config deleted file mode 100644 index c7be2f143e..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/analysis_load_site_config +++ /dev/null @@ -1,2 +0,0 @@ -ANALYSIS_LOAD RML_ENKF_SITE_CONFIG1 rml_enkf.so -ANALYSIS_LOAD RML_ENKF_SITE_CONFIG2 rml_enkf.so diff --git a/ThirdParty/Ert/libenkf/tests/data/config/ert_report_list b/ThirdParty/Ert/libenkf/tests/data/config/ert_report_list deleted file mode 100644 index 270780b1f1..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/ert_report_list +++ /dev/null @@ -1,3 +0,0 @@ -REPORT_TIMEOUT 167 - -REPORT_LARGE TRUE \ No newline at end of file diff --git a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/FAULT_TEMPLATE b/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/FAULT_TEMPLATE deleted file mode 100644 index de1f12ca5b..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/FAULT_TEMPLATE +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/MULTFLT.TXT b/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/MULTFLT.TXT deleted file mode 100644 index c193c48528..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/MULTFLT.TXT +++ /dev/null @@ -1 +0,0 @@ -MULTFLT NORMAL 0 1 diff --git a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_KW_false b/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_KW_false deleted file mode 100644 index d66f17444a..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_KW_false +++ /dev/null @@ -1,8 +0,0 @@ -JOBNAME Job%d -RUNPATH simulations/run%d -NUM_REALIZATIONS 1 - -ENSPATH Storage -JOB_SCRIPT script.sh - -GEN_KW MULTFLT FAULT_TEMPLATE MULTFLT.INC MULTFLT.TXT INIT_FILES:MULTFLT_INIT diff --git a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_KW_true b/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_KW_true deleted file mode 100644 index cd6b539bbb..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_KW_true +++ /dev/null @@ -1,10 +0,0 @@ -JOBNAME Job%d -RUNPATH simulations/run%d -NUM_REALIZATIONS 1 - -ENSPATH Storage -JOB_SCRIPT script.sh - -GEN_KW MULTFLT FAULT_TEMPLATE MULTFLT.INC MULTFLT.TXT INIT_FILES:MULTFLT_INIT FORWARD_INIT:TRUE - - diff --git a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_PARAM_false b/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_PARAM_false deleted file mode 100644 index 4454bbab15..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_PARAM_false +++ /dev/null @@ -1,9 +0,0 @@ -JOBNAME Job%d -RUNPATH simulations/run%d -NUM_REALIZATIONS 1 - -ENSPATH Storage -JOB_SCRIPT script.sh - - -GEN_PARAM PARAM PARAM.INC INIT_FILES:PARAM_INIT INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII \ No newline at end of file diff --git a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_PARAM_true b/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_PARAM_true deleted file mode 100644 index 6ba8d1c4f4..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/config_GEN_PARAM_true +++ /dev/null @@ -1,10 +0,0 @@ -JOBNAME Job%d -RUNPATH simulations/run%d -NUM_REALIZATIONS 1 - -ENSPATH Storage -JOB_SCRIPT script.sh - - -GEN_PARAM PARAM PARAM.INC INIT_FILES:PARAM_INIT INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII FORWARD_INIT:TRUE - diff --git a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/script.sh b/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/script.sh deleted file mode 100644 index 2f92a600cf..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/forward/ert/script.sh +++ /dev/null @@ -1 +0,0 @@ -# Completlely stupid - an executable must be present for the testing. diff --git a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/FAULT_TEMPLATE b/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/FAULT_TEMPLATE deleted file mode 100644 index de1f12ca5b..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/FAULT_TEMPLATE +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/FAULT_TEMPLATE2 b/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/FAULT_TEMPLATE2 deleted file mode 100644 index bb7d23f1dd..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/FAULT_TEMPLATE2 +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/MULTFLT.TXT b/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/MULTFLT.TXT deleted file mode 100644 index ec7d5e43ed..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/MULTFLT.TXT +++ /dev/null @@ -1 +0,0 @@ -MULTFLT LOGUNIF 0.0001 0.01 diff --git a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/MULTFLT2.TXT b/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/MULTFLT2.TXT deleted file mode 100644 index d2f6e43865..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/MULTFLT2.TXT +++ /dev/null @@ -1 +0,0 @@ -MULTFLT2 LOGUNIF 0.0000001 0.00001 diff --git a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/config_GEN_KW_logarithmic b/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/config_GEN_KW_logarithmic deleted file mode 100644 index 8075af97a6..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/config_GEN_KW_logarithmic +++ /dev/null @@ -1,9 +0,0 @@ -JOBNAME Job%d -RUNPATH simulations/run%d -NUM_REALIZATIONS 1 - -ENSPATH Storage -JOB_SCRIPT script.sh - -GEN_KW MULTFLT FAULT_TEMPLATE MULTFLT.INC MULTFLT.TXT -GEN_KW MULTFLT2 FAULT_TEMPLATE2 MULTFLT2.INC MULTFLT2.TXT diff --git a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/script.sh b/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/script.sh deleted file mode 100644 index 2f92a600cf..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_logarithmic/script.sh +++ /dev/null @@ -1 +0,0 @@ -# Completlely stupid - an executable must be present for the testing. diff --git a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/Parameters.txt b/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/Parameters.txt deleted file mode 100644 index ba7f5b2386..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/Parameters.txt +++ /dev/null @@ -1,5 +0,0 @@ -PARAM1 CONST 100 -PARAM2 UNIFORM 0 1 -PARAM3 LOGUNIF 0.001 1000 -PARAM4 LOGNORMAL 0.25 100 - diff --git a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/Template.tmpl b/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/Template.tmpl deleted file mode 100644 index ff8e16240d..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/Template.tmpl +++ /dev/null @@ -1 +0,0 @@ --- Template; not used \ No newline at end of file diff --git a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/config b/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/config deleted file mode 100644 index f043581fe5..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/gen_kw_plot/config +++ /dev/null @@ -1,2 +0,0 @@ -NUM_REALIZATIONS 25 -GEN_KW GEN_KW Template.tmpl Target.inc Parameters.txt \ No newline at end of file diff --git a/ThirdParty/Ert/libenkf/tests/data/config/rng b/ThirdParty/Ert/libenkf/tests/data/config/rng deleted file mode 100644 index ad8ee50cb1..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/rng +++ /dev/null @@ -1,6 +0,0 @@ -NUM_REALIZATIONS 25 -STORE_SEED seed2 -LOAD_SEED seed2 - --- The settings below here are artifacts which should not be necessary ... -JOB_SCRIPT script.sh diff --git a/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/ARGECHO_JOB b/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/ARGECHO_JOB deleted file mode 100644 index 9cd8129c85..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/ARGECHO_JOB +++ /dev/null @@ -1,2 +0,0 @@ -INTERNAL FALSE -EXECUTABLE arg_echo.sh diff --git a/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/ARGECHO_WF b/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/ARGECHO_WF deleted file mode 100644 index 2eef71ca9b..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/ARGECHO_WF +++ /dev/null @@ -1 +0,0 @@ -ARGECHO_JOB runpath_list.txt \ No newline at end of file diff --git a/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/arg_echo.sh b/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/arg_echo.sh deleted file mode 100644 index e7fffa0c13..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/arg_echo.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -echo $1 > $2 diff --git a/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/config b/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/config deleted file mode 100644 index ded46130bb..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/runpath_list/config +++ /dev/null @@ -1,5 +0,0 @@ -RUNPATH_FILE runpath/runpath-file.txt -NUM_REALIZATIONS 10 - -LOAD_WORKFLOW_JOB ARGECHO_JOB -LOAD_WORKFLOW ARGECHO_WF diff --git a/ThirdParty/Ert/libenkf/tests/data/config/script.sh b/ThirdParty/Ert/libenkf/tests/data/config/script.sh deleted file mode 100644 index de495719f7..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/script.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -#Dummy script \ No newline at end of file diff --git a/ThirdParty/Ert/libenkf/tests/data/config/test_context/FAULT_TEMPLATE b/ThirdParty/Ert/libenkf/tests/data/config/test_context/FAULT_TEMPLATE deleted file mode 100644 index de1f12ca5b..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/test_context/FAULT_TEMPLATE +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ThirdParty/Ert/libenkf/tests/data/config/test_context/MULTFLT.TXT b/ThirdParty/Ert/libenkf/tests/data/config/test_context/MULTFLT.TXT deleted file mode 100644 index c193c48528..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/test_context/MULTFLT.TXT +++ /dev/null @@ -1 +0,0 @@ -MULTFLT NORMAL 0 1 diff --git a/ThirdParty/Ert/libenkf/tests/data/config/test_context/config b/ThirdParty/Ert/libenkf/tests/data/config/test_context/config deleted file mode 100644 index 7e702c6b14..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/test_context/config +++ /dev/null @@ -1,11 +0,0 @@ -JOBNAME Job%d -RUNPATH simulations/run%d -NUM_REALIZATIONS 1 - -ENSPATH Storage -JOB_SCRIPT script.sh - -GEN_KW MULTFLT FAULT_TEMPLATE MULTFLT.INC MULTFLT.TXT INIT_FILES:MULTFLT_INIT FORWARD_INIT:TRUE - - -SUMMARY RPR:8 diff --git a/ThirdParty/Ert/libenkf/tests/data/config/test_context/script.sh b/ThirdParty/Ert/libenkf/tests/data/config/test_context/script.sh deleted file mode 100644 index 2f92a600cf..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/test_context/script.sh +++ /dev/null @@ -1 +0,0 @@ -# Completlely stupid - an executable must be present for the testing. diff --git a/ThirdParty/Ert/libenkf/tests/data/config/test_context/wf_job b/ThirdParty/Ert/libenkf/tests/data/config/test_context/wf_job deleted file mode 100644 index ed3a5838fb..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/test_context/wf_job +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_select_case_JOB -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 STRING diff --git a/ThirdParty/Ert/libenkf/tests/data/config/test_context/wf_job_fail b/ThirdParty/Ert/libenkf/tests/data/config/test_context/wf_job_fail deleted file mode 100644 index b8d5206384..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/config/test_context/wf_job_fail +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION unknown_function__ -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 STRING diff --git a/ThirdParty/Ert/libenkf/tests/data/ensemble/GEN_PARAM b/ThirdParty/Ert/libenkf/tests/data/ensemble/GEN_PARAM deleted file mode 100644 index 8f2fdaa749..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/ensemble/GEN_PARAM +++ /dev/null @@ -1 +0,0 @@ -GEN_PARAM GP GP.txt INIT_FILES:GP/GP.txt INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII \ No newline at end of file diff --git a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF1 b/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF1 deleted file mode 100644 index c42a844b29..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF1 +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION util_malloc -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 FLOAT diff --git a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF2 b/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF2 deleted file mode 100644 index f07a3cc4ab..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF2 +++ /dev/null @@ -1,2 +0,0 @@ -This should not be loaded; -instead the CONF2@1 should be loaded in testing. \ No newline at end of file diff --git a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF2@1 b/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF2@1 deleted file mode 100644 index c42a844b29..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF2@1 +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION util_malloc -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 FLOAT diff --git a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF3@1.2.3 b/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF3@1.2.3 deleted file mode 100644 index c42a844b29..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF3@1.2.3 +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION util_malloc -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 FLOAT diff --git a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF4@1.2.0 b/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF4@1.2.0 deleted file mode 100644 index c42a844b29..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF4@1.2.0 +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION util_malloc -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 FLOAT diff --git a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF5@1.2 b/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF5@1.2 deleted file mode 100644 index c42a844b29..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF5@1.2 +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION util_malloc -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 FLOAT diff --git a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF5@1.2.0 b/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF5@1.2.0 deleted file mode 100644 index b138beb40a..0000000000 --- a/ThirdParty/Ert/libenkf/tests/data/workflow_jobs/CONF5@1.2.0 +++ /dev/null @@ -1 +0,0 @@ -Wrong .... diff --git a/ThirdParty/Ert/libenkf/tests/enkf_active_list.c b/ThirdParty/Ert/libenkf/tests/enkf_active_list.c deleted file mode 100644 index 9e647d0d85..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_active_list.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_active_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include - -#include - - - -int main(int argc , char ** argv) { - active_list_type * active_list1 = active_list_alloc( ); - active_list_type * active_list2 = active_list_alloc( ); - - - test_assert_true( active_list_is_instance( active_list1 )); - - test_assert_true( active_list_equal( active_list1 , active_list2 )); - - active_list_add_index( active_list1 , 11 ); - test_assert_false(active_list_equal( active_list1 , active_list2 )); - - active_list_add_index( active_list1 , 12 ); - test_assert_false(active_list_equal( active_list1 , active_list2 )); - - active_list_add_index( active_list2 , 11 ); - test_assert_false(active_list_equal( active_list1 , active_list2 )); - - active_list_add_index( active_list2 , 12 ); - test_assert_true(active_list_equal( active_list1 , active_list2 )); - - active_list_add_index( active_list2 , 13 ); - test_assert_false(active_list_equal( active_list1 , active_list2 )); - - active_list_add_index( active_list1 , 13 ); - test_assert_true(active_list_equal( active_list1 , active_list2 )); - - active_list_add_index( active_list2 , 27 ); - test_assert_false(active_list_equal( active_list1 , active_list2 )); - active_list_copy( active_list1 , active_list2 ); - test_assert_true(active_list_equal( active_list1 , active_list2 )); - - active_list_free( active_list1 ); - active_list_free( active_list2 ); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_analysis_config.c b/ThirdParty/Ert/libenkf/tests/enkf_analysis_config.c deleted file mode 100644 index fcf0d40e7a..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_analysis_config.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_analysis_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - - -analysis_config_type * create_analysis_config() { - rng_type * rng = rng_alloc( MZRAN , INIT_DEFAULT ); - analysis_config_type * ac = analysis_config_alloc( rng ); - return ac; -} - - -void test_create() { - analysis_config_type * ac = create_analysis_config( ); - test_assert_true( analysis_config_is_instance( ac ) ); - analysis_config_free( ac ); -} - - -void test_min_realizations(const char * num_realizations_str, const char * min_realizations_str, int min_realizations_expected_needed) { - test_work_area_type * work_area = test_work_area_alloc("test_min_realizations_string"); - - { - FILE * config_file_stream = util_mkdir_fopen("config_file", "w"); - test_assert_not_NULL(config_file_stream); - - fputs(num_realizations_str, config_file_stream); - fputs(min_realizations_str, config_file_stream); - fclose(config_file_stream); - - config_parser_type * c = config_alloc(); - config_schema_item_type * item = config_add_schema_item(c , NUM_REALIZATIONS_KEY , true ); - config_schema_item_set_default_type(item, CONFIG_INT); - config_schema_item_set_argc_minmax( item , 1 , 1); - - item = config_add_schema_item(c , MIN_REALIZATIONS_KEY , false ); - config_schema_item_set_argc_minmax( item , 1 , 2); - { - config_content_type * content = config_parse(c , "config_file" , "--" , NULL , NULL , NULL , false , true ); - test_assert_true(config_content_is_valid(content)); - - analysis_config_type * ac = create_analysis_config( ); - analysis_config_init(ac, content); - - int num_realizations = config_content_get_value_as_int(content, NUM_REALIZATIONS_KEY); - test_assert_false(analysis_config_have_enough_realisations(ac, min_realizations_expected_needed - 1, num_realizations )); - test_assert_true(analysis_config_have_enough_realisations(ac, min_realizations_expected_needed, num_realizations )); - test_assert_true(analysis_config_have_enough_realisations(ac, min_realizations_expected_needed + 1, num_realizations )); - analysis_config_free( ac ); - config_content_free( content ); - config_free( c ); - } - } - - test_work_area_free(work_area); -} - - -void test_have_enough_realisations_defaulted( ) { - analysis_config_type * ac = create_analysis_config( ); - int ensemble_size = 20; - - // min_realizations not set, should then require 20 (ensemble_size) - test_assert_false( analysis_config_have_enough_realisations( ac , 0, ensemble_size )); - test_assert_false( analysis_config_have_enough_realisations( ac , 10, ensemble_size )); - test_assert_true( analysis_config_have_enough_realisations( ac , 20, ensemble_size )); - - analysis_config_free( ac ); -} - - -void test_current_module_options() { - analysis_config_type * ac = create_analysis_config( ); - test_assert_NULL( analysis_config_get_active_module( ac )); - analysis_config_load_internal_module(ac , "STD_ENKF"); - - test_assert_false( analysis_config_get_module_option( ac , ANALYSIS_SCALE_DATA)); - test_assert_true(analysis_config_select_module(ac , "STD_ENKF")); - test_assert_false( analysis_config_select_module(ac , "DOES_NOT_EXIST")); - - test_assert_true( analysis_module_is_instance( analysis_config_get_active_module( ac ))); - test_assert_true( analysis_config_get_module_option( ac , ANALYSIS_SCALE_DATA)); - test_assert_false( analysis_config_get_module_option( ac , ANALYSIS_ITERABLE)); - analysis_config_free( ac ); -} - -void test_stop_long_running( ) { - analysis_config_type * ac = create_analysis_config( ); - test_assert_bool_equal( false , analysis_config_get_stop_long_running( ac ) ); - analysis_config_set_stop_long_running( ac , true ); - test_assert_bool_equal( true , analysis_config_get_stop_long_running( ac ) ); - analysis_config_free( ac ); -} - -void test_min_realizations_percent() { - { - const char * num_realizations_str = "NUM_REALIZATIONS 80\n"; - const char * min_realizations_str = "MIN_REALIZATIONS 10%\n"; - int min_realizations_expected_needed = 8; - test_min_realizations(num_realizations_str, min_realizations_str, min_realizations_expected_needed); - } - { - const char * num_realizations_str = "NUM_REALIZATIONS 8\n"; - const char * min_realizations_str = "MIN_REALIZATIONS 50%\n"; - int min_realizations_expected_needed = 4; - test_min_realizations(num_realizations_str, min_realizations_str, min_realizations_expected_needed ); - } - { - const char * num_realizations_str = "NUM_REALIZATIONS 8\n"; - const char * min_realizations_str = "MIN_REALIZATIONS 100%\n"; - int min_realizations_expected_needed = 8; - test_min_realizations(num_realizations_str, min_realizations_str, min_realizations_expected_needed ); - } - { - const char * num_realizations_str = "NUM_REALIZATIONS 8\n"; - const char * min_realizations_str = "MIN_REALIZATIONS 10%\n"; - int min_realizations_expected_needed = 8; // Expect 8 because 10 % of 8 will be calculated to zero. - test_min_realizations(num_realizations_str, min_realizations_str, min_realizations_expected_needed ); - } -} - -void test_min_realizations_number() { - { - const char * num_realizations_str = "NUM_REALIZATIONS 80\n"; - const char * min_realizations_str = "MIN_REALIZATIONS 0\n"; - int min_realizations_expected_needed = 80; - test_min_realizations(num_realizations_str, min_realizations_str, min_realizations_expected_needed); - } - { - const char * num_realizations_str = "NUM_REALIZATIONS 900\n"; - int min_realizations_expected_needed = 900; // Nothing specified, expect NUM_REALIZATIONS - test_min_realizations(num_realizations_str, "", min_realizations_expected_needed); - } - { - const char * num_realizations_str = "NUM_REALIZATIONS 900\n"; - const char * min_realizations_str = "MIN_REALIZATIONS 10 \n"; - int min_realizations_expected_needed = 10; - test_min_realizations(num_realizations_str, min_realizations_str, min_realizations_expected_needed); - } - { - const char * num_realizations_str = "NUM_REALIZATIONS 80\n"; - const char * min_realizations_str = "MIN_REALIZATIONS 50\n"; - int min_realizations_expected_needed = 50; - test_min_realizations(num_realizations_str, min_realizations_str, min_realizations_expected_needed); - } - { - const char * num_realizations_str = "NUM_REALIZATIONS 80\n"; - const char * min_realizations_str = "MIN_REALIZATIONS 80\n"; - int min_realizations_expected_needed = 80; - test_min_realizations(num_realizations_str, min_realizations_str, min_realizations_expected_needed); - } - { - const char * num_realizations_str = "NUM_REALIZATIONS 80\n"; - const char * min_realizations_str = "MIN_REALIZATIONS 100\n"; - int min_realizations_expected_needed = 80; - test_min_realizations(num_realizations_str, min_realizations_str, min_realizations_expected_needed); - } -} - -int main(int argc , char ** argv) { - test_create(); - test_have_enough_realisations_defaulted(); - test_min_realizations_percent(); - test_min_realizations_number(); - test_current_module_options(); - test_stop_long_running(); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_analysis_config_analysis_load.c b/ThirdParty/Ert/libenkf/tests/enkf_analysis_config_analysis_load.c deleted file mode 100644 index 361e8fd1b6..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_analysis_config_analysis_load.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_analysis_config_analysis_load.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include - -#include -#include - -#include -#include - -int main(int argc , const char ** argv) { - util_install_signals(); - { - const char * config_file = argv[1]; - - ert_test_context_type * test_context = ert_test_context_alloc("AnalysisLoadFromSiteConfig" , config_file); - enkf_main_type * enkf_main = ert_test_context_get_main(test_context); - - test_assert_true(analysis_config_has_module(enkf_main_get_analysis_config(enkf_main), "RML_ENKF_SITE_CONFIG1")); - analysis_module_type * analysis_module = analysis_config_get_module(enkf_main_get_analysis_config(enkf_main), "RML_ENKF_SITE_CONFIG1"); - test_assert_string_equal(analysis_module_get_name(analysis_module), "RML_ENKF_SITE_CONFIG1"); - - test_assert_true(analysis_config_has_module(enkf_main_get_analysis_config(enkf_main), "RML_ENKF_SITE_CONFIG2")); - analysis_module_type * analysis_module2 = analysis_config_get_module(enkf_main_get_analysis_config(enkf_main), "RML_ENKF_SITE_CONFIG2"); - test_assert_string_equal(analysis_module_get_name(analysis_module2), "RML_ENKF_SITE_CONFIG2"); - - ert_test_context_free(test_context); - } -} - - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_analysis_config_ext_module.c b/ThirdParty/Ert/libenkf/tests/enkf_analysis_config_ext_module.c deleted file mode 100644 index 57b4fd6eb0..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_analysis_config_ext_module.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_analysis_config_ext_module.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - - -void test_load_external_module( analysis_config_type * ac , const char * user_name , const char * lib_name) { - test_assert_true( analysis_config_load_external_module(ac , lib_name , user_name )); -} - - - -int main(int argc , char ** argv) { - rng_type * rng = rng_alloc(MZRAN , INIT_DEFAULT); - analysis_config_type * analysis_config = analysis_config_alloc(rng); - - for (int i = 1; i < argc; i+= 2) { - const char * user_name = argv[i]; - const char * lib_name = argv[i + 1]; - test_load_external_module( analysis_config , user_name , lib_name ); - } - - analysis_config_free(analysis_config); - rng_free( rng ); - exit(0); -} - - - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_analysis_update_job.c b/ThirdParty/Ert/libenkf/tests/enkf_analysis_update_job.c deleted file mode 100644 index 45e4b74955..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_analysis_update_job.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_analysis_update_job.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - - -void test_update_default(const char * config_file , const char * job_file) { - ert_test_context_type * test_context = ert_test_context_alloc("AnalysisJob0" , config_file); - - stringlist_type * args = stringlist_alloc_new(); - test_assert_true( ert_test_context_install_workflow_job( test_context , "JOB" , job_file )); - test_assert_true( ert_test_context_run_worklow_job( test_context , "JOB" , args) ); - stringlist_free( args ); - - ert_test_context_free( test_context ); -} - - -void test_update_new_case(const char * config_file , const char * job_file) { - ert_test_context_type * test_context = ert_test_context_alloc("AnalysisJob1" , config_file); - - stringlist_type * args = stringlist_alloc_new(); - stringlist_append_copy( args , "NewCase" ); - ert_test_context_install_workflow_job( test_context , "JOB" , job_file ); - test_assert_true( ert_test_context_run_worklow_job( test_context , "JOB" , args) ); - stringlist_free( args ); - - ert_test_context_free( test_context ); -} - - -void test_update_new_case_step(const char * config_file , const char * job_file) { - ert_test_context_type * test_context = ert_test_context_alloc("AnalysisJob2" , config_file); - - stringlist_type * args = stringlist_alloc_new(); - stringlist_append_copy( args , "NewCase" ); - stringlist_append_copy( args , "20" ); - ert_test_context_install_workflow_job( test_context , "JOB" , job_file ); - test_assert_true( ert_test_context_run_worklow_job( test_context , "JOB" , args) ); - stringlist_free( args ); - - ert_test_context_free( test_context ); -} - - -void test_update_new_case_step_selected(const char * config_file , const char * job_file) { - ert_test_context_type * test_context = ert_test_context_alloc("AnalysisJob2" , config_file ); - - stringlist_type * args = stringlist_alloc_new(); - stringlist_append_copy( args , "NewCase" ); - stringlist_append_copy( args , "20" ); - stringlist_append_copy( args , "10" ); - stringlist_append_copy( args , ",20" ); - stringlist_append_copy( args , ",30-50" ); - ert_test_context_install_workflow_job( test_context , "JOB" , job_file ); - test_assert_true( ert_test_context_run_worklow_job( test_context , "JOB" , args) ); - stringlist_free( args ); - - ert_test_context_free( test_context ); -} - - - -int main(int argc , char ** argv) { - const char * config_file = argv[1]; - const char * job_file = argv[2]; - - test_update_default( config_file , job_file); - test_update_new_case( config_file , job_file ); - test_update_new_case_step( config_file , job_file ); - test_update_new_case_step_selected( config_file , job_file ); - - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_block_obs.c b/ThirdParty/Ert/libenkf/tests/enkf_block_obs.c deleted file mode 100644 index 774470a7ff..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_block_obs.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_blockdata.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include - -#include - -#include -#include -#include - - -void test_create_invalid_data(ecl_grid_type * grid) { - void * data_config = NULL; - test_assert_NULL(block_obs_alloc( "ObsKey" , data_config , grid )); -} - - - -void test_create_from_field(ecl_grid_type * grid) { - field_config_type * field_config = field_config_alloc_empty( "PRESSURE" , grid , NULL, false ); - block_obs_type * block_obs = block_obs_alloc( "ObsKey" , field_config , grid ); - - test_assert_true( block_obs_is_instance( block_obs )); - test_assert_int_equal(0 , block_obs_get_size( block_obs )); - block_obs_append_field_obs( block_obs , 10 , 12 , 8 , 100 , 25); - test_assert_int_equal(1 , block_obs_get_size( block_obs )); - block_obs_append_field_obs( block_obs , 10 , 12 , 9 , 100 , 25); - test_assert_int_equal(2 , block_obs_get_size( block_obs )); - block_obs_free( block_obs ); - field_config_free( field_config ); -} - - -void test_create_from_summary(ecl_grid_type * grid) { - container_config_type * container_config = container_config_alloc( "Container"); - block_obs_type * block_obs = block_obs_alloc( "ObsKey" , container_config , grid ); - - test_assert_true( block_obs_is_instance( block_obs )); - test_assert_int_equal(0 , block_obs_get_size( block_obs )); - - - block_obs_append_summary_obs( block_obs , 10 , 12 , 8 , "BPR:111,13,9" , 100 , 25); - test_assert_int_equal(1 , block_obs_get_size( block_obs )); - block_obs_append_summary_obs( block_obs , 10 , 12 , 9 , "BPR:11,13,10" , 100 , 25); - test_assert_int_equal(2 , block_obs_get_size( block_obs )); - block_obs_free( block_obs ); - - container_config_free( container_config ); -} - - - -int main (int argc , char ** argv) { - ecl_grid_type * grid = ecl_grid_alloc( argv[1] ); - { - test_create_invalid_data( grid ); - test_create_from_field(grid); - test_create_from_summary( grid); - } - ecl_grid_free( grid ); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_cases_config.c b/ThirdParty/Ert/libenkf/tests/enkf_cases_config.c deleted file mode 100644 index 8063c00f41..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_cases_config.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_cases_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include - - -void test_create_get_set_and_get() { - cases_config_type * cases_config = cases_config_alloc( ); - test_assert_int_equal( 0, cases_config_get_iteration_number( cases_config ) ); - cases_config_set_int( cases_config , "iteration_number" , 12); - test_assert_int_equal( 12, cases_config_get_iteration_number( cases_config ) ); - cases_config_fwrite( cases_config , "TEST_CASES_CONFIG" ); - cases_config_fread( cases_config , "TEST_CASES_CONFIG" ); - cases_config_free( cases_config ); -} - -int main(int argc , char ** argv) { - test_create_get_set_and_get(); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_config_node.c b/ThirdParty/Ert/libenkf/tests/enkf_config_node.c deleted file mode 100644 index ecec479dfe..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_config_node.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_config_node.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include - -#include -#include - - - - -int main(int argc , char ** argv) { - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_ecl_config.c b/ThirdParty/Ert/libenkf/tests/enkf_ecl_config.c deleted file mode 100644 index 39bdcfc341..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_ecl_config.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_ecl_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include - -#include -#include - -int main(int argc , char ** argv) { - ecl_config_type * ecl_config = ecl_config_alloc(); - - if (argc == 2) { - test_assert_true(ecl_config_load_refcase( ecl_config , argv[1])); - - ecl_refcase_list_type * refcase_list = ecl_config_get_refcase_list( ecl_config ); - test_assert_int_equal( ecl_refcase_list_get_size( refcase_list ) , 1 ); - { - const ecl_sum_type * iget0 = ecl_refcase_list_iget_case( refcase_list , 0 ); - const ecl_sum_type * def = ecl_refcase_list_get_default( refcase_list ); - - test_assert_ptr_equal( iget0 , def ); - test_assert_string_equal( argv[1] , ecl_sum_get_case( def )); - test_assert_string_equal( ecl_refcase_list_iget_pathcase( refcase_list , 0) , ecl_sum_get_case( def )); - - } - } - test_assert_false(ecl_config_load_refcase( ecl_config , "DOES_NOT_EXIST" )); - test_assert_true(ecl_config_load_refcase( ecl_config , NULL )); - - - - ecl_config_free( ecl_config ); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_ecl_config_config.c b/ThirdParty/Ert/libenkf/tests/enkf_ecl_config_config.c deleted file mode 100644 index f108cb14fc..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_ecl_config_config.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_ecl_config_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - -int main(int argc , char ** argv) { - util_install_signals(); - { - const char * config_file = argv[1]; - ecl_config_type * ecl_config = ecl_config_alloc(); - ecl_refcase_list_type * refcase_list = ecl_config_get_refcase_list( ecl_config ); - { - config_parser_type * config = config_alloc(); - config_content_type * content; - - ecl_config_add_config_items( config ); - content = config_parse( config , config_file , "--" , NULL , NULL , NULL , CONFIG_UNRECOGNIZED_WARN , true); - - test_assert_true( config_content_is_valid( content )); - ecl_config_init( ecl_config , content ); - - config_content_free( content ); - config_free( config ); - } - - test_assert_true( ecl_config_has_refcase( ecl_config )); - test_assert_int_equal( ecl_refcase_list_get_size( refcase_list) , 17); - - ecl_config_free( ecl_config ); - } - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_enkf_config_node_gen_data.c b/ThirdParty/Ert/libenkf/tests/enkf_enkf_config_node_gen_data.c deleted file mode 100644 index 512762187a..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_enkf_config_node_gen_data.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_enkf_config_node_gen_data.c' is part of ERT - - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include - -#include - - -void test_create() { - enkf_config_node_type * node = enkf_config_node_alloc_GEN_PARAM("key" , false, ASCII , ASCII , "init%d" , "out.txt"); - enkf_config_node_free( node ); -} - - - -int main( int argc , char **argv ) { - test_create(); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_ensemble.c b/ThirdParty/Ert/libenkf/tests/enkf_ensemble.c deleted file mode 100644 index 9979c1ce04..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_ensemble.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_ensemble.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#include -#include - - - - - - - -int main(int argc , char ** argv) { - ensemble_config_type * ensemble = ensemble_config_alloc(); - ensemble_config_free( ensemble ); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_ensemble_GEN_PARAM.c b/ThirdParty/Ert/libenkf/tests/enkf_ensemble_GEN_PARAM.c deleted file mode 100644 index d6d884ab35..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_ensemble_GEN_PARAM.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_ensemble_GEN_PARAM.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - - - - - - - -int main(int argc , char ** argv) { - const char * config_file = argv[1]; - config_parser_type * config = config_alloc(); - config_content_type * content; - ensemble_config_type * ensemble = ensemble_config_alloc(); - - enkf_config_node_add_GEN_PARAM_config_schema( config ); - - content = config_parse( config , config_file , "--" , NULL , NULL , NULL , CONFIG_UNRECOGNIZED_WARN , true ); - test_assert_true( config_content_is_valid( content ) ); - - ensemble_config_init_GEN_PARAM( ensemble, content ); - - config_content_free( content ); - config_free( config ); - ensemble_config_free( ensemble ); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_ensemble_config.c b/ThirdParty/Ert/libenkf/tests/enkf_ensemble_config.c deleted file mode 100644 index c4d3ca0d52..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_ensemble_config.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_gen_data_config_parse.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include -#include - -#include "ert/util/build_config.h" - -#include -#include - -#include - -void add_NULL_node( void * arg) { - ensemble_config_type * ens_config = ensemble_config_safe_cast( arg ); - ensemble_config_add_node( ens_config , NULL ); -} - - - -void test_abort_on_add_NULL() { - ensemble_config_type * ensemble_config = ensemble_config_alloc(); - - test_assert_true( ensemble_config_is_instance( ensemble_config )); - test_assert_util_abort("ensemble_config_add_node" , add_NULL_node , ensemble_config ); - - ensemble_config_free( ensemble_config ); -} - - -int main( int argc , char ** argv) { - test_abort_on_add_NULL(); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_ert_run_context.c b/ThirdParty/Ert/libenkf/tests/enkf_ert_run_context.c deleted file mode 100644 index 6a8abf09b3..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_ert_run_context.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'ert_run_context.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include -#include -#include - -#include -#include -#include - -void test_create() { - bool_vector_type * iactive = bool_vector_alloc(10,true); - bool_vector_iset( iactive , 6 , false ); - bool_vector_iset( iactive , 8 , false ); - { - enkf_fs_type * init_fs = NULL; - subst_list_type * subst_list = subst_list_alloc( NULL ); - path_fmt_type * runpath_fmt = path_fmt_alloc_directory_fmt("/tmp/path/%04d"); - ert_init_context_type * context = ert_init_context_alloc( init_fs , iactive , runpath_fmt , subst_list , INIT_CONDITIONAL , 13 ); - - test_assert_true( ert_init_context_is_instance( context )); - test_assert_int_equal( 8 , ert_init_context_get_size( context )); - - { - run_arg_type * run_arg0 = ert_init_context_iget_arg( context , 0 ); - - test_assert_int_equal( 13 , run_arg_get_iter( run_arg0 )); - test_assert_string_equal( "/tmp/path/0000" , run_arg_get_runpath( run_arg0 )); - - test_assert_true( run_arg_is_instance( run_arg0 )); - } - ert_init_context_free( context ); - path_fmt_free( runpath_fmt ); - } - bool_vector_free( iactive ); -} - - -void test_create_ENSEMBLE_EXPERIMENT() { - bool_vector_type * iactive = bool_vector_alloc(10,true); - bool_vector_iset( iactive , 0 , false ); - bool_vector_iset( iactive , 8 , false ); - { - subst_list_type * subst_list = subst_list_alloc( NULL ); - path_fmt_type * runpath_fmt = path_fmt_alloc_directory_fmt("/tmp/path/%04d/%d"); - enkf_fs_type * fs = NULL; - ert_run_context_type * context = ert_run_context_alloc_ENSEMBLE_EXPERIMENT( fs, iactive , runpath_fmt , subst_list , 7 ); - - test_assert_true( ert_run_context_is_instance( context )); - test_assert_int_equal( 8 , ert_run_context_get_size( context )); - - { - run_arg_type * run_arg0 = ert_run_context_iens_get_arg( context , 0 ); - run_arg_type * run_arg2 = ert_run_context_iens_get_arg( context , 2 ); - run_arg_type * run_argi = ert_run_context_iget_arg( context , 1 ); - - test_assert_NULL( run_arg0 ); - test_assert_true( run_arg_is_instance( run_argi )); - test_assert_ptr_equal( run_arg2 , run_argi); - } - - { - run_arg_type * run_arg1 = ert_run_context_iget_arg( context , 1 ); - - test_assert_int_equal( 7 , run_arg_get_iter( run_arg1 )); - test_assert_string_equal( "/tmp/path/0002/7" , run_arg_get_runpath( run_arg1 )); - - test_assert_true( run_arg_is_instance( run_arg1 )); - } - ert_run_context_free( context ); - path_fmt_free( runpath_fmt ); - subst_list_free( subst_list ); - } - bool_vector_free( iactive ); -} - - - - -void test_iactive_update() { - bool_vector_type * iactive = bool_vector_alloc(10,true); - { - subst_list_type * subst_list = subst_list_alloc( NULL ); - path_fmt_type * runpath_fmt = path_fmt_alloc_directory_fmt("/tmp/path/%04d/%d"); - enkf_fs_type * fs = NULL; - ert_run_context_type * context = ert_run_context_alloc_ENSEMBLE_EXPERIMENT( fs, iactive , runpath_fmt , subst_list , 7 ); - - ert_run_context_deactivate_realization( context , 0 ); - ert_run_context_deactivate_realization( context , 5 ); - ert_run_context_deactivate_realization( context , 9 ); - - ert_run_context_free( context ); - path_fmt_free( runpath_fmt ); - subst_list_free( subst_list ); - } - test_assert_int_equal( bool_vector_count_equal( iactive , true ) , 7 ); - test_assert_false( bool_vector_iget( iactive , 0 )); - test_assert_false( bool_vector_iget( iactive , 5 )); - test_assert_false( bool_vector_iget( iactive , 9 )); - bool_vector_free( iactive ); -} - - -int main( int argc , char ** argv) { - test_create(); - test_create_ENSEMBLE_EXPERIMENT(); - test_iactive_update(); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_ert_test_context.c b/ThirdParty/Ert/libenkf/tests/enkf_ert_test_context.c deleted file mode 100644 index fcf97ab688..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_ert_test_context.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_ert_test_context.c' is part of ERT - Ensemble based - Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - - - -#include -#include - - - - -void test_create_invalid(const char * config_file) { - char * cwd0 = util_alloc_cwd(); - ert_test_context_type * test_context = ert_test_context_alloc("CREATE_CONTEXT" , config_file ); - test_assert_true( ert_test_context_is_instance( test_context )); - test_assert_NULL( ert_test_context_get_main( test_context )); - { - char * cwd1 = util_alloc_cwd(); - test_assert_string_equal(cwd1 , cwd0); - free( cwd1 ); - } - free( cwd0 ); - ert_test_context_free( test_context ); -} - - - -void test_create_valid( const char * config_file ) { - char * cwd0 = util_alloc_cwd(); - ert_test_context_type * test_context = ert_test_context_alloc("CREATE_CONTEXT" , config_file ); - test_assert_true( ert_test_context_is_instance( test_context )); - test_assert_true( enkf_main_is_instance( ert_test_context_get_main( test_context ))); - { - char * cwd1 = util_alloc_cwd(); - test_assert_string_not_equal(cwd1 , cwd0); - free( cwd1 ); - } - free( cwd0 ); - ert_test_context_free( test_context ); -} - - - -void test_install_job( const char * config_file, const char * job_file_OK , const char * job_file_ERROR) { - ert_test_context_type * test_context = ert_test_context_alloc("CREATE_CONTEXT_JOB" , config_file ); - - test_assert_false( ert_test_context_install_workflow_job( test_context , "JOB" , "File/does/not/exist")); - test_assert_false( ert_test_context_install_workflow_job( test_context , "ERROR" , job_file_ERROR)); - test_assert_true( ert_test_context_install_workflow_job( test_context , "OK" , job_file_OK)); - - ert_test_context_free( test_context ); -} - - - -void test_run_workflow_job( const char * config_file , const char * job_file ) { - ert_test_context_type * test_context = ert_test_context_alloc("CREATE_CONTEXT_JOB" , config_file ); - stringlist_type * args0 = stringlist_alloc_new( ); - stringlist_type * args1 = stringlist_alloc_new( ); - - stringlist_append_ref( args1 , "NewCase"); - test_assert_false( ert_test_context_run_worklow_job( test_context , "NO-this-does-not-exist" , args1)); - ert_test_context_install_workflow_job( test_context , "JOB" , job_file ); - - test_assert_false( ert_test_context_run_worklow_job( test_context , "JOB" , args0)); - test_assert_true( ert_test_context_run_worklow_job( test_context , "JOB" , args1)); - - stringlist_free( args0 ); - stringlist_free( args1 ); - ert_test_context_free( test_context ); -} - - -void test_install_workflow( const char * config_file , const char * job_file ) { - ert_test_context_type * test_context = ert_test_context_alloc("INSTALL_WORKFLOW" , config_file ); - const char * wf_file = "WFLOW"; - - ert_test_context_install_workflow_job( test_context , "JOB" , job_file ); - { - FILE * stream = util_fopen( wf_file , "w"); - stringlist_type * args = stringlist_alloc_new( ); - stringlist_append_ref( args , "NewCase"); - ert_test_context_fwrite_workflow_job( stream , "JOB" , args); - stringlist_free( args ); - fclose( stream ); - } - test_assert_true( ert_test_context_install_workflow( test_context , "WFLOW" , wf_file )); - ert_test_context_free( test_context ); -} - - -void test_run_workflow(const char * config_file , const char * job_file) { - ert_test_context_type * test_context = ert_test_context_alloc("INSTALL_WORKFLOW" , config_file ); - test_assert_false( ert_test_context_run_worklow( test_context , "No-does.not.exist")); - - ert_test_context_install_workflow_job( test_context , "JOB" , job_file ); - { - FILE * stream1 = util_fopen( "WFLOW1", "w"); - FILE * stream2 = util_fopen( "WFLOW2", "w"); - stringlist_type * args = stringlist_alloc_new( ); - ert_test_context_fwrite_workflow_job( stream1 , "JOB" , args); - stringlist_append_ref( args , "NewCase"); - ert_test_context_fwrite_workflow_job( stream2 , "JOB" , args); - - stringlist_free( args ); - fclose( stream1 ); - fclose( stream2 ); - } - test_assert_true( ert_test_context_install_workflow( test_context , "WFLOW1" , "WFLOW1")); - test_assert_true( ert_test_context_install_workflow( test_context , "WFLOW2" , "WFLOW2")); - - test_assert_true( ert_test_context_run_worklow( test_context , "WFLOW2")); - test_assert_false( ert_test_context_run_worklow( test_context , "WFLOW1")); - - ert_test_context_free( test_context ); -} - - - - - - -int main( int argc , char ** argv) { - char * config_file = argv[1]; - char * wf_job_fileOK = argv[2]; - char * wf_job_fileERROR = argv[3]; - - test_create_invalid( "DoesNotExist" ); - test_create_valid( config_file ); - test_install_job( config_file , wf_job_fileOK, wf_job_fileERROR ); - test_install_workflow( config_file , wf_job_fileOK); - test_run_workflow( config_file , wf_job_fileOK); - test_run_workflow_job( config_file , wf_job_fileOK); -} - - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_ert_workflow_list.c b/ThirdParty/Ert/libenkf/tests/enkf_ert_workflow_list.c deleted file mode 100644 index b6ea0e583d..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_ert_workflow_list.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_ert_workflow_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include - - - -void test_create_workflow_list() { - ert_workflow_list_type * wf_list = ert_workflow_list_alloc( NULL ); - test_assert_true( ert_workflow_list_is_instance( wf_list )); - ert_workflow_list_free( wf_list ); -} - - - -void test_add_alias( const char * job) { - test_work_area_type * work_area = test_work_area_alloc( "workflow_list/alias" ); - ert_workflow_list_type * wf_list = ert_workflow_list_alloc( NULL ); - ert_workflow_list_add_job( wf_list , "JOB" , job ); - - { - FILE * stream = util_fopen("WF1" , "w"); - fprintf(stream , "SCALE_STD 0.25\n"); - fclose(stream); - } - - - { - FILE * stream = util_fopen("WF2" , "w"); - fprintf(stream , "SCALE_STD 0.25\n"); - fclose(stream); - } - - test_assert_true( workflow_is_instance( ert_workflow_list_add_workflow( wf_list , "WF1" , "WF"))); - test_assert_int_equal( 1 , ert_workflow_list_get_size( wf_list )); - test_assert_false( ert_workflow_list_has_workflow( wf_list , "WF1")); - test_assert_true( ert_workflow_list_has_workflow( wf_list , "WF")); - - ert_workflow_list_add_alias( wf_list , "WF" , "alias"); - test_assert_int_equal( 2 , ert_workflow_list_get_size( wf_list )); - test_assert_true( ert_workflow_list_has_workflow( wf_list , "WF")); - test_assert_true( ert_workflow_list_has_workflow( wf_list , "alias")); - test_assert_true( workflow_is_instance( ert_workflow_list_get_workflow( wf_list , "WF"))); - test_assert_true( workflow_is_instance( ert_workflow_list_get_workflow( wf_list , "alias"))); - - test_assert_true( workflow_is_instance( ert_workflow_list_add_workflow( wf_list , "WF2" , "WF"))); - test_assert_int_equal( 2 , ert_workflow_list_get_size( wf_list )); - test_assert_true( ert_workflow_list_has_workflow( wf_list , "WF")); - test_assert_true( ert_workflow_list_has_workflow( wf_list , "alias")); - test_assert_true( workflow_is_instance( ert_workflow_list_get_workflow( wf_list , "WF"))); - test_assert_true( workflow_is_instance( ert_workflow_list_get_workflow( wf_list , "alias"))); - - test_work_area_free( work_area ); -} - - -int main(int argc , char ** argv) { - const char * job = argv[1]; - test_create_workflow_list(); - test_add_alias(job); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_export_field_test.c b/ThirdParty/Ert/libenkf/tests/enkf_export_field_test.c deleted file mode 100644 index c3fd8a3373..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_export_field_test.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_export_field_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - - - -void test_export_field(ert_test_context_type * test_context , const char * job_name , const char * job_file) { - - test_assert_true( ert_test_context_install_workflow_job( test_context , job_name , job_file )); - { - stringlist_type * args = stringlist_alloc_new(); - - stringlist_append_copy(args, "PERMZ"); - stringlist_append_copy(args, "TEST_EXPORT/test_export_field/PermZ%d.grdecl"); - stringlist_append_copy(args, "0"); - stringlist_append_copy(args, "FORECAST"); - stringlist_append_copy(args, "0, 2"); - - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - stringlist_free( args ); - } - test_assert_true( util_file_exists("TEST_EXPORT/test_export_field/PermZ0.grdecl") ); - test_assert_true( util_file_exists("TEST_EXPORT/test_export_field/PermZ2.grdecl") ); -} - - -void job_file_export_field_ecl_grdecl(ert_test_context_type * test_context , const char * job_name , const char * job_file) { - ert_test_context_install_workflow_job( test_context , job_name , job_file ); - { - stringlist_type * args = stringlist_alloc_new(); - - stringlist_append_copy(args, "PERMX"); - stringlist_append_copy(args, "TEST_EXPORT/test_export_field_ecl_grdecl/PermX%d.grdecl"); - stringlist_append_copy(args, "0"); - stringlist_append_copy(args, "ANALYZED"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_clear(args); - stringlist_append_copy(args, "PERMZ"); - stringlist_append_copy(args, "TEST_EXPORT/test_export_field_ecl_grdecl/PermZ%d"); - stringlist_append_copy(args, "0"); - stringlist_append_copy(args, "FORECAST"); - stringlist_append_copy(args, "0-1"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - - test_assert_true(util_file_exists("TEST_EXPORT/test_export_field_ecl_grdecl/PermX0.grdecl")); - test_assert_true(util_file_exists("TEST_EXPORT/test_export_field_ecl_grdecl/PermX1.grdecl")); - test_assert_true(util_file_exists("TEST_EXPORT/test_export_field_ecl_grdecl/PermX2.grdecl")); - - test_assert_true(util_file_exists("TEST_EXPORT/test_export_field_ecl_grdecl/PermZ0")); - test_assert_true(util_file_exists("TEST_EXPORT/test_export_field_ecl_grdecl/PermZ1")); - - stringlist_free( args ); - } -} - - -void job_file_export_field_rms_roff(ert_test_context_type * test_context , const char * job_name , const char * job_file) { - test_assert_true( ert_test_context_install_workflow_job( test_context , job_name , job_file ) ); - { - stringlist_type * args = stringlist_alloc_new(); - - stringlist_append_copy(args, "PERMZ"); - stringlist_append_copy(args, "TEST_EXPORT/test_export_field_rms_roff/PermZ%d"); - stringlist_append_copy(args, "0"); - stringlist_append_copy(args, "ANALYZED"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_clear(args); - stringlist_append_copy(args, "PERMX"); - stringlist_append_copy(args, "TEST_EXPORT/test_export_field_rms_roff/PermX%d.roff"); - stringlist_append_copy(args, "0"); - stringlist_append_copy(args, "FORECAST"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - test_assert_true(util_file_exists("TEST_EXPORT/test_export_field_rms_roff/PermZ0")); - test_assert_true(util_file_exists("TEST_EXPORT/test_export_field_rms_roff/PermZ1")); - test_assert_true(util_file_exists("TEST_EXPORT/test_export_field_rms_roff/PermZ2")); - - test_assert_true(util_file_exists("TEST_EXPORT/test_export_field_rms_roff/PermX0.roff")); - test_assert_true(util_file_exists("TEST_EXPORT/test_export_field_rms_roff/PermX1.roff")); - test_assert_true(util_file_exists("TEST_EXPORT/test_export_field_rms_roff/PermX2.roff")); - - stringlist_free( args ); - } -} - - - -int main(int argc , const char ** argv) { - enkf_main_install_SIGNALS(); - - const char * config_file = argv[1]; - const char * job_file_export_field = argv[2]; - const char * job_file_export_field_ecl_grdecl = argv[3]; - const char * job_file_export_field_rms_roff = argv[4]; - - ert_test_context_type * test_context = ert_test_context_alloc("ExportFieldsJobs" , config_file); - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - - enkf_main_select_fs( enkf_main , "default" ); - { - test_export_field(test_context, "JOB1" , job_file_export_field); - test_export_field(test_context, "JOB2" , job_file_export_field_ecl_grdecl); - test_export_field(test_context, "JOB3" , job_file_export_field_rms_roff); - } - ert_test_context_free( test_context ); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_export_inactive_cells.c b/ThirdParty/Ert/libenkf/tests/enkf_export_inactive_cells.c deleted file mode 100644 index 934826b289..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_export_inactive_cells.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_export_inactive_cells.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include - - - - -void check_exported_data(const char * exported_file, - const char * init_file, - field_file_format_type file_type, - const field_config_type * field_config, - const field_type * field, - int nx, - int ny, - int nz) { - - FILE * original_stream = NULL; - ecl_kw_type * kw_original = NULL; - FILE * exported_stream = NULL; - ecl_kw_type * kw_exported = NULL; - field_type * exported_field = NULL; - field_config_type * exported_field_config = NULL; - - { - if (init_file) { - original_stream = util_fopen( init_file , "r"); - kw_original = ecl_kw_fscanf_alloc_grdecl_dynamic( original_stream , field_config_get_key(field_config) , ECL_DOUBLE_TYPE ); - } - - if (ECL_GRDECL_FILE == file_type) { - exported_stream = util_fopen( exported_file , "r"); - kw_exported = ecl_kw_fscanf_alloc_grdecl_dynamic( exported_stream , field_config_get_key(field_config) , ECL_DOUBLE_TYPE ); - } else if (RMS_ROFF_FILE == file_type) { - ecl_grid_type * grid = field_config_get_grid(field_config); - exported_field_config = field_config_alloc_empty(field_config_get_key(field_config), grid, NULL, true); - exported_field = field_alloc(exported_field_config); - - bool keep_inactive = true; - field_fload_rms(exported_field, exported_file, keep_inactive); - } - } - - - { - int k, j, i = 0; - - for (k=0; k < nz; k++) { - for (j=0; j < ny; j++) { - for (i=0; i < nx; i++) { - bool active = field_config_active_cell(field_config, i, j, k); - double field_value = active ? field_ijk_get_double(field, i, j, k) : 0.0; - int global_index = field_config_global_index(field_config , i , j , k); - double exported_value = 0.0; - if (ECL_GRDECL_FILE == file_type) - exported_value = ecl_kw_iget_as_double(kw_exported, global_index); - else if (RMS_ROFF_FILE == file_type) { - exported_value = field_ijk_get_double(exported_field, i, j, k); - } - double initial_value = init_file ? ecl_kw_iget_as_double(kw_original, global_index) : 0.0; - - if (active) - test_assert_double_equal(field_value, exported_value); - else if (init_file) - test_assert_double_equal(initial_value, exported_value); - else if (file_type == RMS_ROFF_FILE) - test_assert_double_equal(RMS_INACTIVE_DOUBLE, exported_value); - else - test_assert_double_equal(0.0, exported_value); - } - } - } - } - - - if (init_file) { - util_fclose(original_stream); - ecl_kw_free(kw_original); - } - - if (ECL_GRDECL_FILE == file_type) { - util_fclose(exported_stream); - ecl_kw_free(kw_exported); - } else - field_free(exported_field); -} - - - -void forward_initialize_node(enkf_main_type * enkf_main, const char * init_file, enkf_node_type * field_node) { - { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc(0, false); - bool_vector_iset( iactive , ens_size - 1 , true ); - - enkf_main_create_run_path(enkf_main , iactive , 0); - bool_vector_free(iactive); - } - - { - int iens = 0; - enkf_state_type * state = enkf_main_iget_state( enkf_main , iens ); - enkf_fs_type * fs = enkf_main_get_fs(enkf_main); - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT( fs , 0 ,0 , "simulations/run0"); - - enkf_state_forward_init( state , run_arg); - } -} - - - -int main(int argc , char ** argv) { - enkf_main_install_SIGNALS(); - - const char * config_file = argv[1]; - const char * init_file = argv[2]; - const char * key = "PORO"; - int iens = 0; - - ert_test_context_type * test_context = ert_test_context_alloc("ExportInactiveCellsTest" , config_file); - enkf_main_type * enkf_main = ert_test_context_get_main(test_context); - enkf_fs_type * fs = enkf_main_get_fs(enkf_main); - const ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config(enkf_main); - enkf_config_node_type * config_node = ensemble_config_get_node(ensemble_config , key); - const field_config_type * field_config = enkf_config_node_get_ref( config_node ); - enkf_state_type * state = enkf_main_iget_state( enkf_main , iens ); - enkf_node_type * field_node = enkf_state_get_node( state , key ); - field_type * field = enkf_node_value_ptr(field_node); - - { - forward_initialize_node(enkf_main, init_file, field_node); - node_id_type node_id = {.report_step = 0 , .iens = iens }; - test_assert_true(enkf_node_try_load(field_node , fs , node_id)); - field_scale(field, 3.0); - } - - int nx,ny,nz; - field_config_get_dims(field_config , &nx , &ny , &nz); - const char * export_file_grdecl = "my_test_dir/exported_field_test_file_grdecl"; - const char * export_file_roff = "my_test_dir/exported_field_test_file_roff"; - field_file_format_type file_type; - model_config_type * mc = enkf_main_get_model_config(enkf_main); - path_fmt_type * runpath_fmt = model_config_get_runpath_fmt(mc); - const char * found_init_file = enkf_config_node_get_FIELD_fill_file(config_node, runpath_fmt); - { - file_type = ECL_GRDECL_FILE; - field_export(field, export_file_grdecl, NULL, file_type, false, found_init_file); - check_exported_data(export_file_grdecl, init_file, file_type, field_config, field, nx, ny, nz); - } - { - file_type = RMS_ROFF_FILE; - field_export(field, export_file_roff, NULL, file_type, false, found_init_file); - check_exported_data(export_file_roff, init_file, file_type, field_config, field, nx, ny, nz); - } - - found_init_file = NULL; - { - file_type = ECL_GRDECL_FILE; - field_export(field, export_file_grdecl, NULL, file_type, false, found_init_file); - check_exported_data(export_file_grdecl, found_init_file, file_type, field_config, field, nx, ny, nz); - } - { - file_type = RMS_ROFF_FILE; - field_export(field, export_file_roff, NULL, file_type, false, found_init_file); - check_exported_data(export_file_roff, found_init_file, file_type, field_config, field, nx, ny, nz); - } - - - - ert_test_context_free(test_context); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_forward_init_FIELD.c b/ThirdParty/Ert/libenkf/tests/enkf_forward_init_FIELD.c deleted file mode 100644 index b046029ca6..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_forward_init_FIELD.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_forward_init_FIELD.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - - -void create_runpath(enkf_main_type * enkf_main, int iter) { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc(0,false); - - bool_vector_iset( iactive , ens_size - 1 , true ); - enkf_main_create_run_path(enkf_main , iactive , iter); - bool_vector_free(iactive); -} - - - -int main(int argc , char ** argv) { - enkf_main_install_SIGNALS(); - const char * root_path = argv[1]; - const char * config_file = argv[2]; - const char * init_file = argv[3]; - const char * forward_init_string = argv[4]; - test_work_area_type * work_area = test_work_area_alloc(config_file ); - test_work_area_copy_directory_content( work_area , root_path ); - test_work_area_install_file( work_area , init_file ); - { - bool forward_init; - bool strict = true; - enkf_main_type * enkf_main; - - test_assert_true( util_sscanf_bool( forward_init_string , &forward_init)); - - util_clear_directory( "Storage" , true , true ); - enkf_main = enkf_main_bootstrap( config_file , strict , true ); - { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - enkf_node_type * field_node = enkf_state_get_node( state , "PORO" ); - { - const enkf_config_node_type * field_config_node = enkf_node_get_config( field_node ); - char * init_file1 = enkf_config_node_alloc_initfile( field_config_node , NULL , 0); - char * init_file2 = enkf_config_node_alloc_initfile( field_config_node , "/tmp", 0); - - test_assert_bool_equal( enkf_config_node_use_forward_init( field_config_node ) , forward_init ); - test_assert_string_equal( init_file1 , "petro.grdecl"); - test_assert_string_equal( init_file2 , "/tmp/petro.grdecl"); - - free( init_file1 ); - free( init_file2 ); - } - - test_assert_bool_equal( enkf_node_use_forward_init( field_node ) , forward_init ); - if (forward_init) - test_assert_bool_not_equal( enkf_node_initialize( field_node , 0 , enkf_state_get_rng( state )) , forward_init); - // else hard_failure() - } - test_assert_bool_equal( forward_init, ensemble_config_have_forward_init( enkf_main_get_ensemble_config( enkf_main ))); - - if (forward_init) { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - enkf_node_type * field_node = enkf_state_get_node( state , "PORO" ); - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT( fs , 0 ,0 , "simulations/run0"); - node_id_type node_id = {.report_step = 0 , - .iens = 0 }; - - create_runpath( enkf_main, 0 ); - test_assert_true( util_is_directory( "simulations/run0" )); - - { - int result; - stringlist_type * msg_list = stringlist_alloc_new(); - - - test_assert_false( enkf_node_has_data( field_node , fs, node_id )); - - util_unlink_existing( "simulations/run0/petro.grdecl" ); - - test_assert_false(enkf_node_forward_init(field_node, "simulations/run0", 0)); - result = enkf_state_forward_init(state, run_arg); - test_assert_true(LOAD_FAILURE & result); - - result = 0; - { - enkf_fs_type * fs = enkf_main_get_fs(enkf_main); - state_map_type * state_map = enkf_fs_get_state_map(fs); - state_map_iset(state_map, 0, STATE_INITIALIZED); - } - result = enkf_state_load_from_forward_model(state, run_arg , msg_list); - stringlist_free(msg_list); - test_assert_true(LOAD_FAILURE & result); - } - - - util_copy_file( init_file , "simulations/run0/petro.grdecl"); - { - int result; - stringlist_type * msg_list = stringlist_alloc_new(); - - test_assert_true( enkf_node_forward_init( field_node , "simulations/run0" , 0)); - result = enkf_state_forward_init( state , run_arg); - test_assert_int_equal( result, 0 ); - result = enkf_state_load_from_forward_model( state , run_arg , msg_list ); - - stringlist_free( msg_list ); - test_assert_int_equal(result , 0); - - { - double value; - test_assert_true( enkf_node_user_get( field_node , fs , "5,5,5" , node_id , &value)); - test_assert_double_equal( 0.28485405445 , value); - } - } - util_clear_directory( "simulations" , true , true ); - create_runpath( enkf_main, 0 ); - test_assert_true( util_is_directory( "simulations/run0" )); - test_assert_true( util_is_file( "simulations/run0/PORO.grdecl" )); - test_assert_true( enkf_node_fload( field_node , "simulations/run0/PORO.grdecl")); - { - double value; - test_assert_true( enkf_node_user_get( field_node , fs , "4,4,4" , node_id , &value)); - test_assert_double_equal( 0.130251303315 , value); - } - util_clear_directory( "simulations" , true , true ); - run_arg_free( run_arg ); - } - enkf_main_free( enkf_main ); - } -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_forward_init_GEN_KW.c b/ThirdParty/Ert/libenkf/tests/enkf_forward_init_GEN_KW.c deleted file mode 100644 index 5806bfce4b..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_forward_init_GEN_KW.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_forward_init_GEN_KW.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - - -void create_runpath(enkf_main_type * enkf_main, int iter ) { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc(0,false); - - bool_vector_iset( iactive , ens_size - 1 , true ); - enkf_main_create_run_path(enkf_main , iactive , iter); - bool_vector_free(iactive); -} - - -int main(int argc , char ** argv) { - enkf_main_install_SIGNALS(); - const char * root_path = argv[1]; - const char * config_file = argv[2]; - const char * forward_init_string = argv[3]; - test_work_area_type * work_area = test_work_area_alloc(config_file ); - test_work_area_copy_directory_content( work_area , root_path ); - { - bool forward_init; - bool strict = true; - enkf_main_type * enkf_main; - - test_assert_true( util_sscanf_bool( forward_init_string , &forward_init)); - - util_clear_directory( "Storage" , true , true ); - enkf_main = enkf_main_bootstrap( config_file , strict , true ); - { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - enkf_node_type * gen_kw_node = enkf_state_get_node( state , "MULTFLT" ); - { - const enkf_config_node_type * gen_kw_config_node = enkf_node_get_config( gen_kw_node ); - char * init_file1 = enkf_config_node_alloc_initfile( gen_kw_config_node , NULL , 0); - char * init_file2 = enkf_config_node_alloc_initfile( gen_kw_config_node , "/tmp", 0); - - test_assert_bool_equal( enkf_config_node_use_forward_init( gen_kw_config_node ) , forward_init ); - test_assert_string_equal( init_file1 , "MULTFLT_INIT"); - test_assert_string_equal( init_file2 , "/tmp/MULTFLT_INIT"); - - free( init_file1 ); - free( init_file2 ); - } - - test_assert_bool_equal( enkf_node_use_forward_init( gen_kw_node ) , forward_init ); - if (forward_init) - test_assert_bool_not_equal( enkf_node_initialize( gen_kw_node , 0 , enkf_state_get_rng( state )) , forward_init); - // else hard_failure() - } - test_assert_bool_equal( forward_init, ensemble_config_have_forward_init( enkf_main_get_ensemble_config( enkf_main ))); - - if (forward_init) { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT( fs , 0 , 0 , "simulations/run0"); - enkf_node_type * gen_kw_node = enkf_state_get_node( state , "MULTFLT" ); - node_id_type node_id = {.report_step = 0 , - .iens = 0 }; - - create_runpath( enkf_main, 0 ); - test_assert_true( util_is_directory( "simulations/run0" )); - - { - int error; - stringlist_type * msg_list = stringlist_alloc_new(); - bool_vector_type * iactive = bool_vector_alloc( enkf_main_get_ensemble_size( enkf_main ) , true); - - test_assert_false( enkf_node_has_data( gen_kw_node , fs, node_id )); - util_unlink_existing( "simulations/run0/MULTFLT_INIT" ); - - - test_assert_false( enkf_node_forward_init( gen_kw_node , "simulations/run0" , 0 )); - error = enkf_state_forward_init( state , run_arg ); - test_assert_true(LOAD_FAILURE & error); - - { - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - state_map_type * state_map = enkf_fs_get_state_map(fs); - state_map_iset(state_map , 0 , STATE_INITIALIZED); - } - error = enkf_state_load_from_forward_model( state , run_arg , msg_list ); - stringlist_free( msg_list ); - bool_vector_free( iactive ); - test_assert_true(LOAD_FAILURE & error); - } - - - - { - FILE * stream = util_fopen("simulations/run0/MULTFLT_INIT" , "w"); - fprintf(stream , "123456.0\n" ); - fclose( stream ); - } - - { - int error; - stringlist_type * msg_list = stringlist_alloc_new(); - - test_assert_true( enkf_node_forward_init( gen_kw_node , "simulations/run0" , 0 )); - error = enkf_state_forward_init( state , run_arg ); - test_assert_int_equal(0, error); - error = enkf_state_load_from_forward_model( state , run_arg , msg_list ); - - stringlist_free( msg_list ); - test_assert_int_equal(0, error); - - { - double value; - test_assert_true( enkf_node_user_get( gen_kw_node , fs , "MULTFLT" , node_id , &value)); - test_assert_double_equal( 123456.0 , value); - } - } - - test_assert_true( util_is_file ("simulations/run0/parameters.txt")); //Export of gen kw params - - util_clear_directory( "simulations" , true , true ); - create_runpath( enkf_main, 0 ); - test_assert_true( util_is_directory( "simulations/run0" )); - test_assert_true( util_is_file( "simulations/run0/MULTFLT.INC" )); - { - FILE * stream = util_fopen("simulations/run0/MULTFLT.INC" , "r"); - double value; - fscanf(stream , "%lg" , &value); - fclose( stream ); - test_assert_double_equal( 123456.0 , value); - } - util_clear_directory( "simulations" , true , true ); - run_arg_free( run_arg ); - } - enkf_main_free( enkf_main ); - } - test_work_area_free( work_area ); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_forward_init_GEN_PARAM.c b/ThirdParty/Ert/libenkf/tests/enkf_forward_init_GEN_PARAM.c deleted file mode 100644 index f29e0cab78..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_forward_init_GEN_PARAM.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_forward_init_GEN_PARAM.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - - -void create_runpath(enkf_main_type * enkf_main, int iter ) { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc(0,false); - - bool_vector_iset( iactive , ens_size - 1 , true ); - enkf_main_create_run_path(enkf_main , iactive , iter); - bool_vector_free(iactive); -} - - - -int main(int argc , char ** argv) { - enkf_main_install_SIGNALS(); - const char * root_path = argv[1]; - const char * config_file = argv[2]; - const char * forward_init_string = argv[3]; - test_work_area_type * work_area = test_work_area_alloc(config_file ); - test_work_area_copy_directory_content( work_area , root_path ); - { - bool forward_init; - bool strict = true; - enkf_main_type * enkf_main; - - test_assert_true( util_sscanf_bool( forward_init_string , &forward_init)); - - util_clear_directory( "Storage" , true , true ); - enkf_main = enkf_main_bootstrap( config_file , strict , true ); - { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - enkf_node_type * gen_param_node = enkf_state_get_node( state , "PARAM" ); - { - const enkf_config_node_type * gen_param_config_node = enkf_node_get_config( gen_param_node ); - char * init_file1 = enkf_config_node_alloc_initfile( gen_param_config_node , NULL , 0); - char * init_file2 = enkf_config_node_alloc_initfile( gen_param_config_node , "/tmp", 0); - - test_assert_bool_equal( enkf_config_node_use_forward_init( gen_param_config_node ) , forward_init ); - test_assert_string_equal( init_file1 , "PARAM_INIT"); - test_assert_string_equal( init_file2 , "/tmp/PARAM_INIT"); - - free( init_file1 ); - free( init_file2 ); - } - - test_assert_bool_equal( enkf_node_use_forward_init( gen_param_node ) , forward_init ); - if (forward_init) - test_assert_bool_not_equal( enkf_node_initialize( gen_param_node , 0 , enkf_state_get_rng( state )) , forward_init); - // else hard_failure() - } - test_assert_bool_equal( forward_init, ensemble_config_have_forward_init( enkf_main_get_ensemble_config( enkf_main ))); - - if (forward_init) { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT( fs , 0 , 0 , "simulations/run0"); - enkf_node_type * gen_param_node = enkf_state_get_node( state , "PARAM" ); - node_id_type node_id = {.report_step = 0 , - .iens = 0}; - - create_runpath( enkf_main, 0 ); - test_assert_true( util_is_directory( "simulations/run0" )); - - test_assert_false( enkf_node_has_data( gen_param_node , fs, node_id )); - util_unlink_existing( "simulations/run0/PARAM_INIT" ); - - { - FILE * stream = util_fopen("simulations/run0/PARAM_INIT" , "w"); - fprintf(stream , "0\n1\n2\n3\n" ); - fclose( stream ); - } - - { - int error; - stringlist_type * msg_list = stringlist_alloc_new(); - - test_assert_true( enkf_node_forward_init( gen_param_node , "simulations/run0" , 0 )); - - error = enkf_state_forward_init( state , run_arg ); - test_assert_int_equal(0, error); - { - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - state_map_type * state_map = enkf_fs_get_state_map(fs); - state_map_iset(state_map , 0 , STATE_INITIALIZED); - } - error = enkf_state_load_from_forward_model( state , run_arg , msg_list ); - - stringlist_free( msg_list ); - test_assert_int_equal(0, error); - - { - double value; - test_assert_true( enkf_node_user_get( gen_param_node , fs , "0" , node_id , &value)); - test_assert_double_equal( 0 , value); - - test_assert_true( enkf_node_user_get( gen_param_node , fs , "1" , node_id , &value)); - test_assert_double_equal( 1 , value); - - test_assert_true( enkf_node_user_get( gen_param_node , fs , "2" , node_id , &value)); - test_assert_double_equal( 2 , value); - } - } - util_clear_directory( "simulations" , true , true ); - create_runpath( enkf_main, 0 ); - test_assert_true( util_is_directory( "simulations/run0" )); - test_assert_true( util_is_file( "simulations/run0/PARAM.INC" )); - { - FILE * stream = util_fopen("simulations/run0/PARAM.INC" , "r"); - double v0,v1,v2,v3; - fscanf(stream , "%lg %lg %lg %lg" , &v0,&v1,&v2,&v3); - fclose( stream ); - test_assert_double_equal( 0 , v0); - test_assert_double_equal( 1 , v1); - test_assert_double_equal( 2 , v2); - test_assert_double_equal( 3 , v3); - } - util_clear_directory( "simulations" , true , true ); - run_arg_free( run_arg ); - } - enkf_main_free( enkf_main ); - } - test_work_area_free( work_area ); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_forward_init_SURFACE.c b/ThirdParty/Ert/libenkf/tests/enkf_forward_init_SURFACE.c deleted file mode 100644 index 92fe420906..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_forward_init_SURFACE.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_forward_init_SURFACE.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -void create_runpath(enkf_main_type * enkf_main, int iter ) { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc(0,false); - - bool_vector_iset( iactive , ens_size - 1 , true ); - enkf_main_create_run_path(enkf_main , iactive , iter); - bool_vector_free(iactive); -} - - - -int main(int argc , char ** argv) { - enkf_main_install_SIGNALS(); - const char * root_path = argv[1]; - const char * config_file = argv[2]; - const char * init_file = argv[3]; - const char * forward_init_string = argv[4]; - test_work_area_type * work_area = test_work_area_alloc(config_file ); - - test_work_area_copy_directory_content( work_area , root_path ); - test_work_area_install_file( work_area , init_file ); - { - - bool forward_init; - bool strict = true; - enkf_main_type * enkf_main; - - test_assert_true( util_sscanf_bool( forward_init_string , &forward_init)); - - util_clear_directory( "Storage" , true , true ); - enkf_main = enkf_main_bootstrap( config_file , strict , true ); - { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - enkf_node_type * surface_node = enkf_state_get_node( state , "SURFACE" ); - { - const enkf_config_node_type * surface_config_node = enkf_node_get_config( surface_node ); - char * init_file1 = enkf_config_node_alloc_initfile( surface_config_node , NULL , 0); - char * init_file2 = enkf_config_node_alloc_initfile( surface_config_node , "/tmp", 0); - - test_assert_bool_equal( enkf_config_node_use_forward_init( surface_config_node ) , forward_init ); - test_assert_string_equal( init_file1 , "Surface.irap"); - test_assert_string_equal( init_file2 , "/tmp/Surface.irap"); - - free( init_file1 ); - free( init_file2 ); - } - - test_assert_bool_equal( enkf_node_use_forward_init( surface_node ) , forward_init ); - if (forward_init) - test_assert_bool_not_equal( enkf_node_initialize( surface_node , 0 , enkf_state_get_rng( state )) , forward_init); - // else hard_failure() - } - test_assert_bool_equal( forward_init, ensemble_config_have_forward_init( enkf_main_get_ensemble_config( enkf_main ))); - - if (forward_init) { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT( fs , 0 ,0 , "simulations/run0"); - enkf_node_type * surface_node = enkf_state_get_node( state , "SURFACE" ); - node_id_type node_id = {.report_step = 0 , - .iens = 0 }; - - create_runpath( enkf_main, 0 ); - test_assert_true( util_is_directory( "simulations/run0" )); - - { - int error; - stringlist_type * msg_list = stringlist_alloc_new(); - - - test_assert_false( enkf_node_has_data( surface_node , fs, node_id )); - - util_unlink_existing( "simulations/run0/Surface.irap" ); - - test_assert_false( enkf_node_forward_init( surface_node , "simulations/run0" , 0 )); - error = enkf_state_forward_init( state , run_arg ); - test_assert_true(LOAD_FAILURE & error); - - { - enkf_fs_type * fs = enkf_main_get_fs(enkf_main); - state_map_type * state_map = enkf_fs_get_state_map(fs); - state_map_iset(state_map, 0, STATE_INITIALIZED); - } - error = enkf_state_load_from_forward_model(state, run_arg , msg_list); - stringlist_free( msg_list ); - test_assert_true(LOAD_FAILURE & error); - } - - - util_copy_file( init_file , "simulations/run0/Surface.irap"); - { - int error; - stringlist_type * msg_list = stringlist_alloc_new(); - - - test_assert_true( enkf_node_forward_init( surface_node , "simulations/run0" , 0 )); - error = enkf_state_forward_init( state , run_arg ); - test_assert_int_equal(0, error); - error = enkf_state_load_from_forward_model( state , run_arg , msg_list ); - stringlist_free( msg_list ); - test_assert_int_equal(0, error); - - { - double value; - test_assert_true( enkf_node_user_get( surface_node , fs , "0" , node_id , &value)); - test_assert_double_equal( 2735.7461 , value); - - test_assert_true( enkf_node_user_get( surface_node , fs , "5" , node_id , &value)); - test_assert_double_equal( 2737.0122 , value); - } - } - util_clear_directory( "simulations" , true , true ); - create_runpath( enkf_main, 0 ); - test_assert_true( util_is_directory( "simulations/run0" )); - test_assert_true( util_is_file( "simulations/run0/SURFACE.INC" )); - test_assert_true( enkf_node_fload( surface_node , "simulations/run0/SURFACE.INC")); - { - double value; - test_assert_true( enkf_node_user_get( surface_node , fs , "0" , node_id , &value)); - test_assert_double_equal( 2735.7461 , value); - - test_assert_true( enkf_node_user_get( surface_node , fs , "5" , node_id , &value)); - test_assert_double_equal( 2737.0122 , value); - } - util_clear_directory( "simulations" , true , true ); - } - enkf_main_free( enkf_main ); - } -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_forward_init_transform.c b/ThirdParty/Ert/libenkf/tests/enkf_forward_init_transform.c deleted file mode 100644 index d1cb969763..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_forward_init_transform.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_forward_init_transform.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include - - - - - - -void create_runpath(enkf_main_type * enkf_main, int iter ) { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc(0,false); - - bool_vector_iset( iactive , ens_size - 1 , true ); - enkf_main_create_run_path(enkf_main , iactive , iter); - bool_vector_free(iactive); -} - - -bool check_original_exported_data_equal(const enkf_node_type * field_node) { - FILE * original_stream = util_fopen( "petro.grdecl" , "r"); - ecl_kw_type * kw_original = ecl_kw_fscanf_alloc_grdecl_dynamic( original_stream , "PORO" , ECL_DOUBLE_TYPE ); - - enkf_node_ecl_write(field_node, "tmp", NULL, 0); - FILE * exported_stream = util_fopen( "tmp/PORO.grdecl" , "r"); - ecl_kw_type * kw_exported = ecl_kw_fscanf_alloc_grdecl_dynamic( exported_stream , "PORO" , ECL_DOUBLE_TYPE ); - - bool ret = ecl_kw_numeric_equal(kw_original, kw_exported, 1e-5 , 1e-5); - - util_fclose(original_stream); - util_fclose(exported_stream); - ecl_kw_free(kw_original); - ecl_kw_free(kw_exported); - - return ret; -} - - -int main(int argc , char ** argv) { - enkf_main_install_SIGNALS(); - const char * root_path = argv[1]; - const char * config_file = argv[2]; - const char * init_file = argv[3]; - const char * forward_init_string = argv[4]; - - test_work_area_type * work_area = test_work_area_alloc(config_file ); - test_work_area_copy_directory_content( work_area , root_path ); - test_work_area_install_file( work_area , init_file ); - test_work_area_set_store(work_area, true); - - bool strict = true; - enkf_main_type * enkf_main = enkf_main_bootstrap( config_file , strict , true ); - enkf_fs_type * init_fs = enkf_main_get_fs(enkf_main); - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT( init_fs , 0 ,0 , "simulations/run0"); - enkf_node_type * field_node = enkf_state_get_node( state , "PORO" ); - - bool forward_init; - test_assert_true( util_sscanf_bool( forward_init_string , &forward_init)); - test_assert_bool_equal( enkf_node_use_forward_init( field_node ) , forward_init ); - test_assert_bool_equal( forward_init, ensemble_config_have_forward_init( enkf_main_get_ensemble_config( enkf_main ))); - - util_clear_directory( "Storage" , true , true ); - - create_runpath( enkf_main, 0 ); - test_assert_true( util_is_directory( "simulations/run0" )); - - if (forward_init) - util_copy_file( init_file , "simulations/run0/petro.grdecl"); - - { - bool_vector_type * iactive = bool_vector_alloc( enkf_main_get_ensemble_size(enkf_main) , true); - int error; - stringlist_type * msg_list = stringlist_alloc_new(); - error = enkf_state_load_from_forward_model( state , run_arg , msg_list ); - stringlist_free( msg_list ); - bool_vector_free( iactive ); - test_assert_int_equal(error, 0); - } - - test_assert_true(check_original_exported_data_equal(field_node)); - - run_arg_free( run_arg ); - enkf_main_free(enkf_main); - test_work_area_free(work_area); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_forward_load_context.c b/ThirdParty/Ert/libenkf/tests/enkf_forward_load_context.c deleted file mode 100644 index 0163e2f330..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_forward_load_context.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'forward_load_context.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - -#include -#include - - -void test_update_result() { - forward_load_context_type * load_context = forward_load_context_alloc( NULL , false , NULL , NULL , NULL); - test_assert_int_equal( forward_load_context_get_result( load_context ) , 0 ); - forward_load_context_update_result( load_context , 1 ); - test_assert_int_equal( forward_load_context_get_result( load_context ) , 1 ); - - forward_load_context_update_result( load_context , 1 ); - test_assert_int_equal( forward_load_context_get_result( load_context ) , 1 ); - - forward_load_context_update_result( load_context , 2 ); - test_assert_int_equal( forward_load_context_get_result( load_context ) , 3 ); - - forward_load_context_update_result( load_context , 5 ); - test_assert_int_equal( forward_load_context_get_result( load_context ) , 7 ); - - forward_load_context_free( load_context ); -} - -void test_create() { - forward_load_context_type * load_context = forward_load_context_alloc( NULL , false , NULL , NULL , NULL); - test_assert_true( forward_load_context_is_instance( load_context )); - forward_load_context_free( load_context ); -} - -void test_load_restart1() { - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(NULL , 0 , 0 , "run"); - ecl_config_type * ecl_config = ecl_config_alloc( ); - forward_load_context_type * load_context = forward_load_context_alloc( run_arg , false , ecl_config , "BASE" , NULL ); - - test_assert_false( forward_load_context_load_restart_file( load_context , 10 )); - - forward_load_context_free( load_context ); - ecl_config_free( ecl_config ); - run_arg_free( run_arg ); -} - - -void make_restart_mock( const char * path , const char * eclbase , int report_step) { - char * filename = ecl_util_alloc_filename( path , eclbase , ECL_RESTART_FILE , false , report_step ); - ecl_kw_type * kw = ecl_kw_alloc( "KW" , 100 , ECL_FLOAT_TYPE); - fortio_type * f = fortio_open_writer( filename , false , true ); - ecl_kw_fwrite( kw , f ); - fortio_fclose( f ); - ecl_kw_free( kw ); - free( filename ); -} - -void test_load_restart2() { - test_work_area_type * work_area = test_work_area_alloc("forward_load"); - { - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(NULL , 0 , 0 , "run"); - ecl_config_type * ecl_config = ecl_config_alloc( ); - forward_load_context_type * load_context = forward_load_context_alloc( run_arg , false , ecl_config , "BASE" , NULL ); - util_make_path("run"); - make_restart_mock( "run" , "BASE" , 1 ); - make_restart_mock( "run" , "BASE" , 3 ); - - test_assert_false( forward_load_context_load_restart_file( load_context , 0 )); - test_assert_true( forward_load_context_load_restart_file( load_context , 1 )); - test_assert_false( forward_load_context_load_restart_file( load_context , 2 )); - test_assert_true( forward_load_context_load_restart_file( load_context , 3 )); - - forward_load_context_free( load_context ); - ecl_config_free( ecl_config ); - run_arg_free( run_arg ); - } - test_work_area_free( work_area ); -} - - - -void test_add_message() { - { - forward_load_context_type * load_context = forward_load_context_alloc( NULL , false , NULL , NULL , NULL); - forward_load_context_add_message( load_context , "MESSAGE" ); - test_assert_false( forward_load_context_accept_messages( load_context )); - forward_load_context_free( load_context ); - } - - { - stringlist_type * message_list = stringlist_alloc_new( ); - forward_load_context_type * load_context = forward_load_context_alloc( NULL , false , NULL , NULL , message_list ); - - test_assert_true( forward_load_context_accept_messages( load_context )); - forward_load_context_add_message( load_context , "MESSAGE1" ); - forward_load_context_add_message( load_context , "MESSAGE2" ); - forward_load_context_free( load_context ); - - test_assert_int_equal( 2 , stringlist_get_size( message_list )); - test_assert_string_equal( stringlist_iget( message_list , 0 ) , "MESSAGE1" ); - test_assert_string_equal( stringlist_iget( message_list , 1 ) , "MESSAGE2" ); - stringlist_free( message_list ); - } -} - - - - -int main(int argc , char ** argv) { - util_install_signals(); - test_create(); - test_load_restart1(); - test_load_restart2(); - test_add_message(); - test_update_result(); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_fs.c b/ThirdParty/Ert/libenkf/tests/enkf_fs.c deleted file mode 100644 index 9447bc8c16..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_fs.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_fs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ert/util/build_config.h" - -#include -#include -#include -#include - - -typedef struct -{ - pthread_mutex_t mutex1; - pthread_mutex_t mutex2; -} shared_data; - -static shared_data* data = NULL; - -void test_mount() { - test_work_area_type * work_area = test_work_area_alloc("enkf_fs/mount"); - - test_assert_false( enkf_fs_exists( "mnt" )); - test_assert_NULL( enkf_fs_create_fs("mnt" , BLOCK_FS_DRIVER_ID , NULL , false)); - test_assert_true( enkf_fs_exists( "mnt" )); - { - enkf_fs_type * fs = enkf_fs_mount( "mnt" ); - test_assert_true( util_file_exists("mnt/mnt.lock")); - test_assert_true( enkf_fs_is_instance( fs )); - enkf_fs_decref( fs ); - test_assert_false( util_file_exists("mnt/mnt.lock")); - } - { - enkf_fs_type * fs = enkf_fs_create_fs( "mnt2" , BLOCK_FS_DRIVER_ID , NULL , true); - test_assert_true( enkf_fs_is_instance( fs )); - enkf_fs_decref( fs ); - } - - - test_work_area_free( work_area ); -} - -void test_refcount() { - test_work_area_type * work_area = test_work_area_alloc("enkf_fs/refcount"); - - enkf_fs_create_fs("mnt" , BLOCK_FS_DRIVER_ID , NULL , false); - { - enkf_fs_type * fs = enkf_fs_mount( "mnt" ); - test_assert_int_equal( 1 , enkf_fs_get_refcount( fs )); - enkf_fs_decref( fs ); - } - test_work_area_free( work_area ); -} - -void createFS() { - - pthread_mutex_lock(&data->mutex1); - pid_t pid = fork(); - - if (pid == 0) { - enkf_fs_type * fs_false = enkf_fs_mount( "mnt" ); - test_assert_false(enkf_fs_is_read_only(fs_false)); - test_assert_true( util_file_exists("mnt/mnt.lock")); - pthread_mutex_unlock(&data->mutex1); - pthread_mutex_lock(&data->mutex2); - enkf_fs_decref( fs_false ); - pthread_mutex_unlock(&data->mutex2); - exit(0); - } -} - -void test_fwrite_readonly( void * arg ) { - enkf_fs_type * fs = enkf_fs_safe_cast( arg ); - /* - The arguments here are completely bogus; the important thing is - that this fwrite call should be intercepted by a util_abort() - call (which is again intercepted by the testing function) before - the argument are actually accessed. - */ - enkf_fs_fwrite_node( fs , NULL , "KEY" , PARAMETER , 100 , 1 ); -} - -void initialise_shared() -{ - // place our shared data in shared memory - int prot = PROT_READ | PROT_WRITE; -#ifdef __linux - int flags = MAP_SHARED | MAP_ANONYMOUS; -#elif __APPLE__ - int flags = MAP_SHARED | MAP_ANON; -#endif - - data = mmap(NULL, sizeof(shared_data), prot, flags, -1, 0); - assert(data); - - // initialise mutex so it works properly in shared memory - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); - pthread_mutex_init(&data->mutex1, &attr); - pthread_mutex_init(&data->mutex2, &attr); -} - -/* - This test needs to fork off a seperate process to test the cross-process file locking. -*/ -void test_read_only2() { - initialise_shared(); - test_work_area_type * work_area = test_work_area_alloc("enkf_fs/read_only2"); - enkf_fs_create_fs("mnt" , BLOCK_FS_DRIVER_ID , NULL , false); - pthread_mutex_lock(&data->mutex2); - createFS(); - pthread_mutex_lock(&data->mutex1); - { - enkf_fs_type * fs_false = enkf_fs_mount( "mnt" ); - test_assert_true(enkf_fs_is_read_only(fs_false)); - test_assert_util_abort( "enkf_fs_fwrite_node" , test_fwrite_readonly , fs_false ); - enkf_fs_decref( fs_false ); - } - pthread_mutex_unlock(&data->mutex2); - pthread_mutex_unlock(&data->mutex1); - pthread_mutex_lock(&data->mutex2); - test_work_area_free( work_area ); - pthread_mutex_unlock(&data->mutex2); - munmap(data, sizeof(data)); -} - -int main(int argc, char ** argv) { - test_mount(); - test_refcount(); - test_read_only2(); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_gen_data_config.c b/ThirdParty/Ert/libenkf/tests/enkf_gen_data_config.c deleted file mode 100644 index cb6049e650..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_gen_data_config.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_gen_data_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include -#include - -#include "ert/util/build_config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - - -void test_report_steps_param() { - - gen_data_config_type * config = gen_data_config_alloc_GEN_PARAM("KEY" , ASCII , ASCII); - test_assert_false( gen_data_config_is_dynamic( config )); - test_assert_int_equal( 0 , gen_data_config_num_report_step( config )); - test_assert_false( gen_data_config_has_report_step( config , 0 )); - - /* Add to parameter should fail. */ - gen_data_config_add_report_step( config , 10 ); - test_assert_int_equal( 0 , gen_data_config_num_report_step( config )); - test_assert_false( gen_data_config_has_report_step( config , 10 )); - - /* Add to parameter should fail. */ - gen_data_config_set_active_report_steps_from_string( config , "0-9,100"); - test_assert_int_equal( 0 , gen_data_config_num_report_step( config )); - test_assert_false( gen_data_config_has_report_step( config , 10 )); - - - gen_data_config_free( config ); -} - - -void test_report_steps_dynamic() { - gen_data_config_type * config = gen_data_config_alloc_GEN_DATA_result("KEY" , ASCII); - test_assert_true( gen_data_config_is_dynamic( config )); - test_assert_int_equal( 0 , gen_data_config_num_report_step( config )); - test_assert_false( gen_data_config_has_report_step( config , 0 )); - - gen_data_config_add_report_step( config , 10 ); - test_assert_int_equal( 1 , gen_data_config_num_report_step( config )); - test_assert_true( gen_data_config_has_report_step( config , 10 )); - test_assert_int_equal( gen_data_config_iget_report_step( config , 0 ) , 10); - - gen_data_config_add_report_step( config , 10 ); - test_assert_int_equal( 1 , gen_data_config_num_report_step( config )); - test_assert_true( gen_data_config_has_report_step( config , 10 )); - - - gen_data_config_add_report_step( config , 5 ); - test_assert_int_equal( 2 , gen_data_config_num_report_step( config )); - test_assert_true( gen_data_config_has_report_step( config , 10 )); - test_assert_int_equal( gen_data_config_iget_report_step( config , 0 ) , 5); - test_assert_int_equal( gen_data_config_iget_report_step( config , 1 ) , 10); - - { - const int_vector_type * active_steps = gen_data_config_get_active_report_steps( config ); - - test_assert_int_equal( int_vector_iget( active_steps , 0 ) , 5); - test_assert_int_equal( int_vector_iget( active_steps , 1 ) , 10); - } - - gen_data_config_set_active_report_steps_from_string( config , "0-3,7-10,100"); // 0,1,2,3,7,8,9,10,100 - test_assert_int_equal( 9 , gen_data_config_num_report_step( config )); - test_assert_int_equal( 0 , gen_data_config_iget_report_step( config , 0 )); - test_assert_int_equal( 3 , gen_data_config_iget_report_step( config , 3)); - test_assert_int_equal( 9 , gen_data_config_iget_report_step( config , 6)); - test_assert_int_equal( 100 , gen_data_config_iget_report_step( config , 8)); - - gen_data_config_free( config ); -} - - -void test_gendata_fload(const char * filename) { - test_work_area_type * work_area = test_work_area_alloc( "test_gendata_fload"); - gen_data_config_type * config = gen_data_config_alloc_GEN_DATA_result("KEY" , ASCII); - gen_data_type * gen_data = gen_data_alloc(config); - - const char * cwd = test_work_area_get_cwd(work_area); - enkf_fs_type * write_fs = enkf_fs_create_fs(cwd, BLOCK_FS_DRIVER_ID, NULL , true); - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(write_fs , 0,0,"path"); - forward_load_context_type * load_context = forward_load_context_alloc( run_arg , false , NULL , NULL , NULL); - forward_load_context_select_step(load_context , 0 ); - gen_data_fload_with_report_step(gen_data, filename , load_context); - int data_size = gen_data_config_get_data_size(config, 0); - test_assert_true(data_size > 0); - enkf_fs_decref( write_fs ); - - gen_data_free(gen_data); - gen_data_config_free( config ); - test_work_area_free(work_area); - run_arg_free( run_arg ); - forward_load_context_free( load_context ); -} - - -void test_gendata_fload_empty_file(const char * filename) { - test_work_area_type * work_area = test_work_area_alloc( "test_gendata_fload_empty_file" ); - gen_data_config_type * config = gen_data_config_alloc_GEN_DATA_result("KEY" , ASCII); - gen_data_type * gen_data = gen_data_alloc(config); - const char * cwd = test_work_area_get_cwd(work_area); - enkf_fs_type * write_fs = enkf_fs_create_fs(cwd, BLOCK_FS_DRIVER_ID, NULL , true); - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(write_fs , 0,0,"path"); - forward_load_context_type * load_context = forward_load_context_alloc( run_arg , false , NULL , NULL , NULL); - - forward_load_context_select_step(load_context , 0 ); - gen_data_fload_with_report_step(gen_data, filename, load_context); - int data_size = gen_data_config_get_data_size(config, 0); - test_assert_true(data_size == 0); - enkf_fs_decref( write_fs ); - - gen_data_free(gen_data); - gen_data_config_free( config ); - test_work_area_free(work_area); - run_arg_free( run_arg ); - forward_load_context_free( load_context ); -} - - -void test_result_format() { - test_assert_true( gen_data_config_valid_result_format("path/file%d/extra")); - test_assert_true( gen_data_config_valid_result_format("file%04d")); - test_assert_false( gen_data_config_valid_result_format("/path/file%04d")); - - test_assert_false( gen_data_config_valid_result_format("/path/file%s")); - test_assert_false( gen_data_config_valid_result_format("/path/file")); - test_assert_false( gen_data_config_valid_result_format("/path/file%f")); - - test_assert_false( gen_data_config_valid_result_format(NULL)); -} - - -void alloc_invalid_io_format1( void * arg) { - gen_data_config_type * config = gen_data_config_alloc_GEN_DATA_result("KEY" , ASCII_TEMPLATE ); - gen_data_config_free( config ); -} - - -void alloc_invalid_io_format2( void * arg) { - gen_data_config_type * config = gen_data_config_alloc_GEN_DATA_state("KEY" , GEN_DATA_UNDEFINED , ASCII); - gen_data_config_free( config ); -} - - -void alloc_invalid_io_format3( void *arg) { - gen_data_config_type * config = gen_data_config_alloc_GEN_PARAM("KEY" , ASCII , ASCII_TEMPLATE ); - gen_data_config_free( config ); -} - - - -void test_set_invalid_format() { - test_assert_util_abort( "gen_data_config_alloc_GEN_DATA_result" , alloc_invalid_io_format1 , NULL); - test_assert_util_abort( "gen_data_config_alloc_GEN_DATA_state" , alloc_invalid_io_format2 , NULL); - test_assert_util_abort( "gen_data_config_alloc_GEN_PARAM" , alloc_invalid_io_format3 , NULL); -} - - -void test_format_check() { - test_assert_int_equal( GEN_DATA_UNDEFINED , gen_data_config_check_format( NULL )); - test_assert_int_equal( GEN_DATA_UNDEFINED , gen_data_config_check_format("Error?")); - test_assert_int_equal( ASCII , gen_data_config_check_format("ASCII")); - test_assert_int_equal( ASCII_TEMPLATE , gen_data_config_check_format("ASCII_TEMPLATE")); - test_assert_int_equal( BINARY_DOUBLE , gen_data_config_check_format("BINARY_DOUBLE")); - test_assert_int_equal( BINARY_FLOAT , gen_data_config_check_format("BINARY_FLOAT")); -} - - -void test_set_template_invalid() { - test_work_area_type * work_area = test_work_area_alloc("GEN_DATA_SET_TEMPLATE_INVALID"); - gen_data_config_type * config = gen_data_config_alloc_GEN_PARAM("KEY" , ASCII , ASCII); - - test_assert_false( gen_data_config_set_template( config , "does/not/exist" , NULL ) ); - - { - FILE * stream = util_fopen("template.txt" , "w"); - fprintf(stream , "Header1\n\nHeader2\n"); - fclose( stream ); - - gen_data_config_set_template( config , "template.txt" , ""); - test_assert_string_equal( "template.txt" , gen_data_config_get_template_file( config )); - test_assert_string_equal( "" , gen_data_config_get_template_key( config )); - - - { - char * buffer; - int data_offset , buffer_size , data_skip; - gen_data_config_get_template_data( config , &buffer , &data_offset , &buffer_size , &data_skip); - - test_assert_string_equal( buffer , "Header1\n\nHeader2\n"); - test_assert_int_equal( data_offset , 8 ); - test_assert_int_equal( buffer_size , 22 ); - test_assert_int_equal( data_skip , 5 ); - } - } - - - { - FILE * stream = util_fopen("template2.txt" , "w"); - fprintf(stream , "Template XYZ - lots of shit .... \n"); - fclose( stream ); - - test_assert_false( gen_data_config_set_template( config , "template2.txt" , "")); - - test_assert_string_equal( "template.txt" , gen_data_config_get_template_file( config )); - test_assert_string_equal( "" , gen_data_config_get_template_key( config )); - { - char * buffer; - int data_offset , buffer_size , data_skip; - gen_data_config_get_template_data( config , &buffer , &data_offset , &buffer_size , &data_skip); - - test_assert_string_equal( buffer , "Header1\n\nHeader2\n"); - test_assert_int_equal( data_offset , 8 ); - test_assert_int_equal( buffer_size , 22 ); - test_assert_int_equal( data_skip , 5 ); - } - } - - gen_data_config_free( config ); - test_work_area_free( work_area ); -} - - - -void test_set_template() { - test_work_area_type * work_area = test_work_area_alloc("GEN_DATA_SET_TEMPLATE"); - { - gen_data_config_type * config = gen_data_config_alloc_GEN_PARAM("KEY" , ASCII , ASCII); - - test_assert_true( gen_data_config_set_template( config , NULL , NULL ) ); - test_assert_NULL( gen_data_config_get_template_file( config )); - test_assert_NULL( gen_data_config_get_template_key( config )); - - { - char * buffer; - int data_offset , buffer_size , data_skip; - gen_data_config_get_template_data( config , &buffer , &data_offset , &buffer_size , &data_skip); - - test_assert_NULL( buffer ); - test_assert_int_equal( data_offset , 0 ); - test_assert_int_equal( buffer_size , 0 ); - test_assert_int_equal( data_skip , 0 ); - } - - - { - FILE * stream = util_fopen("template.txt" , "w"); - fprintf(stream , "Header\n"); - fclose( stream ); - - test_assert_true( gen_data_config_set_template( config , "template.txt" , NULL )); - test_assert_string_equal( "template.txt" , gen_data_config_get_template_file( config )); - test_assert_NULL( gen_data_config_get_template_key( config )); - - - { - char * buffer; - int data_offset , buffer_size , data_skip; - gen_data_config_get_template_data( config , &buffer , &data_offset , &buffer_size , &data_skip); - - test_assert_string_equal( buffer , "Header\n"); - test_assert_int_equal( data_offset , 7 ); - test_assert_int_equal( buffer_size , 7 ); - test_assert_int_equal( data_skip , 0 ); - } - } - - { - FILE * stream = util_fopen("template.txt" , "w"); - fprintf(stream , "Header1\n\nHeader2\n"); - fclose( stream ); - - gen_data_config_set_template( config , "template.txt" , ""); - test_assert_string_equal( "template.txt" , gen_data_config_get_template_file( config )); - test_assert_string_equal( "" , gen_data_config_get_template_key( config )); - - - { - char * buffer; - int data_offset , buffer_size , data_skip; - gen_data_config_get_template_data( config , &buffer , &data_offset , &buffer_size , &data_skip); - - test_assert_string_equal( buffer , "Header1\n\nHeader2\n"); - test_assert_int_equal( data_offset , 8 ); - test_assert_int_equal( buffer_size , 22 ); - test_assert_int_equal( data_skip , 5 ); - } - } - - - gen_data_config_set_template( config , NULL , NULL ); - test_assert_NULL( gen_data_config_get_template_file( config )); - test_assert_NULL( gen_data_config_get_template_key( config )); - - { - char * buffer; - int data_offset , buffer_size , data_skip; - gen_data_config_get_template_data( config , &buffer , &data_offset , &buffer_size , &data_skip); - - test_assert_NULL( buffer ); - test_assert_int_equal( data_offset , 0 ); - test_assert_int_equal( buffer_size , 0 ); - test_assert_int_equal( data_skip , 0 ); - } - - - test_assert_true( gen_data_config_set_template( config , NULL , "KEY")); - test_assert_NULL( gen_data_config_get_template_file( config )); - test_assert_NULL( gen_data_config_get_template_key( config )); - - { - char * buffer; - int data_offset , buffer_size , data_skip; - gen_data_config_get_template_data( config , &buffer , &data_offset , &buffer_size , &data_skip); - - test_assert_NULL( buffer ); - test_assert_int_equal( data_offset , 0 ); - test_assert_int_equal( buffer_size , 0 ); - test_assert_int_equal( data_skip , 0 ); - } - - - gen_data_config_free( config ); - } - test_work_area_free( work_area ); -} - - -int main(int argc , char ** argv) { - - const char * gendata_file = argv[1]; - const char * gendata_file_empty = argv[2]; - util_install_signals(); - - test_report_steps_param(); - test_report_steps_dynamic(); - test_result_format(); - test_set_template(); - test_set_template_invalid(); - test_set_invalid_format(); - test_format_check(); - test_gendata_fload(gendata_file); - test_gendata_fload_empty_file(gendata_file_empty); - - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_gen_data_config_parse.c b/ThirdParty/Ert/libenkf/tests/enkf_gen_data_config_parse.c deleted file mode 100644 index 2d9de2ba9e..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_gen_data_config_parse.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_gen_data_config_parse.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - - -enkf_config_node_type * parse_alloc_GEN_PARAM( const char * config_string , bool parse_valid) { - config_parser_type * config = config_alloc(); - enkf_config_node_type * enkf_config_node = NULL; - - enkf_config_node_add_GEN_PARAM_config_schema( config ); - { - FILE * stream = util_fopen("config.txt" , "w"); - fprintf(stream , config_string); - fclose( stream ); - } - - { - config_content_type * content = config_parse( config , "config.txt" , "--" , NULL , NULL , NULL , CONFIG_UNRECOGNIZED_IGNORE , true); - - test_assert_bool_equal( parse_valid , config_content_is_valid( content )); - if (parse_valid) { - const config_content_item_type * config_item = config_content_get_item( content , GEN_PARAM_KEY ); - const config_content_node_type * config_node = config_content_item_iget_node( config_item , 0 ); - - enkf_config_node = enkf_config_node_alloc_GEN_PARAM_from_config( config_node ); - } - config_content_free( content ); - config_free( config ); - } - return enkf_config_node; -} - - - - - -void test_parse_gen_param() { - test_work_area_type * work_area = test_work_area_alloc("GEN_PARAM_parse"); - - // Parse error: missing eclfile - { - enkf_config_node_type * config_node = parse_alloc_GEN_PARAM( "GEN_PARAM KEY\n" , false); - test_assert_NULL( config_node ); - } - - // Missing all required KEY: arguments - { - enkf_config_node_type * config_node = parse_alloc_GEN_PARAM( "GEN_PARAM KEY ECLFILE\n" , true); - test_assert_NULL( config_node ); - } - - - // OUTPUT_FORMAT: Is incorrectly spelled - { - enkf_config_node_type * config_node = parse_alloc_GEN_PARAM( "GEN_PARAM KEY ECLFILE INIT_FILES:XXX INPUT_FORMAT:ASCII OutPutFOrmat:ASCII\n" , true); - test_assert_NULL( config_node ); - } - - - // OUTPUT_FORMAT: ASCII is incorrectly spelled - { - enkf_config_node_type * config_node = parse_alloc_GEN_PARAM( "GEN_PARAM KEY ECLFILE INIT_FILES:XXX INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCI\n" , true); - test_assert_NULL( config_node ); - } - - // Invalid value for INPUT_FORMAT - { - enkf_config_node_type * config_node = parse_alloc_GEN_PARAM( "GEN_PARAM KEY ECLFILE INIT_FILES:XXX INPUT_FORMAT:ASCII_TEMPLATE OUTPUT_FORMAT:ASCII\n" , true); - test_assert_NULL( config_node ); - } - - - // Correct - { - enkf_config_node_type * config_node = parse_alloc_GEN_PARAM( "GEN_PARAM KEY ECLFILE INPUT_FORMAT:BINARY_DOUBLE OUTPUT_FORMAT:ASCII INIT_FILES:INIT%%d\n" , true); - - test_assert_string_equal( "ECLFILE" , enkf_config_node_get_enkf_outfile( config_node )); - test_assert_NULL( enkf_config_node_get_enkf_infile( config_node )); - test_assert_string_equal( "INIT%d" , enkf_config_node_get_init_file_fmt( config_node )); - test_assert_int_equal( PARAMETER , enkf_config_node_get_var_type( config_node )); - { - gen_data_config_type * gen_data_config = enkf_config_node_get_ref( config_node ); - test_assert_int_equal( BINARY_DOUBLE , gen_data_config_get_input_format( gen_data_config )); - test_assert_int_equal( ASCII , gen_data_config_get_output_format( gen_data_config )); - } - - enkf_config_node_free( config_node ); - } - - test_work_area_free( work_area ); -} - - - -enkf_config_node_type * parse_alloc_GEN_DATA_result( const char * config_string , bool parse_valid) { - config_parser_type * config = config_alloc(); - enkf_config_node_type * enkf_config_node = NULL; - - enkf_config_node_add_GEN_DATA_config_schema( config ); - { - FILE * stream = util_fopen("config.txt" , "w"); - fprintf(stream , config_string); - fclose( stream ); - } - { - config_content_type * content = config_parse( config , "config.txt" , "--" , NULL , NULL , NULL , CONFIG_UNRECOGNIZED_IGNORE , true); - test_assert_bool_equal( parse_valid ,config_content_is_valid( content ) ); - if (parse_valid) { - const config_content_item_type * config_item = config_content_get_item( content , GEN_DATA_KEY ); - const config_content_node_type * config_node = config_content_item_iget_node( config_item , 0 ); - - enkf_config_node = enkf_config_node_alloc_GEN_DATA_from_config( config_node ); - } - - config_content_free( content ); - config_free( config ); - } - return enkf_config_node; -} - - - -void test_parse_gen_data_result() { - test_work_area_type * work_area = test_work_area_alloc("GEN_DATA_RESULT_parse"); - // Parse error: missing KEY - { - enkf_config_node_type * config_node = parse_alloc_GEN_DATA_result( "GEN_DATA\n" , false); - test_assert_NULL( config_node ); - } - - // Validation error: missing INPUT_FORMAT: - { - enkf_config_node_type * config_node = parse_alloc_GEN_DATA_result( "GEN_DATA GEN_DATA_KEY RESULT_FILE:Results%%d REPORT_STEPS:10 \n" , true); - test_assert_NULL( config_node ); - } - - - // Validation error: Invalid INPUT_FORMAT: - { - enkf_config_node_type * config_node = parse_alloc_GEN_DATA_result( "GEN_DATA GEN_DATA_KEY RESULT_FILE:Results%%d INPUT_FORMAT:AsCiiiiii REPORT_STEPS:10 \n" , true); - test_assert_NULL( config_node ); - } - - - // Validation error: missing RESULT_FILE: - { - enkf_config_node_type * config_node = parse_alloc_GEN_DATA_result( "GEN_DATA GEN_DATA_KEY INPUT_FORMAT:ASCII REPORT_STEPS:10 \n" , true); - test_assert_NULL( config_node ); - } - - - // Validation error: Invalid RESULT_FILE: - { - enkf_config_node_type * config_node = parse_alloc_GEN_DATA_result( "GEN_DATA GEN_DATA_KEY RESULT_FILE:Results INPUT_FORMAT:ASCII REPORT_STEPS:10 \n" , true); - test_assert_NULL( config_node ); - } - - // Validation error: Missing REPORT_STEPS: - { - enkf_config_node_type * config_node = parse_alloc_GEN_DATA_result( "GEN_DATA GEN_DATA_KEY RESULT_FILE:Results%%d INPUT_FORMAT:ASCII \n" , true); - test_assert_NULL( config_node ); - } - - // Validation error: Invalid REPORT_STEPS - { - enkf_config_node_type * config_node = parse_alloc_GEN_DATA_result( "GEN_DATA GEN_DATA_KEY RESULT_FILE:Results%%d INPUT_FORMAT:ASCII REPORT_STEPS:XXX\n" , true); - test_assert_NULL( config_node ); - } - - // Valid - { - enkf_config_node_type * config_node = parse_alloc_GEN_DATA_result( "GEN_DATA GEN_DATA_KEY RESULT_FILE:Results%%d INPUT_FORMAT:ASCII REPORT_STEPS:10,20,30\n" , true); - test_assert_true( enkf_config_node_is_instance( config_node )); - - test_assert_string_equal( "Results%d" , enkf_config_node_get_enkf_infile( config_node )); - test_assert_NULL( enkf_config_node_get_init_file_fmt( config_node )); - test_assert_NULL( enkf_config_node_get_enkf_outfile( config_node )); - test_assert_int_equal( DYNAMIC_RESULT , enkf_config_node_get_var_type( config_node )); - { - gen_data_config_type * gen_data_config = enkf_config_node_get_ref( config_node ); - test_assert_int_equal( ASCII , gen_data_config_get_input_format( gen_data_config )); - test_assert_int_equal( GEN_DATA_UNDEFINED , gen_data_config_get_output_format( gen_data_config )); - - test_assert_int_equal( 3 , gen_data_config_num_report_step( gen_data_config )); - test_assert_int_equal( 10 , gen_data_config_iget_report_step( gen_data_config , 0 )); - test_assert_int_equal( 30 , gen_data_config_iget_report_step( gen_data_config , 2 )); - - - test_assert_true( gen_data_config_has_report_step( gen_data_config , 10 )); - test_assert_true( gen_data_config_has_report_step( gen_data_config , 20 )); - test_assert_true( gen_data_config_has_report_step( gen_data_config , 30 )); - - test_assert_false( gen_data_config_has_report_step( gen_data_config , 05 )); - test_assert_false( gen_data_config_has_report_step( gen_data_config , 15 )); - test_assert_false( gen_data_config_has_report_step( gen_data_config , 25 )); - test_assert_false( gen_data_config_has_report_step( gen_data_config , 35 )); - - } - test_assert_true( enkf_config_node_internalize( config_node , 10 )); - test_assert_true( enkf_config_node_internalize( config_node , 20 )); - test_assert_true( enkf_config_node_internalize( config_node , 30 )); - - test_assert_false( enkf_config_node_internalize( config_node , 05 )); - test_assert_false( enkf_config_node_internalize( config_node , 15 )); - test_assert_false( enkf_config_node_internalize( config_node , 25 )); - test_assert_false( enkf_config_node_internalize( config_node , 35 )); - - enkf_config_node_free( config_node ); - } - - test_work_area_free( work_area ); -} - - - - -int main(int argc , char ** argv) { - test_parse_gen_param(); - test_parse_gen_data_result(); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_gen_obs_load.c b/ThirdParty/Ert/libenkf/tests/enkf_gen_obs_load.c deleted file mode 100644 index 1b84af5f34..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_gen_obs_load.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_gen_obs_load.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - - - -void test_obs_check_report_steps(const char * config_file ) { - ert_test_context_type * test_context = ert_test_context_alloc( "GEN_OBS" , config_file ); - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - enkf_obs_type * obs = enkf_main_get_obs( enkf_main ); - - test_assert_true( enkf_obs_has_key( obs , "GEN_OBS10")); - test_assert_true( enkf_obs_has_key( obs , "GEN_OBS20")); - test_assert_false( enkf_obs_has_key( obs , "GEN_OBS30")); - - ert_test_context_free( test_context ); -} - - - - - - -int main(int argc , char ** argv) { - const char * config_file = argv[1]; - - test_obs_check_report_steps( config_file ); - -} - - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_hook_manager_test.c b/ThirdParty/Ert/libenkf/tests/enkf_hook_manager_test.c deleted file mode 100644 index 742d2f86de..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_hook_manager_test.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_ecl_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ -#include -#include -#include -#include - -int main(int argc, char ** argv) { - - ert_workflow_list_type * list = NULL; - hook_manager_type * hook_manager = hook_manager_alloc(list); - - char * expected_path = util_alloc_abs_path(".ert_runpath_list"); - test_assert_string_equal(expected_path, hook_manager_get_runpath_list_file(hook_manager)); - free(expected_path); - - hook_manager_set_runpath_list_file(hook_manager, "Folder", NULL); - expected_path = util_alloc_abs_path("Folder/.ert_runpath_list"); - test_assert_string_equal(expected_path, hook_manager_get_runpath_list_file(hook_manager)); - free(expected_path); - - hook_manager_set_runpath_list_file(hook_manager, "Folder", "thefilename.txt"); - expected_path = util_alloc_abs_path("Folder/thefilename.txt"); - test_assert_string_equal(expected_path, hook_manager_get_runpath_list_file(hook_manager)); - free(expected_path); - - hook_manager_set_runpath_list_file(hook_manager, "/tmp/ouagadogo", "thefilename.txt"); - test_assert_string_equal("/tmp/ouagadogo/thefilename.txt", hook_manager_get_runpath_list_file(hook_manager)); - - hook_manager_free(hook_manager); - - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_iter_config.c b/ThirdParty/Ert/libenkf/tests/enkf_iter_config.c deleted file mode 100644 index 3f297eb8e4..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_iter_config.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_iter_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include - - -#define TMP_PATH "/tmp" -char * create_config_file( const char * enspath_fmt , const char * runpath_fmt , int iter_count) { - char * config_file = util_alloc_tmp_file(TMP_PATH , "iter-config" , false); - FILE * stream = util_fopen( config_file , "w"); - fprintf(stream , "%s %s\n" , ITER_CASE_KEY , enspath_fmt); - fprintf(stream , "%s %d\n" , ITER_COUNT_KEY , iter_count); - fclose( stream ); - return config_file; -} - - - -void test_set() { - analysis_iter_config_type * iter_config = analysis_iter_config_alloc(); - - test_assert_false( analysis_iter_config_case_fmt_set( iter_config )); - analysis_iter_config_set_case_fmt( iter_config , "case%d"); - test_assert_true( analysis_iter_config_case_fmt_set( iter_config )); - - test_assert_false( analysis_iter_config_num_iterations_set( iter_config )); - analysis_iter_config_set_num_iterations( iter_config , 77 ); - test_assert_true( analysis_iter_config_num_iterations_set( iter_config )); - - test_assert_int_equal( analysis_iter_config_get_num_retries_per_iteration(iter_config), 4); - analysis_iter_config_set_num_retries_per_iteration(iter_config , 10 ); - test_assert_int_equal( analysis_iter_config_get_num_retries_per_iteration(iter_config), 10); - - - analysis_iter_config_free( iter_config ); -} - - - - -int main(int argc , char ** argv) { - const char * enspath_fmt = "iter%d"; - const char * runpath_fmt = "run/iter%d/real%d"; - const int iter_count = 10; - char * config_file = create_config_file( enspath_fmt , runpath_fmt , iter_count); - - - config_parser_type * config = config_alloc(); - config_content_type * content; - analysis_iter_config_add_config_items( config ); - - content = config_parse( config , config_file , NULL , NULL , NULL , NULL , CONFIG_UNRECOGNIZED_ERROR , true); - test_assert_true( config_content_is_valid( content) ); - - test_assert_true( config_content_has_item( content , ITER_CASE_KEY )); - test_assert_true( config_content_has_item( content , ITER_COUNT_KEY )); - - { - analysis_iter_config_type * iter_config = analysis_iter_config_alloc(); - char itercase[50]; - sprintf(itercase,DEFAULT_ANALYSIS_ITER_CASE,5); - test_assert_string_equal( analysis_iter_config_iget_case( iter_config , 5) , itercase ); - analysis_iter_config_init( iter_config , content ); - - test_assert_int_equal( analysis_iter_config_get_num_iterations( iter_config ) , iter_count ); - test_assert_string_equal( analysis_iter_config_iget_case( iter_config , 5) , "iter5"); - - analysis_iter_config_free( iter_config ); - } - remove( config_file ); - free( config_file ); - config_content_free( content ); - config_free( config ); - - test_set(); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_local_obsdata.c b/ThirdParty/Ert/libenkf/tests/enkf_local_obsdata.c deleted file mode 100644 index 594f08ac6e..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_local_obsdata.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_local_obsdata.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include - -#include -#include - - -void test_wrapper() { - local_obsdata_node_type * node = local_obsdata_node_alloc("KEY" , true); - local_obsdata_type * data = local_obsdata_alloc_wrapper( node ); - test_assert_true( local_obsdata_is_instance( data )); - test_assert_int_equal( 1 , local_obsdata_get_size( data )); - test_assert_ptr_equal( node , local_obsdata_iget( data , 0 )); - test_assert_true( local_obsdata_has_node( data , "KEY" )); - test_assert_false( local_obsdata_has_node( data , "KEYX" )); - test_assert_string_equal( local_obsdata_node_get_key( node ) , local_obsdata_get_name( data )); - local_obsdata_free( data ); -} - - -int main(int argc , char ** argv) { - local_obsdata_type * obsdata; - - obsdata = local_obsdata_alloc( "KEY"); - test_assert_true( local_obsdata_is_instance( obsdata )); - test_assert_int_equal( 0 , local_obsdata_get_size( obsdata )); - test_assert_string_equal( "KEY" , local_obsdata_get_name( obsdata )); - - { - local_obsdata_node_type * obsnode = local_obsdata_node_alloc( "KEY" , true); - test_assert_true( local_obsdata_add_node( obsdata , obsnode ) ); - test_assert_false( local_obsdata_add_node( obsdata , obsnode ) ); - test_assert_int_equal( 1 , local_obsdata_get_size( obsdata )); - test_assert_ptr_equal( obsnode , local_obsdata_iget( obsdata , 0)); - } - - local_obsdata_free( obsdata ); - - test_wrapper(); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_local_obsdata_node.c b/ThirdParty/Ert/libenkf/tests/enkf_local_obsdata_node.c deleted file mode 100644 index a5d1d43622..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_local_obsdata_node.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_local_obsdata_node.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include - -#include -#include - - -void test_content( local_obsdata_node_type * node ) { - const active_list_type * active_list = local_obsdata_node_get_active_list( node ); - - test_assert_not_NULL( active_list ); - test_assert_true( active_list_is_instance( active_list )); - - { - active_list_type * new_active_list = active_list_alloc( ); - - active_list_add_index( new_active_list , 1098 ); - - test_assert_false( active_list_equal( new_active_list , local_obsdata_node_get_active_list( node ))); - local_obsdata_node_copy_active_list( node , new_active_list ); - test_assert_true( active_list_equal( new_active_list , local_obsdata_node_get_active_list( node ))); - - } - { - - - local_obsdata_node_add_tstep( node , 20 ); - local_obsdata_node_add_tstep( node , 10 ); - local_obsdata_node_add_tstep( node , 10 ); // Second add - ignored - - test_assert_false( local_obsdata_node_tstep_active(node, 5)); - test_assert_true( local_obsdata_node_tstep_active(node, 10)); - test_assert_true( local_obsdata_node_tstep_active(node, 20)); - test_assert_true( local_obsdata_node_has_tstep( node , 10 )); - test_assert_true( local_obsdata_node_has_tstep( node , 20 )); - test_assert_false( local_obsdata_node_has_tstep( node , 15 )); - - - local_obsdata_node_add_range( node , 5 , 7 ); - test_assert_true( local_obsdata_node_tstep_active(node, 5)); - test_assert_true( local_obsdata_node_tstep_active(node, 7)); - } - -} - -void test_all_active() { - local_obsdata_node_type * node = local_obsdata_node_alloc( "KEY" , true); - - test_assert_true( local_obsdata_node_all_timestep_active( node )); - test_assert_true( local_obsdata_node_tstep_active( node , 0 )); - test_assert_true( local_obsdata_node_tstep_active( node , 10 )); - test_assert_true( local_obsdata_node_tstep_active( node , 20 )); - - local_obsdata_node_free( node ); -} - - - - - - -int main(int argc , char ** argv) { - const char * obs_key = "1234"; - - { - local_obsdata_node_type * node = local_obsdata_node_alloc( obs_key , true); - - test_assert_true( local_obsdata_node_is_instance( node )); - test_assert_string_equal( obs_key , local_obsdata_node_get_key( node )); - test_content( node ); - local_obsdata_node_free( node ); - } - - { - void * node = local_obsdata_node_alloc( obs_key ,true ); - local_obsdata_node_free__( node ); - } - test_all_active(); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_magic_string_in_workflows.c b/ThirdParty/Ert/libenkf/tests/enkf_magic_string_in_workflows.c deleted file mode 100644 index 88bc0a14fd..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_magic_string_in_workflows.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_magic_string_in_workflows.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include - - -void test_magic_strings( ert_test_context_type * test_context ) { - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - test_assert_true( ert_test_context_run_worklow( test_context , "MAGIC_PRINT") ); - test_assert_true( util_file_exists( "magic-list.txt") ); - - { - FILE * stream = util_fopen("magic-list.txt" , "r"); - char string[128]; - - fscanf( stream , "%s" , string); - test_assert_string_equal( string , enkf_fs_get_case_name( enkf_main_get_fs( enkf_main ))); - - fscanf( stream , "%s" , string); - test_assert_string_equal( string , "MagicAllTheWayToWorkFlow"); - - fclose( stream ); - } -} - - -void test_has_job(ert_test_context_type * test_context ) { - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - ert_workflow_list_type * workflows = enkf_main_get_workflow_list( enkf_main ); - test_assert_true( ert_workflow_list_has_job( workflows , "MAGIC_PRINT" )); -} - - -int main( int argc , char ** argv) { - const char * model_config = argv[1]; - ert_test_context_type * test_context = ert_test_context_alloc( "MAGIC-STRINGS" , model_config); - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - - { - test_has_job( test_context ); - - enkf_main_select_fs(enkf_main , "default"); - test_assert_string_equal( "default" , enkf_fs_get_case_name( enkf_main_get_fs( enkf_main ))); - test_magic_strings( test_context ); - - enkf_main_select_fs(enkf_main , "extraCase"); - test_assert_string_equal( "extraCase" , enkf_fs_get_case_name( enkf_main_get_fs( enkf_main ))); - test_magic_strings( test_context ); - } - ert_test_context_free( test_context ); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_main.c b/ThirdParty/Ert/libenkf/tests/enkf_main.c deleted file mode 100644 index 32db707aad..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_main.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_main.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - - - - -void test_case_initialized() { - test_work_area_type * work_area = test_work_area_alloc("enkf_main_case_initialized" ); - { - enkf_main_type * enkf_main = enkf_main_alloc_empty(); - model_config_type * model_config = enkf_main_get_model_config(enkf_main); - const char * new_case = "fs/case"; - char * mount_point = util_alloc_sprintf("%s/%s" , model_config_get_enspath(model_config) , new_case); - enkf_fs_create_fs(mount_point , BLOCK_FS_DRIVER_ID , NULL , false); - - test_assert_false(enkf_main_case_is_initialized(enkf_main , "does/not/exist" , NULL)); - test_assert_true(enkf_main_case_is_initialized(enkf_main , new_case , NULL)); - - enkf_main_free(enkf_main); - } - test_work_area_free(work_area); -} - - - -void test_create() { - enkf_main_type * enkf_main = enkf_main_alloc_empty(); - test_assert_true( enkf_main_is_instance( enkf_main ) ); - enkf_main_free( enkf_main ); -} - - - -int main(int argc , char ** argv) { - util_install_signals(); - test_create(); - test_case_initialized(); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_main_fs.c b/ThirdParty/Ert/libenkf/tests/enkf_main_fs.c deleted file mode 100644 index ce01664b83..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_main_fs.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_main_fs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include - -#include -#include -#include -#include -#include - - - - - - - -int main(int argc, char ** argv) { - const char * config_file = argv[1]; - test_work_area_type * work_area = test_work_area_alloc( "enkf_main_fs" ); - char * model_config; - util_alloc_file_components( config_file , NULL , &model_config , NULL); - test_work_area_copy_parent_content( work_area , config_file ); - { - enkf_main_type * enkf_main = enkf_main_bootstrap( model_config , false , false ); - - enkf_main_select_fs( enkf_main , "enkf"); - test_assert_true( enkf_main_case_is_current( enkf_main , "enkf")); - test_assert_false( enkf_main_case_is_current( enkf_main , "default_fs")); - test_assert_false( enkf_main_case_is_current( enkf_main , "does_not_exist")); - - test_assert_int_equal( 1 , enkf_fs_get_refcount( enkf_main_get_fs( enkf_main ))); - { - enkf_fs_type * fs_ref = enkf_main_get_fs_ref( enkf_main ); - test_assert_int_equal( 2 , enkf_fs_get_refcount( enkf_main_get_fs( enkf_main ))); - enkf_fs_decref( fs_ref ); - test_assert_int_equal( 1 , enkf_fs_get_refcount( enkf_main_get_fs( enkf_main ))); - } - - { - state_map_type * map1 = enkf_fs_get_state_map( enkf_main_get_fs( enkf_main )); - state_map_type * map2 = enkf_main_alloc_readonly_state_map(enkf_main , "enkf"); - test_assert_true(state_map_equal( map1 , map2 )); - state_map_free( map2 ); - } - { - enkf_fs_type * fs1 = enkf_main_mount_alt_fs( enkf_main , "default" , false ); - enkf_fs_type * fs2 = enkf_main_mount_alt_fs( enkf_main , "enkf" , false ); - - test_assert_int_equal( 2 , enkf_fs_get_refcount( enkf_main_get_fs( enkf_main ))); - test_assert_int_equal( 2 , enkf_fs_get_refcount( fs2 )); - test_assert_int_equal( 1 , enkf_fs_get_refcount( fs1 )); - - enkf_fs_decref( fs1 ); - enkf_fs_decref( fs2 ); - } - - { - enkf_fs_type * enkf_fs = enkf_main_mount_alt_fs( enkf_main , "enkf" , false ); - - enkf_main_select_fs( enkf_main , "default"); - test_assert_int_equal( 1 , enkf_fs_get_refcount( enkf_main_get_fs( enkf_main ))); - enkf_fs_decref( enkf_fs ); - } - - { - enkf_fs_type * default_fs = enkf_main_mount_alt_fs( enkf_main , "default" , false ); - - test_assert_int_equal( 2 , enkf_fs_get_refcount( enkf_main_get_fs( enkf_main ))); - enkf_main_select_fs( enkf_main , "default"); - test_assert_int_equal( 2 , enkf_fs_get_refcount( enkf_main_get_fs( enkf_main ))); - enkf_fs_decref( default_fs ); - test_assert_int_equal( 1 , enkf_fs_get_refcount( enkf_main_get_fs( enkf_main ))); - } - /*****************************************************************/ - { - enkf_fs_type * fs = enkf_main_mount_alt_fs( enkf_main , "default" , false ); - test_assert_int_equal( 2 , enkf_fs_get_refcount( enkf_main_get_fs( enkf_main ))); - - enkf_main_set_fs( enkf_main , fs , NULL ); - enkf_fs_decref( fs ); - test_assert_int_equal( 1 , enkf_fs_get_refcount( enkf_main_get_fs( enkf_main ))); - } - { - enkf_fs_type * fs = enkf_main_mount_alt_fs( enkf_main , "enkf" , false ); - enkf_fs_type * current = enkf_main_mount_alt_fs( enkf_main , "default" , false ); - - test_assert_int_equal( 2 , enkf_fs_get_refcount( current )); - test_assert_int_equal( 1 , enkf_fs_get_refcount( fs)); - enkf_main_set_fs( enkf_main , fs , NULL); - test_assert_int_equal( 2 , enkf_fs_get_refcount( fs)); - test_assert_int_equal( 1 , enkf_fs_get_refcount( current )); - - enkf_fs_decref( current ); - enkf_fs_decref( fs); - } - - - - - test_assert_int_equal( 1 , enkf_fs_get_refcount( enkf_main_get_fs( enkf_main ))); - enkf_main_free( enkf_main ); - } - test_work_area_free( work_area ); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_main_fs_current_file_test.c b/ThirdParty/Ert/libenkf/tests/enkf_main_fs_current_file_test.c deleted file mode 100644 index 4f39d32cfe..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_main_fs_current_file_test.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_main_fs_current_file_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include - -#include -#include -#include -#include - -void test_current_file_not_present_symlink_present(const char * model_config) { - test_assert_true(util_file_exists("Storage/enkf")); - util_make_slink("enkf", "Storage/current" ); - enkf_main_type * enkf_main = enkf_main_bootstrap( model_config , false , false ); - test_assert_true( enkf_main_case_is_current( enkf_main , "enkf")); - test_assert_false(util_file_exists("Storage/current")); - test_assert_true(util_file_exists("Storage/current_case")); - char * current_case = enkf_main_read_alloc_current_case_name(enkf_main); - test_assert_string_equal(current_case, "enkf"); - free(current_case); - enkf_main_free(enkf_main); -} - -void test_current_file_present(const char * model_config) { - test_assert_true(util_file_exists("Storage/current_case")); - enkf_main_type * enkf_main = enkf_main_bootstrap( model_config , false , false ); - test_assert_true( enkf_main_case_is_current( enkf_main , "enkf")); - test_assert_false(util_file_exists("Storage/current")); - char * current_case = enkf_main_read_alloc_current_case_name(enkf_main); - test_assert_string_equal(current_case, "enkf"); - free(current_case); - enkf_main_free(enkf_main); -} - - -void test_change_case(const char * model_config) { - enkf_main_type * enkf_main = enkf_main_bootstrap( model_config , false , false ); - enkf_main_select_fs( enkf_main , "default"); - test_assert_true( enkf_main_case_is_current( enkf_main , "default")); - test_assert_false( enkf_main_case_is_current(enkf_main , "enkf")); - { - char * current_case = enkf_main_read_alloc_current_case_name(enkf_main); - test_assert_string_equal(current_case, "default"); - free(current_case); - } - - enkf_main_select_fs( enkf_main , "enkf"); - test_assert_true( enkf_main_case_is_current( enkf_main , "enkf")); - test_assert_false( enkf_main_case_is_current(enkf_main , "default")); - { - char * current_case = enkf_main_read_alloc_current_case_name(enkf_main); - test_assert_string_equal(current_case, "enkf"); - free(current_case); - } - - enkf_fs_type * enkf_fs = enkf_main_mount_alt_fs( enkf_main , "default" , false ); - enkf_main_select_fs( enkf_main , "default"); - test_assert_true( enkf_main_case_is_current( enkf_main , "default")); - enkf_fs_decref( enkf_fs ); - enkf_main_free(enkf_main); -} - -int main(int argc, char ** argv) { - const char * config_file = argv[1]; - test_work_area_type * work_area = test_work_area_alloc( "enkf_main_fs_current_file_test" ); - test_work_area_set_store(work_area, true); - char * model_config; - util_alloc_file_components( config_file , NULL , &model_config , NULL); - test_work_area_copy_parent_content( work_area , config_file ); - - test_current_file_not_present_symlink_present(model_config); - test_current_file_present(model_config); - test_change_case(model_config); - - free(model_config); - test_work_area_free( work_area ); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_meas_data.c b/ThirdParty/Ert/libenkf/tests/enkf_meas_data.c deleted file mode 100644 index a1b7268996..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_meas_data.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_meas_data.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include "ert/util/build_config.h" - -#include -#include -#include -#include - -#include - - - -void meas_block_iset_abort(void * arg) { - meas_block_type * block = meas_block_safe_cast( arg ); - meas_block_iset( block , 0 , 0 , 100); -} - - -void meas_block_iget_abort(void * arg) { - meas_block_type * block = meas_block_safe_cast( arg ); - meas_block_iget( block , 0 , 0 ); -} - - - -void create_test() { - int_vector_type * ens_active_list = int_vector_alloc(0 , false); - bool_vector_type * ens_mask; - int_vector_append( ens_active_list , 10 ); - int_vector_append( ens_active_list , 20 ); - int_vector_append( ens_active_list , 30 ); - - ens_mask = int_vector_alloc_mask(ens_active_list); - { - meas_data_type * meas_data = meas_data_alloc( ens_mask ); - test_assert_int_equal( 3 , meas_data_get_active_ens_size( meas_data )); - - { - meas_block_type * block = meas_data_add_block(meas_data , "OBS" , 10 , 10); - - meas_block_iset(block , 10 , 0 , 100); - test_assert_double_equal( 100 , meas_block_iget( block , 10 , 0 )); - - test_assert_bool_equal( true , meas_block_iens_active( block , 10 )); - test_assert_bool_equal( false , meas_block_iens_active( block , 11 )); - - test_assert_util_abort( "meas_block_assert_iens_active" , meas_block_iset_abort , block); - test_assert_util_abort( "meas_block_assert_iens_active" , meas_block_iget_abort , block); - } - meas_data_free( meas_data ); - } - - - bool_vector_free( ens_mask ); - int_vector_free( ens_active_list ); -} - - - -int main(int argc , char ** argv) { - create_test(); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_model_config.c b/ThirdParty/Ert/libenkf/tests/enkf_model_config.c deleted file mode 100644 index 5354e83a6c..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_model_config.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_model_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include - -#include - - -void test_create() { - model_config_type * model_config = model_config_alloc(); - test_assert_true( model_config_is_instance( model_config)); - model_config_free( model_config ); -} - - -void test_runpath() { - model_config_type * model_config = model_config_alloc(); - model_config_add_runpath(model_config , "KEY" , "RunPath%d"); - model_config_add_runpath(model_config , "KEY2" , "2-RunPath%d"); - test_assert_true( model_config_select_runpath(model_config , "KEY")); - test_assert_false( model_config_select_runpath(model_config , "KEYX")); - test_assert_string_equal("RunPath%d" , model_config_get_runpath_as_char(model_config)); - - model_config_set_runpath( model_config , "PATH%d"); - test_assert_string_equal("PATH%d" , model_config_get_runpath_as_char(model_config)); - test_assert_true( model_config_select_runpath(model_config , "KEY2")); - test_assert_string_equal("2-RunPath%d" , model_config_get_runpath_as_char(model_config)); - test_assert_true( model_config_select_runpath(model_config , "KEY")); - test_assert_string_equal("PATH%d" , model_config_get_runpath_as_char(model_config)); - - test_assert_false( model_config_runpath_requires_iter( model_config )); - model_config_set_runpath( model_config , "iens%d/iter%d" ); - test_assert_true( model_config_runpath_requires_iter( model_config )); - - model_config_free( model_config ); -} - - -int main(int argc , char ** argv) { - test_create(); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_obs_fs.c b/ThirdParty/Ert/libenkf/tests/enkf_obs_fs.c deleted file mode 100644 index a5050d3e08..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_obs_fs.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_obs_fs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - - -void testS( ert_test_context_type * test_context ) { - { - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - int_vector_type * active_list = int_vector_alloc(0,0); - obs_data_type * obs_data = obs_data_alloc(1.0); - local_obsdata_type * obs_set = local_obsdata_alloc( "KEY" ); - bool_vector_type * ens_mask; - meas_data_type * meas_data; - - - for (int i= 0; i < enkf_main_get_ensemble_size( enkf_main); i++) - int_vector_append( active_list , i ); - ens_mask = int_vector_alloc_mask( active_list); - - obs_data = obs_data_alloc(1.0); - meas_data = meas_data_alloc( ens_mask ); - - enkf_obs_add_local_nodes_with_data( enkf_obs , obs_set , fs , ens_mask ); - enkf_obs_get_obs_and_measure_data( enkf_obs , fs , obs_set, active_list , meas_data , obs_data); - - { - FILE * stream = util_fopen("analysis/Smatrix" , "r"); - matrix_type * S = meas_data_allocS( meas_data ); - matrix_type * S0 = matrix_fread_alloc( stream ); - - test_assert_true( matrix_equal( S0 , S )); - - matrix_free( S ); - matrix_free( S0 ); - fclose( stream ); - } - int_vector_free( active_list ); - meas_data_free( meas_data ); - obs_data_free( obs_data ); - local_obsdata_free( obs_set ); - bool_vector_free( ens_mask ); - } -} - - - -void test_iget(ert_test_context_type * test_context) { - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - - test_assert_int_equal( 32 , enkf_obs_get_size( enkf_obs ) ); - for (int iobs = 0; iobs < enkf_obs_get_size( enkf_obs ); iobs++) { - obs_vector_type * vec1 = enkf_obs_iget_vector( enkf_obs , iobs ); - obs_vector_type * vec2 = enkf_obs_get_vector( enkf_obs , obs_vector_get_key( vec1 )); - - test_assert_ptr_equal( vec1 , vec2 ); - } -} - - -void test_container( ert_test_context_type * test_context ) { - enkf_config_node_type * config_node = enkf_config_node_new_container( "CONTAINER" ); - enkf_config_node_type * wwct1_node = enkf_config_node_alloc_summary( "WWCT:OP_1" , LOAD_FAIL_SILENT); - enkf_config_node_type * wwct2_node = enkf_config_node_alloc_summary( "WWCT:OP_2" , LOAD_FAIL_SILENT); - enkf_config_node_type * wwct3_node = enkf_config_node_alloc_summary( "WWCT:OP_3" , LOAD_FAIL_SILENT); - - - enkf_config_node_update_container( config_node , wwct1_node ); - enkf_config_node_update_container( config_node , wwct2_node ); - enkf_config_node_update_container( config_node , wwct3_node ); - { - enkf_node_type * container = enkf_node_deep_alloc( config_node ); - enkf_node_free( container ); - } - - - enkf_config_node_free( wwct3_node ); - enkf_config_node_free( wwct2_node ); - enkf_config_node_free( wwct1_node ); - enkf_config_node_free( config_node ); -} - - -int main(int argc , char ** argv) { - util_install_signals(); - { - const char * config_file = argv[1]; - ert_test_context_type * test_context = ert_test_context_alloc( "ENKF_OBS_FS" , config_file ); - { - testS( test_context ); - test_iget( test_context ); - test_container( test_context ); - } - ert_test_context_free( test_context ); - exit(0); - } -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_obs_tests.c b/ThirdParty/Ert/libenkf/tests/enkf_obs_tests.c deleted file mode 100644 index b317cb42d8..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_obs_tests.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_enkf_obs_tests.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ - -#include - -#include -#include - -#include -#include -#include -#include - - -int main(int argc, char ** argv) { - history_type * history = NULL; - time_map_type * external_time_map = NULL; - ecl_grid_type * grid = NULL; - ensemble_config_type * ensemble_config = NULL; - ecl_sum_type * refcase = NULL; - - enkf_obs_type * enkf_obs = enkf_obs_alloc(history , external_time_map , grid , refcase , ensemble_config); - - obs_vector_type * obs_vector = obs_vector_alloc(SUMMARY_OBS, "WWCT", NULL, 2); - summary_obs_type * summary_obs1 = summary_obs_alloc( "SummaryKey" , "ObservationKey" , 43.2, 2.0 , AUTO_CORRF_EXP, 42); - obs_vector_install_node( obs_vector , 0 , summary_obs1 ); - - summary_obs_type * summary_obs2 = summary_obs_alloc( "SummaryKey2" , "ObservationKey2" , 4.2, 0.1 , AUTO_CORRF_EXP, 42); - obs_vector_install_node( obs_vector , 1 , summary_obs2 ); - - obs_vector_type * obs_vector2 = obs_vector_alloc(SUMMARY_OBS, "WWCT2", NULL, 2); - summary_obs_type * summary_obs3 = summary_obs_alloc( "SummaryKey" , "ObservationKey" , 43.2, 2.0 , AUTO_CORRF_EXP, 42); - obs_vector_install_node( obs_vector2 , 0 , summary_obs3 ); - - summary_obs_type * summary_obs4 = summary_obs_alloc( "SummaryKey2" , "ObservationKey2" , 4.2, 0.1 , AUTO_CORRF_EXP, 42); - obs_vector_install_node( obs_vector2 , 1 , summary_obs4 ); - - enkf_obs_add_obs_vector(enkf_obs, obs_vector); - enkf_obs_add_obs_vector(enkf_obs, obs_vector2); - - enkf_obs_scale_std(enkf_obs, 3.3); - - enkf_obs_free(enkf_obs); - - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_obs_vector.c b/ThirdParty/Ert/libenkf/tests/enkf_obs_vector.c deleted file mode 100644 index c2d2a773d2..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_obs_vector.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'enkf_obs_vector.c' is part of ERT - Ensemble based - Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - - - -void test_create(enkf_config_node_type * config_node ) { - obs_vector_type * obs_vector = obs_vector_alloc( SUMMARY_OBS , "OBS" , config_node , 100 ); - test_assert_true( obs_vector_is_instance( obs_vector )); - { - const int_vector_type * step_list = obs_vector_get_step_list( obs_vector ); - - { - summary_obs_type * obs_node = summary_obs_alloc( "FOPT" , "FOPT" , 10 , 1 , NULL , 0); - obs_vector_install_node( obs_vector , 10 , obs_node ); - test_assert_int_equal( 1 , int_vector_size( step_list )); - test_assert_int_equal( 10 , int_vector_iget( step_list , 0)); - } - - { - summary_obs_type * obs_node = summary_obs_alloc( "FOPT" , "FOPT" , 10 , 1 , NULL , 0); - obs_vector_install_node( obs_vector , 10 , obs_node ); - test_assert_int_equal( 1 , int_vector_size( step_list )); - test_assert_int_equal( 10 , int_vector_iget( step_list , 0)); - } - - { - summary_obs_type * obs_node = summary_obs_alloc( "FOPT" , "FOPT" , 10 , 1 , NULL , 0); - obs_vector_install_node( obs_vector , 5 , obs_node ); - test_assert_int_equal( 2 , int_vector_size( step_list )); - test_assert_int_equal( 5 , int_vector_iget( step_list , 0)); - test_assert_int_equal( 10 , int_vector_iget( step_list , 1)); - } - - { - summary_obs_type * obs_node = summary_obs_alloc( "FOPT" , "FOPT" , 10 , 1 , NULL , 0); - obs_vector_install_node( obs_vector , 15 , obs_node ); - test_assert_int_equal( 3 , int_vector_size( step_list )); - test_assert_int_equal( 5 , int_vector_iget( step_list , 0)); - test_assert_int_equal( 10 , int_vector_iget( step_list , 1)); - test_assert_int_equal( 15 , int_vector_iget( step_list , 2)); - } - } - obs_vector_free( obs_vector ); -} - - - -int main(int argc , char ** argv) { - enkf_config_node_type * config_node = enkf_config_node_alloc_summary("FOPR" , LOAD_FAIL_EXIT); - { - test_create( config_node ); - } - enkf_config_node_free( config_node ); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_obs_vector_fs.c b/ThirdParty/Ert/libenkf/tests/enkf_obs_vector_fs.c deleted file mode 100644 index 6a93801605..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_obs_vector_fs.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_obs_vector_fs.c' is part of ERT - Ensemble based - Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - - -void test_valid_obs_vector( enkf_main_type * enkf_main , const char * obs_key) { - enkf_fs_type * fs = enkf_main_get_fs(enkf_main); - enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - obs_vector_type * obs_vector = enkf_obs_get_vector( enkf_obs , obs_key ); - bool_vector_type * active_mask = bool_vector_alloc( enkf_main_get_ensemble_size( enkf_main ) , true); - - test_assert_true( obs_vector_has_data( obs_vector , active_mask , fs )); - bool_vector_free( active_mask ); -} - - -/* - This test will modify the enkf_obs container with invalid data; must - be the last test. -*/ - -void test_invalid_obs_vector( enkf_main_type * enkf_main , const char * obs_key) { - enkf_fs_type * fs = enkf_main_get_fs(enkf_main); - enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - obs_vector_type * obs_vector = enkf_obs_get_vector( enkf_obs , obs_key ); - bool_vector_type * active_mask = bool_vector_alloc( enkf_main_get_ensemble_size( enkf_main ) , true); - - test_assert_false( obs_vector_has_data( obs_vector , active_mask , fs )); - bool_vector_free( active_mask ); -} - - -void test_container( ert_test_context_type * test_context ) { - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - obs_vector_type * rft_obs = enkf_obs_get_vector( enkf_obs , "RFT_TEST"); - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - bool_vector_type * active_mask = bool_vector_alloc( enkf_main_get_ensemble_size( enkf_main ) , true ); - - test_assert_true( obs_vector_has_data( rft_obs , active_mask , fs )); - bool_vector_free( active_mask ); -} - - - -void test_measure( ert_test_context_type * test_context ) { - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - obs_vector_type * rft_obs = enkf_obs_get_vector( enkf_obs , "RFT_TEST"); - int_vector_type * ens_active_list = int_vector_alloc(0,0); - active_list_type * active_list = active_list_alloc( ); - meas_data_type * meas_data_RFT; - - for (int i=0; i < enkf_main_get_ensemble_size( enkf_main ); i++) - int_vector_append( ens_active_list , i ); - - { - bool_vector_type * ens_mask; - ens_mask = int_vector_alloc_mask( ens_active_list ); - meas_data_RFT = meas_data_alloc( ens_mask ); - bool_vector_free( ens_mask ); - } - - obs_vector_measure( rft_obs , fs , 20 , ens_active_list , meas_data_RFT , active_list ); - - int_vector_free( ens_active_list ); - active_list_free( active_list ); - meas_data_free( meas_data_RFT ); -} - - - - -int main(int argc , char ** argv) { - const char * config_file = argv[1]; - ert_test_context_type * context = ert_test_context_alloc( "OBS_VECTOR_FS" , config_file); - enkf_main_type * enkf_main = ert_test_context_get_main( context ); - - { - test_valid_obs_vector( enkf_main , "WWCT:OP_3"); - test_container( context ); - test_measure( context ); - test_invalid_obs_vector( enkf_main , "GOPT:OP"); - } - ert_test_context_free( context ); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_pca_plot.c b/ThirdParty/Ert/libenkf/tests/enkf_pca_plot.c deleted file mode 100644 index 71790def4a..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_pca_plot.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_pca_plot.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include -#include -#include - -#include -#include - - - -pca_plot_data_type * create_data() { - matrix_type * PC = matrix_alloc( 3 , 10); - matrix_type * PC_obs = matrix_alloc( 3 , 1 ); - double_vector_type * singular_values = double_vector_alloc(3 , 1); - - pca_plot_data_type * data = pca_plot_data_alloc("KEY" , PC , PC_obs , singular_values); - - double_vector_free( singular_values ); - matrix_free( PC ); - matrix_free( PC_obs ); - return data; -} - - - -void test_create_data() { - matrix_type * PC = matrix_alloc( 3 , 10); - matrix_type * PC_obs = matrix_alloc( 3 , 1 ); - double_vector_type * singular_values = double_vector_alloc(3 , 1); - { - pca_plot_data_type * data = pca_plot_data_alloc("KEY" , PC , PC_obs , singular_values); - test_assert_true( pca_plot_data_is_instance( data )); - test_assert_int_equal( 3 , pca_plot_data_get_size( data )); - test_assert_int_equal( 10 , pca_plot_data_get_ens_size( data )); - test_assert_string_equal( "KEY" , pca_plot_data_get_name( data )); - pca_plot_data_free( data ); - } - matrix_resize( PC , 4 , 10 , false); - test_assert_NULL( pca_plot_data_alloc( "KEY" , PC , PC_obs , singular_values)); - - matrix_resize( PC_obs , 3 , 2 , false); - test_assert_NULL( pca_plot_data_alloc( "KEY" , PC , PC_obs , singular_values)); - - double_vector_free( singular_values ); - matrix_free( PC ); - matrix_free( PC_obs ); -} - - - -void test_create_vector() { - matrix_type * PC = matrix_alloc( 3 , 10); - matrix_type * PC_obs = matrix_alloc( 3 , 1 ); - double_vector_type * singular_values = double_vector_alloc(3 , 1); - - { - pca_plot_vector_type * vector = pca_plot_vector_alloc(0 , PC , PC_obs, singular_values); - test_assert_true( pca_plot_vector_is_instance( vector )); - pca_plot_vector_free( vector ); - } - - double_vector_free( singular_values ); - matrix_free( PC ); - matrix_free( PC_obs ); -} - - -void test_get_vector() { - pca_plot_data_type * data = create_data(); - test_assert_true( pca_plot_vector_is_instance( pca_plot_data_iget_vector( data , 0 ))); - pca_plot_data_free( data ); -} - - -void test_content() { - rng_type * rng = rng_alloc(MZRAN , INIT_DEFAULT); - matrix_type * PC = matrix_alloc( 3 , 10); - matrix_type * PC_obs = matrix_alloc( 3 , 1 ); - double_vector_type * singular_values = double_vector_alloc(3 , 1); - matrix_random_init( PC , rng ); - matrix_random_init( PC_obs , rng ); - { - pca_plot_data_type * data = pca_plot_data_alloc("KEY" , PC , PC_obs, singular_values); - for (int i=0; i < matrix_get_rows( PC ); i++) { - const pca_plot_vector_type * vector = pca_plot_data_iget_vector( data , i ); - - test_assert_double_equal( matrix_iget( PC_obs , i , 0) , - pca_plot_vector_get_obs_value( vector ) ); - - test_assert_double_equal( double_vector_iget( singular_values , i), - pca_plot_vector_get_singular_value( vector ) ); - - for (int j=0; j < matrix_get_columns( PC ); j++) - test_assert_double_equal( matrix_iget( PC , i , j ) , pca_plot_vector_iget_sim_value( vector , j )); - - test_assert_int_equal( matrix_get_columns( PC ) , pca_plot_vector_get_size( vector )); - - } - pca_plot_data_free( data ); - } - - double_vector_free( singular_values ); - matrix_free( PC ); - matrix_free( PC_obs ); -} - - -int main(int argc , char ** argv) { - test_create_data(); - test_create_vector(); - test_get_vector(); - test_content(); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_plot_data.c b/ThirdParty/Ert/libenkf/tests/enkf_plot_data.c deleted file mode 100644 index dc0ecab891..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_plot_data.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_plot_data.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - - - -void test_create() { - enkf_plot_data_type * plot_data = enkf_plot_data_alloc( NULL ); - test_assert_true( enkf_plot_data_is_instance( plot_data )); - test_assert_int_equal( 0 , enkf_plot_data_get_size( plot_data )); - enkf_plot_data_free( plot_data ); -} - - - -int main(int argc , char ** argv) { - test_create(); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_plot_data_fs.c b/ThirdParty/Ert/libenkf/tests/enkf_plot_data_fs.c deleted file mode 100644 index 88ac6b6aa6..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_plot_data_fs.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_plot_data_fs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#include -#include -#include - -#include -#include - -#include -#include -#include - - - -void test_load_GEN_KW( enkf_main_type * enkf_main , const char * key , const char * index_key) { - ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config( enkf_main ); - const enkf_config_node_type * config_node = ensemble_config_get_node( ensemble_config , key ); - enkf_plot_data_type * plot_data = enkf_plot_data_alloc( config_node ); - - { - enkf_fs_type * enkf_fs = enkf_main_mount_alt_fs( enkf_main , "enkf" , true ); - - enkf_plot_data_load( plot_data , enkf_fs , index_key , NULL ); - test_assert_int_equal( 25 , enkf_plot_data_get_size( plot_data )); - { - enkf_plot_tvector_type * plot_vector = enkf_plot_data_iget( plot_data , 10 ); - test_assert_true( enkf_plot_tvector_is_instance( plot_vector )); - test_assert_int_equal( 63 , enkf_plot_tvector_size( plot_vector )); - - test_assert_true( enkf_plot_tvector_iget_active( plot_vector , 0 )); - test_assert_true( enkf_plot_tvector_iget_active( plot_vector , 10 )); - test_assert_true( enkf_plot_tvector_iget_active( plot_vector , 20 )); - test_assert_true( enkf_plot_tvector_iget_active( plot_vector , 30 )); - - test_assert_false( enkf_plot_tvector_iget_active( plot_vector , 1 )); - test_assert_false( enkf_plot_tvector_iget_active( plot_vector , 11 )); - test_assert_false( enkf_plot_tvector_iget_active( plot_vector , 21 )); - test_assert_false( enkf_plot_tvector_iget_active( plot_vector , 31 )); - } - enkf_fs_decref( enkf_fs ); - } - enkf_plot_data_free( plot_data ); -} - - - -void test_load_summary( enkf_main_type * enkf_main , const char * summary_key) { - ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config( enkf_main ); - const enkf_config_node_type * config_node = ensemble_config_get_node( ensemble_config , summary_key ); - enkf_plot_data_type * plot_data = enkf_plot_data_alloc( config_node ); - - { - enkf_fs_type * enkf_fs = enkf_main_mount_alt_fs( enkf_main , "enkf" , true ); - enkf_plot_data_load( plot_data , enkf_fs , NULL , NULL ); - test_assert_int_equal( 25 , enkf_plot_data_get_size( plot_data )); - { - enkf_plot_tvector_type * plot_vector = enkf_plot_data_iget( plot_data , 10 ); - test_assert_true( enkf_plot_tvector_is_instance( plot_vector )); - test_assert_false( enkf_plot_tvector_iget_active( plot_vector , 0 )); - test_assert_int_equal( 63 , enkf_plot_tvector_size( plot_vector )); - } - enkf_fs_decref( enkf_fs ); - } - - { - enkf_fs_type * enkf_fs = enkf_main_mount_alt_fs( enkf_main , "default" , true ); - enkf_plot_data_load( plot_data , enkf_fs , NULL , NULL ); - test_assert_int_equal( 25 , enkf_plot_data_get_size( plot_data )); - { - enkf_plot_tvector_type * plot_vector = enkf_plot_data_iget( plot_data , 0 ); - test_assert_true( enkf_plot_tvector_is_instance( plot_vector )); - test_assert_false( enkf_plot_tvector_iget_active( plot_vector , 0 )); - test_assert_int_equal( 63 , enkf_plot_tvector_size( plot_vector )); - - plot_vector = enkf_plot_data_iget( plot_data , 1 ); - test_assert_true( enkf_plot_tvector_is_instance( plot_vector )); - test_assert_int_equal( 0 , enkf_plot_tvector_size( plot_vector )); - } - enkf_fs_decref( enkf_fs ); - } - enkf_plot_data_free( plot_data ); -} - - - - - -int main(int argc, char ** argv) { - util_install_signals(); - { - const char * config_file = argv[1]; - test_work_area_type * work_area = test_work_area_alloc( "enkf_main_fs" ); - char * model_config; - util_alloc_file_components( config_file , NULL , &model_config , NULL); - test_work_area_set_store( work_area , true ); - test_work_area_copy_parent_content( work_area , config_file ); - { - enkf_main_type * enkf_main = enkf_main_bootstrap( model_config , false , false ); - - test_load_summary(enkf_main , "WWCT:OP_3"); - test_load_GEN_KW( enkf_main , "MULTFLT" , "F3"); - enkf_main_free( enkf_main ); - } - test_work_area_free( work_area ); - exit(0); - } -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw.c b/ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw.c deleted file mode 100644 index 0471ec8ec2..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_gen_kw.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include - -#include -#include -#include - -void test_create_invalid() { - enkf_config_node_type * config_node = enkf_config_node_alloc_summary( "WWCT" , LOAD_FAIL_SILENT); - enkf_plot_gen_kw_type * gen_kw = enkf_plot_gen_kw_alloc( config_node ); - - test_assert_NULL( gen_kw ); - enkf_config_node_free( config_node ); -} - - -void test_create() { - enkf_config_node_type * config_node = enkf_config_node_new_gen_kw( "GEN_KW" , DEFAULT_GEN_KW_TAG_FORMAT, false); - - { - enkf_plot_gen_kw_type * gen_kw = enkf_plot_gen_kw_alloc( config_node ); - test_assert_true( enkf_plot_gen_kw_is_instance( gen_kw )); - test_assert_int_equal( 0 , enkf_plot_gen_kw_get_size( gen_kw )); - enkf_plot_gen_kw_free( gen_kw ); - } - - enkf_config_node_free( config_node ); -} - - - - -int main( int argc , char ** argv) { - test_create(); - test_create_invalid(); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw_fs.c b/ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw_fs.c deleted file mode 100644 index 4dba59071d..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw_fs.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_gen_kw_fs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - - -void test_load(const char * config_file) { - ert_test_context_type * test_context = ert_test_context_alloc( "GEN_KW" , config_file ); - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - int ens_size = enkf_main_get_ensemble_size( enkf_main ); - stringlist_type * param_list = stringlist_alloc_new(); - enkf_fs_type * init_fs = enkf_fs_create_fs( "fs" , BLOCK_FS_DRIVER_ID , NULL , true ); - bool_vector_type * iens_mask = bool_vector_alloc( ens_size , true ); - - stringlist_append_ref( param_list , "GEN_KW"); - enkf_main_initialize_from_scratch( enkf_main , init_fs , param_list , iens_mask , INIT_FORCE); - { - ensemble_config_type * ensemble_config = enkf_main_get_ensemble_config( enkf_main ); - enkf_config_node_type * config_node = ensemble_config_get_node( ensemble_config , "GEN_KW"); - enkf_plot_gen_kw_type * plot_gen_kw = enkf_plot_gen_kw_alloc( config_node ); - bool_vector_type * input_mask = bool_vector_alloc( ens_size , true ); - gen_kw_config_type * gen_kw_config = enkf_config_node_get_ref( config_node ); - - enkf_plot_gen_kw_load( plot_gen_kw , init_fs , true , 0 , input_mask ); - - test_assert_int_equal( ens_size , enkf_plot_gen_kw_get_size( plot_gen_kw )); - - test_assert_int_equal(4, enkf_plot_gen_kw_get_keyword_count(plot_gen_kw)); - - { - enkf_plot_gen_kw_vector_type * vector = enkf_plot_gen_kw_iget( plot_gen_kw , 0 ); - for (int i=0; i < enkf_plot_gen_kw_vector_get_size( vector ); i++) - test_assert_string_equal( enkf_plot_gen_kw_iget_key( plot_gen_kw , i ) , gen_kw_config_iget_name( gen_kw_config , i)); - } - bool_vector_free( input_mask ); - } - - bool_vector_free( iens_mask ); - stringlist_free( param_list ); - enkf_fs_decref( init_fs ); - ert_test_context_free( test_context ); -} - - - - - -int main( int argc , char ** argv) { - util_install_signals(); - { - const char * config_file = argv[1]; - test_load( config_file ); - exit(0); - } -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw_vector.c b/ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw_vector.c deleted file mode 100644 index d95bbdf539..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_plot_gen_kw_vector.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_gen_kw_vector.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include - -#include -#include -#include - - -void test_create() { - enkf_config_node_type * config_node = enkf_config_node_new_gen_kw( "GEN_KW" , DEFAULT_GEN_KW_TAG_FORMAT, false); - - enkf_plot_gen_kw_vector_type * vector = enkf_plot_gen_kw_vector_alloc( config_node , 0 ); - test_assert_true( enkf_plot_gen_kw_vector_is_instance( vector )); - test_assert_int_equal( 0 , enkf_plot_gen_kw_vector_get_size( vector )); - - enkf_plot_gen_kw_vector_free( vector ); - enkf_config_node_free( config_node ); -} - - - - -int main( int argc , char ** argv) { - test_create(); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_plot_gendata.c b/ThirdParty/Ert/libenkf/tests/enkf_plot_gendata.c deleted file mode 100644 index 5185adbbbc..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_plot_gendata.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_gendata.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include - -#include - -#include -#include -#include - -void test_create_invalid() { - enkf_config_node_type * config_node = enkf_config_node_alloc_summary( "WWCT" , LOAD_FAIL_SILENT); - obs_vector_type * obs_vector = obs_vector_alloc(SUMMARY_OBS , "OBS" , config_node , 100); - enkf_plot_gendata_type * gen_data = enkf_plot_gendata_alloc_from_obs_vector( obs_vector ); - test_assert_NULL( gen_data ); - enkf_config_node_free( config_node ); - obs_vector_free( obs_vector ); -} - - -void test_create() { - enkf_config_node_type * config_node = enkf_config_node_alloc_GEN_DATA_result( "key" , ASCII , "Result:%d"); - enkf_plot_gendata_type * gen_data = enkf_plot_gendata_alloc( config_node ); - test_assert_true( enkf_plot_gendata_is_instance( gen_data )); - test_assert_int_equal( 0 , enkf_plot_gendata_get_size( gen_data )); - enkf_config_node_free( config_node ); - enkf_plot_gendata_free( gen_data); -} - - - - -int main( int argc , char ** argv) { - test_create(); - test_create_invalid(); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_plot_gendata_fs.c b/ThirdParty/Ert/libenkf/tests/enkf_plot_gendata_fs.c deleted file mode 100644 index 29c2745263..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_plot_gendata_fs.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_gendata_fs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include - -#include - -#include -#include -#include -#include - - - - -void test_gendata( enkf_main_type * enkf_main , const char * obs_key , int report_step ) { - enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main ); - - obs_vector_type * obs_vector = enkf_obs_get_vector( enkf_obs , obs_key); - - { - enkf_plot_gendata_type * gen_data = enkf_plot_gendata_alloc_from_obs_vector( obs_vector ); - - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - gen_obs_type * gen_obs = obs_vector_iget_node( obs_vector , report_step ); - - { - - double value; - double std; - bool valid; - gen_obs_user_get_with_data_index(gen_obs , "0" , &value , &std , &valid ); - test_assert_double_equal( 0.143841 , value ); - test_assert_double_equal( 0.0300 , std ); - test_assert_true( valid ); - - } - - enkf_plot_gendata_load(gen_data, fs, report_step, NULL); - - test_assert_int_equal( enkf_main_get_ensemble_size( enkf_main ) , enkf_plot_gendata_get_size( gen_data )); - - { - enkf_plot_genvector_type * vector = enkf_plot_gendata_iget( gen_data , 24); - test_assert_true( enkf_plot_genvector_is_instance( vector )); - test_assert_double_equal( 0.675537 , enkf_plot_genvector_iget( vector , 0 )); - test_assert_double_equal( 0.682635 , enkf_plot_genvector_iget( vector , 1 )); - test_assert_double_equal( 0.616371 , enkf_plot_genvector_iget( vector , 2 )); - - - } - - { - enkf_plot_genvector_type * vector = enkf_plot_gendata_iget( gen_data , 9 ); - test_assert_true( enkf_plot_genvector_is_instance( vector )); - test_assert_double_equal( -0.515033 , enkf_plot_genvector_iget( vector , 0 )); - test_assert_double_equal( -0.507350 , enkf_plot_genvector_iget( vector , 1 )); - test_assert_double_equal( -0.541030 , enkf_plot_genvector_iget( vector , 2 )); - } - - - enkf_plot_gendata_free( gen_data ); - } - - -} - - - -int main( int argc , char ** argv) { - const char * config_file = argv[1]; - util_install_signals(); - ert_test_context_type * test_context = ert_test_context_alloc("GENDATA" , config_file ); - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - - test_gendata( enkf_main , "GEN_TIMESHIFT" , 60); - - ert_test_context_free( test_context ); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_plot_genvector.c b/ThirdParty/Ert/libenkf/tests/enkf_plot_genvector.c deleted file mode 100644 index b878af563b..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_plot_genvector.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'enkf_plot_genvector.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include - -#include - -#include -#include -#include -#include - - -void test_create() { - enkf_config_node_type * config_node = enkf_config_node_alloc_GEN_DATA_result( "Key" , ASCII , "Result%d"); - enkf_plot_genvector_type * gen_vector = enkf_plot_genvector_alloc( config_node , 0 ); - test_assert_true( enkf_plot_genvector_is_instance( gen_vector )); - test_assert_int_equal( 0 , enkf_plot_genvector_get_size( gen_vector )); - enkf_config_node_free( config_node ); - enkf_plot_genvector_free(gen_vector); -} - - - - -int main( int argc , char ** argv) { - test_create(); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_plot_tvector.c b/ThirdParty/Ert/libenkf/tests/enkf_plot_tvector.c deleted file mode 100644 index 0896f5788b..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_plot_tvector.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_plot_tvector.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - - - -void create_test() { - enkf_config_node_type * config_node = enkf_config_node_alloc_summary("KEY" , LOAD_FAIL_SILENT); - enkf_plot_tvector_type * tvector = enkf_plot_tvector_alloc( config_node , 0 ); - test_assert_true( enkf_plot_tvector_is_instance( tvector )); - enkf_plot_tvector_free( tvector ); -} - - - -void test_iset() { - enkf_config_node_type * config_node = enkf_config_node_alloc_summary("KEY" , LOAD_FAIL_SILENT); - enkf_plot_tvector_type * tvector = enkf_plot_tvector_alloc( config_node , 0 ); - enkf_plot_tvector_iset( tvector , 10 , 0 , 100 ); - - test_assert_int_equal( 11 , enkf_plot_tvector_size( tvector )); - test_assert_time_t_equal( 0 , enkf_plot_tvector_iget_time( tvector , 10 )); - test_assert_double_equal( 100 , enkf_plot_tvector_iget_value( tvector , 10 )); - { - for (int i=0; i < (enkf_plot_tvector_size( tvector ) - 1); i++) - test_assert_false( enkf_plot_tvector_iget_active( tvector , i )); - - test_assert_true( enkf_plot_tvector_iget_active( tvector , 10 )); - } - - enkf_plot_tvector_free( tvector ); -} - - -void test_all_active() { - enkf_config_node_type * config_node = enkf_config_node_alloc_summary("KEY" , LOAD_FAIL_SILENT); - enkf_plot_tvector_type * tvector = enkf_plot_tvector_alloc( config_node , 0); - test_assert_true( enkf_plot_tvector_all_active( tvector )); - - enkf_plot_tvector_iset( tvector , 00 , 0 , 100 ); - test_assert_true( enkf_plot_tvector_all_active( tvector )); - - enkf_plot_tvector_iset( tvector , 1 , 0 , 100 ); - test_assert_true( enkf_plot_tvector_all_active( tvector )); - - enkf_plot_tvector_iset( tvector , 10 , 0 , 100 ); - test_assert_false( enkf_plot_tvector_all_active( tvector )); -} - - - -void test_iget() { - enkf_config_node_type * config_node = enkf_config_node_alloc_summary("KEY" , LOAD_FAIL_SILENT); - enkf_plot_tvector_type * tvector = enkf_plot_tvector_alloc( config_node , 0); - enkf_plot_tvector_iset( tvector , 0 , 0 , 0 ); - enkf_plot_tvector_iset( tvector , 1 , 100 , 10 ); - enkf_plot_tvector_iset( tvector , 2 , 200 , 20 ); - enkf_plot_tvector_iset( tvector , 3 , 300 , 30 ); - enkf_plot_tvector_iset( tvector , 4 , 400 , 40 ); - - enkf_plot_tvector_iset( tvector , 6 , 600 , 60 ); - - - test_assert_int_equal( 7 , enkf_plot_tvector_size( tvector )); - for (int i=0; i < 7; i++) { - if (i == 5) - test_assert_false( enkf_plot_tvector_iget_active( tvector , i )); - else { - test_assert_true( enkf_plot_tvector_iget_active( tvector , i )); - test_assert_time_t_equal( i * 100 , enkf_plot_tvector_iget_time( tvector , i )); - test_assert_double_equal( i * 10 , enkf_plot_tvector_iget_value( tvector , i )); - } - } -} - - - -int main(int argc , char ** argv) { - create_test(); - test_iset(); - test_all_active(); - test_iget(); - - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_refcase_list.c b/ThirdParty/Ert/libenkf/tests/enkf_refcase_list.c deleted file mode 100644 index 7abe9aac96..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_refcase_list.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_refcase_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -#include - - -int main(int argc , char ** argv) { - const char * case1 = argv[1]; - const char * case_glob = argv[2]; - - { - ecl_refcase_list_type * refcase_list = ecl_refcase_list_alloc( ); - - test_assert_false( ecl_refcase_list_has_case( refcase_list , "DoesNotExist" )); - test_assert_NULL( ecl_refcase_list_get_case( refcase_list , "DoesNotExist")); - - test_assert_int_equal( ecl_refcase_list_add_matching( refcase_list , "DoesNotExist") , 0); - ecl_refcase_list_add_case( refcase_list , "DoesNotExist" ); - test_assert_false( ecl_refcase_list_has_case( refcase_list , "DoesNotExist")); - - ecl_refcase_list_add_case( refcase_list , case1 ); - test_assert_true( ecl_refcase_list_has_case( refcase_list , case1)); - - - test_assert_not_NULL( refcase_list ); - test_assert_false( ecl_refcase_list_has_default( refcase_list )); - test_assert_NULL( ecl_refcase_list_get_default( refcase_list )); - - test_assert_false( ecl_refcase_list_set_default( refcase_list , "DoesNotExist")); - test_assert_false( ecl_refcase_list_has_default( refcase_list )); - test_assert_NULL( ecl_refcase_list_get_default( refcase_list )); - test_assert_int_equal( 1 , ecl_refcase_list_get_size( refcase_list )); - - test_assert_true( ecl_refcase_list_set_default( refcase_list , case1)); - test_assert_true( ecl_refcase_list_has_default( refcase_list )); - test_assert_not_NULL( ecl_refcase_list_get_default( refcase_list )); - test_assert_int_equal( 1 , ecl_refcase_list_get_size( refcase_list )); - - test_assert_false( ecl_refcase_list_set_default( refcase_list , "DoesNotExist")); - test_assert_true( ecl_refcase_list_has_default( refcase_list )); - test_assert_not_NULL( ecl_refcase_list_get_default( refcase_list )); - test_assert_int_equal( 1 , ecl_refcase_list_get_size( refcase_list )); - test_assert_NULL( ecl_refcase_list_iget_case( refcase_list , 100)); - - ecl_refcase_list_free( refcase_list ); - } - - { - ecl_refcase_list_type * refcase_list = ecl_refcase_list_alloc( ); - test_assert_int_equal( ecl_refcase_list_add_matching( refcase_list , case_glob ) , 11); - test_assert_int_equal( 11 , ecl_refcase_list_get_size( refcase_list )); - - test_assert_true( ecl_refcase_list_set_default( refcase_list , case1)); - test_assert_true( ecl_refcase_list_has_default( refcase_list )); - test_assert_not_NULL( ecl_refcase_list_get_default( refcase_list )); - test_assert_int_equal( 11 , ecl_refcase_list_get_size( refcase_list )); - - test_assert_int_equal( ecl_refcase_list_add_matching( refcase_list , case_glob ) , 0); - test_assert_int_equal( ecl_refcase_list_add_matching( refcase_list , case_glob ) , 0); - { - const ecl_sum_type * ecl_sum = ecl_refcase_list_iget_case( refcase_list , 0 ); - test_assert_not_NULL( ecl_sum ); - } - test_assert_int_equal( 11 , ecl_refcase_list_get_size( refcase_list )); - - { - stringlist_type * case_list = stringlist_alloc_new( ); - const int N = ecl_refcase_list_get_size( refcase_list ); - int i; - for (i=0; i < N; i++) - stringlist_append_ref( case_list , ecl_refcase_list_iget_pathcase( refcase_list , N - 1 - i )); - - { - bool equal = true; - for (i=0; i < N; i++) - equal = equal && util_string_equal( stringlist_iget( case_list , i ) , ecl_refcase_list_iget_pathcase( refcase_list , i)); - - test_assert_false( equal ); - stringlist_sort( case_list , (string_cmp_ftype *) util_strcmp_int); - - equal = true; - for (i=0; i < N; i++) - equal = equal && util_string_equal( stringlist_iget( case_list , i ) , ecl_refcase_list_iget_pathcase( refcase_list , i)); - test_assert_true( equal ); - } - stringlist_free( case_list ); - } - ecl_refcase_list_add_matching( refcase_list , "DoesNotExist*"); - test_assert_int_equal( 11 , ecl_refcase_list_get_size( refcase_list )); - ecl_refcase_list_free( refcase_list ); - } - - - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_rng.c b/ThirdParty/Ert/libenkf/tests/enkf_rng.c deleted file mode 100644 index 86d430c207..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_rng.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_rng.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - - -int main(int argc , char ** argv) { - unsigned int rand1,rand2; - { - test_work_area_type * work_area = test_work_area_alloc("enkf-rng-0"); - { - enkf_main_type * enkf_main = enkf_main_alloc_empty(); - enkf_main_resize_ensemble( enkf_main , 10 ); - { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 9 ); - rand1 = enkf_state_get_random( state ); - } - enkf_main_free( enkf_main ); - } - - { - enkf_main_type * enkf_main = enkf_main_alloc_empty(); - enkf_main_resize_ensemble( enkf_main , 10 ); - { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 9 ); - rand2 = enkf_state_get_random( state ); - } - enkf_main_free( enkf_main ); - } - test_assert_uint_not_equal( rand1 , rand2 ); - test_work_area_free( work_area ); - } - - /*****************************************************************/ - - { - test_work_area_type * work_area = test_work_area_alloc("enkf-rng-1" ); - const char * seed_file = "seed"; - { - enkf_main_type * enkf_main = enkf_main_alloc_empty(); - { - rng_config_type * rng_config = enkf_main_get_rng_config( enkf_main ); - rng_config_set_seed_store_file( rng_config , seed_file ); - } - enkf_main_rng_init( enkf_main ); - - enkf_main_resize_ensemble( enkf_main , 10 ); - { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 9 ); - rand1 = enkf_state_get_random( state ); - } - enkf_main_free( enkf_main ); - } - - { - enkf_main_type * enkf_main = enkf_main_alloc_empty(); - { - rng_config_type * rng_config = enkf_main_get_rng_config( enkf_main ); - rng_config_set_seed_load_file( rng_config , seed_file ); - } - enkf_main_rng_init( enkf_main ); - - enkf_main_resize_ensemble( enkf_main , 10 ); - { - enkf_state_type * state = enkf_main_iget_state( enkf_main , 9 ); - rand2 = enkf_state_get_random( state ); - } - enkf_main_free( enkf_main ); - } - test_assert_uint_equal( rand1 , rand2 ); - test_work_area_free( work_area ); - - } - /*****************************************************************/ - { - const char * config_path = argv[1]; - const char * config_file = argv[2]; - test_work_area_type * work_area = test_work_area_alloc("enkf-rng-2" ); - test_work_area_copy_directory_content( work_area , config_path ); - { - enkf_main_type * enkf_main = enkf_main_bootstrap( config_file , true , true ); - enkf_state_type * state = enkf_main_iget_state( enkf_main , 9 ); - rand1 = enkf_state_get_random( state ); - enkf_main_free( enkf_main ); - } - - { - enkf_main_type * enkf_main = enkf_main_bootstrap( config_file , true , true ); - enkf_state_type * state = enkf_main_iget_state( enkf_main , 9 ); - rand2 = enkf_state_get_random( state ); - enkf_main_free( enkf_main ); - } - test_assert_uint_equal( rand1 , rand2 ); - - { - enkf_main_type * enkf_main = enkf_main_bootstrap( config_file , true , true ); - enkf_state_type * state = enkf_main_iget_state( enkf_main , 9 ); - rand2 = enkf_state_get_random( state ); - enkf_main_free( enkf_main ); - } - test_assert_uint_equal( rand1 , rand2 ); - test_work_area_free( work_area ); - } - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_run_arg.c b/ThirdParty/Ert/libenkf/tests/enkf_run_arg.c deleted file mode 100644 index cd38319e6d..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_run_arg.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'ert_run_context.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include "ert/util/build_config.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - - -void call_get_queue_index( void * arg ) { - run_arg_type * run_arg = run_arg_safe_cast( arg ); - run_arg_get_queue_index( run_arg ); -} - -void call_set_queue_index( void * arg ) { - run_arg_type * run_arg = run_arg_safe_cast( arg ); - run_arg_set_queue_index( run_arg , 88 ); -} - - -void test_queue_index() { - test_work_area_type * test_area = test_work_area_alloc("run_arg/ENS"); - { - enkf_fs_type * fs = enkf_fs_create_fs("sim" , BLOCK_FS_DRIVER_ID , NULL , true); - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(fs , 0 , 6 , "path"); - - test_assert_false( run_arg_is_submitted( run_arg ) ); - test_assert_util_abort("run_arg_get_queue_index" , call_get_queue_index , run_arg ); - - run_arg_set_queue_index(run_arg, 78); - test_assert_true( run_arg_is_submitted( run_arg ) ); - test_assert_int_equal( 78 , run_arg_get_queue_index( run_arg )); - - test_assert_util_abort("run_arg_set_queue_index" , call_set_queue_index , run_arg ); - run_arg_free( run_arg ); - enkf_fs_decref( fs ); - } - test_work_area_free( test_area ); -} - -void call_get_result_fs( void * arg ) { - run_arg_type * run_arg = run_arg_safe_cast( arg ); - run_arg_get_result_fs( run_arg ); -} - - -void call_get_update_target_fs( void * arg ) { - run_arg_type * run_arg = run_arg_safe_cast( arg ); - run_arg_get_update_target_fs( run_arg ); -} - - - -void test_SMOOTHER_RUN( ) { - test_work_area_type * test_area = test_work_area_alloc("run_arg/SMOOTHER"); - { - enkf_fs_type * sim_fs = enkf_fs_create_fs("sim" , BLOCK_FS_DRIVER_ID , NULL , true); - enkf_fs_type * target_fs = enkf_fs_create_fs("target" , BLOCK_FS_DRIVER_ID , NULL , true); - run_arg_type * run_arg = run_arg_alloc_SMOOTHER_RUN(sim_fs , target_fs , 0 , 6 , "path"); - test_assert_true( run_arg_is_instance( run_arg )); - test_assert_ptr_equal( run_arg_get_init_fs( run_arg ) , sim_fs ); - test_assert_ptr_equal( run_arg_get_result_fs( run_arg ) , sim_fs ); - test_assert_ptr_equal( run_arg_get_update_target_fs( run_arg ) , target_fs ); - run_arg_free( run_arg ); - - enkf_fs_decref( sim_fs ); - enkf_fs_decref( target_fs ); - } - test_work_area_free( test_area ); -} - - -void alloc_invalid_run_arg(void *arg) { - test_work_area_type * test_area = test_work_area_alloc("run_arg/invalid"); - { - enkf_fs_type * fs = enkf_fs_create_fs("fs" , BLOCK_FS_DRIVER_ID , NULL , true); - run_arg_type * run_arg = run_arg_alloc_SMOOTHER_RUN(fs , fs , 0 , 6 , "path"); // This should explode ... - run_arg_free( run_arg ); - enkf_fs_decref( fs ); - } - test_work_area_free( test_area ); -} - - -void test_invalid_update_on_self( ) { - test_assert_util_abort( "run_arg_alloc" , alloc_invalid_run_arg , NULL); -} - - -void test_INIT_ONLY( ) { - test_work_area_type * test_area = test_work_area_alloc("run_arg/INIT"); - { - enkf_fs_type * init_fs = enkf_fs_create_fs("sim" , BLOCK_FS_DRIVER_ID , NULL , true); - - run_arg_type * run_arg = run_arg_alloc_INIT_ONLY(init_fs , 0 , 6 , "path"); - test_assert_true( run_arg_is_instance( run_arg )); - test_assert_ptr_equal( run_arg_get_init_fs( run_arg ) , init_fs ); - - test_assert_util_abort( "run_arg_get_result_fs" , call_get_result_fs , run_arg ); - test_assert_util_abort( "run_arg_get_update_target_fs" , call_get_update_target_fs , run_arg ); - run_arg_free( run_arg ); - - enkf_fs_decref( init_fs ); - } - test_work_area_free( test_area ); -} - - -void test_ENSEMBLE_EXPERIMENT( ) { - test_work_area_type * test_area = test_work_area_alloc("run_arg/ENS"); - { - enkf_fs_type * fs = enkf_fs_create_fs("sim" , BLOCK_FS_DRIVER_ID , NULL , true); - - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(fs , 0 , 6 , "path"); - test_assert_true( run_arg_is_instance( run_arg )); - - test_assert_ptr_equal( run_arg_get_init_fs( run_arg ) , fs ); - test_assert_ptr_equal( run_arg_get_result_fs( run_arg ) , fs ); - test_assert_util_abort( "run_arg_get_update_target_fs" , call_get_update_target_fs , run_arg ); - - run_arg_free( run_arg ); - enkf_fs_decref( fs ); - } - test_work_area_free( test_area ); -} - - -int main(int argc , char ** argv) { - test_queue_index(); - test_SMOOTHER_RUN(); - test_INIT_ONLY(); - test_ENSEMBLE_EXPERIMENT(); - test_invalid_update_on_self(); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_runpath_list.c b/ThirdParty/Ert/libenkf/tests/enkf_runpath_list.c deleted file mode 100644 index 95fcf9c937..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_runpath_list.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_runpath_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -void * add_pathlist( void * arg ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - runpath_list_type * list = arg_pack_iget_ptr( arg_pack , 0 ); - int offset = arg_pack_iget_int( arg_pack , 1 ); - int bs = arg_pack_iget_int( arg_pack , 2 ); - - int i; - for (i=0; i < bs; i++) - runpath_list_add( list , i + offset , 0, "Path" , "Basename"); - - return NULL; -} - -void test_runpath_list() { - runpath_list_type * list = runpath_list_alloc("DefaultFile"); - - test_assert_int_equal( runpath_list_size( list ) , 0 ); - - runpath_list_add( list , 3 , 0, "path" , "base"); - runpath_list_add( list , 2 , 0, "path" , "base"); - runpath_list_add( list , 1 , 0, "path" , "base"); - - runpath_list_add( list , 3 , 1, "path" , "base"); - runpath_list_add( list , 2 , 1, "path" , "base"); - runpath_list_add( list , 1 , 1, "path" , "base"); - - test_assert_int_equal( runpath_list_size( list ) , 6 ); - test_assert_int_equal( runpath_list_iget_iens( list , 0 ) , 3 ); - test_assert_int_equal( runpath_list_iget_iens( list , 2 ) , 1 ); - test_assert_int_equal( runpath_list_iget_iter( list , 3 ) , 1 ); - - runpath_list_clear( list ); - test_assert_int_equal( runpath_list_size( list ) , 0 ); - - test_assert_string_equal( runpath_list_get_line_fmt( list ) , RUNPATH_LIST_DEFAULT_LINE_FMT ); - { - const char * other_line = "%d %s %s"; - runpath_list_set_line_fmt( list , other_line ); - test_assert_string_equal( runpath_list_get_line_fmt( list ) , other_line ); - } - runpath_list_set_line_fmt( list , NULL ); - test_assert_string_equal( runpath_list_get_line_fmt( list ) , RUNPATH_LIST_DEFAULT_LINE_FMT ); - - { - const int block_size = 100; - const int threads = 100; - thread_pool_type * tp = thread_pool_alloc( threads , true ); - int it; - - for (it = 0; it < threads; it++) { - int iens_offset = it * block_size; - arg_pack_type * arg_pack = arg_pack_alloc(); - - arg_pack_append_ptr( arg_pack , list ); - arg_pack_append_int( arg_pack , iens_offset ); - arg_pack_append_int( arg_pack , block_size ); - - thread_pool_add_job( tp , add_pathlist , arg_pack ); - } - thread_pool_join( tp ); - test_assert_int_equal( runpath_list_size( list ) , block_size * threads ); - - { - test_work_area_type * work_area = test_work_area_alloc("enkf_runpath_list" ); - runpath_list_fprintf( list ); - { - int file_iens; - int file_iter; - char file_path[256]; - char file_base[256]; - int iens; - FILE * stream = util_fopen( runpath_list_get_export_file(list) , "r"); - for (iens = 0; iens < threads * block_size; iens++) { - int fscanf_return = fscanf( stream , "%d %s %s %d" , &file_iens , file_path , file_base, &file_iter); - test_assert_int_equal(fscanf_return, 4 ); - test_assert_int_equal( file_iens , iens ); - test_assert_int_equal( file_iter , 0 ); - } - fclose( stream ); - } - test_work_area_free( work_area ); - } - } - runpath_list_free( list ); -} - - - -void test_config( const char * config_file ) { - ert_test_context_type * test_context = ert_test_context_alloc( "RUNPATH_FILE" , config_file ); - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - hook_manager_type * hook_manager = enkf_main_get_hook_manager( enkf_main ); - - ert_test_context_run_worklow( test_context , "ARGECHO_WF"); - { - FILE * stream = util_fopen("runpath_list.txt" , "r"); - char runpath_file[256]; - fscanf(stream , "%s" , runpath_file ); - fclose( stream ); - test_assert_string_equal( runpath_file , hook_manager_get_runpath_list_file( hook_manager )); - } - - ert_test_context_free( test_context ); -} - - -void test_filename() { - runpath_list_type * list = runpath_list_alloc("DefaultFile"); - test_assert_string_equal( "DefaultFile" , runpath_list_get_export_file(list)); - runpath_list_set_export_file( list , "/tmp/file.txt"); - test_assert_string_equal( "/tmp/file.txt" , runpath_list_get_export_file(list)); - runpath_list_free( list ); -} - -int main(int argc , char ** argv) { - util_install_signals(); - { - test_runpath_list(); - test_config( argv[1] ); - test_filename(); - exit(0); - } -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_scale_correlated_std.c b/ThirdParty/Ert/libenkf/tests/enkf_scale_correlated_std.c deleted file mode 100644 index 59fd2aa401..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_scale_correlated_std.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'enkf_scale_correlated_std.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include - - - - -void test_scaling( ert_test_context_type * test_context , int nobs, const char** obs_keys ) { - stringlist_type * args = stringlist_alloc_new(); - for (int iobs=0; iobs < nobs; iobs++) - stringlist_append_ref( args , obs_keys[iobs]); - - test_assert_true( ert_test_context_run_worklow_job( test_context , "STD_SCALE" , args) ); - stringlist_free( args ); -} - - - -int main(int argc , const char ** argv) { - const char * config_file = argv[1]; - const char * workflow_job_file = argv[2]; - enkf_main_install_SIGNALS(); - { - ert_test_context_type * test_context = ert_test_context_alloc("std_scale_test" , config_file); - - ert_test_context_install_workflow_job( test_context , "STD_SCALE" , workflow_job_file ); - test_scaling(test_context , 1 , ( const char *[1] ) {"WWCT:OP_1"}); - test_scaling(test_context , 2 , ( const char *[2] ) {"WWCT:OP_1", "WWCT:OP_2"}); - test_scaling(test_context , 8 , ( const char *[8] ) {"RPR2_1", "RPR2_2","RPR2_3","RPR2_4","RPR2_5","RPR2_6","RPR2_7","RPR2_8"}); - - ert_test_context_free( test_context ); - } - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_select_case_job.c b/ThirdParty/Ert/libenkf/tests/enkf_select_case_job.c deleted file mode 100644 index 20e19df57b..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_select_case_job.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_select_case_job.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -int main(int argc , const char ** argv) { - enkf_main_install_SIGNALS(); - - const char * config_file = argv[1]; - const char * select_case_job = argv[2]; - - ert_test_context_type * test_context = ert_test_context_alloc("SELECT_CASE" , config_file ); - - test_assert_true( ert_test_context_install_workflow_job( test_context , "SELECT_CASE" , select_case_job)); - { - enkf_main_type * enkf_main = ert_test_context_get_main( test_context ); - stringlist_type * args = stringlist_alloc_new(); - stringlist_append_copy( args , "OtherCase"); - - test_assert_string_not_equal( "OtherCase" , enkf_main_get_current_fs( enkf_main )); - ert_test_context_run_worklow_job( test_context , "SELECT_CASE" , args); - test_assert_true( ert_test_context_run_worklow_job( test_context , "SELECT_CASE" , args) ); - test_assert_string_equal( "OtherCase" , enkf_main_get_current_fs( enkf_main )); - - stringlist_free( args ); - } - ert_test_context_free( test_context ); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_site_config.c b/ThirdParty/Ert/libenkf/tests/enkf_site_config.c deleted file mode 100644 index c709d49b6d..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_site_config.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_site_config.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include - - -#include - - - - -#define INCLUDE_KEY "INCLUDE" -#define DEFINE_KEY "DEFINE" - - -void test_empty() { - site_config_type * site_config = site_config_alloc_empty(); - site_config_free( site_config ); -} - - -void test_init(const char * config_file) { - site_config_type * site_config = site_config_alloc_empty(); - config_parser_type * config = config_alloc(); - config_content_type * content; - - site_config_add_config_items( config , true ); - content = config_parse(config , config_file , "--" , INCLUDE_KEY , DEFINE_KEY , NULL , CONFIG_UNRECOGNIZED_WARN , true); - if (!config_content_is_valid(content)) { - config_error_type * errors = config_content_get_errors( content ); - config_error_fprintf( errors , true , stderr ); - test_assert_true( false ); - } - - if (!site_config_init( site_config , content )) { - printf("Loading site_config from config failed\n"); - test_assert_true( false ); - } - - config_content_free( content ); - config_free( config ); - site_config_free( site_config ); -} - - -void test_job_script() { - test_work_area_type * test_area = test_work_area_alloc("site-config"); - { - site_config_type * site_config = site_config_alloc_empty(); - test_assert_false( site_config_has_job_script( site_config )); - - test_assert_false( site_config_set_job_script( site_config , "/does/not/exist" )); - test_assert_false( site_config_has_job_script( site_config )); - - { - FILE * job_script = util_fopen("Script.sh" , "w"); - fclose( job_script ); - } - test_assert_false( site_config_set_job_script( site_config , "Script.sh" )); - test_assert_false( site_config_has_job_script( site_config )); - chmod("Script.sh" , S_IRWXU ); - test_assert_true( site_config_set_job_script( site_config , "Script.sh" )); - test_assert_true( site_config_has_job_script( site_config )); - - test_assert_false( site_config_set_job_script( site_config , "DoesNotExits")); - test_assert_true( site_config_has_job_script( site_config )); - { - char * full_path = util_alloc_realpath( "Script.sh" ); - test_assert_string_equal( full_path , site_config_get_job_script( site_config)); - free( full_path ); - } - site_config_free( site_config ); - } - test_work_area_free( test_area ); -} - - - -int main(int argc , char ** argv) { - const char * site_config_file = argv[1]; - - util_install_signals(); - - test_empty(); - test_init( site_config_file ); - test_job_script(); - - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_state_manual_load_test.c b/ThirdParty/Ert/libenkf/tests/enkf_state_manual_load_test.c deleted file mode 100644 index c9a7cb9a02..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_state_manual_load_test.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_state_manual_load_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - - -int test_load_manually_to_new_case(enkf_main_type * enkf_main) { - int result = 0; - int iens = 0; - int iter = 0; - const char * casename = "new_case"; - enkf_main_select_fs( enkf_main , casename ); - - - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(fs , iens , iter , "simulations/run0"); - { - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr( arg_pack , enkf_main_iget_state(enkf_main, 0)); - arg_pack_append_ptr( arg_pack , run_arg ); - arg_pack_append_owned_ptr( arg_pack , stringlist_alloc_new() , stringlist_free__); - arg_pack_append_bool( arg_pack, true ); - arg_pack_append_ptr( arg_pack, &result ); - - enkf_state_load_from_forward_model_mt(arg_pack); - arg_pack_free(arg_pack); - } - - return result; -} - - - - -int main(int argc , char ** argv) { - enkf_main_install_SIGNALS(); - const char * root_path = argv[1]; - const char * config_file = argv[2]; - - test_work_area_type * work_area = test_work_area_alloc(config_file); - test_work_area_copy_directory_content( work_area , root_path ); - { - bool strict = true; - enkf_main_type * enkf_main = enkf_main_bootstrap( config_file , strict , true ); - - test_assert_int_equal( 0 , test_load_manually_to_new_case(enkf_main)); - - enkf_main_free( enkf_main ); - } - test_work_area_free(work_area); - - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_state_map.c b/ThirdParty/Ert/libenkf/tests/enkf_state_map.c deleted file mode 100644 index b94c80f3dd..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_state_map.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_state_map.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - - -void create_test() { - state_map_type * state_map = state_map_alloc(); - test_assert_true( state_map_is_instance( state_map )); - test_assert_int_equal( 0 , state_map_get_size( state_map )); - test_assert_false( state_map_is_readonly( state_map )); - state_map_free( state_map ); -} - -void get_test( ) { - state_map_type * state_map = state_map_alloc(); - test_assert_int_equal( STATE_UNDEFINED , state_map_iget( state_map , 0 )); - test_assert_int_equal( STATE_UNDEFINED , state_map_iget( state_map , 100 )); - state_map_free( state_map ); -} - -void set_test( ) { - state_map_type * state_map = state_map_alloc(); - state_map_iset( state_map , 0 , STATE_INITIALIZED ); - test_assert_int_equal( STATE_INITIALIZED , state_map_iget( state_map , 0 )); - - state_map_iset( state_map , 100 , STATE_INITIALIZED ); - test_assert_int_equal( STATE_INITIALIZED , state_map_iget( state_map , 100 )); - - test_assert_int_equal( STATE_UNDEFINED , state_map_iget( state_map , 50 )); - test_assert_int_equal( 101 , state_map_get_size( state_map )); - state_map_free( state_map ); -} - - -void load_empty_test() { - state_map_type * state_map = state_map_fread_alloc( "File/does/not/exists" ); - test_assert_true( state_map_is_instance( state_map )); - test_assert_int_equal( 0 , state_map_get_size( state_map )); - state_map_free( state_map ); -} - - -void test_equal() { - state_map_type * state_map1 = state_map_alloc(); - state_map_type * state_map2 = state_map_alloc(); - - test_assert_true( state_map_equal( state_map1 , state_map2 )); - for (int i =0; i < 25; i++) { - state_map_iset( state_map1 , i , STATE_INITIALIZED ); - state_map_iset( state_map2 , i , STATE_INITIALIZED ); - } - test_assert_true( state_map_equal( state_map1 , state_map2 )); - - state_map_iset( state_map2 , 15 , STATE_HAS_DATA ); - test_assert_false( state_map_equal( state_map1 , state_map2 )); - state_map_iset( state_map2 , 15 , STATE_LOAD_FAILURE ); - state_map_iset( state_map2 , 15 , STATE_INITIALIZED ); - test_assert_true( state_map_equal( state_map1 , state_map2 )); - - state_map_iset( state_map2 , 150 , STATE_INITIALIZED ); - test_assert_false( state_map_equal( state_map1 , state_map2 )); -} - - -void test_copy() { - state_map_type * state_map = state_map_alloc(); - state_map_iset( state_map , 0 , STATE_INITIALIZED ); - state_map_iset( state_map , 100 , STATE_INITIALIZED ); - { - state_map_type * copy = state_map_alloc_copy( state_map ); - test_assert_true( state_map_equal( copy , state_map )); - - state_map_iset( state_map , 10 , STATE_INITIALIZED ); - test_assert_false( state_map_equal( copy , state_map )); - - state_map_free( copy ); - } - state_map_free( state_map ); -} - - -void test_io( ) { - test_work_area_type * work_area = test_work_area_alloc( "enkf-state-map" ); - { - state_map_type * state_map = state_map_alloc(); - state_map_type * copy1 , *copy2; - state_map_iset( state_map , 0 , STATE_INITIALIZED ); - state_map_iset( state_map , 100 , STATE_INITIALIZED ); - state_map_fwrite( state_map , "map"); - - copy1 = state_map_fread_alloc( "map" ); - test_assert_true( state_map_equal( state_map , copy1 )); - - copy2 = state_map_alloc(); - test_assert_true( state_map_fread( copy2 , "map" ) ); - test_assert_true( state_map_equal( state_map , copy2 )); - - state_map_iset( copy2 , 67 , STATE_INITIALIZED ); - test_assert_false(state_map_equal( state_map , copy2 )); - - state_map_fread( copy2 , "map"); - test_assert_true( state_map_equal( state_map , copy2 )); - - test_assert_false(state_map_fread( copy2 , "DoesNotExist")); - test_assert_int_equal( 0 , state_map_get_size( copy2 )); - } - test_work_area_free( work_area ); -} - - - -void test_update_undefined( ) { - state_map_type * map = state_map_alloc( ); - - state_map_iset( map , 10 , STATE_INITIALIZED ); - test_assert_int_equal( STATE_UNDEFINED , state_map_iget( map , 5 ) ); - test_assert_int_equal( STATE_INITIALIZED , state_map_iget( map , 10 ) ); - - state_map_update_undefined( map , 5 , STATE_INITIALIZED ); - test_assert_int_equal( STATE_INITIALIZED , state_map_iget( map , 5 ) ); - - state_map_update_undefined( map , 10 , STATE_INITIALIZED ); - test_assert_int_equal( STATE_INITIALIZED , state_map_iget( map , 10 ) ); - - state_map_free( map ); -} - - -void test_update_matching( ) { - state_map_type * map = state_map_alloc( ); - - state_map_iset( map , 10 , STATE_INITIALIZED ); - state_map_iset( map , 3 , STATE_PARENT_FAILURE ); - test_assert_int_equal( STATE_UNDEFINED , state_map_iget( map , 5 ) ); - test_assert_int_equal( STATE_INITIALIZED , state_map_iget( map , 10 ) ); - - state_map_update_matching( map , 5 , STATE_UNDEFINED | STATE_LOAD_FAILURE , STATE_INITIALIZED ); - state_map_update_matching( map , 10 , STATE_UNDEFINED | STATE_LOAD_FAILURE , STATE_INITIALIZED ); - state_map_update_matching( map , 3 , STATE_UNDEFINED | STATE_LOAD_FAILURE , STATE_INITIALIZED ); - - test_assert_int_equal( STATE_INITIALIZED , state_map_iget( map , 5 ) ); - test_assert_int_equal( STATE_INITIALIZED , state_map_iget( map , 10 ) ); - test_assert_int_equal( STATE_PARENT_FAILURE , state_map_iget( map , 3 ) ); - - state_map_update_undefined( map , 10 , STATE_INITIALIZED ); - test_assert_int_equal( STATE_INITIALIZED , state_map_iget( map , 10 ) ); - - state_map_free( map ); -} - - -void test_select_matching( ) { - state_map_type * map = state_map_alloc( ); - bool_vector_type * mask1 = bool_vector_alloc(21 , false); - bool_vector_type * mask2 = bool_vector_alloc(1000 , true); - - state_map_iset( map , 10 , STATE_INITIALIZED ); - state_map_iset( map , 10 , STATE_HAS_DATA ); - state_map_iset( map , 20 , STATE_INITIALIZED ); - state_map_select_matching( map , mask1 , STATE_HAS_DATA | STATE_INITIALIZED ); - state_map_select_matching( map , mask2 , STATE_HAS_DATA | STATE_INITIALIZED ); - - for (int i=0; i < bool_vector_size( mask1 ); i++) { - if (i==10) - test_assert_true( bool_vector_iget( mask1 , i )); - else if (i== 20) - test_assert_true( bool_vector_iget( mask1 , i )); - else { - test_assert_false( bool_vector_iget( mask1 , i )); - test_assert_true( bool_vector_iget( mask2 , i )); - } - } - - state_map_iset( map , 50 , STATE_INITIALIZED ); - state_map_select_matching( map , mask1 , STATE_HAS_DATA | STATE_INITIALIZED ); - test_assert_int_equal(bool_vector_size( mask1 ), 21); - - bool_vector_free( mask1 ); - bool_vector_free( mask2 ); - state_map_free( map ); -} - - -void test_deselect_matching( ) { - state_map_type * map = state_map_alloc( ); - bool_vector_type * mask1 = bool_vector_alloc(0 , false); - bool_vector_type * mask2 = bool_vector_alloc(1000 , true); - - state_map_iset( map , 10 , STATE_INITIALIZED ); - state_map_iset( map , 10 , STATE_HAS_DATA ); - state_map_iset( map , 20 , STATE_INITIALIZED ); - state_map_deselect_matching( map , mask1 , STATE_HAS_DATA | STATE_INITIALIZED ); - state_map_deselect_matching( map , mask2 , STATE_HAS_DATA | STATE_INITIALIZED ); - - test_assert_int_equal( state_map_get_size( map ) , bool_vector_size( mask1 )); - - for (int i=0; i < bool_vector_size( mask1 ); i++) { - if (i==10) - test_assert_false( bool_vector_iget( mask1 , i )); - else if (i== 20) - test_assert_false( bool_vector_iget( mask2 , i )); - else { - test_assert_false( bool_vector_iget( mask1 , i )); - test_assert_true( bool_vector_iget( mask2 , i )); - } - } - - bool_vector_free( mask1 ); - bool_vector_free( mask2 ); - state_map_free( map ); -} - - -void test_set_from_mask() { - int i; - state_map_type * map1 = state_map_alloc(); - state_map_type * map2 = state_map_alloc(); - bool_vector_type * mask = bool_vector_alloc(0, false); - bool_vector_iset(mask , 10 , true); - bool_vector_iset(mask , 20 , true); - - state_map_set_from_mask(map1 , mask , STATE_INITIALIZED); - state_map_set_from_inverted_mask(map2 , mask , STATE_INITIALIZED); - test_assert_int_equal(21 , state_map_get_size(map1)); - test_assert_int_equal(21 , state_map_get_size(map2)); - for (i = 0; i < state_map_get_size(map1); i++) { - if (i == 10 || i== 20) { - test_assert_int_equal( STATE_INITIALIZED , state_map_iget( map1 , i) ); - test_assert_int_equal( STATE_UNDEFINED , state_map_iget(map2 , i)); - } - else { - test_assert_int_equal(STATE_UNDEFINED , state_map_iget(map1 , i )); - test_assert_int_equal( STATE_INITIALIZED , state_map_iget(map2 , i)); - } - - - } -} - - -void test_count_matching() { - state_map_type * map1 = state_map_alloc(); - state_map_iset(map1 , 10 , STATE_INITIALIZED ); - - state_map_iset(map1 , 15 , STATE_INITIALIZED ); - state_map_iset(map1 , 15 , STATE_HAS_DATA ); - - state_map_iset(map1 , 16 , STATE_INITIALIZED ); - state_map_iset(map1 , 16 , STATE_HAS_DATA ); - state_map_iset(map1 , 16 , STATE_LOAD_FAILURE ); - - test_assert_int_equal( 1 , state_map_count_matching( map1 , STATE_HAS_DATA)); - test_assert_int_equal( 2 , state_map_count_matching( map1 , STATE_HAS_DATA | STATE_LOAD_FAILURE)); - test_assert_int_equal( 3 , state_map_count_matching( map1 , STATE_HAS_DATA | STATE_LOAD_FAILURE | STATE_INITIALIZED)); - - state_map_free( map1 ); -} - -// Probably means that the target should be explicitly set to -// undefined before workflows which automatically change case. -void test_transitions() { - - test_assert_false( state_map_legal_transition(STATE_UNDEFINED , STATE_UNDEFINED )); - test_assert_true( state_map_legal_transition(STATE_UNDEFINED , STATE_INITIALIZED )); - test_assert_false( state_map_legal_transition(STATE_UNDEFINED , STATE_HAS_DATA )); - test_assert_false( state_map_legal_transition(STATE_UNDEFINED , STATE_LOAD_FAILURE )); - test_assert_true( state_map_legal_transition(STATE_UNDEFINED , STATE_PARENT_FAILURE )); - - test_assert_false( state_map_legal_transition(STATE_INITIALIZED , STATE_UNDEFINED )); - test_assert_true( state_map_legal_transition(STATE_INITIALIZED , STATE_INITIALIZED )); - test_assert_true( state_map_legal_transition(STATE_INITIALIZED , STATE_HAS_DATA )); - test_assert_true( state_map_legal_transition(STATE_INITIALIZED , STATE_LOAD_FAILURE )); - test_assert_true( state_map_legal_transition(STATE_INITIALIZED , STATE_PARENT_FAILURE )); // Should maybe false - if the commenta baove is taken into account. - - test_assert_false( state_map_legal_transition(STATE_HAS_DATA , STATE_UNDEFINED )); - test_assert_true( state_map_legal_transition(STATE_HAS_DATA , STATE_INITIALIZED )); - test_assert_true( state_map_legal_transition(STATE_HAS_DATA , STATE_HAS_DATA )); - test_assert_true( state_map_legal_transition(STATE_HAS_DATA , STATE_LOAD_FAILURE )); - test_assert_true( state_map_legal_transition(STATE_HAS_DATA , STATE_PARENT_FAILURE )); // Rerun - - test_assert_false( state_map_legal_transition(STATE_LOAD_FAILURE , STATE_UNDEFINED )); - test_assert_true( state_map_legal_transition(STATE_LOAD_FAILURE , STATE_INITIALIZED )); - test_assert_true( state_map_legal_transition(STATE_LOAD_FAILURE , STATE_HAS_DATA )); - test_assert_true( state_map_legal_transition(STATE_LOAD_FAILURE , STATE_LOAD_FAILURE )); - test_assert_false( state_map_legal_transition(STATE_LOAD_FAILURE , STATE_PARENT_FAILURE )); - - test_assert_false( state_map_legal_transition(STATE_PARENT_FAILURE , STATE_UNDEFINED )); - test_assert_true( state_map_legal_transition(STATE_PARENT_FAILURE , STATE_INITIALIZED )); - test_assert_false( state_map_legal_transition(STATE_PARENT_FAILURE , STATE_HAS_DATA )); - test_assert_false( state_map_legal_transition(STATE_PARENT_FAILURE , STATE_LOAD_FAILURE )); - test_assert_true( state_map_legal_transition(STATE_PARENT_FAILURE , STATE_PARENT_FAILURE )); -} - - - -void test_readonly() { - { - state_map_type * map1 = state_map_fread_alloc_readonly("FileDoesNotExist"); - - test_assert_true(state_map_is_instance(map1)); - test_assert_int_equal(0 , state_map_get_size( map1 )); - test_assert_true( state_map_is_readonly( map1 )); - state_map_free(map1); - } - { - test_work_area_type * work_area = test_work_area_alloc("state-map"); - state_map_type * map1 = state_map_alloc(); - - state_map_iset(map1 , 5 , STATE_INITIALIZED); - state_map_iset(map1 , 9 , STATE_INITIALIZED); - - state_map_fwrite(map1 , "map1"); - { - state_map_type * map2 = state_map_fread_alloc_readonly("map1"); - - test_assert_true(state_map_equal(map1 , map2)); - state_map_free(map2); - } - test_work_area_free( work_area ); - state_map_free(map1); - } -} - - -int main(int argc , char ** argv) { - create_test(); - get_test(); - set_test(); - load_empty_test(); - test_equal(); - test_copy(); - test_io(); - test_update_undefined( ); - test_select_matching(); - test_count_matching(); - test_transitions(); - test_readonly(); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_state_report_step_compatible.c b/ThirdParty/Ert/libenkf/tests/enkf_state_report_step_compatible.c deleted file mode 100644 index 038fde60b0..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_state_report_step_compatible.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_state_report_step_compatible.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - - -bool check_ecl_sum_compatible(const enkf_main_type * enkf_main) -{ - stringlist_type * msg_list = stringlist_alloc_new(); - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(fs , 0 , 0 , "simulations/run0"); - - state_map_type * state_map = enkf_fs_get_state_map(fs); - state_map_iset(state_map, 0, STATE_INITIALIZED); - - int error = enkf_state_load_from_forward_model( state , run_arg , msg_list ); - - - stringlist_free( msg_list ); - return (REPORT_STEP_INCOMPATIBLE & error) ? false : true; -} - - - -int main(int argc , char ** argv) { - enkf_main_install_SIGNALS(); - const char * root_path = argv[1]; - const char * config_file = argv[2]; - const char * compatible_str = argv[3]; - bool check_compatible; - - test_assert_true( util_sscanf_bool( compatible_str , &check_compatible)); - - test_work_area_type * work_area = test_work_area_alloc(config_file ); - test_work_area_copy_directory_content( work_area , root_path ); - - bool strict = true; - enkf_main_type * enkf_main = enkf_main_bootstrap( config_file , strict , true ); - - - test_assert_bool_equal(check_compatible , check_ecl_sum_compatible(enkf_main)); - - enkf_main_free( enkf_main ); - test_work_area_free(work_area); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_state_skip_summary_load_test.c b/ThirdParty/Ert/libenkf/tests/enkf_state_skip_summary_load_test.c deleted file mode 100644 index 09a19290fa..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_state_skip_summary_load_test.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_state_no_summary_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - - -bool check_ecl_sum_loaded(const enkf_main_type * enkf_main) -{ - enkf_fs_type * fs = enkf_main_get_fs( enkf_main ); - stringlist_type * msg_list = stringlist_alloc_new(); - enkf_state_type * state1 = enkf_main_iget_state( enkf_main , 0 ); - run_arg_type * run_arg1 = run_arg_alloc_ENSEMBLE_EXPERIMENT( fs , 0 , 0 , "simulations/run0"); - enkf_state_type * state2 = enkf_main_iget_state( enkf_main , 1 ); - run_arg_type * run_arg2 = run_arg_alloc_ENSEMBLE_EXPERIMENT( fs , 0 , 0 , "simulations/run1"); - - - state_map_type * state_map = enkf_fs_get_state_map(fs); - state_map_iset(state_map, 0, STATE_INITIALIZED); - - int error = enkf_state_load_from_forward_model( state1 , run_arg1 , msg_list ); - - - state_map_iset(state_map, 1, STATE_INITIALIZED); - error = enkf_state_load_from_forward_model( state2 , run_arg2 , msg_list ); - - stringlist_free( msg_list ); - return (0 == error); -} - - - -int main(int argc , char ** argv) { - enkf_main_install_SIGNALS(); - const char * root_path = argv[1]; - const char * config_file = argv[2]; - - test_work_area_type * work_area = test_work_area_alloc(config_file ); - test_work_area_copy_directory_content( work_area , root_path ); - - bool strict = true; - enkf_main_type * enkf_main = enkf_main_bootstrap( config_file , strict , true ); - - test_assert_true( check_ecl_sum_loaded(enkf_main) ); - - enkf_main_free( enkf_main ); - test_work_area_free(work_area); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_time_map.c b/ThirdParty/Ert/libenkf/tests/enkf_time_map.c deleted file mode 100644 index 04daccbceb..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_time_map.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_time_map.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include "ert/util/build_config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -void ecl_test( const char * ecl_case ) { - ecl_sum_type * ecl_sum = ecl_sum_fread_alloc_case( ecl_case , ":"); - time_t start_time = ecl_sum_get_start_time( ecl_sum ); - time_t end_time = ecl_sum_get_end_time( ecl_sum ); - time_map_type * ecl_map = time_map_alloc( ); - - test_assert_true( time_map_summary_update( ecl_map , ecl_sum ) ); - test_assert_true( time_map_summary_update( ecl_map , ecl_sum ) ); - - test_assert_time_t_equal( time_map_get_start_time( ecl_map ) , start_time ); - test_assert_time_t_equal( time_map_get_end_time( ecl_map ) , end_time ); - test_assert_double_equal( time_map_get_end_days( ecl_map ) , ecl_sum_get_sim_length( ecl_sum )); - - time_map_clear( ecl_map ); - time_map_update( ecl_map , 1 , 256 ); - time_map_set_strict( ecl_map , false ); - test_assert_false( time_map_summary_update( ecl_map , ecl_sum )); - - time_map_free( ecl_map ); - ecl_sum_free( ecl_sum ); -} - - -static void map_update( void * arg ) { - vector_type * arg_vector = vector_safe_cast( arg ); - time_map_type * tmap = vector_iget( arg_vector , 0 ); - ecl_sum_type * sum = vector_iget( arg_vector , 1 ); - - time_map_summary_update( tmap , sum ); -} - - - -void test_inconsistent_summary( const char * case1, const char * case2) { - ecl_sum_type * ecl_sum1 = ecl_sum_fread_alloc_case( case1 , ":"); - ecl_sum_type * ecl_sum2 = ecl_sum_fread_alloc_case( case2 , ":"); - - time_map_type * ecl_map = time_map_alloc( ); - - test_assert_true( time_map_summary_update( ecl_map , ecl_sum1 ) ); - { - vector_type * arg = vector_alloc_new(); - vector_append_ref( arg , ecl_map ); - vector_append_ref( arg , ecl_sum2 ); - test_assert_util_abort("time_map_summary_update_abort" , map_update , arg); - vector_free( arg ); - } - - time_map_free( ecl_map ); - ecl_sum_free( ecl_sum1 ); - ecl_sum_free( ecl_sum2 ); -} - -static void alloc_index_map( void * arg) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - time_map_type * map = arg_pack_iget_ptr( arg_pack , 0 ); - ecl_sum_type * sum = arg_pack_iget_ptr( arg_pack , 1 ); - - time_map_alloc_index_map( map , sum ); -} - - - -void test_refcase( const char * refcase_name , const char * case1, const char * case2 , const char * case3 , const char * case4) { - ecl_sum_type * refcase = ecl_sum_fread_alloc_case( refcase_name , ":"); - ecl_sum_type * ecl_sum1 = ecl_sum_fread_alloc_case( case1 , ":"); - ecl_sum_type * ecl_sum2 = ecl_sum_fread_alloc_case( case2 , ":"); - ecl_sum_type * ecl_sum3 = ecl_sum_fread_alloc_case( case3 , ":"); - ecl_sum_type * ecl_sum4 = ecl_sum_fread_alloc_case( case4 , ":"); - - { - time_map_type * ecl_map = time_map_alloc( ); - test_assert_false( time_map_has_refcase( ecl_map )); - test_assert_true( time_map_attach_refcase( ecl_map , refcase ) ); - test_assert_true( time_map_has_refcase( ecl_map )); - time_map_free( ecl_map ); - } - - - { - time_map_type * ecl_map = time_map_alloc( ); - time_map_attach_refcase( ecl_map , refcase ); - test_assert_true( time_map_summary_update( ecl_map , ecl_sum1 ) ); - } - - { - time_map_type * ecl_map = time_map_alloc( ); - - time_map_set_strict( ecl_map , false ); - time_map_attach_refcase( ecl_map , refcase ); - - test_assert_false( time_map_summary_update( ecl_map , ecl_sum2 ) ); - test_assert_int_equal( 25 , time_map_get_size( ecl_map )); - test_assert_true( time_map_summary_update( ecl_map , ecl_sum1 ) ); - test_assert_int_equal( 63 , time_map_get_size( ecl_map )); - } - - { - time_map_type * ecl_map = time_map_alloc( ); - test_assert_true( time_map_summary_update( ecl_map , ecl_sum2 ) ); - test_assert_false( time_map_attach_refcase( ecl_map , refcase )); - } - - - { - test_work_area_type * work_area = test_work_area_alloc( "time_map/attach_short_refcase"); - { - time_map_type * ecl_map = time_map_alloc( ); - test_assert_true( time_map_summary_update( ecl_map , refcase ) ); - test_assert_true( time_map_update( ecl_map , ecl_sum_get_last_report_step( refcase ) + 1 , ecl_sum_get_end_time( refcase ) + 100 )); - test_assert_true( time_map_update( ecl_map , ecl_sum_get_last_report_step( refcase ) + 2 , ecl_sum_get_end_time( refcase ) + 200 )); - test_assert_true( time_map_update( ecl_map , ecl_sum_get_last_report_step( refcase ) + 3 , ecl_sum_get_end_time( refcase ) + 300 )); - time_map_fwrite( ecl_map , "time_map"); - time_map_free( ecl_map ); - } - { - time_map_type * ecl_map = time_map_alloc( ); - time_map_fread(ecl_map , "time_map"); - test_assert_true( time_map_attach_refcase( ecl_map , refcase ) ); - time_map_free( ecl_map ); - } - test_work_area_free( work_area ); - } - - - - ecl_sum_free( refcase ); - ecl_sum_free( ecl_sum1 ); - ecl_sum_free( ecl_sum2 ); - ecl_sum_free( ecl_sum3 ); - ecl_sum_free( ecl_sum4 ); -} - - -void test_index_map( const char * case1, const char * case2 , const char * case3 , const char * case4) { - ecl_sum_type * ecl_sum1 = ecl_sum_fread_alloc_case( case1 , ":"); - ecl_sum_type * ecl_sum2 = ecl_sum_fread_alloc_case( case2 , ":"); - ecl_sum_type * ecl_sum3 = ecl_sum_fread_alloc_case( case3 , ":"); - ecl_sum_type * ecl_sum4 = ecl_sum_fread_alloc_case( case4 , ":"); - - time_map_type * ecl_map = time_map_alloc( ); - - { - int_vector_type * index_map = time_map_alloc_index_map( ecl_map , ecl_sum1 ); - test_assert_int_equal( int_vector_size( index_map ) , 0); - int_vector_free( index_map ); - } - - test_assert_true( time_map_summary_update( ecl_map , ecl_sum1 ) ); - { - int_vector_type * index_map = time_map_alloc_index_map( ecl_map , ecl_sum1 ); - int i; - for (i=0; i < int_vector_size( index_map ); i++) - test_assert_int_equal( i , int_vector_iget( index_map , i )); - - test_assert_int_equal( int_vector_size( index_map ) , ecl_sum_get_last_report_step( ecl_sum1) + 1); - int_vector_free( index_map ); - } - - /* case2 has an extra tstep in the middle of the case. */ - time_map_set_strict( ecl_map , false ); - test_assert_false( time_map_summary_update( ecl_map , ecl_sum2 ) ); - { - int_vector_type * index_map = time_map_alloc_index_map( ecl_map , ecl_sum2 ); - test_assert_int_equal( int_vector_size( index_map ) , ecl_sum_get_last_report_step( ecl_sum2)); - test_assert_int_equal( int_vector_iget( index_map , 24) , 24); - test_assert_int_equal( int_vector_iget( index_map , 25) , 26); - int_vector_free( index_map ); - } - - - /* case3 has an extra tstep in the middle, and ends prematurely */ - test_assert_false( time_map_summary_update( ecl_map , ecl_sum3 ) ); - { - int_vector_type * index_map = time_map_alloc_index_map( ecl_map , ecl_sum3 ); - test_assert_int_equal( int_vector_size( index_map ) , ecl_sum_get_last_report_step( ecl_sum3)); - int_vector_free( index_map ); - } - - - /* case4 has a missing tstep in the middle - that is not handled; and we abort */ - test_assert_false( time_map_summary_update( ecl_map , ecl_sum4 ) ); - { - arg_pack_type * arg = arg_pack_alloc(); - arg_pack_append_ptr( arg , ecl_map ); - arg_pack_append_ptr( arg , ecl_sum4 ); - - test_assert_util_abort( "time_map_alloc_index_map" , alloc_index_map , arg); - arg_pack_free( arg ); - } - - - - time_map_free( ecl_map ); - ecl_sum_free( ecl_sum1 ); - ecl_sum_free( ecl_sum2 ); - ecl_sum_free( ecl_sum3 ); - ecl_sum_free( ecl_sum4 ); -} - - -void simple_test() { - time_map_type * time_map = time_map_alloc( ); - test_work_area_type * work_area = test_work_area_alloc("enkf_time_map" ); - const char * mapfile = "map"; - - time_map_set_strict( time_map , false ); - test_assert_true( time_map_update( time_map , 0 , 100 ) ); - test_assert_true( time_map_update( time_map , 1 , 200 ) ); - test_assert_true( time_map_update( time_map , 1 , 200 ) ); - test_assert_false( time_map_update( time_map , 1 , 250 ) ); - - test_assert_true( time_map_equal( time_map , time_map ) ); - time_map_fwrite( time_map , mapfile); - { - time_map_type * time_map2 = time_map_alloc( ); - - test_assert_false( time_map_equal( time_map , time_map2 ) ); - time_map_fread( time_map2 , mapfile ); - test_assert_true( time_map_equal( time_map , time_map2 ) ); - time_map_free( time_map2 ); - } - { - time_t mtime1 = util_file_mtime( mapfile ); - sleep(2); - time_map_fwrite( time_map , mapfile); - - test_assert_time_t_equal( mtime1 , util_file_mtime( mapfile ) ); - time_map_update( time_map , 2 , 300 ); - time_map_fwrite( time_map , mapfile); - test_assert_time_t_not_equal( mtime1 , util_file_mtime( mapfile ) ); - } - test_work_area_free( work_area ); -} - - -static void simple_update(void * arg) { - time_map_type * tmap = time_map_safe_cast( arg ); - - time_map_update( tmap , 0 , 101 ); -} - - - -void simple_test_inconsistent() { - time_map_type * time_map = time_map_alloc( ); - - test_assert_true( time_map_update( time_map , 0 , 100 ) ); - time_map_set_strict( time_map , false ); - test_assert_false( time_map_update( time_map , 0 , 101 ) ); - - time_map_set_strict( time_map , true ); - test_assert_util_abort( "time_map_update_abort" , simple_update , time_map ); - - time_map_free( time_map ); -} - - - -#define MAP_SIZE 10000 - -void * update_time_map( void * arg ) { - time_map_type * time_map = time_map_safe_cast( arg ); - int i; - for (i=0; i < MAP_SIZE; i++) - time_map_update( time_map , i , i ); - - test_assert_int_equal( MAP_SIZE , time_map_get_size( time_map )); - return NULL; -} - - -void thread_test() { - time_map_type * time_map = time_map_alloc( ); - test_assert_false( time_map_is_readonly( time_map )); - { - int pool_size = 1000; - thread_pool_type * tp = thread_pool_alloc( pool_size/2 , true ); - - thread_pool_add_job( tp , update_time_map , time_map ); - - thread_pool_join(tp); - thread_pool_free(tp); - } - { - int i; - for (i=0; i < MAP_SIZE; i++) - test_assert_true( time_map_iget( time_map , i ) == i ); - } - time_map_free( time_map ); -} - - - -void test_read_only() { - test_work_area_type * work_area = test_work_area_alloc("time-map"); - { - time_map_type * tm = time_map_alloc( ); - - test_assert_true( time_map_is_instance( tm )); - test_assert_true( time_map_is_strict( tm )); - test_assert_false( time_map_is_readonly( tm )); - - time_map_update( tm , 0 , 0 ); - time_map_update( tm , 1 , 10 ); - time_map_update( tm , 2 , 20 ); - - time_map_fwrite( tm , "case/files/time-map" ); - time_map_free( tm ); - } - { - time_map_type * tm = time_map_fread_alloc_readonly( "case/files/time-map"); - test_assert_time_t_equal( 0 , time_map_iget( tm , 0 )); - test_assert_time_t_equal( 10 , time_map_iget( tm , 1 )); - test_assert_time_t_equal( 20 , time_map_iget( tm , 2 )); - test_assert_int_equal( 3 , time_map_get_size( tm )); - time_map_free( tm ); - } - { - time_map_type * tm = enkf_fs_alloc_readonly_time_map( "case" ); - test_assert_time_t_equal( 0 , time_map_iget( tm , 0 )); - test_assert_time_t_equal( 10 , time_map_iget( tm , 1 )); - test_assert_time_t_equal( 20 , time_map_iget( tm , 2 )); - test_assert_int_equal( 3 , time_map_get_size( tm )); - time_map_free( tm ); - } - { - time_map_type * tm = time_map_fread_alloc_readonly( "DoesNotExist"); - test_assert_true( time_map_is_instance( tm )); - test_assert_true( time_map_is_readonly( tm )); - test_assert_int_equal(0 , time_map_get_size( tm )); - time_map_free( tm ); - } - test_work_area_free( work_area ); -} - - -int main(int argc , char ** argv) { - - enkf_main_install_SIGNALS(); - ert_log_init_log(0 , NULL , false ); // Make sure there will be no logging. - - if (argc == 1) { - simple_test(); - simple_test_inconsistent(); - thread_test(); - } else { - ecl_test( argv[1] ); - test_inconsistent_summary( argv[1] , argv[2]); - test_index_map(argv[1] , argv[2] , argv[3] , argv[4]); - test_refcase( argv[1] , argv[1] , argv[2] , argv[3] , argv[4]); - } - - test_read_only(); - - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/enkf_umask_config_test.c b/ThirdParty/Ert/libenkf/tests/enkf_umask_config_test.c deleted file mode 100644 index afa61e0833..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_umask_config_test.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - This file is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - - -int main(int argc , char ** argv) { - enkf_main_install_SIGNALS(); - - const char * config_file = argv[1]; - ert_test_context_type * test_context = ert_test_context_alloc("VerifyJobsFileTest" , config_file); - enkf_main_type * enkf_main = ert_test_context_get_main(test_context); - - { - const int ens_size = enkf_main_get_ensemble_size( enkf_main ); - bool_vector_type * iactive = bool_vector_alloc(0, false); - bool_vector_iset( iactive , ens_size - 1 , true ); - - enkf_main_create_run_path(enkf_main , iactive , 0); - bool_vector_free(iactive); - } - - const char * filename = util_alloc_filename(ert_test_context_get_cwd(test_context), - "simulations/run0/jobs.py", NULL); - const char * jobs_file_content = util_fread_alloc_file_content(filename, NULL); - - test_assert_true (strstr(jobs_file_content, "umask = 0022") != NULL); - test_assert_false (strstr(jobs_file_content, "umask = 0023") != NULL); - test_assert_false (strstr(jobs_file_content, "umask = 0032") != NULL); - test_assert_false (strstr(jobs_file_content, "umask = 0122") != NULL); - test_assert_false (strstr(jobs_file_content, "umask = 1022") != NULL); - - ert_test_context_free(test_context); - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_workflow_job_test.c b/ThirdParty/Ert/libenkf/tests/enkf_workflow_job_test.c deleted file mode 100644 index d924dc0440..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_workflow_job_test.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_workflow_job_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include - - -ert_test_context_type * create_context( const char * config_file, const char * name ) { - ert_test_context_type * test_context = ert_test_context_alloc(name , config_file); - test_assert_not_NULL(test_context); - return test_context; -} - -void test_create_case_job(ert_test_context_type * test_context, const char * job_name , const char * job_file) { - stringlist_type * args = stringlist_alloc_new(); - stringlist_append_copy( args , "newly_created_case"); - test_assert_true( ert_test_context_install_workflow_job( test_context , job_name , job_file )); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - char * new_case = util_alloc_filename( "storage" , "newly_created_case" , NULL); - test_assert_true(util_is_directory(new_case)); - free(new_case); - - stringlist_free( args ); -} - - -void test_init_case_job(ert_test_context_type * test_context, const char * job_name , const char * job_file) { - stringlist_type * args = stringlist_alloc_new(); - enkf_main_type * enkf_main = ert_test_context_get_main(test_context); - - test_assert_true( ert_test_context_install_workflow_job( test_context , "JOB" , job_file ) ); - - //Test init current case from existing - { - enkf_fs_type * cur_fs = enkf_main_mount_alt_fs( enkf_main , "new_current_case" , true ); - enkf_main_select_fs(enkf_main, "new_current_case"); - - test_assert_ptr_not_equal(cur_fs , enkf_main_get_fs( enkf_main )); - - stringlist_append_copy( args, "default"); //case to init from - test_assert_true( ert_test_context_run_worklow_job( test_context , "JOB" , args) ); - - enkf_fs_decref(cur_fs); - } - - { - const char * current_case = enkf_main_get_current_fs( enkf_main ); - test_assert_string_equal(current_case, "new_current_case"); - test_assert_true(enkf_fs_has_node(enkf_main_get_fs(enkf_main), "PERMZ", PARAMETER, 0, 0)); // This had state = ANALYZED; might be unfixable. - - enkf_fs_type * default_fs = enkf_main_mount_alt_fs( enkf_main , "default" , true ); - state_map_type * default_state_map = enkf_fs_get_state_map(default_fs); - state_map_type * current_state_map = enkf_fs_get_state_map(enkf_main_get_fs(enkf_main)); - test_assert_int_equal(state_map_get_size(default_state_map), state_map_get_size(current_state_map)); - enkf_fs_decref(default_fs); - } - - - //Test init case from existing case: - stringlist_clear(args); - stringlist_append_copy(args, "default"); //case to init from - stringlist_append_copy(args, "new_not_current_case"); - test_assert_true( ert_test_context_run_worklow_job( test_context , "JOB" , args) ); - { - enkf_fs_type * fs = enkf_main_mount_alt_fs(enkf_main, "new_not_current_case", true); - test_assert_not_NULL( fs ); - test_assert_true( enkf_fs_has_node(fs, "PERMZ", PARAMETER, 0, 0)); // This had state = ANALYZED; might be unfixable. - - enkf_fs_type * default_fs = enkf_main_mount_alt_fs( enkf_main , "default" , true ); - state_map_type * default_state_map = enkf_fs_get_state_map(default_fs); - state_map_type * new_state_map = enkf_fs_get_state_map(fs); - test_assert_int_equal(state_map_get_size(default_state_map), state_map_get_size(new_state_map)); - enkf_fs_decref(fs); - } - - stringlist_free( args ); -} - - -void test_load_results_job(ert_test_context_type * test_context , const char * job_name , const char * job_file) { - stringlist_type * args = stringlist_alloc_new(); - ert_test_context_install_workflow_job( test_context , job_name , job_file ); - stringlist_append_copy( args , "0"); - stringlist_append_copy( args , ","); - stringlist_append_copy( args , "1"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - stringlist_free( args ); -} - - -void test_load_results_iter_job(ert_test_context_type * test_context , const char * job_name , const char * job_file) { - - stringlist_type * args = stringlist_alloc_new(); - ert_test_context_install_workflow_job( test_context , job_name , job_file ); - stringlist_append_copy( args , "0"); - stringlist_append_copy( args , "0"); - stringlist_append_copy( args , ","); - stringlist_append_copy( args , "1"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - stringlist_free( args ); -} - - -void test_rank_realizations_on_observations_job(ert_test_context_type * test_context , const char * job_name , const char * job_file) { - stringlist_type * args = stringlist_alloc_new(); - ert_test_context_install_workflow_job( test_context , job_name , job_file ); - - stringlist_append_copy( args , "NameOfObsRanking1"); - stringlist_append_copy( args , "|"); - stringlist_append_copy( args , "WOPR:*"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_clear(args); - stringlist_append_copy( args , "NameOfObsRanking2"); - stringlist_append_copy( args, "1-5"); - stringlist_append_copy( args, "55"); - stringlist_append_copy( args , "|"); - stringlist_append_copy( args , "WWCT:*"); - stringlist_append_copy( args , "WOPR:*"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_clear(args); - stringlist_append_copy( args , "NameOfObsRanking3"); - stringlist_append_copy( args, "5"); - stringlist_append_copy( args, "55"); - stringlist_append_copy( args, "|"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_clear(args); - stringlist_append_copy( args , "NameOfObsRanking4"); - stringlist_append_copy( args, "1,3,5-10"); - stringlist_append_copy( args, "55"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_clear(args); - stringlist_append_copy( args , "NameOfObsRanking5"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_clear(args); - stringlist_append_copy( args , "NameOfObsRanking6"); - stringlist_append_copy( args, "|"); - stringlist_append_copy( args , "UnrecognizableObservation"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_free( args ); -} - - -void test_rank_realizations_on_data_job(ert_test_context_type * test_context , const char * job_name , const char * job_file) { - stringlist_type * args = stringlist_alloc_new(); - ert_test_context_install_workflow_job( test_context , job_name , job_file ); - - stringlist_append_copy( args , "NameOfDataRanking"); - stringlist_append_copy( args , "PORO:1,2,3"); - stringlist_append_copy( args , "false"); - stringlist_append_copy( args , "0"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_clear(args); - stringlist_append_copy( args , "NameOfDataRanking2"); - stringlist_append_copy( args , "PORO:1,2,3"); - stringlist_append_copy( args , "false"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_free( args ); -} - -void test_export_ranking(ert_test_context_type * test_context , const char * job_name , const char * job_file) { - stringlist_type * args = stringlist_alloc_new(); - ert_test_context_install_workflow_job( test_context , job_name , job_file ); - - stringlist_append_copy( args , "NameOfDataRanking"); - stringlist_append_copy( args , "/tmp/fileToSaveDataRankingIn.txt"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_clear(args); - stringlist_append_copy( args , "NameOfObsRanking1"); - stringlist_append_copy( args , "/tmp/fileToSaveObservationRankingIn1.txt"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_clear(args); - stringlist_append_copy( args , "NameOfObsRanking6"); - stringlist_append_copy( args , "/tmp/fileToSaveObservationRankingIn6.txt"); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - stringlist_free( args ); -} - - -void test_init_misfit_table(ert_test_context_type * test_context , const char * job_name , const char * job_file) { - stringlist_type * args = stringlist_alloc_new(); - ert_test_context_install_workflow_job( test_context , job_name , job_file ); - - enkf_main_type * enkf_main = ert_test_context_get_main(test_context); - enkf_fs_type * fs = enkf_main_get_fs(enkf_main); - - misfit_ensemble_type * misfit_ensemble = enkf_fs_get_misfit_ensemble( fs ); - test_assert_false(misfit_ensemble_initialized(misfit_ensemble)); - - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - test_assert_true(misfit_ensemble_initialized(misfit_ensemble)); - - stringlist_free( args ); -} - - - - -static void test_export_runpath_file(ert_test_context_type * test_context, - const char * job_name, - const char * job_file, - stringlist_type * args, - int_vector_type * iens_values, - int_vector_type * iter_values) { - - ert_test_context_install_workflow_job( test_context , job_name , job_file ); - test_assert_true( ert_test_context_run_worklow_job( test_context , job_name , args) ); - - { - const enkf_main_type * enkf_main = ert_test_context_get_main(test_context); - hook_manager_type * hook_manager = enkf_main_get_hook_manager( enkf_main ); - const char * runpath_file_name = hook_manager_get_runpath_list_file(hook_manager); - - ecl_config_type * ecl_config = enkf_main_get_ecl_config(enkf_main); - const model_config_type * model_config = enkf_main_get_model_config(enkf_main); - const char * base_fmt = ecl_config_get_eclbase(ecl_config); - const char * runpath_fmt = model_config_get_runpath_as_char(model_config); - - test_assert_true(util_file_exists(runpath_file_name)); - FILE * file = util_fopen(runpath_file_name, "r"); - - int file_iens = 0; - char file_path[256]; - char file_base[256]; - int file_iter = 0; - char * cwd = util_alloc_cwd(); - int counter = 0; - int iens_index = 0; - int iter_index = 0; - - while (4 == fscanf( file , "%d %s %s %d" , &file_iens , file_path , file_base, &file_iter)) { - ++ counter; - - test_assert_true(int_vector_size(iens_values) >= iens_index+1); - test_assert_true(int_vector_size(iter_values) >= iter_index+1); - - int iens = int_vector_iget(iens_values, iens_index); - int iter = int_vector_iget(iter_values, iter_index); - - test_assert_int_equal(file_iens, iens); - test_assert_int_equal(file_iter, iter); - - char * base = util_alloc_sprintf("--%d", iens); - if (base_fmt && (util_int_format_count(base_fmt) == 1)) - base = util_alloc_sprintf(base_fmt, iens); - - test_assert_string_equal(base, file_base); - - char * runpath = ""; - if (util_int_format_count(runpath_fmt) == 1) - runpath = util_alloc_sprintf(runpath_fmt, iens); - else if (util_int_format_count(runpath_fmt) == 2) - runpath = util_alloc_sprintf(runpath_fmt, iens,iter); - - test_assert_string_equal(runpath, file_path); - - if (iens_index+1 < int_vector_size(iens_values)) - ++iens_index; - else if ((iens_index+1 == int_vector_size(iens_values))) { - ++iter_index; - iens_index = 0; - } - - free(base); - free(runpath); - } - - int linecount = int_vector_size(iens_values) * int_vector_size(iter_values); - test_assert_int_equal(linecount, counter); - free(cwd); - fclose(file); - } -} - - - -void test_export_runpath_files(const char * config_file, - const char * config_file_iterations, - const char * job_file_export_runpath) { - - stringlist_type * args = stringlist_alloc_new(); - const char * job_name = "export_job"; - - ert_test_context_type * test_context_iterations = create_context( config_file_iterations, "enkf_workflow_job_test_export_runpath_iter" ); - - { - int_vector_type * iens_values = int_vector_alloc(5,0); - const int iens[5] = {0,1,2,3,4}; - int_vector_set_many(iens_values, 0, &iens[0], 5); - int_vector_type * iter_values = int_vector_alloc(1,0); - - test_export_runpath_file(test_context_iterations, job_name, job_file_export_runpath, args, iens_values, iter_values); - - int_vector_free(iens_values); - int_vector_free(iter_values); - } - { - stringlist_append_copy( args, "0-2"); //realization range - - int_vector_type * iens_values = int_vector_alloc(3,0); - const int iens[] = {0,1,2}; - int_vector_set_many(iens_values, 0, &iens[0], 3); - int_vector_type * iter_values = int_vector_alloc(1,0); - - test_export_runpath_file(test_context_iterations, job_name, job_file_export_runpath, args, iens_values, iter_values); - - int_vector_free(iens_values); - int_vector_free(iter_values); - - stringlist_clear(args); - } - { - stringlist_append_copy( args, "0,3-5"); //realization range - - int_vector_type * iens_values = int_vector_alloc(4,0); - const int iens[] = {0,3,4,5}; - int_vector_set_many(iens_values, 0, &iens[0], 4); - int_vector_type * iter_values = int_vector_alloc(1,0); - - test_export_runpath_file(test_context_iterations, job_name, job_file_export_runpath, args, iens_values, iter_values); - - int_vector_free(iens_values); - int_vector_free(iter_values); - - stringlist_clear(args); - } - { - stringlist_append_copy( args, "1-2"); //realization range - stringlist_append_copy( args, "|"); //delimiter - stringlist_append_copy( args, "1-3"); //iteration range - - int_vector_type * iens_values = int_vector_alloc(2,0); - int iens[] = {1,2}; - int_vector_set_many(iens_values, 0, &iens[0], 2); - int_vector_type * iter_values = int_vector_alloc(3,0); - int iter[] = {1,2,3}; - int_vector_set_many(iter_values, 0, &iter[0], 3); - - test_export_runpath_file(test_context_iterations, job_name, job_file_export_runpath, args, iens_values, iter_values); - - int_vector_free(iens_values); - int_vector_free(iter_values); - - stringlist_clear(args); - } - { - stringlist_append_copy( args, "*"); //realization range - stringlist_append_copy( args, "|"); //delimiter - stringlist_append_copy( args, "*"); //iteration range - - int_vector_type * iens_values = int_vector_alloc(5,0); - int iens[] = {0,1,2,3,4}; - int_vector_set_many(iens_values, 0, &iens[0], 5); - int_vector_type * iter_values = int_vector_alloc(4,0); - int iter[] = {0,1,2,3}; - int_vector_set_many(iter_values, 0, &iter[0], 4); - - test_export_runpath_file(test_context_iterations, job_name, job_file_export_runpath, args, iens_values, iter_values); - - int_vector_free(iens_values); - int_vector_free(iter_values); - - stringlist_clear(args); - } - - ert_test_context_free(test_context_iterations); - ert_test_context_type * test_context = create_context( config_file, "enkf_workflow_job_test_export_runpath" ); - - { - int_vector_type * iens_values = int_vector_alloc(1,0); - int_vector_init_range(iens_values, 0, 25, 1); - int_vector_type * iter_values = int_vector_alloc(1,0); - - test_export_runpath_file(test_context, job_name, job_file_export_runpath, args, iens_values, iter_values); - - int_vector_free(iens_values); - int_vector_free(iter_values); - - stringlist_clear(args); - } - { - stringlist_append_copy( args, "1-3"); //realization range - - int_vector_type * iens_values = int_vector_alloc(3,0); - int iens[] = {1,2,3}; - int_vector_set_many(iens_values, 0, &iens[0], 3); - int_vector_type * iter_values = int_vector_alloc(1,0); - - test_export_runpath_file(test_context, job_name, job_file_export_runpath, args, iens_values, iter_values); - - int_vector_free(iens_values); - int_vector_free(iter_values); - - stringlist_clear(args); - } - { - stringlist_append_copy( args, "1,2"); //realization range - stringlist_append_copy( args, "|"); //delimiter - stringlist_append_copy( args, "1-3"); //iteration range - - int_vector_type * iens_values = int_vector_alloc(2,0); - int iens[] = {1,2}; - int_vector_set_many(iens_values, 0, &iens[0], 2); - int_vector_type * iter_values = int_vector_alloc(1,0); - - test_export_runpath_file(test_context, job_name, job_file_export_runpath, args, iens_values, iter_values); - - int_vector_free(iens_values); - int_vector_free(iter_values); - - stringlist_clear(args); - } - - - ert_test_context_free(test_context); - - - stringlist_free( args ); -} - - - - - -int main(int argc , const char ** argv) { - enkf_main_install_SIGNALS(); - - const char * config_file = argv[1]; - const char * config_file_iterations = argv[2]; - const char * job_file_create_case = argv[3]; - const char * job_file_init_case_job = argv[4]; - const char * job_file_load_results = argv[5]; - const char * job_file_load_results_iter = argv[6]; - const char * job_file_observation_ranking = argv[7]; - const char * job_file_data_ranking = argv[8]; - const char * job_file_ranking_export = argv[9]; - const char * job_file_init_misfit_table = argv[10]; - const char * job_file_export_runpath = argv[11]; - - - ert_test_context_type * test_context = create_context( config_file, "enkf_workflow_job_test" ); - { - test_create_case_job(test_context, "JOB1" , job_file_create_case); - test_init_case_job(test_context, "JOB2", job_file_init_case_job); - test_load_results_job(test_context, "JOB3" , job_file_load_results); - test_load_results_iter_job( test_context, "JOB4" , job_file_load_results_iter ); - test_init_misfit_table(test_context, "JOB5" , job_file_init_misfit_table); - test_rank_realizations_on_observations_job(test_context, "JOB6" , job_file_observation_ranking); - test_rank_realizations_on_data_job(test_context , "JOB7" , job_file_data_ranking); - test_export_ranking(test_context, "JOB8" , job_file_ranking_export); - } - ert_test_context_free( test_context ); - - test_export_runpath_files(config_file, config_file_iterations, job_file_export_runpath); - - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/enkf_workflow_job_test_version.c b/ThirdParty/Ert/libenkf/tests/enkf_workflow_job_test_version.c deleted file mode 100644 index d60e2c799c..0000000000 --- a/ThirdParty/Ert/libenkf/tests/enkf_workflow_job_test_version.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - The file 'enkf_workflow_job_test_version.c' is part of ERT - - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -/* - These version functions are overrideed here to get a consistent - version mapping. -*/ - -int version_get_major_ert_version( ) { - return 1; -} - - -int version_get_minor_ert_version( ) { - return 2; -} - - -const char* version_get_micro_ert_version( ) { - return "3"; -} - - -void test_version() { - test_assert_int_equal( version_get_major_ert_version( ) , 1 ); - test_assert_int_equal( version_get_minor_ert_version( ) , 2 ); - test_assert_string_equal( version_get_micro_ert_version( ) , "3" ); -} - - -int main(int argc , const char ** argv) { - enkf_main_install_SIGNALS(); - test_version( ); - { - const char * path = argv[1]; - ert_workflow_list_type * workflows = ert_workflow_list_alloc( NULL ); - ert_workflow_list_add_jobs_in_directory( workflows , path ); - - // The CONF1 only exists as default - unversioned - test_assert_true( ert_workflow_list_has_job( workflows , "CONF1")); - - // The CONF2 exists as the default - which is invalid and will not load, - // and CONF2@1 - which should load. - test_assert_false( ert_workflow_list_has_job( workflows , "CONF2@1")); - test_assert_true( ert_workflow_list_has_job( workflows , "CONF2")); - - // The CONF3 only exists as a fully versioned CONF3@1.2.3 - which should load. - test_assert_true( ert_workflow_list_has_job( workflows , "CONF3")); - - // The CONF4 only exists as a fully versioned CONF4@1.2.0 - which should not load. - test_assert_false( ert_workflow_list_has_job( workflows , "CONF4")); - - // The CONF5 exists as a fully versioned CONF5@1.2.0 - which should not load and - // CONF@1.2 which should load. - test_assert_true( ert_workflow_list_has_job( workflows , "CONF5")); - - ert_workflow_list_free( workflows ); - } - exit(0); -} diff --git a/ThirdParty/Ert/libenkf/tests/gen_kw_logarithmic_test.c b/ThirdParty/Ert/libenkf/tests/gen_kw_logarithmic_test.c deleted file mode 100644 index 2747b91a2c..0000000000 --- a/ThirdParty/Ert/libenkf/tests/gen_kw_logarithmic_test.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'gen_kw_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - - - -void test_write_gen_kw_export_file(enkf_main_type * enkf_main) -{ - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - test_assert_not_NULL(state); - enkf_node_type * enkf_node = enkf_state_get_node( state , "MULTFLT" ); - enkf_node_type * enkf_node2 = enkf_state_get_node( state , "MULTFLT2" ); - test_assert_not_NULL(enkf_node); - test_assert_not_NULL(enkf_node2); - test_assert_true(enkf_node_get_impl_type(enkf_node) == GEN_KW); - test_assert_true(enkf_node_get_impl_type(enkf_node2) == GEN_KW); - - gen_kw_type * gen_kw = enkf_node_value_ptr(enkf_node); - gen_kw_type * gen_kw2 = enkf_node_value_ptr(enkf_node2); - - - { - rng_type * rng = rng_alloc( MZRAN , INIT_DEFAULT ); - const enkf_config_node_type * config = enkf_node_get_config(enkf_node); - const int data_size = enkf_config_node_get_data_size( config, 0 ); - const double mean = 0.0; /* Mean and std are hardcoded - the variability should be in the transformation. */ - const double std = 1.0; - - for (int i=0; i < data_size; ++i) { - double random_number = enkf_util_rand_normal(mean , std , rng); - gen_kw_data_iset(gen_kw, i, random_number); - gen_kw_data_iset(gen_kw2, i, random_number); - } - - rng_free(rng); - } - - - { - enkf_fs_type * init_fs = enkf_main_get_fs( enkf_main ); - run_arg_type * run_arg = run_arg_alloc_INIT_ONLY( init_fs , 0 ,0 , "simulations/run0"); - enkf_state_ecl_write(state, run_arg , init_fs); - test_assert_true(util_file_exists("simulations/run0/parameters.txt")); - run_arg_free( run_arg ); - } - - - { - int buffer_size = 0; - char * file_content = util_fread_alloc_file_content("simulations/run0/parameters.txt", &buffer_size); - - stringlist_type * token_list = stringlist_alloc_from_split(file_content, " \n"); - double value = stringlist_iget_as_double(token_list, 5, NULL); - - test_assert_true(value > 0.0); //Verify precision - test_assert_true(NULL != strstr(file_content, "LOG10_")); //Verify log entry - - stringlist_free(token_list); - free(file_content); - } -} - - - -int main(int argc , char ** argv) { - const char * config_file = argv[1]; - ert_test_context_type * test_context = ert_test_context_alloc("gen_kw_logarithmic_test" , config_file ); - enkf_main_type * enkf_main = ert_test_context_get_main(test_context); - - test_assert_not_NULL(enkf_main); - - test_write_gen_kw_export_file(enkf_main); - - ert_test_context_free( test_context ); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/gen_kw_test.c b/ThirdParty/Ert/libenkf/tests/gen_kw_test.c deleted file mode 100644 index fdf5e677bd..0000000000 --- a/ThirdParty/Ert/libenkf/tests/gen_kw_test.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'gen_kw_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include "ert/util/build_config.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - - - -void test_send_fortio_to_gen_kw_ecl_write(void * arg) { - enkf_main_type * enkf_main = arg; - test_assert_not_NULL(enkf_main); - fortio_type * fortio = fortio_open_writer("my_new_file", false, ECL_ENDIAN_FLIP); - test_assert_not_NULL(fortio); - - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - test_assert_not_NULL(state); - enkf_node_type * enkf_node = enkf_state_get_node( state , "MULTFLT" ); - test_assert_not_NULL(enkf_node); - const enkf_config_node_type * config_node = enkf_node_get_config(enkf_node); - test_assert_not_NULL(config_node); - - if (GEN_KW == enkf_config_node_get_impl_type(config_node)) { - const char * dummy_path = "dummy_path"; - enkf_node_ecl_write(enkf_node, dummy_path, fortio, 0); - } -} - - -void test_write_gen_kw_export_file(enkf_main_type * enkf_main) -{ - test_assert_not_NULL(enkf_main); - enkf_fs_type * init_fs = enkf_main_get_fs( enkf_main ); - enkf_state_type * state = enkf_main_iget_state( enkf_main , 0 ); - run_arg_type * run_arg = run_arg_alloc_INIT_ONLY( init_fs , 0 ,0 , "simulations/run0"); - test_assert_not_NULL(state); - enkf_node_type * enkf_node = enkf_state_get_node( state , "MULTFLT" ); - - test_assert_not_NULL(enkf_node); - const enkf_config_node_type * config_node = enkf_node_get_config(enkf_node); - test_assert_not_NULL(config_node); - - if (GEN_KW == enkf_config_node_get_impl_type(config_node)) { - enkf_state_ecl_write(state, run_arg , init_fs); - test_assert_true(util_file_exists("simulations/run0/parameters.txt")); - } - run_arg_free( run_arg ); -} - - - -static void read_erroneous_gen_kw_file( void * arg) { - vector_type * arg_vector = vector_safe_cast( arg ); - gen_kw_config_type * gen_kw_config = vector_iget( arg_vector, 0 ); - const char * filename = vector_iget( arg, 1 ); - gen_kw_config_set_parameter_file(gen_kw_config, filename); -} - - -void test_read_erroneous_gen_kw_file() { - const char * parameter_filename = "MULTFLT_with_errors.txt"; - const char * tmpl_filename = "MULTFLT.tmpl"; - - { - FILE * stream = util_fopen(parameter_filename, "w"); - const char * data = util_alloc_sprintf("MULTFLT1 NORMAL 0\nMULTFLT2 RAW\nMULTFLT3 NORMAL 0"); - util_fprintf_string(data, 30, true, stream); - util_fclose(stream); - - FILE * tmpl_stream = util_fopen(tmpl_filename, "w"); - const char * tmpl_data = util_alloc_sprintf(" \n"); - util_fprintf_string(tmpl_data, 30, true, tmpl_stream); - util_fclose(tmpl_stream); - } - - gen_kw_config_type * gen_kw_config = gen_kw_config_alloc_empty("MULTFLT", "<%s>"); - vector_type * arg = vector_alloc_new(); - vector_append_ref( arg , gen_kw_config ); - vector_append_ref(arg, parameter_filename); - - test_assert_util_abort("arg_pack_fscanf", read_erroneous_gen_kw_file, arg); - - vector_free(arg); - gen_kw_config_free(gen_kw_config); -} - - -int main(int argc , char ** argv) { - const char * config_file = argv[1]; - ert_test_context_type * test_context = ert_test_context_alloc("gen_kw_test" , config_file ); - enkf_main_type * enkf_main = ert_test_context_get_main(test_context); - test_assert_not_NULL(enkf_main); - - test_write_gen_kw_export_file(enkf_main); - test_assert_util_abort("gen_kw_ecl_write", test_send_fortio_to_gen_kw_ecl_write, enkf_main); - test_read_erroneous_gen_kw_file(); - - ert_test_context_free( test_context ); - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/obs_vector_tests.c b/ThirdParty/Ert/libenkf/tests/obs_vector_tests.c deleted file mode 100644 index 33485d7c0d..0000000000 --- a/ThirdParty/Ert/libenkf/tests/obs_vector_tests.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'enkf_obs_vector_tests.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ - -#include -#include -#include -#include - -#include "ert/enkf/gen_obs.h" - -bool alloc_strippedparameters_noerrors() { - obs_vector_type * obs_vector = obs_vector_alloc(SUMMARY_OBS, "WHAT", NULL, 0); - obs_vector_free(obs_vector); - return true; -} - -/*******Summary obs tests*******************/ -bool scale_std_summary_nodata_no_errors() { - obs_vector_type * obs_vector = obs_vector_alloc(SUMMARY_OBS, "WHAT", NULL, 0); - local_obsdata_node_type * local_node = obs_vector_alloc_local_node( obs_vector ); - obs_vector_scale_std(obs_vector, local_node , 2.0); - obs_vector_free(obs_vector); - local_obsdata_node_free( local_node ); - return true; -} - -bool scale_std_summarysingleobservation_no_errors() { - obs_vector_type * obs_vector = obs_vector_alloc(SUMMARY_OBS, "WHAT", NULL, 1); - summary_obs_type * summary_obs = summary_obs_alloc("SummaryKey", "ObservationKey", 43.2, 2.0, AUTO_CORRF_EXP, 42); - obs_vector_install_node(obs_vector, 0, summary_obs); - test_assert_double_equal(2.0, summary_obs_get_std(summary_obs)); - test_assert_double_equal(1.0, summary_obs_get_std_scaling(summary_obs)); - - { - local_obsdata_node_type * local_node = obs_vector_alloc_local_node( obs_vector ); - obs_vector_scale_std(obs_vector, local_node , 2.0); - local_obsdata_node_free( local_node ); - } - test_assert_double_equal(2.0, summary_obs_get_std_scaling(summary_obs)); - - obs_vector_free(obs_vector); - return true; -} - -bool scale_std_summarymanyobservations_no_errors() { - int num_observations = 100; - double scaling_factor = 1.456; - - obs_vector_type * obs_vector = obs_vector_alloc(SUMMARY_OBS, "WHAT", NULL, num_observations); - - test_assert_bool_equal(0, obs_vector_get_num_active(obs_vector)); - - summary_obs_type * observations[num_observations]; - for (int i = 0; i < num_observations; i++) { - summary_obs_type * summary_obs = summary_obs_alloc("SummaryKey", "ObservationKey", 43.2, i, AUTO_CORRF_EXP, 42); - obs_vector_install_node(obs_vector, i, summary_obs); - observations[i] = summary_obs; - } - - for (int i = 0; i < num_observations; i++) { - summary_obs_type * before_scale = observations[i]; - test_assert_double_equal(i, summary_obs_get_std(before_scale)); - } - - test_assert_bool_equal(num_observations, obs_vector_get_num_active(obs_vector)); - { - local_obsdata_node_type * local_node = obs_vector_alloc_local_node( obs_vector ); - obs_vector_scale_std(obs_vector, local_node , scaling_factor); - local_obsdata_node_free( local_node ); - } - for (int i = 0; i < num_observations; i++) { - summary_obs_type * after_scale = observations[i]; - test_assert_double_equal(scaling_factor, summary_obs_get_std_scaling(after_scale)); - } - - obs_vector_free(obs_vector); - return true; -} - -/************ Block obs tests *****************************************************/ - -bool scale_std_block_nodata_no_errors() { - obs_vector_type * obs_vector = obs_vector_alloc(BLOCK_OBS, "WHAT", NULL, 0); - local_obsdata_node_type * local_node = obs_vector_alloc_local_node( obs_vector ); - obs_vector_scale_std(obs_vector, local_node , 2.0); - local_obsdata_node_free( local_node ); - obs_vector_free(obs_vector); - return true; -} - -block_obs_type * create_block_obs(ecl_grid_type * grid, int size, double value, double std_dev) { - field_config_type * field_config = field_config_alloc_empty( "PRESSURE" , grid , NULL, false ); - int * i = util_calloc(size, sizeof * i); - int * j = util_calloc(size, sizeof * j); - int * k = util_calloc(size, sizeof * k); - double * obs_value = util_calloc(size, sizeof * obs_value); - double * obs_std = util_calloc(size, sizeof * obs_std); - - for (int num = 0; num < size; num++) { - obs_value[num] = value; - obs_std[num] = std_dev; - i[num] = num; - j[num] = num; - k[num] = num; - } - - block_obs_type * block_obs = block_obs_alloc_complete("Label", SOURCE_FIELD, NULL, field_config , grid, size, i, j, k, obs_value, obs_std); - - free(i); - free(j); - free(k); - free(obs_value); - free(obs_std); - field_config_free( field_config ); - - return block_obs; -} - -bool scale_std_block100observations_no_errors() { - int num_observations = 100; - int num_points = 10; - - obs_vector_type * obs_vector = obs_vector_alloc(BLOCK_OBS, "WHAT", NULL, num_observations); - ecl_grid_type * grid = ecl_grid_alloc_rectangular(num_points, num_points, num_points, 1.0, 1.0, 1.0, NULL); - - double scale_factor = 3.3; - double obs_value = 44; - double obs_std = 3.2; - - block_obs_type * observations[num_observations]; - - for (int i = 0; i < num_observations; i++) { - block_obs_type * block_obs = create_block_obs(grid, num_points, obs_value, obs_std); - obs_vector_install_node(obs_vector, i, block_obs); - observations[i] = block_obs; - } - - for (int i = 0; i < num_observations; i++) { - for (int point_nr = 0; point_nr < num_points; point_nr++) { - double value, std; - block_obs_iget(observations[i], point_nr, &value, &std); - test_assert_double_equal(obs_value, value); - test_assert_double_equal(obs_std, std); - } - } - - { - local_obsdata_node_type * local_node = obs_vector_alloc_local_node( obs_vector ); - obs_vector_scale_std(obs_vector, local_node , scale_factor); - local_obsdata_node_free( local_node ); - } - - for (int i = 0; i < num_observations; i++) { - for (int point_nr = 0; point_nr < num_points; point_nr++) { - double value, std; - block_obs_iget(observations[i], point_nr, &value, &std); - test_assert_double_equal(obs_value, value); - test_assert_double_equal(obs_std , std); - test_assert_double_equal(scale_factor , block_obs_iget_std_scaling( observations[i] , point_nr)); - } - } - - ecl_grid_free(grid); - obs_vector_free(obs_vector); - return true; -} - -/*************Gen obs tests************************************************/ - -bool scale_std_gen_nodata_no_errors() { - obs_vector_type * obs_vector = obs_vector_alloc(GEN_OBS, "WHAT", NULL, 0); - local_obsdata_node_type * local_node = obs_vector_alloc_local_node( obs_vector ); - obs_vector_scale_std(obs_vector, local_node , 2.0); - obs_vector_free(obs_vector); - local_obsdata_node_free( local_node ); - return true; -} - -bool scale_std_gen_withdata_no_errors() { - int num_observations = 100; - double value = 42; - double std_dev = 2.2; - double multiplier = 3.4; - - obs_vector_type * obs_vector = obs_vector_alloc(GEN_OBS, "WHAT", NULL, num_observations); - - gen_obs_type * observations[num_observations]; - for (int i = 0; i < num_observations; i++) { - gen_obs_type * gen_obs = gen_obs_alloc(NULL, "WWCT-GEN", NULL, value, std_dev, NULL, NULL, NULL); - obs_vector_install_node(obs_vector, i, gen_obs); - observations[i] = gen_obs; - } - - { - local_obsdata_node_type * local_node = obs_vector_alloc_local_node( obs_vector ); - obs_vector_scale_std(obs_vector, local_node , multiplier); - local_obsdata_node_free( local_node ); - } - - for (int i = 0; i < num_observations; i++) { - char * index_key = util_alloc_sprintf("%d", 0); - double value_new, std_new; - bool valid; - gen_obs_user_get_with_data_index(observations[i], index_key, &value_new, &std_new, &valid); - test_assert_double_equal(std_dev , std_new); - test_assert_double_equal(value, value_new); - test_assert_double_equal(multiplier , gen_obs_iget_std_scaling( observations[i] , 0 )); - free(index_key); - } - - obs_vector_free(obs_vector); - return true; -} - -int main(int argc, char ** argv) { - test_assert_bool_equal(alloc_strippedparameters_noerrors(), true); - test_assert_bool_equal(scale_std_summary_nodata_no_errors(), true); - test_assert_bool_equal(scale_std_summarysingleobservation_no_errors(), true); - test_assert_bool_equal(scale_std_summarymanyobservations_no_errors(), true); - - test_assert_bool_equal(scale_std_block_nodata_no_errors(), true); - test_assert_bool_equal(scale_std_block100observations_no_errors(), true); - - test_assert_bool_equal(scale_std_gen_nodata_no_errors(), true); - test_assert_bool_equal(scale_std_gen_withdata_no_errors(), true); - - exit(0); -} - diff --git a/ThirdParty/Ert/libenkf/tests/statoil_tests.cmake b/ThirdParty/Ert/libenkf/tests/statoil_tests.cmake deleted file mode 100644 index de6baa0cf4..0000000000 --- a/ThirdParty/Ert/libenkf/tests/statoil_tests.cmake +++ /dev/null @@ -1,220 +0,0 @@ -add_executable( enkf_site_config enkf_site_config.c ) -target_link_libraries( enkf_site_config enkf test_util ) -add_test( enkf_site_config ${EXECUTABLE_OUTPUT_PATH}/enkf_site_config /project/res/etc/ERT/site-config) - -add_executable( enkf_gen_data_config enkf_gen_data_config.c ) -target_link_libraries( enkf_gen_data_config enkf test_util ) -add_test( enkf_gen_data_config ${EXECUTABLE_OUTPUT_PATH}/enkf_gen_data_config - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/gendata_test/RFT_E-3H_21 - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/gendata_test/RFT_E-3H_21_empty) - -add_executable( enkf_block_obs enkf_block_obs.c ) -target_link_libraries( enkf_block_obs enkf test_util ) -add_test( enkf_block_obs ${EXECUTABLE_OUTPUT_PATH}/enkf_block_obs ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID) - -add_executable( enkf_obs_fs enkf_obs_fs.c ) -target_link_libraries( enkf_obs_fs enkf test_util ) -add_test( enkf_obs_fs ${EXECUTABLE_OUTPUT_PATH}/enkf_obs_fs ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/obs_testing/config ) - -add_executable( enkf_magic_string_in_workflows enkf_magic_string_in_workflows.c ) -target_link_libraries( enkf_magic_string_in_workflows enkf test_util ) -add_test( enkf_magic_string_in_workflows ${EXECUTABLE_OUTPUT_PATH}/enkf_magic_string_in_workflows ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/with_data/config ) - -add_executable( enkf_obs_vector_fs enkf_obs_vector_fs.c ) -target_link_libraries( enkf_obs_vector_fs enkf test_util ) -add_test( enkf_obs_vector_fs ${EXECUTABLE_OUTPUT_PATH}/enkf_obs_vector_fs ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/obs_testing/config ) - -add_executable( enkf_plot_data_fs enkf_plot_data_fs.c ) -target_link_libraries( enkf_plot_data_fs enkf test_util ) -add_test( enkf_plot_data_fs ${EXECUTABLE_OUTPUT_PATH}/enkf_plot_data_fs ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/plotData/config ) - -add_executable( enkf_time_map enkf_time_map.c ) -target_link_libraries( enkf_time_map enkf test_util ) -add_test( enkf_time_map1 ${EXECUTABLE_OUTPUT_PATH}/enkf_time_map ) -add_test( enkf_time_map2 ${EXECUTABLE_OUTPUT_PATH}/enkf_time_map ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE - ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/ModifiedSummary/EXTRA_TSTEP - ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/ModifiedSummary/SHORT - ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/ModifiedSummary/MISSING_TSTEP ) - -add_executable( enkf_main_fs enkf_main_fs.c ) -target_link_libraries( enkf_main_fs enkf test_util ) -add_test( enkf_main_fs ${EXECUTABLE_OUTPUT_PATH}/enkf_main_fs ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/plotData/config ) - -add_executable( enkf_main_fs_current_file_test enkf_main_fs_current_file_test.c ) -target_link_libraries( enkf_main_fs_current_file_test enkf test_util ) -add_test( enkf_main_fs_current_file_test ${EXECUTABLE_OUTPUT_PATH}/enkf_main_fs_current_file_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/plotData/config ) - -add_executable( enkf_scale_correlated_std enkf_scale_correlated_std.c ) -target_link_libraries( enkf_scale_correlated_std enkf test_util ) -add_test( enkf_scale_correlated_std ${EXECUTABLE_OUTPUT_PATH}/enkf_scale_correlated_std - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/with_data/config - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/STD_SCALE_CORRELATED_OBS ) - -add_executable( enkf_plot_gendata_fs enkf_plot_gendata_fs.c ) -target_link_libraries( enkf_plot_gendata_fs enkf test_util ) -add_test( enkf_plot_gendata_fs ${EXECUTABLE_OUTPUT_PATH}/enkf_plot_gendata_fs - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/with_GEN_DATA/config ) - -add_test( enkf_state_report_step_compatible_TRUE - ${EXECUTABLE_OUTPUT_PATH}/enkf_state_report_step_compatible ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/ecl_sum_compatible_true config_ecl_sum_compatible_true TRUE) - -add_test( enkf_state_report_step_compatible_FALSE - ${EXECUTABLE_OUTPUT_PATH}/enkf_state_report_step_compatible ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/ecl_sum_compatible_false config_ecl_sum_compatible_false FALSE) - - -#----------------------------------------------------------------- - -add_executable( enkf_state_manual_load_test enkf_state_manual_load_test.c ) -target_link_libraries( enkf_state_manual_load_test enkf test_util ) -add_test( enkf_state_manual_load_test ${EXECUTABLE_OUTPUT_PATH}/enkf_state_manual_load_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/ecl_sum_compatible_true config_ecl_sum_compatible_true) - -#----------------------------------------------------------------- - - -add_executable( enkf_state_skip_summary_load_test enkf_state_skip_summary_load_test.c ) -target_link_libraries( enkf_state_skip_summary_load_test enkf test_util ) - -add_test( enkf_state_summary_vars_present - ${EXECUTABLE_OUTPUT_PATH}/enkf_state_skip_summary_load_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/ecl_summary_vars_config config_summary_vars) - -add_test( enkf_state_no_summary_vars_present - ${EXECUTABLE_OUTPUT_PATH}/enkf_state_skip_summary_load_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/ecl_no_summary_vars_config config_no_summary_vars) - - -#----------------------------------------------------------------- - - -add_executable( enkf_export_field_test enkf_export_field_test.c ) -target_link_libraries( enkf_export_field_test enkf test_util ) - -add_test( enkf_export_field_test - ${EXECUTABLE_OUTPUT_PATH}/enkf_export_field_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/export_fields/config - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/EXPORT_FIELD - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/EXPORT_FIELD_ECL_GRDECL - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/EXPORT_FIELD_RMS_ROFF) - - - -add_executable( enkf_workflow_job_test enkf_workflow_job_test.c ) -target_link_libraries( enkf_workflow_job_test enkf test_util ) - -add_test( enkf_workflow_job_test - ${EXECUTABLE_OUTPUT_PATH}/enkf_workflow_job_test ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/with_data/config - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/enkf_state_runpath/config_runpath_multiple_iterations - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal-tui/config/CREATE_CASE - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal-tui/config/INIT_CASE_FROM_EXISTING - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/LOAD_RESULTS - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/LOAD_RESULTS_ITER - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/OBSERVATION_RANKING - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/DATA_RANKING - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/EXPORT_RANKING - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/INIT_MISFIT_TABLE - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/EXPORT_RUNPATH) - -#----------------------------------------------------------------- - -add_executable( enkf_forward_init_SURFACE enkf_forward_init_SURFACE.c ) -target_link_libraries( enkf_forward_init_SURFACE enkf test_util ) - -add_test( enkf_forward_init_SURFACE_TRUE - ${EXECUTABLE_OUTPUT_PATH}/enkf_forward_init_SURFACE - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/forward_init/surface config_surface_true - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/forward_init/surface/Surface.irap - TRUE) - -add_test( enkf_forward_init_SURFACE_FALSE - ${EXECUTABLE_OUTPUT_PATH}/enkf_forward_init_SURFACE - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/forward_init/surface config_surface_false - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/forward_init/surface/Surface.irap - FALSE) - -#----------------------------------------------------------------- - -add_executable( enkf_forward_init_FIELD enkf_forward_init_FIELD.c ) -target_link_libraries( enkf_forward_init_FIELD enkf test_util ) - -add_test( enkf_forward_init_FIELD_TRUE - ${EXECUTABLE_OUTPUT_PATH}/enkf_forward_init_FIELD - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/forward_init/field config_field_true - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/forward_init/field/petro.grdecl - TRUE) - -add_test( enkf_forward_init_FIELD_FALSE - ${EXECUTABLE_OUTPUT_PATH}/enkf_forward_init_FIELD - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/forward_init/field config_field_false - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/forward_init/field/petro.grdecl - FALSE) - -#----------------------------------------------------------------- - -add_executable( enkf_forward_init_transform enkf_forward_init_transform.c ) -target_link_libraries( enkf_forward_init_transform enkf test_util ) - -add_test( enkf_forward_init_transform_TRUE - ${EXECUTABLE_OUTPUT_PATH}/enkf_forward_init_transform - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/transform transform_forward_init_true - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/transform/petro.grdecl - TRUE) - -add_test( enkf_forward_init_transform_FALSE - ${EXECUTABLE_OUTPUT_PATH}/enkf_forward_init_transform - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/transform transform_forward_init_false - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/transform/petro.grdecl - FALSE) - -#----------------------------------------------------------------- - -add_executable( enkf_export_inactive_cells enkf_export_inactive_cells.c ) -target_link_libraries( enkf_export_inactive_cells enkf test_util ) - -add_test( enkf_export_inactive_cells - ${EXECUTABLE_OUTPUT_PATH}/enkf_export_inactive_cells - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/export_inactive_cells/config - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/export_inactive_cells/petro.grdecl) - -#----------------------------------------------------------------- - -add_executable( enkf_refcase_list enkf_refcase_list.c ) -target_link_libraries( enkf_refcase_list enkf test_util ) -add_test( enkf_refcase_list ${EXECUTABLE_OUTPUT_PATH}/enkf_refcase_list ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat*/ECLIPSE) -add_test( enkf_refcase_list2 ${EXECUTABLE_OUTPUT_PATH}/enkf_refcase_list ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat*/ECLIPSE.*) -set_property( TEST enkf_refcase_list PROPERTY LABELS StatoilData ) -set_property( TEST enkf_refcase_list2 PROPERTY LABELS StatoilData ) - -add_executable( enkf_ecl_config enkf_ecl_config.c ) -target_link_libraries( enkf_ecl_config enkf test_util ) -add_test( enkf_ecl_config1 ${EXECUTABLE_OUTPUT_PATH}/enkf_ecl_config ) -add_test( enkf_ecl_config2 ${EXECUTABLE_OUTPUT_PATH}/enkf_ecl_config ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE) -set_property( TEST enkf_ecl_config2 PROPERTY LABELS StatoilData ) - -add_executable( enkf_ecl_config_config enkf_ecl_config_config.c ) -target_link_libraries( enkf_ecl_config_config enkf test_util ) -add_test( enkf_ecl_config_config ${EXECUTABLE_OUTPUT_PATH}/enkf_ecl_config_config ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/ecl_config ) -set_property( TEST enkf_ecl_config_config PROPERTY LABELS StatoilData ) - -set_property( TEST enkf_plot_data_fs PROPERTY LABELS StatoilData ) -set_property( TEST enkf_time_map2 PROPERTY LABELS StatoilData ) -set_property( TEST enkf_site_config PROPERTY LABELS StatoilData ) -set_property( TEST enkf_state_report_step_compatible_TRUE PROPERTY LABELS StatoilData ) -set_property( TEST enkf_state_report_step_compatible_FALSE PROPERTY LABELS StatoilData ) -set_property( TEST enkf_forward_init_SURFACE_FALSE PROPERTY LABELS StatoilData ) -set_property( TEST enkf_forward_init_SURFACE_TRUE PROPERTY LABELS StatoilData ) -set_property( TEST enkf_forward_init_FIELD_FALSE PROPERTY LABELS StatoilData ) -set_property( TEST enkf_forward_init_FIELD_TRUE PROPERTY LABELS StatoilData ) -set_property( TEST enkf_forward_init_transform_TRUE PROPERTY LABELS StatoilData ) -set_property( TEST enkf_forward_init_transform_FALSE PROPERTY LABELS StatoilData ) -set_property( TEST enkf_main_fs PROPERTY LABELS StatoilData ) -set_property( TEST enkf_state_summary_vars_present PROPERTY LABELS StatoilData ) -set_property( TEST enkf_state_no_summary_vars_present PROPERTY LABELS StatoilData ) -set_property( TEST enkf_export_field_test PROPERTY LABELS StatoilData ) -set_property( TEST enkf_workflow_job_test PROPERTY LABELS StatoilData ) -set_property( TEST enkf_main_fs_current_file_test PROPERTY LABELS StatoilData ) -set_property( TEST enkf_state_manual_load_test PROPERTY LABELS StatoilData ) -set_property( TEST enkf_block_obs PROPERTY LABELS StatoilData ) -set_property( TEST enkf_plot_gendata_fs PROPERTY LABELS StatoilData ) -set_property( TEST enkf_export_inactive_cells PROPERTY LABELS StatoilData ) -set_property( TEST enkf_obs_fs PROPERTY LABELS StatoilData ) -set_property( TEST enkf_obs_vector_fs PROPERTY LABELS StatoilData ) -set_property( TEST enkf_magic_string_in_workflows PROPERTY LABELS StatoilData ) -set_property( TEST enkf_gen_data_config PROPERTY LABELS StatoilData ) -set_property( TEST enkf_scale_correlated_std PROPERTY LABELS StatoilData ) \ No newline at end of file diff --git a/ThirdParty/Ert/libenkf/tests/tests.cmake b/ThirdParty/Ert/libenkf/tests/tests.cmake deleted file mode 100644 index 422545a549..0000000000 --- a/ThirdParty/Ert/libenkf/tests/tests.cmake +++ /dev/null @@ -1,254 +0,0 @@ -add_executable( enkf_runpath_list enkf_runpath_list.c ) -target_link_libraries( enkf_runpath_list enkf test_util ) -add_test( enkf_runpath_list ${EXECUTABLE_OUTPUT_PATH}/enkf_runpath_list ${CMAKE_CURRENT_SOURCE_DIR}/data/config/runpath_list/config ) - -add_executable( enkf_plot_tvector enkf_plot_tvector.c ) -target_link_libraries( enkf_plot_tvector enkf test_util ) -add_test( enkf_plot_tvector ${EXECUTABLE_OUTPUT_PATH}/enkf_plot_tvector) - -add_executable( enkf_plot_data enkf_plot_data.c ) -target_link_libraries( enkf_plot_data enkf test_util ) -add_test( enkf_plot_data ${EXECUTABLE_OUTPUT_PATH}/enkf_plot_data) - -add_executable( enkf_ert_run_context enkf_ert_run_context.c ) -target_link_libraries( enkf_ert_run_context enkf test_util ) -add_test( enkf_ert_run_context ${EXECUTABLE_OUTPUT_PATH}/enkf_ert_run_context) - -add_executable( enkf_run_arg enkf_run_arg.c ) -target_link_libraries( enkf_run_arg enkf test_util ) -add_test( enkf_run_arg ${EXECUTABLE_OUTPUT_PATH}/enkf_run_arg) - -add_executable( enkf_gen_obs_load enkf_gen_obs_load.c ) -target_link_libraries( enkf_gen_obs_load enkf test_util ) -add_test( enkf_gen_obs_load ${EXECUTABLE_OUTPUT_PATH}/enkf_gen_obs_load ${PROJECT_SOURCE_DIR}/test-data/local/config/gen_data/config ) - -add_executable( enkf_gen_data_config_parse enkf_gen_data_config_parse.c ) -target_link_libraries( enkf_gen_data_config_parse enkf test_util ) -add_test( enkf_gen_data_config_parse ${EXECUTABLE_OUTPUT_PATH}/enkf_gen_data_config_parse) - -add_executable( enkf_enkf_config_node_gen_data enkf_enkf_config_node_gen_data.c ) -target_link_libraries( enkf_enkf_config_node_gen_data enkf test_util ) -add_test( enkf_enkf_config_node_gen_data ${EXECUTABLE_OUTPUT_PATH}/enkf_enkf_config_node_gen_data) - - -add_executable( enkf_ert_workflow_list enkf_ert_workflow_list.c ) -target_link_libraries( enkf_ert_workflow_list enkf test_util ) -add_test( enkf_ert_workflow_list ${EXECUTABLE_OUTPUT_PATH}/enkf_ert_workflow_list ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal/config/SCALE_STD) - - -add_executable( enkf_obs_vector enkf_obs_vector.c ) -target_link_libraries( enkf_obs_vector enkf test_util ) -add_test( enkf_obs_vector ${EXECUTABLE_OUTPUT_PATH}/enkf_obs_vector ) - - - - -add_executable( enkf_ensemble_config enkf_ensemble_config.c ) -target_link_libraries( enkf_ensemble_config enkf test_util ) -add_test( enkf_ensemble_config ${EXECUTABLE_OUTPUT_PATH}/enkf_ensemble_config) - -add_executable( enkf_pca_plot enkf_pca_plot.c ) -target_link_libraries( enkf_pca_plot enkf test_util) -add_test( enkf_pca_plot ${EXECUTABLE_OUTPUT_PATH}/enkf_pca_plot) - -add_executable( enkf_cases_config enkf_cases_config.c ) -target_link_libraries( enkf_cases_config enkf test_util ) -add_test( enkf_cases_config ${EXECUTABLE_OUTPUT_PATH}/enkf_cases_config ) - -add_executable( enkf_analysis_config enkf_analysis_config.c ) -target_link_libraries( enkf_analysis_config enkf test_util ) -add_test( enkf_analysis_config ${EXECUTABLE_OUTPUT_PATH}/enkf_analysis_config) - -add_executable( enkf_analysis_config_ext_module enkf_analysis_config_ext_module.c ) -target_link_libraries( enkf_analysis_config_ext_module enkf test_util ) - -ert_module_name( VAR_RML rml_enkf ${LIBRARY_OUTPUT_PATH} ) -add_test( enkf_analysis_config_ext_module ${EXECUTABLE_OUTPUT_PATH}/enkf_analysis_config_ext_module - rml_enkf ${VAR_RML} ) - -add_executable( enkf_analysis_config_analysis_load enkf_analysis_config_analysis_load.c ) -target_link_libraries( enkf_analysis_config_analysis_load enkf test_util) -add_test( enkf_analysis_config_analysis_load ${EXECUTABLE_OUTPUT_PATH}/enkf_analysis_config_analysis_load ${CMAKE_CURRENT_SOURCE_DIR}/data/config/analysis_load_config) -set_property( TEST enkf_analysis_config_analysis_load PROPERTY ENVIRONMENT "ERT_SITE_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/data/config/analysis_load_site_config" ) - -add_executable( enkf_local_obsdata_node enkf_local_obsdata_node.c ) -target_link_libraries( enkf_local_obsdata_node enkf test_util) -add_test( enkf_local_obsdata_node ${EXECUTABLE_OUTPUT_PATH}/enkf_local_obsdata_node ) - -add_executable( enkf_local_obsdata enkf_local_obsdata.c ) -target_link_libraries( enkf_local_obsdata enkf test_util) -add_test( enkf_local_obsdata ${EXECUTABLE_OUTPUT_PATH}/enkf_local_obsdata ) - -add_executable( enkf_active_list enkf_active_list.c ) -target_link_libraries( enkf_active_list enkf test_util) -add_test( enkf_active_list ${EXECUTABLE_OUTPUT_PATH}/enkf_active_list ) - -add_executable( enkf_main enkf_main.c ) -target_link_libraries( enkf_main enkf test_util ) -add_test( enkf_main ${EXECUTABLE_OUTPUT_PATH}/enkf_main ) - -add_executable( enkf_fs enkf_fs.c ) -target_link_libraries( enkf_fs enkf test_util ) -add_test( enkf_fs ${EXECUTABLE_OUTPUT_PATH}/enkf_fs ) - -add_executable( enkf_workflow_job_test_version enkf_workflow_job_test_version.c ) -target_link_libraries( enkf_workflow_job_test_version enkf test_util ) -add_test( enkf_workflow_job_test_version ${EXECUTABLE_OUTPUT_PATH}/enkf_workflow_job_test_version - ${CMAKE_CURRENT_SOURCE_DIR}/data/workflow_jobs ) - - -add_executable( enkf_ert_test_context enkf_ert_test_context.c ) -target_link_libraries( enkf_ert_test_context enkf test_util ) -add_test( enkf_ert_test_context ${EXECUTABLE_OUTPUT_PATH}/enkf_ert_test_context - ${CMAKE_CURRENT_SOURCE_DIR}/data/config/test_context/config - ${CMAKE_CURRENT_SOURCE_DIR}/data/config/test_context/wf_job - ${CMAKE_CURRENT_SOURCE_DIR}/data/config/test_context/wf_job_fail) - - - -add_executable( enkf_plot_gen_kw enkf_plot_gen_kw.c ) -target_link_libraries( enkf_plot_gen_kw enkf test_util ) -add_test( enkf_plot_gen_kw ${EXECUTABLE_OUTPUT_PATH}/enkf_plot_gen_kw ) - -add_executable( enkf_plot_gen_kw_vector enkf_plot_gen_kw_vector.c ) -target_link_libraries( enkf_plot_gen_kw_vector enkf test_util ) -add_test( enkf_plot_gen_kw_vector ${EXECUTABLE_OUTPUT_PATH}/enkf_plot_gen_kw_vector ) - -add_executable( enkf_plot_gen_kw_fs enkf_plot_gen_kw_fs.c ) -target_link_libraries( enkf_plot_gen_kw_fs enkf test_util ) -add_test( enkf_plot_gen_kw_fs ${EXECUTABLE_OUTPUT_PATH}/enkf_plot_gen_kw_fs ${CMAKE_CURRENT_SOURCE_DIR}/data/config/gen_kw_plot/config ) - -add_executable( enkf_plot_genvector enkf_plot_genvector.c ) -target_link_libraries( enkf_plot_genvector enkf test_util ) -add_test( enkf_plot_genvector ${EXECUTABLE_OUTPUT_PATH}/enkf_plot_genvector ) - -add_executable( enkf_plot_gendata enkf_plot_gendata.c ) -target_link_libraries( enkf_plot_gendata enkf test_util ) -add_test( enkf_plot_gendata ${EXECUTABLE_OUTPUT_PATH}/enkf_plot_gendata ) - -add_executable( enkf_config_node enkf_config_node.c ) -target_link_libraries( enkf_config_node enkf test_util ) -add_test( enkf_config_node ${EXECUTABLE_OUTPUT_PATH}/enkf_config_node ) - - -#----------------------------------------------------------------- - -add_executable( gen_kw_test gen_kw_test.c ) -target_link_libraries( gen_kw_test enkf test_util ) - -add_test( gen_kw_test - ${EXECUTABLE_OUTPUT_PATH}/gen_kw_test - ${CMAKE_CURRENT_SOURCE_DIR}/data/config/forward/ert/config_GEN_KW_true) - - -add_executable( gen_kw_logarithmic_test gen_kw_logarithmic_test.c ) -target_link_libraries( gen_kw_logarithmic_test enkf test_util ) - -add_test( gen_kw_logarithmic_test - ${EXECUTABLE_OUTPUT_PATH}/gen_kw_logarithmic_test - ${CMAKE_CURRENT_SOURCE_DIR}/data/config/gen_kw_logarithmic/config_GEN_KW_logarithmic) - - - -#----------------------------------------------------------------- - -add_executable( enkf_forward_init_GEN_KW enkf_forward_init_GEN_KW.c ) -target_link_libraries( enkf_forward_init_GEN_KW enkf test_util ) - -add_test( enkf_forward_init_GEN_KW_TRUE - ${EXECUTABLE_OUTPUT_PATH}/enkf_forward_init_GEN_KW - ${CMAKE_CURRENT_SOURCE_DIR}/data/config/forward/ert config_GEN_KW_true TRUE) - -add_test( enkf_forward_init_GEN_KW_FALSE - ${EXECUTABLE_OUTPUT_PATH}/enkf_forward_init_GEN_KW - ${CMAKE_CURRENT_SOURCE_DIR}/data/config/forward/ert config_GEN_KW_false FALSE) - - -#----------------------------------------------------------------- - -add_executable( enkf_state_report_step_compatible enkf_state_report_step_compatible.c ) -target_link_libraries( enkf_state_report_step_compatible enkf test_util ) - - - - -add_executable( enkf_select_case_job enkf_select_case_job.c ) -target_link_libraries( enkf_select_case_job enkf test_util ) - -add_test( enkf_select_case_job - ${EXECUTABLE_OUTPUT_PATH}/enkf_select_case_job - ${PROJECT_SOURCE_DIR}/test-data/local/snake_oil/snake_oil.ert - ${PROJECT_SOURCE_DIR}/share/workflows/jobs/internal-tui/config/SELECT_CASE) - - -#----------------------------------------------------------------- - - -add_executable( enkf_forward_init_GEN_PARAM enkf_forward_init_GEN_PARAM.c ) -target_link_libraries( enkf_forward_init_GEN_PARAM enkf test_util ) - -add_test( enkf_forward_init_GEN_PARAM_TRUE - ${EXECUTABLE_OUTPUT_PATH}/enkf_forward_init_GEN_PARAM - ${CMAKE_CURRENT_SOURCE_DIR}/data/config/forward/ert config_GEN_PARAM_true TRUE) - -add_test( enkf_forward_init_GEN_PARAM_FALSE - ${EXECUTABLE_OUTPUT_PATH}/enkf_forward_init_GEN_PARAM - ${CMAKE_CURRENT_SOURCE_DIR}/data/config/forward/ert config_GEN_PARAM_false FALSE) - - -add_executable( enkf_umask_config_test enkf_umask_config_test.c ) -target_link_libraries( enkf_umask_config_test enkf test_util ) - -add_test( enkf_umask_config_test - ${EXECUTABLE_OUTPUT_PATH}/enkf_umask_config_test - ${PROJECT_SOURCE_DIR}/test-data/local/simple_config/config_umask) - -#----------------------------------------------------------------- - -add_executable( enkf_iter_config enkf_iter_config.c ) -target_link_libraries( enkf_iter_config enkf test_util ) -add_test( enkf_iter_config ${EXECUTABLE_OUTPUT_PATH}/enkf_iter_config ) - - -add_executable( enkf_model_config enkf_model_config.c ) -target_link_libraries( enkf_model_config enkf test_util ) -add_test( enkf_model_config ${EXECUTABLE_OUTPUT_PATH}/enkf_model_config ) - -add_executable( enkf_rng enkf_rng.c ) -target_link_libraries( enkf_rng enkf test_util ) -add_test( enkf_rng ${EXECUTABLE_OUTPUT_PATH}/enkf_rng ${CMAKE_CURRENT_SOURCE_DIR}/data/config rng) - -add_executable( enkf_forward_load_context enkf_forward_load_context.c ) -target_link_libraries( enkf_forward_load_context enkf test_util ) -add_test( enkf_forward_load_context ${EXECUTABLE_OUTPUT_PATH}/enkf_forward_load_context ${CMAKE_CURRENT_SOURCE_DIR}/data/config forward_load_context) - - -add_executable( enkf_hook_manager_test enkf_hook_manager_test.c ) -target_link_libraries( enkf_hook_manager_test enkf test_util ) -add_test( enkf_hook_manager_test ${EXECUTABLE_OUTPUT_PATH}/enkf_hook_manager_test ) - -add_executable(enkf_obs_tests enkf_obs_tests.c) -target_link_libraries(enkf_obs_tests enkf test_util ) -add_test(enkf_obs_tests ${EXECUTABLE_OUTPUT_PATH}/enkf_obs_tests) - -add_executable(obs_vector_tests obs_vector_tests.c) -target_link_libraries(obs_vector_tests enkf test_util ) -add_test(obs_vector_tests ${EXECUTABLE_OUTPUT_PATH}/obs_vector_tests) - - -add_executable( enkf_state_map enkf_state_map.c ) -target_link_libraries( enkf_state_map enkf test_util ) -add_test( enkf_state_map ${EXECUTABLE_OUTPUT_PATH}/enkf_state_map ) - - -add_executable( enkf_meas_data enkf_meas_data.c ) -target_link_libraries( enkf_meas_data enkf test_util ) -add_test( enkf_meas_data ${EXECUTABLE_OUTPUT_PATH}/enkf_meas_data ) - -add_executable( enkf_ensemble_GEN_PARAM enkf_ensemble_GEN_PARAM.c ) -target_link_libraries( enkf_ensemble_GEN_PARAM enkf test_util ) -add_test( enkf_ensemble_GEN_PARAM ${EXECUTABLE_OUTPUT_PATH}/enkf_ensemble_GEN_PARAM ${CMAKE_CURRENT_SOURCE_DIR}/data/ensemble/GEN_PARAM ) - -add_executable( enkf_ensemble enkf_ensemble.c ) -target_link_libraries( enkf_ensemble enkf test_util ) -add_test( enkf_ensemble ${EXECUTABLE_OUTPUT_PATH}/enkf_ensemble ) diff --git a/ThirdParty/Ert/libert_util/include/ert/util/ert_api_config.h.in b/ThirdParty/Ert/libert_util/include/ert/util/ert_api_config.h.in index 5dfd4b0cc4..11b43d6b19 100644 --- a/ThirdParty/Ert/libert_util/include/ert/util/ert_api_config.h.in +++ b/ThirdParty/Ert/libert_util/include/ert/util/ert_api_config.h.in @@ -15,6 +15,6 @@ #cmakedefine ERT_TIME_T_64BIT_ACCEPT_PRE1970 #cmakedefine ERT_WINDOWS_LFS #cmakedefine ERT_HAVE_PING - +#cmakedefine PING_CMD "@PING_PATH@" diff --git a/ThirdParty/Ert/libert_util/include/ert/util/struct_vector.h b/ThirdParty/Ert/libert_util/include/ert/util/struct_vector.h index 58a9804966..79f56ffe18 100644 --- a/ThirdParty/Ert/libert_util/include/ert/util/struct_vector.h +++ b/ThirdParty/Ert/libert_util/include/ert/util/struct_vector.h @@ -26,14 +26,18 @@ extern "C" { typedef struct struct_vector_struct struct_vector_type; - +typedef int ( struct_vector_cmp_ftype ) (const void * , const void *); struct_vector_type * struct_vector_alloc( int element_size ); void struct_vector_free( struct_vector_type * struct_vector ); int struct_vector_get_size( const struct_vector_type * struct_vector ); void struct_vector_append( struct_vector_type * struct_vector , void * value); void struct_vector_iget( const struct_vector_type * struct_vector , int index , void * value); + void * struct_vector_iget_ptr( const struct_vector_type * struct_vector , int index); void struct_vector_reset( struct_vector_type * struct_vector ); + void struct_vector_reserve( struct_vector_type * struct_vector , int reserve_size); + void * struct_vector_get_data( const struct_vector_type * struct_vector ); + void struct_vector_sort( struct_vector_type * struct_vector , struct_vector_cmp_ftype * cmp); UTIL_IS_INSTANCE_HEADER( struct_vector ); diff --git a/ThirdParty/Ert/libert_util/include/ert/util/test_util.h b/ThirdParty/Ert/libert_util/include/ert/util/test_util.h index 8c68dbe8f8..131ef67735 100644 --- a/ThirdParty/Ert/libert_util/include/ert/util/test_util.h +++ b/ThirdParty/Ert/libert_util/include/ert/util/test_util.h @@ -26,6 +26,7 @@ extern "C" { #include #include +#include #include #if defined(__APPLE__) @@ -123,6 +124,11 @@ extern "C" { void test_install_SIGNALS(void); + jmp_buf * util_abort_test_jump_buffer(); + void test_util_addr2line(); + void test_assert_util_abort(const char * function_name , void call_func (void *) , void * arg); + + #ifdef __cplusplus } #endif diff --git a/ThirdParty/Ert/libert_util/include/ert/util/test_util_abort.h b/ThirdParty/Ert/libert_util/include/ert/util/test_util_abort.h deleted file mode 100644 index 2a2ad843ff..0000000000 --- a/ThirdParty/Ert/libert_util/include/ert/util/test_util_abort.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'test_util_abort.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/* - This header is purely a convenience header - it is not installed. -*/ - -#ifndef ERT_TEST_UTIL_ABORT -#define ERT_TEST_UTIL_ABORT - -#ifdef __cplusplus -extern "C" { -#endif - -#include - - jmp_buf * util_abort_test_jump_buffer(); - void test_util_addr2line(); - void test_assert_util_abort(const char * function_name , void call_func (void *) , void * arg); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/ThirdParty/Ert/libert_util/include/ert/util/util.h b/ThirdParty/Ert/libert_util/include/ert/util/util.h index 4121512027..d8a134d8d1 100644 --- a/ThirdParty/Ert/libert_util/include/ert/util/util.h +++ b/ThirdParty/Ert/libert_util/include/ert/util/util.h @@ -294,6 +294,8 @@ typedef enum {left_pad = 0, bool util_string_isspace(const char * s); char * util_alloc_dump_filename(void); + void util_abort_test_set_intercept_function(const char *); + bool util_addr2line_lookup(const void *, char **, char **, int *); void util_exit(const char * fmt , ...); void util_install_signals(void); void util_update_signals(void); diff --git a/ThirdParty/Ert/libert_util/src/CMakeLists.txt b/ThirdParty/Ert/libert_util/src/CMakeLists.txt index ec6cbde855..4765a45a9c 100644 --- a/ThirdParty/Ert/libert_util/src/CMakeLists.txt +++ b/ThirdParty/Ert/libert_util/src/CMakeLists.txt @@ -33,6 +33,7 @@ set(source_files ert_version.c struct_vector.c perm_vector.c + test_util.c ) set(header_files @@ -71,10 +72,9 @@ set(header_files buffer_string.h perm_vector.h ert_version.h + test_util.h ) -set( test_source test_util.c ) -set( test_headers test_util.h ) # Add compile time variable values to ert_version.c @@ -162,11 +162,6 @@ if (ERT_BUILD_CXX) endif() add_library( ert_util ${LIBRARY_TYPE} ${source_files} ) -if (BUILD_TESTS) - add_library( test_util ${LIBRARY_TYPE} ${test_source} ) - target_link_libraries( test_util ert_util ) - set_target_properties( test_util PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR} ) -endif() message(STATUS "Linking with: ${ERT_EXTERNAL_UTIL_LIBS}") set_target_properties( ert_util PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR} ) diff --git a/ThirdParty/Ert/libert_util/src/struct_vector.c b/ThirdParty/Ert/libert_util/src/struct_vector.c index a60dd086b2..9f17b8e0c0 100644 --- a/ThirdParty/Ert/libert_util/src/struct_vector.c +++ b/ThirdParty/Ert/libert_util/src/struct_vector.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'struct_vector.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. + Copyright (C) 2014 Statoil ASA, Norway. + + The file 'struct_vector.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 at + for more details. */ #include @@ -30,7 +30,7 @@ struct struct_vector_struct { int size; int element_size; int alloc_size; - + char * data; }; @@ -43,6 +43,12 @@ static void struct_vector_resize( struct_vector_type * struct_vector , int new_a } +void struct_vector_reserve( struct_vector_type * struct_vector , int reserve_size) { + if (reserve_size > struct_vector->alloc_size) + struct_vector_resize( struct_vector , reserve_size ); +} + + struct_vector_type * struct_vector_alloc( int element_size ) { if (element_size <= 0) { @@ -57,9 +63,9 @@ struct_vector_type * struct_vector_alloc( int element_size ) { vector->alloc_size = 0; vector->element_size = element_size; vector->data = NULL; - + struct_vector_resize( vector , 10 ); - + return vector; } } @@ -88,6 +94,10 @@ void struct_vector_append( struct_vector_type * struct_vector , void * value) { } +void * struct_vector_get_data( const struct_vector_type * struct_vector ) { + return struct_vector->data; +} + void struct_vector_iget( const struct_vector_type * struct_vector , int index , void * value) { if (index < struct_vector->size) { @@ -98,7 +108,21 @@ void struct_vector_iget( const struct_vector_type * struct_vector , int index , } +void * struct_vector_iget_ptr( const struct_vector_type * struct_vector , int index ) { + if (index < struct_vector->size) { + size_t offset = index * struct_vector->element_size; + return &struct_vector->data[offset]; + } else + util_abort("%s: fatal error - invalid index:%d size:%d\n",__func__ , index , struct_vector->size); + return NULL; +} + void struct_vector_reset( struct_vector_type * struct_vector ) { struct_vector->size = 0; } + + +void struct_vector_sort( struct_vector_type * struct_vector , struct_vector_cmp_ftype * cmp) { + qsort(struct_vector->data , struct_vector->size , struct_vector->element_size , cmp); +} diff --git a/ThirdParty/Ert/libert_util/src/test_util.c b/ThirdParty/Ert/libert_util/src/test_util.c index 831fac17fb..760f37d9af 100644 --- a/ThirdParty/Ert/libert_util/src/test_util.c +++ b/ThirdParty/Ert/libert_util/src/test_util.c @@ -29,7 +29,7 @@ #include #include #include - +#include void test_error_exit( const char * fmt , ...) { char * s; @@ -287,12 +287,6 @@ void test_install_SIGNALS(void) { #ifdef HAVE_BACKTRACE #include -#include - - bool util_addr2line_lookup(const void * bt_addr , char ** func_name , char ** file_name , int * line_nr); - jmp_buf * util_abort_test_jump_buffer(); - void util_abort_test_set_intercept_function(const char * function); - void test_util_addr2line() { @@ -315,12 +309,6 @@ void test_util_addr2line() { } - - - - - - void test_assert_util_abort(const char * function_name , void call_func (void *) , void * arg) { bool util_abort_intercepted = false; @@ -343,6 +331,27 @@ void test_assert_util_abort(const char * function_name , void call_func (void *) } } +#else + +/* + These are non-functional stubs. +*/ + +bool util_addr2line_lookup(const void * bt_addr , char ** func_name , char ** file_name , int * line_nr) +{ + return false; +} + +jmp_buf * util_abort_test_jump_buffer() +{ + return NULL; +} + +void util_abort_test_set_intercept_function(const char * function) +{ + return; +} + #endif diff --git a/ThirdParty/Ert/libert_util/src/test_work_area.c b/ThirdParty/Ert/libert_util/src/test_work_area.c index f9010eaf91..2ca36ac7c9 100644 --- a/ThirdParty/Ert/libert_util/src/test_work_area.c +++ b/ThirdParty/Ert/libert_util/src/test_work_area.c @@ -137,8 +137,9 @@ static test_work_area_type * test_work_area_alloc__(const char * prefix , const work_area->original_cwd = util_alloc_cwd(); work_area->cwd = test_cwd; work_area->change_dir = change_dir; - if (change_dir) - util_chdir( work_area->cwd ); + if (change_dir ) + if(util_chdir( work_area->cwd ) != 0) + util_abort("%s: Failed to move into temporary directory: %s", __func__, test_cwd); test_work_area_set_store( work_area , DEFAULT_STORE); diff --git a/ThirdParty/Ert/libert_util/src/util_abort_gnu.c b/ThirdParty/Ert/libert_util/src/util_abort_gnu.c index 19084fcc1e..c595f3fe46 100644 --- a/ThirdParty/Ert/libert_util/src/util_abort_gnu.c +++ b/ThirdParty/Ert/libert_util/src/util_abort_gnu.c @@ -75,7 +75,7 @@ static bool util_addr2line_lookup__(const void * bt_addr , char ** func_name , c } /* 2: Parse stdout output */ - { + if (util_file_exists( stdout_file )) { bool at_eof; FILE * stream = util_fopen(stdout_file , "r"); char * tmp_fname = util_fscanf_alloc_line(stream , &at_eof); @@ -293,7 +293,7 @@ void util_abort__(const char * file , const char * function , int line , const c } fprintf(stderr, "\nSee file: %s for more details of the crash.\nSetting the environment variable \"ERT_SHOW_BACKTRACE\" will show the backtrace on stderr.\n", filename); } - + chmod(filename, 00644); // -rw-r--r-- free(filename); } @@ -304,4 +304,3 @@ void util_abort__(const char * file , const char * function , int line , const c /*****************************************************************/ - diff --git a/ThirdParty/Ert/libert_util/tests/CMakeLists.txt b/ThirdParty/Ert/libert_util/tests/CMakeLists.txt index 33f9d5db2c..2142cab296 100644 --- a/ThirdParty/Ert/libert_util/tests/CMakeLists.txt +++ b/ThirdParty/Ert/libert_util/tests/CMakeLists.txt @@ -1,200 +1,196 @@ -# This should be a space separated list of up to three servers which -# will be tried out when testing the util_ping() functionality. The -# list of servers should behave like this: -# -# 1. First server - this should be an existing server which should return true. -# 2. This should be an invalid hostname - should return false. -# 3. This should be an valid host which does not answer ping - i.e currently off? -set(PING_SERVERS "" CACHE STRING "List of servers for testing ping") - - link_directories( ${ERT_BINARY_DIR}/libert_util/src ) add_executable( test_thread_pool test_thread_pool.c ) -target_link_libraries( test_thread_pool ert_util test_util ) -add_test( test_thread_pool valgrind --error-exitcode=1 --tool=memcheck ${EXECUTABLE_OUTPUT_PATH}/test_thread_pool ) +target_link_libraries( test_thread_pool ert_util ) + +find_library( VALGRIND NAMES valgr ) +if (VALGRIND) + add_test( test_thread_pool valgrind --error-exitcode=1 --tool=memcheck ${EXECUTABLE_OUTPUT_PATH}/test_thread_pool ) +else() + add_test( test_thread_pool ${EXECUTABLE_OUTPUT_PATH}/test_thread_pool ) +endif() add_executable( ert_util_matrix ert_util_matrix.c ) -target_link_libraries( ert_util_matrix ert_util test_util ) +target_link_libraries( ert_util_matrix ert_util ) add_test( ert_util_matrix ${EXECUTABLE_OUTPUT_PATH}/ert_util_matrix ) if (ERT_HAVE_LAPACK) add_executable( ert_util_matrix_lapack ert_util_matrix_lapack.c ) - target_link_libraries( ert_util_matrix_lapack ert_util test_util ) + target_link_libraries( ert_util_matrix_lapack ert_util ) add_test( ert_util_matrix_lapack ${EXECUTABLE_OUTPUT_PATH}/ert_util_matrix_lapack ) add_executable( ert_util_matrix_stat ert_util_matrix_stat.c ) - target_link_libraries( ert_util_matrix_stat ert_util test_util ) + target_link_libraries( ert_util_matrix_stat ert_util ) add_test( ert_util_matrix_stat ${EXECUTABLE_OUTPUT_PATH}/ert_util_matrix_stat ) endif() add_executable( ert_util_subst_list ert_util_subst_list.c ) -target_link_libraries( ert_util_subst_list ert_util test_util ) +target_link_libraries( ert_util_subst_list ert_util ) add_test( ert_util_subst_list ${EXECUTABLE_OUTPUT_PATH}/ert_util_subst_list ) add_executable( ert_util_buffer ert_util_buffer.c ) -target_link_libraries( ert_util_buffer ert_util test_util ) +target_link_libraries( ert_util_buffer ert_util ) add_test( ert_util_buffer ${EXECUTABLE_OUTPUT_PATH}/ert_util_buffer ) add_executable( ert_util_statistics ert_util_statistics.c ) -target_link_libraries( ert_util_statistics ert_util test_util ) +target_link_libraries( ert_util_statistics ert_util ) add_test( ert_util_statistics ${EXECUTABLE_OUTPUT_PATH}/ert_util_statistics ) add_executable( ert_util_copy_file ert_util_copy_file.c ) -target_link_libraries( ert_util_copy_file ert_util test_util ) +target_link_libraries( ert_util_copy_file ert_util ) add_test( ert_util_copy_file ${EXECUTABLE_OUTPUT_PATH}/ert_util_copy_file ${EXECUTABLE_OUTPUT_PATH}/ert_util_copy_file ) add_executable( ert_util_filename ert_util_filename.c ) -target_link_libraries( ert_util_filename ert_util test_util ) +target_link_libraries( ert_util_filename ert_util ) add_test( ert_util_filename ${EXECUTABLE_OUTPUT_PATH}/ert_util_filename ) add_executable( ert_util_sscan_test ert_util_sscan_test.c ) -target_link_libraries( ert_util_sscan_test ert_util test_util ) +target_link_libraries( ert_util_sscan_test ert_util ) add_test( ert_util_sscan_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_sscan_test ) add_executable( ert_util_string_util ert_util_string_util.c ) -target_link_libraries( ert_util_string_util ert_util test_util ) +target_link_libraries( ert_util_string_util ert_util ) add_test( ert_util_string_util ${EXECUTABLE_OUTPUT_PATH}/ert_util_string_util ) add_executable( ert_util_vector_test ert_util_vector_test.c ) -target_link_libraries( ert_util_vector_test ert_util test_util ) +target_link_libraries( ert_util_vector_test ert_util ) add_test( ert_util_vector_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_vector_test ) add_executable( ert_util_cwd_test ert_util_cwd_test.c ) -target_link_libraries( ert_util_cwd_test ert_util test_util ) +target_link_libraries( ert_util_cwd_test ert_util ) add_test( ert_util_cwd_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_cwd_test ${CMAKE_CURRENT_BINARY_DIR}) add_executable( ert_util_relpath_test ert_util_relpath_test.c ) -target_link_libraries( ert_util_relpath_test ert_util test_util ) +target_link_libraries( ert_util_relpath_test ert_util ) add_test( ert_util_relpath_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_relpath_test ) add_executable( ert_util_path_stack_test ert_util_path_stack_test.c ) -target_link_libraries( ert_util_path_stack_test ert_util test_util ) +target_link_libraries( ert_util_path_stack_test ert_util ) add_test( ert_util_path_stack_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_path_stack_test ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) add_executable( ert_util_PATH_test ert_util_PATH_test.c ) -target_link_libraries( ert_util_PATH_test ert_util test_util ) +target_link_libraries( ert_util_PATH_test ert_util ) add_test( ert_util_PATH_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_PATH_test ) add_executable( ert_util_strcat_test ert_util_strcat_test.c ) -target_link_libraries( ert_util_strcat_test ert_util test_util ) +target_link_libraries( ert_util_strcat_test ert_util ) add_test( ert_util_strcat_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_strcat_test ) add_executable( ert_util_sprintf_escape ert_util_sprintf_escape.c ) -target_link_libraries( ert_util_sprintf_escape ert_util test_util ) +target_link_libraries( ert_util_sprintf_escape ert_util ) add_test( ert_util_sprintf_escape ${EXECUTABLE_OUTPUT_PATH}/ert_util_sprintf_escape ) add_executable( ert_util_stringlist_test ert_util_stringlist_test.c ) -target_link_libraries( ert_util_stringlist_test ert_util test_util ) +target_link_libraries( ert_util_stringlist_test ert_util ) add_test( ert_util_stringlist_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_stringlist_test ) add_executable( ert_util_realpath ert_util_realpath.c ) -target_link_libraries( ert_util_realpath ert_util test_util ) +target_link_libraries( ert_util_realpath ert_util ) add_test( ert_util_realpath ${EXECUTABLE_OUTPUT_PATH}/ert_util_realpath ) add_executable( ert_util_hash_test ert_util_hash_test.c ) -target_link_libraries( ert_util_hash_test ert_util test_util ) +target_link_libraries( ert_util_hash_test ert_util ) add_test( ert_util_hash_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_hash_test ) add_executable( ert_util_binary_split ert_util_binary_split.c ) -target_link_libraries( ert_util_binary_split ert_util test_util ) +target_link_libraries( ert_util_binary_split ert_util ) add_test( ert_util_binary_split ${EXECUTABLE_OUTPUT_PATH}/ert_util_binary_split ) add_executable( ert_util_logh ert_util_logh.c ) -target_link_libraries( ert_util_logh ert_util test_util ) +target_link_libraries( ert_util_logh ert_util ) add_test( ert_util_logh ${EXECUTABLE_OUTPUT_PATH}/ert_util_logh ) add_executable( ert_util_rng ert_util_rng.c ) -target_link_libraries( ert_util_rng ert_util test_util ) +target_link_libraries( ert_util_rng ert_util ) add_test( ert_util_rng ${EXECUTABLE_OUTPUT_PATH}/ert_util_rng ) add_executable( ert_util_time_interval ert_util_time_interval.c ) -target_link_libraries( ert_util_time_interval ert_util test_util ) +target_link_libraries( ert_util_time_interval ert_util ) add_test( ert_util_time_interval ${EXECUTABLE_OUTPUT_PATH}/ert_util_time_interval ) add_executable( ert_util_before_after ert_util_before_after.c ) -target_link_libraries( ert_util_before_after ert_util test_util ) +target_link_libraries( ert_util_before_after ert_util ) add_test( ert_util_before_after ${EXECUTABLE_OUTPUT_PATH}/ert_util_before_after ) add_executable( ert_util_approx_equal ert_util_approx_equal.c ) -target_link_libraries( ert_util_approx_equal ert_util test_util ) +target_link_libraries( ert_util_approx_equal ert_util ) add_test( ert_util_approx_equal ${EXECUTABLE_OUTPUT_PATH}/ert_util_approx_equal ) -if (PING_PATH) +if (ERT_HAVE_PING) add_executable( ert_util_ping ert_util_ping.c ) - target_link_libraries( ert_util_ping ert_util test_util ) - add_test( ert_util_ping ${EXECUTABLE_OUTPUT_PATH}/ert_util_ping ${PING_SERVERS}) + target_link_libraries( ert_util_ping ert_util ) + add_test( ert_util_ping ${EXECUTABLE_OUTPUT_PATH}/ert_util_ping) endif() add_executable( ert_util_file_readable ert_util_file_readable.c ) -target_link_libraries( ert_util_file_readable ert_util test_util ) +target_link_libraries( ert_util_file_readable ert_util ) add_test( ert_util_file_readable ${EXECUTABLE_OUTPUT_PATH}/ert_util_file_readable ${FILE_READABLE_SERVERS}) add_executable( ert_util_type_vector_functions ert_util_type_vector_functions.c ) -target_link_libraries( ert_util_type_vector_functions ert_util test_util ) +target_link_libraries( ert_util_type_vector_functions ert_util ) add_test( ert_util_type_vector_functions ${EXECUTABLE_OUTPUT_PATH}/ert_util_type_vector_functions) add_executable( ert_util_ui_return ert_util_ui_return.c ) -target_link_libraries( ert_util_ui_return ert_util test_util ) +target_link_libraries( ert_util_ui_return ert_util ) add_test( ert_util_ui_return ${EXECUTABLE_OUTPUT_PATH}/ert_util_ui_return ) add_executable( ert_util_clamp ert_util_clamp.c ) -target_link_libraries( ert_util_clamp ert_util test_util ) +target_link_libraries( ert_util_clamp ert_util ) add_test( ert_util_clamp ${EXECUTABLE_OUTPUT_PATH}/ert_util_clamp ) add_executable( ert_util_strstr_int_format ert_util_strstr_int_format.c ) -target_link_libraries( ert_util_strstr_int_format ert_util test_util ) +target_link_libraries( ert_util_strstr_int_format ert_util ) add_test( ert_util_strstr_int_format ${EXECUTABLE_OUTPUT_PATH}/ert_util_strstr_int_format ) add_executable( ert_util_parent_path ert_util_parent_path.c ) -target_link_libraries( ert_util_parent_path ert_util test_util ) +target_link_libraries( ert_util_parent_path ert_util ) add_test( ert_util_parent_path ${EXECUTABLE_OUTPUT_PATH}/ert_util_parent_path) add_executable( ert_util_alloc_file_components ert_util_alloc_file_components.c ) -target_link_libraries( ert_util_alloc_file_components ert_util test_util ) +target_link_libraries( ert_util_alloc_file_components ert_util ) add_test( ert_util_alloc_file_components ${EXECUTABLE_OUTPUT_PATH}/ert_util_alloc_file_components) add_executable( ert_util_work_area ert_util_work_area.c ) -target_link_libraries( ert_util_work_area ert_util test_util ) +target_link_libraries( ert_util_work_area ert_util ) add_test( NAME ert_util_work_area COMMAND ${EXECUTABLE_OUTPUT_PATH}/ert_util_work_area data2/file1 ${CMAKE_CURRENT_SOURCE_DIR}/data2/file2 data2 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) add_executable( ert_util_arg_pack ert_util_arg_pack.c) set_target_properties( ert_util_arg_pack PROPERTIES COMPILE_FLAGS "-Werror") -target_link_libraries( ert_util_arg_pack ert_util test_util ) +target_link_libraries( ert_util_arg_pack ert_util ) add_test( ert_util_arg_pack ${EXECUTABLE_OUTPUT_PATH}/ert_util_arg_pack) if (HAVE_BACKTRACE) add_executable( ert_util_abort_gnu_tests ert_util_abort_gnu_tests.c) - target_link_libraries( ert_util_abort_gnu_tests ert_util test_util) + target_link_libraries( ert_util_abort_gnu_tests ert_util ) add_test( ert_util_abort_gnu_tests ${EXECUTABLE_OUTPUT_PATH}/ert_util_abort_gnu_tests) add_executable( ert_util_addr2line ert_util_addr2line.c ) - target_link_libraries( ert_util_addr2line ert_util test_util ) + target_link_libraries( ert_util_addr2line ert_util ) add_test( ert_util_addr2line ${EXECUTABLE_OUTPUT_PATH}/ert_util_addr2line) endif() if (HAVE_UTIL_ABORT_INTERCEPT) add_executable( ert_util_block_fs ert_util_block_fs.c) - target_link_libraries( ert_util_block_fs ert_util test_util) + target_link_libraries( ert_util_block_fs ert_util ) add_test( ert_util_block_fs ${EXECUTABLE_OUTPUT_PATH}/ert_util_block_fs) add_executable( ert_util_struct_vector ert_util_struct_vector.c ) - target_link_libraries( ert_util_struct_vector ert_util test_util ) + target_link_libraries( ert_util_struct_vector ert_util ) add_test( ert_util_struct_vector ${EXECUTABLE_OUTPUT_PATH}/ert_util_struct_vector ) add_executable( ert_util_type_vector_test ert_util_type_vector_test.c ) - target_link_libraries( ert_util_type_vector_test ert_util test_util ) + target_link_libraries( ert_util_type_vector_test ert_util ) add_test( ert_util_type_vector_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_type_vector_test ) endif() if (ERT_HAVE_SPAWN) add_executable( ert_util_spawn ert_util_spawn.c ) - target_link_libraries( ert_util_spawn ert_util test_util ) + target_link_libraries( ert_util_spawn ert_util ) add_test( ert_util_spawn ${EXECUTABLE_OUTPUT_PATH}/ert_util_spawn) endif() diff --git a/ThirdParty/Ert/libert_util/tests/ert_util_abort_gnu_tests.c b/ThirdParty/Ert/libert_util/tests/ert_util_abort_gnu_tests.c index c8f91affce..923240054f 100644 --- a/ThirdParty/Ert/libert_util/tests/ert_util_abort_gnu_tests.c +++ b/ThirdParty/Ert/libert_util/tests/ert_util_abort_gnu_tests.c @@ -1,4 +1,4 @@ -/* +/* * File: ert_util_abort_gnu_tests.c * Author: kflik * @@ -9,7 +9,6 @@ #include #include #include -#include void test_assert_util_abort(const char * function_name , void (void *) , void * arg); diff --git a/ThirdParty/Ert/libert_util/tests/ert_util_addr2line.c b/ThirdParty/Ert/libert_util/tests/ert_util_addr2line.c index c621a3b332..5aa62222c0 100644 --- a/ThirdParty/Ert/libert_util/tests/ert_util_addr2line.c +++ b/ThirdParty/Ert/libert_util/tests/ert_util_addr2line.c @@ -1,19 +1,19 @@ /* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'ert_util_addr2line.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. + Copyright (C) 2012 Statoil ASA, Norway. + + The file 'ert_util_addr2line.c' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 at + for more details. */ #include #include @@ -23,7 +23,6 @@ #include #include #include -#include @@ -32,15 +31,15 @@ void test_lookup(bool valid_address, bool change_cwd) { const char * func = __func__; int line; const int max_bt = 50; - void *bt_addr[max_bt]; + void *bt_addr[max_bt]; int size; char * func_name , * file_name; int line_nr; - + line = __LINE__ + 2; - size = backtrace(bt_addr , max_bt); + size = backtrace(bt_addr , max_bt); test_assert_int_equal( size , 4 ); - + if (change_cwd) { char * cwd = util_alloc_cwd(); util_chdir("/tmp"); @@ -80,14 +79,14 @@ int main( int argc , char ** argv) { char * path; char * name; char * dot_name; - /* + /* This bisaaarre hoopsing is to be able to emulate the situation where addr2line can not find the executable; this behaviour is invoked when change_cwd is set to true in the test_lookup() - call. + call. */ util_alloc_file_components( argv[0] , &path , &name, NULL); - + util_chdir(path); dot_name = util_alloc_sprintf("./%s" , name); util_spawn_blocking(dot_name, 0, NULL, NULL, NULL); @@ -96,13 +95,13 @@ int main( int argc , char ** argv) { printf("Testing internal lookup ....\n"); test_lookup(true, false); test_lookup(false , false); - + test_lookup(true, true); test_lookup(false , true); - + printf("Testing external lookup ....\n"); - test_util_addr2line(); - + test_util_addr2line(); + exit(0); } } diff --git a/ThirdParty/Ert/libert_util/tests/ert_util_matrix.c b/ThirdParty/Ert/libert_util/tests/ert_util_matrix.c index ac6492f36c..c3c47a0953 100644 --- a/ThirdParty/Ert/libert_util/tests/ert_util_matrix.c +++ b/ThirdParty/Ert/libert_util/tests/ert_util_matrix.c @@ -28,8 +28,6 @@ #include #include #include -#include - void test_resize() { @@ -96,54 +94,6 @@ void test_dims() { } -void test_det4() { - matrix_type * m = matrix_alloc(4 , 4 ); - rng_type * rng = rng_alloc(MZRAN , INIT_DEV_URANDOM ); - for (int i=0; i < 10; i++) { - matrix_random_init( m , rng ); - { - double det4 = matrix_det4( m ); - double det = matrix_det( m ); - - test_assert_double_equal( det , det4 ); - } - } - - matrix_free( m ); - rng_free( rng ); -} - - -void test_det3() { - matrix_type * m = matrix_alloc(3 , 3 ); - rng_type * rng = rng_alloc(MZRAN , INIT_DEV_URANDOM ); - matrix_random_init( m , rng ); - - { - double det3 = matrix_det3( m ); - double det = matrix_det( m ); - - test_assert_double_equal( det , det3 ); - } - - matrix_free( m ); - rng_free( rng ); -} - - -void test_det2() { - matrix_type * m = matrix_alloc(2,2); - rng_type * rng = rng_alloc(MZRAN , INIT_DEV_URANDOM ); - matrix_random_init( m , rng ); - { - double det2 = matrix_det2( m ); - double det = matrix_det( m ); - - test_assert_double_equal( det , det2 ); - } - matrix_free( m ); - rng_free( rng ); -} void test_readwrite() { @@ -283,9 +233,7 @@ int main( int argc , char ** argv) { test_resize(); test_column_equal(); test_dims(); - test_det2(); - test_det3(); - test_det4(); + test_readwrite(); test_diag_std(); test_masked_copy(); diff --git a/ThirdParty/Ert/libert_util/tests/ert_util_ping.c b/ThirdParty/Ert/libert_util/tests/ert_util_ping.c index 52cd1e16ff..4910a11dcb 100644 --- a/ThirdParty/Ert/libert_util/tests/ert_util_ping.c +++ b/ThirdParty/Ert/libert_util/tests/ert_util_ping.c @@ -30,13 +30,5 @@ int main( int argc , char ** argv) { test_assert_true( util_ping("127.0.0.1" )); test_assert_false( util_ping("does.not.exist")); - if (argc > 1) { - stringlist_type * server_list = stringlist_alloc_from_split( argv[1] , " "); - int is ; - for (is = 0; is < stringlist_get_size( server_list ); is++) { - test_assert_true( util_ping( stringlist_iget( server_list , is ))); - } - } - exit(0); } diff --git a/ThirdParty/Ert/libert_util/tests/ert_util_struct_vector.c b/ThirdParty/Ert/libert_util/tests/ert_util_struct_vector.c index 6e863d0b9f..67a7347964 100644 --- a/ThirdParty/Ert/libert_util/tests/ert_util_struct_vector.c +++ b/ThirdParty/Ert/libert_util/tests/ert_util_struct_vector.c @@ -38,6 +38,8 @@ void test_create() { struct_vector_type * struct_vector = struct_vector_alloc( sizeof d ); test_assert_true( struct_vector_is_instance( struct_vector )); test_assert_int_equal( struct_vector_get_size( struct_vector ) , 0 ); + struct_vector_reserve( struct_vector , 1000 ); + test_assert_int_equal( struct_vector_get_size( struct_vector ) , 0 ); struct_vector_free( struct_vector ); } @@ -59,7 +61,9 @@ void test_append_iget() { struct_vector_append( struct_vector , &d1 ); test_assert_int_equal( struct_vector_get_size( struct_vector ) , 1 ); - + struct_vector_reserve( struct_vector , 0 ); + test_assert_int_equal( struct_vector_get_size( struct_vector ) , 1 ); + test_assert_false( d1.x == d2.x ); test_assert_false( d1.y == d2.y ); test_assert_false( d1.z == d2.z ); @@ -69,6 +73,13 @@ void test_append_iget() { test_assert_true( d1.y == d2.y ); test_assert_true( d1.z == d2.z ); + { + struct test_struct * d = struct_vector_get_data( struct_vector ); + struct test_struct d3 = d[0]; + test_assert_true( d1.x == d3.x ); + test_assert_true( d1.y == d3.y ); + test_assert_true( d1.z == d3.z ); + } struct_vector_reset( struct_vector ); test_assert_int_equal( struct_vector_get_size( struct_vector ) , 0 ); @@ -77,9 +88,53 @@ void test_append_iget() { +int cmp( const void * _d1, const void * _d2) { + const struct test_struct * d1 = (const struct test_struct *) _d1; + const struct test_struct * d2 = (const struct test_struct *) _d2; + + return d1->x - d2->x; +} + + +int rcmp( const void * _d1, const void * _d2) { + return cmp(_d2 , _d1); +} + + + +void test_sort() { + struct test_struct d; + struct_vector_type * struct_vector = struct_vector_alloc( sizeof d ); + for (int i = 0; i < 10; i++) { + struct test_struct d = {.x = 9 - i, + .y = 9 - i, + .z = 9 - i }; + struct_vector_append( struct_vector , &d ); + } + struct_vector_sort( struct_vector , cmp ); + for (int i = 0; i < 9; i++) { + struct test_struct d1; + struct test_struct d2; + struct_vector_iget( struct_vector , i ,&d1 ); + struct_vector_iget( struct_vector , i + 1,&d2 ); + test_assert_true( cmp(&d1 , &d2) <= 0); + } + + struct_vector_sort( struct_vector , rcmp ); + for (int i = 0; i < 9; i++) { + struct test_struct d1; + struct test_struct d2; + struct_vector_iget( struct_vector , i ,&d1 ); + struct_vector_iget( struct_vector , i + 1,&d2 ); + test_assert_true( cmp(&d1 , &d2) >= 0); + } +} + + int main(int argc , char ** argv) { test_create(); test_create_invalid(); test_append_iget(); + test_sort(); } diff --git a/ThirdParty/Ert/libert_util/tests/ert_util_type_vector_test.c b/ThirdParty/Ert/libert_util/tests/ert_util_type_vector_test.c index b75768b500..e5bc248634 100644 --- a/ThirdParty/Ert/libert_util/tests/ert_util_type_vector_test.c +++ b/ThirdParty/Ert/libert_util/tests/ert_util_type_vector_test.c @@ -21,7 +21,6 @@ #include #include #include -#include void assert_equal( bool equal ) { if (!equal) diff --git a/ThirdParty/Ert/libert_utilxx/tests/CMakeLists.txt b/ThirdParty/Ert/libert_utilxx/tests/CMakeLists.txt index ce609df250..e9cd19572e 100644 --- a/ThirdParty/Ert/libert_utilxx/tests/CMakeLists.txt +++ b/ThirdParty/Ert/libert_utilxx/tests/CMakeLists.txt @@ -1,7 +1,7 @@ add_executable(ert_util_unique_ptr ert_util_unique_ptr.cpp ) -target_link_libraries(ert_util_unique_ptr test_util ert_util) +target_link_libraries(ert_util_unique_ptr ert_util) add_test(ert_util_unique_ptr ${EXECUTABLE_OUTPUT_PATH}/ert_util_unique_ptr) add_executable(ert_util_test_area_xx ert_util_test_area_xx.cpp ) -target_link_libraries(ert_util_test_area_xx test_util ert_utilxx) +target_link_libraries(ert_util_test_area_xx ert_utilxx) add_test(ert_util_test_area_xx ${EXECUTABLE_OUTPUT_PATH}/ert_util_test_area_xx) diff --git a/ThirdParty/Ert/libgeometry/src/geo_surface.c b/ThirdParty/Ert/libgeometry/src/geo_surface.c index c8f42c3136..7d9b443c77 100644 --- a/ThirdParty/Ert/libgeometry/src/geo_surface.c +++ b/ThirdParty/Ert/libgeometry/src/geo_surface.c @@ -60,31 +60,6 @@ static void geo_surface_copy_header( const geo_surface_type * src , geo_surface_ } } - -/* -static int geo_surface_cornerindex( const geo_surface_type * geo_surface , int cell_ix , int cell_iy) { - return (geo_surface->nx + 1) * cell_iy + cell_ix; -} - - -static void geo_surface_init_cells( geo_surface_type * geo_surface ) { - int ix,iy; - geo_surface->cells = util_malloc( geo_surface->nx * geo_surface->ny * sizeof * geo_surface->cells , __func__); - for (iy = 0; iy < geo_surface->ny; iy++) { - for (ix = 0; ix < geo_surface->nx; ix++) { - int cell_index = iy * geo_surface->nx + ix; - - geo_surface->cells[ cell_index ].index_list[0] = geo_surface_cornerindex( geo_surface , ix , iy ); - geo_surface->cells[ cell_index ].index_list[1] = geo_surface_cornerindex( geo_surface , ix + 1 , iy ); - geo_surface->cells[ cell_index ].index_list[2] = geo_surface_cornerindex( geo_surface , ix + 1 , iy + 1); - geo_surface->cells[ cell_index ].index_list[3] = geo_surface_cornerindex( geo_surface , ix , iy + 1); - - } - } -} -*/ - - static geo_surface_type * geo_surface_alloc_empty( bool internal_z ) { geo_surface_type * surface = util_malloc( sizeof * surface ); UTIL_TYPE_ID_INIT( surface , GEO_SURFACE_TYPE_ID ) @@ -116,28 +91,20 @@ static void geo_surface_init_regular( geo_surface_type * surface , const double static bool geo_surface_fscanf_zcoord( const geo_surface_type * surface , FILE * stream , double * zcoord) { - bool OK = false; int index = 0; while (true) { if (fscanf(stream , "%lg" , &zcoord[index]) == 1) index++; else - /* File is too short */ - break; + return false; // File is too short if (index == surface->nx * surface->ny) { double extra_value; int fscanf_return = fscanf( stream , "%lg" , &extra_value); - - /* Check that there is not more data dangling at the end of the file. */ - if (fscanf_return == EOF) - OK = true; - break; + return (fscanf_return == EOF); // no more data dangling at the end of the file. } } - - return OK; } diff --git a/ThirdParty/Ert/libgeometry/tests/CMakeLists.txt b/ThirdParty/Ert/libgeometry/tests/CMakeLists.txt index 9a39bd4e17..3547148055 100644 --- a/ThirdParty/Ert/libgeometry/tests/CMakeLists.txt +++ b/ThirdParty/Ert/libgeometry/tests/CMakeLists.txt @@ -1,18 +1,18 @@ add_executable( geo_util_xlines geo_util_xlines.c ) -target_link_libraries( geo_util_xlines ert_geometry test_util ) +target_link_libraries( geo_util_xlines ert_geometry ) add_test( geo_util_xlines ${EXECUTABLE_OUTPUT_PATH}/geo_util_xlines ) add_executable( geo_polygon geo_polygon.c ) -target_link_libraries( geo_polygon ert_geometry test_util ) +target_link_libraries( geo_polygon ert_geometry ) add_test( geo_polygon ${EXECUTABLE_OUTPUT_PATH}/geo_polygon ) add_executable( geo_polygon_collection geo_polygon_collection.c ) -target_link_libraries( geo_polygon_collection ert_geometry test_util ) +target_link_libraries( geo_polygon_collection ert_geometry ) add_test( geo_polygon_collection ${EXECUTABLE_OUTPUT_PATH}/geo_polygon_collection ) if (STATOIL_TESTDATA_ROOT) add_executable( geo_surface geo_surface.c ) - target_link_libraries( geo_surface ert_geometry test_util ) + target_link_libraries( geo_surface ert_geometry ) add_test( geo_surface ${EXECUTABLE_OUTPUT_PATH}/geo_surface ${PROJECT_SOURCE_DIR}/test-data/Statoil/Geometry/Surface.irap diff --git a/ThirdParty/Ert/libjob_queue/CMakeLists.txt b/ThirdParty/Ert/libjob_queue/CMakeLists.txt deleted file mode 100644 index 9ea4540853..0000000000 --- a/ThirdParty/Ert/libjob_queue/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -set( HAVE_LSF_LIBRARY OFF ) - -set( ERT_LSF_LIB_PATH "" CACHE FILEPATH "Path to search for the LSF libraries" ) -set( ERT_LSF_INCLUDE_PATH "" CACHE FILEPATH "Path to search for the LSF header files" ) - -find_path( LSF_HEADER_PATH lsf/lsf.h - PATHS ${ERT_LSF_INCLUDE_PATH}) - -find_library( LSF_LIBRARY NAMES lsf PATHS ${ERT_LSF_LIB_PATH}) - - - -if (LSF_HEADER_PATH) - if (LSF_LIBRARY) - set( HAVE_LSF_LIBRARY ON ) - endif() -endif() - - -if (HAVE_LSF_LIBRARY) - include_directories( ${LSF_HEADER_PATH} ) - add_definitions( -DHAVE_LSF_LIBRARY ) - message(STATUS "Found LSF as ${LSF_HEADER_PATH} and ${LSF_LIBRARY}") -else() - message(STATUS "LSF not found") -endif() - -add_subdirectory( src ) -if (BUILD_APPLICATIONS) - add_subdirectory( applications ) -endif() - -if (BUILD_TESTS) - add_subdirectory( tests ) -endif() - - diff --git a/ThirdParty/Ert/libjob_queue/applications/CMakeLists.txt b/ThirdParty/Ert/libjob_queue/applications/CMakeLists.txt deleted file mode 100644 index 94693ed1a1..0000000000 --- a/ThirdParty/Ert/libjob_queue/applications/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -if (HAVE_LSF_LIBRARY) - add_executable( block_node block_node.c ) - target_link_libraries( block_node job_queue ert_util) - if (USE_RUNPATH) - add_runpath( block_node ) - endif() - - install(TARGETS block_node DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -endif() diff --git a/ThirdParty/Ert/libjob_queue/applications/block_node.c b/ThirdParty/Ert/libjob_queue/applications/block_node.c deleted file mode 100644 index 21e5ebbb85..0000000000 --- a/ThirdParty/Ert/libjob_queue/applications/block_node.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'block_node.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#define BLOCK_COMMAND "/project/res/bin/block-job" -#define STATOIL_LSF_REQUEST "select[cs && x86_64Linux]" - - - -static lsf_driver_type * lsf_driver; -static vector_type * job_pool; -static hash_type * nodes; - - -typedef struct { - lsf_job_type * lsf_job; - stringlist_type * hostlist; - bool running; - bool block_job; -} block_job_type; - - -typedef struct { - int target; - int current; -} count_pair_type; - - -count_pair_type * count_pair_alloc() { - count_pair_type * pair = util_malloc( sizeof * pair ); - pair->target = 0; - pair->current = 0; - return pair; -} - - - - -block_job_type * block_job_alloc() { - block_job_type * job = util_malloc( sizeof * job ); - - job->lsf_job = NULL; - job->running = false; - job->block_job = false; - job->hostlist = stringlist_alloc_new(); - - return job; -} - - -void block_job_free( block_job_type * block_job ) { - stringlist_free( block_job->hostlist ); - if (block_job->lsf_job) - lsf_job_free( block_job->lsf_job ); - - free( block_job ); -} - - -const char * block_job_get_hostname( const block_job_type * block_job ) { - return stringlist_iget( block_job->hostlist , 0 ); -} - - - -void update_job_status( block_job_type * job ) { - if (!job->running) { - int lsf_status = lsf_driver_get_job_status_lsf( lsf_driver , job->lsf_job ); - if (lsf_status == JOB_STAT_RUN) { - lsf_job_export_hostnames( job->lsf_job , job->hostlist ); - { - int ihost; - for (ihost = 0; ihost < stringlist_get_size( job->hostlist ); ihost++) { - const char * host = stringlist_iget( job->hostlist , ihost ); - if (hash_has_key( nodes, host)) { /* This is one of the instances which should be left running. */ - count_pair_type * pair = hash_get( nodes , host); - if (pair->current < pair->target) { - pair->current += 1; - job->block_job = true; - } - } - } - } - job->running = true; - } - } -} - - - -/*****************************************************************/ - - - -void add_jobs( int chunk_size) { - int i; - char * cwd = util_alloc_cwd(); - for (i=0; i < chunk_size; i++) { - block_job_type * job = block_job_alloc(); - job->lsf_job = lsf_driver_submit_job(lsf_driver , BLOCK_COMMAND , 1 , cwd , "BLOCK" , 0 , NULL ); - vector_append_ref( job_pool , job ); - } - free( cwd ); -} - - -void update_pool_status( bool *all_blocked , int * pending) { - int i; - int pend_count = 0; - *all_blocked = true; - - for (i=0; i < vector_get_size( job_pool ); i++) { - block_job_type * job = vector_iget( job_pool , i ); - update_job_status( job ); - - if (!job->running) - pend_count++; - } - - { - hash_iter_type * iter = hash_iter_alloc( nodes ); - while (!hash_iter_is_complete( iter )) { - const char * hostname = hash_iter_get_next_key( iter ); - const count_pair_type * count = hash_get( nodes , hostname ); - if (count->current < count->target) - *all_blocked = false; - } - } - *pending = pend_count; -} - - -void print_status() { - int total_running = 0; - int total_pending = 0; - for (int i=0; i < vector_get_size( job_pool ); i++) { - block_job_type * job = vector_iget( job_pool , i ); - if (job->running) - total_running += 1; - else - total_pending += 1; - } - printf("Running:%3d Pending: %3d Blocks active: ",total_running , total_pending); - { - hash_iter_type * iter = hash_iter_alloc( nodes ); - while (!hash_iter_is_complete( iter )) { - const char * hostname = hash_iter_get_next_key( iter ); - const count_pair_type * count = hash_get( nodes , hostname ); - printf("%s %d/%d ",hostname , count->current , count->target); - } - printf("\n"); - hash_iter_free( iter ); - } -} - - -void block_node_exit( int signal ) { - int job_nr; - - print_status(); - for (job_nr = 0; job_nr < vector_get_size( job_pool ); job_nr++) { - block_job_type * job = vector_iget( job_pool , job_nr ); - - if (job->block_job) { - printf("Job:%ld is running on host: ", lsf_job_get_jobnr( job->lsf_job )); - stringlist_fprintf( job->hostlist , " " , stdout ); - printf("\n"); - } else - lsf_driver_kill_job( lsf_driver , job->lsf_job ); - - block_job_free( job ); - } - printf("Remember to kill these jobs when the BLOCK is no longer needed\n"); - if (signal != 0) - exit(0); -} - - -int main( int argc, char ** argv) { - if (argc == 1) - util_exit("block_node node1 node2 node3:2 \n"); - - /* Initialize lsf environment */ - util_setenv( "LSF_BINDIR" , "/prog/LSF/9.1/linux2.6-glibc2.3-x86_64/bin" ); - util_setenv( "LSF_LINDIR" , "/prog/LSF/9.1/linux2.6-glibc2.3-x86_64/lib" ); - util_setenv( "XLSF_UIDDIR" , "/prog/LSF/9.1/linux2.6-glibc2.3-x86_64/lib/uid" ); - util_setenv( "LSF_SERVERDIR" , "/prog/LSF/9.1/linux2.6-glibc2.3-x86_64/etc"); - util_setenv( "LSF_ENVDIR" , "/prog/LSF/conf"); - - util_update_path_var( "PATH" , "/prog/LSF/9.1/linux2.6-glibc2.3-x86_64/bin" , false); - util_update_path_var( "LD_LIBRARY_PATH" , "/prog/LSF/9.1/linux2.6-glibc2.3-x86_64/lib" , false); - - - lsf_driver = lsf_driver_alloc(); - if (lsf_driver_get_submit_method( lsf_driver ) != LSF_SUBMIT_INTERNAL) - util_exit("Sorry - the block_node program must be invoked on a proper LSF node \n"); - - { - - int iarg; - int total_blocked_target = 0; - nodes = hash_alloc(); - for (iarg = 1; iarg < argc; iarg++) { - char *node_name; - int num_slots; - - { - char * num_slots_string; - util_binary_split_string( argv[iarg] , ":" , true , &node_name , &num_slots_string); - if (num_slots_string) - util_sscanf_int( num_slots_string , &num_slots); - else - num_slots = 1; - } - - if (!hash_has_key( nodes , node_name)) - hash_insert_hash_owned_ref( nodes , node_name , count_pair_alloc() , free); - - { - count_pair_type * pair = hash_get( nodes , node_name); - pair->target += num_slots; - } - total_blocked_target += num_slots; - } - - signal(SIGINT , block_node_exit ); - { - const int sleep_time = 5; - const int chunk_size = 10; /* We submit this many at a time. */ - const int max_pool_size = 1000; /* The absolute total maximum of jobs we will submit. */ - - bool cont = true; - int pending = 0; - bool all_blocked; - job_pool = vector_alloc_new(); - - while (cont) { - printf("[Ctrl-C to give up] "); fflush( stdout ); - if (cont) sleep( sleep_time ); - if (pending == 0) { - if (vector_get_size( job_pool ) < max_pool_size) - add_jobs( chunk_size ); - } - - update_pool_status( &all_blocked , &pending); - print_status(); - - if (all_blocked) - cont = false; - } - if (!all_blocked) - printf("Sorry - failed to block all the nodes \n"); - - block_node_exit( 0 ); - hash_free( nodes ); - } - } -} diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/ext_job.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/ext_job.h deleted file mode 100644 index d8f79e6a02..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/ext_job.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ext_job.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_EXT_JOB_H -#define ERT_EXT_JOB_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include -#include - -typedef struct ext_job_struct ext_job_type; - - -const char * ext_job_get_help_text( const ext_job_type * job ); -void ext_job_set_help_text( ext_job_type * job , const char * help_text); - -void ext_job_fprintf_config(const ext_job_type * ext_job , const char * fmt , FILE * stream); -ext_job_type * ext_job_alloc_copy(const ext_job_type * ); -ext_job_type * ext_job_alloc(const char * , const char * license_root_path , bool private_job); - const char * ext_job_get_name(const ext_job_type * ); -void ext_job_free(ext_job_type * ) ; -void ext_job_free__(void * ); -void ext_job_add_environment(ext_job_type *, const char * , const char * ) ; -void ext_job_save( const ext_job_type * ext_job ); -void ext_job_fprintf(const ext_job_type * , FILE * stream ); -void ext_job_set_private_arg(ext_job_type * , const char * , const char * ); - -void ext_job_set_argc(ext_job_type * , const char ** , int); -void ext_job_python_fprintf(const ext_job_type * , FILE * , const subst_list_type *); -ext_job_type * ext_job_fscanf_alloc(const char * , const char * , bool private_job , const char *, bool search_path); -const stringlist_type * ext_job_get_arglist( const ext_job_type * ext_job ); -bool ext_job_is_shared( const ext_job_type * ext_job ); -bool ext_job_is_private( const ext_job_type * ext_job ); - -void ext_job_set_executable(ext_job_type * ext_job, const char * executable_abs, const char * executable_input, bool search_path); -const char * ext_job_get_executable(const ext_job_type * ext_job); - - - -void ext_job_set_config_file(ext_job_type * ext_job, const char * config_file); -const char * ext_job_get_config_file(const ext_job_type * ext_job); -void ext_job_set_target_file(ext_job_type * ext_job, const char * target_file); -const char * ext_job_get_target_file(const ext_job_type * ext_job); -void ext_job_set_start_file(ext_job_type * ext_job, const char * start_file); -const char * ext_job_get_start_file(const ext_job_type * ext_job); -void ext_job_set_name(ext_job_type * ext_job, const char * name); -const char * ext_job_get_name(const ext_job_type * ext_job); -void ext_job_set_lsf_request(ext_job_type * ext_job, const char * lsf_request); -const char * ext_job_get_lsf_request(const ext_job_type * ext_job); -void ext_job_set_stdin_file(ext_job_type * ext_job, const char * stdin_file); -const char * ext_job_get_stdin_file(const ext_job_type * ext_job); -void ext_job_set_stdout_file(ext_job_type * ext_job, const char * stdout_file); -const char * ext_job_get_stdout_file(const ext_job_type * ext_job); -void ext_job_set_stderr_file(ext_job_type * ext_job, const char * stderr_file); -const char * ext_job_get_stderr_file(const ext_job_type * ext_job); -void ext_job_set_max_running( ext_job_type * ext_job , int max_running); -int ext_job_get_max_running( const ext_job_type * ext_job ); -void ext_job_set_max_running_minutes( ext_job_type * ext_job , int max_running_minutes); -int ext_job_get_max_running_minutes( const ext_job_type * ext_job ); -void ext_job_add_environment(ext_job_type *ext_job , const char * key , const char * value); -void ext_job_clear_environment( ext_job_type * ext_job ); -hash_type * ext_job_get_environment( ext_job_type * ext_job ); -int ext_job_set_private_args_from_string( ext_job_type * ext_job , const char * arg_string ); -const char * ext_job_get_private_args_as_string( ext_job_type * ext_job ); -//const char * ext_job_get_arglist_as_string( ext_job_type * ext_job ); -//void ext_job_set_arglist_from_string( ext_job_type * ext_job , const char * argv_string ); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/ext_joblist.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/ext_joblist.h deleted file mode 100644 index eff19d8d6d..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/ext_joblist.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ext_joblist.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_EXT_JOBLIST_H -#define ERT_EXT_JOBLIST_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include -#include - -#include - - -typedef struct ext_joblist_struct ext_joblist_type; - -ext_joblist_type * ext_joblist_alloc(); -void ext_joblist_free(ext_joblist_type * ); -void ext_joblist_add_job(ext_joblist_type * joblist , const char * name , ext_job_type * new_job); -ext_job_type * ext_joblist_get_job(const ext_joblist_type * , const char * ); -ext_job_type * ext_joblist_get_job_copy(const ext_joblist_type * , const char * ); -//void ext_joblist_python_fprintf(const ext_joblist_type * , const stringlist_type * , const char * , const subst_list_type *); -bool ext_joblist_has_job(const ext_joblist_type * , const char * ); -stringlist_type * ext_joblist_alloc_list( const ext_joblist_type * joblist); -bool ext_joblist_del_job( ext_joblist_type * joblist , const char * job_name ); -void ext_joblist_add_jobs_in_directory(ext_joblist_type * joblist , const char * path, const char * license_root_path, bool user_mode, bool search_path ); -int ext_joblist_get_size( const ext_joblist_type * joblist ); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/forward_model.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/forward_model.h deleted file mode 100644 index 6068e64cd1..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/forward_model.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'forward_model.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_FORWARD_MODEL_H -#define ERT_FORWARD_MODEL_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include - -#include - -typedef struct forward_model_struct forward_model_type ; - - - stringlist_type * forward_model_alloc_joblist( const forward_model_type * forward_model ); - const ext_joblist_type * forward_model_get_joblist(const forward_model_type * ); - void forward_model_clear( forward_model_type * forward_model ); - void forward_model_fprintf(const forward_model_type * , FILE * ); - forward_model_type * forward_model_alloc(const ext_joblist_type * ext_joblist); - void forward_model_parse_init(forward_model_type * forward_model , const char * input_string ); - void forward_model_python_fprintf(const forward_model_type * , const char * , const subst_list_type * , mode_t umask); - void forward_model_free( forward_model_type * ); - forward_model_type * forward_model_alloc_copy(const forward_model_type * forward_model); - void forward_model_iset_job_arg( forward_model_type * forward_model , int job_index , const char * arg , const char * value); - ext_job_type * forward_model_iget_job( forward_model_type * forward_model , int index); - int forward_model_get_length( const forward_model_type * forward_model ); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_list.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_list.h deleted file mode 100644 index 8193e7a50c..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_list.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'job_node.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_JOB_LIST_H -#define ERT_JOB_LIST_H - - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include - - -typedef struct job_list_struct job_list_type; - - job_list_type * job_list_alloc(); - void job_list_free( job_list_type * job_list ); - int job_list_get_size( const job_list_type * job_list ); - void job_list_add_job( job_list_type * job_list , job_queue_node_type * job_node ); - job_queue_node_type * job_list_iget_job( const job_list_type * job_list , int queue_index); - void job_list_reset( job_list_type * job_list ); - void job_list_get_wrlock( job_list_type * list); - void job_list_get_rdlock( job_list_type * list); - void job_list_reader_wait( job_list_type * list, int usleep_time1, int usleep_time2); - void job_list_unlock( job_list_type * list); - - UTIL_SAFE_CAST_HEADER( job_list ); - UTIL_IS_INSTANCE_HEADER( job_list ); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_node.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_node.h deleted file mode 100644 index b657bba84b..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_node.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'job_node.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_JOB_NODE_H -#define ERT_JOB_NODE_H - - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -/** - This struct holds the job_queue information about one job. Observe - the following: - - 1. This struct is purely static - i.e. it is invisible outside of - this file-scope. - - 2. Typically the driver would like to store some additional - information, i.e. the PID of the running process for the local - driver; that is stored in a (driver specific) struct under the - field job_data. - - 3. If the driver detects that a job has failed it leaves an EXIT - file, the exit status is (currently) not reliably transferred - back to to the job_queue layer. - -*/ - -typedef bool (job_callback_ftype) (void *); -typedef struct job_queue_node_struct job_queue_node_type; - - - bool job_queue_node_status_transition( job_queue_node_type * node , job_queue_status_type * status , job_status_type new_status); - bool job_queue_node_status_confirmed_running(job_queue_node_type * node); - submit_status_type job_queue_node_submit( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver); - void job_queue_node_free_error_info( job_queue_node_type * node ); - void job_queue_node_fscanf_EXIT( job_queue_node_type * node ); - void job_queue_node_clear_error_info(job_queue_node_type * node); - void job_queue_node_clear(job_queue_node_type * node); - void job_queue_node_free_data(job_queue_node_type * node); - job_queue_node_type * job_queue_node_alloc( const char * job_name , - const char * run_path , - const char * run_cmd , - int argc , - const char ** argv , - int num_cpu , - const char * ok_file, - const char * status_file, - const char * exit_file, - job_callback_ftype * done_callback, - job_callback_ftype * retry_callback, - job_callback_ftype * exit_callback, - void * callback_arg); - - - job_queue_node_type * job_queue_node_alloc_simple( const char * job_name , - const char * run_path , - const char * run_cmd , - int argc , - const char ** argv ); - - bool job_queue_node_kill( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver); - void job_queue_node_free(job_queue_node_type * node); - job_status_type job_queue_node_get_status(const job_queue_node_type * node); - void job_queue_node_free_driver_data( job_queue_node_type * node , queue_driver_type * driver); - void job_queue_node_restart( job_queue_node_type * node , job_queue_status_type * status); - bool job_queue_node_update_status( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver); - - const char * job_queue_node_get_run_path( const job_queue_node_type * node); - const char * job_queue_node_get_name( const job_queue_node_type * node); - int job_queue_node_get_submit_attempt( const job_queue_node_type * node); - void job_queue_node_reset_submit_attempt( job_queue_node_type * node); - const char * job_queue_node_get_failed_job( const job_queue_node_type * node); - const char * job_queue_node_get_error_reason( const job_queue_node_type * node); - const char * job_queue_node_get_stderr_capture( const job_queue_node_type * node); - const char * job_queue_node_get_stderr_file( const job_queue_node_type * node); - - time_t job_queue_node_get_sim_start( const job_queue_node_type * node ); - time_t job_queue_node_get_sim_end( const job_queue_node_type * node ); - time_t job_queue_node_get_submit_time( const job_queue_node_type * node ); - double job_queue_node_time_since_sim_start( const job_queue_node_type * node ) ; - void job_queue_node_set_max_confirmation_wait_time( job_queue_node_type * node, time_t time ); - - const char * job_queue_node_get_ok_file( const job_queue_node_type * node); - const char * job_queue_node_get_status_file( const job_queue_node_type * node); - const char * job_queue_node_get_exit_file( const job_queue_node_type * node); - - bool job_queue_node_run_DONE_callback( job_queue_node_type * node ); - bool job_queue_node_run_RETRY_callback( job_queue_node_type * node ); - void job_queue_node_run_EXIT_callback( job_queue_node_type * node ); - int job_queue_node_get_queue_index( const job_queue_node_type * node ); - void job_queue_node_set_queue_index( job_queue_node_type * node , int queue_index); - - void * job_queue_node_get_driver_data( job_queue_node_type * node ); - - UTIL_IS_INSTANCE_HEADER( job_queue_node ); - UTIL_SAFE_CAST_HEADER( job_queue_node ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue.h deleted file mode 100644 index 48d2df4179..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'job_queue.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_JOB_QUEUE_H -#define ERT_JOB_QUEUE_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -#include - -#include -#include - - - typedef struct job_queue_struct job_queue_type; - - - void job_queue_submit_complete( job_queue_type * queue ); - job_driver_type job_queue_get_driver_type( const job_queue_type * queue ); - void job_queue_set_driver(job_queue_type * queue , queue_driver_type * driver); - bool job_queue_has_driver(const job_queue_type * queue ); - //void job_queue_set_size( job_queue_type * job_queue , int size ); - void job_queue_set_runpath_fmt(job_queue_type * , const path_fmt_type * ); - job_queue_type * job_queue_alloc( int , const char * ok_file , const char * status_file, const char * exit_file); - void job_queue_free(job_queue_type *); - - int job_queue_add_job(job_queue_type * , - const char * run_cmd , - job_callback_ftype * done_callback, - job_callback_ftype * retry_callback, - job_callback_ftype * exit_callback, - void * callback_arg , - int num_cpu , - const char * , - const char * , - int argc , - const char ** argv ); - - bool job_queue_accept_jobs(const job_queue_type * queue); - void job_queue_reset(job_queue_type * queue); - void job_queue_run_jobs(job_queue_type * queue, int num_total_run, bool verbose); - void job_queue_run_jobs_threaded(job_queue_type * queue , int num_total_run, bool verbose); - void * job_queue_run_jobs__(void * ); - void job_queue_start_manager_thread( job_queue_type * job_queue , pthread_t * queue_thread , int job_size , bool verbose); - - job_status_type job_queue_iget_job_status(job_queue_type * , int ); - - int job_queue_iget_status_summary( const job_queue_type * queue , job_status_type status); - time_t job_queue_iget_sim_start( job_queue_type * queue, int job_index); - time_t job_queue_iget_sim_end( job_queue_type * queue, int job_index); - time_t job_queue_iget_submit_time( job_queue_type * queue, int job_index); - void job_queue_iset_max_confirm_wait_time( job_queue_type * queue, int job_index, time_t time ); - - void job_queue_set_max_job_duration(job_queue_type * queue, int max_duration_seconds); - int job_queue_get_max_job_duration(const job_queue_type * queue); - void job_queue_set_job_stop_time(job_queue_type * queue, time_t time); - time_t job_queue_get_job_stop_time(const job_queue_type * queue); - void job_queue_set_auto_job_stop_time(job_queue_type * queue); - bool job_queue_kill_job( job_queue_type * queue , int job_index); - bool job_queue_is_running( const job_queue_type * queue ); - void job_queue_set_max_submit( job_queue_type * job_queue , int max_submit ); - int job_queue_get_max_submit(const job_queue_type * job_queue ); - bool job_queue_get_open(const job_queue_type * job_queue); - bool job_queue_get_pause( const job_queue_type * job_queue ); - void job_queue_set_pause_on( job_queue_type * job_queue); - void job_queue_set_pause_off( job_queue_type * job_queue); - bool job_queue_start_user_exit( job_queue_type * queue); - bool job_queue_get_user_exit( const job_queue_type * queue); - void * job_queue_iget_job_data( job_queue_type * job_queue , int job_nr ); - - int job_queue_get_active_size( const job_queue_type * queue ); - int job_queue_get_num_callback( const job_queue_type * queue); - int job_queue_get_num_running( const job_queue_type * queue); - int job_queue_get_num_pending( const job_queue_type * queue); - int job_queue_get_num_waiting( const job_queue_type * queue); - int job_queue_get_num_complete( const job_queue_type * queue); - int job_queue_get_num_failed( const job_queue_type * queue); - int job_queue_get_num_killed( const job_queue_type * queue); - void * job_queue_iget_driver_data( job_queue_type * queue , int job_index); - const char * job_queue_iget_failed_job( job_queue_type * queue , int job_index); - const char * job_queue_iget_error_reason( job_queue_type * queue , int job_index); - const char * job_queue_iget_stderr_capture( job_queue_type * queue , int job_index); - const char * job_queue_iget_stderr_file( job_queue_type * queue , int job_index); - const char * job_queue_iget_run_path( job_queue_type * queue , int job_index); - void job_queue_iset_external_restart(job_queue_type * queue , int job_index); - job_queue_node_type * job_queue_iget_job( job_queue_type * job_queue , int job_nr ); - bool job_queue_has_driver(const job_queue_type * queue ); - job_queue_node_type * job_queue_iget_node(job_queue_type * queue , int job_index); - int job_queue_get_max_running( const job_queue_type * queue ); - - UTIL_SAFE_CAST_HEADER( job_queue ); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue_manager.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue_manager.h deleted file mode 100644 index eb2ee80be1..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue_manager.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'job_queue.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_JOB_QUEUE_MANAGER_H -#define ERT_JOB_QUEUE_MANAGER_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -typedef struct job_queue_manager_struct job_queue_manager_type; - - job_queue_manager_type * job_queue_manager_alloc( job_queue_type * job_queue ); - void job_queue_manager_free( job_queue_manager_type * manager ); - void job_queue_manager_start_queue( job_queue_manager_type * manager , int num_total_run , bool verbose , bool reset_queue); - bool job_queue_manager_try_wait( job_queue_manager_type * manager , int timeout_seconds); - void job_queue_manager_wait( job_queue_manager_type * manager); - int job_queue_manager_get_num_running( const job_queue_manager_type * manager); - int job_queue_manager_get_num_success( const job_queue_manager_type * manager); - int job_queue_manager_get_num_waiting( const job_queue_manager_type * manager); - int job_queue_manager_get_num_failed( const job_queue_manager_type * manager); - bool job_queue_manager_is_running( const job_queue_manager_type * manager); - - bool job_queue_manager_job_success( const job_queue_manager_type * manager , int job_index); - bool job_queue_manager_job_complete( const job_queue_manager_type * manager , int job_index); - bool job_queue_manager_job_waiting( const job_queue_manager_type * manager , int job_index); - bool job_queue_manager_job_running( const job_queue_manager_type * manager , int job_index); - bool job_queue_manager_job_failed( const job_queue_manager_type * manager , int job_index); - - job_status_type job_queue_manager_iget_job_status(const job_queue_manager_type * manager, int job_index); - - UTIL_IS_INSTANCE_HEADER( job_queue_manager ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue_status.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue_status.h deleted file mode 100644 index f962a58082..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/job_queue_status.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'job_status_test.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_JOB_QUEUE_STATUS_H -#define ERT_JOB_QUEUE_STATUS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - - typedef struct job_queue_status_struct job_queue_status_type; - - job_queue_status_type * job_queue_status_alloc(); - void job_queue_status_free( job_queue_status_type * status ); - int job_queue_status_get_count( job_queue_status_type * status , job_status_type status_type); - void job_queue_status_clear( job_queue_status_type * status ); - void job_queue_status_inc( job_queue_status_type * status_count , job_status_type status_type); - bool job_queue_status_transition( job_queue_status_type * status_count , job_status_type src_status , job_status_type target_status); - int job_queue_status_get_total_count( const job_queue_status_type * status ); - - UTIL_IS_INSTANCE_HEADER( job_queue_status ); - UTIL_SAFE_CAST_HEADER( job_queue_status ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/local_driver.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/local_driver.h deleted file mode 100644 index ca178097f8..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/local_driver.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_driver.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_LOCAL_DRIVER_H -#define ERT_LOCAL_DRIVER_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - - typedef struct local_driver_struct local_driver_type; - typedef struct local_job_struct local_job_type; - - - void * local_driver_alloc(); - - - void * local_driver_submit_job(void * __driver , - const char * submit_cmd , - int num_cpu , - const char * run_path , - const char * job_name , - int argc, - const char ** argv ); - void local_driver_kill_job(void * __driver , void * __job); - void local_driver_free__(void * __driver ); - job_status_type local_driver_get_job_status(void * __driver , void * __job); - void local_driver_free_job(void * __job); - void local_driver_init_option_list(stringlist_type * option_list); - - - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsb.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsb.h deleted file mode 100644 index be5d70509e..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsb.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'lsb.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - -#ifndef ERT_LSB_H -#define ERT_LSB_H - - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -#include - - typedef struct lsb_struct lsb_type; - - - lsb_type * lsb_alloc(); - void lsb_free( lsb_type * lsb); - bool lsb_ready( const lsb_type * lsb); - - int lsb_initialize( const lsb_type * lsb); - int lsb_submitjob( const lsb_type * lsb , struct submit * , struct submitReply *); - int lsb_killjob( const lsb_type * lsb , int lsf_jobnr); - int lsb_openjob( const lsb_type * lsb , int lsf_jobnr); - struct jobInfoEnt * lsb_readjob( const lsb_type * lsb ); - int lsb_closejob( const lsb_type * lsb ); - char * lsb_sys_msg( const lsb_type * lsb ); - stringlist_type * lsb_get_error_list( const lsb_type * lsb ); - - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsf_driver.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsf_driver.h deleted file mode 100644 index 6313ab1851..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsf_driver.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'lsf_driver.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_LSF_DRIVER_H -#define ERT_LSF_DRIVER_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include - - -/* - The options supported by the LSF driver. -*/ -#define LSF_QUEUE "LSF_QUEUE" -#define LSF_RESOURCE "LSF_RESOURCE" -#define LSF_SERVER "LSF_SERVER" -#define LSF_RSH_CMD "LSF_RSH_CMD" // This option is set to DEFAULT_RSH_CMD at driver creation. -#define LSF_LOGIN_SHELL "LSF_LOGIN_SHELL" // Not fully implemented yet -#define LSF_BSUB_CMD "BSUB_CMD" -#define LSF_BJOBS_CMD "BJOBS_CMD" -#define LSF_BKILL_CMD "BKILL_CMD" -#define LSF_BHIST_CMD "BHIST_CMD" -#define LSF_BJOBS_TIMEOUT "BJOBS_TIMEOUT" -#define LSF_DEBUG_OUTPUT "DEBUG_OUTPUT" -#define LSF_SUBMIT_SLEEP "SUBMIT_SLEEP" -#define LSF_EXCLUDE_HOST "EXCLUDE_HOST" - -#define LOCAL_LSF_SERVER "LOCAL" -#define NULL_LSF_SERVER "NULL" -#define DEFAULT_SUBMIT_SLEEP "0" - - typedef enum { - LSF_SUBMIT_INVALID = 0, - LSF_SUBMIT_INTERNAL = 1, - LSF_SUBMIT_LOCAL_SHELL = 2, - LSF_SUBMIT_REMOTE_SHELL = 3 - } lsf_submit_method_enum; - - -typedef struct lsf_driver_struct lsf_driver_type; -typedef struct lsf_job_struct lsf_job_type; - - void lsf_job_export_hostnames( const lsf_job_type * job , stringlist_type * hostlist); - void lsf_job_free(lsf_job_type * job); - long lsf_job_get_jobnr( const lsf_job_type * job ); - - void * lsf_driver_alloc( ); - stringlist_type * lsf_driver_alloc_cmd(lsf_driver_type * driver , - const char * run_path , - const char * job_name , - const char * submit_cmd , - int num_cpu , - int job_argc, - const char ** job_argv); - - void * lsf_driver_submit_job(void * __driver , - const char * submit_cmd , - int num_cpu , - const char * run_path , - const char * job_name , - int argc, - const char ** argv ); - job_status_type lsf_driver_convert_status( int lsf_status ); - void lsf_driver_blacklist_node(void * __driver , void * __job ); - void lsf_driver_kill_job(void * __driver , void * __job ); - void lsf_driver_free__(void * __driver ); - void lsf_driver_free( lsf_driver_type * driver ); - job_status_type lsf_driver_get_job_status(void * __driver , void * __job); - int lsf_driver_get_job_status_lsf(void * __driver , void * __job); - void lsf_driver_free_job(void * __job); - void lsf_driver_display_info( void * __driver , void * __job); - void lsf_driver_set_bjobs_refresh_interval( lsf_driver_type * driver , int refresh_interval); - - void lsf_driver_add_exclude_hosts( lsf_driver_type * driver , const char * excluded); - lsf_submit_method_enum lsf_driver_get_submit_method( const lsf_driver_type * driver ); - - bool lsf_driver_has_option( const void * __driver , const char * option_key); - const void * lsf_driver_get_option( const void * __driver , const char * option_key); - bool lsf_driver_set_option( void * __driver , const char * option_key , const void * value); - void lsf_driver_init_option_list(stringlist_type * option_list); - int lsf_job_parse_bsub_stdout(const char * bsub_cmd, const char * stdout_file); - char * lsf_job_write_bjobs_to_file(const char * bjobs_cmd, lsf_driver_type * driver, const long jobid); - - stringlist_type * lsf_job_alloc_parse_hostnames(const char* fname); - UTIL_SAFE_CAST_HEADER( lsf_driver ); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsf_job_stat.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsf_job_stat.h deleted file mode 100644 index c6c9ed3725..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/lsf_job_stat.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'lsf_driver.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifdef HAVE_LSF_LIBRARY -#include -#else -#define JOB_STAT_NULL 0 -#define JOB_STAT_PEND 1 -#define JOB_STAT_SSUSP 0x08 -#define JOB_STAT_USUSP 0x10 -#define JOB_STAT_PSUSP 0x02 -#define JOB_STAT_RUN 0x04 -#define JOB_STAT_EXIT 0x20 -#define JOB_STAT_DONE 0x40 -#define JOB_STAT_PDONE 0x80 -#define JOB_STAT_UNKWN 0x10000 -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/queue_driver.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/queue_driver.h deleted file mode 100644 index e03c66da68..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/queue_driver.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'queue_driver.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ - -#ifndef ERT_QUEUE_DRIVER_H -#define ERT_QUEUE_DRIVER_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - - typedef enum { - NULL_DRIVER = 0, - LSF_DRIVER = 1, - LOCAL_DRIVER = 2, - RSH_DRIVER = 3, - TORQUE_DRIVER = 4 - } job_driver_type; - -#define JOB_DRIVER_ENUM_DEFS \ -{.value = 0 , .name = "NULL_DRIVER"}, \ -{.value = 1 , .name = "LSF_DRIVER"}, \ -{.value = 2 , .name = "LOCAL_DRIVER"}, \ -{.value = 3 , .name = "RSH_DRIVER"}, \ -{.value = 4 , .name = "TORQUE_DRIVER"} - -#define JOB_DRIVER_ENUM_SIZE 5 - - /* - The options supported by the base queue_driver. - */ -#define MAX_RUNNING "MAX_RUNNING" - - - typedef enum { - JOB_QUEUE_NOT_ACTIVE = 1, /* This value is used in external query routines - for jobs which are (currently) not active. */ - //JOB_QUEUE_LOADING = 2, /* This value is used by external routines. Not used in the libjob_queue implementation. */ - JOB_QUEUE_WAITING = 4, /* A node which is waiting in the internal queue. */ - JOB_QUEUE_SUBMITTED = 8, /* Internal status: It has has been submitted - the next status update will (should) place it as pending or running. */ - JOB_QUEUE_PENDING = 16, /* A node which is pending - a status returned by the external system. I.e LSF */ - JOB_QUEUE_RUNNING = 32, /* The job is running */ - JOB_QUEUE_DONE = 64, /* The job is done - but we have not yet checked if the target file is produced */ - JOB_QUEUE_EXIT = 128, /* The job has exited - check attempts to determine if we retry or go to complete_fail */ - //JOB_QUEUE_RUN_OK = 256, /* The job has completed - and all checks performed by the queue layer indicate success. */ - //JOB_QUEUE_RUN_FAIL = 512, /* The job has completed - but the queue system has detected that it has failed. */ - //JOB_QUEUE_ALL_OK = 1024, /* The job has loaded OK - observe that it is the calling scope which will set the status to this. */ - //JOB_QUEUE_ALL_FAIL = 2048, /* The job has failed completely - the calling scope must set this status. */ - JOB_QUEUE_IS_KILLED = 4096, /* The job has been killed, following a JOB_QUEUE_DO_KILL*/ - JOB_QUEUE_DO_KILL = 8192, /* The the job should be killed, either due to user request, or automated measures - the job can NOT be restarted. */ - JOB_QUEUE_SUCCESS = 16384, - JOB_QUEUE_RUNNING_CALLBACK = 32768, - JOB_QUEUE_FAILED = 65536, - JOB_QUEUE_DO_KILL_NODE_FAILURE = 131072, /* LSF will attempt to blacklist the nodes that failed this job */ - JOB_QUEUE_STATUS_FAILURE = 262144 /* The command to get job_status has failed - let the status remain unchanged. */ - } job_status_type; - -#define JOB_QUEUE_MAX_STATE 14 - - /* - All jobs which are in the status set defined by - JOB_QUEUE_CAN_RESTART can be restarted based on external - user-input. It is OK to try to restart a job which is not in this - state - basically nothing should happen. - */ -#define JOB_QUEUE_CAN_RESTART (JOB_QUEUE_FAILED + JOB_QUEUE_IS_KILLED + JOB_QUEUE_SUCCESS) - - - /* - These are the jobs which can be killed. It is OK to try to kill a - job which is not in this state, the only thing happening is that the - function job_queue_kill_simulation() wil return false. - */ -#define JOB_QUEUE_CAN_KILL (JOB_QUEUE_WAITING + JOB_QUEUE_RUNNING + JOB_QUEUE_PENDING + JOB_QUEUE_SUBMITTED + JOB_QUEUE_DO_KILL + JOB_QUEUE_DO_KILL_NODE_FAILURE) - -#define JOB_QUEUE_WAITING_STATUS (JOB_QUEUE_WAITING + JOB_QUEUE_PENDING) - -#define JOB_QUEUE_CAN_UPDATE_STATUS (JOB_QUEUE_RUNNING + JOB_QUEUE_PENDING + JOB_QUEUE_SUBMITTED) - -#define JOB_QUEUE_COMPLETE_STATUS (JOB_QUEUE_IS_KILLED + JOB_QUEUE_SUCCESS + JOB_QUEUE_FAILED) - - - typedef struct queue_driver_struct queue_driver_type; - - typedef void * (submit_job_ftype) (void * data, const char * cmd, int num_cpu, const char * run_path, const char * job_name, int argc, const char ** argv); - typedef void (blacklist_node_ftype) (void *, void *); - typedef void (kill_job_ftype) (void *, void *); - typedef job_status_type(get_status_ftype) (void *, void *); - typedef void (free_job_ftype) (void *); - typedef void (free_queue_driver_ftype) (void *); - typedef bool (set_option_ftype) (void *, const char*, const void *); - typedef const void * (get_option_ftype) (const void *, const char *); - typedef bool (has_option_ftype) (const void *, const char *); - typedef void (init_option_list_ftype) (stringlist_type *); - - - queue_driver_type * queue_driver_alloc_RSH(const char * rsh_cmd, const hash_type * rsh_hostlist); - queue_driver_type * queue_driver_alloc_LSF(const char * queue_name, const char * resource_request, const char * remote_lsf_server); - queue_driver_type * queue_driver_alloc_TORQUE(); - queue_driver_type * queue_driver_alloc_local(); - queue_driver_type * queue_driver_alloc(job_driver_type type); - - void * queue_driver_submit_job(queue_driver_type * driver, const char * run_cmd, int num_cpu, const char * run_path, const char * job_name, int argc, const char ** argv); - void queue_driver_free_job(queue_driver_type * driver, void * job_data); - void queue_driver_blacklist_node(queue_driver_type * driver, void * job_data); - void queue_driver_kill_job(queue_driver_type * driver, void * job_data); - job_status_type queue_driver_get_status(queue_driver_type * driver, void * job_data); - - const char * queue_driver_get_name(const queue_driver_type * driver); - - bool queue_driver_set_option(queue_driver_type * driver, const char * option_key, const void * value); - const void * queue_driver_get_option(queue_driver_type * driver, const char * option_key); - void queue_driver_init_option_list(queue_driver_type * driver, stringlist_type * option_list); - - void queue_driver_free(queue_driver_type * driver); - void queue_driver_free__(void * driver); - const char * queue_driver_type_enum_iget(int index, int * value); - - typedef enum {SUBMIT_OK = 0 , - SUBMIT_JOB_FAIL = 1 , /* Typically no more attempts. */ - SUBMIT_DRIVER_FAIL = 2 , /* The driver would not take the job - for whatever reason?? */ - SUBMIT_QUEUE_CLOSED = 3 } /* The queue is currently not accepting more jobs - either (temporarilty) - because of pause or it is going down. */ submit_status_type; - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/rsh_driver.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/rsh_driver.h deleted file mode 100644 index 2f9f7d9669..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/rsh_driver.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rsh_driver.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RSH_DRIVER_H -#define ERT_RSH_DRIVER_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#define RSH_HOST "RSH_HOST" -#define RSH_HOSTLIST "RSH_HOSTLIST" -#define RSH_CMD "RSH_CMD" -#define RSH_CLEAR_HOSTLIST "RSH_CLEAR_HOSTLIST" - - typedef struct rsh_driver_struct rsh_driver_type; - typedef struct rsh_job_struct rsh_job_type; - - void rsh_driver_add_host(rsh_driver_type * , const char * , int ); - void * rsh_driver_alloc( ); - - void * rsh_driver_submit_job(void * __driver , - const char * submit_cmd , - int num_cpu , - const char * run_path , - const char * job_name , - int argc, - const char ** argv ); - void rsh_driver_kill_job(void * __driver , void * __job); - void rsh_driver_free__(void * __driver ); - job_status_type rsh_driver_get_job_status(void * __driver , void * __job); - void rsh_driver_free_job(void * __job); - - - bool rsh_driver_set_option( void * __driver, const char * option_key , const void * value ); - const void * rsh_driver_get_option( const void * __driver , const char * option_key); - void rsh_driver_init_option_list(stringlist_type * option_list); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/torque_driver.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/torque_driver.h deleted file mode 100644 index e18c7df8e5..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/torque_driver.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'torque_driver.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ -#ifndef TORQUE_DRIVER_H -#define TORQUE_DRIVER_H - -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include - - /* - The options supported by the Torque driver. - */ -#define TORQUE_QSUB_CMD "QSUB_CMD" -#define TORQUE_QSTAT_CMD "QSTAT_CMD" -#define TORQUE_QDEL_CMD "QDEL_CMD" -#define TORQUE_QUEUE "QUEUE" -#define TORQUE_NUM_CPUS_PER_NODE "NUM_CPUS_PER_NODE" -#define TORQUE_NUM_NODES "NUM_NODES" -#define TORQUE_KEEP_QSUB_OUTPUT "KEEP_QSUB_OUTPUT" -#define TORQUE_CLUSTER_LABEL "CLUSTER_LABEL" -#define TORQUE_JOB_PREFIX_KEY "JOB_PREFIX" -#define TORQUE_SUBMIT_SLEEP "SUBMIT_SLEEP" -#define TORQUE_DEBUG_OUTPUT "DEBUG_OUTPUT" - -#define TORQUE_DEFAULT_QSUB_CMD "qsub" -#define TORQUE_DEFAULT_QSTAT_CMD "qstat" -#define TORQUE_DEFAULT_QDEL_CMD "qdel" -#define TORQUE_DEFAULT_SUBMIT_SLEEP "0" - - - typedef struct torque_driver_struct torque_driver_type; - typedef struct torque_job_struct torque_job_type; - - - void * torque_driver_alloc(); - - - void * torque_driver_submit_job(void * __driver, - const char * submit_cmd, - int num_cpu, - const char * run_path, - const char * job_name, - int argc, - const char ** argv); - - void torque_driver_kill_job(void * __driver, void * __job); - void torque_driver_free__(void * __driver); - void torque_driver_free(torque_driver_type * driver); - job_status_type torque_driver_get_job_status(void * __driver, void * __job); - void torque_driver_free_job(void * __job); - void torque_driver_set_qstat_refresh_interval(torque_driver_type * driver, int refresh_interval); - - const void * torque_driver_get_option(const void * __driver, const char * option_key); - bool torque_driver_set_option(void * __driver, const char * option_key, const void * value); - void torque_driver_init_option_list(stringlist_type * option_list); - - void torque_job_create_submit_script(const char * run_path, const char * submit_cmd, int argc, const char ** job_argv); - int torque_driver_get_submit_sleep( const torque_driver_type * driver ); - FILE * torque_driver_get_debug_stream( const torque_driver_type * driver ); - - - UTIL_SAFE_CAST_HEADER(torque_driver); - -#ifdef __cplusplus -} -#endif - -#endif /* TORQUE_DRIVER_H */ - diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow.h deleted file mode 100644 index f6b3f7eb98..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'workflow.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_WORKFLOW_H -#define ERT_WORKFLOW_H - - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -#include -#include - - typedef struct workflow_struct workflow_type; - - const config_error_type * workflow_get_last_error( const workflow_type * workflow); - workflow_type * workflow_alloc( const char * src_file , workflow_joblist_type * joblist); - bool workflow_run( workflow_type * workflow, void * self , bool verbose , const subst_list_type * context); - void workflow_free( workflow_type * workflow ); - void workflow_free__( void * arg ); - - int workflow_get_stack_size( const workflow_type * workflow ); - void * workflow_iget_stack_ptr( const workflow_type * workflow , int index); - void * workflow_pop_stack( workflow_type * workflow ); - - int workflow_size( const workflow_type * workflow); - const workflow_job_type * workflow_iget_job( const workflow_type * workflow, int index); - stringlist_type * workflow_iget_arguments( const workflow_type * workflow, int index); - bool workflow_try_compile( workflow_type * script , const subst_list_type * context); - UTIL_IS_INSTANCE_HEADER( workflow ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow_job.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow_job.h deleted file mode 100644 index 6168beb2d0..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow_job.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'workflow_job.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_WORKFLOW_JOB_H -#define ERT_WORKFLOW_JOB_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - - - typedef void * (workflow_job_ftype) (void * self , const stringlist_type * arg ); - typedef struct workflow_job_struct workflow_job_type; - - const char * workflow_job_get_name( const workflow_job_type * workflow_job ); - bool workflow_job_internal( const workflow_job_type * workflow_job ); - config_parser_type * workflow_job_alloc_config(); - workflow_job_type * workflow_job_alloc(const char * name , bool internal); - void workflow_job_free( workflow_job_type * workflow_job ); - void workflow_job_free__( void * arg); - void workflow_job_set_executable( workflow_job_type * workflow_job , const char * executable ); - workflow_job_type * workflow_job_config_alloc( const char * name , config_parser_type * config , const char * config_file); - - void workflow_job_update_config_compiler( const workflow_job_type * workflow_job , config_parser_type * config_compiler ); - void workflow_job_set_executable( workflow_job_type * workflow_job , const char * executable); - char * workflow_job_get_executable( workflow_job_type * workflow_job); - - void workflow_job_set_internal_script( workflow_job_type * workflow_job , const char * script_path); - char* workflow_job_get_internal_script_path( const workflow_job_type * workflow_job); - bool workflow_job_is_internal_script( const workflow_job_type * workflow_job); - - void workflow_job_set_function( workflow_job_type * workflow_job , const char * function); - char * workflow_job_get_function( workflow_job_type * workflow_job); - void workflow_job_set_module( workflow_job_type * workflow_job , const char * module); - char * workflow_job_get_module( workflow_job_type * workflow_job); - void * workflow_job_run( const workflow_job_type * job, void * self , bool verbose , const stringlist_type * arg); - - int workflow_job_get_min_arg( const workflow_job_type * workflow_job ); - int workflow_job_get_max_arg( const workflow_job_type * workflow_job ); - config_item_types workflow_job_iget_argtype( const workflow_job_type * workflow_job, int index); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow_joblist.h b/ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow_joblist.h deleted file mode 100644 index e8d37af18e..0000000000 --- a/ThirdParty/Ert/libjob_queue/include/ert/job_queue/workflow_joblist.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'workflow_joblist.h' is part of ERT - Ensemble based - Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - - - -#ifndef ERT_WORKFLOW_JOBLIST_H -#define ERT_WORKFLOW_JOBLIST_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -typedef struct workflow_joblist_struct workflow_joblist_type; - - workflow_joblist_type * workflow_joblist_alloc(); - void workflow_joblist_free( workflow_joblist_type * joblist); - const workflow_job_type * workflow_joblist_get_job( const workflow_joblist_type * joblist , const char * job_name); - void workflow_joblist_add_job( workflow_joblist_type * joblist , const workflow_job_type * job); - bool workflow_joblist_add_job_from_file( workflow_joblist_type * joblist , const char * job_name , const char * config_file ); - config_parser_type * workflow_joblist_get_compiler( const workflow_joblist_type * joblist ); - config_parser_type * workflow_joblist_get_job_config( const workflow_joblist_type * joblist ); - bool workflow_joblist_has_job( const workflow_joblist_type * joblist , const char * job_name); - stringlist_type * workflow_joblist_get_job_names(const workflow_joblist_type * joblist); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libjob_queue/src/CMakeLists.txt b/ThirdParty/Ert/libjob_queue/src/CMakeLists.txt deleted file mode 100644 index 4332edbc83..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -#configure_file (${CMAKE_CURRENT_SOURCE_DIR}/CMake/include/libjob_queue_build_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/libjob_queue_build_config.h) - - -set(source_files job_queue_status.c forward_model.c queue_driver.c job_queue.c job_node.c job_list.c local_driver.c rsh_driver.c torque_driver.c ext_job.c ext_joblist.c workflow_job.c workflow.c workflow_joblist.c job_queue_manager.c) -set(header_files job_queue.h queue_driver.h local_driver.h job_node.h job_list.h rsh_driver.h torque_driver.h ext_job.h ext_joblist.h forward_model.h workflow_job.h workflow.h workflow_joblist.h job_queue_manager.h) -set_property(SOURCE rsh_driver.c PROPERTY COMPILE_FLAGS "-Wno-error") - -list( APPEND source_files lsf_driver.c) -list( APPEND header_files lsf_driver.h) - -if (HAVE_LSF_LIBRARY) - list( APPEND source_files lsb.c) - list( APPEND header_files lsb.h) -endif() - -add_library( job_queue SHARED ${source_files} ) -set_target_properties( job_queue PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR} ) -target_link_libraries( job_queue config ert_util ) -if (USE_RUNPATH) - add_runpath( job_queue ) -endif() - -target_link_libraries( job_queue dl ) - -if (INSTALL_ERT) - install(TARGETS job_queue DESTINATION ${CMAKE_INSTALL_LIBDIR}) - foreach(header ${header_files}) - install(FILES ../include/ert/job_queue/${header} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/ert/job_queue) - endforeach() -endif() diff --git a/ThirdParty/Ert/libjob_queue/src/ext_job.c b/ThirdParty/Ert/libjob_queue/src/ext_job.c deleted file mode 100644 index 29772ffcb1..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/ext_job.c +++ /dev/null @@ -1,985 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ext_job.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -/* - About arguments - --------------- - How a job is run is defined in terms of the following variables: - - o stdout_file / stdin_file / stderr_file - o arglist - o .... - - These variables will then contain string values from when the job - configuration is read in, for example this little job - - STDOUT my_stdout - STDERR my_stderr - ARGLIST my_job_input my_job_output - - stdout & stderr are redirected to the files 'my_stdout' and - 'my_stderr' respectively, and when invoked with an exec() call the - job is given the argumentlist: - - my_job_input my_job_output - - This implies that _every_time_ this job is invoked the argumentlist - will be identical; that is clearly quite limiting! To solve this we - have the possibility of performing string substitutions on the - strings in the job defintion prior to executing the job, this is - handled with the privat_args substitutions. The definition for a - copy-file job: - - - EXECUTABLE /bin/cp - ARGLIST - - - This can then be invoked several times, with different key=value - arguments for the SRC_FILE and TARGET_FILE: - - - COPY_FILE(SRC_FILE = file1 , TARGET_FILE = /tmp/file1) - COPY_FILE(SRC_FILE = file2 , TARGET_FILE = /tmp/file2) - -*/ - - - -/* - - -jobList = [ - {"executable" : None, - "environment" : {"LM_LICENSE_PATH" : "1700@osl001lic.hda.hydro.com:1700@osl002lic.hda.hydro.com:1700@osl003lic.hda.hydro.com", - "F_UFMTENDIAN" : "big"}, - "target_file":"222", - "argList" : [], - "stdout" : "eclipse.stdout", - "stderr" : "eclipse.stdout", - "stdin" : "eclipse.stdin"}] -*/ - - -#define EXT_JOB_TYPE_ID 763012 - - -struct ext_job_struct { - UTIL_TYPE_ID_DECLARATION; - char * name; - char * executable; - char * target_file; - char * error_file; /* Job has failed if this is present. */ - char * start_file; /* Will not start if not this file is present */ - char * stdout_file; - char * stdin_file; - char * stderr_file; - char * license_path; /* If this is NULL - it will be unrestricted ... */ - char * license_root_path; - char * config_file; - int max_running; /* 0 means unlimited. */ - int max_running_minutes; /* The maximum number of minutes this job is allowed to run - 0: unlimited. */ - subst_list_type * private_args; /* A substitution list of input arguments which is performed before the external substitutions - - these are the arguments supplied as key=value pairs in the forward model call. */ - char * private_args_string; - char * argv_string; - stringlist_type * argv; /* This should *NOT* start with the executable */ - hash_type * environment; - hash_type * default_mapping; - char * help_text; - - bool private_job; /* Can the current user/delete this job? (private_job == true) means the user can edit it. */ - bool __valid; /* Temporary variable consulted during the bootstrap - when the ext_job is completely initialized this should NOT be consulted anymore. */ -}; - - -static UTIL_SAFE_CAST_FUNCTION( ext_job , EXT_JOB_TYPE_ID) - - - - - - - -static ext_job_type * ext_job_alloc__(const char * name , const char * license_root_path , bool private_job) { - ext_job_type * ext_job = util_malloc(sizeof * ext_job ); - - UTIL_TYPE_ID_INIT( ext_job , EXT_JOB_TYPE_ID); - ext_job->name = util_alloc_string_copy( name ); - ext_job->license_root_path = util_alloc_string_copy( license_root_path ); - ext_job->executable = NULL; - ext_job->stdout_file = NULL; - ext_job->target_file = NULL; - ext_job->error_file = NULL; - ext_job->start_file = NULL; - ext_job->stdin_file = NULL; - ext_job->stderr_file = NULL; - ext_job->environment = hash_alloc(); - ext_job->default_mapping = hash_alloc(); - ext_job->argv = stringlist_alloc_new(); - ext_job->argv_string = NULL; - ext_job->__valid = true; - ext_job->license_path = NULL; - ext_job->config_file = NULL; - ext_job->max_running = 0; /* 0 means unlimited. */ - ext_job->max_running_minutes = 0; /* 0 means unlimited. */ - ext_job->private_job = private_job; /* If private_job == true the job is user editable. */ - ext_job->help_text = NULL; - ext_job->private_args_string = NULL; - - /* - ext_job->private_args is set explicitly in the ext_job_alloc() - and ext_job_alloc_copy() functions. - */ - return ext_job; -} - - -const char * ext_job_get_help_text( const ext_job_type * job ) { - if (job->help_text != NULL) - return job->help_text; - else - return "No help text installed for this job."; -} - - -void ext_job_set_help_text( ext_job_type * job , const char * help_text) { - job->help_text = util_realloc_string_copy( job->help_text , help_text ); -} - -/* - Exported function - must have name != NULL. Observe that the - instance returned from this function is not really usable for - anything. - - Should probably define a minium set of parameters which must be set - before the job is in a valid initialized state. -*/ - -ext_job_type * ext_job_alloc(const char * name , const char * license_root_path , bool private_job) { - ext_job_type * ext_job = ext_job_alloc__(name , license_root_path , private_job); - ext_job->private_args = subst_list_alloc( NULL ); - return ext_job; -} - - - - -ext_job_type * ext_job_alloc_copy(const ext_job_type * src_job) { - ext_job_type * new_job = ext_job_alloc__( src_job->name , src_job->license_root_path , true /* All copies are by default private jobs. */); - - new_job->config_file = util_alloc_string_copy(src_job->config_file); - new_job->executable = util_alloc_string_copy(src_job->executable); - new_job->target_file = util_alloc_string_copy(src_job->target_file); - new_job->error_file = util_alloc_string_copy(src_job->error_file); - new_job->start_file = util_alloc_string_copy(src_job->start_file); - new_job->stdout_file = util_alloc_string_copy(src_job->stdout_file); - new_job->stdin_file = util_alloc_string_copy(src_job->stdin_file); - new_job->stderr_file = util_alloc_string_copy(src_job->stderr_file); - new_job->license_path = util_alloc_string_copy(src_job->license_path); - - ext_job_set_help_text( new_job , src_job->help_text ); - - new_job->max_running_minutes = src_job->max_running_minutes; - new_job->max_running = src_job->max_running; - new_job->private_args = subst_list_alloc_deep_copy( src_job->private_args ); - - /* Copying over all the keys in the environment hash table */ - { - hash_iter_type * iter = hash_iter_alloc( src_job->environment ); - const char * key = hash_iter_get_next_key(iter); - while (key != NULL) { - char * value = hash_get( src_job->environment , key); - hash_insert_hash_owned_ref( new_job->environment , key , util_alloc_string_copy(value) , free); - key = hash_iter_get_next_key(iter); - } - hash_iter_free(iter); - } - - - /* The default mapping. */ - { - hash_iter_type * iter = hash_iter_alloc( src_job->default_mapping ); - const char * key = hash_iter_get_next_key(iter); - while (key != NULL) { - char * value = hash_get( src_job->default_mapping , key); - hash_insert_hash_owned_ref( new_job->default_mapping , key , util_alloc_string_copy(value) , free); - key = hash_iter_get_next_key(iter); - } - hash_iter_free(iter); - } - - - - stringlist_deep_copy( new_job->argv , src_job->argv ); - - return new_job; -} - - - - -void ext_job_free(ext_job_type * ext_job) { - free(ext_job->name); - util_safe_free(ext_job->executable); - util_safe_free(ext_job->stdout_file); - util_safe_free(ext_job->stdin_file); - util_safe_free(ext_job->target_file); - util_safe_free(ext_job->error_file); - util_safe_free(ext_job->stderr_file); - util_safe_free(ext_job->license_path); - util_safe_free(ext_job->license_root_path); - util_safe_free(ext_job->config_file); - util_safe_free(ext_job->argv_string); - util_safe_free(ext_job->help_text); - util_safe_free(ext_job->private_args_string); - - hash_free( ext_job->default_mapping); - hash_free( ext_job->environment ); - stringlist_free(ext_job->argv); - subst_list_free( ext_job->private_args ); - free(ext_job); -} - -void ext_job_free__(void * __ext_job) { - ext_job_free ( ext_job_safe_cast(__ext_job) ); -} - - -static void __update_mode( const char * filename , mode_t add_mode) { - util_addmode_if_owner( filename , add_mode); -} - - -/** - The license_path = - - root_license_path / job_name / job_name - -*/ - -static void ext_job_init_license_control(ext_job_type * ext_job) { - if (ext_job->license_path == NULL) { - ext_job->license_path = util_alloc_sprintf("%s%c%s" , ext_job->license_root_path , UTIL_PATH_SEP_CHAR , ext_job->name ); - util_make_path( ext_job->license_path ); - printf("License for %s in %s \n",ext_job->name , ext_job->license_path); - } -} - - - -void ext_job_set_max_time( ext_job_type * ext_job , int max_time ) { - ext_job->max_running_minutes = max_time; -} - - - -/** - @executable parameter: - The raw executable is either - - an absolute path read directly from config - - an absolute path constructed from the relative path from config - with the assumption that the path was a relative path from the - location of the job description file to the executable. - - @executable_raw parameter: - The raw executable as read from config, unprocessed. - - This method have the following logic: - - @executable exists: - We store the full path as the executable field of the job; and - try to update the mode of the full_path executable to make sure it - is executable. - - @executable does not exist, but @executable_raw exists: - We have found an executable relative to the current working - directory. This is deprecated behaviour, support will later be - removed. Suggest new path to executable to user, relative to job - description file and do a recursive call to this method, using - the absolute path as @executable parameter - - @executable does not exist, @executable_raw does not exist and - is an absolute path: - Write error message - - @executable does not exist, @executable_raw does not exist and - is a relative path: - Search trough the PATH variable to try to locate the executable. - If found, do a recursive call to this method, using the absolute path - as @executable parameter - -*/ - -void ext_job_set_executable(ext_job_type * ext_job, const char * executable_abs, const char * executable_input,bool search_path) { - - if (util_file_exists(executable_abs)) { - /* - The @executable parameter points to an existing file; we store - the full path as the executable field of the job; we also try - to update the mode of the full_path executable to make sure it - is executable. - */ - char * full_path = util_alloc_realpath( executable_abs ); - __update_mode( full_path , S_IRUSR + S_IWUSR + S_IXUSR + S_IRGRP + S_IWGRP + S_IXGRP + S_IROTH + S_IXOTH); /* u:rwx g:rwx o:rx */ - ext_job->executable = util_realloc_string_copy(ext_job->executable , full_path); - free( full_path ); - } else if (util_file_exists(executable_input)) { - /* - This "if" case means that we have found an executable relative - to the current working directory. This is deprecated behaviour, - support will be removed - */ - char * full_path = util_alloc_abs_path(executable_input); - const char * job_description_file = ext_job_get_config_file(ext_job); - char * path_to_job_descr_file = util_split_alloc_dirname(job_description_file); - char * new_relative_path_to_exe = util_alloc_rel_path(path_to_job_descr_file, full_path); - char * relative_config_file = util_alloc_rel_path(NULL , ext_job->config_file); - - fprintf(stderr,"/----------------------------------------------------------------\n"); - fprintf(stderr,"| ** WARNING ** \n"); - fprintf(stderr,"|\n"); - fprintf(stderr,"| The convention for locating the executable in a forward model \n"); - fprintf(stderr,"| job has changed. When using a relative path in the EXECUTABLE \n"); - fprintf(stderr,"| setting in the job description file, the path will be interpreted\n"); - fprintf(stderr,"| relative to the location of the job description file. \n"); - fprintf(stderr,"|\n"); - fprintf(stderr,"| The job:\'%s\' will temporarilty continue to work in the \n",ext_job->name); - fprintf(stderr,"| present form, but it is recommended to update: \n"); - fprintf(stderr,"|\n"); - fprintf(stderr,"| 1. Open the file:%s in an editor \n",relative_config_file); - fprintf(stderr,"|\n"); - fprintf(stderr,"| 2. Change the EXECUTABLE line to: \n"); - fprintf(stderr,"|\n"); - fprintf(stderr,"| EXECUTABLE %s \n" , new_relative_path_to_exe); - fprintf(stderr,"|\n"); - fprintf(stderr,"| The main advantage with this change in behaviour is that the\n"); - fprintf(stderr,"| job description file and the executable can be relocated.\n"); - fprintf(stderr,"\\----------------------------------------------------------------\n\n"); - - ext_job_set_executable(ext_job, full_path, NULL, search_path); - - free(new_relative_path_to_exe); - free(path_to_job_descr_file); - free(full_path); - free(relative_config_file); - - } else if (util_is_abs_path( executable_input )) { - /* If you have given an absolute path (i.e. starting with '/' to - a non existing job we mark it as invalid - no possibility to - provide context replacement afterwards. The job will be - discarded by the calling scope. - */ - fprintf(stderr , "** Warning: the executable:%s can not be found,\n" - " job:%s will not be available.\n" , executable_abs , ext_job->name ); - ext_job->__valid = false; - } else { - if (search_path){ - /* Go through the PATH variable to try to locate the executable. */ - char * path_executable = util_alloc_PATH_executable( executable_input ); - - if (path_executable != NULL) { - ext_job_set_executable( ext_job , path_executable, NULL, search_path ); - free( path_executable ); - } else { - /* We take the chance that user will supply a valid subst key for this later; - if the final executable is not an actually executable file when exporting the - job from ext_job_python_fprintf() a big warning will be written on stderr. - */ - fprintf(stderr , "** Warning: Unable to locate the executable %s for job %s.\n" - " Path to executable must be relative to the job description file, or an absolute path.\n" - " Please update job EXECUTABLE for job %s. \n" , executable_abs , ext_job->name, ext_job->name); - ext_job->__valid = false; - } - } else { - ext_job->executable = util_realloc_string_copy(ext_job->executable , executable_input); - } - } - - /* - If in the end we do not have execute rights to the executable : - discard the job. - */ - if (ext_job->executable != NULL) { - if (util_file_exists(executable_abs)) { - if (!util_is_executable( ext_job->executable )) { - fprintf(stderr , "** You do not have execute rights to:%s - job will not be available.\n" , ext_job->executable); - ext_job->__valid = false; /* Mark the job as NOT successfully installed - the ext_job - instance will later be freed and discarded. */ - } - } - } -} - - - -/** - Observe that this does NOT reread the ext_job instance from the new - config_file. -*/ - - -/*****************************************************************/ -/* Scalar set and get functions */ - -void ext_job_set_config_file(ext_job_type * ext_job, const char * config_file) { - ext_job->config_file = util_realloc_string_copy(ext_job->config_file , config_file); -} - -const char * ext_job_get_config_file(const ext_job_type * ext_job) { - return ext_job->config_file; -} - -void ext_job_set_target_file(ext_job_type * ext_job, const char * target_file) { - ext_job->target_file = util_realloc_string_copy(ext_job->target_file , target_file); -} - -const char * ext_job_get_target_file(const ext_job_type * ext_job) { - return ext_job->target_file; -} - -void ext_job_set_error_file(ext_job_type * ext_job, const char * error_file) { - ext_job->error_file = util_realloc_string_copy(ext_job->error_file , error_file); -} - -const char * ext_job_get_error_file(const ext_job_type * ext_job) { - return ext_job->error_file; -} - -const char * ext_job_get_executable(const ext_job_type * ext_job) { - return ext_job->executable; -} - -void ext_job_set_start_file(ext_job_type * ext_job, const char * start_file) { - ext_job->start_file = util_realloc_string_copy(ext_job->start_file , start_file); -} - -const char * ext_job_get_start_file(const ext_job_type * ext_job) { - return ext_job->start_file; -} - -void ext_job_set_name(ext_job_type * ext_job, const char * name) { - ext_job->name = util_realloc_string_copy(ext_job->name , name); -} - -const char * ext_job_get_name(const ext_job_type * ext_job) { - return ext_job->name; -} -void ext_job_set_stdin_file(ext_job_type * ext_job, const char * stdin_file) { - ext_job->stdin_file = util_realloc_string_copy(ext_job->stdin_file , stdin_file); -} - -const char * ext_job_get_stdin_file(const ext_job_type * ext_job) { - return ext_job->stdin_file; -} - -void ext_job_set_stdout_file(ext_job_type * ext_job, const char * stdout_file) { - ext_job->stdout_file = util_realloc_string_copy(ext_job->stdout_file , stdout_file); -} - -const char * ext_job_get_stdout_file(const ext_job_type * ext_job) { - return ext_job->stdout_file; -} - -void ext_job_set_stderr_file(ext_job_type * ext_job, const char * stderr_file) { - ext_job->stderr_file = util_realloc_string_copy(ext_job->stderr_file , stderr_file); -} - -const char * ext_job_get_stderr_file(const ext_job_type * ext_job) { - return ext_job->stderr_file; -} - -void ext_job_set_max_running( ext_job_type * ext_job , int max_running) { - ext_job->max_running = max_running; - if (max_running > 0) - ext_job_init_license_control( ext_job ); -} - -int ext_job_get_max_running( const ext_job_type * ext_job ) { - return ext_job->max_running; -} - -void ext_job_set_max_running_minutes( ext_job_type * ext_job , int max_running_minutes) { - ext_job->max_running_minutes = max_running_minutes; -} - -int ext_job_get_max_running_minutes( const ext_job_type * ext_job ) { - return ext_job->max_running_minutes; -} - -/*****************************************************************/ - -void ext_job_set_private_arg(ext_job_type * ext_job, const char * key , const char * value) { - subst_list_append_copy( ext_job->private_args , key , value , NULL); -} - -void ext_job_add_environment(ext_job_type *ext_job , const char * key , const char * value) { - hash_insert_hash_owned_ref( ext_job->environment , key , util_alloc_string_copy( value ) , free); -} - - -void ext_job_clear_environment( ext_job_type * ext_job ) { - hash_clear( ext_job->environment ); -} - -hash_type * ext_job_get_environment( ext_job_type * ext_job ) { - return ext_job->environment; -} - - -/*****************************************************************/ - - -static char * __alloc_filtered_string( const char * src_string , const subst_list_type * private_args, const subst_list_type * global_args) { - char * tmp1 = subst_list_alloc_filtered_string( private_args , src_string ); /* internal filtering first */ - char * tmp2; - - if (global_args != NULL) { - tmp2 = subst_list_alloc_filtered_string( global_args , tmp1 ); /* Global filtering. */ - free( tmp1 ); - } else - tmp2 = tmp1; - - return tmp2; - -} - -static void __fprintf_string(FILE * stream , const char * s , const subst_list_type * private_args, const subst_list_type * global_args) { - char * filtered_string = __alloc_filtered_string(s , private_args , global_args ); - fprintf(stream , "\"%s\"" , filtered_string ); - free( filtered_string ); -} - - -static void __fprintf_python_string(FILE * stream , const char * id , const char * value, const subst_list_type * private_args, const subst_list_type * global_args) { - fprintf(stream , "\"%s\" : " , id); - if (value == NULL) - fprintf(stream,"None"); - else - __fprintf_string(stream , value , private_args , global_args); -} - - -static void __fprintf_init_python_list( FILE * stream , const char * id ) { - fprintf(stream , "\"%s\" : " , id); - fprintf(stream,"["); -} - -static void __fprintf_close_python_list( FILE * stream ) { - fprintf(stream,"]"); -} - - - - - -static void __fprintf_python_hash(FILE * stream , const char * id , hash_type * hash, const subst_list_type * private_args, const subst_list_type * global_args) { - fprintf(stream , "\"%s\" : " , id); - int hash_size = hash_get_size(hash); - if (hash_size > 0) { - int counter = 0; - fprintf(stream,"{"); - hash_iter_type * iter = hash_iter_alloc(hash); - const char * key = hash_iter_get_next_key(iter); - while (key != NULL) { - const char * value = hash_get(hash , key); - - fprintf(stream,"\"%s\" : " , key); - __fprintf_string(stream , value , private_args , global_args); - - if (counter < (hash_size - 1)) - fprintf(stream,","); - - key = hash_iter_get_next_key(iter); - } - fprintf(stream,"}"); - } else - fprintf(stream , "None"); -} - - -static void __fprintf_python_int( FILE * stream , const char * key , int value) { - if (value > 0) - fprintf(stream , "\"%s\" : %d" , key , value); - else - fprintf(stream , "\"%s\" : None" , key); -} - - -static void __end_line(FILE * stream) { - fprintf(stream,",\n"); -} - - -static void __indent(FILE * stream, int indent) { - int i; - for (i = 0; i < indent; i++) - fprintf(stream," "); -} - - -/* - This is special cased to support the default mapping. -*/ - -static void ext_job_fprintf_python_argList( const ext_job_type * ext_job , FILE * stream , const subst_list_type * global_args) { - __fprintf_init_python_list( stream , "argList" ); - { - for (int index = 0; index < stringlist_get_size( ext_job->argv ); index++) { - const char * src_string = stringlist_iget( ext_job->argv , index ); - char * filtered_string = __alloc_filtered_string(src_string , ext_job->private_args , global_args ); - if (hash_has_key( ext_job->default_mapping , filtered_string )) - filtered_string = util_realloc_string_copy( filtered_string , hash_get( ext_job->default_mapping , filtered_string )); - - fprintf(stream , "\"%s\"" , filtered_string ); - if (index < (stringlist_get_size( ext_job->argv) - 1)) - fprintf(stream , "," ); - - free( filtered_string ); - } - } - __fprintf_close_python_list( stream ); -} - - - -void ext_job_python_fprintf(const ext_job_type * ext_job, FILE * stream, const subst_list_type * global_args) { - fprintf(stream," {"); - { - __indent(stream, 0); __fprintf_python_string(stream , "name" , ext_job->name , ext_job->private_args , NULL); __end_line(stream); - __indent(stream, 2); __fprintf_python_string(stream , "executable" , ext_job->executable , ext_job->private_args, global_args); __end_line(stream); - __indent(stream, 2); __fprintf_python_string(stream , "target_file" , ext_job->target_file , ext_job->private_args, global_args); __end_line(stream); - __indent(stream, 2); __fprintf_python_string(stream , "error_file" , ext_job->error_file , ext_job->private_args, global_args); __end_line(stream); - __indent(stream, 2); __fprintf_python_string(stream , "start_file" , ext_job->start_file , ext_job->private_args, global_args); __end_line(stream); - __indent(stream, 2); __fprintf_python_string(stream , "stdout" , ext_job->stdout_file , ext_job->private_args, global_args); __end_line(stream); - __indent(stream, 2); __fprintf_python_string(stream , "stderr" , ext_job->stderr_file , ext_job->private_args, global_args); __end_line(stream); - __indent(stream, 2); __fprintf_python_string(stream , "stdin" , ext_job->stdin_file , ext_job->private_args, global_args); __end_line(stream); - __indent(stream, 2); ext_job_fprintf_python_argList(ext_job , stream , global_args); __end_line(stream); - __indent(stream, 2); __fprintf_python_hash(stream , "environment" , ext_job->environment , ext_job->private_args, global_args); __end_line(stream); - __indent(stream, 2); __fprintf_python_string(stream , "license_path" , ext_job->license_path , ext_job->private_args, global_args); __end_line(stream); - __indent(stream, 2); __fprintf_python_int( stream , "max_running_minutes" , ext_job->max_running_minutes ); __end_line(stream); - __indent(stream, 2); __fprintf_python_int( stream , "max_running" , ext_job->max_running ); __end_line(stream); - } - fprintf(stream,"}"); -} - - -#define PRINT_KEY_STRING( stream , key , value ) \ -if (value != NULL) \ -{ \ - fprintf(stream , "%16s ", key); \ - fprintf(stream , "%s\n" , value); \ -} - - -#define PRINT_KEY_INT( stream , key , value ) \ -if (value != 0) \ -{ \ - fprintf(stream , "%16s ", key); \ - fprintf(stream , "%d\n" , value); \ -} - - -/** - Observe that the job will save itself to the internalized - config_file; if you wish to save to some other place you must call - ext_job_set_config_file() first. -*/ - -void ext_job_save( const ext_job_type * ext_job ) { - FILE * stream = util_mkdir_fopen( ext_job->config_file , "w" ); - - PRINT_KEY_STRING( stream , "EXECUTABLE" , ext_job->executable); - PRINT_KEY_STRING( stream , "STDIN" , ext_job->stdin_file); - PRINT_KEY_STRING( stream , "STDERR" , ext_job->stderr_file); - PRINT_KEY_STRING( stream , "STDOUT" , ext_job->stdout_file); - PRINT_KEY_STRING( stream , "TARGET_FILE" , ext_job->target_file); - PRINT_KEY_STRING( stream , "START_FILE" , ext_job->start_file); - PRINT_KEY_STRING( stream , "ERROR_FILE" , ext_job->error_file); - PRINT_KEY_INT( stream , "MAX_RUNNING" , ext_job->max_running); - PRINT_KEY_INT( stream , "MAX_RUNNING_MINUTES" , ext_job->max_running_minutes); - - if (stringlist_get_size( ext_job->argv ) > 0) { - fprintf(stream , "%16s" , "ARGLIST"); - stringlist_fprintf( ext_job->argv , " " , stream ); - fprintf(stream , "\n"); - } - if (hash_get_size( ext_job->environment ) > 0) { - hash_iter_type * hash_iter = hash_iter_alloc( ext_job->environment ); - while (!hash_iter_is_complete( hash_iter )) { - const char * key = hash_iter_get_next_key( hash_iter ); - fprintf(stream, "%16s %16s %s\n" , "ENV" , key , (const char *) hash_get( ext_job->environment , key )); - } - hash_iter_free( hash_iter ); - } - fclose( stream ); -} - -#undef PRINT_KEY_STRING -#undef PRINT_KEY_INT - - - -void ext_job_fprintf(const ext_job_type * ext_job , FILE * stream) { - fprintf(stream , "%s", ext_job->name); - if (subst_list_get_size( ext_job->private_args ) > 0) { - fprintf(stream , "("); - subst_list_fprintf(ext_job->private_args , stream); - fprintf(stream , ")"); - } - fprintf(stream , " "); -} - - -/** - The format variable @fmt should contain two '%s' placeholders - - one for the job name, and one for the job description file. -*/ - -void ext_job_fprintf_config(const ext_job_type * ext_job , const char * fmt , FILE * stream) { - fprintf(stream , fmt , ext_job->name , ext_job->config_file ); -} - - - - - - -ext_job_type * ext_job_fscanf_alloc(const char * name , const char * license_root_path , bool private_job , const char * config_file, bool search_path) { - { - mode_t target_mode = S_IRUSR + S_IWUSR + S_IRGRP + S_IWGRP + S_IROTH; /* u+rw g+rw o+r */ - __update_mode( config_file , target_mode ); - } - - if (util_entry_readable( config_file)) { - ext_job_type * ext_job = NULL; - config_parser_type * config = config_alloc( ); - - { - config_schema_item_type * item; - item = config_add_schema_item(config , "MAX_RUNNING" , false ); config_schema_item_set_argc_minmax(item , 1 , 1 ); config_schema_item_iset_type( item , 0 , CONFIG_INT ); - item = config_add_schema_item(config , "STDIN" , false ); config_schema_item_set_argc_minmax(item , 1 , 1 ); - item = config_add_schema_item(config , "STDOUT" , false ); config_schema_item_set_argc_minmax(item , 1 , 1 ); - item = config_add_schema_item(config , "STDERR" , false ); config_schema_item_set_argc_minmax(item , 1 , 1 ); - item = config_add_schema_item(config , "EXECUTABLE" , true ); config_schema_item_set_argc_minmax(item , 1 , 1 ); config_schema_item_iset_type(item, 0, CONFIG_PATH); - item = config_add_schema_item(config , "TARGET_FILE" , false ); config_schema_item_set_argc_minmax(item , 1 , 1 ); - item = config_add_schema_item(config , "ERROR_FILE" , false ); config_schema_item_set_argc_minmax(item , 1 , 1 ); - item = config_add_schema_item(config , "START_FILE" , false ); config_schema_item_set_argc_minmax(item , 1 , 1 ); - item = config_add_schema_item(config , "ENV" , false ); config_schema_item_set_argc_minmax(item , 2 , 2 ); - item = config_add_schema_item(config , "DEFAULT" , false ); config_schema_item_set_argc_minmax(item , 2 , 2 ); - item = config_add_schema_item(config , "ARGLIST" , false ); config_schema_item_set_argc_minmax(item , 1 , CONFIG_DEFAULT_ARG_MAX ); - item = config_add_schema_item(config , "MAX_RUNNING_MINUTES" , false ); config_schema_item_set_argc_minmax(item , 1 , 1 ); config_schema_item_iset_type( item , 0 , CONFIG_INT ); - } - config_add_alias(config , "EXECUTABLE" , "PORTABLE_EXE"); - - { - config_content_type * content = config_parse(config , config_file , "--" , NULL , NULL , NULL , CONFIG_UNRECOGNIZED_WARN , true); - if (config_content_is_valid( content )) { - ext_job = ext_job_alloc(name , license_root_path , private_job); - ext_job_set_config_file( ext_job , config_file ); - - - if (config_content_has_item(content , "STDIN")) ext_job_set_stdin_file(ext_job , config_content_iget(content , "STDIN" , 0,0)); - if (config_content_has_item(content , "STDOUT")) ext_job_set_stdout_file(ext_job , config_content_iget(content , "STDOUT" , 0,0)); - if (config_content_has_item(content , "STDERR")) ext_job_set_stderr_file(ext_job , config_content_iget(content , "STDERR" , 0,0)); - if (config_content_has_item(content , "ERROR_FILE")) ext_job_set_error_file(ext_job , config_content_iget(content , "ERROR_FILE" , 0,0)); - if (config_content_has_item(content , "TARGET_FILE")) ext_job_set_target_file(ext_job , config_content_iget(content , "TARGET_FILE" , 0,0)); - if (config_content_has_item(content , "START_FILE")) ext_job_set_start_file(ext_job , config_content_iget(content , "START_FILE" , 0,0)); - if (config_content_has_item(content , "MAX_RUNNING")) ext_job_set_max_running(ext_job , config_content_iget_as_int(content , "MAX_RUNNING" , 0,0)); - if (config_content_has_item(content , "MAX_RUNNING_MINUTES")) ext_job_set_max_time(ext_job , config_content_iget_as_int(content , "MAX_RUNNING_MINUTES" , 0,0)); - - - { - const char * executable = config_content_get_value_as_abspath(content , "EXECUTABLE"); - const char * executable_raw = config_content_iget(content , "EXECUTABLE" , 0,0); - ext_job_set_executable(ext_job , executable, executable_raw, search_path); - } - - - { - if (config_content_has_item( content , "ARGLIST")) { - config_content_node_type * arg_node = config_content_get_value_node( content , "ARGLIST"); - int i; - for (i=0; i < config_content_node_get_size( arg_node ); i++) - stringlist_append_copy( ext_job->argv , config_content_node_iget( arg_node , i )); - } - } - - - /** - The code assumes that the hash tables are valid, can not be NULL: - */ - { - if (config_content_has_item( content , "ENV")) { - const config_content_item_type * env_item = config_content_get_item( content , "ENV" ); - for (int ivar = 0; ivar < config_content_item_get_size( env_item ); ivar++) { - const config_content_node_type * env_node = config_content_item_iget_node( env_item , ivar ); - for (int i=0; i < config_content_node_get_size( env_node ); i+= 2) { - const char * key = config_content_node_iget( env_node , i ); - const char * value = config_content_node_iget( env_node , i + 1); - hash_insert_hash_owned_ref( ext_job->environment, key , util_alloc_string_copy( value ) , free); - } - } - } - } - - /* Default mappings; these are used to set values in the argList - which have not been supplied by the calling context. */ - { - if (config_content_has_item( content , "DEFAULT")) { - const config_content_item_type * default_item = config_content_get_item( content , "DEFAULT"); - for (int ivar = 0; ivar < config_content_item_get_size( default_item ); ivar++) { - const config_content_node_type * default_node = config_content_item_iget_node( default_item , ivar ); - for (int i=0; i < config_content_node_get_size( default_node ); i+= 2) { - const char * key = config_content_node_iget( default_node , i ); - const char * value = config_content_node_iget( default_node , i + 1); - hash_insert_hash_owned_ref( ext_job->default_mapping, key , util_alloc_string_copy( value ) , free); - } - } - } - } - - if (!ext_job->__valid) { - /* - Something NOT OK (i.e. EXECUTABLE now); free the job instance and return NULL: - */ - ext_job_free( ext_job ); - ext_job = NULL; - fprintf(stderr,"** Warning: job: \'%s\' not available ... \n", name ); - } - } else { - config_error_type * error = config_content_get_errors( content ); - config_error_fprintf( error , true , stderr ); - fprintf(stderr,"** Warning: job: \'%s\' not available ... \n", name ); - } - config_content_free( content ); - } - config_free(config); - - return ext_job; - } else { - fprintf(stderr,"** Warning: you do not have permission to read file:\'%s\' - job:%s not available. \n", config_file , name); - return NULL; - } -} - - -const stringlist_type * ext_job_get_arglist( const ext_job_type * ext_job ) { - return ext_job->argv; -} - - -/** - -*/ - -//const char * ext_job_get_arglist_as_string( ext_job_type * ext_job ) { -// if (stringlist_get_size( ext_job->argv ) == 0) -// return NULL; -// else { -// const char * sep = " "; -// int argc = stringlist_get_size( ext_job->argv ); -// int i; -// buffer_type * buffer = buffer_alloc( 512 ); -// for (i = 0; i < argc; i++) { -// const char * arg = stringlist_iget( ext_job->argv , i ); -// bool quote = false; -// if (strchr(arg , ' ') != NULL) -// quote = true; -// -// if (quote) -// buffer_fwrite_char( buffer , ' ' ); -// buffer_fwrite_char_ptr( buffer , arg ); -// if (quote) -// buffer_fwrite_char( buffer , ' ' ); -// -// if (i < (argc - 1)) -// buffer_fwrite_char_ptr( buffer , sep ); -// -// buffer_fwrite_char( buffer , '\0'); -// util_safe_free(ext_job->argv_string); -// ext_job->argv_string = buffer_alloc_data_copy( buffer ); -// buffer_free( buffer ); -// -// return ext_job->argv_string; -// } -//} -// -// -//void ext_job_set_arglist_from_string( ext_job_type * ext_job , const char * argv_string ) { -// parser_type * parser = parser_alloc(" " , "\"" , NULL , NULL , NULL , NULL ); -// stringlist_free( ext_job->argv ); -// ext_job->argv = parser_tokenize_buffer( parser , argv_string , true ); -// parser_free( parser ); -//} - - -const char * ext_job_get_private_args_as_string( ext_job_type * ext_job ) { - util_safe_free( ext_job->private_args_string ); - ext_job->private_args_string = subst_list_alloc_string_representation( ext_job->private_args ); - return ext_job->private_args_string; -} - - -/** - Set the internal arguments of the job based on an input string - @arg_string which is of the form: - - key1=value1, key2=value2 , key3=value3 - - The internal private argument list is cleared before adding these - arguments. -*/ - -int ext_job_set_private_args_from_string( ext_job_type * ext_job , const char * arg_string ) { - subst_list_clear( ext_job->private_args ); - return subst_list_add_from_string( ext_job->private_args , arg_string , true ); -} - - - -bool ext_job_is_shared( const ext_job_type * ext_job ) { - return !ext_job->private_job; -} - -bool ext_job_is_private( const ext_job_type * ext_job ) { - return ext_job->private_job; -} - - -#undef ASSERT_TOKENS diff --git a/ThirdParty/Ert/libjob_queue/src/ext_joblist.c b/ThirdParty/Ert/libjob_queue/src/ext_joblist.c deleted file mode 100644 index c55343c302..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/ext_joblist.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'ext_joblist.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - - -//#define MODULE_NAME "jobs.py" -//#define JOBLIST_NAME "jobList" - - -/** - About the 'license' system: - --------------------------- - - There is a simple possibility to limit the number of jobs which are - running in parallell. It works like this: - - 1. For the joblist as a whole a license_path is created. This - license path should contain both a uid and pid of the current - process. This ensures that: - - a. The license count is per user and per ert instance. - b. Each ert instance starts with a fresh license count. A - license path, and license files left dangling after unclean - shutdown can just be removed. - - 2. For each job in the joblist a subdirectory is created under the - license_path. - - 3. For each job a license_file is created, and for each time a new - instance is checked out a hard_link to this license_file is - created - i.e. the number of checked out licenses is a - hard_link count (-1). - - Step three here is implemented by the job_dispatch script - actually running the jobs. - - It is essential that the license_root_path is on a volume which is - accessible from all the nodes which will run jobs. Using e.g. /tmp - as license_root_path will fail HARD. - -*/ - - - -/*****************************************************************/ - -struct ext_joblist_struct { - hash_type * jobs; -}; - - - - -ext_joblist_type * ext_joblist_alloc( ) { - ext_joblist_type * joblist = util_malloc( sizeof * joblist ); - joblist->jobs = hash_alloc(); - return joblist; -} - - -void ext_joblist_free(ext_joblist_type * joblist) { - hash_free(joblist->jobs); - free(joblist); -} - - -void ext_joblist_add_job(ext_joblist_type * joblist , const char * name , ext_job_type * new_job) { - hash_insert_hash_owned_ref(joblist->jobs , name , new_job , ext_job_free__); -} - - -ext_job_type * ext_joblist_get_job(const ext_joblist_type * joblist , const char * job_name) { - if (hash_has_key(joblist->jobs , job_name)) - return hash_get(joblist->jobs , job_name); - else { - util_abort("%s: asked for job:%s which does not exist\n",__func__ , job_name); - return NULL; - } -} - - -ext_job_type * ext_joblist_get_job_copy(const ext_joblist_type * joblist , const char * job_name) { - if (hash_has_key(joblist->jobs , job_name)) - return ext_job_alloc_copy(hash_get(joblist->jobs , job_name)); - else { - util_abort("%s: asked for job:%s which does not exist\n",__func__ , job_name); - return NULL; - } -} - - -bool ext_joblist_has_job(const ext_joblist_type * joblist , const char * job_name) { - return hash_has_key(joblist->jobs , job_name); -} - - -stringlist_type * ext_joblist_alloc_list( const ext_joblist_type * joblist) { - return hash_alloc_stringlist( joblist->jobs ); -} - - -/** - Will attempt to remove the job @job_name from the joblist; if the - job is marked as a shared_job (i.e. installed centrally) the user - is not allowed to delete it. In this case the function will fail - silently. - - Returns true if the job is actually removed, and false otherwise. -*/ - -bool ext_joblist_del_job( ext_joblist_type * joblist , const char * job_name ) { - ext_job_type * job = ext_joblist_get_job( joblist , job_name ); - if (!ext_job_is_shared( job )) { - hash_del( joblist->jobs , job_name ); - return true; - } else - return false; -} - - -hash_type * ext_joblist_get_jobs( const ext_joblist_type * joblist ) { - return joblist->jobs; -} - -void ext_joblist_add_jobs_in_directory(ext_joblist_type * joblist , const char * path, const char * license_root_path, bool user_mode, bool search_path ) { - DIR * dirH = opendir( path ); - if (dirH) { - while (true) { - struct dirent * entry = readdir( dirH ); - if (entry != NULL) { - if ((strcmp(entry->d_name , ".") != 0) && (strcmp(entry->d_name , "..") != 0)) { - char * full_path = util_alloc_filename( path , entry->d_name , NULL ); - if (util_is_file( full_path )) { - ext_job_type * new_job = ext_job_fscanf_alloc(entry->d_name, license_root_path, user_mode, full_path, search_path); - if (new_job != NULL) { - ext_joblist_add_job(joblist, entry->d_name, new_job); - } - else{ - fprintf(stderr," Failed to add forward model job: %s \n",full_path); - } - } - free( full_path ); - } - } else - break; - } - closedir( dirH ); - } else - fprintf(stderr, "** Warning: failed to open jobs directory: %s\n", path); -} - - -int ext_joblist_get_size( const ext_joblist_type * joblist ) { - return hash_get_size( joblist->jobs ); -} - diff --git a/ThirdParty/Ert/libjob_queue/src/forward_model.c b/ThirdParty/Ert/libjob_queue/src/forward_model.c deleted file mode 100644 index 6dc51f14d4..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/forward_model.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'forward_model.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - - -/** - This file implements a 'forward-model' object. I -*/ - -struct forward_model_struct { - vector_type * jobs; /* The actual jobs in this forward model. */ - const ext_joblist_type * ext_joblist; /* This is the list of external jobs which have been installed - which we can choose from. */ -}; - -#define DEFAULT_JOB_MODULE "jobs.py" -#define DEFAULT_JOBLIST_NAME "jobList" - - - - -forward_model_type * forward_model_alloc(const ext_joblist_type * ext_joblist) { - forward_model_type * forward_model = util_malloc( sizeof * forward_model ); - - forward_model->jobs = vector_alloc_new(); - forward_model->ext_joblist = ext_joblist; - - return forward_model; -} - - -/** - Allocates and returns a stringlist with all the names in the - current forward_model. -*/ -stringlist_type * forward_model_alloc_joblist( const forward_model_type * forward_model ) { - stringlist_type * names = stringlist_alloc_new( ); - int i; - for (i=0; i < vector_get_size( forward_model->jobs ); i++) { - const ext_job_type * job = vector_iget_const( forward_model->jobs , i); - stringlist_append_ref( names , ext_job_get_name( job )); - } - - return names; -} - - -/** - This function adds the job named 'job_name' to the forward model. The return - value is the newly created ext_job instance. This can be used to set private - arguments for this job. -*/ - -ext_job_type * forward_model_add_job(forward_model_type * forward_model , const char * job_name) { - ext_job_type * new_job = ext_joblist_get_job_copy(forward_model->ext_joblist , job_name); - vector_append_owned_ref( forward_model->jobs , new_job , ext_job_free__); - return new_job; -} - - - -/** - This function is used to set private argument values to jobs in the - forward model (i.e. the argument values passed in with KEY=VALUE - pairs in the defining (). - - The use of 'index' to get the job is unfortunate , however one - forward model can contain several instances of the same job, it is - therefor not possible to use name based lookup. -*/ - -void forward_model_iset_job_arg( forward_model_type * forward_model , int job_index , const char * arg , const char * value) { - ext_job_type * job = vector_iget( forward_model->jobs , job_index ); - ext_job_set_private_arg(job , arg , value); -} - - -void forward_model_clear( forward_model_type * forward_model ) { - vector_clear( forward_model->jobs ); -} - - - -void forward_model_free( forward_model_type * forward_model) { - vector_free( forward_model->jobs ); - free(forward_model); -} - - - - -/** - this function takes an input string of the type: - - job1 job2 job3(arg1 = value1, arg2 = value2, arg3= value3) - - and creates a forward model of it. observe the following rules: - - * if the function takes private arguments it is not allowed with space - between the end of the function name and the opening parenthesis. - -*/ - - -void forward_model_parse_init(forward_model_type * forward_model , const char * input_string ) { - //tokenizer_type * tokenizer_alloc(" " , "\'\"" , ",=()" , null , null , null); - //stringlist_type * tokens = tokenizer_buffer( tokenizer , input_string , true); - //stringlist_free( tokens ); - //tokenizer_free( tokenizer ); - - char * p1 = (char *) input_string; - while (true) { - ext_job_type * current_job; - char * job_name; - int job_index; - { - int job_length = strcspn(p1 , " ("); /* scanning until we meet ' ' or '(' */ - job_name = util_alloc_substring_copy(p1 , 0 , job_length); - p1 += job_length; - } - job_index = vector_get_size( forward_model->jobs ); - current_job = forward_model_add_job(forward_model , job_name); - - if (*p1 == '(') { /* the function has arguments. */ - int arg_length = strcspn(p1 , ")"); - if (arg_length == strlen(p1)) - util_abort("%s: paranthesis not terminated for job:%s \n",__func__ , job_name); - { - char * arg_string = util_alloc_substring_copy((p1 + 1) , 0 , arg_length - 1); - ext_job_set_private_args_from_string( current_job , arg_string ); - p1 += (1 + arg_length); - free( arg_string ); - } - } - /*****************************************************************/ - /* At this point we are done with the parsing - the rest of the - code in this while { } construct is only to check that the - input is well formed. */ - - { - int space_length = strspn(p1 , " "); - p1 += space_length; - if (*p1 == '(') - /* detected lonesome '(' */ - util_abort("%s: found space between job:%s and \'(\' - aborting \n",__func__ , job_name); - } - - /* - now p1 should point at the next character after the job, - or after the ')' if the job has arguments. - */ - - free(job_name); - if (*p1 == '\0') /* we have parsed the whole string. */ - break; - - } -} - - - -/*****************************************************************/ - -/* - the name of the pyton module - and the variable in the module, - used when running the remote jobs. -*/ - -void forward_model_python_fprintf(const forward_model_type * forward_model , - const char * path, - const subst_list_type * global_args, - mode_t umask) { - char * module_file = util_alloc_filename(path , DEFAULT_JOB_MODULE , NULL); - FILE * stream = util_fopen(module_file , "w"); - int i; - - fprintf(stream , "%s = [" , DEFAULT_JOBLIST_NAME); - for (i=0; i < vector_get_size(forward_model->jobs); i++) { - const ext_job_type * job = vector_iget_const(forward_model->jobs , i); - ext_job_python_fprintf(job , stream , global_args); - if (i < (vector_get_size( forward_model->jobs ) - 1)) - fprintf(stream,",\n"); - } - fprintf(stream , "]\n"); - fprintf(stream, "umask = %04o\n", umask); - fclose(stream); - free(module_file); -} - -#undef DEFAULT_JOB_MODULE -#undef DEFAULT_JOBLIST_NAME - - - - -forward_model_type * forward_model_alloc_copy(const forward_model_type * forward_model) { - int ijob; - forward_model_type * new; - - new = forward_model_alloc(forward_model->ext_joblist ); - for (ijob = 0; ijob < vector_get_size(forward_model->jobs); ijob++) { - const ext_job_type * job = vector_iget_const( forward_model->jobs , ijob); - vector_append_owned_ref( new->jobs , ext_job_alloc_copy( job ) , ext_job_free__); - } - - return new; -} - -ext_job_type * forward_model_iget_job( forward_model_type * forward_model , int index) { - return vector_iget( forward_model->jobs , index ); -} - - - -void forward_model_fprintf(const forward_model_type * forward_model , FILE * stream) { - int ijob; - fprintf(stream , " "); - for (ijob = 0; ijob < vector_get_size(forward_model->jobs); ijob++) { - ext_job_fprintf( vector_iget(forward_model->jobs , ijob) , stream); - fprintf(stream , " "); - } - fprintf(stream , "\n"); -} - - -const ext_joblist_type * forward_model_get_joblist(const forward_model_type * forward_model) { - return forward_model->ext_joblist; -} - -int forward_model_get_length( const forward_model_type * forward_model ) { - return vector_get_size( forward_model->jobs ); -} diff --git a/ThirdParty/Ert/libjob_queue/src/job_list.c b/ThirdParty/Ert/libjob_queue/src/job_list.c deleted file mode 100644 index 0c8b1b4fab..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/job_list.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'job_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - - -#define JOB_LIST_TYPE_ID 8154222 - -struct job_list_struct { - UTIL_TYPE_ID_DECLARATION; - int active_size; - int alloc_size; - job_queue_node_type ** jobs; - pthread_rwlock_t lock; -}; - - -UTIL_IS_INSTANCE_FUNCTION( job_list , JOB_LIST_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION( job_list , JOB_LIST_TYPE_ID ) - -job_list_type * job_list_alloc() { - job_list_type * job_list = util_malloc( sizeof * job_list ); - UTIL_TYPE_ID_INIT( job_list , JOB_LIST_TYPE_ID ); - job_list->active_size = 0; - job_list->alloc_size = 0; - job_list->jobs = NULL; - pthread_rwlock_init( &job_list->lock , NULL); - return job_list; -} - - -void job_list_reset( job_list_type * job_list ) { - int queue_index; - for (queue_index = 0; queue_index < job_list->active_size; queue_index++) { - job_queue_node_type * node = job_list_iget_job( job_list , queue_index ); - job_queue_node_free( node ); - job_list->jobs[queue_index] = NULL; - } - job_list->active_size = 0; -} - - -int job_list_get_size( const job_list_type * job_list ) { - return job_list->active_size; -} - - -/* - This takes ownership to the job node instance. -*/ -void job_list_add_job( job_list_type * job_list , job_queue_node_type * job_node ) { - if (job_list->alloc_size == job_list->active_size) { - -#ifdef QUEUE_DEBUG - int new_alloc_size = job_list->alloc_size + 1; - job_queue_node_type ** new_jobs = util_malloc( sizeof * new_jobs * new_alloc_size ); - memcpy( new_jobs , job_list->jobs , sizeof * new_jobs * job_list->active_size ); - free( job_list->jobs ); - job_list->jobs = new_jobs; -#else - int new_alloc_size = util_int_max( 16 , job_list->alloc_size * 2); - job_list->jobs = util_realloc( job_list->jobs , sizeof * job_list->jobs * new_alloc_size ); -#endif - - job_list->alloc_size = new_alloc_size; - } - - { - int queue_index = job_list_get_size( job_list ); - job_queue_node_set_queue_index(job_node, queue_index ); - job_list->jobs[queue_index] = job_node; - } - job_list->active_size++; - -} - - -job_queue_node_type * job_list_iget_job( const job_list_type * job_list , int queue_index) { - if (queue_index >= 0 && queue_index < job_list->active_size) - return job_list->jobs[queue_index]; - else { - util_abort("%s: invalid queue_index:%d Valid range: [0,%d) \n",__func__ , queue_index , queue_index); - return NULL; - } -} - - -void job_list_free( job_list_type * job_list ) { - if (job_list->alloc_size > 0) { - job_list_reset( job_list ); - free( job_list->jobs ); - } - free( job_list ); -} - - - -void job_list_get_wrlock( job_list_type * list) { - pthread_rwlock_wrlock( &list->lock ); -} - -void job_list_get_rdlock( job_list_type * list) { - pthread_rwlock_rdlock( &list->lock ); -} - - -void job_list_unlock( job_list_type * list) { - pthread_rwlock_unlock( &list->lock ); -} - - -void job_list_reader_wait( job_list_type * list, int usleep_time1, int usleep_time2) { - if (pthread_rwlock_tryrdlock( &list->lock ) == 0) { - // Seems to be no writers waiting - take a short sleep and return. - pthread_rwlock_unlock( &list->lock ); - usleep( usleep_time1 ); - } else - // A writer already has the lock - let more writers get access; sleep longer. - usleep( usleep_time2 ); - -} diff --git a/ThirdParty/Ert/libjob_queue/src/job_node.c b/ThirdParty/Ert/libjob_queue/src/job_node.c deleted file mode 100644 index ab9312d2cf..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/job_node.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'job_node.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#define JOB_QUEUE_NODE_TYPE_ID 3315299 -#define INVALID_QUEUE_INDEX -999 - -struct job_queue_node_struct { - UTIL_TYPE_ID_DECLARATION; - int num_cpu; /* How many cpu's will this job need - the driver is free to ignore if not relevant. */ - char *run_cmd; /* The path to the actual executable. */ - char *exit_file; /* The queue will look for the occurence of this file to detect a failure. */ - char *ok_file; /* The queue will look for this file to verify that the job was OK - can be NULL - in which case it is ignored. */ - char *status_file; /* The queue will look for this file to verify that the job is running or has run. */ - char *job_name; /* The name of the job. */ - char *run_path; /* Where the job is run - absolute path. */ - job_callback_ftype *done_callback; - job_callback_ftype *retry_callback; /* To determine if job can be retried */ - job_callback_ftype *exit_callback; /* Callback to perform any cleanup */ - void *callback_arg; - int argc; /* The number of commandline arguments to pass when starting the job. */ - char **argv; /* The commandline arguments. */ - int queue_index; - - /*-----------------------------------------------------------------*/ - char *failed_job; /* Name of the job (in the chain) which has failed. */ - char *error_reason; /* The error message from the failed job. */ - char *stderr_capture; - char *stderr_file; /* Name of the file containing stderr information. */ - /*-----------------------------------------------------------------*/ - - int submit_attempt; /* Which attempt is this ... */ - job_status_type job_status; /* The current status of the job. */ - bool confirmed_running;/* Set to true if file status_file has been detected written. */ - pthread_mutex_t data_mutex; /* Protecting the access to the job_data pointer. */ - void *job_data; /* Driver specific data about this job - fully handled by the driver. */ - time_t submit_time; /* When was the job added to job_queue - the FIRST TIME. */ - time_t sim_start; /* When did the job change status -> RUNNING - the LAST TIME. */ - time_t sim_end ; /* When did the job finish successfully */ - time_t max_confirm_wait;/* Max waiting between sim_start and confirmed_running is 2 minutes */ -}; - - - -void job_queue_node_free_error_info( job_queue_node_type * node ) { - util_safe_free(node->error_reason); - util_safe_free(node->stderr_capture); - util_safe_free(node->stderr_file); - util_safe_free(node->failed_job); -} - - - -/* - When the job script has detected failure it will create a "EXIT" - file in the runpath directory; this function will inspect the EXIT - file and determine which job has failed, the reason the job script - has given to fail the job (typically missing TARGET_FILE) and - capture the stderr from the job. - - The file is XML formatted: - - ------------------------------------------------ - - - Name of job - Reason why the job failed - - Capture of stderr from the job, can typically be - a multiline string. - - - ------------------------------------------------ - - This format is written by the dump_EXIT_file() function in the - job_dispatch.py script. -*/ - -/* - This extremely half-assed XML "parsing" should of course be kept a - secret... -*/ - -static char * __alloc_tag_content( const char * xml_buffer , const char * tag) { - char * open_tag = util_alloc_sprintf("<%s>" , tag); - char * close_tag = util_alloc_sprintf("" , tag); - - char * start_ptr = strstr( xml_buffer , open_tag ); - char * end_ptr = strstr( xml_buffer , close_tag ); - char * tag_content = NULL; - - if ((start_ptr != NULL) && (end_ptr != NULL)) { - int length; - start_ptr += strlen(open_tag); - - length = end_ptr - start_ptr; - tag_content = util_alloc_substring_copy( start_ptr , 0 , length ); - } - - free( open_tag ); - free( close_tag ); - return tag_content; -} - - - - -/** - This code is meant to capture which of the jobs has failed; why it - has failed and the stderr stream of the failing job. Depending on - the failure circumstances the EXIT file might not be around. -*/ - -void job_queue_node_fscanf_EXIT( job_queue_node_type * node ) { - job_queue_node_free_error_info( node ); - if (node->exit_file) { - if (util_file_exists( node->exit_file )) { - char * xml_buffer = util_fread_alloc_file_content( node->exit_file, NULL); - - node->failed_job = __alloc_tag_content( xml_buffer , "job" ); - node->error_reason = __alloc_tag_content( xml_buffer , "reason" ); - node->stderr_capture = __alloc_tag_content( xml_buffer , "stderr"); - node->stderr_file = __alloc_tag_content( xml_buffer , "stderr_file"); - - free( xml_buffer ); - } else - node->failed_job = util_alloc_sprintf("EXIT file:%s not found - load failure?" , node->exit_file); - } -} - - - - - - -UTIL_IS_INSTANCE_FUNCTION( job_queue_node , JOB_QUEUE_NODE_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION( job_queue_node , JOB_QUEUE_NODE_TYPE_ID ) - - - -int job_queue_node_get_queue_index( const job_queue_node_type * node ) { - if (node->queue_index == INVALID_QUEUE_INDEX) - util_abort("%s: internal error: asked for not-yet-initialized node->queue_index\n",__func__); - return node->queue_index; -} - -void job_queue_node_set_queue_index( job_queue_node_type * node , int queue_index) { - if (node->queue_index == INVALID_QUEUE_INDEX) - node->queue_index = queue_index; - else - util_abort("%s: internal error: atteeempt to reset queue_index \n",__func__); -} - - -/* - The error information is retained even after the job has completed - completely, so that calling scope can ask for it - that is the - reason there are separate free() and clear functions for the error related fields. -*/ - -void job_queue_node_free_data(job_queue_node_type * node) { - util_safe_free( node->job_name ); - util_safe_free( node->exit_file ); - util_safe_free( node->ok_file ); - util_safe_free( node->run_cmd ); - util_free_stringlist( node->argv , node->argc ); - - if (node->job_data != NULL) - util_abort("%s: internal error - driver spesific job data has not been freed - will leak.\n",__func__); -} - - -void job_queue_node_free(job_queue_node_type * node) { - job_queue_node_free_data(node); - job_queue_node_free_error_info(node); - util_safe_free(node->run_path); - - // Since the type of the callback_arg is void* it should maybe be - // registered with a private destructor - or the type should be - // changed to arg_pack? - if (arg_pack_is_instance( node->callback_arg )) - arg_pack_free( node->callback_arg ); - - free(node); -} - - -job_status_type job_queue_node_get_status(const job_queue_node_type * node) { - return node->job_status; -} - - - - - - -/******************************************************************/ -/* - These four functions all require that the caller has aquired the - data lock before entering. -*/ - - - - - -void job_queue_node_reset_submit_attempt( job_queue_node_type * node) { - node->submit_attempt = 0; -} - -int job_queue_node_get_submit_attempt( const job_queue_node_type * node) { - return node->submit_attempt; -} - - - - - - - - - -job_queue_node_type * job_queue_node_alloc_simple( const char * job_name , - const char * run_path , - const char * run_cmd , - int argc , - const char ** argv) { - return job_queue_node_alloc( job_name , run_path , run_cmd , argc , argv , 1, NULL , NULL, NULL, NULL, NULL, NULL, NULL); -} - - -job_queue_node_type * job_queue_node_alloc( const char * job_name , - const char * run_path , - const char * run_cmd , - int argc , - const char ** argv, - int num_cpu, - const char * ok_file, - const char * status_file, - const char * exit_file, - job_callback_ftype * done_callback, - job_callback_ftype * retry_callback, - job_callback_ftype * exit_callback, - void * callback_arg) { - - if (util_is_directory( run_path )) { - job_queue_node_type * node = util_malloc(sizeof * node ); - - UTIL_TYPE_ID_INIT( node , JOB_QUEUE_NODE_TYPE_ID ); - { - /* The data initialized in this block should *NEVER* change. */ - node->job_name = util_alloc_string_copy( job_name ); - - if (util_is_abs_path(run_path)) - node->run_path = util_alloc_string_copy( run_path ); - else - node->run_path = util_alloc_realpath( run_path ); - - node->run_cmd = util_alloc_string_copy( run_cmd ); - node->argc = argc; - node->argv = util_alloc_stringlist_copy( argv , argc ); - node->num_cpu = num_cpu; - - if (ok_file) - node->ok_file = util_alloc_filename(node->run_path , ok_file , NULL); - else - node->ok_file = NULL; - - if (status_file) - node->status_file = util_alloc_filename(node->run_path , status_file , NULL); - else - node->status_file = NULL; - node->confirmed_running = false; - - if (exit_file) - node->exit_file = util_alloc_filename(node->run_path , exit_file , NULL); - else - node->exit_file = NULL; - - node->exit_callback = exit_callback; - node->retry_callback = retry_callback; - node->done_callback = done_callback; - node->callback_arg = callback_arg; - } - { - node->error_reason = NULL; - node->stderr_capture = NULL; - node->stderr_file = NULL; - node->failed_job = NULL; - } - { - node->job_status = JOB_QUEUE_NOT_ACTIVE; - node->queue_index = INVALID_QUEUE_INDEX; - node->submit_attempt = 0; - node->job_data = NULL; /* The allocation is run in single thread mode - we assume. */ - node->sim_start = 0; - node->sim_end = 0; - node->submit_time = time( NULL ); - node->max_confirm_wait= 60*2; /* 2 minutes before we consider job dead. */ - } - - pthread_mutex_init( &node->data_mutex , NULL ); - return node; - } else - return NULL; -} - - -const char * job_queue_node_get_error_reason( const job_queue_node_type * node) { - return node->error_reason; -} - -const char * job_queue_node_get_stderr_capture( const job_queue_node_type * node) { - return node->stderr_capture; -} - - -const char * job_queue_node_get_stderr_file( const job_queue_node_type * node) { - return node->stderr_file; -} - - -const char * job_queue_node_get_exit_file( const job_queue_node_type * node) { - return node->exit_file; -} - - -const char * job_queue_node_get_ok_file( const job_queue_node_type * node) { - return node->ok_file; -} - -const char * job_queue_node_get_status_file( const job_queue_node_type * node) { - return node->status_file; -} - -const char * job_queue_node_get_run_path( const job_queue_node_type * node) { - return node->run_path; -} - -const char * job_queue_node_get_name( const job_queue_node_type * node) { - return node->job_name; -} - -const char * job_queue_node_get_failed_job( const job_queue_node_type * node) { - return node->failed_job; -} - - -time_t job_queue_node_get_sim_start( const job_queue_node_type * node ) { - return node->sim_start; -} - - -time_t job_queue_node_get_sim_end( const job_queue_node_type * node ) { - return node->sim_end; -} - -time_t job_queue_node_get_submit_time( const job_queue_node_type * node ) { - return node->submit_time; -} - -double job_queue_node_time_since_sim_start (const job_queue_node_type * node ) { - return util_difftime_seconds( node->sim_start , time(NULL)); -} - -bool job_queue_node_run_DONE_callback( job_queue_node_type * node ) { - bool OK = true; - if (node->done_callback) - OK = node->done_callback( node->callback_arg ); - - return OK; -} - - -bool job_queue_node_run_RETRY_callback( job_queue_node_type * node ) { - bool retry = false; - if (node->retry_callback) - retry = node->retry_callback( node->callback_arg ); - - return retry; -} - - -void job_queue_node_run_EXIT_callback( job_queue_node_type * node ) { - if (node->exit_callback) - node->exit_callback( node->callback_arg ); -} - -static void job_queue_node_set_status(job_queue_node_type * node , job_status_type new_status) { - if (new_status != node->job_status) { - node->job_status = new_status; - - /* - We record sim start when the node is in state JOB_QUEUE_WAITING - to be sure that we do not miss the start time completely for - very fast jobs which are registered in the state - JOB_QUEUE_RUNNING. - */ - if (new_status == JOB_QUEUE_WAITING) - node->sim_start = time( NULL ); - - if (new_status == JOB_QUEUE_RUNNING) - node->sim_start = time( NULL ); - - if (new_status == JOB_QUEUE_SUCCESS) - node->sim_end = time( NULL ); - - if (new_status == JOB_QUEUE_FAILED) - job_queue_node_fscanf_EXIT( node ); - - } -} - - -submit_status_type job_queue_node_submit( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver) { - submit_status_type submit_status; - pthread_mutex_lock( &node->data_mutex ); - { - void * job_data = queue_driver_submit_job( driver, - node->run_cmd, - node->num_cpu, - node->run_path, - node->job_name, - node->argc, - (const char **) node->argv); - if (job_data != NULL) { - job_status_type old_status = node->job_status; - job_status_type new_status = JOB_QUEUE_SUBMITTED; - - node->job_data = job_data; - node->submit_attempt++; - /* - The status JOB_QUEUE_SUBMITTED is internal, and not - exported anywhere. The job_queue_update_status() will - update this to PENDING or RUNNING at the next call. The - important difference between SUBMITTED and WAITING is - that SUBMITTED have job_data != NULL and the - job_queue_node free function must be called on it. - */ - submit_status = SUBMIT_OK; - job_queue_node_set_status( node , new_status); - job_queue_status_transition(status, old_status, new_status); - } else - /* - In this case the status of the job itself will be - unmodified; i.e. it will still be WAITING, and a new attempt - to submit it will be performed in the next round. - */ - submit_status = SUBMIT_DRIVER_FAIL; - } - pthread_mutex_unlock( &node->data_mutex ); - return submit_status; -} - -static bool job_queue_node_status_update_confirmed_running__(job_queue_node_type * node) { - if (node->confirmed_running) - return true; - - if (!node->status_file) { - node->confirmed_running = true; - return true; - } - - if (util_file_exists(node->status_file)) - node->confirmed_running = true; - return node->confirmed_running; -} - -// if status = running, and current_time > sim_start + max_confirm_wait -// (usually 2 min), check if job is confirmed running (status_file exists). -// If not confirmed, set job to JOB_QUEUE_FAILED. -bool job_queue_node_update_status( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver ) { - bool status_change = false; - pthread_mutex_lock(&node->data_mutex); - { - if (node->job_data) { - job_status_type current_status = job_queue_node_get_status(node); - - bool confirmed = job_queue_node_status_update_confirmed_running__(node); - - if ((current_status & JOB_QUEUE_RUNNING) && !confirmed) { - // it's running, but not confirmed running. - double runtime = job_queue_node_time_since_sim_start(node); - if (runtime >= node->max_confirm_wait) { - // max_confirm_wait has passed since sim_start without success; the job is dead - job_status_type new_status = JOB_QUEUE_DO_KILL_NODE_FAILURE; - status_change = job_queue_status_transition(status, current_status, new_status); - job_queue_node_set_status(node, new_status); - } - } - current_status = job_queue_node_get_status(node); - if (current_status & JOB_QUEUE_CAN_UPDATE_STATUS) { - job_status_type new_status = queue_driver_get_status( driver , node->job_data); - status_change = job_queue_status_transition(status , current_status , new_status); - job_queue_node_set_status(node,new_status); - } - } - } - pthread_mutex_unlock( &node->data_mutex ); - return status_change; -} - -bool job_queue_node_status_transition( job_queue_node_type * node , job_queue_status_type * status , job_status_type new_status) { - bool status_change; - pthread_mutex_lock( &node->data_mutex ); - { - job_status_type old_status = job_queue_node_get_status( node ); - status_change = job_queue_status_transition(status , old_status, new_status); - - if (status_change) - job_queue_node_set_status( node , new_status ); - } - pthread_mutex_unlock( &node->data_mutex ); - return status_change; -} - -void job_queue_node_set_max_confirmation_wait_time(job_queue_node_type * node, time_t time) { - node->max_confirm_wait = time; -} - - -bool job_queue_node_status_confirmed_running(job_queue_node_type * node) { - return node->confirmed_running; -} - - -bool job_queue_node_kill( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver) { - bool result = false; - pthread_mutex_lock( &node->data_mutex ); - { - job_status_type current_status = job_queue_node_get_status( node ); - if (current_status & JOB_QUEUE_CAN_KILL) { - /* - If the job is killed before it is even started no driver - specific job data has been assigned; we therefor must check - the node->job_data pointer before entering. - */ - if (node->job_data) { - queue_driver_kill_job( driver , node->job_data ); - queue_driver_free_job( driver , node->job_data ); - node->job_data = NULL; - } - job_queue_status_transition(status, current_status, JOB_QUEUE_IS_KILLED); - job_queue_node_set_status( node , JOB_QUEUE_IS_KILLED); - result = true; - } - } - pthread_mutex_unlock( &node->data_mutex ); - return result; -} - - -/* - This frees the storage allocated by the driver - the storage - allocated by the queue layer is retained. - - In the case of jobs which are first marked as successfull by the - queue layer, and then subsequently set to status EXIT by the - DONE_callback this function will be called twice; i.e. we must - protect against a double free. -*/ - -void job_queue_node_free_driver_data( job_queue_node_type * node , queue_driver_type * driver) { - pthread_mutex_lock( &node->data_mutex ); - { - if (node->job_data != NULL) - queue_driver_free_job( driver , node->job_data ); - node->job_data = NULL; - } - pthread_mutex_unlock( &node->data_mutex ); -} - - -/* - This returns a pointer to a very internal datastructure; used by the - Job class in Python which interacts directly with the driver - implementation. This is too low level, and the whole Driver / Job - implementation in Python should be changed to only expose the higher - level queue class. -*/ - -void * job_queue_node_get_driver_data( job_queue_node_type * node ) { - return node->job_data; -} - - -void job_queue_node_restart( job_queue_node_type * node , job_queue_status_type * status) { - pthread_mutex_lock( &node->data_mutex ); - { - job_status_type current_status = job_queue_node_get_status( node ); - job_queue_status_transition(status, current_status, JOB_QUEUE_WAITING); - job_queue_node_set_status( node , JOB_QUEUE_WAITING); - job_queue_node_reset_submit_attempt(node); - } - pthread_mutex_unlock( &node->data_mutex ); -} diff --git a/ThirdParty/Ert/libjob_queue/src/job_queue.c b/ThirdParty/Ert/libjob_queue/src/job_queue.c deleted file mode 100644 index f24aa0cf2f..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/job_queue.c +++ /dev/null @@ -1,1357 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'job_queue.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -/** - - The running of external jobs is handled thruogh an abstract - job_queue implemented in this file; the job_queue then contains a - 'driver' which actually runs the job. All drivers must support the - following functions - - submit: This will submit a job, and return a pointer to a - newly allocated queue_job instance. - - clean: This will clear up all resources used by the job. - - abort: This will stop the job, and then call clean. - - status: This will get the status of the job. - - - When calling the various driver functions the queue layer needs to - dereference the driver structures, i.e. to get access to the - driver->submit_jobs function. This is currently (rather clumsily?? - implemented like this): - - When implementing a driver the driver struct MUST start like - this: - - struct some_driver { - UTIL_TYPE_ID_DECLARATION - QUEUE_DRIVER_FUNCTIONS - .... - .... - } - - The function allocating a driver instance will just return a - (void *) however in the queue layer the driver is stored as a - queue_driver_type instance which is a struct like this: - - struct queue_driver_struct { - UTIL_TYPE_ID_DECLARATION - QUEUE_DRIVER_FIELDS - } - - I.e. it only contains the pointers common to all the driver - implementations. When calling a driver function the spesific - driver will cast to it's datatype. - - Observe that this library also contains the files ext_joblist and - ext_job, those files implement a particular way of dispatching - external jobs in a series; AFTER THEY HAVE BEEN SUBMITTED. So seen - from the this scope those files do not provide any particluar - functionality; there is no compile-time dependencies either. -*/ - - - -/* - Some words about status - ======================= - - The status of a particular job is given by the job_status field of - the job_queue_node_type, the possible values are given by the enum - job_status_type, defined in queue_driver.h. - - To actually __GET__ the status of a job we use the driver->status() - function which will invoke a driver specific function and return the - new status. - - 1. The driver->status() function is invoked by the - job_queue_update_status() function. This should be invoked by - the same thread as is running the main queue management in - job_queue_run_jobs(). - - - 2. The actual change of status is handled by the function - job_queue_change_node_status(); arbitrary assignments of the - type job->status = new_status is STRICTLY ILLEGAL. - - - 3. When external functions query about the status of a particular - job they get the status value currently stored (i.e. cached) in - the job_node; external scope can NOT initiate a - driver->status() function call. - - This might result in external scope getting a outdated status - - live with it. - - - 4. The name 'status' indicates that this is read-only property; - that is actually not the case. In the main manager function - job_queue_run_jobs() action is taken based on the value of the - status field, and to initiate certain action on jobs the queue - system (and also external scope) can explicitly set the status - of a job (by using the job_queue_change_node_status() function). - - The most promiment example of this is when we want to run a - certain job again, that is achieved with: - - job_queue_node_change_status( queue , node , JOB_QUEUE_WAITING ); - - When the queue manager subsequently finds the job with status - 'JOB_QUEUE_WAITING' it will (re)submit this job. -*/ - - - -/* - Communicating success/failure between the job_script and the job_queue: - ======================================================================= - - The system for communicatin success/failure between the queue system - (i.e. this file) and the job script is quite elaborate. There are - essentially three problems which make this complicated: - - 1. The exit status of the jobs is NOT reliably captured - the job - might very well fail without us detecing it with the exit - status. - - 2. Syncronizing of disks can be quite slow, so altough a job has - completede successfully the files we expect to find might not - present. - - 3. There is layer upon layer here - this file scope (i.e. the - internal queue_system) spawns external jobs in the form of a job - script. This script again spawns a series of real external jobs - like e.g. ECLIPSE and RMS. The job_script does not reliably - capture the exit status of the external programs. - - - The approach to this is as follows: - - 1. If the job (i.e. the job script) finishes with a failure status - we communicate the failure back to the calling scope with no - more ado. - - 2. When a job has finished (seemingly OK) we try hard to determine - whether the job has failed or not. This is based on the - following tests: - - a) If the job has produced an EXIT file it has failed. - - b) If the job has produced an OK file it has succeeded. - - c) If neither EXIT nor OK files have been produced we spin for a - while waiting for one of the files, if none turn up we will - eventually mark the job as failed. - -*/ - - - - - -/** - This struct holds the job_queue information about one job. Observe - the following: - - 1. This struct is purely static - i.e. it is invisible outside of - this file-scope. - - 2. Typically the driver would like to store some additional - information, i.e. the PID of the running process for the local - driver; that is stored in a (driver specific) struct under the - field job_data. - - 3. If the driver detects that a job has failed it leaves an EXIT - file, the exit status is (currently) not reliably transferred - back to to the job_queue layer. - -*/ - -/*****************************************************************/ - -#define JOB_QUEUE_TYPE_ID 665210 - -struct job_queue_struct { - UTIL_TYPE_ID_DECLARATION; - job_list_type * job_list; - job_queue_status_type * status; - char * exit_file; /* The queue will look for the occurence of this file to detect a failure. */ - char * ok_file; /* The queue will look for this file to verify that the job was OK - can be NULL - in which case it is ignored. */ - char * status_file; /* The queue will look for this file to verify that the job is running or has run. If not, ok_file is ignored. */ - queue_driver_type * driver; /* A pointer to a driver instance (LSF|LOCAL|RSH) which actually 'does it'. */ - - bool open; /* True if the queue has been reset and is ready for use, false if the queue has been used and not reset */ - bool user_exit; /* If there comes an external signal to abondond the whole thing user_exit will be set to true, and things start to dwindle down. */ - bool running; - bool pause_on; - bool submit_complete; - - int max_submit; /* The maximum number of submit attempts for one job. */ - int max_ok_wait_time; /* Seconds to wait for an OK file - when the job itself has said all OK. */ - int max_duration; /* Maximum allowed time for a job to run, 0 = unlimited */ - time_t stop_time; /* A job is only allowed to run until this time. 0 = no time set, ignore stop_time */ - unsigned long usleep_time; /* The sleep time before checking for updates. */ - pthread_mutex_t run_mutex; /* This mutex is used to ensure that ONLY one thread is executing the job_queue_run_jobs(). */ - thread_pool_type * work_pool; -}; - - - - - - -/* - Must hold on to: - - 1. A write lock for the job node. - 3. A read lock for the job_list - -*/ -static bool job_queue_change_node_status(job_queue_type * queue , job_queue_node_type * node , job_status_type new_status) { - return job_queue_node_status_transition( node , queue->status , new_status ); -} - - - - -/*****************************************************************/ - - - - - - - -/** - Observe that this function should only query the driver for state - change when the job is currently in one of the states: - - JOB_QUEUE_WAITING || JOB_QUEUE_PENDING || JOB_QUEUE_RUNNING - - The other state transitions are handled by the job_queue itself, - without consulting the driver functions. -*/ - -/* - Will return true if there is any status change. Must already hold - on to joblist readlock -*/ - -static bool job_queue_update_status(job_queue_type * queue ) { - bool update = false; - int ijob; - - for (ijob = 0; ijob < job_list_get_size( queue->job_list ); ijob++) { - job_queue_node_type * node = job_list_iget_job( queue->job_list , ijob ); - bool node_update = job_queue_node_update_status( node , queue->status , queue->driver ); - if (node_update) - update = true; - } - return update; -} - -/* - Must hold on to joblist readlock -*/ - -static submit_status_type job_queue_submit_job(job_queue_type * queue , int queue_index) { - submit_status_type submit_status; - if (queue->user_exit || queue->pause_on) - submit_status = SUBMIT_QUEUE_CLOSED; /* The queue is currently not accepting more jobs. */ - else { - { - job_queue_node_type * node = job_list_iget_job( queue->job_list , queue_index ); - submit_status = job_queue_node_submit( node , queue->status , queue->driver ); - } - } - return submit_status; -} - - - - - - - - - -/** - Will return the number of jobs with status @status. - - #include - - printf("Running jobs...: %03d \n", job_queue_iget_status_summary( queue , JOB_QUEUE_RUNNING )); - printf("Waiting jobs:..: %03d \n", job_queue_iget_status_summary( queue , JOB_QUEUE_WAITING )); - - Observe that if this function is called repeatedly the status might change between - calls, with the consequence that the total number of jobs does not add up - properly. The handles itself autonomously so as long as the return value from this - function is only used for information purposes this does not matter. Alternatively - the function job_queue_export_status_summary(), which does proper locking, can be - used. -*/ - -int job_queue_iget_status_summary( const job_queue_type * queue , job_status_type status) { - return job_queue_status_get_count(queue->status, status); -} - -int job_queue_get_num_callback( const job_queue_type * queue) { - return job_queue_iget_status_summary( queue , JOB_QUEUE_RUNNING_CALLBACK ); -} - -int job_queue_get_num_running( const job_queue_type * queue) { - return job_queue_iget_status_summary( queue , JOB_QUEUE_RUNNING ); -} - -int job_queue_get_num_pending( const job_queue_type * queue) { - return job_queue_iget_status_summary( queue , JOB_QUEUE_PENDING ); -} - -int job_queue_get_num_waiting( const job_queue_type * queue) { - return job_queue_iget_status_summary( queue , JOB_QUEUE_WAITING ); -} - -int job_queue_get_num_complete( const job_queue_type * queue) { - return job_queue_iget_status_summary( queue , JOB_QUEUE_SUCCESS ); -} - -int job_queue_get_num_failed( const job_queue_type * queue) { - return job_queue_iget_status_summary( queue , JOB_QUEUE_FAILED ); -} - -int job_queue_get_num_killed( const job_queue_type * queue) { - return job_queue_iget_status_summary( queue , JOB_QUEUE_IS_KILLED ); -} - -int job_queue_get_active_size( const job_queue_type * queue ) { - return job_list_get_size( queue->job_list ); -} - -void job_queue_set_max_job_duration(job_queue_type * queue, int max_duration_seconds) { - queue->max_duration = max_duration_seconds; -} - -int job_queue_get_max_job_duration(const job_queue_type * queue) { - return queue->max_duration; -} - -void job_queue_set_job_stop_time(job_queue_type * queue, time_t time) { - queue->stop_time = time; -} - -time_t job_queue_get_job_stop_time(const job_queue_type * queue) { - return queue->stop_time; -} - -void job_queue_set_auto_job_stop_time(job_queue_type * queue) { - time_t sum_run_time_succeded_jobs = 0; - int num_succeded_jobs = 0; - - for (int i = 0; i < job_list_get_size( queue->job_list ); i++) { - if (job_queue_iget_job_status(queue,i) == JOB_QUEUE_SUCCESS) { - sum_run_time_succeded_jobs += difftime(job_queue_iget_sim_end(queue, i), job_queue_iget_sim_start(queue, i)); - num_succeded_jobs++; - } - } - - if (num_succeded_jobs > 0) { - time_t avg_run_time_succeded_jobs = sum_run_time_succeded_jobs / num_succeded_jobs; - time_t stop_time = time(NULL) + (avg_run_time_succeded_jobs * 0.25); - job_queue_set_job_stop_time(queue, stop_time); - } -} - -/** - Observe that jobs with status JOB_QUEUE_WAITING can also be killed; for those - jobs the kill should be interpreted as "Forget about this job for now and set - the status JOB_QUEUE_IS_KILLED", however it is important that we not call - the driver->kill() function on it because the job slot will have no data - (i.e. LSF jobnr), and the driver->kill() function will fail if presented with - such a job. - - Only jobs which have a status matching "JOB_QUEUE_CAN_KILL" can be - killed; if the job is not in a killable state the function will do - nothing. This includes trying to kill a job which is not even - found. - - Observe that jobs (slots) with status JOB_QUEUE_NOT_ACTIVE can NOT be - meaningfully killed; that is because these jobs have not yet been submitted - to the queue system, and there is not yet established a mapping between - external id and queue_index. - - Must hold on to joblist:read lock. -*/ - -static bool job_queue_kill_job_node( job_queue_type * queue , job_queue_node_type * node) { - bool result = job_queue_node_kill( node , queue->status , queue->driver ); - return result; -} - -#define ASSIGN_LOCKED_ATTRIBUTE( var , func , ...) \ -job_list_get_rdlock( queue->job_list ); \ -{ \ - job_queue_node_type * node = job_list_iget_job( queue->job_list , job_index ); \ - var = func(__VA_ARGS__); \ -} \ -job_list_unlock( queue->job_list ); - - - -bool job_queue_kill_job( job_queue_type * queue , int job_index) { - bool result; - ASSIGN_LOCKED_ATTRIBUTE( result , job_queue_kill_job_node , queue , node); - return result; -} - - -time_t job_queue_iget_sim_start( job_queue_type * queue, int job_index) { - time_t sim_start; - ASSIGN_LOCKED_ATTRIBUTE( sim_start , job_queue_node_get_sim_start , node ); - return sim_start; -} - - -time_t job_queue_iget_sim_end( job_queue_type * queue, int job_index) { - time_t sim_end; - ASSIGN_LOCKED_ATTRIBUTE( sim_end , job_queue_node_get_sim_end , node ); - return sim_end; -} - - -time_t job_queue_iget_submit_time( job_queue_type * queue, int job_index) { - time_t submit_time; - ASSIGN_LOCKED_ATTRIBUTE( submit_time , job_queue_node_get_submit_time , node ); - return submit_time; -} - -const char * job_queue_iget_run_path( job_queue_type * queue , int job_index) { - const char * run_path; - ASSIGN_LOCKED_ATTRIBUTE(run_path, job_queue_node_get_run_path, node ); - return run_path; -} - - -const char * job_queue_iget_failed_job( job_queue_type * queue , int job_index) { - const char * failed_job; - ASSIGN_LOCKED_ATTRIBUTE(failed_job, job_queue_node_get_failed_job, node ); - return failed_job; -} - - -const char * job_queue_iget_error_reason( job_queue_type * queue , int job_index) { - const char * error_reason; - ASSIGN_LOCKED_ATTRIBUTE(error_reason, job_queue_node_get_error_reason, node ); - return error_reason; -} - - -const char * job_queue_iget_stderr_capture( job_queue_type * queue , int job_index) { - const char * stderr_capture; - ASSIGN_LOCKED_ATTRIBUTE(stderr_capture, job_queue_node_get_stderr_capture, node ); - return stderr_capture; -} - - -const char * job_queue_iget_stderr_file( job_queue_type * queue , int job_index) { - const char * stderr_file; - ASSIGN_LOCKED_ATTRIBUTE(stderr_file, job_queue_node_get_stderr_file, node ); - return stderr_file; -} - - - -job_status_type job_queue_iget_job_status( job_queue_type * queue , int job_index) { - job_status_type job_status; - ASSIGN_LOCKED_ATTRIBUTE(job_status, job_queue_node_get_status , node ); - return job_status; -} - - -void job_queue_iset_max_confirm_wait_time(job_queue_type * queue, int job_index, time_t time) { - job_list_get_rdlock( queue->job_list ); - { - job_queue_node_type * node = job_list_iget_job( queue->job_list , job_index ); - job_queue_node_set_max_confirmation_wait_time( node, time ); - } - job_list_unlock( queue->job_list ); -} - - - - -/** - The external scope asks the queue to restart the the job; we reset - the submit counter to zero. This function should typically be used - in combination with resampling, however that is the responsability - of the calling scope. -*/ - -void job_queue_iset_external_restart(job_queue_type * queue , int job_index) { - job_list_get_rdlock( queue->job_list ); - { - job_queue_node_type * node = job_list_iget_job( queue->job_list , job_index ); - job_queue_node_restart(node,queue->status); - } - job_list_unlock( queue->job_list ); -} - - -/** - The queue system has said that the job completed OK, however the - external scope failed to load all the results and are using this - function to inform the queue system that the job has indeed - failed. The queue system will then either retry the job, or switch - status to JOB_QUEUE_RUN_FAIL. - - - This is a bit dangerous beacuse the queue system has said that the - job was all hunkadory, and freed the driver related resources - attached to the job; it is therefor essential that the - JOB_QUEUE_EXIT code explicitly checks the status of the job node's - driver specific data before dereferencing. -*/ - -void job_queue_iset_external_fail(job_queue_type * queue , int job_index) { - job_list_get_rdlock( queue->job_list ); - { - job_queue_node_type * node = job_list_iget_job( queue->job_list , job_index ); - job_queue_node_status_transition(node,queue->status,JOB_QUEUE_EXIT); - } - job_list_unlock( queue->job_list ); -} - - -/* - This returns a pointer to a very internal datastructure; used by the - Job class in Python which interacts directly with the driver - implementation. This is too low level, and the whole Driver / Job - implementation in Python should be changed to only expose the higher - level queue class. -*/ - -void * job_queue_iget_driver_data( job_queue_type * queue , int job_index) { - void * driver_data; - ASSIGN_LOCKED_ATTRIBUTE(driver_data, job_queue_node_get_driver_data , node ); - return driver_data; -} - - - - -static void job_queue_update_spinner( int * phase ) { - const char * spinner = "-\\|/"; - int spinner_length = strlen( spinner ); - - printf("%c\b" , spinner[ (*phase % spinner_length) ]); - fflush(stdout); - (*phase) += 1; -} - - -static void job_queue_print_summary(job_queue_type *queue, bool status_change ) { - const char * status_fmt = "Waiting: %3d Pending: %3d Running: %3d Checking/Loading: %3d Failed: %3d Complete: %3d [ ]\b\b"; - int string_length = 105; - - if (status_change) { - for (int i=0; i < string_length; i++) - printf("\b"); - - { - int waiting = job_queue_status_get_count( queue->status , JOB_QUEUE_WAITING ); - int pending = job_queue_status_get_count( queue->status , JOB_QUEUE_PENDING ); - - /* - EXIT and DONE are included in "xxx_running", because the target - file has not yet been checked. - */ - int running = job_queue_status_get_count( queue->status , JOB_QUEUE_RUNNING ) + - job_queue_status_get_count( queue->status , JOB_QUEUE_DONE ) + - job_queue_status_get_count( queue->status , JOB_QUEUE_EXIT ); - int complete = job_queue_status_get_count( queue->status , JOB_QUEUE_SUCCESS ); - int failed = job_queue_status_get_count( queue->status , JOB_QUEUE_FAILED ) + - job_queue_status_get_count( queue->status , JOB_QUEUE_IS_KILLED ); - int loading = job_queue_status_get_count( queue->status , JOB_QUEUE_RUNNING_CALLBACK ); - - printf(status_fmt , waiting , pending , running , loading , failed , complete); - } - } -} - - - - - -/** - This function goes through all the nodes and call finalize on - them. What about jobs which were NOT in a CAN_KILL state when the - killing was done, i.e. jobs which are in one of the intermediate - load like states?? They -*/ - -void job_queue_reset(job_queue_type * queue) { - job_list_get_wrlock( queue->job_list ); - job_list_reset( queue->job_list ); - job_list_unlock( queue->job_list ); - job_queue_status_clear(queue->status); - - /* - Be ready for the next run - */ - queue->submit_complete = false; - queue->pause_on = false; - queue->user_exit = false; - queue->open = true; - queue->stop_time = 0; -} - - -bool job_queue_is_running( const job_queue_type * queue ) { - return queue->running; -} - - -static void job_queue_user_exit__( job_queue_type * queue ) { - int queue_index; - for (queue_index = 0; queue_index < job_list_get_size( queue->job_list ); queue_index++) { - job_queue_node_type * node = job_list_iget_job( queue->job_list , queue_index ); - - if (JOB_QUEUE_CAN_KILL & job_queue_node_get_status(node)) - job_queue_node_status_transition(node,queue->status,JOB_QUEUE_DO_KILL); - } -} - - -static bool job_queue_check_node_status_files( const job_queue_type * job_queue , job_queue_node_type * node) { - const char * exit_file = job_queue_node_get_exit_file( node ); - if ((exit_file != NULL) && util_file_exists(exit_file)) - return false; /* It has failed. */ - else { - const char * ok_file = job_queue_node_get_ok_file( node ); - if (ok_file == NULL) - return true; /* If the ok-file has not been set we just return true immediately. */ - else { - int ok_sleep_time = 1; /* Time to wait between checks for OK|EXIT file. */ - int total_wait_time = 0; - - while (true) { - if (util_file_exists( ok_file )) { - return true; - break; - } else { - if (total_wait_time < job_queue->max_ok_wait_time) { - sleep( ok_sleep_time ); - total_wait_time += ok_sleep_time; - } else { - /* We have waited long enough - this does not seem to give any OK file. */ - return false; - break; - } - } - } - } - } -} - - -static void * job_queue_run_DONE_callback( void * arg ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - job_queue_type * job_queue = arg_pack_iget_ptr( arg_pack , 0 ); - int queue_index = arg_pack_iget_int( arg_pack , 1 ); - job_list_get_rdlock( job_queue->job_list ); - { - job_queue_node_type * node = job_list_iget_job( job_queue->job_list , queue_index ); - bool OK = job_queue_check_node_status_files( job_queue , node ); - - if (OK) - OK = job_queue_node_run_DONE_callback( node ); - - if (OK) - job_queue_change_node_status( job_queue , node , JOB_QUEUE_SUCCESS ); - else - job_queue_change_node_status( job_queue , node , JOB_QUEUE_EXIT ); - - job_queue_node_free_driver_data( node , job_queue->driver ); - } - job_list_unlock(job_queue->job_list ); - arg_pack_free( arg_pack ); - return NULL; -} - -static void job_queue_handle_DONE( job_queue_type * queue , job_queue_node_type * node) { - job_queue_change_node_status(queue , node , JOB_QUEUE_RUNNING_CALLBACK ); - { - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr( arg_pack , queue ); - arg_pack_append_int( arg_pack , job_queue_node_get_queue_index(node)); - thread_pool_add_job( queue->work_pool , job_queue_run_DONE_callback , arg_pack ); - } -} - - -static void * job_queue_run_EXIT_callback( void * arg ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - job_queue_type * job_queue = arg_pack_iget_ptr( arg_pack , 0 ); - int queue_index = arg_pack_iget_int( arg_pack , 1 ); - - job_list_get_rdlock( job_queue->job_list ); - { - job_queue_node_type * node = job_list_iget_job( job_queue->job_list , queue_index ); - - if (job_queue_node_get_submit_attempt( node ) < job_queue->max_submit) - job_queue_change_node_status( job_queue , node , JOB_QUEUE_WAITING ); /* The job will be picked up for antother go. */ - else { - bool retry = job_queue_node_run_RETRY_callback( node ); - - if (retry) { - /* OK - we have invoked the retry_callback() - and that has returned true; - giving this job a brand new start. */ - job_queue_node_reset_submit_attempt( node ); - job_queue_change_node_status(job_queue , node , JOB_QUEUE_WAITING); - } else { - // It's time to call it a day - - job_queue_node_run_EXIT_callback( node ); - job_queue_change_node_status(job_queue , node , JOB_QUEUE_FAILED); - } - } - job_queue_node_free_driver_data( node , job_queue->driver ); - } - job_list_unlock(job_queue->job_list ); - arg_pack_free( arg_pack ); - - return NULL; -} - - -static void * job_queue_run_DO_KILL_callback( void * arg ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - job_queue_type * job_queue = arg_pack_iget_ptr( arg_pack , 0 ); - int queue_index = arg_pack_iget_int( arg_pack , 1 ); - - job_list_get_rdlock( job_queue->job_list ); - { - job_queue_node_type * node = job_list_iget_job( job_queue->job_list , queue_index ); - job_queue_node_free_driver_data( node , job_queue->driver ); - - // It's time to call it a day - job_queue_node_run_EXIT_callback( node ); - job_queue_change_node_status(job_queue, node, JOB_QUEUE_IS_KILLED); - } - job_list_unlock(job_queue->job_list ); - arg_pack_free( arg_pack ); - return NULL; -} - -static void job_queue_handle_DO_KILL_NODE_FAILURE(job_queue_type * queue, job_queue_node_type * node) { - queue_driver_blacklist_node( queue->driver, node ); - job_queue_change_node_status(queue, node, JOB_QUEUE_DO_KILL); -} - -static void job_queue_handle_DO_KILL( job_queue_type * queue , job_queue_node_type * node) { - job_queue_kill_job_node(queue, node); - job_queue_change_node_status(queue , node , JOB_QUEUE_RUNNING_CALLBACK ); - { - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr( arg_pack , queue ); - arg_pack_append_int( arg_pack , job_queue_node_get_queue_index(node)); - thread_pool_add_job( queue->work_pool , job_queue_run_DO_KILL_callback , arg_pack ); - } -} - -static void job_queue_handle_EXIT( job_queue_type * queue , job_queue_node_type * node) { - job_queue_change_node_status(queue , node , JOB_QUEUE_RUNNING_CALLBACK ); - { - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr( arg_pack , queue ); - arg_pack_append_int( arg_pack , job_queue_node_get_queue_index(node)); - thread_pool_add_job( queue->work_pool , job_queue_run_EXIT_callback , arg_pack ); - } -} - - - -/*****************************************************************/ - -static void job_queue_check_expired(job_queue_type * queue) { - if ((job_queue_get_max_job_duration(queue) <= 0) && (job_queue_get_job_stop_time(queue) <= 0)) - return; - - for (int i = 0; i < job_list_get_size( queue->job_list ); i++) { - job_queue_node_type * node = job_list_iget_job( queue->job_list , i ); - - if (job_queue_node_get_status(node) == JOB_QUEUE_RUNNING) { - time_t now = time(NULL); - if ( job_queue_get_max_job_duration(queue) > 0) { - double elapsed = difftime(now, job_queue_node_get_sim_start( node )); - if (elapsed > job_queue_get_max_job_duration(queue)) - job_queue_change_node_status(queue, node, JOB_QUEUE_DO_KILL); - } - if (job_queue_get_job_stop_time(queue) > 0) { - if (now >= job_queue_get_job_stop_time(queue)) - job_queue_change_node_status(queue, node, JOB_QUEUE_DO_KILL); - } - } - } -} - -bool job_queue_get_open(const job_queue_type * job_queue) { - return job_queue->open; -} - -void job_queue_check_open(job_queue_type* queue) { - if (!job_queue_get_open(queue)) - util_abort("%s: queue not open and not ready for use; method job_queue_reset must be called before using the queue - aborting\n", __func__ ); -} - -bool job_queue_accept_jobs(const job_queue_type * queue) { - if (queue->user_exit) - return false; - - return queue->open; -} - - -/** - If the total number of jobs is not known in advance the job_queue_run_jobs - function can be called with @num_total_run == 0. In that case it is paramount - to call the function job_queue_submit_complete() whan all jobs have been submitted. - - Observe that this function is assumed to have ~exclusive access to - the jobs array; meaning that: - - 1. The jobs array is read without taking a reader lock. - - 2. Other functions accessing the jobs array concurrently must - take a read lock. - - 3. This function should be the *only* function modifying - the jobs array, and that is done *with* the write lock. - -*/ - -void job_queue_run_jobs(job_queue_type * queue , int num_total_run, bool verbose) { - int trylock = pthread_mutex_trylock( &queue->run_mutex ); - if (trylock != 0) - util_abort("%s: another thread is already running the queue_manager\n",__func__); - else if (!queue->user_exit) { - /* OK - we have got an exclusive lock to the run_jobs code. */ - - //Check if queue is open. Fails hard if not open - job_queue_check_open(queue); - - /* - The number of threads in the thread pool running callbacks. Memory consumption can - potentially be quite high while running the DONE callback - should therefor not use - too many threads. - */ - const int NUM_WORKER_THREADS = 4; - queue->work_pool = thread_pool_alloc( NUM_WORKER_THREADS , true ); - { - bool new_jobs = false; - bool cont = true; - int phase = 0; - - queue->running = true; - do { - bool local_user_exit = false; - job_list_get_rdlock( queue->job_list ); - /*****************************************************************/ - if (queue->user_exit) {/* An external thread has called the job_queue_user_exit() function, and we should kill - all jobs, do some clearing up and go home. Observe that we will go through the - queue handling codeblock below ONE LAST TIME before exiting. */ - job_queue_user_exit__( queue ); - local_user_exit = true; - } - - job_queue_check_expired(queue); - - /*****************************************************************/ - { - bool update_status = job_queue_update_status( queue ); - if (verbose) { - if (update_status || new_jobs) - job_queue_print_summary(queue , update_status ); - job_queue_update_spinner( &phase ); - } - - - { - int num_complete = job_queue_status_get_count(queue->status, JOB_QUEUE_SUCCESS) + - job_queue_status_get_count(queue->status, JOB_QUEUE_FAILED) + - job_queue_status_get_count(queue->status, JOB_QUEUE_IS_KILLED); - - if ((num_total_run > 0) && (num_total_run == num_complete)) - /* The number of jobs completed is equal to the number - of jobs we have said we want to run; so we are finished. - */ - cont = false; - else { - if (num_total_run == 0) { - /* We have not informed about how many jobs we will - run. To check if we are complete we perform the two - tests: - - 1. All the jobs which have been added with - job_queue_add_job() have completed. - - 2. The user has used job_queue_complete_submit() - to signal that no more jobs will be forthcoming. - */ - if ((num_complete == job_list_get_size( queue->job_list )) && queue->submit_complete) - cont = false; - } - } - } - - if (cont) { - /* Submitting new jobs */ - int max_submit = 5; /* This is the maximum number of jobs submitted in one while() { ... } below. - Only to ensure that the waiting time before a status update is not too long. */ - int total_active = job_queue_status_get_count(queue->status, JOB_QUEUE_PENDING) + job_queue_status_get_count(queue->status, JOB_QUEUE_RUNNING); - int num_submit_new; - - { - int max_running = job_queue_get_max_running( queue ); - if (max_running > 0) - num_submit_new = util_int_min( max_submit , max_running - total_active ); - else - /* - If max_running == 0 that should be interpreted as no limit; i.e. the queue layer will - attempt to send an unlimited number of jobs to the driver - the driver can reject the jobs. - */ - num_submit_new = util_int_min( max_submit , job_queue_status_get_count(queue->status, JOB_QUEUE_WAITING)); - } - - new_jobs = false; - if (job_queue_status_get_count(queue->status, JOB_QUEUE_WAITING) > 0) /* We have waiting jobs at all */ - if (num_submit_new > 0) /* The queue can allow more running jobs */ - new_jobs = true; - - if (new_jobs) { - int submit_count = 0; - int queue_index = 0; - - while ((queue_index < job_list_get_size( queue->job_list )) && (num_submit_new > 0)) { - job_queue_node_type * node = job_list_iget_job( queue->job_list , queue_index ); - if (job_queue_node_get_status(node) == JOB_QUEUE_WAITING) { - { - submit_status_type submit_status = job_queue_submit_job(queue , queue_index); - - if (submit_status == SUBMIT_OK) { - num_submit_new--; - submit_count++; - } else if ((submit_status == SUBMIT_DRIVER_FAIL) || (submit_status == SUBMIT_QUEUE_CLOSED)) - break; - } - } - queue_index++; - } - } - - - { - /* - Checking for complete / exited / overtime jobs - */ - int queue_index; - for (queue_index = 0; queue_index < job_list_get_size( queue->job_list ); queue_index++) { - job_queue_node_type * node = job_list_iget_job( queue->job_list , queue_index ); - - switch (job_queue_node_get_status(node)) { - case(JOB_QUEUE_DONE): - job_queue_handle_DONE(queue, node); - break; - case(JOB_QUEUE_EXIT): - job_queue_handle_EXIT(queue, node); - break; - case(JOB_QUEUE_DO_KILL_NODE_FAILURE): - job_queue_handle_DO_KILL_NODE_FAILURE(queue, node); - break; - case(JOB_QUEUE_DO_KILL): - job_queue_handle_DO_KILL(queue, node); - break; - default: - break; - } - - - } - } - } else - /* print an updated status to stdout before exiting. */ - if (verbose) - job_queue_print_summary(queue , true); - } - job_list_unlock( queue->job_list ); - if (local_user_exit) - cont = false; /* This is how we signal that we want to get out . */ - else { - util_yield(); - job_list_reader_wait( queue->job_list , queue->usleep_time , 8 * queue->usleep_time); - } - } while ( cont ); - } - if (verbose) - printf("\n"); - thread_pool_join( queue->work_pool ); - thread_pool_free( queue->work_pool ); - } - - /* - Set the queue's "open" flag to false to signal that the queue is - not ready to be used in a new job_queue_run_jobs or - job_queue_add_job method call as it has not been reset yet. Not - resetting the queue here implies that the queue object is still - available for queries after this method has finished - */ - queue->open = false; - queue->running = false; - pthread_mutex_unlock( &queue->run_mutex ); -} - - - - - -void * job_queue_run_jobs__(void * __arg_pack) { - arg_pack_type * arg_pack = arg_pack_safe_cast(__arg_pack); - job_queue_type * queue = arg_pack_iget_ptr(arg_pack , 0); - int num_total_run = arg_pack_iget_int(arg_pack , 1); - bool verbose = arg_pack_iget_bool(arg_pack , 2); - - job_queue_run_jobs(queue , num_total_run , verbose); - arg_pack_free( arg_pack ); - return NULL; -} - - -void job_queue_start_manager_thread( job_queue_type * job_queue , pthread_t * queue_thread , int job_size , bool verbose) { - - arg_pack_type * queue_args = arg_pack_alloc(); /* This arg_pack will be freed() in the job_que_run_jobs__() */ - arg_pack_append_ptr(queue_args , job_queue); - arg_pack_append_int(queue_args , job_size); - arg_pack_append_bool(queue_args , verbose); - - job_queue->running = true; - pthread_create( queue_thread , NULL , job_queue_run_jobs__ , queue_args); -} - - - - -/** - The most flexible use scenario is as follows: - - 1. The job_queue_run_jobs() is run by one thread. - 2. Jobs are added asyncronously with job_queue_add_job() from othread threads(s). - - - Unfortunately it does not work properly (i.e. Ctrl-C breaks) to use a Python - thread to invoke the job_queue_run_jobs() function; and this function is - mainly a workaround around that problem. The function will create a new - thread and run job_queue_run_jobs() in that thread; the calling thread will - just return. - - No reference is retained to the thread actually running the - job_queue_run_jobs() function. -*/ - - -void job_queue_run_jobs_threaded(job_queue_type * queue , int num_total_run, bool verbose) { - pthread_t queue_thread; - job_queue_start_manager_thread( queue , &queue_thread , num_total_run , verbose ); - pthread_detach( queue_thread ); /* Signal that the thread resources should be cleaned up when - the thread has exited. */ -} - - - -/*****************************************************************/ -/* Adding new jobs - it is complicated ... */ - - -/** - This initializes the non-driver-spesific fields of a job, i.e. the - name, runpath and so on, and sets the job->status == - JOB_QUEUE_WAITING. This status means the job is ready to be - submitted proper to one of the drivers (when a slot is ready). - When submitted the job will get (driver specific) job_data != NULL - and status SUBMITTED. -*/ - - - - -int job_queue_add_job(job_queue_type * queue , - const char * run_cmd , - job_callback_ftype * done_callback, - job_callback_ftype * retry_callback, - job_callback_ftype * exit_callback, - void * callback_arg , - int num_cpu , - const char * run_path , - const char * job_name , - int argc , - const char ** argv) { - - - if (job_queue_accept_jobs(queue)) { - int queue_index; - job_queue_node_type * node = job_queue_node_alloc( job_name , - run_path , - run_cmd , - argc , - argv , - num_cpu , - queue->ok_file , - queue->status_file , - queue->exit_file, - done_callback , - retry_callback , - exit_callback , - callback_arg ); - if (node) { - job_list_get_wrlock( queue->job_list ); - { - job_list_add_job( queue->job_list , node ); - queue_index = job_queue_node_get_queue_index(node); - job_queue_change_node_status(queue , node , JOB_QUEUE_WAITING); - } - job_list_unlock( queue->job_list ); - return queue_index; /* Handle used by the calling scope. */ - } else { - char * cwd = util_alloc_cwd(); - util_abort("%s: failed to create job %s in path: %s cwd:%s \n",__func__ , job_name , run_path , cwd); - return -1; - } - } else - return -1; -} - - -UTIL_SAFE_CAST_FUNCTION( job_queue , JOB_QUEUE_TYPE_ID) - - -/** - Observe that the job_queue returned by this function is NOT ready - for use; a driver must be set explicitly with a call to - job_queue_set_driver() first. -*/ - -job_queue_type * job_queue_alloc(int max_submit , - const char * ok_file , - const char * status_file , - const char * exit_file ) { - - - - job_queue_type * queue = util_malloc(sizeof * queue ); - UTIL_TYPE_ID_INIT( queue , JOB_QUEUE_TYPE_ID); - queue->usleep_time = 250000; /* 1000000 : 1 second */ - queue->max_ok_wait_time = 60; - queue->max_duration = 0; - queue->stop_time = 0; - queue->max_submit = max_submit; - queue->driver = NULL; - queue->ok_file = util_alloc_string_copy( ok_file ); - queue->exit_file = util_alloc_string_copy( exit_file ); - queue->status_file = util_alloc_string_copy( status_file ); - queue->open = true; - queue->user_exit = false; - queue->pause_on = false; - queue->running = false; - queue->submit_complete = false; - queue->work_pool = NULL; - queue->job_list = job_list_alloc( ); - queue->status = job_queue_status_alloc( ); - - pthread_mutex_init( &queue->run_mutex , NULL ); - - return queue; -} - - -/** - When the job_queue_run_jobs() has been called with @total_num_jobs - == 0 that means that the total number of jobs to run is not known - in advance. In that case it is essential to signal the queue when - we will not submit any more jobs, so that it can finalize and - return. That is done with the function job_queue_submit_complete() -*/ - -void job_queue_submit_complete( job_queue_type * queue ){ - queue->submit_complete = true; -} - - - -/** - The calling scope must retain a handle to the current driver and - free it. Should (in principle) be possible to change driver on a - running system whoaaa. Will read and update the max_running value - from the driver. -*/ - -void job_queue_set_driver(job_queue_type * queue , queue_driver_type * driver) { - queue->driver = driver; -} - - -bool job_queue_has_driver(const job_queue_type * queue ) { - if (queue->driver == NULL) - return false; - else - return true; -} - - -void job_queue_set_max_submit( job_queue_type * job_queue , int max_submit ) { - job_queue->max_submit = max_submit; -} - - -int job_queue_get_max_submit(const job_queue_type * job_queue ) { - return job_queue->max_submit; -} - - -/** - Returns true if the queue is currently paused, which means that no - more jobs are submitted. -*/ - -bool job_queue_get_pause( const job_queue_type * job_queue ) { - return job_queue->pause_on; -} - - -void job_queue_set_pause_on( job_queue_type * job_queue) { - job_queue->pause_on = true; -} - - -void job_queue_set_pause_off( job_queue_type * job_queue) { - job_queue->pause_on = false; -} - -/* - An external thread sets the user_exit flag to true, then - subsequently the thread managing the queue will see this, and close - down the queue. Will check that the queue is actually running before - setting the user_exit flag. If the queue does not change to running - state within a timeout limit the user_exit flag is not set, and the - function return false. -*/ - -bool job_queue_start_user_exit( job_queue_type * queue) { - if (!queue->user_exit) { - int timeout_limit = 10 * 1000000; // 10 seconds - int usleep_time = 100000; // 0.1 second - int total_sleep = 0; - - while (true) { - if (queue->running) { - queue->user_exit = true; - break; - } - usleep( usleep_time ); - total_sleep += usleep_time; - - if (total_sleep > timeout_limit) - break; - } - } - return queue->user_exit; -} - -bool job_queue_get_user_exit( const job_queue_type * queue) { - return queue->user_exit; -} - -void job_queue_free(job_queue_type * queue) { - util_safe_free( queue->ok_file ); - util_safe_free( queue->exit_file ); - job_list_free( queue->job_list ); - job_queue_status_free( queue->status ); - free(queue); -} - - - - - - -int job_queue_get_max_running_option(queue_driver_type * driver) { - char * max_running_string = (char*)queue_driver_get_option(driver, MAX_RUNNING); - int max_running; - if (!util_sscanf_int(max_running_string, &max_running)) { - fprintf(stderr, "%s: Unable to parse option MAX_RUNNING with value %s to an int", __func__, max_running_string); - } - return max_running; -} - - -void job_queue_set_max_running_option(queue_driver_type * driver, int max_running) { - char * max_running_string = util_alloc_sprintf("%d", max_running); - queue_driver_set_option(driver, MAX_RUNNING, max_running_string); - free(max_running_string); -} - - -/** - Observe that if the max number of running jobs is decreased, - nothing will be done to reduce the number of jobs currently - running; but no more jobs will be submitted until the number of - running has fallen below the new limit. - - The updated value will also be pushed down to the current driver. - - NOTE: These next three *max_running functions should not be used, rather - use the set_option feature, with MAX_RUNNING. They are (maybe) used by python - therefore not removed. -*/ -int job_queue_get_max_running( const job_queue_type * queue ) { - return job_queue_get_max_running_option(queue->driver); -} - -void job_queue_set_max_running( job_queue_type * queue , int max_running ) { - job_queue_set_max_running_option(queue->driver, max_running); -} diff --git a/ThirdParty/Ert/libjob_queue/src/job_queue_manager.c b/ThirdParty/Ert/libjob_queue/src/job_queue_manager.c deleted file mode 100644 index eeede2c8fb..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/job_queue_manager.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'job_queue_manager.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */ -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#define JOB_QUEUE_MANAGER_TYPE_ID 81626006 - - - -struct job_queue_manager_struct { - UTIL_TYPE_ID_DECLARATION; - pthread_t queue_thread; - job_queue_type * job_queue; -}; - - -UTIL_IS_INSTANCE_FUNCTION( job_queue_manager , JOB_QUEUE_MANAGER_TYPE_ID ) - - -job_queue_manager_type * job_queue_manager_alloc( job_queue_type * job_queue ) { - job_queue_manager_type * manager = util_malloc( sizeof * manager ); - UTIL_TYPE_ID_INIT( manager , JOB_QUEUE_MANAGER_TYPE_ID ); - manager->job_queue = job_queue; - return manager; -} - - -void job_queue_manager_free( job_queue_manager_type * manager) { - free( manager ); -} - - -void job_queue_manager_start_queue( job_queue_manager_type * manager , int num_total_run , bool verbose , bool reset_queue) { - if (reset_queue) - job_queue_reset( manager->job_queue ); - - job_queue_start_manager_thread( manager->job_queue , &manager->queue_thread , num_total_run , verbose ); -} - - - -void job_queue_manager_wait( job_queue_manager_type * manager) { - pthread_join( manager->queue_thread , NULL ); -} - - -bool job_queue_manager_try_wait( job_queue_manager_type * manager , int timeout_seconds) { - struct timespec ts; - time_t timeout_time = time( NULL ); - - util_inplace_forward_seconds_utc(&timeout_time , timeout_seconds ); - ts.tv_sec = timeout_time; - ts.tv_nsec = 0; - -#ifdef HAVE_TIMEDJOIN - { - int join_return = pthread_timedjoin_np( manager->queue_thread , NULL , &ts); /* Wait for the main thread to complete. */ - if (join_return == 0) - return true; - else - return false; - } -#else - while(true) { - if (pthread_kill(manager->queue_thread, 0) == 0){ - util_yield(); - } else { - return true; - } - - time_t now = time(NULL); - - if(util_difftime_seconds(now, timeout_time) <= 0) { - return false; - } - } - -#endif -} - - - -bool job_queue_manager_is_running( const job_queue_manager_type * manager) { - return job_queue_is_running( manager->job_queue ); -} - - -int job_queue_manager_get_num_waiting( const job_queue_manager_type * manager) { - return job_queue_get_num_waiting( manager->job_queue ); -} - - -int job_queue_manager_get_num_running( const job_queue_manager_type * manager) { - return job_queue_get_num_running( manager->job_queue ); -} - - -int job_queue_manager_get_num_success( const job_queue_manager_type * manager) { - return job_queue_get_num_complete( manager->job_queue ); -} - -int job_queue_manager_get_num_failed( const job_queue_manager_type * manager) { - return job_queue_get_num_failed( manager->job_queue ); -} - - - -bool job_queue_manager_job_complete( const job_queue_manager_type * manager , int job_index) { - job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index ); - if (status & JOB_QUEUE_COMPLETE_STATUS) - return true; - else - return false; -} - - -bool job_queue_manager_job_waiting( const job_queue_manager_type * manager , int job_index) { - job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index ); - if (status & JOB_QUEUE_WAITING_STATUS) - return true; - else - return false; -} - -bool job_queue_manager_job_running( const job_queue_manager_type * manager , int job_index) { - job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index ); - if (status == JOB_QUEUE_RUNNING) - return true; - else - return false; -} - - -bool job_queue_manager_job_failed( const job_queue_manager_type * manager , int job_index) { - job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index ); - if (status == JOB_QUEUE_FAILED) - return true; - else - return false; -} - - -bool job_queue_manager_job_success( const job_queue_manager_type * manager , int job_index) { - job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index ); - if (status == JOB_QUEUE_SUCCESS) - return true; - else - return false; -} - -job_status_type job_queue_manager_iget_job_status(const job_queue_manager_type * manager, int job_index) { - return job_queue_iget_job_status(manager->job_queue, job_index); -} - diff --git a/ThirdParty/Ert/libjob_queue/src/job_queue_status.c b/ThirdParty/Ert/libjob_queue/src/job_queue_status.c deleted file mode 100644 index a862283a07..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/job_queue_status.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'job_status_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include -#include - -#include -#include - -#define JOB_QUEUE_STATUS_TYPE_ID 777620306 - -struct job_queue_status_struct { - UTIL_TYPE_ID_DECLARATION; - int status_list[JOB_QUEUE_MAX_STATE]; - pthread_mutex_t update_mutex; -}; - -static const int status_index[] = { JOB_QUEUE_NOT_ACTIVE , // Initial, allocated job state, job not added - controlled by job_queue - JOB_QUEUE_WAITING , // The job is ready to be started - controlled by job_queue - JOB_QUEUE_SUBMITTED , // Job is submitted to driver - temporary state - controlled by job_queue - JOB_QUEUE_PENDING , // Job is pending, before actual execution - controlled by queue_driver - JOB_QUEUE_RUNNING , // Job is executing - controlled by queue_driver - JOB_QUEUE_DONE , // Job is done (successful or not), temporary state - controlled/returned by by queue_driver - JOB_QUEUE_EXIT , // Job is done, with exit status != 0, temporary state - controlled/returned by by queue_driver - JOB_QUEUE_IS_KILLED , // Job has been killed, due to JOB_QUEUE_DO_KILL, FINAL STATE - controlled by job_queue - JOB_QUEUE_DO_KILL , // User / queue system has requested killing of job - controlled by job_queue / external scope - JOB_QUEUE_SUCCESS , // All good, comes after JOB_QUEUE_DONE, with additional checks, FINAL STATE - controlled by job_queue - JOB_QUEUE_RUNNING_CALLBACK, // Temporary state, while running requested callbacks after an ended job - controlled by job_queue - JOB_QUEUE_FAILED , // Job has failed, no more retries, FINAL STATE - JOB_QUEUE_DO_KILL_NODE_FAILURE // Job has failed, node should be blacklisted - }; - -static int STATUS_INDEX( job_status_type status ) { - int index = 0; - - while (true) { - if (status_index[index] == status) - return index; - - index++; - if (index == JOB_QUEUE_MAX_STATE) - util_abort("%s: failed to get index from status:%d \n",__func__ , status); - } -} - - -UTIL_IS_INSTANCE_FUNCTION( job_queue_status , JOB_QUEUE_STATUS_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION( job_queue_status , JOB_QUEUE_STATUS_TYPE_ID ) - - -job_queue_status_type * job_queue_status_alloc() { - job_queue_status_type * status = util_malloc( sizeof * status ); - UTIL_TYPE_ID_INIT( status , JOB_QUEUE_STATUS_TYPE_ID ); - pthread_mutex_init( &status->update_mutex , NULL ); - job_queue_status_clear( status ); - return status; -} - - -void job_queue_status_free( job_queue_status_type * status ) { - free( status ); -} - - -void job_queue_status_clear( job_queue_status_type * status ) { - int index; - for (index = 0; index < JOB_QUEUE_MAX_STATE; index++) - status->status_list[ index ] = 0; -} - - -int job_queue_status_get_count( job_queue_status_type * status_count , job_status_type status_type) { - int index = STATUS_INDEX( status_type ); - int count; - - count = status_count->status_list[index]; - - return count; -} - - -void job_queue_status_inc( job_queue_status_type * status_count , job_status_type status_type) { - int index = STATUS_INDEX( status_type ); - - pthread_mutex_lock( &status_count->update_mutex ); - { - int count = status_count->status_list[index]; - status_count->status_list[index] = count + 1; - } - pthread_mutex_unlock( &status_count->update_mutex ); -} - - -static void job_queue_status_dec( job_queue_status_type * status_count , job_status_type status_type) { - int index = STATUS_INDEX( status_type ); - - pthread_mutex_lock( &status_count->update_mutex ); - { - int count = status_count->status_list[index]; - status_count->status_list[index] = count - 1; - } - pthread_mutex_unlock( &status_count->update_mutex ); -} - - -/* - The important point is that each individual ++ and -- operation is - atomic, if the different status counts do not add up perfectly at - all times that is ok. -*/ -bool job_queue_status_transition(job_queue_status_type * status_count, job_status_type src_status, - job_status_type target_status) { - if (src_status == target_status) - return false; - - /* - The target_status indicates that the routine which queried for new - status failed; we just remain in the current status. - */ - if (target_status == JOB_QUEUE_STATUS_FAILURE) - return false; - - job_queue_status_dec( status_count, src_status ); - job_queue_status_inc( status_count, target_status ); - return true; -} - - -int job_queue_status_get_total_count( const job_queue_status_type * status ) { - int total_count = 0; - for (int index = 0; index < JOB_QUEUE_MAX_STATE; index++) - total_count += status->status_list[ index ]; - return total_count; -} diff --git a/ThirdParty/Ert/libjob_queue/src/local_driver.c b/ThirdParty/Ert/libjob_queue/src/local_driver.c deleted file mode 100644 index 52a16d5a64..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/local_driver.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'local_driver.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - - -struct local_job_struct { - UTIL_TYPE_ID_DECLARATION; - bool active; - job_status_type status; - pthread_t run_thread; - pid_t child_process; -}; - - -#define LOCAL_DRIVER_TYPE_ID 66196305 -#define LOCAL_JOB_TYPE_ID 63056619 - -struct local_driver_struct { - UTIL_TYPE_ID_DECLARATION; - pthread_attr_t thread_attr; - pthread_mutex_t submit_lock; -}; - -/*****************************************************************/ - - -static UTIL_SAFE_CAST_FUNCTION( local_driver , LOCAL_DRIVER_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION( local_job , LOCAL_JOB_TYPE_ID ) - - -local_job_type * local_job_alloc() { - local_job_type * job; - job = util_malloc(sizeof * job ); - UTIL_TYPE_ID_INIT( job , LOCAL_JOB_TYPE_ID ); - job->active = false; - job->status = JOB_QUEUE_WAITING; - return job; -} - -void local_job_free(local_job_type * job) { - if (job->active) { - /* Thread clean up */ - } - free(job); -} - - - -job_status_type local_driver_get_job_status(void * __driver, void * __job) { - if (__job == NULL) - /* The job has not been registered at all ... */ - return JOB_QUEUE_NOT_ACTIVE; - else { - local_job_type * job = local_job_safe_cast( __job ); - return job->status; - } -} - - - -void local_driver_free_job( void * __job ) { - local_job_type * job = local_job_safe_cast( __job ); - local_job_free(job); -} - - -void local_driver_kill_job( void * __driver , void * __job) { - local_job_type * job = local_job_safe_cast( __job ); - - if (job->active) { - pthread_cancel( job->run_thread ); - } - - kill( job->child_process , SIGTERM ); -} - - -void * submit_job_thread__(void * __arg) { - arg_pack_type *arg_pack = arg_pack_safe_cast(__arg); - const char *executable = arg_pack_iget_const_ptr(arg_pack, 0); - /* - The arg_pack contains a run_path field as the second argument, - it has therefor been left here as a comment: - - const char * run_path = arg_pack_iget_const_ptr(arg_pack , 1); - */ - int argc = arg_pack_iget_int(arg_pack, 2); - char **argv = arg_pack_iget_ptr(arg_pack, 3); - local_job_type *job = arg_pack_iget_ptr(arg_pack, 4); - - { - int wait_status; - job->child_process = util_spawn(executable, argc, (const char**) argv, NULL, NULL); - util_free_stringlist(argv, argc); - arg_pack_free(arg_pack); - waitpid(job->child_process, &wait_status, 0); - } - - job->status = JOB_QUEUE_DONE; - job->active = false; - pthread_exit(NULL); - return NULL; -} - - - -void * local_driver_submit_job(void * __driver , - const char * submit_cmd , - int num_cpu , /* Ignored */ - const char * run_path , - const char * job_name , - int argc , - const char ** argv ) { - local_driver_type * driver = local_driver_safe_cast( __driver ); - { - local_job_type * job = local_job_alloc(); - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_const_ptr( arg_pack , submit_cmd); - arg_pack_append_const_ptr( arg_pack , run_path ); - arg_pack_append_int( arg_pack , argc ); - arg_pack_append_ptr( arg_pack , util_alloc_stringlist_copy( argv , argc )); /* Due to conflict with threads and python GC we take a local copy. */ - arg_pack_append_ptr( arg_pack , job ); - - pthread_mutex_lock( &driver->submit_lock ); - job->active = true; - job->status = JOB_QUEUE_RUNNING; - - if (pthread_create( &job->run_thread , &driver->thread_attr , submit_job_thread__ , arg_pack) != 0) - util_abort("%s: failed to create run thread - aborting \n",__func__); - - pthread_mutex_unlock( &driver->submit_lock ); - return job; - } -} - - - -void local_driver_free(local_driver_type * driver) { - pthread_attr_destroy ( &driver->thread_attr ); - free(driver); - driver = NULL; -} - - -void local_driver_free__(void * __driver) { - local_driver_type * driver = local_driver_safe_cast( __driver ); - local_driver_free( driver ); -} - - -void * local_driver_alloc() { - local_driver_type * local_driver = util_malloc(sizeof * local_driver ); - UTIL_TYPE_ID_INIT( local_driver , LOCAL_DRIVER_TYPE_ID); - pthread_mutex_init( &local_driver->submit_lock , NULL ); - pthread_attr_init( &local_driver->thread_attr ); - pthread_attr_setdetachstate( &local_driver->thread_attr , PTHREAD_CREATE_DETACHED ); - - return local_driver; -} - - -bool local_driver_set_option( void * __driver , const char * option_key , const void * value){ - return false; -} - -void local_driver_init_option_list(stringlist_type * option_list) { - //No options specific for local driver; do nothing -} - -#undef LOCAL_DRIVER_ID -#undef LOCAL_JOB_ID - -/*****************************************************************/ - diff --git a/ThirdParty/Ert/libjob_queue/src/lsb.c b/ThirdParty/Ert/libjob_queue/src/lsb.c deleted file mode 100644 index e9f1f0f252..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/lsb.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'lsb.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -/* - This file implements a very small wrapper structure around the - lsb_xxxx() functions from the libbat.so shared library which are - used to submit, monitor and control simulations with LSF. - - Loading and initializing the lsf libraries is quite painful, in an - attempt to reduce unecessary dependencies the lsf libraries are - loaded with dlopen() in the lsb_alloc() function below. This means - that the libjob_queue.so shared library can be loaded without access - to the lsf libraries. -*/ - -#include -#include - -#include - -#include -#include - -#include - - - -typedef int (lsb_submit_ftype) ( struct submit * , struct submitReply *); -typedef int (lsb_openjobinfo_ftype) (int , char * , char * , char * , char * , int); -typedef struct jobInfoEnt * (lsb_readjobinfo_ftype) (int * ); -typedef int (lsb_closejobinfo_ftype) ( ); -typedef int (lsb_forcekilljob_ftype) ( int ); -typedef int (lsb_init_ftype) ( char * ); -typedef char * (lsb_sysmsg_ftype) ( ); - - - -struct lsb_struct { - lsb_submit_ftype * submit; - lsb_openjobinfo_ftype * open_job; - lsb_readjobinfo_ftype * read_job; - lsb_closejobinfo_ftype * close_job; - lsb_forcekilljob_ftype * kill_job; - lsb_init_ftype * lsb_init; - lsb_sysmsg_ftype * sys_msg; - - stringlist_type * error_list; - void * lib_bat; - void * lib_nsl; - void * lib_lsf; - bool ready; -}; - - - -static void * lsb_dlsym( lsb_type * lsb , const char * function_name ) { - void * function = dlsym( lsb->lib_bat , function_name ); - if (!function) { - lsb->ready = false; - stringlist_append_owned_ref( lsb->error_list , util_alloc_sprintf( "Failed to locate symbol:%s dlerror:%s" , function_name , dlerror())); - } - - return function; -} - - -void * lsb_dlopen( lsb_type * lsb , const char * lib_name) { - void * lib_handle = dlopen( lib_name , RTLD_NOW | RTLD_GLOBAL); - if (!lib_handle) { - lsb->ready = false; - stringlist_append_owned_ref( lsb->error_list , util_alloc_sprintf("dlopen(%s) - failed:%s \n" , lib_name , dlerror())); - } - return lib_handle; -} - -/* - The following environment variables must be set (at some stage) before - LSF will work properly: - - LSF_BINDIR $LSF_HOME/bin - LSF_LIBDIR $LSF_HOME/lib - XLSF_UIDDIR $LSF_HOME/lib/uid - LSF_SERVERDIR $LSF_HOME/etc - LSF_ENVDIR /prog/LSF/conf - - The runtime linker must locate the libnsl, libbat and liblsf - libraries using whatever method it usually does. If the loading - fails the lsb object will get the ->ready flag set to false, and the - lsf_driver will discard the lsb instance (and hopefully use shell - commands to perform job management). -*/ - -lsb_type * lsb_alloc() { - lsb_type * lsb = util_malloc( sizeof * lsb ); - lsb->ready = true; - lsb->error_list = stringlist_alloc_new(); - - lsb->lib_nsl = lsb_dlopen(lsb , "libnsl.so" ); - lsb->lib_lsf = lsb_dlopen(lsb , "liblsf.so" ); - lsb->lib_bat = lsb_dlopen(lsb , "libbat.so"); - - if (lsb->lib_bat) { - lsb->submit = (lsb_submit_ftype *) lsb_dlsym( lsb , "lsb_submit"); - lsb->open_job = (lsb_openjobinfo_ftype *) lsb_dlsym( lsb , "lsb_openjobinfo"); - lsb->read_job = (lsb_readjobinfo_ftype *) lsb_dlsym( lsb , "lsb_readjobinfo"); - lsb->close_job = (lsb_closejobinfo_ftype *) lsb_dlsym( lsb , "lsb_closejobinfo"); - lsb->kill_job = (lsb_forcekilljob_ftype *) lsb_dlsym( lsb , "lsb_forcekilljob"); - lsb->lsb_init = (lsb_init_ftype *) lsb_dlsym( lsb , "lsb_init"); - lsb->sys_msg = (lsb_sysmsg_ftype *) lsb_dlsym( lsb , "lsb_sysmsg"); - } - - return lsb; -} - - - -void lsb_free( lsb_type * lsb) { - stringlist_free( lsb->error_list ); - - if (lsb->lib_nsl) - dlclose( lsb->lib_nsl ); - - if (lsb->lib_lsf) - dlclose( lsb->lib_lsf ); - - if (lsb->lib_bat) - dlclose( lsb->lib_bat ); - - free( lsb ); -} - - - -bool lsb_ready( const lsb_type * lsb) { - return lsb->ready; -} - -stringlist_type * lsb_get_error_list( const lsb_type * lsb ) { - return lsb->error_list; -} - - -/*****************************************************************/ - -int lsb_initialize( const lsb_type * lsb) { - /* - The environment variable LSF_ENVDIR must be set to point the - directory containing LSF configuration information, the whole - thing will crash and burn if this is not properly set. - */ - if ( lsb->lsb_init(NULL) != 0 ) { - - fprintf(stderr,"LSF_ENVDIR: "); - if (getenv("LSF_ENVDIR") != NULL) - fprintf(stderr,"%s\n", getenv("LSF_ENVDIR")); - else - fprintf(stderr, "not set\n"); - - util_abort("%s failed to initialize LSF environment : %s \n",__func__ , lsb->sys_msg() ); - } - return 0; -} - - -int lsb_submitjob( const lsb_type * lsb , struct submit * submit_data, struct submitReply * reply_data) { - return lsb->submit( submit_data , reply_data ); -} - - -int lsb_killjob( const lsb_type * lsb , int lsf_jobnr) { - return lsb->kill_job(lsf_jobnr); -} - - -int lsb_openjob( const lsb_type * lsb , int lsf_jobnr) { - return lsb->open_job(lsf_jobnr , NULL , NULL , NULL , NULL , ALL_JOB); -} - - -int lsb_closejob( const lsb_type * lsb) { - return lsb->close_job(); -} - -char * lsb_sys_msg( const lsb_type * lsb) { - return lsb->sys_msg(); -} - - -struct jobInfoEnt * lsb_readjob( const lsb_type * lsb ) { - struct jobInfoEnt * job_info = lsb->read_job( NULL ); - return job_info; -} diff --git a/ThirdParty/Ert/libjob_queue/src/lsf_driver.c b/ThirdParty/Ert/libjob_queue/src/lsf_driver.c deleted file mode 100644 index ef4419b337..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/lsf_driver.c +++ /dev/null @@ -1,1306 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'lsf_driver.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#ifdef HAVE_LSF_LIBRARY -#include -#endif - - - - -/** - Documentation/examples of programming towards the lsf libraries can - be found in /prog/LSF/7.0/misc/examples -*/ - - -/* - How to call the lsf commands bsub/bjobs/bkill: - ---------------------------------------------- - - The commands to submit, monitor and modify LSF jobs are available - through library calls through the lsf library. This is a good - solution which works well. - - Unfortunately only quite few of the workstations in Statoil are - "designated LSF machines", meaning that they are allowed to talk to - the LIM servers, to be able to use the low-level lsb_xxx() function - calls the host making the calls must configured (by an LSF - administrator) to be a LSF client. - - The lsf_driver can either make use of the proper lsf library calls - (lsb_submit(), lsb_openjobinfo(), ...) or alternatively it can issue - ssh calls to an external LSF_SERVER and call up the bsub/bkill/bjob - executables on the remote server. - - All the functions with 'library' in the name are based on library - calls, and the functions with 'shell' in the name are based on - external functions (the actual calls are through the - util_spawn() function). - - By default the driver will use the library, but if a value is - provided with the LSF_SERVER option, the shell based functions will - be used. Internally this is goverened by the boolean flag - 'use_library_calls'. - - Even though you only intend to submit through the shell commands - bsub / bjobs / bkill the build process still requires access to the - lsf headers and the lsf library; that is probably not optimal. - - - Remote login shell - ------------------ - - When submitting with LSF the job will inherit the current - environment on the submitting host, and not read the users login - files on the remote host where the job is actually executed. E.g. in - situations where submitting host and executing host are - e.g. different operating system versions this might be - unfortunate. The '-L @shell' switch can used with bsub to force lsf - to source schell specific input files prior to executing your - job. This can be achieved with the LSF_LOGIN_SHELL option: - - lsf_driver_set_option( driver , LSF_LOGIN_SHELL , "/bin/csh" ); - -*/ - - - - - -#define LSF_DRIVER_TYPE_ID 10078365 -#define LSF_JOB_TYPE_ID 9963900 -#define MAX_ERROR_COUNT 100 -#define SUBMIT_ERROR_SLEEP 2 -#define BJOBS_REFRESH_TIME "10" -#define DEFAULT_RSH_CMD "/usr/bin/ssh" -#define DEFAULT_BSUB_CMD "bsub" -#define DEFAULT_BJOBS_CMD "bjobs" -#define DEFAULT_BKILL_CMD "bkill" -#define DEFAULT_BHIST_CMD "bhist" - - - -struct lsf_job_struct { - UTIL_TYPE_ID_DECLARATION; - long int lsf_jobnr; - int num_exec_host; - char **exec_host; - char * lsf_jobnr_char; /* Used to look up the job status in the bjobs_cache hash table */ -}; - - - -struct lsf_driver_struct { - UTIL_TYPE_ID_DECLARATION; - char * queue_name; - char * resource_request; - stringlist_type * exclude_hosts; - char * login_shell; - pthread_mutex_t submit_lock; - - lsf_submit_method_enum submit_method; - int submit_sleep; - - int error_count; - int max_error_count; - int submit_error_sleep; - - /*-----------------------------------------------------------------*/ - /* Fields used by the lsf library functions */ -#ifdef HAVE_LSF_LIBRARY - struct submit lsf_request; - struct submitReply lsf_reply; - lsb_type * lsb; -#endif - - /*-----------------------------------------------------------------*/ - /* Fields used by the shell based functions */ - bool debug_output; - int bjobs_refresh_interval; - time_t last_bjobs_update; - hash_type * my_jobs; /* A hash table of all jobs submitted by this ERT instance - - to ensure that we do not check status of old jobs in e.g. ZOMBIE status. */ - hash_type * status_map; - hash_type * bjobs_cache; /* The output of calling bjobs is cached in this table. */ - pthread_mutex_t bjobs_mutex; /* Only one thread should update the bjobs_chache table. */ - char * remote_lsf_server; - char * rsh_cmd; - char * bsub_cmd; - char * bjobs_cmd; - char * bkill_cmd; - char * bhist_cmd; -}; - - - - -/*****************************************************************/ - -UTIL_SAFE_CAST_FUNCTION( lsf_driver , LSF_DRIVER_TYPE_ID) -static UTIL_SAFE_CAST_FUNCTION_CONST( lsf_driver , LSF_DRIVER_TYPE_ID) -static UTIL_SAFE_CAST_FUNCTION( lsf_job , LSF_JOB_TYPE_ID) - -lsf_job_type * lsf_job_alloc() { - lsf_job_type * job; - job = util_malloc(sizeof * job); - job->num_exec_host = 0; - job->exec_host = NULL; - - job->lsf_jobnr = 0; - job->lsf_jobnr_char = NULL; - UTIL_TYPE_ID_INIT( job , LSF_JOB_TYPE_ID); - return job; -} - - - -void lsf_job_free(lsf_job_type * job) { - util_safe_free(job->lsf_jobnr_char); - util_free_stringlist(job->exec_host , job->num_exec_host); - free(job); -} - - -void lsf_job_export_hostnames( const lsf_job_type * job , stringlist_type * hostlist) { - int host_nr; - - stringlist_clear( hostlist ); - for (host_nr = 0; host_nr < job->num_exec_host; host_nr++) - stringlist_append_copy( hostlist , job->exec_host[ host_nr ]); -} - - -long lsf_job_get_jobnr( const lsf_job_type * job ) { - return job->lsf_jobnr; -} - -int lsf_job_parse_bsub_stdout(const char * bsub_cmd, const char * stdout_file) { - int jobid = 0; - if ((util_file_exists(stdout_file)) && (util_file_size(stdout_file) > 0)) { - FILE * stream = util_fopen(stdout_file , "r"); - if (util_fseek_string(stream , "<" , true , true)) { - char * jobid_string = util_fscanf_alloc_upto(stream , ">" , false); - if (jobid_string != NULL) { - util_sscanf_int( jobid_string , &jobid); - free( jobid_string ); - } - } - fclose( stream ); - - if (jobid == 0) { - char * file_content = util_fread_alloc_file_content( stdout_file , NULL ); - fprintf(stderr,"Failed to get lsf job id from file: %s \n",stdout_file ); - fprintf(stderr,"bsub command : %s \n",bsub_cmd ); - fprintf(stderr,"%s\n", file_content); - free( file_content ); - util_abort("%s: \n",__func__); - } - } - return jobid; -} - -/** - * Assumes fname points to a file with content "hname1:hname2:hname3" as written by lsf_job_write_bjobs_to_file - */ -stringlist_type * lsf_job_alloc_parse_hostnames(const char* fname) { - FILE *stream = util_fopen(fname, "r"); - - bool at_eof = false; - while (!at_eof) { - char * line = util_fscanf_alloc_line(stream, &at_eof); - if (line != NULL) { - stringlist_type * hosts = stringlist_alloc_from_split(line, ":"); // bjobs uses : as std. delimiter - - for (int i = 0; i < stringlist_get_size(hosts); i++) { - const char * host = stringlist_iget(hosts, i); - stringlist_type * h = stringlist_alloc_from_split(host, "*"); - stringlist_iset_copy(hosts, i, stringlist_iget(h, stringlist_get_size(h) - 1)); // hostname 4*be-lsf01 -> be-lsf01 - stringlist_free(h); - } - - free(line); - fclose(stream); - return hosts; - } - } - fclose(stream); - return stringlist_alloc_new(); -} - -char* lsf_job_write_bjobs_to_file(const char * bjobs_cmd, lsf_driver_type * driver, const long jobid) { - // will typically run "bjobs -noheader -o 'EXEC_HOST' jobid" - - const char * noheader = "-noheader"; - const char * fields = "EXEC_HOST"; - char * cmd = util_alloc_sprintf("%s %s -o '%s' %d", bjobs_cmd, noheader, fields, jobid); - - char * tmp_file = util_alloc_tmp_file("/tmp", "ert_job_exec_host", true); - - if (driver->submit_method == LSF_SUBMIT_REMOTE_SHELL) { - char ** argv = util_calloc(2, sizeof *argv); - argv[0] = driver->remote_lsf_server; - argv[1] = cmd; - util_spawn_blocking(driver->rsh_cmd, 2, (const char **) argv, tmp_file, NULL); - free(argv); - } else if (driver->submit_method == LSF_SUBMIT_LOCAL_SHELL) { - char ** argv = util_calloc(1, sizeof *argv); - argv[0] = ""; - util_spawn_blocking(cmd, 1, (const char **) argv, tmp_file, NULL); - } - free(cmd); - - return tmp_file; -} - - -static void lsf_driver_internal_error( const lsf_driver_type * driver ) { - fprintf(stderr , "\n\n"); - fprintf(stderr , "*****************************************************************\n"); - fprintf(stderr , "** The LSF driver can be configured and used in many different **\n"); - fprintf(stderr , "** ways. The important point is how we choose to submit: **\n"); - fprintf(stderr , "** **\n"); - fprintf(stderr , "** 1. Using the lsf library calls **\n"); - fprintf(stderr , "** 2. Using the bsub/bjobs/bkill commands locally **\n"); - fprintf(stderr , "** 3. Using the bsub/bjobs/bkill commands through ssh **\n"); - fprintf(stderr , "** **\n"); - fprintf(stderr , "** To chose between these three alternatives you set the remote**\n"); - fprintf(stderr , "** server with the lsf_driver_set_option() function. Passing **\n"); - fprintf(stderr , "** the value NULL will give alternative 1, passing the special **\n"); - fprintf(stderr , "** string \'%s\' will give alternative 2, and any other **\n",LOCAL_LSF_SERVER); - fprintf(stderr , "** value will submit through that host using ssh. **\n"); - fprintf(stderr , "** **\n"); - fprintf(stderr , "** The ability to submit thorugh lsf library calls must be **\n"); - fprintf(stderr , "** compiled in by defining the symbol \'HAVE_LSF_LIBRARY\' when **\n"); - fprintf(stderr , "** compiling. **\n"); - fprintf(stderr , "** **\n"); -#ifdef HAVE_LSF_LIBRARY - fprintf(stderr , "** This lsf driver has support for using lsf library calls. **\n"); -#else - fprintf(stderr , "** This lsf driver does NOT have support for using lsf **\n"); - fprintf(stderr , "** library calls; but you have tried to submit without setting **\n"); - fprintf(stderr , "** a value for LSF_SERVER. Set this and try again. **\n"); -#endif - fprintf(stderr , "*****************************************************************\n\n"); - exit(1); -} - - - -static void lsf_driver_assert_submit_method( const lsf_driver_type * driver ) { - if (driver->submit_method == LSF_SUBMIT_INVALID) { - lsf_driver_internal_error(driver); - } -} - - - - - -stringlist_type * lsf_driver_alloc_cmd(lsf_driver_type * driver , - const char * lsf_stdout , - const char * job_name , - const char * submit_cmd , - int num_cpu , - int job_argc, - const char ** job_argv) { - - stringlist_type * argv = stringlist_alloc_new(); - char * num_cpu_string = util_alloc_sprintf("%d" , num_cpu); - char * quoted_resource_request = NULL; - - /* - The resource request string contains spaces, and when passed - through the shell it must be protected with \"..\"; this applies - when submitting to a remote lsf server with ssh. However when - submitting to the local workstation using a bsub command the - command will be invoked with the util_spawn() command - and no - shell is involved. In this latter case we must avoid the \"...\" - quoting. - */ - - { - stringlist_type * select_list = stringlist_alloc_new(); - if (stringlist_get_size(driver->exclude_hosts) > 0) { - for (int i = 0; i < stringlist_get_size(driver->exclude_hosts); i++) { - char * exclude_host = util_alloc_sprintf("hname!='%s'", stringlist_iget(driver->exclude_hosts, i)); - stringlist_append_owned_ref(select_list, exclude_host); - } - } - - char * excludes_string = NULL; - char * req = ""; - char * resreq = NULL; - - if (stringlist_get_size(select_list) > 0) { - excludes_string = stringlist_alloc_joined_string(select_list, " && "); - if (driver->resource_request != NULL) { - resreq = util_alloc_string_copy(driver->resource_request); - util_string_tr(resreq, ']', ' '); // remove "]" from "select[A && B] - excludes_string = stringlist_alloc_joined_string(select_list, " && "); - req = util_alloc_sprintf("%s && %s]", resreq, excludes_string); - } else { - req = util_alloc_sprintf("select[%s]", excludes_string); - } - } else { - if (driver->resource_request != NULL) { - resreq = util_alloc_string_copy(driver->resource_request); - req = util_alloc_sprintf("%s", resreq); - } - } - if (resreq) - free(resreq); - - if (driver->submit_method == LSF_SUBMIT_REMOTE_SHELL) - quoted_resource_request = util_alloc_sprintf("\"%s\"", req); - else - quoted_resource_request = util_alloc_string_copy(req); - - free(req); - if (excludes_string) - free(excludes_string); - stringlist_free(select_list); - } - - if (driver->submit_method == LSF_SUBMIT_REMOTE_SHELL) - stringlist_append_ref( argv , driver->bsub_cmd); - - stringlist_append_ref( argv , "-o" ); - stringlist_append_copy( argv , lsf_stdout ); - if (driver->queue_name != NULL) { - stringlist_append_ref( argv , "-q" ); - stringlist_append_ref( argv , driver->queue_name ); - } - stringlist_append_ref( argv , "-J" ); - stringlist_append_ref( argv , job_name ); - stringlist_append_ref( argv , "-n" ); - stringlist_append_copy( argv , num_cpu_string ); - - if (quoted_resource_request != NULL) { - stringlist_append_ref( argv , "-R"); - stringlist_append_copy( argv , quoted_resource_request ); - } - - if (driver->login_shell != NULL) { - stringlist_append_ref( argv , "-L"); - stringlist_append_ref( argv , driver->login_shell ); - } - - stringlist_append_ref( argv , submit_cmd); - { - int iarg; - for (iarg = 0; iarg < job_argc; iarg++) - stringlist_append_ref( argv , job_argv[ iarg ]); - } - free( num_cpu_string ); - util_safe_free( quoted_resource_request ); - return argv; -} - - -/** - * Submit internal job (LSF_SUBMIT_INTERNAL) using system calls instead of - * invoking shell commands. This method only works when actually called from - * an LSF node. - * - * Note that this method does not support the EXCLUDE_HOST configuration option. - */ -static int lsf_driver_submit_internal_job( lsf_driver_type * driver , - const char * lsf_stdout , - const char * job_name , - const char * submit_cmd , - int num_cpu , - int argc, - const char ** argv) { - -#ifdef HAVE_LSF_LIBRARY - char * command; - { - buffer_type * command_buffer = buffer_alloc( 256 ); - buffer_strcat( command_buffer , submit_cmd ); - for (int iarg = 0; iarg < argc; iarg++) { - buffer_strcat( command_buffer , " "); - buffer_strcat( command_buffer , argv[ iarg ]); - } - command = buffer_get_data( command_buffer ); - buffer_free_container( command_buffer ); - } - - { - int options = SUB_JOB_NAME + SUB_OUT_FILE; - - if (driver->queue_name != NULL) - options += SUB_QUEUE; - - if (driver->resource_request != NULL) - options += SUB_RES_REQ; - - if (driver->login_shell != NULL) - options += SUB_LOGIN_SHELL; - - driver->lsf_request.options = options; - } - - driver->lsf_request.resReq = driver->resource_request; - driver->lsf_request.loginShell = driver->login_shell; - driver->lsf_request.queue = driver->queue_name; - driver->lsf_request.jobName = (char *) job_name; - driver->lsf_request.outFile = (char *) lsf_stdout; - driver->lsf_request.command = command; - driver->lsf_request.numProcessors = num_cpu; - - { - int lsf_jobnr = lsb_submitjob( driver->lsb , &driver->lsf_request , &driver->lsf_reply ); - free( command ); /* I trust the lsf layer is finished with the command? */ - if (lsf_jobnr <= 0) - fprintf(stderr,"%s: ** Warning: lsb_submit() failed: %s \n",__func__ , lsb_sys_msg( driver->lsb )); - - return lsf_jobnr; - } -#else - lsf_driver_internal_error( driver ); - return -1; -#endif -} - - - -static int lsf_driver_submit_shell_job(lsf_driver_type * driver , - const char * lsf_stdout , - const char * job_name , - const char * submit_cmd , - int num_cpu , - int job_argc, - const char ** job_argv) { - int job_id; - char * tmp_file = util_alloc_tmp_file("/tmp" , "enkf-submit" , true); - - { - stringlist_type * remote_argv = lsf_driver_alloc_cmd( driver , lsf_stdout , job_name , submit_cmd , num_cpu , job_argc , job_argv); - - if (driver->submit_method == LSF_SUBMIT_REMOTE_SHELL) { - char ** argv = util_calloc( 2 , sizeof * argv ); - argv[0] = driver->remote_lsf_server; - argv[1] = stringlist_alloc_joined_string( remote_argv , " "); - - if (driver->debug_output) - printf("Submitting: %s %s %s \n",driver->rsh_cmd , argv[0] , argv[1]); - - util_spawn_blocking(driver->rsh_cmd, 2, (const char **) argv, tmp_file, NULL); - - free( argv[1] ); - free( argv ); - } else if (driver->submit_method == LSF_SUBMIT_LOCAL_SHELL) { - char ** argv = stringlist_alloc_char_ref( remote_argv ); - - if (driver->debug_output) { - printf("Submitting: %s ",driver->bsub_cmd); - stringlist_fprintf(remote_argv , " " , stdout); - printf("\n"); - } - util_spawn_blocking(driver->bsub_cmd, stringlist_get_size( remote_argv), (const char **) argv, tmp_file, tmp_file); - free( argv ); - } - - stringlist_free( remote_argv ); - } - - job_id = lsf_job_parse_bsub_stdout(driver->bsub_cmd , tmp_file); - util_unlink_existing( tmp_file ); - free(tmp_file); - return job_id; -} - - - -static int lsf_driver_get_status__(lsf_driver_type * driver , const char * status, const char * job_id) { - if (hash_has_key( driver->status_map , status)) - return hash_get_int( driver->status_map , status); - else { - util_exit("The lsf_status:%s for job:%s is not recognized; call your LSF administrator - sorry :-( \n", status , job_id); - return -1; - } -} - - - -static void lsf_driver_update_bjobs_table(lsf_driver_type * driver) { - char * tmp_file = util_alloc_tmp_file("/tmp" , "enkf-bjobs" , true); - - if (driver->submit_method == LSF_SUBMIT_REMOTE_SHELL) { - char ** argv = util_calloc( 2 , sizeof * argv); - argv[0] = driver->remote_lsf_server; - argv[1] = util_alloc_sprintf("%s -a" , driver->bjobs_cmd); - util_spawn_blocking(driver->rsh_cmd, 2, (const char **) argv, tmp_file, NULL); - free( argv[1] ); - free( argv ); - } else if (driver->submit_method == LSF_SUBMIT_LOCAL_SHELL) { - char ** argv = util_calloc( 1 , sizeof * argv); - argv[0] = "-a"; - util_spawn_blocking(driver->bjobs_cmd, 1, (const char **) argv, tmp_file, NULL); - free( argv ); - } - - { - char user[32]; - char status[16]; - FILE *stream = util_fopen(tmp_file , "r");; - bool at_eof = false; - hash_clear(driver->bjobs_cache); - util_fskip_lines(stream , 1); - while (!at_eof) { - char * line = util_fscanf_alloc_line(stream , &at_eof); - if (line != NULL) { - int job_id_int; - - if (sscanf(line , "%d %s %s", &job_id_int , user , status) == 3) { - char * job_id = util_alloc_sprintf("%d" , job_id_int); - - if (hash_has_key( driver->my_jobs , job_id )) /* Consider only jobs submitted by this ERT instance - not old jobs lying around from the same user. */ - hash_insert_int(driver->bjobs_cache , job_id , lsf_driver_get_status__( driver , status , job_id)); - - free(job_id); - } - free(line); - } - } - fclose(stream); - } - util_unlink_existing(tmp_file); - free(tmp_file); -} - - - -static int lsf_driver_get_job_status_libary(void * __driver , void * __job) { - if (__job == NULL) - /* the job has not been registered at all ... */ - return JOB_QUEUE_NOT_ACTIVE; - else { - int status; - lsf_driver_type * driver = lsf_driver_safe_cast( __driver ); -#ifdef HAVE_LSF_LIBRARY - lsf_job_type * job = lsf_job_safe_cast( __job ); - if (lsb_openjob( driver->lsb , job->lsf_jobnr) != 1) { - /* - Failed to get information about the job - we boldly assume - the following situation has occured: - - 1. The job is running happily along. - 2. The lsf deamon is not responding for a long time. - 3. The job finishes, and is eventually expired from the LSF job database. - 4. The lsf deamon answers again - but can not find the job... - - */ - fprintf(stderr,"Warning: failed to get status information for job:%ld - assuming it is finished. \n", job->lsf_jobnr); - status = JOB_QUEUE_DONE; - } else { - struct jobInfoEnt *job_info = lsb_readjob( driver->lsb ); - if (job->num_exec_host == 0) { - job->num_exec_host = job_info->numExHosts; - job->exec_host = util_alloc_stringlist_copy( (const char **) job_info->exHosts , job->num_exec_host); - } - status = job_info->status; - lsb_closejob(driver->lsb); - } -#else - lsf_driver_internal_error( driver ); - /* the above function calls exit(), so this value is never returned */ - status = JOB_QUEUE_FAILED; -#endif - - return status; - } -} - - -static bool lsf_driver_run_bhist(lsf_driver_type * driver , lsf_job_type * job , int * pend_time , int * run_time) { - bool bhist_ok = true; - char * output_file = util_alloc_tmp_file("/tmp" , "bhist" , true); - - if (driver->submit_method == LSF_SUBMIT_REMOTE_SHELL) { - char ** argv = util_calloc( 2 , sizeof * argv); - argv[0] = driver->remote_lsf_server; - argv[1] = util_alloc_sprintf("%s %s" , driver->bhist_cmd , job->lsf_jobnr_char); - util_spawn_blocking(driver->rsh_cmd, 2, (const char **) argv, output_file, NULL); - free( argv[1] ); - free( argv ); - } else if (driver->submit_method == LSF_SUBMIT_LOCAL_SHELL) { - char ** argv = util_calloc( 1 , sizeof * argv); - argv[0] = job->lsf_jobnr_char; - util_spawn_blocking(driver->bjobs_cmd, 2, (const char **) argv, output_file, NULL); - free( argv ); - } - - { - char job_id[16]; - char user[32]; - char job_name[32]; - int psusp_time; - - FILE *stream = util_fopen(output_file , "r");; - util_fskip_lines(stream , 2); - - if ( fscanf( stream , "%s %s %s %d %d %d" , job_id , user , job_name , pend_time , &psusp_time , run_time) == 6) - bhist_ok = true; - else - bhist_ok = false; - - fclose( stream ); - } - util_unlink_existing(output_file); - free(output_file); - - return bhist_ok; -} - -/* - When a job has completed you can query the status using the bjobs - command for a while, and then the job will be evicted from the LSF - status table. If there have been connection problems with the LSF - server we can risk a situation where a job has completed and - subsequently evicted from the LSF status table, before we are able - to record the DONE/EXIT status. - - When a job is missing from the bjobs_cache table we as a last resort - invoke the bhist command (which is based on internal LSF data with - much longer lifetime) and measure the change in run_time and - pend_time between two subsequent calls: - - - 1. ((pend_time1 == pend_time2) && (run_time1 == run_time2)) : - Nothing is happening, and we assume that the job is DONE (this - method can not distinguish between DONE and EXIT). - - 2. (run_time2 > run_time1) : The job is running. - - 3. (pend_tim2 > pend_time1) : The job is pending. - - 4. Status unknown - have not got a clue?! -*/ - - -static int lsf_driver_get_bhist_status_shell( lsf_driver_type * driver , lsf_job_type * job) { - int status = JOB_STAT_UNKWN; - int sleep_time = 4; - int run_time1, run_time2, pend_time1 , pend_time2; - - fprintf(stderr,"** Warning: could not find status of job:%s using \'bjobs\' - trying with \'bhist\'.\n" , job->lsf_jobnr_char); - if (!lsf_driver_run_bhist( driver , job , &pend_time1 , &run_time1)) - return status; - - sleep( sleep_time ); - if (!lsf_driver_run_bhist( driver , job , &pend_time2 , &run_time2)) - return status; - - if ((run_time1 == run_time2) && (pend_time1 == pend_time2)) - status = JOB_STAT_DONE; - - if (pend_time2 > pend_time1) - status = JOB_STAT_PEND; - - if (run_time2 > run_time1) - status = JOB_STAT_RUN; - - return status; -} - - -static int lsf_driver_get_job_status_shell(void * __driver , void * __job) { - int status = JOB_STAT_NULL; - - if (__job != NULL) { - lsf_job_type * job = lsf_job_safe_cast( __job ); - lsf_driver_type * driver = lsf_driver_safe_cast( __driver ); - - { - /** - Updating the bjobs_table of the driver involves a significant change in - the internal state of the driver; that is semantically a bit - unfortunate because this is clearly a get() function; to protect - against concurrent updates of this table we use a mutex. - */ - pthread_mutex_lock( &driver->bjobs_mutex ); - { - bool update_cache = ((difftime(time(NULL) , driver->last_bjobs_update) > driver->bjobs_refresh_interval) || - (!hash_has_key( driver->bjobs_cache , job->lsf_jobnr_char) )); - if (update_cache) { - lsf_driver_update_bjobs_table(driver); - driver->last_bjobs_update = time( NULL ); - } - } - pthread_mutex_unlock( &driver->bjobs_mutex ); - - if (hash_has_key( driver->bjobs_cache , job->lsf_jobnr_char) ) - status = hash_get_int(driver->bjobs_cache , job->lsf_jobnr_char); - else { - /* - The job was not in the status cache, this *might* mean that - it has completed/exited and fallen out of the bjobs status - table maintained by LSF. We try calling bhist to get the status. - */ - status = lsf_driver_get_bhist_status_shell( driver , job ); - if (status != JOB_STAT_UNKWN) - hash_insert_int( driver->bjobs_cache , job->lsf_jobnr_char , status ); - } - } - } - - return status; -} - - -job_status_type lsf_driver_convert_status( int lsf_status ) { - job_status_type job_status; - switch (lsf_status) { - case JOB_STAT_NULL: - job_status = JOB_QUEUE_NOT_ACTIVE; - break; - case JOB_STAT_PEND: - job_status = JOB_QUEUE_PENDING; - break; - case JOB_STAT_SSUSP: - job_status = JOB_QUEUE_RUNNING; - break; - case JOB_STAT_USUSP: - job_status = JOB_QUEUE_RUNNING; - break; - case JOB_STAT_PSUSP: - job_status = JOB_QUEUE_RUNNING; - break; - case JOB_STAT_RUN: - job_status = JOB_QUEUE_RUNNING; - break; - case JOB_STAT_DONE: - job_status = JOB_QUEUE_DONE; - break; - case JOB_STAT_EXIT: - job_status = JOB_QUEUE_EXIT; - break; - case JOB_STAT_UNKWN: // Have lost contact with one of the daemons. - job_status = JOB_QUEUE_EXIT; - break; - case JOB_STAT_DONE + JOB_STAT_PDONE: // = 192. JOB_STAT_PDONE: the job had a - // post-execution script which completed - // successfully. - job_status = JOB_QUEUE_DONE; - break; - default: - job_status = JOB_QUEUE_NOT_ACTIVE; - util_abort("%s: unrecognized lsf status code:%d \n",__func__ , lsf_status ); - } - return job_status; -} - - -int lsf_driver_get_job_status_lsf(void * __driver , void * __job) { - int lsf_status; - lsf_driver_type * driver = lsf_driver_safe_cast( __driver ); - - if (driver->submit_method == LSF_SUBMIT_INTERNAL) - lsf_status = lsf_driver_get_job_status_libary(__driver , __job); - else - lsf_status = lsf_driver_get_job_status_shell(__driver , __job); - - return lsf_status; -} - - - -job_status_type lsf_driver_get_job_status(void * __driver , void * __job) { - int lsf_status = lsf_driver_get_job_status_lsf( __driver , __job ); - return lsf_driver_convert_status( lsf_status ); -} - - - - -void lsf_driver_free_job(void * __job) { - lsf_job_type * job = lsf_job_safe_cast( __job ); - lsf_job_free(job); -} - -static void lsf_driver_node_failure(lsf_driver_type * driver, long lsf_job_id) { - fprintf(stderr, "%s attempting to blacklist nodes for job id %ld.\n", __func__, lsf_job_id); - - { - char * fname = lsf_job_write_bjobs_to_file(driver->bsub_cmd, driver, lsf_job_id); - stringlist_type * hosts = lsf_job_alloc_parse_hostnames(fname); - char* hostnames = stringlist_alloc_joined_string(hosts, ", "); - fprintf(stderr, "%s blacklisting nodes %s.\n", __func__, hostnames); - - lsf_driver_add_exclude_hosts(driver, hostnames); - - util_free(hostnames); - stringlist_free(hosts); - util_free(fname); - } - -} - -void lsf_driver_blacklist_node(void * __driver, void * __job) { - lsf_driver_type * driver = lsf_driver_safe_cast(__driver); - lsf_job_type * job = lsf_job_safe_cast(__job); - long lsf_job_id = lsf_job_get_jobnr(job); - lsf_driver_node_failure(driver, lsf_job_id); -} - - -void lsf_driver_kill_job(void * __driver , void * __job) { - lsf_driver_type * driver = lsf_driver_safe_cast( __driver ); - lsf_job_type * job = lsf_job_safe_cast( __job ); - { - if (driver->submit_method == LSF_SUBMIT_INTERNAL) { -#ifdef HAVE_LSF_LIBRARY - lsb_killjob( driver->lsb , job->lsf_jobnr); -#else - lsf_driver_internal_error( driver ); -#endif - } else { - if (driver->submit_method == LSF_SUBMIT_REMOTE_SHELL) { - char ** argv = util_calloc( 2, sizeof * argv ); - argv[0] = driver->remote_lsf_server; - argv[1] = util_alloc_sprintf("%s %s" , driver->bkill_cmd , job->lsf_jobnr_char); - - util_spawn_blocking(driver->rsh_cmd, 2, (const char **) argv, NULL, NULL); - - free( argv[1] ); - free( argv ); - } else if (driver->submit_method == LSF_SUBMIT_LOCAL_SHELL) { - util_spawn_blocking(driver->bkill_cmd, 1, (const char **) &job->lsf_jobnr_char, NULL, NULL); - } - } - } -} - - - - - -void * lsf_driver_submit_job(void * __driver , - const char * submit_cmd , - int num_cpu , - const char * run_path , - const char * job_name , - int argc, - const char ** argv ) { - lsf_driver_type * driver = lsf_driver_safe_cast( __driver ); - lsf_driver_assert_submit_method( driver ); - { - lsf_job_type * job = lsf_job_alloc(); - usleep( driver->submit_sleep ); - - { - char * lsf_stdout = util_alloc_filename(run_path , job_name , "LSF-stdout"); - lsf_submit_method_enum submit_method = driver->submit_method; - pthread_mutex_lock( &driver->submit_lock ); - - if (driver->debug_output) - printf("LSF DRIVER submitting using method:%d \n",submit_method); - - if (submit_method == LSF_SUBMIT_INTERNAL) { - if (stringlist_get_size(driver->exclude_hosts) > 0) - printf("WARNING: EXCLUDE_HOST is not supported with submit method LSF_SUBMIT_INTERNAL"); - job->lsf_jobnr = lsf_driver_submit_internal_job( driver , lsf_stdout , job_name , submit_cmd , num_cpu , argc, argv); - } else { - job->lsf_jobnr = lsf_driver_submit_shell_job( driver , lsf_stdout , job_name , submit_cmd , num_cpu , argc, argv); - job->lsf_jobnr_char = util_alloc_sprintf("%ld" , job->lsf_jobnr); - hash_insert_ref( driver->my_jobs , job->lsf_jobnr_char , NULL ); - } - - pthread_mutex_unlock( &driver->submit_lock ); - free( lsf_stdout ); - } - - if (job->lsf_jobnr > 0) - return job; - else { - /* - The submit failed - the queue system shall handle - NULL return values. - */ - driver->error_count++; - - if (driver->error_count >= driver->max_error_count) - util_exit("Maximum number of submit errors exceeded - giving up\n"); - else { - fprintf(stderr,"** ERROR ** Failed when submitting to LSF - will try again.\n"); - usleep( driver->submit_error_sleep ); - } - - lsf_job_free(job); - return NULL; - } - } -} - - - -void lsf_driver_free(lsf_driver_type * driver ) { - util_safe_free(driver->login_shell); - util_safe_free(driver->queue_name); - util_safe_free(driver->resource_request ); - util_safe_free(driver->remote_lsf_server ); - util_safe_free(driver->rsh_cmd ); - stringlist_free(driver->exclude_hosts); - free( driver->bhist_cmd ); - free( driver->bkill_cmd ); - free( driver->bjobs_cmd ); - free( driver->bsub_cmd ); - - hash_free(driver->status_map); - hash_free(driver->bjobs_cache); - hash_free(driver->my_jobs); - -#ifdef HAVE_LSF_LIBRARY - if (driver->lsb != NULL) - lsb_free( driver->lsb ); -#endif - - free(driver); - driver = NULL; -} - -void lsf_driver_free__(void * __driver ) { - lsf_driver_type * driver = lsf_driver_safe_cast( __driver ); - lsf_driver_free( driver ); -} - - -static void lsf_driver_set_queue( lsf_driver_type * driver, const char * queue ) { - driver->queue_name = util_realloc_string_copy( driver->queue_name , queue); -} - - -static void lsf_driver_set_login_shell( lsf_driver_type * driver, const char * login_shell ) { - driver->login_shell = util_realloc_string_copy( driver->login_shell , login_shell); -} - -static void lsf_driver_set_rsh_cmd( lsf_driver_type * driver , const char * rsh_cmd) { - driver->rsh_cmd = util_realloc_string_copy( driver->rsh_cmd , rsh_cmd ); -} - -static void lsf_driver_set_bsub_cmd( lsf_driver_type * driver , const char * bsub_cmd) { - driver->bsub_cmd = util_realloc_string_copy( driver->bsub_cmd , bsub_cmd ); -} - -static void lsf_driver_set_bjobs_cmd( lsf_driver_type * driver , const char * bjobs_cmd) { - driver->bjobs_cmd = util_realloc_string_copy( driver->bjobs_cmd , bjobs_cmd ); -} - -static void lsf_driver_set_bkill_cmd( lsf_driver_type * driver , const char * bkill_cmd) { - driver->bkill_cmd = util_realloc_string_copy( driver->bkill_cmd , bkill_cmd ); -} - -static void lsf_driver_set_bhist_cmd( lsf_driver_type * driver , const char * bhist_cmd) { - driver->bhist_cmd = util_realloc_string_copy( driver->bhist_cmd , bhist_cmd ); -} - -#ifdef HAVE_LSF_LIBRARY -static void lsf_driver_set_internal_submit( lsf_driver_type * driver) { - /* No remote server has been set - assuming we can issue proper library calls. */ - /* The BSUB_QUEUE variable must NOT be set when using the shell - function, because then stdout is redirected and read. */ - - util_setenv("BSUB_QUIET" , "yes"); - driver->submit_method = LSF_SUBMIT_INTERNAL; - util_safe_free( driver->remote_lsf_server ); - driver->remote_lsf_server = NULL; -} -#endif - -static void lsf_driver_set_remote_server( lsf_driver_type * driver , const char * remote_server) { - if (remote_server == NULL) { -#ifdef HAVE_LSF_LIBRARY - if (driver->lsb) - lsf_driver_set_internal_submit( driver ); - else - lsf_driver_set_remote_server( driver , LOCAL_LSF_SERVER ); // If initializing the lsb layer failed we try the local shell commands. -#endif - } else { - driver->remote_lsf_server = util_realloc_string_copy( driver->remote_lsf_server , remote_server ); - util_unsetenv( "BSUB_QUIET" ); - { - char * tmp_server = util_alloc_strupr_copy( remote_server ); - - if (strcmp(tmp_server , LOCAL_LSF_SERVER) == 0) - driver->submit_method = LSF_SUBMIT_LOCAL_SHELL; - else if (strcmp(tmp_server , NULL_LSF_SERVER) == 0) // We trap the special string 'NULL' and call again with a true NULL pointer. - lsf_driver_set_remote_server( driver , NULL); - else - driver->submit_method = LSF_SUBMIT_REMOTE_SHELL; - - free( tmp_server ); - } - } -} - -void lsf_driver_add_exclude_hosts(lsf_driver_type * driver, const char * excluded) { - stringlist_type * host_list = stringlist_alloc_from_split(excluded, ", "); - for (int i = 0; i < stringlist_get_size(host_list); i++) { - const char * excluded = stringlist_iget(host_list, i); - if (!stringlist_contains(driver->exclude_hosts, excluded)) - stringlist_append_copy(driver->exclude_hosts, excluded); - } -} - -lsf_submit_method_enum lsf_driver_get_submit_method( const lsf_driver_type * driver ) { - return driver->submit_method; -} - - -static bool lsf_driver_set_debug_output( lsf_driver_type * driver , const char * arg) { - bool debug_output; - bool OK = util_sscanf_bool( arg , &debug_output); - if (OK) - driver->debug_output = debug_output; - - return OK; -} - - -static bool lsf_driver_set_submit_sleep( lsf_driver_type * driver , const char * arg) { - double submit_sleep; - bool OK = util_sscanf_double( arg , &submit_sleep); - if (OK) - driver->submit_sleep = (int) (1000000 * submit_sleep); - - return OK; -} - -void lsf_driver_set_bjobs_refresh_interval_option( lsf_driver_type * driver , const char * option_value) { - int refresh_interval; - if (util_sscanf_int( option_value , &refresh_interval)) - lsf_driver_set_bjobs_refresh_interval( driver , refresh_interval ); -} - - - -/*****************************************************************/ -/* Generic functions for runtime manipulation of options. - - LSF_SERVER - LSF_QUEUE - LSF_RESOURCE -*/ - -bool lsf_driver_set_option( void * __driver , const char * option_key , const void * value) { - lsf_driver_type * driver = lsf_driver_safe_cast( __driver ); - bool has_option = true; - { - if (strcmp( LSF_RESOURCE , option_key ) == 0) - driver->resource_request = util_realloc_string_copy( driver->resource_request , value ); - else if (strcmp( LSF_SERVER , option_key) == 0) - lsf_driver_set_remote_server( driver , value ); - else if (strcmp( LSF_QUEUE , option_key) == 0) - lsf_driver_set_queue( driver , value ); - else if (strcmp( LSF_LOGIN_SHELL , option_key) == 0) - lsf_driver_set_login_shell( driver , value ); - else if (strcmp( LSF_RSH_CMD , option_key) == 0) - lsf_driver_set_rsh_cmd( driver , value ); - else if (strcmp( LSF_BSUB_CMD , option_key) == 0) - lsf_driver_set_bsub_cmd( driver , value ); - else if (strcmp( LSF_BJOBS_CMD , option_key) == 0) - lsf_driver_set_bjobs_cmd( driver , value ); - else if (strcmp( LSF_BKILL_CMD , option_key) == 0) - lsf_driver_set_bkill_cmd( driver , value ); - else if (strcmp( LSF_BHIST_CMD , option_key) == 0) - lsf_driver_set_bhist_cmd( driver , value ); - else if (strcmp( LSF_DEBUG_OUTPUT , option_key) == 0) - lsf_driver_set_debug_output( driver , value ); - else if (strcmp( LSF_SUBMIT_SLEEP , option_key) == 0) - lsf_driver_set_submit_sleep( driver , value ); - else if (strcmp( LSF_EXCLUDE_HOST , option_key) == 0) - lsf_driver_add_exclude_hosts( driver , value ); - else if (strcmp( LSF_BJOBS_TIMEOUT , option_key) == 0) - lsf_driver_set_bjobs_refresh_interval_option( driver , value ); - else - has_option = false; - } - return has_option; -} - - -const void * lsf_driver_get_option( const void * __driver , const char * option_key) { - const lsf_driver_type * driver = lsf_driver_safe_cast_const( __driver ); - { - if (strcmp( LSF_RESOURCE , option_key ) == 0) - return driver->resource_request; - else if (strcmp( LSF_SERVER , option_key ) == 0) - return driver->remote_lsf_server; - else if (strcmp( LSF_QUEUE , option_key ) == 0) - return driver->queue_name; - else if (strcmp( LSF_LOGIN_SHELL , option_key ) == 0) - return driver->login_shell; - else if (strcmp( LSF_RSH_CMD , option_key ) == 0) - return driver->rsh_cmd; - else if (strcmp( LSF_BJOBS_CMD , option_key ) == 0) - return driver->bjobs_cmd; - else if (strcmp( LSF_BSUB_CMD , option_key ) == 0) - return driver->bsub_cmd; - else if (strcmp( LSF_BKILL_CMD , option_key ) == 0) - return driver->bkill_cmd; - else if (strcmp( LSF_BHIST_CMD , option_key ) == 0) - return driver->bhist_cmd; - else if (strcmp( LSF_BJOBS_TIMEOUT , option_key ) == 0) { - /* This will leak. */ - char * timeout_string = util_alloc_sprintf( "%d" , driver->bjobs_refresh_interval ); - return timeout_string; - } else { - util_abort("%s: option_id:%s not recognized for LSF driver \n",__func__ , option_key); - return NULL; - } - } -} - - - -bool lsf_driver_has_option( const void * __driver , const char * option_key) { - return false; -} - -void lsf_driver_init_option_list(stringlist_type * option_list) { - stringlist_append_ref(option_list, LSF_QUEUE); - stringlist_append_ref(option_list, LSF_RESOURCE); - stringlist_append_ref(option_list, LSF_SERVER); - stringlist_append_ref(option_list, LSF_RSH_CMD); - stringlist_append_ref(option_list, LSF_LOGIN_SHELL); - stringlist_append_ref(option_list, LSF_BSUB_CMD); - stringlist_append_ref(option_list, LSF_BJOBS_CMD); - stringlist_append_ref(option_list, LSF_BKILL_CMD); - stringlist_append_ref(option_list, LSF_BHIST_CMD); - stringlist_append_ref(option_list, LSF_BJOBS_TIMEOUT); -} - - - -/*****************************************************************/ - -/* - Observe that this driver IS not properly initialized when returning - from this function, the option interface must be used to set the - keys: -*/ - -void lsf_driver_set_bjobs_refresh_interval( lsf_driver_type * driver , int refresh_interval) { - driver->bjobs_refresh_interval = refresh_interval; -} - - - - -static void lsf_driver_lib_init( lsf_driver_type * lsf_driver ) { -#ifdef HAVE_LSF_LIBRARY - memset(&lsf_driver->lsf_request , 0 , sizeof (lsf_driver->lsf_request)); - lsf_driver->lsf_request.beginTime = 0; - lsf_driver->lsf_request.termTime = 0; - lsf_driver->lsf_request.numProcessors = 1; - lsf_driver->lsf_request.maxNumProcessors = 1; - { - int i; - for (i=0; i < LSF_RLIM_NLIMITS; i++) - lsf_driver->lsf_request.rLimits[i] = DEFAULT_RLIMIT; - } - lsf_driver->lsf_request.options2 = 0; - - lsf_driver->lsb = lsb_alloc(); - if (lsb_ready(lsf_driver->lsb)) - lsb_initialize(lsf_driver->lsb); - else { - lsb_free( lsf_driver->lsb ); - lsf_driver->lsb = NULL; - } -#endif -} - - - -static void lsf_driver_shell_init( lsf_driver_type * lsf_driver ) { - lsf_driver->last_bjobs_update = time( NULL ); - lsf_driver->bjobs_cache = hash_alloc(); - lsf_driver->my_jobs = hash_alloc(); - lsf_driver->status_map = hash_alloc(); - lsf_driver->bsub_cmd = NULL; - lsf_driver->bjobs_cmd = NULL; - lsf_driver->bkill_cmd = NULL; - lsf_driver->bhist_cmd = NULL; - - - hash_insert_int(lsf_driver->status_map , "PEND" , JOB_STAT_PEND); - hash_insert_int(lsf_driver->status_map , "SSUSP" , JOB_STAT_SSUSP); - hash_insert_int(lsf_driver->status_map , "PSUSP" , JOB_STAT_PSUSP); - hash_insert_int(lsf_driver->status_map , "USUSP" , JOB_STAT_USUSP); - hash_insert_int(lsf_driver->status_map , "RUN" , JOB_STAT_RUN); - hash_insert_int(lsf_driver->status_map , "EXIT" , JOB_STAT_EXIT); - hash_insert_int(lsf_driver->status_map , "ZOMBI" , JOB_STAT_EXIT); /* The ZOMBI status does not seem to be available from the api. */ - hash_insert_int(lsf_driver->status_map , "DONE" , JOB_STAT_DONE); - hash_insert_int(lsf_driver->status_map , "PDONE" , JOB_STAT_PDONE); /* Post-processor is done. */ - hash_insert_int(lsf_driver->status_map , "UNKWN" , JOB_STAT_UNKWN); /* Uncertain about this one */ - pthread_mutex_init( &lsf_driver->bjobs_mutex , NULL ); -} - - - -void * lsf_driver_alloc( ) { - lsf_driver_type * lsf_driver = util_malloc(sizeof * lsf_driver ); - UTIL_TYPE_ID_INIT( lsf_driver , LSF_DRIVER_TYPE_ID); - lsf_driver->submit_method = LSF_SUBMIT_INVALID; - lsf_driver->login_shell = NULL; - lsf_driver->queue_name = NULL; - lsf_driver->remote_lsf_server = NULL; - lsf_driver->rsh_cmd = NULL; - lsf_driver->resource_request = NULL; - lsf_driver->error_count = 0; - lsf_driver->max_error_count = MAX_ERROR_COUNT; - lsf_driver->submit_error_sleep = SUBMIT_ERROR_SLEEP * 1000000; - lsf_driver->exclude_hosts = stringlist_alloc_new(); - pthread_mutex_init( &lsf_driver->submit_lock , NULL ); - - lsf_driver_lib_init( lsf_driver ); - lsf_driver_shell_init( lsf_driver ); - - lsf_driver_set_option( lsf_driver , LSF_SERVER , NULL ); - lsf_driver_set_option( lsf_driver , LSF_RSH_CMD , DEFAULT_RSH_CMD ); - lsf_driver_set_option( lsf_driver , LSF_BSUB_CMD , DEFAULT_BSUB_CMD ); - lsf_driver_set_option( lsf_driver , LSF_BJOBS_CMD , DEFAULT_BJOBS_CMD ); - lsf_driver_set_option( lsf_driver , LSF_BKILL_CMD , DEFAULT_BKILL_CMD ); - lsf_driver_set_option( lsf_driver , LSF_BHIST_CMD , DEFAULT_BHIST_CMD ); - lsf_driver_set_option( lsf_driver , LSF_DEBUG_OUTPUT , "FALSE"); - lsf_driver_set_option( lsf_driver , LSF_SUBMIT_SLEEP , DEFAULT_SUBMIT_SLEEP); - lsf_driver_set_option( lsf_driver , LSF_BJOBS_TIMEOUT , BJOBS_REFRESH_TIME); - return lsf_driver; -} - - -/*****************************************************************/ - diff --git a/ThirdParty/Ert/libjob_queue/src/queue_driver.c b/ThirdParty/Ert/libjob_queue/src/queue_driver.c deleted file mode 100644 index e171ba5bb0..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/queue_driver.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'queue_driver.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ - -#include -#include - -#include - -#include -#include -#include -#include -#include - - -/** - This file implements the datatype queue_driver_type which is an - abstract datatype for communicating with a subsystem for - communcating with other low-level systems for running external - jobs. The job_queue instance, which will handle a queue of jobs, - interacts with the jobs through a queue_driver instance. - - The queue_driver type is a quite small datastructure which "wraps" - and underlying specific driver instance; examples of specific - driver instances are the lsf_driver which communicates with the LSF - system and the local_driver which runs jobs directly on the current - workstation. The queue_driver type contains essentially three - different types of fields: - - 1. Functions pointers for manipulating the jobs, and the state of - the low-level driver. - - 2. An opaque (i.e. void *) pointer to the state of the low level - driver. This will be passed as first argument to all the - function pointers, e.g. like the "self" in Python methods. - - 3. Some data fields which are common to all driver types. - - */ - -#define QUEUE_DRIVER_ID 86516032 - -struct queue_driver_struct { - UTIL_TYPE_ID_DECLARATION; - /* - Function pointers - pointing to low level functions in the implementations of - e.g. lsf_driver. - */ - submit_job_ftype * submit; - free_job_ftype * free_job; - kill_job_ftype * kill_job; - blacklist_node_ftype * blacklist_node; - get_status_ftype * get_status; - free_queue_driver_ftype * free_driver; - set_option_ftype * set_option; - get_option_ftype * get_option; - has_option_ftype * has_option; - init_option_list_ftype * init_options; - - void * data; /* Driver specific data - passed as first argument to the driver functions above. */ - - /* - Generic data - common to all driver types. - */ - char * name; /* String name of driver. */ - job_driver_type driver_type; /* Enum value for driver. */ - char * max_running_string; - int max_running; /* Possible to maintain different max_running values for different - drivers; the value 0 is interpreted as no limit - i.e. the queue layer - will (try) to send an unlimited number of jobs to the driver. */ - -}; - - - -/*****************************************************************/ - - -/*****************************************************************/ - -void queue_driver_set_max_running(queue_driver_type * driver, int max_running) { - driver->max_running_string = util_realloc_sprintf(driver->max_running_string,"%d", max_running); - driver->max_running = max_running; -} - -int queue_driver_get_max_running(const queue_driver_type * driver) { - return driver->max_running; -} - -const char * queue_driver_get_name(const queue_driver_type * driver) { - return driver->name; -} - - -static bool queue_driver_set_generic_option__(queue_driver_type * driver, const char * option_key, const void * value) { - bool option_set = true; - { - if (strcmp(MAX_RUNNING, option_key) == 0) { - int max_running_int = 0; - if (util_sscanf_int(value, &max_running_int)) { - queue_driver_set_max_running(driver, max_running_int); - option_set = true; - } - else - option_set = false; - } else - option_set = false; - } - return option_set; -} - -static void * queue_driver_get_generic_option__(queue_driver_type * driver, const char * option_key) { - if (strcmp(MAX_RUNNING, option_key) == 0) { - return driver->max_running_string; - } else { - util_abort("%s: driver:%s does not support generic option %s\n", __func__, driver->name, option_key); - return NULL; - } -} - -static bool queue_driver_has_generic_option__(queue_driver_type * driver, const char * option_key) { - if (strcmp(MAX_RUNNING, option_key) == 0) - return true; - else - return false; -} - -/** - Set option - can also be used to perform actions - not only setting - of parameters. There is no limit :-) - */ -bool queue_driver_set_option(queue_driver_type * driver, const char * option_key, const void * value) { - if (queue_driver_set_generic_option__(driver, option_key, value)) { - return true; - } else if (driver->set_option != NULL) - /* The actual low level set functions can not fail! */ - return driver->set_option(driver->data, option_key, value); - else { - util_abort("%s: driver:%s does not support run time setting of options\n", __func__, driver->name); - return false; - } - return false; -} - - -/** - Observe that after the driver instance has been allocated it does - NOT support modification of the common fields, only the data owned - by the specific low level driver, i.e. the LSF data, can be - modified runtime. - - The driver returned from the queue_driver_alloc_empty() function is - NOT properly initialized and NOT ready for use. - */ - -static queue_driver_type * queue_driver_alloc_empty() { - queue_driver_type * driver = util_malloc(sizeof * driver); - UTIL_TYPE_ID_INIT(driver, QUEUE_DRIVER_ID); - driver->driver_type = NULL_DRIVER; - driver->submit = NULL; - driver->get_status = NULL; - driver->kill_job = NULL; - driver->free_job = NULL; - driver->free_driver = NULL; - driver->get_option = NULL; - driver->set_option = NULL; - driver->has_option = NULL; - driver->name = NULL; - driver->data = NULL; - driver->max_running_string = NULL; - driver->init_options = NULL; - - queue_driver_set_generic_option__(driver, MAX_RUNNING, "0"); - - return driver; -} - -static UTIL_SAFE_CAST_FUNCTION(queue_driver, QUEUE_DRIVER_ID) - - -/** - The driver created in this function has all the function pointers - correctly initialized; but no options have been set. I.e. unless - the driver in question needs no options (e.g. the LOCAL driver) the - returned driver will NOT be ready for use. - */ - - -queue_driver_type * queue_driver_alloc(job_driver_type type) { - queue_driver_type * driver = queue_driver_alloc_empty(); - driver->driver_type = type; - switch (type) { - case LSF_DRIVER: - driver->submit = lsf_driver_submit_job; - driver->get_status = lsf_driver_get_job_status; - driver->blacklist_node = lsf_driver_blacklist_node; - driver->kill_job = lsf_driver_kill_job; - driver->free_job = lsf_driver_free_job; - driver->free_driver = lsf_driver_free__; - driver->set_option = lsf_driver_set_option; - driver->get_option = lsf_driver_get_option; - driver->has_option = lsf_driver_has_option; - driver->name = util_alloc_string_copy("LSF"); - driver->init_options = lsf_driver_init_option_list; - driver->data = lsf_driver_alloc(); - break; - case LOCAL_DRIVER: - driver->submit = local_driver_submit_job; - driver->get_status = local_driver_get_job_status; - driver->blacklist_node = NULL; - driver->kill_job = local_driver_kill_job; - driver->free_job = local_driver_free_job; - driver->free_driver = local_driver_free__; - driver->name = util_alloc_string_copy("local"); - driver->init_options = local_driver_init_option_list; - driver->data = local_driver_alloc(); - break; - case RSH_DRIVER: - driver->submit = rsh_driver_submit_job; - driver->get_status = rsh_driver_get_job_status; - driver->blacklist_node = NULL; - driver->kill_job = rsh_driver_kill_job; - driver->free_job = rsh_driver_free_job; - driver->free_driver = rsh_driver_free__; - driver->set_option = rsh_driver_set_option; - driver->get_option = rsh_driver_get_option; - driver->name = util_alloc_string_copy("RSH"); - driver->init_options = rsh_driver_init_option_list; - driver->data = rsh_driver_alloc(); - break; - case TORQUE_DRIVER: - driver->submit = torque_driver_submit_job; - driver->get_status = torque_driver_get_job_status; - driver->blacklist_node = NULL; - driver->kill_job = torque_driver_kill_job; - driver->free_job = torque_driver_free_job; - driver->free_driver = torque_driver_free__; - driver->set_option = torque_driver_set_option; - driver->get_option = torque_driver_get_option; - driver->name = util_alloc_string_copy("TORQUE"); - driver->init_options = torque_driver_init_option_list; - driver->data = torque_driver_alloc(); - break; - default: - util_abort("%s: unrecognized driver type:%d \n", __func__, type); - } - - queue_driver_set_generic_option__(driver, MAX_RUNNING, "0"); - return driver; -} - - -/*****************************************************************/ - -bool queue_driver_has_option(queue_driver_type * driver, const char * option_key) { - if (driver->has_option != NULL) - return driver->has_option(driver, option_key); - else - return false; -} - -/*****************************************************************/ - -const void * queue_driver_get_option(queue_driver_type * driver, const char * option_key) { - if (queue_driver_has_generic_option__(driver, option_key)) { - return queue_driver_get_generic_option__(driver, option_key); - } else if (driver->get_option != NULL) - /* The actual low level set functions can not fail! */ - return driver->get_option(driver->data, option_key); - else { - util_abort("%s: driver:%s does not support run time reading of options\n", __func__, driver->name); - return NULL; - } - return NULL; -} - -/*****************************************************************/ - -void queue_driver_init_option_list(queue_driver_type * driver, stringlist_type * option_list) { - //Add options common for all driver types - stringlist_append_ref(option_list, MAX_RUNNING); - - //Add options for the specific driver type - if (driver->init_options) - driver->init_options(option_list); - else - util_abort("%s: driver:%s does not support run time reading of options\n", __func__, driver->name); - } - - -queue_driver_type * queue_driver_alloc_LSF(const char * queue_name, const char * resource_request, const char * remote_lsf_server) { - queue_driver_type * driver = queue_driver_alloc(LSF_DRIVER); - - queue_driver_set_option(driver, LSF_QUEUE, queue_name); - queue_driver_set_option(driver, LSF_RESOURCE, resource_request); - queue_driver_set_option(driver, LSF_SERVER, remote_lsf_server); - - return driver; -} - -queue_driver_type * queue_driver_alloc_TORQUE() { - queue_driver_type * driver = queue_driver_alloc(TORQUE_DRIVER); - return driver; -} - -queue_driver_type * queue_driver_alloc_RSH(const char * rsh_cmd, const hash_type * rsh_hostlist) { - queue_driver_type * driver = queue_driver_alloc(RSH_DRIVER); - - queue_driver_set_option(driver, RSH_HOSTLIST, rsh_hostlist); - queue_driver_set_option(driver, RSH_CMD, rsh_cmd); - - return driver; -} - -queue_driver_type * queue_driver_alloc_local() { - queue_driver_type * driver = queue_driver_alloc(LOCAL_DRIVER); - - /* No options set for the local driver. */ - - return driver; -} - -/* These are the functions used by the job_queue layer. */ - -void * queue_driver_submit_job(queue_driver_type * driver, const char * run_cmd, int num_cpu, const char * run_path, const char * job_name, int argc, const char ** argv) { - return driver->submit(driver->data, run_cmd, num_cpu, run_path, job_name, argc, argv); -} - -void queue_driver_free_job(queue_driver_type * driver, void * job_data) { - driver->free_job(job_data); -} - -void queue_driver_blacklist_node(queue_driver_type * driver, void * job_data) { - if (driver->driver_type == LSF_DRIVER) - driver->blacklist_node(driver->data, job_data); -} - -void queue_driver_kill_job(queue_driver_type * driver, void * job_data) { - driver->kill_job(driver->data, job_data); -} - -job_status_type queue_driver_get_status(queue_driver_type * driver, void * job_data) { - job_status_type status = driver->get_status(driver->data, job_data); - return status; -} - -void queue_driver_free_driver(queue_driver_type * driver) { - driver->free_driver(driver->data); -} - -/*****************************************************************/ - -void queue_driver_free(queue_driver_type * driver) { - queue_driver_free_driver(driver); - util_safe_free(driver->name); - util_safe_free(driver->max_running_string); - free(driver); -} - -void queue_driver_free__(void * driver) { - queue_driver_type * queue_driver = queue_driver_safe_cast(driver); - queue_driver_free(queue_driver); -} - - -/*****************************************************************/ - -/* Small functions to support enum introspection. */ - -const char * queue_driver_type_enum_iget(int index, int * value) { - - return util_enum_iget(index, JOB_DRIVER_ENUM_SIZE, (const util_enum_element_type []) { - JOB_DRIVER_ENUM_DEFS - }, value); -} diff --git a/ThirdParty/Ert/libjob_queue/src/rsh_driver.c b/ThirdParty/Ert/libjob_queue/src/rsh_driver.c deleted file mode 100644 index 5e6aa9d609..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/rsh_driver.c +++ /dev/null @@ -1,484 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rsh_driver.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - - -#include -#include -#include - -#include -#include - - - - - - -struct rsh_job_struct { - UTIL_TYPE_ID_DECLARATION; - bool active; /* Means that it allocated - not really in use */ - job_status_type status; - pthread_t run_thread; - const char * host_name; /* Currently not set */ - char * run_path; -}; - - - -typedef struct { - char * host_name; - int max_running; /* How many can the host handle. */ - int running; /* How many are currently running on the host (goverened by this driver instance that is). */ - pthread_mutex_t host_mutex; -} rsh_host_type; - - - -#define RSH_DRIVER_TYPE_ID 44963256 -#define RSH_JOB_TYPE_ID 63256701 - - -struct rsh_driver_struct { - UTIL_TYPE_ID_DECLARATION; - pthread_mutex_t submit_lock; - pthread_attr_t thread_attr; - char * rsh_command; - int num_hosts; - int last_host_index; - rsh_host_type **host_list; - hash_type *__host_hash; /* Stupid redundancy ... */ -}; - - - -/******************************************************************/ -static UTIL_SAFE_CAST_FUNCTION_CONST( rsh_driver , RSH_DRIVER_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION( rsh_driver , RSH_DRIVER_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION( rsh_job , RSH_JOB_TYPE_ID ) - - - -/** - If the host is for some reason not available, NULL should be - returned. Will also return NULL if some funny guy tries to allocate - with max_running <= 0. -*/ - -static rsh_host_type * rsh_host_alloc(const char * host_name , int max_running) { - if (max_running > 0) { - struct addrinfo * result; - if (getaddrinfo(host_name , NULL , NULL , &result) == 0) { - rsh_host_type * host = util_malloc(sizeof * host ); - - host->host_name = util_alloc_string_copy(host_name); - host->max_running = max_running; - host->running = 0; - pthread_mutex_init( &host->host_mutex , NULL ); - - freeaddrinfo( result ); - return host; - } else { - fprintf(stderr,"** Warning: could not locate server: %s \n",host_name); - return NULL; - } - } else - return NULL; -} - - - -static void rsh_host_free(rsh_host_type * rsh_host) { - free(rsh_host->host_name); - free(rsh_host); -} - - -static bool rsh_host_available(rsh_host_type * rsh_host) { - bool available; - - pthread_mutex_lock( &rsh_host->host_mutex ); - { - available = false; - if ((rsh_host->max_running - rsh_host->running) > 0) { // The host has free slots() - bool ping_ok = true; -#ifdef ERT_HAVE_PING - ping_ok = util_ping( rsh_host->host_name ); -#endif - if (ping_ok) { // The host answers to ping() - available = true; - rsh_host->running++; - } - } - } - pthread_mutex_unlock( &rsh_host->host_mutex ); - - return available; -} - - - - - -static void rsh_host_submit_job(rsh_host_type * rsh_host , rsh_job_type * job, const char * rsh_cmd , const char * submit_cmd , int num_cpu , int job_argc , const char ** job_argv) { - /* - Observe that this job has already been added to the running jobs - in the rsh_host_available function. - */ - int argc = job_argc + 2; - const char ** argv = util_malloc( argc * sizeof * argv ); - - argv[0] = rsh_host->host_name; - argv[1] = submit_cmd; - { - int iarg; - for (iarg = 0; iarg < job_argc; iarg++) - argv[iarg + 2] = job_argv[iarg]; - } - - util_spawn_blocking(rsh_cmd, argc, argv, NULL, NULL); /* This call is blocking. */ - job->status = JOB_QUEUE_DONE; - - pthread_mutex_lock( &rsh_host->host_mutex ); - rsh_host->running--; - pthread_mutex_unlock( &rsh_host->host_mutex ); - free( argv ); -} - - -/* - static const char * rsh_host_get_hostname(const rsh_host_type * host) { return host->host_name; } -*/ - - - -static void * rsh_host_submit_job__(void * __arg_pack) { - arg_pack_type * arg_pack = arg_pack_safe_cast(__arg_pack); - char * rsh_cmd = arg_pack_iget_ptr(arg_pack , 0); - rsh_host_type * rsh_host = arg_pack_iget_ptr(arg_pack , 1); - char * submit_cmd = arg_pack_iget_ptr(arg_pack , 2); - int num_cpu = arg_pack_iget_int(arg_pack , 3); - int argc = arg_pack_iget_int(arg_pack , 4); - const char ** argv = arg_pack_iget_ptr(arg_pack , 5); - rsh_job_type * job = arg_pack_iget_ptr(arg_pack , 6); - - rsh_host_submit_job(rsh_host , job , rsh_cmd , submit_cmd , num_cpu , argc , argv); - pthread_exit( NULL ); - arg_pack_free( arg_pack ); -} - - - - - -/*****************************************************************/ - - -/*****************************************************************/ - - - - -rsh_job_type * rsh_job_alloc(const char * run_path) { - rsh_job_type * job; - job = util_malloc(sizeof * job ); - job->active = false; - job->status = JOB_QUEUE_WAITING; - job->run_path = util_alloc_string_copy(run_path); - UTIL_TYPE_ID_INIT( job , RSH_JOB_TYPE_ID ); - return job; -} - - - -void rsh_job_free(rsh_job_type * job) { - free(job->run_path); - free(job); -} - - - - -job_status_type rsh_driver_get_job_status(void * __driver , void * __job) { - if (__job == NULL) - /* The job has not been registered at all ... */ - return JOB_QUEUE_NOT_ACTIVE; - else { - rsh_job_type * job = rsh_job_safe_cast( __job ); - { - if (job->active == false) { - util_abort("%s: internal error - should not query status on inactive jobs \n" , __func__); - return JOB_QUEUE_NOT_ACTIVE; /* Dummy to shut up compiler */ - } else - return job->status; - } - } -} - - - -void rsh_driver_free_job( void * __job ) { - rsh_job_type * job = rsh_job_safe_cast( __job ); - rsh_job_free(job); -} - - - -void rsh_driver_kill_job(void * __driver ,void * __job) { - rsh_job_type * job = rsh_job_safe_cast( __job ); - if (job->active) - pthread_cancel( job->run_thread ); - rsh_job_free( job ); -} - - - -void * rsh_driver_submit_job(void * __driver, - const char * submit_cmd , - int num_cpu , /* Ignored */ - const char * run_path , - const char * job_name , - int argc, - const char ** argv ) { - - rsh_driver_type * driver = rsh_driver_safe_cast( __driver ); - rsh_job_type * job = NULL; - { - /* - command is freed in the start_routine() function - */ - pthread_mutex_lock( &driver->submit_lock ); - { - rsh_host_type * host = NULL; - int ihost; - int host_index = 0; - - if (driver->num_hosts == 0) - util_abort("%s: fatal error - no hosts added to the rsh driver.\n",__func__); - - for (ihost = 0; ihost < driver->num_hosts; ihost++) { - host_index = (ihost + driver->last_host_index) % driver->num_hosts; - if (rsh_host_available(driver->host_list[host_index])) { - host = driver->host_list[host_index]; - break; - } - } - driver->last_host_index = (host_index + 1) % driver->num_hosts; - - if (host != NULL) { - /* A host is available */ - arg_pack_type * arg_pack = arg_pack_alloc(); /* The arg_pack is freed() in the rsh_host_submit_job__() function. - freeing it here is dangerous, because we might free it before the - thread-called function is finished with it. */ - - job = rsh_job_alloc(run_path); - - arg_pack_append_ptr(arg_pack , driver->rsh_command); - arg_pack_append_ptr(arg_pack , host); - arg_pack_append_ptr(arg_pack , (char *) submit_cmd); - arg_pack_append_int(arg_pack , num_cpu ); - arg_pack_append_int(arg_pack , argc ); - arg_pack_append_ptr(arg_pack , argv ); - arg_pack_append_ptr(arg_pack , job); - - { - int pthread_return_value = pthread_create( &job->run_thread , &driver->thread_attr , rsh_host_submit_job__ , arg_pack); - if (pthread_return_value != 0) - util_abort("%s failed to create thread ERROR:%d \n", __func__ , pthread_return_value); - } - job->status = JOB_QUEUE_RUNNING; - job->active = true; - } - } - pthread_mutex_unlock( &driver->submit_lock ); - } - return job; -} - - -void rsh_driver_clear_host_list( rsh_driver_type * driver ) { - int ihost; - for (ihost =0; ihost < driver->num_hosts; ihost++) - rsh_host_free(driver->host_list[ihost]); - util_safe_free(driver->host_list); - - driver->num_hosts = 0; - driver->host_list = NULL; - driver->last_host_index = 0; -} - - -void rsh_driver_free(rsh_driver_type * driver) { - rsh_driver_clear_host_list( driver ); - pthread_attr_destroy ( &driver->thread_attr ); - util_safe_free(driver->rsh_command ); - hash_free( driver->__host_hash ); - free(driver); - driver = NULL; -} - - -void rsh_driver_free__(void * __driver) { - rsh_driver_type * driver = rsh_driver_safe_cast( __driver ); - rsh_driver_free( driver ); -} - - -void rsh_driver_set_host_list( rsh_driver_type * rsh_driver , const hash_type * rsh_host_list) { - rsh_driver_clear_host_list( rsh_driver ); - if (rsh_host_list != NULL) { - hash_iter_type * hash_iter = hash_iter_alloc( rsh_host_list ); - while (!hash_iter_is_complete( hash_iter )) { - const char * host = hash_iter_get_next_key( hash_iter ); - int max_running = hash_get_int( rsh_host_list , host ); - rsh_driver_add_host(rsh_driver , host , max_running); - } - if (rsh_driver->num_hosts == 0) - util_abort("%s: failed to add any valid RSH hosts - aborting.\n",__func__); - } -} - - - - -/** - -*/ - -void * rsh_driver_alloc( ) { - rsh_driver_type * rsh_driver = util_malloc( sizeof * rsh_driver ); - UTIL_TYPE_ID_INIT( rsh_driver , RSH_DRIVER_TYPE_ID ); - pthread_mutex_init( &rsh_driver->submit_lock , NULL ); - pthread_attr_init( &rsh_driver->thread_attr ); - pthread_attr_setdetachstate( &rsh_driver->thread_attr , PTHREAD_CREATE_DETACHED ); - - /** - To simplify the Python wrapper it is possible to pass in NULL as - rsh_host_list pointer, and then subsequently add hosts with - rsh_driver_add_host(). - */ - rsh_driver->num_hosts = 0; - rsh_driver->host_list = NULL; - rsh_driver->last_host_index = 0; - rsh_driver->rsh_command = NULL; - rsh_driver->__host_hash = hash_alloc(); - return rsh_driver; -} - - - -void rsh_driver_add_host(rsh_driver_type * rsh_driver , const char * hostname , int host_max_running) { - rsh_host_type * new_host = rsh_host_alloc(hostname , host_max_running); /* Could in principle update an existing node if the host name is old. */ - if (new_host != NULL) { - rsh_driver->num_hosts++; - rsh_driver->host_list = util_realloc(rsh_driver->host_list , rsh_driver->num_hosts * sizeof * rsh_driver->host_list ); - rsh_driver->host_list[(rsh_driver->num_hosts - 1)] = new_host; - } -} - - -/** - Hostname should be a string as host:max_running, the ":max_running" - part is optional, and will default to 1. -*/ - -void rsh_driver_add_host_from_string(rsh_driver_type * rsh_driver , const char * hostname) { - int host_max_running; - char ** tmp; - char * host; - int tokens; - - util_split_string( hostname , ":" , &tokens , &tmp); - if (tokens > 1) { - if (!util_sscanf_int( tmp[tokens - 1] , &host_max_running)) - util_abort("%s: failed to parse out integer from: %s \n",__func__ , hostname); - host = util_alloc_joined_string((const char **) tmp , tokens - 1 , ":"); - } else - host = util_alloc_string_copy( tmp[0] ); - rsh_driver_add_host( rsh_driver , host , host_max_running ); - - util_free_stringlist( tmp , tokens ); - free( host ); -} - - - - -bool rsh_driver_set_option( void * __driver , const char * option_key , const void * value ) { - rsh_driver_type * driver = rsh_driver_safe_cast( __driver ); - bool has_option = true; - { - if (strcmp(RSH_HOST , option_key) == 0) /* Add one host - value should be hostname:max */ - rsh_driver_add_host_from_string( driver , value ); - else if (strcmp(RSH_HOSTLIST , option_key) == 0) { /* Set full host list - value should be hash of integers. */ - if (value != NULL) { - const hash_type * hash_value = hash_safe_cast_const( value ); - rsh_driver_set_host_list( driver , hash_value ); - } - } else if (strcmp( RSH_CLEAR_HOSTLIST , option_key) == 0) - /* Value is not considered - this is an action, and not a _set operation. */ - rsh_driver_set_host_list( driver , NULL ); - else if (strcmp( RSH_CMD , option_key) == 0) - driver->rsh_command = util_realloc_string_copy( driver->rsh_command , value ); - else - has_option = false; - } - return has_option; -} - - -const void * rsh_driver_get_option( const void * __driver , const char * option_key ) { - const rsh_driver_type * driver = rsh_driver_safe_cast_const( __driver ); - { - if (strcmp( RSH_CMD , option_key ) == 0) - return driver->rsh_command; - else if (strcmp( RSH_HOSTLIST , option_key) == 0) { - int ihost; - hash_clear( driver->__host_hash ); - for (ihost = 0; ihost < driver->num_hosts; ihost++) { - rsh_host_type * host = driver->host_list[ ihost ]; - hash_insert_int( driver->__host_hash , host->host_name , host->max_running); - } - return driver->__host_hash; - } else { - util_abort("%s: get not implemented fro option_id:%s for rsh \n",__func__ , option_key ); - return NULL; - } - } -} - - -void rsh_driver_init_option_list(stringlist_type * option_list) { - stringlist_append_ref(option_list, RSH_HOST); - stringlist_append_ref(option_list, RSH_HOSTLIST); - stringlist_append_ref(option_list, RSH_CMD); - stringlist_append_ref(option_list, RSH_CLEAR_HOSTLIST); -} - -#undef RSH_JOB_ID - -/*****************************************************************/ - diff --git a/ThirdParty/Ert/libjob_queue/src/torque_driver.c b/ThirdParty/Ert/libjob_queue/src/torque_driver.c deleted file mode 100644 index 574aadffab..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/torque_driver.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'torque_driver.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ -#include -#include -#include - -#include -#include - -#include - - -#define TORQUE_DRIVER_TYPE_ID 34873653 -#define TORQUE_JOB_TYPE_ID 12312312 - - -struct torque_driver_struct { - UTIL_TYPE_ID_DECLARATION; - char * queue_name; - char * qsub_cmd; - char * qstat_cmd; - char * qdel_cmd; - char * num_cpus_per_node_char; - char * job_prefix; - char * num_nodes_char; - bool keep_qsub_output; - int num_cpus_per_node; - int num_nodes; - char * cluster_label; - int submit_sleep; - FILE * debug_stream; -}; - -struct torque_job_struct { - UTIL_TYPE_ID_DECLARATION; - long int torque_jobnr; - char * torque_jobnr_char; -}; - -UTIL_SAFE_CAST_FUNCTION(torque_driver, TORQUE_DRIVER_TYPE_ID); - -static UTIL_SAFE_CAST_FUNCTION_CONST(torque_driver, TORQUE_DRIVER_TYPE_ID) -static UTIL_SAFE_CAST_FUNCTION(torque_job, TORQUE_JOB_TYPE_ID) - -void * torque_driver_alloc() { - torque_driver_type * torque_driver = util_malloc(sizeof * torque_driver); - UTIL_TYPE_ID_INIT(torque_driver, TORQUE_DRIVER_TYPE_ID); - - torque_driver->queue_name = NULL; - torque_driver->qsub_cmd = NULL; - torque_driver->qstat_cmd = NULL; - torque_driver->qdel_cmd = NULL; - torque_driver->num_cpus_per_node_char = NULL; - torque_driver->num_nodes_char = NULL; - torque_driver->keep_qsub_output = false; - torque_driver->num_cpus_per_node = 1; - torque_driver->num_nodes = 1; - torque_driver->cluster_label = NULL; - torque_driver->job_prefix = NULL; - torque_driver->debug_stream = NULL; - - torque_driver_set_option(torque_driver, TORQUE_QSUB_CMD, TORQUE_DEFAULT_QSUB_CMD); - torque_driver_set_option(torque_driver, TORQUE_QSTAT_CMD, TORQUE_DEFAULT_QSTAT_CMD); - torque_driver_set_option(torque_driver, TORQUE_QDEL_CMD, TORQUE_DEFAULT_QDEL_CMD); - torque_driver_set_option(torque_driver, TORQUE_NUM_CPUS_PER_NODE, "1"); - torque_driver_set_option(torque_driver, TORQUE_NUM_NODES, "1"); - torque_driver_set_option(torque_driver, TORQUE_SUBMIT_SLEEP, TORQUE_DEFAULT_SUBMIT_SLEEP); - - return torque_driver; -} - -static void torque_driver_set_debug_output(torque_driver_type * driver, const char * debug_file) { - if (driver->debug_stream) - fclose( driver->debug_stream ); - - if (debug_file) - driver->debug_stream = util_mkdir_fopen( debug_file , "w"); - else - driver->debug_stream = NULL; -} - - -static void torque_driver_set_qsub_cmd(torque_driver_type * driver, const char * qsub_cmd) { - driver->qsub_cmd = util_realloc_string_copy(driver->qsub_cmd, qsub_cmd); -} - -static void torque_driver_set_qstat_cmd(torque_driver_type * driver, const char * qstat_cmd) { - driver->qstat_cmd = util_realloc_string_copy(driver->qstat_cmd, qstat_cmd); -} - -static void torque_driver_set_qdel_cmd(torque_driver_type * driver, const char * qdel_cmd) { - driver->qdel_cmd = util_realloc_string_copy(driver->qdel_cmd, qdel_cmd); -} - -static void torque_driver_set_queue_name(torque_driver_type * driver, const char * queue_name) { - driver->queue_name = util_realloc_string_copy(driver->queue_name, queue_name); -} - -static bool torque_driver_set_submit_sleep(torque_driver_type * driver, const char* submit_sleep) { - double seconds_sleep; - if (util_sscanf_double( submit_sleep , &seconds_sleep)) { - driver->submit_sleep = (int) (seconds_sleep * 1000000); - return true; - } else - return false; -} - - -static bool torque_driver_set_num_nodes(torque_driver_type * driver, const char* num_nodes_char) { - int num_nodes = 0; - if (util_sscanf_int(num_nodes_char, &num_nodes)) { - driver->num_nodes = num_nodes; - driver->num_nodes_char = util_realloc_string_copy(driver->num_nodes_char, num_nodes_char); - return true; - } else { - return false; - } -} - -static bool torque_driver_set_keep_qsub_output(torque_driver_type * driver, const char* keep_output_bool_as_char) { - bool keep_output_parsed; - - if (util_sscanf_bool(keep_output_bool_as_char, &keep_output_parsed)) { - driver->keep_qsub_output = keep_output_parsed; - return true; - } else { - return false; - } -} - -static void torque_driver_set_job_prefix(torque_driver_type * driver, const char * job_prefix){ - driver->job_prefix = util_realloc_string_copy( driver->job_prefix , job_prefix); -} - -static void torque_driver_set_cluster_label(torque_driver_type * driver, const char* cluster_label) { - driver->cluster_label = util_realloc_string_copy(driver->cluster_label, cluster_label); -} - -static bool torque_driver_set_num_cpus_per_node(torque_driver_type * driver, const char* num_cpus_per_node_char) { - int num_cpus_per_node = 0; - if (util_sscanf_int(num_cpus_per_node_char, &num_cpus_per_node)) { - driver->num_cpus_per_node = num_cpus_per_node; - driver->num_cpus_per_node_char = util_realloc_string_copy(driver->num_cpus_per_node_char, num_cpus_per_node_char); - return true; - } else { - return false; - } -} - -bool torque_driver_set_option(void * __driver, const char * option_key, const void * value) { - torque_driver_type * driver = torque_driver_safe_cast(__driver); - bool option_set = true; - { - if (strcmp(TORQUE_QSUB_CMD, option_key) == 0) - torque_driver_set_qsub_cmd(driver, value); - else if (strcmp(TORQUE_QSTAT_CMD, option_key) == 0) - torque_driver_set_qstat_cmd(driver, value); - else if (strcmp(TORQUE_QDEL_CMD, option_key) == 0) - torque_driver_set_qdel_cmd(driver, value); - else if (strcmp(TORQUE_QUEUE, option_key) == 0) - torque_driver_set_queue_name(driver, value); - else if (strcmp(TORQUE_NUM_CPUS_PER_NODE, option_key) == 0) - option_set = torque_driver_set_num_cpus_per_node(driver, value); - else if (strcmp(TORQUE_NUM_NODES, option_key) == 0) - option_set = torque_driver_set_num_nodes(driver, value); - else if (strcmp(TORQUE_KEEP_QSUB_OUTPUT, option_key) == 0) - option_set = torque_driver_set_keep_qsub_output(driver, value); - else if (strcmp(TORQUE_CLUSTER_LABEL, option_key) == 0) - torque_driver_set_cluster_label(driver, value); - else if (strcmp(TORQUE_JOB_PREFIX_KEY, option_key) == 0) - torque_driver_set_job_prefix(driver, value); - else if (strcmp(TORQUE_DEBUG_OUTPUT, option_key) == 0) - torque_driver_set_debug_output(driver, value); - else if (strcmp(TORQUE_SUBMIT_SLEEP, option_key) == 0) - option_set = torque_driver_set_submit_sleep(driver, value); - else - option_set = false; - } - return option_set; -} - -const void * torque_driver_get_option(const void * __driver, const char * option_key) { - const torque_driver_type * driver = torque_driver_safe_cast_const(__driver); - { - if (strcmp(TORQUE_QSUB_CMD, option_key) == 0) - return driver->qsub_cmd; - else if (strcmp(TORQUE_QSTAT_CMD, option_key) == 0) - return driver->qstat_cmd; - else if (strcmp(TORQUE_QDEL_CMD, option_key) == 0) - return driver->qdel_cmd; - else if (strcmp(TORQUE_QUEUE, option_key) == 0) - return driver->queue_name; - else if (strcmp(TORQUE_NUM_CPUS_PER_NODE, option_key) == 0) - return driver->num_cpus_per_node_char; - else if (strcmp(TORQUE_NUM_NODES, option_key) == 0) - return driver->num_nodes_char; - else if (strcmp(TORQUE_KEEP_QSUB_OUTPUT, option_key) == 0) - return driver->keep_qsub_output ? "1" : "0"; - else if (strcmp(TORQUE_CLUSTER_LABEL, option_key) == 0) - return driver->cluster_label; - else if(strcmp(TORQUE_JOB_PREFIX_KEY, option_key) == 0) - return driver->job_prefix; - else { - util_abort("%s: option_id:%s not recognized for TORQUE driver \n", __func__, option_key); - return NULL; - } - } -} - -void torque_driver_init_option_list(stringlist_type * option_list) { - stringlist_append_ref(option_list, TORQUE_QSUB_CMD); - stringlist_append_ref(option_list, TORQUE_QSTAT_CMD); - stringlist_append_ref(option_list, TORQUE_QDEL_CMD); - stringlist_append_ref(option_list, TORQUE_QUEUE); - stringlist_append_ref(option_list, TORQUE_NUM_CPUS_PER_NODE); - stringlist_append_ref(option_list, TORQUE_NUM_NODES); - stringlist_append_ref(option_list, TORQUE_KEEP_QSUB_OUTPUT); - stringlist_append_ref(option_list, TORQUE_CLUSTER_LABEL); - stringlist_append_ref(option_list, TORQUE_JOB_PREFIX_KEY); -} - -torque_job_type * torque_job_alloc() { - torque_job_type * job; - job = util_malloc(sizeof * job); - job->torque_jobnr_char = NULL; - job->torque_jobnr = 0; - UTIL_TYPE_ID_INIT(job, TORQUE_JOB_TYPE_ID); - - return job; -} - -stringlist_type * torque_driver_alloc_cmd(torque_driver_type * driver, - const char * job_name, - const char * submit_script) { - - - stringlist_type * argv = stringlist_alloc_new(); - - if (driver->keep_qsub_output) { - stringlist_append_ref(argv, "-k"); - stringlist_append_ref(argv, "oe"); - } - - { - char * resource_string; - if (driver->cluster_label) - resource_string = util_alloc_sprintf("nodes=%d:%s:ppn=%d", driver->num_nodes, driver->cluster_label, driver->num_cpus_per_node); - else - resource_string = util_alloc_sprintf("nodes=%d:ppn=%d", driver->num_nodes, driver->num_cpus_per_node); - - stringlist_append_ref(argv, "-l"); - stringlist_append_copy(argv, resource_string); - free(resource_string); - } - - if (driver->queue_name != NULL) { - stringlist_append_ref(argv, "-q"); - stringlist_append_ref(argv, driver->queue_name); - } - - if (job_name != NULL) { - stringlist_append_ref(argv, "-N"); - stringlist_append_ref(argv, job_name); - } - - stringlist_append_ref(argv, submit_script); - - return argv; -} - -static void torque_debug(torque_driver_type * driver , const char * fmt , ...) { - if (driver->debug_stream) { - { - va_list ap; - va_start(ap , fmt); - vfprintf(driver->debug_stream , fmt , ap ); - va_end(ap); - } - fprintf(driver->debug_stream , "\n"); - fsync( fileno(driver->debug_stream) ); - } -} - - -static int torque_job_parse_qsub_stdout(const torque_driver_type * driver, const char * stdout_file) { - int jobid; - { - FILE * stream = util_fopen(stdout_file, "r"); - char * jobid_string = util_fscanf_alloc_upto(stream, ".", false); - - torque_debug(driver, "Torque job ID string: '%s'", jobid_string); - - if (jobid_string == NULL || !util_sscanf_int(jobid_string, &jobid)) { - - char * file_content = util_fread_alloc_file_content(stdout_file, NULL); - fprintf(stderr, "Failed to get torque job id from file: %s \n", stdout_file); - fprintf(stderr, "qsub command : %s \n", driver->qsub_cmd); - fprintf(stderr, "File content: [%s]\n", file_content); - free(file_content); - util_exit("%s: \n", __func__); - } - free(jobid_string); - fclose(stream); - } - return jobid; -} - -void torque_job_create_submit_script(const char * script_filename, const char * submit_cmd, int argc, const char ** job_argv) { - if (submit_cmd == NULL) { - util_abort("%s: cannot create submit script, because there is no executing commmand specified.", __func__); - } - - FILE* script_file = util_fopen(script_filename, "w"); - fprintf(script_file, "#!/bin/sh\n"); - - fprintf(script_file, "%s", submit_cmd); - for (int i = 0; i < argc; i++) { - fprintf(script_file, " %s", job_argv[i]); - } - - util_fclose(script_file); -} - -static void torque_debug_spawn_status_info(torque_driver_type *driver, int status) { - if (WIFEXITED((status))) { - torque_debug(driver, "Torque spawn exited with status=%d", WEXITSTATUS((status))); - } else if (WIFSIGNALED((status))) { - torque_debug(driver, "Torque spawn killed by signal %d", WTERMSIG((status))); - } else if (WIFSTOPPED((status))) { - torque_debug(driver, "Torque spawn stopped by signal %d", WSTOPSIG((status))); - } else if (WIFCONTINUED((status))) { - torque_debug(driver, "Torque spawn continued"); - } else { - torque_debug(driver, "Torque spawn failed with unknown status code: %d", (status)); - } -} - -static int torque_driver_submit_shell_job(torque_driver_type * driver, - const char * run_path, - const char * job_name, - const char * submit_cmd, - int num_cpu, - int job_argc, - const char ** job_argv) { - - usleep( driver->submit_sleep ); - { - int job_id; - char * tmp_std_file = util_alloc_tmp_file("/tmp", "enkf-submit-std", true); - char * tmp_err_file = util_alloc_tmp_file("/tmp", "enkf-submit-err", true); - char * script_filename = util_alloc_filename(run_path, "qsub_script", "sh"); - - torque_debug(driver, "Setting up submit stdout target '%s' for '%s'", tmp_std_file, script_filename); - torque_debug(driver, "Setting up submit stderr target '%s' for '%s'", tmp_err_file, script_filename); - torque_job_create_submit_script(script_filename, submit_cmd, job_argc, job_argv); - { - int p_units_from_driver = driver->num_cpus_per_node * driver->num_nodes; - if (num_cpu > p_units_from_driver) { - util_abort("%s: Error in config, job's config requires %d processing units, but config says %s: %d, and %s: %d, which multiplied becomes: %d \n", - __func__, num_cpu, TORQUE_NUM_CPUS_PER_NODE, driver->num_cpus_per_node, TORQUE_NUM_NODES, driver->num_nodes, p_units_from_driver); - } - { - stringlist_type * remote_argv = torque_driver_alloc_cmd(driver, job_name, script_filename); - torque_debug(driver, "Submit arguments: %s", stringlist_alloc_joined_string(remote_argv, " ")); - char ** argv = stringlist_alloc_char_ref(remote_argv); - int status = util_spawn_blocking(driver->qsub_cmd, stringlist_get_size(remote_argv), (const char **) argv, tmp_std_file, tmp_err_file); - if (status != 0) { - torque_debug_spawn_status_info(driver, status); - } - free(argv); - stringlist_free(remote_argv); - } - } - - job_id = torque_job_parse_qsub_stdout(driver, tmp_std_file); - - util_unlink_existing(tmp_std_file); - util_unlink_existing(tmp_err_file); - free(tmp_std_file); - free(tmp_err_file); - - return job_id; - } -} - -void torque_job_free(torque_job_type * job) { - - util_safe_free(job->torque_jobnr_char); - free(job); -} - -void torque_driver_free_job(void * __job) { - - torque_job_type * job = torque_job_safe_cast(__job); - torque_job_free(job); -} - -void * torque_driver_submit_job(void * __driver, - const char * submit_cmd, - int num_cpu, - const char * run_path, - const char * job_name, - int argc, - const char ** argv) { - torque_driver_type * driver = torque_driver_safe_cast(__driver); - torque_job_type * job = torque_job_alloc(); - - torque_debug( driver , "Submitting job in:%s" , run_path); - { - char * local_job_name = NULL; - if (driver->job_prefix) - local_job_name = util_alloc_sprintf("%s%s",driver->job_prefix, job_name); - else - local_job_name = util_alloc_string_copy( job_name ); - - job->torque_jobnr = torque_driver_submit_shell_job(driver, run_path, local_job_name, submit_cmd, num_cpu, argc, argv); - job->torque_jobnr_char = util_alloc_sprintf("%ld", job->torque_jobnr); - - torque_debug( driver , "Job:%s Id:%d" , run_path , job->torque_jobnr); - free(local_job_name); - } - - if (job->torque_jobnr > 0) - return job; - else { - /* - The submit failed - the queue system shall handle - NULL return values. - */ - torque_job_free(job); - return NULL; - } -} - -static char* torque_driver_get_qstat_status(torque_driver_type * driver, char * jobnr_char) { - char * status = util_malloc(sizeof (char)*2); - char * tmp_file = util_alloc_tmp_file("/tmp", "enkf-qstat", true); - - { - char ** argv = util_calloc(1, sizeof * argv); - argv[0] = jobnr_char; - - util_spawn_blocking(driver->qstat_cmd, 1, (const char **) argv, tmp_file, NULL); - free(argv); - } - - FILE *stream = util_fopen(tmp_file, "r"); - bool at_eof = false; - util_fskip_lines(stream, 2); - char * line = util_fscanf_alloc_line(stream, &at_eof); - fclose(stream); - - if (line != NULL) { - char job_id_full_string[32]; - if (sscanf(line, "%s %*s %*s %*s %s %*s", job_id_full_string, status) == 2) { - char *dotPtr = strchr(job_id_full_string, '.'); - int dotPosition = dotPtr - job_id_full_string; - char* job_id_as_char_ptr = util_alloc_substring_copy(job_id_full_string, 0, dotPosition); - if (strcmp(job_id_as_char_ptr, jobnr_char) != 0) { - util_abort("%s: Job id input (%d) does not match the one found by qstat (%d)\n", __func__, jobnr_char, job_id_as_char_ptr); - } - free(job_id_as_char_ptr); - } - free(line); - } else { - util_abort("%s: Unable to read qstat's output line number 3 from file: %s", __func__, tmp_file); - } - - util_unlink_existing(tmp_file); - free(tmp_file); - - return status; -} - -job_status_type torque_driver_get_job_status(void * __driver, void * __job) { - torque_driver_type * driver = torque_driver_safe_cast(__driver); - torque_job_type * job = torque_job_safe_cast(__job); - char * status = torque_driver_get_qstat_status(driver, job->torque_jobnr_char); - int result = JOB_QUEUE_FAILED; - if (strcmp(status, "R") == 0) { - result = JOB_QUEUE_RUNNING; - } else if (strcmp(status, "E") == 0) { - result = JOB_QUEUE_DONE; - } else if (strcmp(status, "C") == 0) { - result = JOB_QUEUE_DONE; - } else if (strcmp(status, "Q") == 0) { - result = JOB_QUEUE_PENDING; - } else { - fprintf(stderr, "%s: Unknown status found (%s), expecting one of R, E, C and Q.\n", __func__, status); - result = JOB_QUEUE_STATUS_FAILURE; - } - free(status); - - return result; -} - -void torque_driver_kill_job(void * __driver, void * __job) { - - torque_driver_type * driver = torque_driver_safe_cast(__driver); - torque_job_type * job = torque_job_safe_cast(__job); - util_spawn_blocking(driver->qdel_cmd, 1, (const char **) &job->torque_jobnr_char, NULL, NULL); -} - -void torque_driver_free(torque_driver_type * driver) { - torque_driver_set_debug_output(driver, NULL); - util_safe_free(driver->queue_name); - free(driver->qdel_cmd); - free(driver->qstat_cmd); - free(driver->qsub_cmd); - free(driver->num_cpus_per_node_char); - free(driver->num_nodes_char); - if (driver->job_prefix) - free(driver->job_prefix); - - free(driver); -} - -void torque_driver_free__(void * __driver) { - torque_driver_type * driver = torque_driver_safe_cast(__driver); - torque_driver_free(driver); -} - -int torque_driver_get_submit_sleep( const torque_driver_type * driver ) { - return driver->submit_sleep; -} - -FILE * torque_driver_get_debug_stream( const torque_driver_type * driver ) { - return driver->debug_stream; -} diff --git a/ThirdParty/Ert/libjob_queue/src/workflow.c b/ThirdParty/Ert/libjob_queue/src/workflow.c deleted file mode 100644 index c0c132ed81..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/workflow.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'workflow.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#define CMD_TYPE_ID 66153 -#define WORKFLOW_TYPE_ID 6762081 -#define WORKFLOW_COMMENT_STRING "--" -#define WORKFLOW_INCLUDE "INCLUDE" - -typedef struct cmd_struct cmd_type; - -struct cmd_struct { - UTIL_TYPE_ID_DECLARATION; - const workflow_job_type * workflow_job; - stringlist_type * arglist; -}; - - - - -struct workflow_struct { - UTIL_TYPE_ID_DECLARATION; - time_t compile_time; - bool compiled; - char * src_file; - vector_type * cmd_list; - workflow_joblist_type * joblist; - config_error_type * last_error; - vector_type * stack; -}; - -/*****************************************************************/ - - -static cmd_type * cmd_alloc( const workflow_job_type * workflow_job , const stringlist_type * arglist) { - cmd_type * cmd = util_malloc( sizeof * cmd ); - UTIL_TYPE_ID_INIT(cmd , CMD_TYPE_ID ); - cmd->workflow_job = workflow_job; - cmd->arglist = stringlist_alloc_deep_copy( arglist ); - return cmd; -} - -static UTIL_SAFE_CAST_FUNCTION( cmd , CMD_TYPE_ID ); - -static void cmd_free( cmd_type * cmd ){ - stringlist_free( cmd->arglist ); - free( cmd ); -} - -static void cmd_free__( void * arg ) { - cmd_type * cmd = cmd_safe_cast( arg ); - cmd_free( cmd ); -} - -/*****************************************************************/ - -static void workflow_add_cmd( workflow_type * workflow , cmd_type * cmd ) { - vector_append_owned_ref( workflow->cmd_list , cmd , cmd_free__ ); -} - - -static void workflow_clear( workflow_type * workflow ) { - vector_clear( workflow->cmd_list ); -} - -static void workflow_store_error( workflow_type * workflow , const config_error_type * error) { - if (workflow->last_error) - config_error_free( workflow->last_error ); - - if (error) - workflow->last_error = config_error_alloc_copy( error ); - else - workflow->last_error = NULL; -} - - - - -bool workflow_try_compile( workflow_type * script , const subst_list_type * context) { - if (util_file_exists( script->src_file )) { - const char * src_file = script->src_file; - char * tmp_file = NULL; - bool update = false; - if (context != NULL) { - tmp_file = util_alloc_tmp_file("/tmp" , "ert-workflow" , false ); - update = subst_list_filter_file( context , script->src_file , tmp_file ); - if (update) { - script->compiled = false; - src_file = tmp_file; - } else { - remove( tmp_file ); - free( tmp_file ); - tmp_file = NULL; - } - } - - { - time_t src_mtime = util_file_mtime( script->src_file ); - if (script->compiled) { - if (util_difftime_seconds( src_mtime , script->compile_time ) > 0 ) - return true; - else { - // Script has been compiled succesfully, but then changed afterwards. - // We try to recompile; if that fails we are left with 'nothing'. - } - } - } - - { - // Try to compile - config_parser_type * config_compiler = workflow_joblist_get_compiler( script->joblist ); - script->compiled = false; - workflow_clear( script ); - { - config_content_type * content = config_parse( config_compiler , src_file , WORKFLOW_COMMENT_STRING , WORKFLOW_INCLUDE , NULL , NULL , CONFIG_UNRECOGNIZED_ERROR , true ); - - if (config_content_is_valid( content )) { - int cmd_line; - for (cmd_line = 0; cmd_line < config_content_get_size(content); cmd_line++) { - const config_content_node_type * node = config_content_iget_node( content , cmd_line ); - const char * jobname = config_content_node_get_kw( node ); - const workflow_job_type * job = workflow_joblist_get_job( script->joblist , jobname ); - cmd_type * cmd = cmd_alloc( job , config_content_node_get_stringlist( node )); - - workflow_add_cmd( script , cmd ); - } - script->compiled = true; - } else - workflow_store_error( script , config_content_get_errors( content )); - - config_content_free( content ); - } - } - - if (tmp_file != NULL) { - if (script->compiled) - remove( tmp_file ); - free( tmp_file ); - } - } - - // It is legal to remove the script after successfull compilation but - // then the context will not be applied at subsequent invocations. - return script->compiled; -} - - -bool workflow_run(workflow_type * workflow, void * self , bool verbose , const subst_list_type * context) { - vector_clear( workflow->stack ); - workflow_try_compile( workflow , context); - - if (workflow->compiled) { - int icmd; - for (icmd = 0; icmd < vector_get_size( workflow->cmd_list ); icmd++) { - const cmd_type * cmd = vector_iget_const( workflow->cmd_list , icmd ); - void * return_value = workflow_job_run( cmd->workflow_job, self , verbose , cmd->arglist ); - vector_push_front_ref( workflow->stack , return_value ); - } - return true; - } else - return false; -} - -int workflow_get_stack_size( const workflow_type * workflow ) { - return vector_get_size( workflow->stack ); -} - - -void * workflow_iget_stack_ptr( const workflow_type * workflow , int index) { - return vector_iget( workflow->stack , index ); -} - - -void * workflow_pop_stack( workflow_type * workflow ) { - return vector_pop_front( workflow->stack); -} - - - -workflow_type * workflow_alloc( const char * src_file , workflow_joblist_type * joblist) { - workflow_type * script = util_malloc( sizeof * script ); - UTIL_TYPE_ID_INIT( script , WORKFLOW_TYPE_ID ); - - script->src_file = util_alloc_string_copy( src_file ); - script->joblist = joblist; - script->cmd_list = vector_alloc_new(); - script->compiled = false; - script->last_error = NULL; - script->stack = vector_alloc_new(); - - workflow_try_compile( script , NULL ); - return script; -} - - -static UTIL_SAFE_CAST_FUNCTION( workflow , WORKFLOW_TYPE_ID ) -UTIL_IS_INSTANCE_FUNCTION( workflow , WORKFLOW_TYPE_ID) - -void workflow_free( workflow_type * workflow ) { - free( workflow->src_file ); - vector_free( workflow->cmd_list ); - vector_free( workflow->stack ); - - if (workflow->last_error) - config_error_free( workflow->last_error ); - - free( workflow ); -} - - -void workflow_free__( void * arg ) { - workflow_type * workflow = workflow_safe_cast( arg ); - workflow_free( workflow ); -} - - -const config_error_type * workflow_get_last_error( const workflow_type * workflow) { - return workflow->last_error; -} - -int workflow_size(const workflow_type * workflow) { - return vector_get_size( workflow->cmd_list ); -} - -const workflow_job_type * workflow_iget_job( const workflow_type * workflow, int index) { - const cmd_type * cmd = vector_iget_const( workflow->cmd_list , index ); - return cmd->workflow_job; -} - -stringlist_type * workflow_iget_arguments( const workflow_type * workflow, int index) { - const cmd_type * cmd = vector_iget_const( workflow->cmd_list , index ); - return cmd->arglist; -} diff --git a/ThirdParty/Ert/libjob_queue/src/workflow_job.c b/ThirdParty/Ert/libjob_queue/src/workflow_job.c deleted file mode 100644 index 63e985b581..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/workflow_job.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'workflow_job.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include - - -/* The default values are interepreted as no limit. */ -#define DEFAULT_INTERNAL false - - -#define MIN_ARG_KEY "MIN_ARG" -#define MAX_ARG_KEY "MAX_ARG" -#define ARG_TYPE_KEY "ARG_TYPE" -#define INTERNAL_KEY "INTERNAL" -#define MODULE_KEY "MODULE" -#define FUNCTION_KEY "FUNCTION" -#define SCRIPT_KEY "SCRIPT" -#define EXECUTABLE_KEY "EXECUTABLE" - -#define NULL_STRING "NULL" -#define WORKFLOW_JOB_STRING_TYPE "STRING" -#define WORKFLOW_JOB_INT_TYPE "INT" -#define WORKFLOW_JOB_FLOAT_TYPE "FLOAT" -#define WORKFLOW_JOB_BOOL_TYPE "BOOL" - -#define WORKFLOW_JOB_TYPE_ID 614441 - - -struct workflow_job_struct { - UTIL_TYPE_ID_DECLARATION; - bool internal; - int min_arg; - int max_arg; - int_vector_type * arg_types; // Should contain values from the config_item_types enum in config.h. - char * executable; - char * internal_script_path; - char * module; - char * function; - char * name; - void * lib_handle; - workflow_job_ftype * dl_func; - bool valid; -}; - - -bool workflow_job_internal( const workflow_job_type * workflow_job ) { - return workflow_job->internal; -} - -const char * workflow_job_get_name( const workflow_job_type * workflow_job ) { - return workflow_job->name; -} - - -config_parser_type * workflow_job_alloc_config() { - config_parser_type * config = config_alloc(); - { - config_schema_item_type * item; - - item = config_add_schema_item( config , MIN_ARG_KEY , false ); - config_schema_item_set_argc_minmax( item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , CONFIG_INT ); - - item = config_add_schema_item( config , MAX_ARG_KEY , false ); - config_schema_item_set_argc_minmax( item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , CONFIG_INT ); - - item = config_add_schema_item( config , ARG_TYPE_KEY , false ); - config_schema_item_set_argc_minmax( item , 2 , 2 ); - config_schema_item_iset_type( item , 0 , CONFIG_INT ); - config_schema_item_set_indexed_selection_set( item , 1 , 4 , (const char *[4]) {WORKFLOW_JOB_STRING_TYPE , WORKFLOW_JOB_INT_TYPE , WORKFLOW_JOB_FLOAT_TYPE, WORKFLOW_JOB_BOOL_TYPE}); - - /*****************************************************************/ - item = config_add_schema_item( config , EXECUTABLE_KEY , false ); - config_schema_item_set_argc_minmax( item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , CONFIG_PATH ); - - /*****************************************************************/ - item = config_add_schema_item( config , SCRIPT_KEY , false ); - config_schema_item_set_argc_minmax( item , 1 , 1 ); - config_schema_item_iset_type( item , 0 , CONFIG_PATH ); - - /*---------------------------------------------------------------*/ - - item = config_add_schema_item( config , FUNCTION_KEY , false ); - config_schema_item_set_argc_minmax( item , 1 , 1); - - item = config_add_schema_item( config , MODULE_KEY , false ); - config_schema_item_set_argc_minmax( item , 1 , 1); - /*****************************************************************/ - - item = config_add_schema_item( config , INTERNAL_KEY , false ); - config_schema_item_set_argc_minmax( item , 1 , 1); - config_schema_item_iset_type( item , 0 , CONFIG_BOOL); - } - return config; -} - - - -static UTIL_SAFE_CAST_FUNCTION(workflow_job , WORKFLOW_JOB_TYPE_ID ); - -void workflow_job_update_config_compiler( const workflow_job_type * workflow_job , config_parser_type * config_compiler ) { - config_schema_item_type * item = config_add_schema_item( config_compiler , workflow_job->name , false ); - /* - Ensure that the arg_types mapping is at least as large as the - max_arg value. The arg_type vector will be left padded with - CONFIG_STRING values. - */ - { - int iarg; - config_schema_item_set_argc_minmax( item , workflow_job->min_arg , workflow_job->max_arg ); - for (iarg = 0; iarg < int_vector_size( workflow_job->arg_types ); iarg++) - config_schema_item_iset_type( item , iarg , int_vector_iget( workflow_job->arg_types , iarg )); - } -} - - -workflow_job_type * workflow_job_alloc( const char * name , bool internal ) { - workflow_job_type * workflow_job = util_malloc( sizeof * workflow_job ); - UTIL_TYPE_ID_INIT( workflow_job , WORKFLOW_JOB_TYPE_ID ); - workflow_job->internal = internal; // this can not be changed run-time. - workflow_job->min_arg = CONFIG_DEFAULT_ARG_MIN; - workflow_job->max_arg = CONFIG_DEFAULT_ARG_MAX; - workflow_job->arg_types = int_vector_alloc( 0 , CONFIG_STRING ); - - workflow_job->executable = NULL; - workflow_job->internal_script_path = NULL; - workflow_job->module = NULL; - workflow_job->function = NULL; - - if (name == NULL) - util_abort("%s: trying to create workflow_job with name == NULL - illegal\n",__func__); - else - workflow_job->name = util_alloc_string_copy( name ); - - workflow_job->valid = false; - - return workflow_job; -} - - -void workflow_job_set_executable( workflow_job_type * workflow_job , const char * executable ) { - workflow_job->executable = util_realloc_string_copy( workflow_job->executable , executable ); -} - -char* workflow_job_get_executable( workflow_job_type * workflow_job) { - return workflow_job->executable; -} - -void workflow_job_set_internal_script( workflow_job_type * workflow_job , const char * script_path ) { - workflow_job->internal_script_path = util_realloc_string_copy( workflow_job->internal_script_path , script_path ); -} - -char* workflow_job_get_internal_script_path( const workflow_job_type * workflow_job) { - return workflow_job->internal_script_path; -} - -bool workflow_job_is_internal_script( const workflow_job_type * workflow_job) { - return workflow_job->internal && workflow_job->internal_script_path != NULL; -} - -void workflow_job_set_module( workflow_job_type * workflow_job , const char * module) { - if (strcmp(module ,NULL_STRING) == 0) - module = NULL; - - workflow_job->module = util_realloc_string_copy( workflow_job->module , module ); -} - -char * workflow_job_get_module( workflow_job_type * workflow_job) { - return workflow_job->module; -} - -void workflow_job_set_function( workflow_job_type * workflow_job , const char * function) { - workflow_job->function = util_realloc_string_copy( workflow_job->function , function ); -} - -char * workflow_job_get_function( workflow_job_type * workflow_job) { - return workflow_job->function; -} - -void workflow_job_iset_argtype( workflow_job_type * workflow_job , int iarg , config_item_types type) { - if (type == CONFIG_STRING || type == CONFIG_INT || type == CONFIG_FLOAT || type == CONFIG_BOOL) - int_vector_iset( workflow_job->arg_types , iarg , type ); -} - -void workflow_job_set_min_arg( workflow_job_type * workflow_job , int min_arg) { - workflow_job->min_arg = min_arg; -} - -void workflow_job_set_max_arg( workflow_job_type * workflow_job , int max_arg) { - workflow_job->max_arg = max_arg; -} - -int workflow_job_get_min_arg( const workflow_job_type * workflow_job ) { - return workflow_job->min_arg; -} - -int workflow_job_get_max_arg( const workflow_job_type * workflow_job ) { - return workflow_job->max_arg; -} - -config_item_types workflow_job_iget_argtype( const workflow_job_type * workflow_job, int index) { - return int_vector_safe_iget( workflow_job->arg_types , index ); -} - - - -static void workflow_job_iset_argtype_string( workflow_job_type * workflow_job , int iarg , const char * arg_type) { - config_item_types type = CONFIG_INVALID; - - if (strcmp( arg_type , WORKFLOW_JOB_STRING_TYPE) == 0) - type = CONFIG_STRING; - else if (strcmp( arg_type , WORKFLOW_JOB_INT_TYPE) == 0) - type = CONFIG_INT; - else if (strcmp( arg_type , WORKFLOW_JOB_FLOAT_TYPE) == 0) - type = CONFIG_FLOAT; - else if (strcmp( arg_type , WORKFLOW_JOB_BOOL_TYPE) == 0) - type = CONFIG_BOOL; - - if (type != CONFIG_INVALID) - workflow_job_iset_argtype( workflow_job , iarg , type ); - -} - - -static void workflow_job_validate_internal( workflow_job_type * workflow_job ) { - if (workflow_job->executable == NULL) { - if ((workflow_job->internal_script_path == NULL) && (workflow_job->function != NULL)) { - workflow_job->lib_handle = dlopen( workflow_job->module , RTLD_NOW ); - if (workflow_job->lib_handle != NULL) { - workflow_job->dl_func = (workflow_job_ftype *) dlsym( workflow_job->lib_handle , workflow_job->function ); - if (workflow_job->dl_func != NULL) - workflow_job->valid = true; - else - fprintf(stderr,"Failed to load symbol:%s Error:%s \n",workflow_job->function , dlerror()); - } else { - if (workflow_job->module != NULL) - fprintf(stderr,"Failed to load module:%s Error:%s \n",workflow_job->module , dlerror()); - } - } else if ((workflow_job->internal_script_path != NULL) && (workflow_job->function == NULL)) { - workflow_job->valid = true; - } else { - fprintf(stderr, "Must have function != NULL or internal_script != NULL for internal jobs"); - } - } else { - fprintf(stderr, "Must have executable == NULL for internal jobs\n"); - } -} - - -static void workflow_job_validate_external( workflow_job_type * workflow_job ) { - if (workflow_job->executable != NULL) { - if (util_is_executable( workflow_job->executable ) && - (workflow_job->module == workflow_job->function) && - (workflow_job->module == NULL)) - workflow_job->valid = true; - } -} - - - -static void workflow_job_validate( workflow_job_type * workflow_job ) { - if (workflow_job->internal) - workflow_job_validate_internal( workflow_job ); - else - workflow_job_validate_external( workflow_job ); -} - - - - -workflow_job_type * workflow_job_config_alloc( const char * name , config_parser_type * config , const char * config_file) { - workflow_job_type * workflow_job = NULL; - config_content_type * content = config_parse( config , config_file , "--", NULL , NULL , NULL , CONFIG_UNRECOGNIZED_WARN , true); - if (config_content_is_valid( content )) { - bool internal = DEFAULT_INTERNAL; - if (config_content_has_item( content , INTERNAL_KEY)) - internal = config_content_iget_as_bool( content , INTERNAL_KEY , 0 , 0 ); - - { - workflow_job = workflow_job_alloc( name , internal ); - - if (config_content_has_item( content , MIN_ARG_KEY)) - workflow_job_set_min_arg( workflow_job , config_content_iget_as_int( content , MIN_ARG_KEY , 0 , 0 )); - - if (config_content_has_item( content , MAX_ARG_KEY)) - workflow_job_set_max_arg( workflow_job , config_content_iget_as_int( content , MAX_ARG_KEY , 0 , 0 )); - - { - int i; - for (i=0; i < config_content_get_occurences( content , ARG_TYPE_KEY); i++) { - int iarg = config_content_iget_as_int( content , ARG_TYPE_KEY , i , 0 ); - const char * arg_type = config_content_iget( content , ARG_TYPE_KEY , i , 1 ); - - workflow_job_iset_argtype_string( workflow_job , iarg , arg_type ); - } - } - - if (config_content_has_item( content , MODULE_KEY)) - workflow_job_set_module( workflow_job , config_content_get_value( content , MODULE_KEY)); // Could be a pure so name; or a full path ..... Like executable - - if (config_content_has_item( content , FUNCTION_KEY)) - workflow_job_set_function( workflow_job , config_content_get_value( content , FUNCTION_KEY)); - - if (config_content_has_item( content , EXECUTABLE_KEY)) - workflow_job_set_executable( workflow_job , config_content_get_value_as_abspath( content , EXECUTABLE_KEY)); - - if (config_content_has_item( content , SCRIPT_KEY)) { - workflow_job_set_internal_script( workflow_job , config_content_get_value_as_abspath( content , SCRIPT_KEY)); - } - - workflow_job_validate( workflow_job ); - - if (!workflow_job->valid) { - workflow_job_free( workflow_job ); - workflow_job = NULL; - } - } - } - config_content_free( content ); - return workflow_job; -} - - - - -void workflow_job_free( workflow_job_type * workflow_job ) { - util_safe_free( workflow_job->module ); - util_safe_free( workflow_job->function ); - util_safe_free( workflow_job->executable ); - int_vector_free( workflow_job->arg_types ); - free( workflow_job->name ); - free( workflow_job ); -} - - -void workflow_job_free__( void * arg) { - workflow_job_type * workflow_job = workflow_job_safe_cast( arg ); - workflow_job_free( workflow_job ); -} - -/* - The workflow job can return an arbitrary (void *) pointer. It is the - calling scopes responsability to interpret this object correctly. If - the the workflow job allocates storage the calling scope must - discard it. -*/ - -static void * workflow_job_run_internal( const workflow_job_type * job, void * self , bool verbose , const stringlist_type * arg) { - return job->dl_func( self , arg ); -} - - -static void * workflow_job_run_external( const workflow_job_type * job, bool verbose , const stringlist_type * arg) { - char ** argv = stringlist_alloc_char_copy( arg ); - - util_spawn_blocking(job->executable, stringlist_get_size(arg), (const char **) argv, NULL, NULL); - - if (argv != NULL) { - int i; - for (i=0; i < stringlist_get_size( arg ); i++) - free( argv[i] ); - free( argv ); - } - return NULL; -} - -/* This is the old C way and will only be used from the TUI */ -void * workflow_job_run( const workflow_job_type * job, void * self , bool verbose , const stringlist_type * arg) { - if (job->internal) { - if (workflow_job_is_internal_script(job)) { - fprintf(stderr, "*** Can not run internal script workflow jobs using this method: workflow_job_run()\n"); - return NULL; - } else { - return workflow_job_run_internal( job, self, verbose, arg ); - } - } else { - return workflow_job_run_external( job, verbose, arg ); - } -} diff --git a/ThirdParty/Ert/libjob_queue/src/workflow_joblist.c b/ThirdParty/Ert/libjob_queue/src/workflow_joblist.c deleted file mode 100644 index 23806cc81a..0000000000 --- a/ThirdParty/Ert/libjob_queue/src/workflow_joblist.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'workflow_joblist.c' is part of ERT - Ensemble based - Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - - -struct workflow_joblist_struct { - config_parser_type * workflow_compiler; - config_parser_type * job_config; - - hash_type * joblist; -}; - - -workflow_joblist_type * workflow_joblist_alloc( ) { - workflow_joblist_type * joblist = util_malloc( sizeof * joblist ); - - joblist->job_config = workflow_job_alloc_config(); - joblist->workflow_compiler = config_alloc(); - joblist->joblist = hash_alloc(); - - return joblist; -} - - -void workflow_joblist_free( workflow_joblist_type * joblist) { - config_free( joblist->job_config ); - config_free( joblist->workflow_compiler ); - hash_free( joblist->joblist ); - free( joblist ); -} - - -const workflow_job_type * workflow_joblist_get_job( const workflow_joblist_type * joblist , const char * job_name) { - return hash_get( joblist->joblist , job_name ); -} - - -void workflow_joblist_add_job( workflow_joblist_type * joblist , const workflow_job_type * job) { - hash_insert_hash_owned_ref( joblist->joblist , workflow_job_get_name( job ) , job , workflow_job_free__ ); - workflow_job_update_config_compiler( job , joblist->workflow_compiler ); -} - - -bool workflow_joblist_has_job( const workflow_joblist_type * joblist , const char * job_name) { - workflow_job_type * job = hash_safe_get(joblist->joblist, job_name); - return (NULL != job); -} - -bool workflow_joblist_add_job_from_file( workflow_joblist_type * joblist , const char * job_name , const char * config_file ) { - workflow_job_type * job = workflow_job_config_alloc( job_name , joblist->job_config , config_file ); - if (job) { - workflow_joblist_add_job( joblist , job ); - return true; - } else - return false; -} - - -config_parser_type * workflow_joblist_get_compiler( const workflow_joblist_type * joblist ) { - return joblist->workflow_compiler; -} - - -config_parser_type * workflow_joblist_get_job_config( const workflow_joblist_type * joblist ) { - return joblist->job_config; -} - -stringlist_type * workflow_joblist_get_job_names(const workflow_joblist_type * joblist) { - return hash_alloc_stringlist(joblist->joblist); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/CMakeLists.txt b/ThirdParty/Ert/libjob_queue/tests/CMakeLists.txt deleted file mode 100644 index 873cc1a515..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/CMakeLists.txt +++ /dev/null @@ -1,87 +0,0 @@ -add_executable( job_status_test job_status_test.c ) -add_executable( job_loadOK job_loadOK.c ) -add_executable( job_loadFail job_loadFail.c ) -add_executable( job_node_test job_node_test.c ) -add_executable( job_list_test job_list_test.c ) -add_executable( create_file create_file.c ) -add_executable( job_workflow_test job_workflow_test.c ) -add_executable( job_lsf_parse_bsub_stdout job_lsf_parse_bsub_stdout.c ) -add_executable( job_lsf_exclude_hosts_test job_lsf_exclude_hosts_test.c ) - -target_link_libraries( job_status_test job_queue test_util ) -target_link_libraries( job_workflow_test job_queue test_util ) -target_link_libraries( create_file job_queue test_util ) -target_link_libraries( job_loadOK job_queue test_util ) -target_link_libraries( job_loadFail job_queue test_util ) -target_link_libraries( job_lsf_parse_bsub_stdout job_queue test_util) -target_link_libraries( job_node_test job_queue test_util) -target_link_libraries( job_list_test job_queue test_util) -target_link_libraries( job_lsf_exclude_hosts_test job_queue util ) - -add_test( job_status_test ${EXECUTABLE_OUTPUT_PATH}/job_status_test) -add_test( job_lsf_parse_bsub_stdout ${EXECUTABLE_OUTPUT_PATH}/job_lsf_parse_bsub_stdout ) - -add_test( job_workflow_test ${EXECUTABLE_OUTPUT_PATH}/job_workflow_test ${EXECUTABLE_OUTPUT_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/data/internal_job) - -add_test( job_loadOK1 ${EXECUTABLE_OUTPUT_PATH}/job_loadOK ${CMAKE_CURRENT_SOURCE_DIR}/data/internalOK) -add_test( job_loadOK2 ${EXECUTABLE_OUTPUT_PATH}/job_loadOK ${CMAKE_CURRENT_SOURCE_DIR}/data/externalOK) -add_test( job_loadOK3 ${EXECUTABLE_OUTPUT_PATH}/job_loadOK ${CMAKE_CURRENT_SOURCE_DIR}/data/internalOK ${CMAKE_CURRENT_SOURCE_DIR}/data/externalOK) - -add_test( job_loadFail1 ${EXECUTABLE_OUTPUT_PATH}/job_loadFail ${CMAKE_CURRENT_SOURCE_DIR}/data/internalFail) -add_test( job_loadFail2 ${EXECUTABLE_OUTPUT_PATH}/job_loadFail ${CMAKE_CURRENT_SOURCE_DIR}/data/externalFail) -add_test( job_loadFail3 ${EXECUTABLE_OUTPUT_PATH}/job_loadFail ${CMAKE_CURRENT_SOURCE_DIR}/data/internalFail ${CMAKE_CURRENT_SOURCE_DIR}/data/externalFail) - -add_test( job_node_test ${EXECUTABLE_OUTPUT_PATH}/job_node_test) -add_test( job_list_test valgrind --leak-check=full --error-exitcode=1 ${EXECUTABLE_OUTPUT_PATH}/job_list_test) -add_test( job_lsf_exclude_hosts_test ${EXECUTABLE_OUTPUT_PATH}/job_lsf_exclude_hosts_test ${EXECUTABLE_OUTPUT_PATH}/job_program NULL LOCAL) - -add_executable( job_program_output job_program_output.c ) -target_link_libraries( job_program_output ert_util test_util) - -add_executable( job_queue_test job_job_queue_test.c ) -target_link_libraries( job_queue_test job_queue test_util ) -add_test( job_queue_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_test ${EXECUTABLE_OUTPUT_PATH}/job_program_output ) - -add_executable( job_queue_stress_task job_queue_stress_task.c ) -target_link_libraries( job_queue_stress_task ert_util ) - -add_executable( job_queue_stress_test job_queue_stress_test.c ) -target_link_libraries( job_queue_stress_test job_queue test_util ) -add_test( job_queue_stress_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_stress_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_stress_task False) -add_test( job_queue_user_exit ${EXECUTABLE_OUTPUT_PATH}/job_queue_stress_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_stress_task True) - -add_executable( job_queue_timeout_test job_queue_timeout_test.c ) -target_link_libraries( job_queue_timeout_test job_queue test_util ) -add_test( job_queue_timeout_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_timeout_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_stress_task) - -add_executable( job_queue_driver_test job_queue_driver_test.c ) -target_link_libraries( job_queue_driver_test job_queue test_util ) -add_test( job_queue_driver_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_driver_test ) - - -if (ERT_LSF_SUBMIT_TEST) - include( lsf_tests.cmake ) -endif() - - -add_executable( job_torque_test job_torque_test.c ) -target_link_libraries( job_torque_test job_queue ert_util test_util ) -add_test( job_torque_test ${EXECUTABLE_OUTPUT_PATH}/job_torque_test ) - -add_executable( job_queue_manager job_queue_manager.c ) -target_link_libraries( job_queue_manager job_queue ert_util test_util ) -add_test( job_queue_manager ${EXECUTABLE_OUTPUT_PATH}/job_queue_manager ) - -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/qsub_emulators/ DESTINATION ${EXECUTABLE_OUTPUT_PATH}) - -add_executable( job_torque_submit_test job_torque_submit_test.c ) -target_link_libraries( job_torque_submit_test job_queue ert_util test_util ) -add_test(NAME job_torque_submit_test WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} COMMAND ${EXECUTABLE_OUTPUT_PATH}/job_torque_submit_test dummyparam) -set_property(TEST job_torque_submit_test PROPERTY ENVIRONMENT “setenv PATH ${EXECUTABLE_OUTPUT_PATH}:$PATHâ€) - - -add_executable( ext_joblist_test ext_joblist_test.c ) -target_link_libraries( ext_joblist_test job_queue test_util ) -add_test( ext_joblist_test ${EXECUTABLE_OUTPUT_PATH}/ext_joblist_test ${CMAKE_CURRENT_SOURCE_DIR}/data/jobs/util ${CMAKE_CURRENT_SOURCE_DIR}) -set_property(TEST ext_joblist_test PROPERTY LABELS StatoilData ) - diff --git a/ThirdParty/Ert/libjob_queue/tests/create_file.c b/ThirdParty/Ert/libjob_queue/tests/create_file.c deleted file mode 100644 index fbba657756..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/create_file.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'create_file.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - - -int main( int argc , char ** argv) { - char * filename = argv[1]; - int value = atoi( argv[2] ); - FILE * stream = fopen( filename , "w"); - fprintf(stream , "%d\n", value ); - fclose( stream ); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/data/externalFail b/ThirdParty/Ert/libjob_queue/tests/data/externalFail deleted file mode 100644 index 0f53d812c3..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/externalFail +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL False -MIN_ARG 1 -MAX_ARG 2 -ARG_TYPE 0 STRING -ARG_TYPE 1 INT diff --git a/ThirdParty/Ert/libjob_queue/tests/data/externalOK b/ThirdParty/Ert/libjob_queue/tests/data/externalOK deleted file mode 100644 index 67dec0bef2..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/externalOK +++ /dev/null @@ -1,6 +0,0 @@ -INTERNAL False -EXECUTABLE /usr/bin/python -MIN_ARG 1 -MAX_ARG 2 -ARG_TYPE 0 STRING -ARG_TYPE 1 INT diff --git a/ThirdParty/Ert/libjob_queue/tests/data/external_job b/ThirdParty/Ert/libjob_queue/tests/data/external_job deleted file mode 100644 index 5b39223101..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/external_job +++ /dev/null @@ -1,5 +0,0 @@ -EXECUTABLE /private/joaho/ERT/git/ert/build/bin/create_file -ARG_TYPE 0 STRING -ARG_TYPE 1 INT -MIN_ARG 2 -MAX_ARG 2 \ No newline at end of file diff --git a/ThirdParty/Ert/libjob_queue/tests/data/internalFail b/ThirdParty/Ert/libjob_queue/tests/data/internalFail deleted file mode 100644 index 40686fc1d5..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/internalFail +++ /dev/null @@ -1,6 +0,0 @@ -INTERNAL True -MODULE NULL -MIN_ARG 1 -MAX_ARG 2 -ARG_TYPE 0 STRING -ARG_TYPE 1 INT diff --git a/ThirdParty/Ert/libjob_queue/tests/data/internalOK b/ThirdParty/Ert/libjob_queue/tests/data/internalOK deleted file mode 100644 index 6252998faa..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/internalOK +++ /dev/null @@ -1,7 +0,0 @@ -INTERNAL True -MODULE NULL -FUNCTION workflow_job_alloc -MIN_ARG 1 -MAX_ARG 2 -ARG_TYPE 0 STRING -ARG_TYPE 1 INT diff --git a/ThirdParty/Ert/libjob_queue/tests/data/internal_job b/ThirdParty/Ert/libjob_queue/tests/data/internal_job deleted file mode 100644 index 2c86544a44..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/internal_job +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION read_file -ARG_TYPE 0 STRING -MIN_ARG 1 -MAX_ARG 1 diff --git a/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/COPY_FILE b/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/COPY_FILE deleted file mode 100644 index 9867a28978..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/COPY_FILE +++ /dev/null @@ -1,2 +0,0 @@ -EXECUTABLE /bin/cp -ARGLIST diff --git a/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/REPLACE b/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/REPLACE deleted file mode 100644 index 79e5f19b01..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/REPLACE +++ /dev/null @@ -1,6 +0,0 @@ -STDOUT replace.stdout -STDERR replace.stderr - -EXECUTABLE /project/res/x86_64_RH_4/bin/replace.x -ARGLIST - diff --git a/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/STORE_FILE b/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/STORE_FILE deleted file mode 100644 index 0bdb3d3b68..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/STORE_FILE +++ /dev/null @@ -1,5 +0,0 @@ -STDOUT store_file.stdout -STDERR store_file.stderr - -EXECUTABLE ../../../Scripts/store_file.py -ARGLIST diff --git a/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/SYMLINK b/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/SYMLINK deleted file mode 100644 index 72ebb65a7c..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/jobs/util/SYMLINK +++ /dev/null @@ -1,6 +0,0 @@ -STDERR SYMLINK.stderr -STDOUT SYMLINK.stdout - -EXECUTABLE /bin/ln -ARGLIST -sf - diff --git a/ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qdel b/ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qdel deleted file mode 100644 index 513e57d5da..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qdel +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -echo "#!/bin/sh" > qstat -echo "echo \"Job id Name User Time Use S Queue\"" >> qstat -echo "echo \"------------------------- ---------------- --------------- -------- - -----\"" >> qstat -echo "echo \"1612427.st-lcmm ...130getupdates fama 00:00:01 E normal\"" >> qstat \ No newline at end of file diff --git a/ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qstat b/ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qstat deleted file mode 100644 index 47ae34dc9b..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qstat +++ /dev/null @@ -1 +0,0 @@ -Content will be piped into this file \ No newline at end of file diff --git a/ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qsub b/ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qsub deleted file mode 100644 index 43ddcb8568..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/data/qsub_emulators/qsub +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -echo 1612427.greier.og.greier -echo "#!/bin/sh" > qstat -echo "echo \"Job id Name User Time Use S Queue\"" >> qstat -echo "echo \"------------------------- ---------------- --------------- -------- - -----\"" >> qstat -echo "echo \"1612427.st-lcmm ...130getupdates fama 00:00:01 R normal\"" >> qstat \ No newline at end of file diff --git a/ThirdParty/Ert/libjob_queue/tests/ext_joblist_test.c b/ThirdParty/Ert/libjob_queue/tests/ext_joblist_test.c deleted file mode 100644 index 5dfdc9848b..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/ext_joblist_test.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'ext_joblist_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -void load_job_directory(ext_joblist_type * joblist , const char * path, const char * license_root_path) { - bool user_mode = false; - ext_joblist_add_jobs_in_directory(joblist , path, license_root_path, user_mode, true ); - test_assert_true( ext_joblist_has_job(joblist, "SYMLINK")); -} - -int main( int argc , char ** argv) { - int status = 0; - ext_joblist_type * joblist = ext_joblist_alloc(); - load_job_directory(joblist , argv[1], argv[2] ); - ext_joblist_free(joblist); - exit( status ); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_job_queue_test.c b/ThirdParty/Ert/libjob_queue/tests/job_job_queue_test.c deleted file mode 100644 index a24e5afcd6..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_job_queue_test.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'job_queue_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - -void submit_jobs_to_queue(job_queue_type * queue, test_work_area_type * work_area, char * executable_to_run, int number_of_jobs, int number_of_slowjobs, char* sleep_short, char* sleep_long) { - int submitted_slowjobs = 0; - for (int i = 0; i < number_of_jobs; i++) { - char * runpath = util_alloc_sprintf("%s/%s_%d", test_work_area_get_cwd(work_area), "job", i); - util_make_path(runpath); - - char * sleeptime = sleep_short; - if (submitted_slowjobs < number_of_slowjobs) { - sleeptime = sleep_long; - submitted_slowjobs++; - } - - job_queue_add_job(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) {runpath, sleeptime}); - free(runpath); - } - test_assert_int_equal( number_of_jobs , job_queue_get_active_size(queue) ); -} - -void monitor_job_queue(job_queue_type * queue, int max_job_duration, time_t stop_time, int min_realizations) { - if (min_realizations > 0) { - while (true) { - util_usleep(100); - - //Check if minimum number of realizations have run, and if so, kill the rest after a certain time - if ((job_queue_get_num_complete(queue) >= min_realizations)) { - job_queue_set_max_job_duration(queue, max_job_duration); - job_queue_set_job_stop_time(queue, stop_time); - break; - } - } - } -} - - - -void run_jobs_with_time_limit_test(char * executable_to_run, int number_of_jobs, int number_of_slowjobs, char * sleep_short, char * sleep_long, int max_sleep) { - test_work_area_type * work_area = test_work_area_alloc("job_queue"); - job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "STATUS", "ERROR"); - - queue_driver_type * driver = queue_driver_alloc_local(); - job_queue_set_driver(queue, driver); - job_queue_set_max_job_duration(queue, max_sleep); - - submit_jobs_to_queue(queue, work_area, executable_to_run, number_of_jobs, number_of_slowjobs, sleep_short, sleep_long); - - job_queue_run_jobs(queue, number_of_jobs, false); - - test_assert_int_equal(number_of_jobs - number_of_slowjobs, job_queue_get_num_complete(queue)); - test_assert_int_equal(number_of_slowjobs, job_queue_get_num_killed(queue)); - - test_assert_bool_equal(false, job_queue_get_open(queue)); - job_queue_reset(queue); - test_assert_bool_equal(true, job_queue_get_open(queue)); - - test_assert_int_equal(0, job_queue_get_num_complete(queue)); - - job_queue_free(queue); - queue_driver_free(driver); - test_work_area_free(work_area); -} - - -void run_and_monitor_jobs(char * executable_to_run, - int number_of_jobs , - int max_job_duration, - time_t stop_time, - int min_realizations, - int min_completed, - int max_completed , - int interval_between_jobs) { - - test_work_area_type * work_area = test_work_area_alloc("job_queue"); - job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "STATUS", "ERROR"); - job_queue_manager_type * queue_manager = job_queue_manager_alloc( queue ); - queue_driver_type * driver = queue_driver_alloc_local(); - - job_queue_set_driver(queue, driver); - - - int job_run_time = 0; - - for (int i = 0; i < number_of_jobs; i++) { - char * runpath = util_alloc_sprintf("%s/%s_%d", test_work_area_get_cwd(work_area), "job", i); - char * sleeptime = util_alloc_sprintf("%d", job_run_time); - - util_make_path(runpath); - job_queue_add_job(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) {runpath, sleeptime}); - job_run_time += interval_between_jobs; - - free(sleeptime); - free(runpath); - } - job_queue_submit_complete(queue); - job_queue_manager_start_queue(queue_manager,0,false,false); - monitor_job_queue( queue , max_job_duration , stop_time , min_realizations ); - job_queue_manager_wait(queue_manager); - - printf("Completed: %d <= %d <= %d ?\n",min_completed , job_queue_get_num_complete(queue) , max_completed); - test_assert_true(job_queue_get_num_complete(queue) >= min_completed); - test_assert_true(job_queue_get_num_complete(queue) <= max_completed); - - test_assert_int_equal(number_of_jobs - job_queue_get_num_complete( queue ) , job_queue_get_num_killed(queue)); - test_assert_bool_equal(false, job_queue_get_open(queue)); - job_queue_reset(queue); - test_assert_bool_equal(true, job_queue_get_open(queue)); - test_assert_int_equal(0, job_queue_get_num_complete(queue)); - - job_queue_free(queue); - queue_driver_free(driver); - job_queue_manager_free( queue_manager ); - test_work_area_free(work_area); -} - -void run_jobs_time_limit_multithreaded(char * executable_to_run, int number_of_jobs, int number_of_slowjobs, char * sleep_short, char * sleep_long, int max_sleep) { - test_work_area_type * work_area = test_work_area_alloc("job_queue"); - - - job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "STATUS", "ERROR"); - queue_driver_type * driver = queue_driver_alloc_local(); - job_queue_set_driver(queue, driver); - job_queue_set_max_job_duration(queue, max_sleep); - - arg_pack_type * arg_pack = arg_pack_alloc(); - arg_pack_append_ptr(arg_pack, queue); - arg_pack_append_int(arg_pack, 0); - arg_pack_append_bool(arg_pack, false); - - thread_pool_type * pool = thread_pool_alloc(1, true); - thread_pool_add_job(pool, job_queue_run_jobs__, arg_pack); - - submit_jobs_to_queue(queue, work_area, executable_to_run, number_of_jobs, number_of_slowjobs, sleep_short, sleep_long); - - job_queue_submit_complete(queue); - thread_pool_join(pool); - thread_pool_free(pool); - - test_assert_int_equal(number_of_jobs - number_of_slowjobs, job_queue_get_num_complete(queue)); - test_assert_int_equal(number_of_slowjobs, job_queue_get_num_killed(queue)); - test_assert_bool_equal(false, job_queue_get_open(queue)); - job_queue_reset(queue); - test_assert_bool_equal(true, job_queue_get_open(queue)); - test_assert_int_equal(0, job_queue_get_num_complete(queue)); - - job_queue_free(queue); - queue_driver_free(driver); - test_work_area_free(work_area); -} - -void test1(char ** argv) { - printf("001: Running JobQueueRunJobs_ReuseQueue_AllOk\n"); - - int number_of_jobs = 20; - int number_of_queue_reuse = 10; - - test_work_area_type * work_area = test_work_area_alloc("job_queue"); - - job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "STATUS", "ERROR"); - queue_driver_type * driver = queue_driver_alloc_local(); - job_queue_set_driver(queue, driver); - - for (int j = 0; j < number_of_queue_reuse; j++) { - submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, 0, "0", "0"); - - job_queue_run_jobs(queue, number_of_jobs, false); - - test_assert_int_equal(number_of_jobs, job_queue_get_num_complete(queue)); - test_assert_bool_equal(false, job_queue_get_open(queue)); - job_queue_reset(queue); - test_assert_bool_equal(true, job_queue_get_open(queue)); - test_assert_int_equal(0, job_queue_get_num_complete(queue)); - } - job_queue_free(queue); - queue_driver_free(driver); - test_work_area_free(work_area); - -} - -void test2(char ** argv) { - printf("002: Running JobQueueRunJobs_ReuseQueueWithStopTime_AllOk\n"); - - int number_of_jobs = 3; - int number_of_slow_jobs = 2; - int number_of_queue_reuse = 3; - - test_work_area_type * work_area = test_work_area_alloc("job_queue"); - - job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "STATUS", "ERROR"); - queue_driver_type * driver = queue_driver_alloc_local(); - job_queue_set_driver(queue, driver); - - for (int j = 0; j < number_of_queue_reuse; j++) { - submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_slow_jobs, "1", "5"); - - job_queue_run_jobs(queue, number_of_jobs, false); - time_t current_time = time(NULL); - job_queue_set_job_stop_time(queue, current_time); - - test_assert_int_equal(number_of_jobs, job_queue_get_num_complete(queue)); - test_assert_bool_equal(false, job_queue_get_open(queue)); - job_queue_reset(queue); - test_assert_bool_equal(true, job_queue_get_open(queue)); - test_assert_int_equal(0, job_queue_get_num_complete(queue)); - } - job_queue_free(queue); - queue_driver_free(driver); - test_work_area_free(work_area); - -} - - -void test3(char ** argv) { - printf("003: Running JobQueueSetStopTime_StopTimeEarly_MinRealisationsAreRun\n"); - - //Use stop_time to to stop jobs after min_realizations are finished - int number_of_jobs = 10; - int min_realizations = 5; - int num_expected_completed = 5; - int max_duration_time = 0; - int interval_between_jobs = 2; - time_t stoptime = time( NULL ); - - run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs); -} - -void test4(char ** argv) { - printf("004: Running JobQueueSetMaxDuration_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds\n"); - run_jobs_with_time_limit_test(argv[1], 100, 23, "1", "100", 5); -} - - -void test5(char ** argv) { - printf("005: Running JobQueueSetStopTime_StopTimeLate_AllRealisationsAreRun\n"); - - //Use stop_time to to stop jobs after min_realizations are finished - int number_of_jobs = 10; - int min_realizations = 5; - int num_expected_completed = 10; - int max_duration_time = 0; - int interval_between_jobs = 0; - time_t currenttime; - time(¤ttime); - time_t stoptime = currenttime + 15; - run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs); -} - -void test6(char ** argv) { - printf("006: Running JobQueueSetStopTimeAndMaxDuration_MaxDurationShort_StopTimeLong_MinRealisationsAreRun\n"); - - int number_of_jobs = 10; - int min_realizations = 1; - int num_expected_completed = 1; - int max_duration_time = 1; - int interval_between_jobs = 2; - time_t currenttime; - time(¤ttime); - time_t stoptime = currenttime + 10; - run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, number_of_jobs , interval_between_jobs); - -} - -void test7(char ** argv) { - printf("007: Running JobQueueSetStopTimeAndMaxDuration_MaxDurationLong_StopTimeEarly_MinRealisationsAreRun\n"); - - int number_of_jobs = 10; - int min_realizations = 1; - int num_expected_completed = 1; - int max_duration_time = 10; - int interval_between_jobs = 2; - time_t currenttime; - time(¤ttime); - time_t stoptime = currenttime + 1; - run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs); -} - -void test8(char ** argv) { - printf("008: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShort_OnlyMinRealizationsAreRun\n"); - - // Must have one job completed, the rest are then killed due to the max_duration_time gets exceeded. - int number_of_jobs = 10; - int min_realizations = 1; - int num_expected_completed = 1; - int max_duration_time = 1; - int interval_between_jobs = 2; - time_t currenttime = 0; - - run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, num_expected_completed, 3 , interval_between_jobs); -} - -void test9(char ** argv) { - printf("009: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationLooong_AllRealizationsAreRun\n"); - - // Min realizations is 1, but the max running time exceeds the time used by any of the jobs, so all run to completion - int number_of_jobs = 10; - int min_realizations = 1; - int num_expected_completed = 10; - int max_duration_time = 12; - int interval_between_jobs = 1; - time_t currenttime = 0; - run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs); -} - - -void test10(char ** argv) { - printf("010: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationSemiLong_MoreThanMinRealizationsAreRun\n"); - - int number_of_jobs = 10; - int min_realizations = 3; - int max_duration_time = 7; - int interval_between_jobs = 2; - time_t currenttime = 0; - run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, min_realizations , number_of_jobs , interval_between_jobs); -} - -void test11(char ** argv) { - printf("011: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShortButMinRealizationsIsAll_AllRealizationsAreRun\n"); - - // Min is 10, so all run to completion - int number_of_jobs = 10; - int min_realizations = 10; - int num_expected_completed = 10; - int max_duration_time = 1; - int interval_between_jobs = 0; - time_t currenttime = 0; - run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs); -} - -void test12(char ** argv) { - printf("012: Running JobQueueSetMaxDuration_DurationZero_AllRealisationsAreRun\n"); - run_jobs_with_time_limit_test(argv[1], 10, 0, "1", "100", 0); // 0 as limit means no limit*/ -} - -void test13(char ** argv) { - printf("013: Running JobQueueSetMaxDurationRunJobsLoopInThread_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds\n"); - run_jobs_time_limit_multithreaded(argv[1], 100, 23, "1", "100", 5); -} - -void test14(char ** argv) { - printf("014: Running JobQueueSetAutoStopTime_ThreeQuickJobs_AutoStopTimeKillsTheRest\n"); - - int number_of_jobs = 10; - - test_work_area_type * work_area = test_work_area_alloc("job_queue"); - job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "STATUS", "ERROR"); - queue_driver_type * driver = queue_driver_alloc_local(); - job_queue_manager_type * queue_manager = job_queue_manager_alloc( queue ); - job_queue_set_driver(queue, driver); - - - int number_of_slowjobs = 7; - int number_of_fastjobs = number_of_jobs - number_of_slowjobs; - char * sleep_short = "0"; - char * sleep_long = "100"; - submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_slowjobs, sleep_short, sleep_long); - job_queue_submit_complete(queue); - job_queue_manager_start_queue( queue_manager , 10 , false , false); - - /* - The jobs are distributed with some very fast, and some quite - long. Here we busy wait until all the fast ones have completed and - then we calculate a stop for the remaining jobs with the - job_queue_set_auto_job_stop_time() function. - */ - - while (true) { - int num_complete = job_queue_get_num_complete(queue); - if (num_complete == number_of_fastjobs) - break; - util_usleep( 100000 ); - } - - job_queue_set_auto_job_stop_time(queue); - job_queue_manager_wait(queue_manager); - - - test_assert_int_equal(number_of_jobs - number_of_slowjobs, job_queue_get_num_complete(queue)); - test_assert_int_equal(number_of_slowjobs, job_queue_get_num_killed(queue)); - - test_assert_bool_equal(false, job_queue_get_open(queue)); - job_queue_reset(queue); - test_assert_bool_equal(true, job_queue_get_open(queue)); - - test_assert_int_equal(0, job_queue_get_num_complete(queue)); - - job_queue_manager_free( queue_manager ); - job_queue_free(queue); - queue_driver_free(driver); - test_work_area_free(work_area); -} - -void test15(char ** argv) { - printf("015: Running JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing\n"); - - int number_of_jobs = 10; - - test_work_area_type * work_area = test_work_area_alloc("job_queue"); - job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "STATUS", "ERROR"); - queue_driver_type * driver = queue_driver_alloc_local(); - job_queue_set_driver(queue, driver); - - char * sleep_long = "100"; - - submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_jobs, "0", sleep_long); - - job_queue_set_auto_job_stop_time(queue); - - test_assert_int_equal(0, job_queue_get_num_complete(queue)); - test_assert_bool_equal(true, job_queue_get_open(queue)); - - job_queue_free(queue); - queue_driver_free(driver); - test_work_area_free(work_area); -} - -void test16(char ** argv) { - printf("016: Running JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing\n"); - - int number_of_jobs = 10; - test_work_area_type * work_area = test_work_area_alloc("job_queue"); - job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "STATUS", "ERROR"); - - queue_driver_type * driver = queue_driver_alloc_local(); - job_queue_set_driver(queue, driver); - - submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, 0, "0", "0"); - - job_queue_run_jobs(queue, number_of_jobs, false); - - test_assert_int_equal(number_of_jobs, job_queue_get_num_complete(queue)); - test_assert_bool_equal(false, job_queue_get_open(queue)); - job_queue_reset(queue); - test_assert_bool_equal(true, job_queue_get_open(queue)); - test_assert_int_equal(0, job_queue_get_num_complete(queue)); - job_queue_free(queue); - queue_driver_free(driver); - test_work_area_free(work_area); -} - - -int main(int argc, char ** argv) { - util_install_signals(); - - test1(argv); - test2(argv); - test3(argv); - test4(argv); - test5(argv); - test6(argv); - test7(argv); - test8(argv); - test9(argv); - test10(argv); - test11(argv); - test12(argv); - test13(argv); - test14(argv); - test15(argv); - test16(argv); - - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_list_test.c b/ThirdParty/Ert/libjob_queue/tests/job_list_test.c deleted file mode 100644 index 5859623adb..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_list_test.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'job_node_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include "ert/util/build_config.h" - -#include -#include -#include - -#include -#include - - -void test_create() { - job_list_type * list = job_list_alloc(); - test_assert_true( job_list_is_instance( list )); - test_assert_int_equal( 0 , job_list_get_size( list )); - job_list_free( list ); -} - - - -void call_add_job( void * arg ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - job_list_type * job_list = arg_pack_iget_ptr( arg_pack , 0 ); - job_queue_node_type * node = arg_pack_iget_ptr( arg_pack , 1 ); - job_list_add_job( job_list , node ); -} - - -void call_iget_job( void * arg ) { - job_list_type * job_list = job_list_safe_cast( arg ); - job_list_iget_job( job_list , 10); -} - - - -void test_add_job() { - job_list_type * list = job_list_alloc(); - job_queue_node_type * node = job_queue_node_alloc_simple("name" , "/tmp" , "/bin/ls" , 0 , NULL); - job_list_add_job( list , node ); - test_assert_int_equal( job_list_get_size( list ) , 1 ); - test_assert_int_equal( job_queue_node_get_queue_index(node) , 0 ); - test_assert_ptr_equal( node , job_list_iget_job(list , 0)); - { - arg_pack_type * arg_pack = arg_pack_alloc( ); - arg_pack_append_ptr( arg_pack , list ); - arg_pack_append_ptr( arg_pack , node ); - test_assert_util_abort("job_queue_node_set_queue_index", call_add_job, arg_pack ); - arg_pack_free( arg_pack ); - } - test_assert_util_abort("job_list_iget_job", call_iget_job, list); - job_list_reset( list ); - test_assert_int_equal( 0 , job_list_get_size( list )); - job_list_free( list ); -} - - -int main( int argc , char ** argv) { - util_install_signals(); - test_create(); - test_add_job(); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_loadFail.c b/ThirdParty/Ert/libjob_queue/tests/job_loadFail.c deleted file mode 100644 index a2e5c20d28..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_loadFail.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_loadFail.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include - -#include - - - -bool loadConfig(config_parser_type * config , const char * config_file, config_parser_type * config_compiler) { - bool OK = false; - workflow_job_type * cmd = workflow_job_config_alloc( "NAME" , config , config_file); - - if (cmd != NULL) { - OK = true; - workflow_job_update_config_compiler( cmd , config_compiler ); - workflow_job_free( cmd ); - } - - return OK; -} - - - -int main( int argc , char ** argv) { - int status = 0; - { - config_parser_type * config = workflow_job_alloc_config(); - config_parser_type * config_compiler = config_alloc(); - int iarg; - bool OK = true; - - for (iarg = 1; iarg < argc; iarg++) - OK = OK && (loadConfig( config , argv[iarg] , config_compiler ) == false); - - if (!OK) - status = 1; - - config_free(config_compiler); - config_free(config); - } - exit( status ); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_loadOK.c b/ThirdParty/Ert/libjob_queue/tests/job_loadOK.c deleted file mode 100644 index 2e15a636e5..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_loadOK.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_loadOK.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include - -#include - - - -bool loadConfig(config_parser_type * config , const char * config_file , config_parser_type * config_compiler) { - bool OK = false; - workflow_job_type * cmd = workflow_job_config_alloc( "NAME" , config , config_file); - - if (cmd != NULL) { - OK = true; - workflow_job_update_config_compiler( cmd , config_compiler ); - workflow_job_free( cmd ); - } - - return OK; -} - - - -int main( int argc , char ** argv) { - int status = 0; - { - config_parser_type * config = workflow_job_alloc_config(); - config_parser_type * config_compiler = config_alloc(); - int iarg; - bool OK = true; - - for (iarg = 1; iarg < argc; iarg++) - OK = OK && loadConfig( config , argv[iarg] , config_compiler); - - if (!OK) - status = 1; - - config_free(config_compiler); - config_free(config); - } - exit( status ); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_lsb.c b/ThirdParty/Ert/libjob_queue/tests/job_lsb.c deleted file mode 100644 index efd340ce4a..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_lsb.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_lsb.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - -#include - -#include - -/* - This test should ideally be run twice in two different environments; - with and without dlopen() access to the lsf libraries. -*/ - -int main( int argc , char ** argv) { - lsb_type * lsb = lsb_alloc(); - - test_assert_not_NULL( lsb ); - if (!lsb_ready(lsb)) { - const stringlist_type * error_list = lsb_get_error_list( lsb ); - stringlist_fprintf(error_list , "\n", stdout); - } - - if (dlopen( "libbat.so" , RTLD_NOW | RTLD_GLOBAL)) - test_assert_true( lsb_ready( lsb )); - else - test_assert_false( lsb_ready( lsb )); - - lsb_free( lsb ); - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_lsf_exclude_hosts_test.c b/ThirdParty/Ert/libjob_queue/tests/job_lsf_exclude_hosts_test.c deleted file mode 100644 index 6ea2275f8c..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_lsf_exclude_hosts_test.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2016 Statoil ASA, Norway. - * - * This file is part of ERT - Ensemble based Reservoir Tool. - * - * ERT 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. - * - * ERT 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 at - * for more details. - */ - -#include -#include -#include - -#include -#include - -#include -#include - -void test_submit(lsf_driver_type * driver, const char * cmd) { - { - char * node1 = "enern"; - char * node2 = "toern"; - char * node3 = "tre-ern.statoil.org"; - char * black1 = util_alloc_sprintf("hname!='%s'", node1); - char * black2 = util_alloc_sprintf("hname!='%s'", node2); - char * black3 = util_alloc_sprintf("hname!='%s'", node3); - char * select = util_alloc_sprintf("select[%s && %s && %s]", black1, black2, black3); - - lsf_driver_add_exclude_hosts(driver, node1); - lsf_driver_add_exclude_hosts(driver, node2); - lsf_driver_add_exclude_hosts(driver, node3); - - { - stringlist_type * argv = lsf_driver_alloc_cmd(driver, "", "NAME", "bsub", 1, 0, NULL); - if (!stringlist_contains(argv, select)) { - printf("%s lsf_driver_alloc_cmd argv does not contain %s\n", __func__, select); - printf("%s lsf_driver_alloc_cmd was %s\n", __func__, stringlist_alloc_joined_string(argv, " ")); - exit(1); - } - } - } -} - -void test_bjobs_parse_hosts() { - const char* full_hostnames = "hname1:4*hname2:13*st-rst666-01-42.st.example.org:1*hname4:hname5\n"; - const char* hostnames = "hname1:hname2:st-rst666-01-42.st.example.org:hname4:hname5"; - stringlist_type * expected = stringlist_alloc_from_split(hostnames,":"); - if (stringlist_get_size(expected) != 5) { - printf("Even expected has wrong size.\n"); - exit(1); - } - - char * fname = util_alloc_tmp_file("/tmp", "ert_job_exec_host", true); - - FILE * fptr; - fptr = fopen(fname, "w"); - fprintf(fptr, full_hostnames); // : is std bjobs delimiter - fclose(fptr); - - stringlist_type * hosts = lsf_job_alloc_parse_hostnames(fname); - - if (!stringlist_equal(expected, hosts)) { - printf("hosts differ: expected [%s] got [%s]\n", - stringlist_alloc_joined_string(expected, ":"), - stringlist_alloc_joined_string(hosts, ":")); - exit(1); - } - - util_unlink_existing(fname); - free(fname); - stringlist_free( hosts ); -} - -int main(int argc, char ** argv) { - lsf_driver_type * driver = lsf_driver_alloc(); - test_submit(driver, argv[1]); - lsf_driver_free(driver); - test_bjobs_parse_hosts(); - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_lsf_library_submit_test.c b/ThirdParty/Ert/libjob_queue/tests/job_lsf_library_submit_test.c deleted file mode 100644 index f834ebfdf4..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_lsf_library_submit_test.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_lsf_submit_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - -#include -#include - -#include -#include - - - -void test_submit(lsf_driver_type * driver, const char * cmd) { - assert( lsf_driver_set_option(driver , LSF_DEBUG_OUTPUT , "TRUE" ) ); - assert( LSF_SUBMIT_INTERNAL == lsf_driver_get_submit_method( driver )); - { - char * run_path = util_alloc_cwd(); - lsf_job_type * job = lsf_driver_submit_job( driver , cmd , 1 , run_path , "NAME" , 0 , NULL ); - assert( job ); - { - { - int lsf_status = lsf_driver_get_job_status_lsf( driver , job ); - assert( (lsf_status == JOB_STAT_RUN) || (lsf_status == JOB_STAT_PEND) ); - } - - lsf_driver_kill_job( driver , job ); - lsf_driver_set_bjobs_refresh_interval( driver , 0 ); - sleep(1); - - { - int lsf_status = lsf_driver_get_job_status_lsf( driver , job ); - assert( lsf_status == JOB_STAT_EXIT); - } - } - - free( run_path ); - } -} - - - -int main( int argc , char ** argv) { - lsf_driver_type * driver = lsf_driver_alloc(); - test_submit(driver , argv[1]); - lsf_driver_free( driver ); - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_lsf_parse_bsub_stdout.c b/ThirdParty/Ert/libjob_queue/tests/job_lsf_parse_bsub_stdout.c deleted file mode 100644 index a60c8551a7..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_lsf_parse_bsub_stdout.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'job_lsf_submit_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - - -#include "ert/util/build_config.h" - -#include -#include -#include - -#include - - -void test_empty_file() { - const char * stdout_file = "bsub_empty"; - { - FILE * stream = util_fopen(stdout_file , "w"); - fclose( stream ); - } - test_assert_int_equal( lsf_job_parse_bsub_stdout("bsub" , stdout_file ) , 0); -} - - -void test_OK() { - const char * stdout_file = "bsub_OK"; - { - FILE * stream = util_fopen(stdout_file , "w"); - fprintf(stream , "Job <12345> is submitted to default queue .\n"); - fclose( stream ); - } - test_assert_int_equal( lsf_job_parse_bsub_stdout("bsub" , stdout_file ) , 12345); -} - - -void test_file_does_not_exist() { - test_assert_int_equal( lsf_job_parse_bsub_stdout("bsub" , "does/not/exist") , 0); -} - - - -void parse_invalid( void * arg ) { - const char * filename = (const char*) arg; - lsf_job_parse_bsub_stdout("bsub" , filename); -} - - -void test_parse_fail_abort() { - const char * stdout_file = "bsub_abort"; - { - FILE * stream = util_fopen(stdout_file , "w"); - fprintf(stream , "Job 12345 is submitted to default queue .\n"); - fclose( stream ); - } - test_assert_util_abort( "lsf_job_parse_bsub_stdout" , parse_invalid , (void *) stdout_file ); -} - - -int main(int argc, char ** argv) { - test_work_area_type * work_area = test_work_area_alloc( "bsub_parse_stdout"); - { - test_empty_file(); - test_file_does_not_exist( ); - test_OK(); - test_parse_fail_abort(); - } - test_work_area_free( work_area ); -} - - diff --git a/ThirdParty/Ert/libjob_queue/tests/job_lsf_remote_submit_test.c b/ThirdParty/Ert/libjob_queue/tests/job_lsf_remote_submit_test.c deleted file mode 100644 index 8d1aab392a..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_lsf_remote_submit_test.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_lsf_submit_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - -#include -#include - -#include -#include - - -void test_submit(lsf_driver_type * driver , const char * server , const char * bsub_cmd , const char * bjobs_cmd , const char * bkill_cmd , const char * cmd) { - - test_assert_true( lsf_driver_set_option(driver , LSF_DEBUG_OUTPUT , "TRUE" ) ); - test_assert_true( lsf_driver_set_option(driver , LSF_SERVER , server ) ); - - if (bsub_cmd != NULL) - test_assert_true( lsf_driver_set_option(driver , LSF_BSUB_CMD , server )); - - if (bjobs_cmd != NULL) - test_assert_true( lsf_driver_set_option(driver , LSF_BJOBS_CMD , server ) ); - - if (bkill_cmd != NULL) - test_assert_true( lsf_driver_set_option(driver , LSF_BKILL_CMD , server )); - - { - char * run_path = util_alloc_cwd(); - lsf_job_type * job = lsf_driver_submit_job( driver , cmd , 1 , run_path , "NAME" , 0 , NULL ); - if (job) { - { - int lsf_status = lsf_driver_get_job_status_lsf( driver , job ); - if (!((lsf_status == JOB_STAT_RUN) || (lsf_status == JOB_STAT_PEND))) - test_error_exit("Got lsf_status:%d expected: %d or %d \n",lsf_status , JOB_STAT_RUN , JOB_STAT_PEND); - } - - lsf_driver_kill_job( driver , job ); - lsf_driver_set_bjobs_refresh_interval( driver , 0 ); - sleep(2); - - { - int lsf_status = 0; - for(int i=0; i < 10; i++){ - lsf_status = lsf_driver_get_job_status_lsf( driver , job ); - if (lsf_status != JOB_STAT_EXIT){ - sleep(2); - }else{ - break; - } - } - if (lsf_status != JOB_STAT_EXIT) - test_error_exit("Got lsf_status:%d expected: %d \n",lsf_status , JOB_STAT_EXIT ); - } - } else - test_error_exit("lsf_driver_submit_job() returned NULL \n"); - - - free( run_path ); - } -} - - -int main( int argc , char ** argv) { - util_install_signals(); - { - int iarg; - lsf_driver_type * driver = lsf_driver_alloc(); - - for (iarg = 2; iarg < argc; iarg++) { - const char * server = argv[iarg]; - printf("Testing lsf server:%s \n",server); - test_submit(driver , server , NULL , NULL , NULL , argv[1]); - } - - lsf_driver_free( driver ); - } - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_lsf_submit_library_test.c b/ThirdParty/Ert/libjob_queue/tests/job_lsf_submit_library_test.c deleted file mode 100644 index ef327d6df7..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_lsf_submit_library_test.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_lsf_submit_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include - -#include -#include - -#include -#include - - -void test_submit(lsf_driver_type * driver) { - test_assert_true( lsf_driver_set_option(driver , LSF_DEBUG_OUTPUT , "TRUE" ) ); - test_assert_int_equal( LSF_SUBMIT_INTERNAL , lsf_driver_get_submit_method( driver )); - { - char * run_path = util_alloc_cwd(); - lsf_job_type * job = lsf_driver_submit_job( driver , cmd , 1 , run_path , "NAME" , 0 , NULL ); - if (job) { - { - int lsf_status = lsf_driver_get_job_status_lsf( driver , job ); - if (!((lsf_status == JOB_STAT_RUN) || (lsf_status == JOB_STAT_PEND))) - test_error_exit("Got lsf_status:%d expected: %d or %d \n",lsf_status , JOB_STAT_RUN , JOB_STAT_PEND); - } - - lsf_driver_kill_job( driver , job ); - lsf_driver_set_bjobs_refresh_interval( driver , 0 ); - sleep(1); - - { - int lsf_status = lsf_driver_get_job_status_lsf( driver , job ); - if (lsf_status != JOB_STAT_EXIT) - test_error_exit("Got lsf_status:%d expected: %d \n",lsf_status , JOB_STAT_EXIT ); - } - } else - test_error_exit("lsf_driver_submit_job() returned NULL \n"); - - - free( run_path ); - } -} - - - -int main( int argc , char ** argv) { - lsf_driver_type * driver = lsf_driver_alloc(); - test_submit(driver); - lsf_driver_free( driver ); - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_lsf_test.c b/ThirdParty/Ert/libjob_queue/tests/job_lsf_test.c deleted file mode 100644 index a4a22b9d99..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_lsf_test.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_lsf_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include - -#include -#include -#include - - -void test_option(lsf_driver_type * driver , const char * option , const char * value) { - test_assert_true( lsf_driver_set_option( driver , option , value)); - test_assert_string_equal(lsf_driver_get_option( driver , option) , value); -} - - -void test_server(lsf_driver_type * driver , const char * server, lsf_submit_method_enum submit_method) { - lsf_driver_set_option(driver , LSF_SERVER , server ); - test_assert_true( lsf_driver_get_submit_method( driver ) == submit_method ); -} - - -void test_status(int lsf_status , job_status_type job_status) { - test_assert_true( lsf_driver_convert_status( lsf_status ) == job_status); -} - - -/* - This test should ideally be run twice in two different environments; - with and without dlopen() access to the lsf libraries. -*/ - -int main( int argc , char ** argv) { - lsf_driver_type * driver = lsf_driver_alloc(); - - test_option( driver , LSF_BSUB_CMD , "Xbsub"); - test_option( driver , LSF_BJOBS_CMD , "Xbsub"); - test_option( driver , LSF_BKILL_CMD , "Xbsub"); - test_option( driver , LSF_RSH_CMD , "RSH"); - test_option( driver , LSF_LOGIN_SHELL , "shell"); - test_option( driver , LSF_BSUB_CMD , "bsub"); - printf("Options OK\n"); - - { - - lsf_submit_method_enum submit_NULL; - lsb_type * lsb = lsb_alloc(); - if (lsb_ready(lsb)) - submit_NULL = LSF_SUBMIT_INTERNAL; - else - submit_NULL = LSF_SUBMIT_LOCAL_SHELL; - - - test_server( driver , NULL , submit_NULL ); - test_server( driver , "LoCaL" , LSF_SUBMIT_LOCAL_SHELL ); - test_server( driver , "LOCAL" , LSF_SUBMIT_LOCAL_SHELL ); - test_server( driver , "XLOCAL" , LSF_SUBMIT_REMOTE_SHELL ); - test_server( driver , NULL , submit_NULL ); - test_server( driver , "NULL" , submit_NULL ); - test_server( driver , "be-grid01" , LSF_SUBMIT_REMOTE_SHELL ); - printf("Servers OK\n"); - - lsb_free( lsb ); - } - test_status( JOB_STAT_PEND , JOB_QUEUE_PENDING ); - test_status( JOB_STAT_PSUSP , JOB_QUEUE_RUNNING ); - test_status( JOB_STAT_USUSP , JOB_QUEUE_RUNNING ); - test_status( JOB_STAT_SSUSP , JOB_QUEUE_RUNNING ); - test_status( JOB_STAT_RUN , JOB_QUEUE_RUNNING ); - test_status( JOB_STAT_NULL , JOB_QUEUE_NOT_ACTIVE ); - test_status( JOB_STAT_DONE , JOB_QUEUE_DONE ); - test_status( JOB_STAT_EXIT , JOB_QUEUE_EXIT ); - test_status( JOB_STAT_UNKWN , JOB_QUEUE_EXIT ); - test_status( 192 , JOB_QUEUE_DONE ); - printf("Status OK \n"); - - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_node_test.c b/ThirdParty/Ert/libjob_queue/tests/job_node_test.c deleted file mode 100644 index 02ed8026e8..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_node_test.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'job_node_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include "ert/util/build_config.h" - -#include -#include -#include - - -void test_create() { - job_queue_node_type * node = job_queue_node_alloc_simple("name" , "/tmp" , "/bin/ls" , 0 , NULL); - test_assert_true( job_queue_node_is_instance( node )); - job_queue_node_free( node ); -} - - - -void call_get_queue_index( void * arg ) { - job_queue_node_type * node = job_queue_node_safe_cast( arg ); - job_queue_node_get_queue_index( node ); -} - - - - -void test_queue_index() { - job_queue_node_type * node = job_queue_node_alloc_simple( "name" , "/tmp" , "/bin/ls" , 0 , NULL ); - test_assert_util_abort("job_queue_node_get_queue_index" , call_get_queue_index , node ); -} - - -void test_path_does_not_exist() { - job_queue_node_type * node = job_queue_node_alloc_simple( "name" , "does-not-exist" , "/bin/ls" , 0 , NULL); - test_assert_NULL( node ); -} - - -int main( int argc , char ** argv) { - util_install_signals(); - test_create(); - test_queue_index(); - test_path_does_not_exist(); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_program.c b/ThirdParty/Ert/libjob_queue/tests/job_program.c deleted file mode 100644 index d57e12a030..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_program.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_program.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - - -int main( int argc , char ** argv) { - int max_count = 100; - int count = 0; - while (true) { - sleep(1); - count++; - printf("%d/%d \n",count , max_count); - if (count == max_count) - break; - } - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_program_output.c b/ThirdParty/Ert/libjob_queue/tests/job_program_output.c deleted file mode 100644 index 28cc0ce62a..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_program_output.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_program.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -int main( int argc , char ** argv) { - int sleep_time; - util_sscanf_int(argv[2], &sleep_time); - sleep(sleep_time); - - char * filename = util_alloc_filename(argv[1], "OK", "status"); - - if (util_file_exists(argv[1])) { - FILE * file = util_fopen(filename, "w"); - fprintf(file, "All good"); - util_fclose(file); - exit(0); - } else - exit(1); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_queue_driver_test.c b/ThirdParty/Ert/libjob_queue/tests/job_queue_driver_test.c deleted file mode 100644 index 6f880f9e51..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_queue_driver_test.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_queue_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include - -void job_queue_set_driver_(job_driver_type driver_type) { - job_queue_type * queue = job_queue_alloc(10, "OK", "STATUS", "ERROR"); - queue_driver_type * driver = queue_driver_alloc(driver_type); - test_assert_false(job_queue_has_driver(queue)); - - job_queue_set_driver(queue, driver); - test_assert_true(job_queue_has_driver(queue)); - - job_queue_free(queue); - queue_driver_free(driver); - - -} - -void set_option_max_running_max_running_value_set() { - queue_driver_type * driver_torque = queue_driver_alloc(TORQUE_DRIVER); - test_assert_true(queue_driver_set_option(driver_torque, MAX_RUNNING, "42")); - test_assert_string_equal("42", queue_driver_get_option(driver_torque, MAX_RUNNING)); - queue_driver_free(driver_torque); - - - queue_driver_type * driver_lsf = queue_driver_alloc(LSF_DRIVER); - test_assert_true(queue_driver_set_option(driver_lsf, MAX_RUNNING, "72")); - test_assert_string_equal("72", queue_driver_get_option(driver_lsf, MAX_RUNNING)); - queue_driver_free(driver_lsf); -} - -void set_option_max_running_max_running_option_set() { - queue_driver_type * driver_torque = queue_driver_alloc(TORQUE_DRIVER); - test_assert_true(queue_driver_set_option(driver_torque, MAX_RUNNING, "42")); - test_assert_string_equal("42", queue_driver_get_option(driver_torque, MAX_RUNNING)); - queue_driver_free(driver_torque); - -} - -void set_option_invalid_option_returns_false() { - queue_driver_type * driver_torque = queue_driver_alloc(TORQUE_DRIVER); - test_assert_false(queue_driver_set_option(driver_torque, "MAKS_RUNNING", "42")); - queue_driver_free(driver_torque); -} - -void set_option_invalid_value_returns_false() { - queue_driver_type * driver_torque = queue_driver_alloc(TORQUE_DRIVER); - test_assert_false(queue_driver_set_option(driver_torque, "MAX_RUNNING", "2a")); - queue_driver_free(driver_torque); -} - -void set_option_valid_on_specific_driver_returns_true() { - queue_driver_type * driver_torque = queue_driver_alloc(TORQUE_DRIVER); - test_assert_true(queue_driver_set_option(driver_torque, TORQUE_NUM_CPUS_PER_NODE, "33")); - test_assert_string_equal("33", queue_driver_get_option(driver_torque, TORQUE_NUM_CPUS_PER_NODE)); - queue_driver_free(driver_torque); -} - -void get_driver_option_lists() { - //Torque driver option list - { - queue_driver_type * driver_torque = queue_driver_alloc(TORQUE_DRIVER); - stringlist_type * option_list = stringlist_alloc_new(); - queue_driver_init_option_list(driver_torque, option_list); - - test_assert_true(stringlist_contains(option_list, MAX_RUNNING)); - test_assert_true(stringlist_contains(option_list, TORQUE_QSUB_CMD)); - test_assert_true(stringlist_contains(option_list, TORQUE_QSTAT_CMD)); - test_assert_true(stringlist_contains(option_list, TORQUE_QDEL_CMD)); - test_assert_true(stringlist_contains(option_list, TORQUE_QUEUE)); - test_assert_true(stringlist_contains(option_list, TORQUE_NUM_CPUS_PER_NODE)); - test_assert_true(stringlist_contains(option_list, TORQUE_NUM_NODES)); - test_assert_true(stringlist_contains(option_list, TORQUE_KEEP_QSUB_OUTPUT)); - test_assert_true(stringlist_contains(option_list, TORQUE_CLUSTER_LABEL)); - - stringlist_free(option_list); - queue_driver_free(driver_torque); - } - - //Local driver option list (only general queue_driver options) - { - queue_driver_type * driver_local = queue_driver_alloc(LOCAL_DRIVER); - stringlist_type * option_list = stringlist_alloc_new(); - queue_driver_init_option_list(driver_local, option_list); - - test_assert_true(stringlist_contains(option_list, MAX_RUNNING)); - - stringlist_free(option_list); - queue_driver_free(driver_local); - } - - //Lsf driver option list - { - queue_driver_type * driver_lsf = queue_driver_alloc(LSF_DRIVER); - stringlist_type * option_list = stringlist_alloc_new(); - queue_driver_init_option_list(driver_lsf, option_list); - - test_assert_true(stringlist_contains(option_list, MAX_RUNNING)); - test_assert_true(stringlist_contains(option_list, LSF_QUEUE)); - test_assert_true(stringlist_contains(option_list, LSF_RESOURCE)); - test_assert_true(stringlist_contains(option_list, LSF_SERVER)); - test_assert_true(stringlist_contains(option_list, LSF_RSH_CMD)); - test_assert_true(stringlist_contains(option_list, LSF_LOGIN_SHELL)); - test_assert_true(stringlist_contains(option_list, LSF_BSUB_CMD)); - test_assert_true(stringlist_contains(option_list, LSF_BJOBS_CMD)); - test_assert_true(stringlist_contains(option_list, LSF_BKILL_CMD)); - - stringlist_free(option_list); - queue_driver_free(driver_lsf); - } - - //Rsh driver option list - { - queue_driver_type * driver_rsh = queue_driver_alloc(RSH_DRIVER); - stringlist_type * option_list = stringlist_alloc_new(); - queue_driver_init_option_list(driver_rsh, option_list); - - test_assert_true(stringlist_contains(option_list, MAX_RUNNING)); - test_assert_true(stringlist_contains(option_list, RSH_HOST)); - test_assert_true(stringlist_contains(option_list, RSH_HOSTLIST)); - test_assert_true(stringlist_contains(option_list, RSH_CMD)); - test_assert_true(stringlist_contains(option_list, RSH_CLEAR_HOSTLIST)); - - stringlist_free(option_list); - queue_driver_free(driver_rsh); - } -} - -int main(int argc, char ** argv) { - job_queue_set_driver_(LSF_DRIVER); - job_queue_set_driver_(LOCAL_DRIVER); - job_queue_set_driver_(RSH_DRIVER); - job_queue_set_driver_(TORQUE_DRIVER); - - set_option_max_running_max_running_value_set(); - set_option_max_running_max_running_option_set(); - set_option_invalid_option_returns_false(); - set_option_invalid_value_returns_false(); - - set_option_valid_on_specific_driver_returns_true(); - get_driver_option_lists(); - - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_queue_manager.c b/ThirdParty/Ert/libjob_queue/tests/job_queue_manager.c deleted file mode 100644 index 98419158c3..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_queue_manager.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_queue_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ -#include -#include - -#include - -#include -#include - - - - -void test_create() { - job_queue_type * job_queue = job_queue_alloc( 100 , "OK" , "STATUS", "ERROR"); - job_queue_manager_type * manager = job_queue_manager_alloc( job_queue ); - - test_assert_true( job_queue_manager_is_instance( manager )); - - job_queue_manager_free( manager ); - job_queue_free( job_queue ); -} - - - - - - -int main( int argc , char ** argv) { - test_create(); - exit(0); -} - diff --git a/ThirdParty/Ert/libjob_queue/tests/job_queue_stress_task.c b/ThirdParty/Ert/libjob_queue/tests/job_queue_stress_task.c deleted file mode 100644 index b37d97c491..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_queue_stress_task.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'job_queue_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include - - -/* - This is a small test job used by the job_queue_stress_test. The job - does the following: - - 0. Chadir to runpath - 1. Create the file @runfile. - 2. Wait with usleep( @usleep_time ). - 3. Remove the @runfile. - 4. Create new file @OK_file - 5. exit. -*/ - -int main(int argc, char ** argv) { - const char * runpath = argv[1]; - const char * runfile = argv[2]; - const char * OK_file = argv[3]; - - int usleep_time; - - util_chdir( runpath ); - util_sscanf_int( argv[4] , &usleep_time ); - { - FILE * stream = util_fopen( runfile , "w"); - fprintf(stream , "Running ... \n"); - fclose( stream ); - } - usleep( usleep_time ); - util_unlink_existing(runfile); - { - FILE * stream = util_fopen( OK_file , "w"); - fprintf(stream , "OK ... \n"); - fclose( stream ); - } - return 0; -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_queue_stress_test.c b/ThirdParty/Ert/libjob_queue/tests/job_queue_stress_test.c deleted file mode 100644 index e1a4927def..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_queue_stress_test.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'job_queue_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#define JOB_TYPE_ID 77539 -typedef struct { - UTIL_TYPE_ID_DECLARATION; - char * run_path; - bool callback_run; - int queue_index; - int submit_usleep; - int callback_usleep; - int run_usleep; - int argc; - char ** argv; - const char * cmd; -} job_type; - - - -UTIL_SAFE_CAST_FUNCTION( job , JOB_TYPE_ID ) - -job_type * alloc_job( rng_type * rng , const char * cmd) { - const int second = 1000000; - const int submit_min = 0; - const int submit_max = 10 * second; - - const int callback_min = 0.5 * second; - const int callback_max = 2 * second; - - const int run_min = 2 * second; - const int run_max = 10 * second; - - job_type * job = util_malloc( sizeof * job ); - UTIL_TYPE_ID_INIT( job , JOB_TYPE_ID ) - job->callback_run = false; - job->queue_index = -1; - job->submit_usleep = submit_min + rng_get_int( rng , (submit_max - submit_min )); - job->callback_usleep = callback_min + rng_get_int( rng , (callback_max - callback_min )); - job->run_usleep = run_min + rng_get_int( rng , (run_max - run_min )); - job->run_path = util_alloc_sprintf("%08d", rng_get_int(rng , 100000000)); - job->cmd = cmd; - job->argc = 4; - - job->argv = util_malloc( 4 * sizeof * job->argv ); - job->argv[0] = job->run_path; - job->argv[1] = "RUNNING"; - job->argv[2] = "OK"; - job->argv[3] = util_alloc_sprintf("%d", job->run_usleep); - - util_make_path( job->run_path ); - return job; -} - - -job_type ** alloc_jobs( rng_type * rng , int num_jobs , const char * cmd) { - job_type ** jobs = util_malloc( num_jobs * sizeof * jobs ); - for (int i=0; i < num_jobs; i++) { - job_type * job = alloc_job( rng , cmd); - job_safe_cast( job ); - jobs[i] = job; - } - return jobs; -} - - - -bool callback( void * arg ) { - job_type * job = job_safe_cast( arg ); - usleep( job->callback_usleep ); - job->callback_run = true; - return true; -} - - -void * submit_job__( void * arg ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - job_type * job = job_safe_cast( arg_pack_iget_ptr( arg_pack , 0 ) ); - job_queue_type * queue = arg_pack_iget_ptr( arg_pack , 1 ); - job->queue_index = job_queue_add_job( queue , job->cmd , callback , NULL , NULL , job , 1 , job->run_path , job->run_path , job->argc , (const char **) job->argv ); - - if (job->queue_index >= 0) - usleep( job->submit_usleep ); - return NULL; -} - - -void submit_jobs( job_queue_type * queue , int num_jobs , job_type ** jobs , thread_pool_type * tp) { - for (int i=0; i < num_jobs; i++) { - job_type * job = jobs[i]; - arg_pack_type * arg = arg_pack_alloc(); - arg_pack_append_ptr( arg , job ); - arg_pack_append_ptr( arg , queue ); - thread_pool_add_job(tp , submit_job__ , arg ); - } -} - - -void check_jobs( int num_jobs , job_type ** jobs ) { - for (int i=0; i < num_jobs; i++) { - job_type * job = jobs[i]; - if (!job->callback_run) - fprintf(stderr,"The callback has not been registered on job:%d/%d \n",i,job->queue_index); - test_assert_true( job->callback_run ); - } -} - - -void * global_status( void * arg ) { - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - job_queue_type * job_queue = job_queue_safe_cast( arg_pack_iget_ptr( arg_pack , 0 )); - bool user_exit = arg_pack_iget_bool( arg_pack , 1 ); - bool exit_called = false; - int counter = 0; - int signature = -1; - while (true) { - util_usleep(100000); - - if (job_queue_get_num_complete(job_queue) == job_queue_get_active_size(job_queue)) - break; - - if ((counter % 10) == 0) - printf("Waiting:%03d Running:%03d Callback:%03d Complete:%03d \n", - job_queue_get_num_waiting(job_queue) , - job_queue_get_num_running(job_queue), - job_queue_get_num_callback( job_queue ) , - job_queue_get_num_complete(job_queue)); - - counter++; - - if (user_exit && (job_queue_get_num_complete( job_queue ) >= job_queue_get_active_size(job_queue)/2)) { - - if (job_queue_accept_jobs( job_queue )) { - exit_called = true; - job_queue_start_user_exit( job_queue ); - } - } - - if (exit_called) { - int w = job_queue_get_num_waiting(job_queue); - int r = job_queue_get_num_running(job_queue); - int c = job_queue_get_num_callback( job_queue ); - int f = job_queue_get_num_complete(job_queue); - int new = (w + r*256 + c *256*256 + f *256*256*256); - - if (new == signature) - break; - else - signature = new; - } - } - arg_pack_free( arg_pack ); - return NULL; -} - - -void * status_job__( void * arg ) { - const int usleep_time = 10000; - arg_pack_type * arg_pack = arg_pack_safe_cast( arg ); - job_type * job = job_safe_cast( arg_pack_iget_ptr( arg_pack , 0 ) ); - job_queue_type * queue = arg_pack_iget_ptr( arg_pack , 1 ); - bool user_exit = arg_pack_iget_bool( arg_pack , 2 ); - char * run_file = util_alloc_filename( job->run_path , "RUNNING" , NULL); - - while (true) { - if (job->queue_index >= 0) { - job_status_type status; - if (util_is_file(run_file)) { - status = job_queue_iget_job_status(queue, job->queue_index); - if (util_is_file(run_file)) { - bool status_true = (status == JOB_QUEUE_RUNNING) || (status == JOB_QUEUE_SUBMITTED || (status == JOB_QUEUE_RUNNING_CALLBACK) || (status == JOB_QUEUE_DONE)); - if (!status_true) { - if (user_exit) - status_true = (status == JOB_QUEUE_DO_KILL) || (status == JOB_QUEUE_IS_KILLED || (status == JOB_QUEUE_RUNNING_CALLBACK)); - } - if (!status_true) - fprintf(stderr," Invalid status:%d for job:%d \n",status , job->queue_index ); - test_assert_true( status_true ); - } - } - status = job_queue_iget_job_status(queue, job->queue_index); - if ((status == JOB_QUEUE_SUCCESS) || (status == JOB_QUEUE_IS_KILLED)) - break; - } else { - if (!job_queue_accept_jobs(queue)) - break; - } - - usleep( usleep_time ); - } - - arg_pack_free( arg_pack ); - free( run_file ); - return NULL; -} - - - -void status_jobs( job_queue_type * queue , int num_jobs , bool user_exit , job_type ** jobs , thread_pool_type * tp) { - for (int i=0; i < num_jobs; i++) { - job_type * job = jobs[i]; - arg_pack_type * arg = arg_pack_alloc(); - arg_pack_append_ptr( arg , job ); - arg_pack_append_ptr( arg , queue ); - arg_pack_append_bool( arg , user_exit ); - thread_pool_add_job(tp , status_job__ , arg ); - } - { - arg_pack_type * arg_pack = arg_pack_alloc( ); - - arg_pack_append_ptr( arg_pack , queue ); - arg_pack_append_bool( arg_pack , user_exit ); - thread_pool_add_job( tp , global_status , arg_pack ); - } -} - - -/* - The purpose of this test is to stress the queue system with a - massively multithreaded workload. The test will submit jobs, let - them run and run a callback. The various elements are pimped with - usleep() calls to ensure that all of these actions: - - 1. Submit - 2. Run callback - 3. Check status - - Are performed concurrently. The total runtime of the test should be - ~ 120 seconds. -*/ - - -int main(int argc , char ** argv) { - const int queue_timeout = 180; - const int submit_timeout = 180; - const int status_timeout = 180; - const int number_of_jobs = 50; - const int submit_threads = number_of_jobs / 10 ; - const int status_threads = number_of_jobs + 1; - const char * job = util_alloc_abs_path(argv[1]); - rng_type * rng = rng_alloc( MZRAN , INIT_CLOCK ); - bool user_exit; - test_work_area_type * work_area = test_work_area_alloc("job_queue"); - job_type **jobs = alloc_jobs( rng , number_of_jobs , job); - - job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK", "STATUS", "ERROR"); - queue_driver_type * driver = queue_driver_alloc_local(); - job_queue_manager_type * queue_manager = job_queue_manager_alloc( queue ); - - util_install_signals(); - util_sscanf_bool(argv[2] , &user_exit); - job_queue_set_driver(queue, driver); - job_queue_manager_start_queue(queue_manager, 0, false , true); - - { - thread_pool_type * status_pool = thread_pool_alloc( status_threads , true ); - thread_pool_type * submit_pool = thread_pool_alloc( submit_threads , true ); - - submit_jobs( queue , number_of_jobs , jobs , submit_pool ); - status_jobs( queue , number_of_jobs , user_exit , jobs , status_pool ); - - if (!thread_pool_try_join( submit_pool , submit_timeout )) - util_exit("Joining submit pool failed \n"); - thread_pool_free( submit_pool ); - job_queue_submit_complete(queue); - if (!thread_pool_try_join( status_pool , status_timeout)) - util_exit("Joining status pool failed \n"); - thread_pool_free( status_pool ); - } - - if (!job_queue_manager_try_wait(queue_manager , queue_timeout)) - util_exit("job_queue never completed \n"); - - job_queue_manager_free(queue_manager); - job_queue_free(queue); - if (!user_exit) - check_jobs( number_of_jobs , jobs ); - - queue_driver_free(driver); - test_work_area_free(work_area); - rng_free( rng ); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_queue_timeout_test.c b/ThirdParty/Ert/libjob_queue/tests/job_queue_timeout_test.c deleted file mode 100644 index 041bf9314d..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_queue_timeout_test.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - Copyright (C) 2016 Statoil ASA, Norway. - - This file is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -#define JOB_TYPE_ID 77539 -typedef struct -{ - UTIL_TYPE_ID_DECLARATION; - char * run_path; - bool callback_run; - int queue_index; - int submit_usleep; - int callback_usleep; - int run_usleep; - int argc; - char ** argv; - const char * cmd; -} job_type; - -UTIL_SAFE_CAST_FUNCTION(job, JOB_TYPE_ID) - -job_type * alloc_job(int ind, const char * cmd) { - job_type * job = util_malloc(sizeof *job); - UTIL_TYPE_ID_INIT(job, JOB_TYPE_ID) - job->callback_run = false; - job->queue_index = -1; - job->submit_usleep = 0; - job->callback_usleep = 0; - job->run_usleep = 2 * 1000*1000; // 4 sec - job->run_path = util_alloc_sprintf("timeout_test_%d", ind); - job->cmd = cmd; - job->argc = 4; - - job->argv = util_malloc(4 * sizeof *job->argv); - job->argv[0] = job->run_path; - job->argv[1] = "RUNNING"; - job->argv[2] = "OK"; - job->argv[3] = util_alloc_sprintf("%d", job->run_usleep); - - util_make_path(job->run_path); - return job; -} - -job_type ** alloc_jobs(int num_jobs, const char * cmd) { - job_type ** jobs = util_malloc(num_jobs * sizeof *jobs); - for (int i = 0; i < num_jobs; i++) { - job_type * job = alloc_job(i, cmd); - job_safe_cast(job); - jobs[i] = job; - } - return jobs; -} - - -void submit_jobs(job_queue_type * queue, int num_jobs, job_type ** jobs) { - for (int i = 0; i < num_jobs; i++) { - job_type * job = jobs[i]; - - job->queue_index = job_queue_add_job(queue, job->cmd, NULL, NULL, NULL, job, 1, job->run_path, job->run_path, - job->argc, (const char **) job->argv); - } -} - -void check_jobs(int num_jobs, job_type ** jobs) { - for (int i = 0; i < num_jobs; i++) { - job_type * job = jobs[i]; - if (!job->callback_run) - fprintf(stderr, "The callback has not been registered on job:%d/%d \n", i, job->queue_index); - test_assert_true(job->callback_run); - } -} - -int main(int argc, char ** argv) { - setbuf(stdout, NULL); - - const int number_of_jobs = 1; - util_alloc_abs_path(argv[1]); - - const int running_timeout = 0; - const int sec = 1000*1000; - - test_work_area_type * work_area = test_work_area_alloc("job_timeout"); - test_work_area_set_store(work_area, true); - - job_type **jobs = alloc_jobs(number_of_jobs, argv[1]); - - job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK", "DOES_NOT_EXIST", "ERROR"); - queue_driver_type * driver = queue_driver_alloc_local(); - job_queue_manager_type * queue_manager = job_queue_manager_alloc(queue); - - util_install_signals(); - job_queue_set_driver(queue, driver); - job_queue_manager_start_queue(queue_manager, number_of_jobs, false, true); - - { - submit_jobs(queue, number_of_jobs, jobs); - - if (job_queue_get_active_size(queue) > 0) { - job_queue_iset_max_confirm_wait_time(queue, 0, running_timeout); // job 0 - } else { - util_exit("Job failed to be queued!\n"); - } - - usleep(1 * sec); // 1.0 sec - int job_status = job_queue_iget_job_status(queue, 0); - - if (job_status != JOB_QUEUE_IS_KILLED) { - util_exit("Job should have been killed, had status %d != %d\n", job_status, JOB_QUEUE_IS_KILLED); - } - } - if (!job_queue_manager_try_wait(queue_manager, 5 * sec)) - util_exit("job_queue never completed \n"); - job_queue_manager_free(queue_manager); - job_queue_free(queue); - queue_driver_free(driver); - test_work_area_free(work_area); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_status_test.c b/ThirdParty/Ert/libjob_queue/tests/job_status_test.c deleted file mode 100644 index 2dca4b664d..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_status_test.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - Copyright (C) 2015 Statoil ASA, Norway. - - The file 'job_status_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include "ert/util/build_config.h" - -#include -#include -#include -#include - - -void call_get_status( void * arg ) { - job_queue_status_type * job_status = job_queue_status_safe_cast( arg ); - job_queue_status_get_count( job_status , JOB_QUEUE_DONE + JOB_QUEUE_DO_KILL); -} - - - -void test_create() { - job_queue_status_type * status = job_queue_status_alloc(); - test_assert_true( job_queue_status_is_instance( status )); - test_assert_int_equal( job_queue_status_get_count( status , JOB_QUEUE_DONE ) , 0 ); - test_assert_util_abort( "STATUS_INDEX" , call_get_status , status ); - job_queue_status_free( status ); -} - - -void * add_sim( void * arg ) { - job_queue_status_type * job_status = job_queue_status_safe_cast( arg ); - job_queue_status_inc( job_status , JOB_QUEUE_WAITING ); - return NULL; -} - - -void * user_exit( void * arg ) { - job_queue_status_type * job_status = job_queue_status_safe_cast( arg ); - job_queue_status_transition( job_status , JOB_QUEUE_WAITING , JOB_QUEUE_DO_KILL); - return NULL; -} - - -void * user_done( void * arg ) { - job_queue_status_type * job_status = job_queue_status_safe_cast( arg ); - job_queue_status_transition( job_status , JOB_QUEUE_WAITING , JOB_QUEUE_DONE); - return NULL; -} - - - -void test_update() { - int N = 15000; - pthread_t * thread_list = util_malloc( 2*N*sizeof * thread_list); - int num_exit_threads = 0; - int num_done_threads = 0; - job_queue_status_type * status = job_queue_status_alloc(); - - test_assert_int_equal( 0 , job_queue_status_get_total_count( status )); - for (int i=0; i < 2*N; i++) - add_sim( status ); - test_assert_int_equal( 2*N , job_queue_status_get_count( status , JOB_QUEUE_WAITING )); - - { - int i = 0; - while (true) { - int thread_status; - - if ((i % 2) == 0) { - thread_status = pthread_create( &thread_list[i] , NULL , user_exit , status ); - if (thread_status == 0) - num_exit_threads++; - else - break; - } else { - thread_status = pthread_create( &thread_list[i] , NULL , user_done , status ); - if (thread_status == 0) - num_done_threads++; - else - break; - } - - i++; - if (i == N) - break; - } - } - if ((num_done_threads + num_exit_threads) == 0) { - fprintf(stderr, "Hmmm - not a single thread created - very suspicious \n"); - exit(1); - } - - for (int i=0; i < num_done_threads + num_exit_threads; i++) - pthread_join( thread_list[i] , NULL ); - - test_assert_int_equal( 2*N - num_done_threads - num_exit_threads , job_queue_status_get_count( status , JOB_QUEUE_WAITING )); - test_assert_int_equal( num_exit_threads , job_queue_status_get_count( status , JOB_QUEUE_DO_KILL )); - test_assert_int_equal( num_done_threads , job_queue_status_get_count( status , JOB_QUEUE_DONE )); - - test_assert_int_equal( 2*N , job_queue_status_get_total_count( status )); - job_queue_status_free( status ); -} - - -int main( int argc , char ** argv) { - util_install_signals(); - test_create(); - test_update(); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_torque_submit_test.c b/ThirdParty/Ert/libjob_queue/tests/job_torque_submit_test.c deleted file mode 100644 index d4854ab611..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_torque_submit_test.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'job_torque_submit_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ -#include -#include -#include - -#include -#include -#include - -#include - -void assert_status( torque_driver_type * driver, torque_job_type * job, int status_mask) { - int torque_status = torque_driver_get_job_status(driver, job); - if ((torque_status & status_mask) == 0) - test_exit("Incorrect status:%d - expected overlap with: %d\n" , torque_status , status_mask); -} - - - -void test_submit(torque_driver_type * driver, const char * cmd) { - char * run_path = util_alloc_cwd(); - torque_job_type * job = torque_driver_submit_job(driver, cmd, 1, run_path, "TEST-TORQUE-SUBMIT", 0, NULL); - - if (job != NULL) { - assert_status( driver , job, JOB_QUEUE_RUNNING + JOB_QUEUE_PENDING); - torque_driver_kill_job(driver, job); - printf("Waiting 2 seconds"); - for (int i = 0; i < 2; i++) { - printf("."); - fflush(stdout); - sleep(1); - } - printf("\n"); - - int torque_status = torque_driver_get_job_status(driver, job); - if (torque_status != JOB_QUEUE_EXIT && torque_status != JOB_QUEUE_DONE) { - exit(1); - test_exit("After kill of job, the status is %d, it should have been JOB_QUEUE_EXIT, which is %d\n", torque_status, JOB_QUEUE_EXIT); - } - } else { - exit(1); - test_exit("Function %s returned null-pointer to job, terminating test.", "torque_driver_submit_job"); - } - - free(run_path); - torque_driver_free_job(job); -} - -void test_submit_nocommand(torque_driver_type * driver) { - test_submit(driver, NULL); -} - - - - -void test_submit_failed_qstat(torque_driver_type * driver, const char * cmd) { - char * run_path = util_alloc_cwd(); - torque_job_type * job = torque_driver_submit_job(driver, cmd, 1, run_path, "TEST-TORQUE-SUBMIT", 0, NULL); - - { - test_work_area_type * work_area = test_work_area_alloc("torque-failed-qstat"); - test_work_area_copy_file( work_area , torque_driver_get_option( driver , TORQUE_QSTAT_CMD )); - assert_status( driver , job , JOB_QUEUE_RUNNING + JOB_QUEUE_PENDING); - - { - char * qstat_cmd = util_alloc_abs_path( "qstat.local" ); - FILE * stream = util_fopen( qstat_cmd , "w"); - fprintf(stream , "#!/bin/sh\n"); - fprintf(stream , "echo XYZ - Error\n"); - fclose( stream ); - util_addmode_if_owner(qstat_cmd, S_IXUSR ); - torque_driver_set_option(driver, TORQUE_QSTAT_CMD, qstat_cmd); - free( qstat_cmd ); - } - - assert_status( driver , job , JOB_QUEUE_STATUS_FAILURE ); - test_work_area_free( work_area ); - } - - torque_driver_free_job(job); - free(run_path); -} - - - -int main(int argc, char ** argv) { - torque_driver_type * driver = torque_driver_alloc(); - if (argc == 1) { - test_submit_nocommand(driver); - } else if (argc == 2) { - test_submit(driver, argv[1]); - test_submit_failed_qstat( driver , argv[1] ); - } else { - printf("Only accepts zero or one arguments (the job script to run)\n"); - exit(1); - } - printf("Submit, status and kill OK\n"); - torque_driver_free(driver); - - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_torque_test.c b/ThirdParty/Ert/libjob_queue/tests/job_torque_test.c deleted file mode 100644 index 11f27602b3..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_torque_test.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_lsf_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. - */ -#include -#include -#include - -#include -#include -#include -#include - -void test_option(torque_driver_type * driver, const char * option, const char * value) { - test_assert_true(torque_driver_set_option(driver, option, value)); - test_assert_string_equal(torque_driver_get_option(driver, option), value); -} - -void setoption_setalloptions_optionsset() { - torque_driver_type * driver = torque_driver_alloc(); - - test_option(driver, TORQUE_QSUB_CMD, "XYZaaa"); - test_option(driver, TORQUE_QSTAT_CMD, "xyZfff"); - test_option(driver, TORQUE_QDEL_CMD, "ZZyfff"); - test_option(driver, TORQUE_QUEUE, "superhigh"); - test_option(driver, TORQUE_NUM_CPUS_PER_NODE, "42"); - test_option(driver, TORQUE_NUM_NODES, "36"); - test_option(driver, TORQUE_KEEP_QSUB_OUTPUT, "1"); - test_option(driver, TORQUE_KEEP_QSUB_OUTPUT, "0"); - test_option(driver, TORQUE_CLUSTER_LABEL, "thecluster"); - test_option(driver, TORQUE_JOB_PREFIX_KEY, "coolJob"); - - test_assert_int_equal( 0 , torque_driver_get_submit_sleep(driver)); - test_assert_NULL( torque_driver_get_debug_stream(driver) ); - - test_assert_true( torque_driver_set_option( driver , TORQUE_SUBMIT_SLEEP , "0.25")); - test_assert_int_equal( 250000 , torque_driver_get_submit_sleep(driver)); - - test_assert_true( torque_driver_set_option( driver , TORQUE_DEBUG_OUTPUT , "/tmp/torqueue_debug.txt")); - test_assert_not_NULL( torque_driver_get_debug_stream(driver) ); - - printf("Options OK\n"); - torque_driver_free(driver); -} - -void setoption_set_typed_options_wrong_format_returns_false() { - torque_driver_type * driver = torque_driver_alloc(); - test_assert_false(torque_driver_set_option(driver, TORQUE_NUM_CPUS_PER_NODE, "42.2")); - test_assert_false(torque_driver_set_option(driver, TORQUE_NUM_CPUS_PER_NODE, "fire")); - test_assert_false(torque_driver_set_option(driver, TORQUE_NUM_NODES, "42.2")); - test_assert_false(torque_driver_set_option(driver, TORQUE_NUM_NODES, "fire")); - test_assert_true(torque_driver_set_option(driver, TORQUE_KEEP_QSUB_OUTPUT, "true")); - test_assert_true(torque_driver_set_option(driver, TORQUE_KEEP_QSUB_OUTPUT, "1")); - test_assert_false(torque_driver_set_option(driver, TORQUE_KEEP_QSUB_OUTPUT, "ja")); - test_assert_false(torque_driver_set_option(driver, TORQUE_KEEP_QSUB_OUTPUT, "22")); - test_assert_false(torque_driver_set_option(driver, TORQUE_KEEP_QSUB_OUTPUT, "1.1")); - test_assert_false(torque_driver_set_option(driver, TORQUE_SUBMIT_SLEEP, "X45")); -} - -void getoption_nooptionsset_defaultoptionsreturned() { - torque_driver_type * driver = torque_driver_alloc(); - test_assert_string_equal(torque_driver_get_option(driver, TORQUE_QSUB_CMD), TORQUE_DEFAULT_QSUB_CMD); - test_assert_string_equal(torque_driver_get_option(driver, TORQUE_QSTAT_CMD), TORQUE_DEFAULT_QSTAT_CMD); - test_assert_string_equal(torque_driver_get_option(driver, TORQUE_QDEL_CMD), TORQUE_DEFAULT_QDEL_CMD); - test_assert_string_equal(torque_driver_get_option(driver, TORQUE_KEEP_QSUB_OUTPUT), "0"); - test_assert_string_equal(torque_driver_get_option(driver, TORQUE_NUM_CPUS_PER_NODE), "1"); - test_assert_string_equal(torque_driver_get_option(driver, TORQUE_NUM_NODES), "1"); - test_assert_string_equal(torque_driver_get_option(driver, TORQUE_CLUSTER_LABEL), NULL ); - test_assert_string_equal(torque_driver_get_option(driver, TORQUE_JOB_PREFIX_KEY), NULL); - - printf("Default options OK\n"); - torque_driver_free(driver); -} - -void create_submit_script_script_according_to_input() { - test_work_area_type * work_area = test_work_area_alloc("job_torque_test" ); - const char * script_filename = "qsub_script.sh"; - - { - char ** args = util_calloc(2, sizeof * args); - args[0] = "/tmp/jaja/"; - args[1] = "number2arg"; - torque_job_create_submit_script(script_filename, "job_program.py", 2, (const char **) args); - free( args ); - } - - { - FILE* file_stream = util_fopen(script_filename, "r"); - bool at_eof = false; - - char * line = util_fscanf_alloc_line(file_stream, &at_eof); - test_assert_string_equal("#!/bin/sh", line); - free(line); - - line = util_fscanf_alloc_line(file_stream, &at_eof); - test_assert_string_equal("job_program.py /tmp/jaja/ number2arg", line); - free(line); - - line = util_fscanf_alloc_line(file_stream, &at_eof); - free(line); - test_assert_true(at_eof); - - fclose(file_stream); - } - test_work_area_free( work_area ); -} - - -int main(int argc, char ** argv) { - getoption_nooptionsset_defaultoptionsreturned(); - setoption_setalloptions_optionsset(); - - setoption_set_typed_options_wrong_format_returns_false(); - create_submit_script_script_according_to_input(); - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/job_workflow_test.c b/ThirdParty/Ert/libjob_queue/tests/job_workflow_test.c deleted file mode 100644 index 22c8481f43..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/job_workflow_test.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - Copyright (C) 2012 Statoil ASA, Norway. - - The file 'job_workflow_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include - - -void create_workflow( const char * workflow_file , const char * tmp_file , int value) { - FILE * stream = util_fopen( workflow_file , "w"); - fprintf(stream , "CREATE_FILE %s %d\n" , tmp_file , value); - fprintf(stream , "READ_FILE %s\n" , tmp_file ); - fclose( stream ); - - printf("Have created:%s \n",workflow_file ); -} - - -void create_error_workflow( const char * workflow_file , const char * tmp_file , int value) { - FILE * stream = util_fopen( workflow_file , "w"); - fprintf(stream , "CREATE_FILE %s %d\n" , tmp_file , value); - fprintf(stream , "XREAD_FILE %s\n" , tmp_file ); - fclose( stream ); - - printf("Have created:%s \n",workflow_file ); -} - - -void * read_file( void * self , const stringlist_type * args) { - printf("Running read_file \n"); - int * value = (int *) self; - FILE * stream = util_fopen(stringlist_iget(args , 0 ) , "r"); - fscanf(stream , "%d" , value ); - fclose( stream ); - { - int * return_value = util_malloc( sizeof * return_value ); - return_value[0] = value[0]; - - return return_value; - } -} - - -static void create_exjob( const char * workflow , const char * bin_path) -{ - FILE * stream = util_fopen( workflow , "w"); - fprintf(stream , "EXECUTABLE \"%s/create_file\"\n" , bin_path); - fprintf(stream , "ARG_TYPE 1 INT\n"); - fprintf(stream , "MIN_ARG 2\n"); - fprintf(stream , "MAX_ARG 2\n"); - fclose(stream); -} - - -void test_has_job(const char * job) { - workflow_joblist_type * joblist = workflow_joblist_alloc(); - - test_assert_false( workflow_joblist_has_job( joblist , "NoNotThis")); - test_assert_true( workflow_joblist_add_job_from_file( joblist , "CREATE_FILE" , job) ); - test_assert_true( workflow_joblist_has_job( joblist , "CREATE_FILE")); - - workflow_joblist_free( joblist ); -} - - -int main( int argc , char ** argv) { - const char * exjob_file = "job"; - const char * bin_path = argv[1]; - const char * internal_workflow = argv[2]; - test_work_area_type * work_area = test_work_area_alloc( "job_workflow_test" ); - - signal(SIGSEGV , util_abort_signal); - create_exjob( exjob_file , bin_path ); - test_has_job( exjob_file ); - { - - int int_value = rand(); - int read_value = 100; - workflow_joblist_type * joblist = workflow_joblist_alloc(); - - if (!workflow_joblist_add_job_from_file( joblist , "CREATE_FILE" , exjob_file)) { - remove( exjob_file ); - test_error_exit("Loading job CREATE_FILE failed\n"); - } else - remove( exjob_file ); - - if (!workflow_joblist_add_job_from_file( joblist , "READ_FILE" , internal_workflow)) - test_error_exit("Loading job READ_FILE failed\n"); - - { - config_parser_type * workflow_compiler = workflow_joblist_get_compiler( joblist ); - if (config_get_schema_size( workflow_compiler ) != 2) - test_error_exit("Config compiler - wrong size \n"); - } - - - { - const char * workflow_file = "workflow"; - const char * tmp_file = "fileX"; - workflow_type * workflow; - - create_workflow( workflow_file , tmp_file , int_value ); - workflow = workflow_alloc(workflow_file , joblist ); - unlink( workflow_file ); - - { - bool runOK; - runOK = workflow_run( workflow , &read_value , false , NULL); - if (runOK) { - if (int_value != read_value) - test_error_exit("Wrong numeric value read back \n"); - - test_assert_int_equal( workflow_get_stack_size( workflow ) , 2 ); - test_assert_not_NULL( workflow_iget_stack_ptr( workflow , 0 ) ); - test_assert_NULL( workflow_iget_stack_ptr( workflow , 1 ) ); - - { - void * return_value = workflow_iget_stack_ptr( workflow , 0 ); - int return_int = *((int *) return_value); - if (int_value != return_int) - test_error_exit("Wrong numeric value read back \n"); - - test_assert_not_NULL( workflow_pop_stack( workflow )); - test_assert_NULL( workflow_pop_stack( workflow )); - test_assert_int_equal( workflow_get_stack_size( workflow ) , 0 ); - - free( return_value ); - - } - } else { - unlink( tmp_file ); - test_error_exit("Workflow did not run\n"); - } - unlink( tmp_file ); - } - } - workflow_joblist_free( joblist ); - - } - { - workflow_joblist_type * joblist = workflow_joblist_alloc(); - const char * workflow_file = "workflow"; - const char * tmp_file = "fileX"; - int read_value; - int int_value = 100; - workflow_type * workflow; - - create_workflow( workflow_file , tmp_file , int_value ); - workflow = workflow_alloc(workflow_file , joblist ); - unlink( workflow_file ); - test_assert_false( workflow_run( workflow , &read_value , false , NULL) ); - test_assert_int_equal( workflow_get_stack_size( workflow ) , 0 ); - } - test_work_area_free( work_area ); - exit(0); -} diff --git a/ThirdParty/Ert/libjob_queue/tests/lsf_tests.cmake b/ThirdParty/Ert/libjob_queue/tests/lsf_tests.cmake deleted file mode 100644 index b7336f97fb..0000000000 --- a/ThirdParty/Ert/libjob_queue/tests/lsf_tests.cmake +++ /dev/null @@ -1,57 +0,0 @@ -# The testing of the lsf submit capabilities is quite troublesome for -# two reasons, and therefor by default disabled: -# -# -# 1. The shell based LSF commands require that user running the -# bsub/bjobs/bxxx command has passwordless ssh configured to log in -# to the lsf server. When the build and testing is run as a common -# 'jenkins' user this becomes difficult. -# -# 2. Submitting through the lsf library requires that the build/test -# server actually is a LIM host; which it typically is not. -# -#----------------------------------------------------------------- -# -# This should be a space separated list of servers which will be -# tried out when testing the LSF submit capability. The test program -# will interpret the special strings 'NULL' and 'LOCAL' as follows: -# -# NULL: Submit using the linked in library functions. -# LOCAL: Submit using shell commands on the current server -# -set(LSF_SERVER "" CACHE STRING "List of LSF servers for testing") - -if (HAVE_LSF_LIBRARY) - add_executable( job_lsf_test job_lsf_test.c ) - target_link_libraries( job_lsf_test job_queue util test_util ) - add_test( job_lsf_test ${EXECUTABLE_OUTPUT_PATH}/job_lsf_test ) -endif() - - - -if (HAVE_LSF_LIBRARY) - add_executable( job_lsb job_lsb.c ) - target_link_libraries( job_lsb job_queue util test_util ) - add_test( job_lsb ${EXECUTABLE_OUTPUT_PATH}/job_lsb ) -endif() - -add_executable( job_lsf_remote_submit_test job_lsf_remote_submit_test.c ) -target_link_libraries( job_lsf_remote_submit_test job_queue util test_util ) - -add_executable( job_lsf_library_submit_test job_lsf_library_submit_test.c ) -target_link_libraries( job_lsf_library_submit_test job_queue util ) - -add_executable( job_program job_program.c ) - -if (LSF_SERVER) - add_test( job_lsf_remote_submit_test ${EXECUTABLE_OUTPUT_PATH}/job_lsf_remote_submit_test ${EXECUTABLE_OUTPUT_PATH}/job_program ${LSF_SERVER} NULL LOCAL) -else() - add_test( job_lsf_remote_submit_test ${EXECUTABLE_OUTPUT_PATH}/job_lsf_remote_submit_test ${EXECUTABLE_OUTPUT_PATH}/job_program NULL LOCAL) -endif() -set_property( TEST job_lsf_remote_submit_test PROPERTY LABELS StatoilData) - -# The test program is installed - actually running the test must be -# handled completely on the outside of this build system. -if (INSTALL_ERT) - install(TARGETS job_program job_lsf_library_submit_test DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -endif() diff --git a/ThirdParty/Ert/librms/CMakeLists.txt b/ThirdParty/Ert/librms/CMakeLists.txt deleted file mode 100644 index 2e88f5e50d..0000000000 --- a/ThirdParty/Ert/librms/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_subdirectory( src ) -if (BUILD_APPLICATIONS) - add_subdirectory( applications ) -endif() - -if (BUILD_TESTS) - add_subdirectory( tests ) -endif() - - diff --git a/ThirdParty/Ert/librms/applications/CMakeLists.txt b/ThirdParty/Ert/librms/applications/CMakeLists.txt deleted file mode 100644 index 48cbff4f02..0000000000 --- a/ThirdParty/Ert/librms/applications/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -add_executable( rms_extract rms_extract.c ) -add_executable( rms_setname rms_setname.c ) -add_executable( rms_stat rms_stat.c ) -add_executable( rms_test rms_test.c ) -add_executable( tag_list tag_list.c ) - - -set(program_list rms_extract rms_setname rms_stat rms_test tag_list) -foreach(prog ${program_list}) - target_link_libraries( ${prog} rms ecl util ) - if (USE_RUNPATH) - add_runpath( ${prog} ) - endif() - - #----------------------------------------------------------------- - - set (destination ${CMAKE_INSTALL_PREFIX}/bin) - - if (INSTALL_ERT) - install(TARGETS ${prog} DESTINATION ${destination}) - if (INSTALL_GROUP) - install(CODE "EXECUTE_PROCESS(COMMAND chgrp ${INSTALL_GROUP} ${destination}/${prog})") - install(CODE "EXECUTE_PROCESS(COMMAND chmod g+w ${destination}/${prog})") - endif() - endif() -endforeach() diff --git a/ThirdParty/Ert/librms/applications/rms_extract.c b/ThirdParty/Ert/librms/applications/rms_extract.c deleted file mode 100644 index cffd6dad58..0000000000 --- a/ThirdParty/Ert/librms/applications/rms_extract.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_extract.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include - -#include -#include -#include - - -void split_name(const char * arg, char **_old_name , char **_new_name) { - char * new_name; - char * old_name; - int i; - int old_name_len = 0; - - for (i=0; i < strlen(arg); i++) { - if (arg[i] == '=') - old_name_len = i; - } - - if (old_name_len > 0) { - old_name = util_alloc_substring_copy(arg , 0 , old_name_len); - new_name = util_alloc_string_copy(&arg[old_name_len + 1]); - } else { - old_name = util_alloc_string_copy(arg); - new_name = old_name; - } - - *_old_name = old_name; - *_new_name = new_name; -} - - - - -int main (int argc , char **argv) { - { - if (argc <= 2) { - fprintf(stderr,"rms_extract.x filename tag1(=new_tag1) tag2 ... \n"); - abort(); - } - } - { - const char * filename = argv[1]; - int i; - rms_tag_type * dim_tag; - rms_file_type *file = rms_file_alloc(filename , false); - printf("Skal laste inn file: %s \n",filename); - rms_file_fread(file); - dim_tag = rms_file_get_dim_tag_ref(file); - - for (i = 2; i < argc; i++) { - char * new_name; - char * old_name; - char * new_file; - - split_name(argv[i] , &old_name , &new_name); - printf("Exctracting %s -> %s \n" , old_name , new_name); fflush(stdout); - new_file = util_alloc_filename(NULL , new_name , "ROFF"); - - { - rms_tag_type * tag; - rms_file_type * out_file = rms_file_alloc(new_file , false); - FILE *stream = rms_file_fopen_w(out_file); - rms_file_init_fwrite(out_file , "parameter"); - rms_tag_fwrite(dim_tag , stream); - - tag = rms_file_get_tag_ref(file , "parameter" , "name" , old_name , true); - rms_tag_fwrite_parameter(new_name, rms_tag_get_datakey(tag) , stream); - rms_file_complete_fwrite(out_file); - fclose(stream); - } - if (new_name == old_name) - free(new_name); - else { - free(new_name); - free(old_name); - } - } - rms_file_free(file); - return 0; - } -} - diff --git a/ThirdParty/Ert/librms/applications/rms_setname.c b/ThirdParty/Ert/librms/applications/rms_setname.c deleted file mode 100644 index b1a250df72..0000000000 --- a/ThirdParty/Ert/librms/applications/rms_setname.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_setname.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include - - -int main (int argc , char **argv) { - int i; - char *name; - int name_length; - argv++; - argc--; - - name = argv[0]; - name_length = strlen(name) + 1; - - argv++; - argc--; - for (i = 0; i < argc; i++) { - rms_file_type *file = rms_file_alloc(argv[i] , false); - rms_tagkey_type *tagkey; - rms_tag_type *tag; - rms_file_fread(file); - - tag = rms_file_get_tag_ref(file , "parameter" , NULL , NULL , true); - tagkey = rms_tag_get_key(tag , "name"); - rms_tagkey_manual_realloc_data(tagkey , name_length); - rms_tagkey_set_data(tagkey , name); - rms_file_fwrite(file , "parameter"); - rms_file_free(file); - } - - return 0; -} - diff --git a/ThirdParty/Ert/librms/applications/rms_stat.c b/ThirdParty/Ert/librms/applications/rms_stat.c deleted file mode 100644 index 770d84176d..0000000000 --- a/ThirdParty/Ert/librms/applications/rms_stat.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_stat.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include - - - -void convert_test(const char * rms_file, const char * ecl_path) { - rms_file_2eclipse(rms_file , ecl_path , false , 1); -} - - -int main (int argc , char **argv) { - char * tagname; - rms_tagkey_type *mean , *std; - rms_tag_type *dim_tag; - bool log_transform = false; - rms_file_type *file; - - if (argc < 4) { - printf("%s: PARAM-NAME file1 file2 file3 .....\n",argv[0]); - exit(1); - } - - - file = rms_file_alloc(argv[2] , false); - tagname = argv[1]; - dim_tag = rms_file_fread_alloc_tag(file , "dimensions" , NULL , NULL); - mean = rms_file_fread_alloc_data_tagkey(file , "parameter" , "name" , tagname); - std = rms_tagkey_copyc(mean); - - rms_file_free_data(file); - rms_stats_mean_std(mean , std , tagname , argc - 2 , (const char **) &argv[2] , log_transform); - - { - char * outfile = malloc(strlen(tagname) + strlen("_stats.ROFF") + 1); - sprintf(outfile , "%s_stats.ROFF" , tagname); - rms_file_set_filename(file , outfile , false); - printf("Statistics collected in: %s \n",outfile); - free(outfile); - } - - { - char * out_tag = malloc(strlen(tagname) + 6); - FILE *stream = rms_file_fopen_w(file); - rms_file_init_fwrite(file , "parameter"); - rms_tag_fwrite(dim_tag , stream); - sprintf(out_tag , "%s.mean" , tagname); rms_tag_fwrite_parameter(out_tag , mean , stream); - sprintf(out_tag , "%s.std" , tagname); rms_tag_fwrite_parameter(out_tag , std , stream); - rms_file_complete_fwrite(file); - fclose(stream); - free(out_tag); - } - - rms_tag_free(dim_tag); - rms_tagkey_free(mean); - rms_tagkey_free(std); - rms_file_free_data(file); - rms_file_free(file); - - exit(1); - - { - const int ens_size = 100; - char **file_list; - double **X; - int i , j; - file_list = malloc(ens_size * sizeof * file_list); - for (i=0; i < ens_size; i++) { - file_list[i] = malloc(100); - sprintf(file_list[i] , "PERMX_%04d.INC" , i + 1); - } - - - X = malloc(ens_size * sizeof *X); - for (i=0; i < ens_size; i++) - X[i] = malloc(ens_size * sizeof *X[i]); - - for (i=0; i < ens_size; i++) - for (j=0; j < ens_size; j++) - X[i][j] = 0; - - for (i=0; i < ens_size; i++) - X[i][i] = 1.0; - - rms_stats_update_ens("Posterior" , "Post2" , (const char **) file_list , "PERMX" , ens_size , (const double **) X); - - for (i=0; i < ens_size; i++) { - free(X[i]); - free(file_list[i]); - } - free(X); - free(file_list); - } - - return 0; -} - diff --git a/ThirdParty/Ert/librms/applications/rms_test.c b/ThirdParty/Ert/librms/applications/rms_test.c deleted file mode 100644 index fea7328777..0000000000 --- a/ThirdParty/Ert/librms/applications/rms_test.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include - - - -void convert_test(const char * rms_file, const char * ecl_path) { - rms_file_2eclipse(rms_file , ecl_path , false , 1); -} - - -int main (int argc , char **argv) { - rms_tagkey_type *mean , *std; - rms_tag_type *dim_tag; - bool log_transform = false; - - rms_file_type *file = rms_file_alloc(argv[1] , false); - dim_tag = rms_file_fread_alloc_tag(file , "dimensions" , NULL , NULL); - mean = rms_file_fread_alloc_data_tagkey(file , "parameter" , "name" , "PERMX"); - std = rms_tagkey_copyc(mean); - - rms_file_free_data(file); - rms_stats_mean_std(mean , std , "PERMX" , argc - 1 , (const char **) &argv[1] , log_transform); - rms_file_set_filename(file , "Stats.ROFF" , false); - - { - FILE *stream = rms_file_fopen_w(file); - rms_file_init_fwrite(file , "parameter"); - rms_tag_fwrite(dim_tag , stream); - rms_tag_fwrite_parameter("mean:PERMX" , mean , stream); - rms_tag_fwrite_parameter("std:PERMX" , std , stream); - rms_file_complete_fwrite(file); - fclose(stream); - } - - rms_tag_free(dim_tag); - rms_tagkey_free(mean); - rms_tagkey_free(std); - rms_file_free_data(file); - rms_file_free(file); - - exit(1); - - { - const int ens_size = 100; - char **file_list; - double **X; - int i , j; - file_list = malloc(ens_size * sizeof * file_list); - for (i=0; i < ens_size; i++) { - file_list[i] = malloc(100); - sprintf(file_list[i] , "PERMX_%04d.INC" , i + 1); - } - - - X = malloc(ens_size * sizeof *X); - for (i=0; i < ens_size; i++) - X[i] = malloc(ens_size * sizeof *X[i]); - - for (i=0; i < ens_size; i++) - for (j=0; j < ens_size; j++) - X[i][j] = 0; - - for (i=0; i < ens_size; i++) - X[i][i] = 1.0; - - rms_stats_update_ens("Posterior" , "Post2" , (const char **) file_list , "PERMX" , ens_size , (const double **) X); - - for (i=0; i < ens_size; i++) { - free(X[i]); - free(file_list[i]); - } - free(X); - free(file_list); - } - - return 0; -} - diff --git a/ThirdParty/Ert/librms/applications/tag_list.c b/ThirdParty/Ert/librms/applications/tag_list.c deleted file mode 100644 index 0f755c1bd1..0000000000 --- a/ThirdParty/Ert/librms/applications/tag_list.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'tag_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include - - - -int main (int argc , char **argv) { - int i; - - argc--; - argv++; - - for (i = 0; i < argc; i++) { - rms_file_type *file = rms_file_alloc(argv[i] , false); - rms_file_fread(file); - rms_file_fprintf(file , stdout); - rms_file_free(file); - } - - return 0; -} - diff --git a/ThirdParty/Ert/librms/include/ert/rms/rms_export.h b/ThirdParty/Ert/librms/include/ert/rms/rms_export.h deleted file mode 100644 index 67886dcdd8..0000000000 --- a/ThirdParty/Ert/librms/include/ert/rms/rms_export.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_export.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RMS_EXPORT_H -#define ERT_RMS_EXPORT_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - - -void rms_export_roff_from_keyword(const char *filename, ecl_grid_type *ecl_grid, - ecl_kw_type **ecl_kw, int size); - - - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/ThirdParty/Ert/librms/include/ert/rms/rms_file.h b/ThirdParty/Ert/librms/include/ert/rms/rms_file.h deleted file mode 100644 index c8dc136e89..0000000000 --- a/ThirdParty/Ert/librms/include/ert/rms/rms_file.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_file.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RMS_FILE_H -#define ERT_RMS_FILE_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include - -typedef struct rms_file_struct rms_file_type; - -void rms_file_2eclipse(const char * rms_file , const char * , bool , int ); -void rms_file_fclose(rms_file_type *); -FILE * rms_file_fopen_r(rms_file_type *rms_file); -FILE * rms_file_fopen_w(rms_file_type *rms_file); -void rms_file_set_filename(rms_file_type * , const char * , bool); -rms_file_type * rms_file_alloc (const char *, bool ); -void rms_file_fread (rms_file_type *); -void rms_file_fwrite (rms_file_type * , const char *); -void rms_file_fprintf (const rms_file_type * , FILE *); -void rms_file_free (rms_file_type *); -void rms_file_free_data (rms_file_type *); -rms_tag_type * rms_file_get_dim_tag_ref(const rms_file_type * ); -rms_tag_type * rms_file_get_tag_ref (const rms_file_type *, const char *, const char *, const char * , bool); -void rms_file_assert_dimensions(const rms_file_type *, int , int , int ); -rms_tag_type * rms_file_fread_alloc_tag(rms_file_type * , const char *, const char *, const char *); -rms_tagkey_type * rms_file_fread_alloc_data_tagkey(rms_file_type * , const char *, const char *, const char *); -void rms_file_complete_fwrite(const rms_file_type *); -void rms_file_init_fwrite(const rms_file_type * , const char *); -void rms_file_get_dims(const rms_file_type * , int * ); -FILE * rms_file_get_FILE(const rms_file_type * ); -void rms_file_add_dimensions(rms_file_type * , int , int , int , bool); -bool rms_file_is_roff(FILE * ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/librms/include/ert/rms/rms_stats.h b/ThirdParty/Ert/librms/include/ert/rms/rms_stats.h deleted file mode 100644 index d9193a5849..0000000000 --- a/ThirdParty/Ert/librms/include/ert/rms/rms_stats.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_stats.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RMS_STATS_H -#define ERT_RMS_STATS_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - -void rms_stats_mean_std(rms_tagkey_type * , rms_tagkey_type * , const char * , int , const char ** , bool); -void rms_stats_update_ens(const char * , const char *, const char **, const char *, int , const double **); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/librms/include/ert/rms/rms_tag.h b/ThirdParty/Ert/librms/include/ert/rms/rms_tag.h deleted file mode 100644 index c0a42d63eb..0000000000 --- a/ThirdParty/Ert/librms/include/ert/rms/rms_tag.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_tag.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RMS_TAG_H -#define ERT_RMS_TAG_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include -#include - -#include - -#include - - - -typedef struct rms_tag_struct rms_tag_type; - -int rms_tag_get_datakey_sizeof_ctype(const rms_tag_type * ); -const char * rms_tag_get_namekey_name(const rms_tag_type * ); -const char * rms_tag_get_name(const rms_tag_type *); -rms_tagkey_type * rms_tag_get_datakey(const rms_tag_type *); -void rms_tag_free(rms_tag_type *); -void rms_tag_free__(void * arg); -rms_tag_type * rms_tag_fread_alloc(FILE *, hash_type *, bool , bool *); -bool rms_tag_name_eq(const rms_tag_type *, const char * , const char *, const char *); -rms_tagkey_type * rms_tag_get_key(const rms_tag_type *, const char *); -void rms_tag_fwrite_filedata(const char * , FILE *stream); -void rms_tag_fwrite_eof(FILE *stream); -void rms_tag_fwrite(const rms_tag_type * , FILE * ); -void rms_tag_fprintf(const rms_tag_type * , FILE * ); -const char * rms_tag_name_ref(const rms_tag_type * ); -rms_tag_type * rms_tag_alloc_dimensions(int , int , int ); -void rms_tag_fwrite_dimensions(int , int , int , FILE *); -void rms_tag_fwrite_parameter(const char *, const rms_tagkey_type *, FILE *); -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/librms/include/ert/rms/rms_tagkey.h b/ThirdParty/Ert/librms/include/ert/rms/rms_tagkey.h deleted file mode 100644 index 821eba8a10..0000000000 --- a/ThirdParty/Ert/librms/include/ert/rms/rms_tagkey.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_tagkey.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RMS_TAGKEY_H -#define ERT_RMS_TAGKEY_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -#include - -#include - -typedef struct rms_tagkey_struct rms_tagkey_type; - - -bool rms_tagkey_cmp(const rms_tagkey_type * , const rms_tagkey_type * ); -void rms_tagkey_free(rms_tagkey_type *); -rms_tagkey_type * rms_tagkey_alloc_empty(bool); -rms_tagkey_type * rms_tagkey_alloc_complete(const char * , int , rms_type_enum , const void * , bool); -const char * rms_tagkey_get_name(const rms_tagkey_type *); -rms_type_enum rms_tagkey_get_rms_type(const rms_tagkey_type * ); -ecl_type_enum rms_tagkey_get_ecl_type(const rms_tagkey_type * ); -void rms_tagkey_manual_realloc_data(rms_tagkey_type * , int ); -void rms_tagkey_set_data(rms_tagkey_type * , const void * ); - -bool rms_tagkey_char_eq(const rms_tagkey_type *, const char *); -void rms_tagkey_free_(void *); -void * rms_tagkey_copyc_(const void *); -void rms_tagkey_load(rms_tagkey_type *, bool , FILE *, hash_type *); -void * rms_tagkey_get_data_ref(const rms_tagkey_type *); -void rms_tagkey_fwrite(const rms_tagkey_type * , FILE *); -void rms_tagkey_fprintf(const rms_tagkey_type * , FILE *); -rms_tagkey_type * rms_tagkey_copyc(const rms_tagkey_type *); -int rms_tagkey_get_size(const rms_tagkey_type *); - - -rms_tagkey_type * rms_tagkey_alloc_byteswap(); -rms_tagkey_type * rms_tagkey_alloc_creationDate(); -rms_tagkey_type * rms_tagkey_alloc_filetype(const char * ); -rms_tagkey_type * rms_tagkey_alloc_dim(const char * , int ); -rms_tagkey_type * rms_tagkey_alloc_parameter_name(const char * ); - -void rms_tagkey_assign(rms_tagkey_type * , const rms_tagkey_type *); -void rms_tagkey_apply(rms_tagkey_type * , double (f) (double)); -void rms_tagkey_inplace_log10(rms_tagkey_type * ); -void rms_tagkey_inplace_sqr(rms_tagkey_type *); -void rms_tagkey_inplace_sqrt(rms_tagkey_type *); -void rms_tagkey_inplace_mul(rms_tagkey_type * , const rms_tagkey_type *); -void rms_tagkey_inplace_add(rms_tagkey_type * , const rms_tagkey_type *); -void rms_tagkey_inplace_add_scaled(rms_tagkey_type * , const rms_tagkey_type * , double); -void rms_tagkey_scale(rms_tagkey_type * , double ); -void rms_tagkey_clear(rms_tagkey_type * ); -int rms_tagkey_get_sizeof_ctype(const rms_tagkey_type * ); -void rms_tagkey_max_min(const rms_tagkey_type * , void *, void *); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/librms/include/ert/rms/rms_type.h b/ThirdParty/Ert/librms/include/ert/rms/rms_type.h deleted file mode 100644 index 124b5b4c5c..0000000000 --- a/ThirdParty/Ert/librms/include/ert/rms/rms_type.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_type.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RMS_TYPE_H -#define ERT_RMS_TYPE_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - - -typedef enum rms_type_enum_def rms_type_enum; - -enum rms_type_enum_def {rms_char_type , rms_float_type , rms_double_type , rms_bool_type , rms_byte_type , rms_int_type}; - -/* This *really* should not be exported ... */ - -typedef struct { - rms_type_enum rms_type; - int sizeof_ctype; - -} __rms_type; - -/*****************************************************************/ - -void rms_type_free(void *); -__rms_type * rms_type_alloc(rms_type_enum , int ); -const void * rms_type_copyc(const void * ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/librms/include/ert/rms/rms_util.h b/ThirdParty/Ert/librms/include/ert/rms/rms_util.h deleted file mode 100644 index adf913b24d..0000000000 --- a/ThirdParty/Ert/librms/include/ert/rms/rms_util.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_util.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_RMS_UTIL_H -#define ERT_RMS_UTIL_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -#include - -#define RMS_INACTIVE_DOUBLE -999.00 -#define RMS_INACTIVE_FLOAT -999.00 -#define RMS_INACTIVE_INT -999 - - -rms_type_enum rms_util_convert_ecl_type(ecl_type_enum ); -int rms_util_global_index_from_eclipse_ijk(int, int, int, int, int, int); -void rms_util_translate_undef(void * , int , int , const void * , const void * ); -void rms_util_set_fortran_data(void *, const void * , int , int , int , int); -void rms_util_read_fortran_data(const void *, void * , int , int , int , int); -void rms_util_fskip_string(FILE *); -int rms_util_fread_strlen(FILE *); -bool rms_util_fread_string(char * , int , FILE *); -void rms_util_fwrite_string(const char * string , FILE *stream); -void rms_util_fwrite_comment(const char * , FILE *); -void rms_util_fwrite_newline(FILE *stream); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/librms/src/CMakeLists.txt b/ThirdParty/Ert/librms/src/CMakeLists.txt deleted file mode 100644 index 606e86e815..0000000000 --- a/ThirdParty/Ert/librms/src/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -set( source_files rms_file.c rms_util.c rms_tag.c rms_type.c rms_tagkey.c rms_stats.c rms_export.c) -set( header_files rms_file.h rms_util.h rms_tag.h rms_type.h rms_tagkey.h rms_stats.h rms_export.h) - -add_library( rms ${LIBRARY_TYPE} ${source_files} ) -set_target_properties( rms PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR} ) -target_link_libraries( rms ecl ) -if (USE_RUNPATH) - add_runpath( rms ) -endif() - - -#----------------------------------------------------------------- -if (INSTALL_ERT) - install(TARGETS rms DESTINATION ${CMAKE_INSTALL_LIBDIR}) - foreach(header ${header_files}) - install(FILES ../include/ert/rms/${header} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/ert/rms) - endforeach() -endif() - diff --git a/ThirdParty/Ert/librms/src/readme.overview b/ThirdParty/Ert/librms/src/readme.overview deleted file mode 100644 index 5b3c3dff52..0000000000 --- a/ThirdParty/Ert/librms/src/readme.overview +++ /dev/null @@ -1,55 +0,0 @@ -The EnKF functionality is organized in xxx libraries with different -functionalities. The different libraries depend on eachother, and the -libraries must be built in correct order. The dependencies is as -follows: - -libhash : -libutil : libhash -libecl : libhash libutil -librms : libecl libutil libhash -libsched : libecl linutil libhash -libenkf : libecl libsched librm linutil libhash - - -libhash: This library implements the classes hash_type, set_type and - list_type. - -libutil: This library is a collection utility routines. Observe that - this library only implements routines, and not statefull - objects. - -libecl: This library implements functions for reading/writing ECLIPSE - restart/summary/init/grid files. - -libsched: This library implements a basic SCHEDULE file parser. - -librms: This library implements (basic) reader and writer for binary - RMS ROFF files. - -libenkf: This library implements various high level objects for EnKF - functionality. - ------------------------------------------------------------------ - -All the makefiles start with the statement: - -include "path_config" - -The file path_config is *not* under version control, this is on -purpose because every user can/should have a private confiiguration of -paths. The file path_config should define make-variables for the -location of all the libraries, this is an example of a valid -path-config file: - - LIBHASH_HOME = /h/a152128/EnKF/EnKF/libhash - LIBUTIL_HOME = /h/a152128/EnKF/EnKF/libutil - LIBSCHED_HOME = /h/a152128/EnKF/EnKF/libsched - LIBRMS_HOME = /h/a152128/EnKF/EnKF/librms - LIBECL_HOME = /h/a152128/EnKF/EnKF/libecl - LIBENKF_HOME = /h/a152128/EnKF/EnKF/libenkf - -In this example all libraries have a common path prefix, that is not -a requirement. - - - diff --git a/ThirdParty/Ert/librms/src/rms_export.c b/ThirdParty/Ert/librms/src/rms_export.c deleted file mode 100644 index 672eb25025..0000000000 --- a/ThirdParty/Ert/librms/src/rms_export.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_export.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include - - -void rms_export_roff_from_keyword(const char *filename, ecl_grid_type *ecl_grid, - ecl_kw_type **ecl_kw, int size) { - - rms_file_type *rms_file; - rms_tagkey_type *data_key; - int nx, ny, nz, active_size; - int i, j, k; - int global_size; - int n; - - ecl_grid_get_dims(ecl_grid, &nx, &ny, &nz, &active_size); - global_size = ecl_grid_get_global_size(ecl_grid); - - rms_file = rms_file_alloc(filename, false); - rms_file_fopen_w(rms_file); - - rms_file_init_fwrite(rms_file , "parameter"); - rms_tag_fwrite_dimensions(nx , ny , nz , rms_file_get_FILE(rms_file)); - - for (n = 0; n < size; n++) { - float *src_data; - float *target_data; - - src_data = (float *) ecl_kw_get_void_ptr(ecl_kw[n]); - target_data = util_calloc(global_size , sizeof * target_data ); - - for (k=0; k < nz; k++) { - for (j=0; j < ny; j++) { - for (i=0; i < nx; i++) { - int index1D; - int index3D; - double fill = RMS_INACTIVE_FLOAT; - /* TODO: - * This currently only supports FLOAT / REAL type. - */ - - index1D = ecl_grid_get_active_index3(ecl_grid, i, j, k); - index3D = rms_util_global_index_from_eclipse_ijk(nx, ny, nz, i, j, k); - - if (index1D >= 0) - target_data[index3D] = src_data[index1D]; - else - memcpy(&target_data[index3D] , &fill, sizeof(float)); - } - } - } - - data_key = rms_tagkey_alloc_complete("data", global_size, - rms_util_convert_ecl_type(ecl_kw_get_type(ecl_kw[n])), target_data, true); - rms_tag_fwrite_parameter(ecl_kw_get_header8(ecl_kw[n]), data_key, - rms_file_get_FILE(rms_file)); - rms_tagkey_free(data_key); - - util_safe_free(target_data); - } - - rms_file_complete_fwrite(rms_file); - rms_file_fclose(rms_file); - rms_file_free(rms_file); - -} diff --git a/ThirdParty/Ert/librms/src/rms_file.c b/ThirdParty/Ert/librms/src/rms_file.c deleted file mode 100644 index 26a4f6aa44..0000000000 --- a/ThirdParty/Ert/librms/src/rms_file.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_file.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -/*****************************************************************/ -static const char * rms_ascii_header = "roff-asc"; -static const char * rms_binary_header = "roff-bin"; - -static const char * rms_comment1 = "ROFF file"; -static const char * rms_comment2 = "Creator: RMS - Reservoir Modelling System, version 8.1"; -/* - static const char * rms_parameter_tagname = "parameter"; -*/ - - - - - -struct rms_file_struct { - char * filename; - bool endian_convert; - bool fmt_file; - hash_type * type_map; - vector_type * tag_list; - FILE * stream; -}; - - - -/*****************************************************************/ -/* Pure roff routines */ - - - - -static bool rms_fmt_file(const rms_file_type *rms_file) { - bool fmt_file; - char filetype[9]; - rms_util_fread_string( filetype , 9 , rms_file->stream); - - if (strncmp(filetype , rms_binary_header , 8) == 0) - fmt_file = false; - else if (strncmp(filetype , rms_ascii_header , 8) == 0) - fmt_file = true; - else { - fprintf(stderr,"%s: header : %8s not recognized in file: %s - aborting \n",__func__ , filetype , rms_file->filename); - abort(); - } - return fmt_file; -} - - - -static void rms_file_add_tag(rms_file_type *rms_file , const rms_tag_type *tag) { - vector_append_owned_ref(rms_file->tag_list , tag , rms_tag_free__ ); -} - - -void rms_file_add_dimensions(rms_file_type * rms_file , int nX , int nY , int nZ , bool save) { - if (rms_file_get_tag_ref(rms_file , "dimensions" , NULL , NULL , false) != NULL) { - fprintf(stderr,"%s: dimensions tag already persent in rms_file object - aborting \n",__func__); - abort(); - } - { - rms_tag_type * dim_tag = rms_tag_alloc_dimensions(nX , nY , nZ); - rms_file_add_tag(rms_file , dim_tag); - if (save) - rms_tag_fwrite(dim_tag , rms_file->stream); - } -} - - -rms_tag_type * rms_file_get_tag_ref(const rms_file_type *rms_file , - const char *tagname , - const char *keyname , - const char *keyvalue, bool abort_on_error) { - - rms_tag_type *return_tag = NULL; - bool cont; - { - int index = 0; - while (cont) { - if (index < vector_get_size( rms_file->tag_list )) { - rms_tag_type *tag = vector_iget( rms_file->tag_list , index ); - if (rms_tag_name_eq(tag , tagname , keyname , keyvalue)) { - return_tag = tag; - cont = false; - } else - index++; - } else - cont = false; - } - } - - if (return_tag == NULL && abort_on_error) { - if (keyname != NULL && keyvalue != NULL) - fprintf(stderr,"%s: failed to find tag:%s with key:%s=%s in file:%s - aborting \n",__func__ , tagname , keyname , keyvalue , rms_file->filename); - else - fprintf(stderr,"%s: failed to find tag:%s in file:%s - aborting \n",__func__ , tagname , rms_file->filename); - } - return return_tag; -} - - - - - - -/** - This function allocates and rms_file_type * handle, but it does - not load the file content. -*/ - - -rms_file_type * rms_file_alloc(const char *filename, bool fmt_file) { - rms_file_type *rms_file = malloc(sizeof *rms_file); - rms_file->endian_convert = false; - rms_file->type_map = hash_alloc(); - rms_file->tag_list = vector_alloc_new(); - - hash_insert_hash_owned_ref(rms_file->type_map , "byte" , rms_type_alloc(rms_byte_type , 1) , rms_type_free); - hash_insert_hash_owned_ref(rms_file->type_map , "bool" , rms_type_alloc(rms_bool_type, 1) , rms_type_free); - hash_insert_hash_owned_ref(rms_file->type_map , "int" , rms_type_alloc(rms_int_type , 4) , rms_type_free); - hash_insert_hash_owned_ref(rms_file->type_map , "float" , rms_type_alloc(rms_float_type , 4) , rms_type_free); - hash_insert_hash_owned_ref(rms_file->type_map , "double" , rms_type_alloc(rms_double_type , 8) , rms_type_free); - - hash_insert_hash_owned_ref(rms_file->type_map , "char" , rms_type_alloc(rms_char_type , -1) , rms_type_free); /* Char are a f*** mix of vector and scalar */ - - rms_file->filename = NULL; - rms_file->stream = NULL; - rms_file_set_filename(rms_file , filename , fmt_file); - return rms_file; -} - - - - - - -void rms_file_set_filename(rms_file_type * rms_file , const char *filename , bool fmt_file) { - rms_file->filename = util_realloc_string_copy(rms_file->filename , filename); - rms_file->fmt_file = fmt_file; -} - - - -void rms_file_free_data(rms_file_type * rms_file) { - vector_clear( rms_file->tag_list ); -} - - - -void rms_file_free(rms_file_type * rms_file) { - rms_file_free_data(rms_file); - vector_free( rms_file->tag_list ); - hash_free(rms_file->type_map); - free(rms_file->filename); - free(rms_file); -} - - -static int rms_file_get_dim(const rms_tag_type *tag , const char *dim_name) { - rms_tagkey_type *key = rms_tag_get_key(tag , dim_name); - if (key == NULL) { - fprintf(stderr,"%s: failed to find tagkey:%s aborting \n" , __func__ , dim_name); - abort(); - } - return * (int *) rms_tagkey_get_data_ref(key); -} - - - -void rms_file_assert_dimensions(const rms_file_type *rms_file , int nx , int ny , int nz) { - bool OK = true; - rms_tag_type *tag = rms_file_get_tag_ref(rms_file , "dimensions" , NULL , NULL , true); - OK = (nx == rms_file_get_dim(tag , "nX")); - OK = OK && (ny == rms_file_get_dim(tag , "nY")); - OK = OK && (nz == rms_file_get_dim(tag , "nZ")); - - if (!OK) { - fprintf(stderr,"%s: dimensions on file: %s (%d, %d, %d) did not match with input dimensions (%d,%d,%d) - aborting \n",__func__ , rms_file->filename, - rms_file_get_dim(tag , "nX"), rms_file_get_dim(tag , "nY"), rms_file_get_dim(tag , "nZ"), - nx , ny , nz); - abort(); - } -} - -rms_tag_type * rms_file_get_dim_tag_ref(const rms_file_type * rms_file) { - return rms_file_get_tag_ref(rms_file , "dimensions" , NULL , NULL , true); -} - - -void rms_file_get_dims(const rms_file_type * rms_file , int * dims) { - rms_tag_type *tag = rms_file_get_dim_tag_ref(rms_file); - dims[0] = rms_file_get_dim(tag , "nX"); - dims[1] = rms_file_get_dim(tag , "nY"); - dims[2] = rms_file_get_dim(tag , "nZ"); -} - - -FILE * rms_file_get_FILE(const rms_file_type * rms_file) { return rms_file->stream; } - - -static void rms_file_init_fread(rms_file_type * rms_file) { - - rms_file->fmt_file = rms_fmt_file( rms_file ); - if (rms_file->fmt_file) { - fprintf(stderr,"%s only binary files implemented - aborting \n",__func__); - abort(); - } - /* Skipping two comment lines ... */ - rms_util_fskip_string(rms_file->stream); - rms_util_fskip_string(rms_file->stream); - { - bool eof_tag; - rms_tag_type * filedata_tag = rms_tag_fread_alloc(rms_file->stream , rms_file->type_map , rms_file->endian_convert , &eof_tag); - rms_tagkey_type * byteswap_key = rms_tag_get_key(filedata_tag , "byteswaptest"); - if (byteswap_key == NULL) { - fprintf(stderr,"%s: failed to find filedata/byteswaptest - aborting \n", __func__); - abort(); - } - int byteswap_value = *( int *) rms_tagkey_get_data_ref(byteswap_key); - if (byteswap_value == 1) - rms_file->endian_convert = false; - else - rms_file->endian_convert = true; - rms_tag_free(filedata_tag); - } -} - - - -rms_tag_type * rms_file_fread_alloc_tag(rms_file_type * rms_file , const char *tagname , const char * keyname , const char *keyvalue ) { - rms_tag_type * tag = NULL; - rms_file_fopen_r(rms_file); - { - - bool cont = true; - bool tag_found = false; - long int start_pos = util_ftell(rms_file->stream); - util_fseek(rms_file->stream , 0 , SEEK_SET); - rms_file_init_fread(rms_file); - while (cont) { - bool eof_tag; - rms_tag_type * tmp_tag = rms_tag_fread_alloc(rms_file->stream , rms_file->type_map , rms_file->endian_convert , &eof_tag); - if (rms_tag_name_eq(tmp_tag , tagname , keyname , keyvalue)) { - tag_found = true; - tag = tmp_tag; - } else - rms_tag_free(tmp_tag); - if (tag_found || eof_tag) - cont = false; - } - if (tag == NULL) { - util_fseek(rms_file->stream , start_pos , SEEK_SET); - util_abort("%s: could not find tag: \"%s\" (with %s=%s) in file:%s - aborting.\n",__func__ , tagname , keyname , keyvalue , rms_file->filename); - } - } - rms_file_fclose(rms_file); - return tag; -} - - - -FILE * rms_file_fopen_r(rms_file_type *rms_file) { - rms_file->stream = util_fopen(rms_file->filename , "r"); - return rms_file->stream; -} - - -FILE * rms_file_fopen_w(rms_file_type *rms_file) { - rms_file->stream = util_mkdir_fopen(rms_file->filename , "w"); - return rms_file->stream; -} - -void rms_file_fclose(rms_file_type * rms_file) { - fclose(rms_file->stream); - rms_file->stream = NULL; -} - - -rms_tagkey_type * rms_file_fread_alloc_data_tagkey(rms_file_type * rms_file , const char *tagname , const char * keyname , const char *keyvalue) { - rms_tag_type * tag = rms_file_fread_alloc_tag(rms_file , tagname , keyname , keyvalue); - if (tag != NULL) { - rms_tagkey_type *tagkey = rms_tagkey_copyc( rms_tag_get_key(tag , "data") ); - rms_tag_free(tag); - return tagkey; - } else - return NULL; -} - - - -void rms_file_fread(rms_file_type *rms_file) { - rms_file_fopen_r(rms_file); - rms_file_init_fread(rms_file); - - /* The main read loop */ - { - bool eof_tag = false; - while (!eof_tag) { - rms_tag_type * tag = rms_tag_fread_alloc(rms_file->stream , rms_file->type_map , rms_file->endian_convert , &eof_tag ); - if (!eof_tag) - rms_file_add_tag(rms_file , tag); - else - rms_tag_free(tag); - - } - } - rms_file_fclose(rms_file); -} - - - -/*static */ -void rms_file_init_fwrite(const rms_file_type * rms_file , const char * filetype) { - if (!rms_file->fmt_file) - rms_util_fwrite_string(rms_binary_header , rms_file->stream); - else { - fprintf(stderr,"%s: Sorry only binary writes implemented ... \n",__func__); - rms_util_fwrite_string(rms_ascii_header , rms_file->stream); - } - - rms_util_fwrite_comment(rms_comment1 , rms_file->stream); - rms_util_fwrite_comment(rms_comment2 , rms_file->stream); - rms_tag_fwrite_filedata(filetype , rms_file->stream); -} - - - -void rms_file_complete_fwrite(const rms_file_type * rms_file) { - rms_tag_fwrite_eof(rms_file->stream); -} - - - -void rms_file_fwrite(rms_file_type * rms_file, const char * filetype) { - rms_file_fopen_w(rms_file); - rms_file_init_fwrite(rms_file , filetype ); - - { - int tag_index; - for (tag_index = 0; tag_index < vector_get_size( rms_file->tag_list ); tag_index++) { - const rms_tag_type *tag = vector_iget_const( rms_file->tag_list , tag_index ); - rms_tag_fwrite(tag , rms_file->stream); - } - } - - rms_file_complete_fwrite(rms_file ); - rms_file_fclose(rms_file); -} - - -void rms_file_fprintf(const rms_file_type *rms_file , FILE *stream) { - fprintf(stream , "<%s>\n",rms_file->filename); - { - int tag_index; - for (tag_index = 0; tag_index < vector_get_size( rms_file->tag_list ); tag_index++) { - const rms_tag_type *tag = vector_iget_const( rms_file->tag_list , tag_index ); - rms_tag_fprintf(tag , rms_file->stream); - } - } - fprintf(stream , "\n",rms_file->filename); -} - - - -/* - Hardcoded assumption that the parameter type is float - otherwise this - will break hard. -*/ - -void rms_file_2eclipse(const char * rms_file , const char * ecl_path, bool ecl_fmt_file , int ecl_file_nr) { - char * rms_base_file; - int dims[3] , size; - rms_file_type *file = rms_file_alloc(rms_file , false); - rms_file_fread(file); - rms_file_get_dims(file , dims); - size = dims[0] * dims[1] * dims[2] ; - - util_alloc_file_components(rms_file , NULL , &rms_base_file , NULL); - { - float * ecl_data = malloc(size * sizeof * ecl_data); - int tag_index; - for (tag_index = 0; tag_index < vector_get_size( file->tag_list ); tag_index++) { - rms_tag_type * rms_tag = vector_iget( file->tag_list , tag_index ); - - if (rms_tag_name_eq(rms_tag , "parameter" , NULL , NULL)) { - rms_tagkey_type * rms_tagkey = rms_tag_get_datakey(rms_tag); - const float * data = rms_tagkey_get_data_ref(rms_tagkey); - rms_util_set_fortran_data(ecl_data , data , sizeof * ecl_data , dims[0] , dims[1] , dims[2]); - - { - float rms_undef = -999; - float ecl_undef = 0; - rms_util_translate_undef(ecl_data , size , rms_tagkey_get_sizeof_ctype(rms_tagkey) , &rms_undef , &ecl_undef); - } - - { - const char * tagname = rms_tag_get_namekey_name(rms_tag); - char * ecl_base = malloc(4 + strlen(tagname) + 2); - char * ecl_file; - - sprintf(ecl_base , "%s_%04d" , tagname , ecl_file_nr); - ecl_file = util_alloc_filename(ecl_path , ecl_base , NULL); - if (util_same_file(ecl_file , rms_file)) { - fprintf(stderr,"%s: attempt to overwrite %s -> %s - aborting \n",__func__ , rms_file , ecl_file); - abort(); - } - - ecl_kw_fwrite_param(ecl_file , ecl_fmt_file , tagname , ECL_FLOAT_TYPE , size , ecl_data); - free(ecl_base); - free(ecl_file); - - } - } - } - free(ecl_data); - } - free(rms_base_file); -} - - - -bool rms_file_is_roff(FILE * stream) { - const int len = strlen(rms_comment1); - char *header = malloc(strlen(rms_comment1) + 1); - const long int current_pos = util_ftell(stream); - bool roff_file = false; - - util_fseek(stream , 1 + 1 + 8 , SEEK_CUR); /* Skipping #roff-bin#0# WILL Fail with formatted files */ - rms_util_fread_string(header , len+1 , stream); - if (strncmp(rms_comment1 , header , len) == 0) - roff_file = true; - - util_fseek(stream , current_pos , SEEK_SET); - free(header); - return roff_file; -} - - -/*****************************************************************/ -/* Old hack version: */ - - -void old_rms_roff_load(const char *filename , const char *param_name , float *param) { - const int offset = 327 + strlen(param_name); - int n_read; - int size; - FILE *stream = fopen(filename , "r"); - - util_fseek(stream , offset , SEEK_SET); - fread(&size , 1 , sizeof size , stream); - n_read = fread(param , sizeof *param , size , stream); - - fclose(stream); - if (n_read != size) { - fprintf(stderr,"%s: wanted:%d elements - only read:%d - aborting \n",__func__, size , n_read); - abort(); - } -} diff --git a/ThirdParty/Ert/librms/src/rms_stats.c b/ThirdParty/Ert/librms/src/rms_stats.c deleted file mode 100644 index 0de7946029..0000000000 --- a/ThirdParty/Ert/librms/src/rms_stats.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_stats.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include - -#include -#include -#include -#include - - - - - -void rms_stats_mean_std(rms_tagkey_type * mean , rms_tagkey_type * std , const char *parameter_name , int files , const char **filelist , bool log_transform) { - int filenr; - double norm = 1.0 / files; - - rms_tagkey_clear(mean); - rms_tagkey_clear(std); - - - printf("Loading: "); - for (filenr = 0; filenr < files; filenr++) { - printf("%s",filelist[filenr]); fflush(stdout); - { - rms_file_type *rms_file = rms_file_alloc(filelist[filenr] , false); - rms_tagkey_type * file_tag = rms_file_fread_alloc_data_tagkey(rms_file, "parameter" , "name" , parameter_name); - - if (log_transform) - rms_tagkey_inplace_log10(file_tag); - - rms_tagkey_inplace_add_scaled(mean , file_tag , norm); - rms_tagkey_inplace_sqr(file_tag); - rms_tagkey_inplace_add_scaled(std , file_tag , norm); - rms_tagkey_free(file_tag); - - rms_file_free(rms_file); - } - { - int j; - for (j = 0; j < strlen(filelist[filenr]); j++) fputc('\b' , stdout); - } - } - printf("\n"); - - { - rms_tagkey_type * mean2; - mean2 = rms_tagkey_copyc(mean); - rms_tagkey_inplace_sqr(mean2); - - rms_tagkey_inplace_add_scaled(std , mean2 , -1.0); - rms_tagkey_inplace_sqrt(std); - rms_tagkey_free(mean2); - } -} - - - -void rms_stats_update_ens(const char *prior_path , const char *posterior_path , const char **file_list , const char *param_name , int ens_size , const double **X) { - int iens , j; - rms_tagkey_type ** prior; - rms_tagkey_type * post ; - rms_tag_type * dim_tag = NULL; - - if (!util_is_directory(posterior_path)) { - fprintf(stderr,"%s: posterior_path:%s does not exist - aborting \n",__func__ , posterior_path); - abort(); - } - - prior = malloc(ens_size * sizeof * prior); - printf("Loading: "); - for (iens = 0; iens < ens_size; iens++) { - char * file_name = util_alloc_filename(prior_path , file_list[iens] , NULL); - printf("%s",file_name); fflush(stdout); - { - rms_file_type * rms_file = rms_file_alloc(file_name , false); - prior[iens] = rms_file_fread_alloc_data_tagkey(rms_file , "parameter" , "name" , param_name); - - if (iens == 0) - dim_tag = rms_file_fread_alloc_tag(rms_file , "dimensions" , NULL , NULL); - - rms_file_free(rms_file); - } - for (j = 0; j < strlen(file_name); j++) fputc('\b' , stdout); - - - free(file_name); - } - printf("\n"); - - printf("Writing: "); - post = rms_tagkey_copyc(prior[0]); - for (iens = 0; iens < ens_size; iens++) { - rms_tagkey_clear(post); - - for (j=0; j < iens; j++) - rms_tagkey_inplace_add_scaled(post , prior[j] , X[iens][j]); - - { - char * file_name = util_alloc_filename(posterior_path , file_list[iens] , NULL); - rms_file_type *file = rms_file_alloc(file_name , false); - FILE *stream = rms_file_fopen_w(file); - - printf("%s",file_name); fflush(stdout); - rms_file_init_fwrite(file , "parameter"); - rms_tag_fwrite(dim_tag , stream); - rms_tag_fwrite_parameter(param_name , post , stream); - rms_file_complete_fwrite(file); - fclose(stream); - rms_file_free(file); - - for (j = 0; j < strlen(file_name); j++) fputc('\b' , stdout); - free(file_name); - } - } - printf("\n"); - - rms_tag_free(dim_tag); - rms_tagkey_free(post); - for (iens = 0; iens < ens_size; iens++) - rms_tagkey_free(prior[iens]); - free(prior); -} - diff --git a/ThirdParty/Ert/librms/src/rms_tag.c b/ThirdParty/Ert/librms/src/rms_tag.c deleted file mode 100644 index 078fc859df..0000000000 --- a/ThirdParty/Ert/librms/src/rms_tag.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_tag.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -static const char * rms_eof_tag = "eof"; -static const char * rms_starttag_string = "tag"; -static const char * rms_endtag_string = "endtag"; - - -#define SHARED 0 -#define OWNED_REF 1 -#define COPY 2 - -#define RMS_TAG_TYPE_ID 4431296 - -struct rms_tag_struct { - UTIL_TYPE_ID_DECLARATION; - char * name; - vector_type * key_list; - hash_type * key_hash; /* Hash of tagkey instances */ -}; - -/*****************************************************************/ - - -rms_tag_type * rms_tag_alloc(const char * name) { - rms_tag_type *tag = malloc(sizeof *tag); - UTIL_TYPE_ID_INIT( tag , RMS_TAG_TYPE_ID ) - tag->name = NULL; - tag->key_hash = hash_alloc(); - tag->key_list = vector_alloc_new(); - if (name != NULL) - tag->name = util_alloc_string_copy(name); - return tag; -} - - -static UTIL_SAFE_CAST_FUNCTION( rms_tag , RMS_TAG_TYPE_ID ) - - -void rms_tag_free(rms_tag_type *tag) { - free(tag->name); - hash_free(tag->key_hash); - vector_free(tag->key_list); - free(tag); -} - -void rms_tag_free__(void * arg) { - rms_tag_type * tag = rms_tag_safe_cast( arg ); - rms_tag_free( tag ); -} - - -const char * rms_tag_get_name(const rms_tag_type *tag) { - return tag->name; -} - - - -/*static*/ -void rms_tag_fread_header(rms_tag_type *tag , FILE *stream , bool *eof_tag) { - char *buffer; - *eof_tag = false; - buffer = util_calloc( 4 , sizeof * buffer); - if (rms_util_fread_string(buffer , 4 , stream )) { - if (strcmp(buffer , rms_starttag_string) == 0) { - /* OK */ - { - char *tmp = util_calloc( rms_util_fread_strlen(stream) + 1 , sizeof * tmp); - rms_util_fread_string(tmp , 0 , stream); - tag->name = tmp; - if (strcmp(tag->name , rms_eof_tag) == 0) - *eof_tag = true; - } - } else - util_abort("%s: not at tag - header aborting \n",__func__); - } else - util_abort("%s: not at tag - header aborting \n",__func__); - - free(buffer); -} - - - -/** - This function does a "two-level" comparison. - - 1. tag->name is compared with tagname. - 2. Iff test number one succeeds we go further to step2. The second will always suceed if tagkey_name == NULL. - -*/ - -bool rms_tag_name_eq(const rms_tag_type *tag , const char * tagname , const char *tagkey_name , const char *keyvalue) { - bool eq = false; - if (strcmp(tag->name , tagname) == 0) { - if (tagkey_name != NULL && keyvalue != NULL) { - if (hash_has_key(tag->key_hash , tagkey_name)) { - const rms_tagkey_type *tagkey = hash_get(tag->key_hash , tagkey_name); - eq = rms_tagkey_char_eq(tagkey , keyvalue); - } - } else - eq = true; - } - return eq; -} - - - - -rms_tagkey_type * rms_tag_get_key(const rms_tag_type *tag , const char *keyname) { - if (hash_has_key(tag->key_hash , keyname)) - return hash_get(tag->key_hash, keyname); - else - return NULL; -} - - -rms_tagkey_type * rms_tag_get_datakey(const rms_tag_type *tag) { - return rms_tag_get_key(tag , "data"); -} - - -const char * rms_tag_get_namekey_name(const rms_tag_type * tag) { - rms_tagkey_type * name_key = rms_tag_get_key(tag , "name"); - if (name_key == NULL) - util_abort("%s: no name tagkey defined for this tag - aborting \n",__func__); - - return rms_tagkey_get_data_ref(name_key); -} - - -int rms_tag_get_datakey_sizeof_ctype(const rms_tag_type * tag) { - rms_tagkey_type * data_key = rms_tag_get_key(tag , "data"); - if (data_key == NULL) - util_abort("%s: no data tagkey defined for this tag - aborting \n",__func__); - - return rms_tagkey_get_sizeof_ctype(data_key); -} - - - - - -void rms_tag_add_tagkey(rms_tag_type *tag , const rms_tagkey_type *tagkey, int mem_mode) { - rms_tagkey_type * tagkey_copy; - - switch (mem_mode) { - case(COPY): - tagkey_copy = rms_tagkey_copyc(tagkey); - vector_append_owned_ref( tag->key_list , tagkey_copy , rms_tagkey_free_ ); - hash_insert_ref(tag->key_hash , rms_tagkey_get_name(tagkey_copy) , tagkey_copy); - break; - case(OWNED_REF): - vector_append_owned_ref( tag->key_list , tagkey , rms_tagkey_free_ ); - hash_insert_ref(tag->key_hash , rms_tagkey_get_name(tagkey) , tagkey); - break; - case(SHARED): - vector_append_ref( tag->key_list , tagkey ); - hash_insert_ref(tag->key_hash , rms_tagkey_get_name(tagkey) , tagkey); - break; - } -} - - - -static bool rms_tag_at_endtag(FILE *stream) { - const int init_pos = util_ftell(stream); - bool at_endtag; - char tag[7]; - if (rms_util_fread_string(tag , 7 , stream)) { - if (strcmp(tag , rms_endtag_string) == 0) - at_endtag = true; - else - at_endtag = false; - } else - at_endtag = false; - - if (!at_endtag) - util_fseek(stream , init_pos , SEEK_SET); - return at_endtag; -} - - -void rms_fread_tag(rms_tag_type *tag, FILE *stream , hash_type *type_map , bool endian_convert , bool *at_eof) { - rms_tag_fread_header(tag , stream , at_eof); - if (!*at_eof) { - while (! rms_tag_at_endtag(stream)) { - rms_tagkey_type *tagkey = rms_tagkey_alloc_empty(endian_convert); - rms_tagkey_load(tagkey , endian_convert , stream , type_map); - rms_tag_add_tagkey(tag , tagkey , COPY); - rms_tagkey_free(tagkey); - } - } -} - - - -rms_tag_type * rms_tag_fread_alloc(FILE *stream , hash_type *type_map , bool endian_convert , bool *at_eof) { - rms_tag_type *tag = rms_tag_alloc(NULL); - rms_fread_tag(tag , stream , type_map , endian_convert , at_eof); - return tag; -} - - - -void rms_tag_fwrite(const rms_tag_type * tag , FILE * stream) { - rms_util_fwrite_string("tag" , stream); - rms_util_fwrite_string(tag->name , stream); - { - - int i; - for (i=0; i < vector_get_size( tag->key_list ); i++) { - const rms_tagkey_type * tagkey = vector_iget_const( tag->key_list , i ); - rms_tagkey_fwrite( tagkey , stream); - } - - } - rms_util_fwrite_string("endtag" , stream); -} - - -void rms_tag_fprintf(const rms_tag_type * tag , FILE * stream) { - fprintf(stream , " <%s>\n",tag->name); - { - - int i; - for (i=0; i < vector_get_size( tag->key_list ); i++) { - const rms_tagkey_type * tagkey = vector_iget_const( tag->key_list , i ); - rms_tagkey_fprintf( tagkey , stream); - } - - } - fprintf(stream , " \n",tag->name); -} - - -void rms_tag_fwrite_eof(FILE *stream) { - rms_tag_type * tag = rms_tag_alloc("eof"); - rms_tag_fwrite(tag , stream); - rms_tag_free(tag); -} - - -void rms_tag_fwrite_filedata(const char * filetype, FILE *stream) { - rms_tag_type * tag = rms_tag_alloc("filedata"); - - rms_tag_add_tagkey(tag , rms_tagkey_alloc_byteswap() , OWNED_REF); - rms_tag_add_tagkey(tag , rms_tagkey_alloc_filetype(filetype) , OWNED_REF); - rms_tag_add_tagkey(tag , rms_tagkey_alloc_creationDate() , OWNED_REF); - - rms_tag_fwrite(tag , stream); - rms_tag_free(tag); -} - - -rms_tag_type * rms_tag_alloc_dimensions(int nX , int nY , int nZ) { - rms_tag_type * tag = rms_tag_alloc("dimensions"); - - rms_tag_add_tagkey(tag , rms_tagkey_alloc_dim("nX", nX) , OWNED_REF); - rms_tag_add_tagkey(tag , rms_tagkey_alloc_dim("nY", nY) , OWNED_REF); - rms_tag_add_tagkey(tag , rms_tagkey_alloc_dim("nZ", nZ) , OWNED_REF); - - return tag; -} - - -void rms_tag_fwrite_dimensions(int nX , int nY , int nZ , FILE *stream) { - rms_tag_type * tag = rms_tag_alloc_dimensions(nX , nY , nZ); - rms_tag_fwrite(tag , stream); - rms_tag_free(tag); -} - - -void rms_tag_fwrite_parameter(const char *param_name , const rms_tagkey_type *data_key, FILE *stream) { - rms_tag_type * tag = rms_tag_alloc("parameter"); - - rms_tag_add_tagkey(tag , rms_tagkey_alloc_parameter_name(param_name) , OWNED_REF); - rms_tag_add_tagkey(tag , data_key , SHARED); - rms_tag_fwrite(tag , stream); - rms_tag_free(tag); - -} - - -const char *rms_tag_name_ref(const rms_tag_type * tag) { - return tag->name; -} - - diff --git a/ThirdParty/Ert/librms/src/rms_tagkey.c b/ThirdParty/Ert/librms/src/rms_tagkey.c deleted file mode 100644 index 3e0fb2ccd1..0000000000 --- a/ThirdParty/Ert/librms/src/rms_tagkey.c +++ /dev/null @@ -1,718 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_tagkey.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -static const char * rms_array_string = "array"; - -static const char rms_type_names[6][7] = {{"char\0"}, - {"float\0"}, - {"double\0"}, - {"bool\0"}, - {"byte\0"}, - {"int\0"}}; - -static const int rms_type_size[6] = {1 , 4 , 8 , 1 , 1 , 4}; /* */ - - -struct rms_tagkey_struct { - int size; - int sizeof_ctype; - int data_size; - int alloc_size; - rms_type_enum rms_type; - char *name; - void *data; - bool endian_convert; - bool shared_data; -}; - - -/*****************************************************************/ - - - -/*****************************************************************/ - - -static void rms_tagkey_assert_fnum(const rms_tagkey_type * tagkey) { - if (!(tagkey->rms_type == rms_float_type || tagkey->rms_type == rms_double_type)) { - fprintf(stderr,"%s: tried to perform numerical operataion on rms_type: %s invalid/not implemented\n",__func__ , rms_type_names[tagkey->rms_type]); - abort(); - } -} - -static void rms_tagkey_assert_fnum2(const rms_tagkey_type * tagkey1 , const rms_tagkey_type *tagkey2) { - rms_tagkey_assert_fnum(tagkey1); - rms_tagkey_assert_fnum(tagkey2); - if (tagkey1->size != tagkey2->size || tagkey1->rms_type != tagkey2->rms_type) { - fprintf(stderr,"%s: tried to combine tagkey with different size/type - aborting \n",__func__); - abort(); - } -} - - -void rms_tagkey_clear(rms_tagkey_type * tagkey) { - int i; - rms_tagkey_assert_fnum(tagkey); - switch (tagkey->rms_type) { - case(rms_double_type): - { - double *tmp = (double *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] = 0; - } - break; - case(rms_float_type): - { - float *tmp = (float *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] = 0; - } - break; - default: - fprintf(stderr,"%s: only implemented for rms_double_type and rms_float_type - aborting \n",__func__); - abort(); - } -} - - -void rms_tagkey_apply(rms_tagkey_type * tagkey , double (f) (double)) { -int i; - rms_tagkey_assert_fnum(tagkey); - switch (tagkey->rms_type) { - case(rms_double_type): - { - double *tmp = (double *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] = f(tmp[i]); - } - break; - - case(rms_float_type): - { - float *tmp = (float *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] = f(tmp[i]); - } - break; - - default: - fprintf(stderr,"%s: only implemented for rms_double_type and rms_float_type - aborting \n",__func__); - abort(); - } -} - - -void rms_tagkey_inplace_sqr(rms_tagkey_type * tagkey) { - int i; - rms_tagkey_assert_fnum(tagkey); - switch (tagkey->rms_type) { - case(rms_double_type): - { - double *tmp = (double *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] *= tmp[i]; - } - break; - - case(rms_float_type): - { - float *tmp = (float *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] *= tmp[i]; - } - break; - - default: - fprintf(stderr,"%s: only implemented for rms_double_type and rms_float_type - aborting \n",__func__); - abort(); - } -} - - -void rms_tagkey_assign(rms_tagkey_type * new, const rms_tagkey_type *src) { - memcpy(new->data , src->data , new->size * new->sizeof_ctype); -} - - -void rms_tagkey_inplace_log10(rms_tagkey_type * tagkey) { - int i; - rms_tagkey_assert_fnum(tagkey); - switch (tagkey->rms_type) { - case(rms_double_type): - { - double *tmp = (double *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] = log10(tmp[i]); - } - break; - - case(rms_float_type): - { - float *tmp = (float *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] = log10(tmp[i]); - } - break; - - default: - fprintf(stderr,"%s: only implemented for rms_double_type and rms_float_type - aborting \n",__func__); - abort(); - } -} - - -void rms_tagkey_inplace_sqrt(rms_tagkey_type * tagkey) { - int i; - rms_tagkey_assert_fnum(tagkey); - switch (tagkey->rms_type) { - case(rms_double_type): - { - double *tmp = (double *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] = sqrt(util_double_max(0.0 , tmp[i])); - } - break; - - case(rms_float_type): - { - float *tmp = (float *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] = sqrtf(util_float_max(0.0 , tmp[i])); - } - break; - - default: - fprintf(stderr,"%s: only implemented for rms_double_type and rms_float_type - aborting \n",__func__); - abort(); - } -} - - -void rms_tagkey_scale(rms_tagkey_type * tagkey , double scale_factor) { - int i; - rms_tagkey_assert_fnum(tagkey); - switch (tagkey->rms_type) { - case(rms_double_type): - { - double *tmp = (double *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] *= scale_factor; - } - break; - - case(rms_float_type): - { - float *tmp = (float *) tagkey->data; - for (i=0; i < tagkey->size; i++) - tmp[i] *= scale_factor; - } - break; - - default: - fprintf(stderr,"%s: only implemented for rms_double_type and rms_float_type - aborting \n",__func__); - abort(); - } -} - - -void rms_tagkey_inplace_add(rms_tagkey_type * tagkey , const rms_tagkey_type *delta) { - int i; - rms_tagkey_assert_fnum2(tagkey , delta); - switch (tagkey->rms_type) { - case(rms_double_type): - { - double *tmp1 = (double *) tagkey->data; - const double *tmp2 = (const double *) delta->data; - for (i=0; i < tagkey->size; i++) - tmp1[i] += tmp2[i]; - } - break; - - case(rms_float_type): - { - float *tmp1 = (float *) tagkey->data; - const float *tmp2 = (const float *) delta->data; - for (i=0; i < tagkey->size; i++) - tmp1[i] += tmp2[i]; - } - break; - - default: - fprintf(stderr,"%s: only implemented for rms_double_type and rms_float_type - aborting \n",__func__); - abort(); - } -} - - -void rms_tagkey_inplace_add_scaled(rms_tagkey_type * tagkey , const rms_tagkey_type *delta, double factor) { - int i; - rms_tagkey_assert_fnum2(tagkey , delta); - switch (tagkey->rms_type) { - case(rms_double_type): - { - double *tmp1 = (double *) tagkey->data; - const double *tmp2 = (const double *) delta->data; - for (i=0; i < tagkey->size; i++) - tmp1[i] += tmp2[i] * factor; - } - break; - - case(rms_float_type): - { - float *tmp1 = (float *) tagkey->data; - const float *tmp2 = (const float *) delta->data; - for (i=0; i < tagkey->size; i++) - tmp1[i] += tmp2[i] * factor; - } - break; - - default: - fprintf(stderr,"%s: only implemented for rms_double_type and rms_float_type - aborting \n",__func__); - abort(); - } -} - - -void rms_tagkey_inplace_mul(rms_tagkey_type * tagkey , const rms_tagkey_type *delta) { - int i; - rms_tagkey_assert_fnum2(tagkey , delta); - switch (tagkey->rms_type) { - case(rms_double_type): - { - double *tmp1 = (double *) tagkey->data; - const double *tmp2 = (const double *) delta->data; - for (i=0; i < tagkey->size; i++) - tmp1[i] *= tmp2[i]; - } - break; - - case(rms_float_type): - { - float *tmp1 = (float *) tagkey->data; - const float *tmp2 = (const float *) delta->data; - for (i=0; i < tagkey->size; i++) - tmp1[i] *= tmp2[i]; - } - break; - - default: - fprintf(stderr,"%s: only implemented for rms_double_type and rms_float_type - aborting \n",__func__); - abort(); - } -} - - -#define TAGKEY_MAX_MIN(type) \ -{ \ - type * data = rms_tagkey_get_data_ref(tagkey); \ - type max = -data[0]; \ - type min = data[0]; \ - int i; \ - for (i=1; i < tagkey->size; i++) \ - util_update_ ## type ## _max_min(data[i] , &max , &min); \ - memcpy(_max , &max , tagkey->sizeof_ctype); \ - memcpy(_min , &min , tagkey->sizeof_ctype); \ -} - - - -void rms_tagkey_max_min(const rms_tagkey_type * tagkey , void * _max , void *_min) { - switch (tagkey->rms_type) { - case(rms_float_type): - TAGKEY_MAX_MIN(float); - break; - case(rms_double_type): - TAGKEY_MAX_MIN(double); - break; - case(rms_int_type): - TAGKEY_MAX_MIN(int); - break; - default: - fprintf(stderr,"%s: invalid type for element sum \n",__func__); - abort(); - } -} - -#undef TAGKEY_MAX_MIN - - - - - -void rms_tagkey_free_(void *_tagkey) { - rms_tagkey_type * tagkey = (rms_tagkey_type *) _tagkey; - rms_tagkey_free(tagkey); -} - - -static void rms_tagkey_alloc_data(rms_tagkey_type *tagkey) { - if (!tagkey->shared_data) { - - if (tagkey->data_size > tagkey->alloc_size) { - void *tmp = realloc(tagkey->data , tagkey->data_size); - if (tmp == NULL) { - fprintf(stderr,"%s: failed to allocate: %d bytes of storage - aborting \n",__func__ , tagkey->data_size); - abort(); - } - tagkey->data = tmp; - tagkey->alloc_size = tagkey->data_size; - - } - } -} - - - - -rms_tagkey_type * rms_tagkey_copyc(const rms_tagkey_type *tagkey) { - rms_tagkey_type *new_tagkey = rms_tagkey_alloc_empty(tagkey->endian_convert); - - new_tagkey->alloc_size = 0; - new_tagkey->size = tagkey->size; - new_tagkey->sizeof_ctype = tagkey->sizeof_ctype; - new_tagkey->data_size = tagkey->data_size; - new_tagkey->rms_type = tagkey->rms_type; - new_tagkey->data = NULL; - new_tagkey->shared_data = tagkey->shared_data; - - rms_tagkey_alloc_data(new_tagkey); - memcpy(new_tagkey->data , tagkey->data , tagkey->data_size); - new_tagkey->name = util_alloc_string_copy(tagkey->name); - return new_tagkey; -} - - -void * rms_tagkey_copyc_(const void * _tagkey) { - const rms_tagkey_type * tagkey = (const rms_tagkey_type *) _tagkey; - return rms_tagkey_copyc(tagkey); -} - - -static void rms_tagkey_set_data_size(rms_tagkey_type *tagkey , FILE *stream , int strlen) { - - if (tagkey->rms_type == rms_char_type) { - if (stream != NULL) { - const long int init_pos = util_ftell(stream); - int i; - for (i=0; i < tagkey->size; i++) - rms_util_fskip_string(stream); - tagkey->data_size = util_ftell(stream) - init_pos; - util_fseek(stream , init_pos , SEEK_SET); - } else - tagkey->data_size = strlen + 1; - } else - tagkey->data_size = tagkey->size * tagkey->sizeof_ctype; -} - - - -static void rms_tagkey_fread_data(rms_tagkey_type *tagkey , bool endian_convert , FILE *stream) { - if (tagkey->alloc_size < tagkey->data_size) { - fprintf(stderr,"%s: fatal error buffer to small - aborting \n",__func__); - abort(); - } - - int bytes_read = fread(tagkey->data , 1 , tagkey->data_size , stream); - if (bytes_read != tagkey->data_size) { - fprintf(stderr,"%s: failed to read %d bytes - premature EOF? \n",__func__ , tagkey->data_size); - fprintf(stderr,"%s: tagkey: %s \n",__func__ , tagkey->name); - abort(); - } - if (endian_convert) - if (tagkey->sizeof_ctype > 1) - util_endian_flip_vector(tagkey->data , tagkey->sizeof_ctype , tagkey->size); -} - -void rms_tagkey_manual_realloc_data(rms_tagkey_type * tagkey , int data_size) { - tagkey->data_size = data_size; - rms_tagkey_alloc_data(tagkey); -} - -void rms_tagkey_set_data(rms_tagkey_type * tagkey , const void * data) { - if (tagkey->shared_data) - tagkey->data = (void *) data; - else - memcpy(tagkey->data , data , tagkey->data_size); -} - - - - -static void rms_fread_tagkey_header(rms_tagkey_type *tagkey , FILE *stream, hash_type *type_map) { - bool is_array; - char type_string[7]; - - rms_util_fread_string(type_string , 7 , stream); - if (strcmp(type_string , rms_array_string) == 0) { - is_array = true; - rms_util_fread_string(type_string , 7 , stream); - } else - is_array = false; - - { - __rms_type * rms_t = hash_get(type_map , type_string); - tagkey->rms_type = rms_t->rms_type; - tagkey->sizeof_ctype = rms_t->sizeof_ctype; - } - - tagkey->name = realloc(tagkey->name , rms_util_fread_strlen(stream) + 1); - - rms_util_fread_string(tagkey->name , 0 , stream); - if (is_array) - fread(&tagkey->size , 1 , sizeof tagkey->size, stream); - else - tagkey->size = 1; - rms_tagkey_set_data_size(tagkey , stream , -1); -} - - - -static void rms_fread_realloc_tagkey(rms_tagkey_type *tagkey , bool endian_convert , FILE *stream , hash_type *type_map) { - - rms_fread_tagkey_header(tagkey , stream , type_map); - rms_tagkey_alloc_data(tagkey); - rms_tagkey_fread_data(tagkey , endian_convert , stream); - -} - - - -static void rms_tagkey_fwrite_data(const rms_tagkey_type * tagkey , FILE *stream) { - int elm = fwrite(tagkey->data , 1 , tagkey->data_size , stream); - if (elm != tagkey->data_size) { - fprintf(stderr,"%s: failed to write %d bytes to file [tagkey:%s] - aborting \n",__func__ , tagkey->data_size , tagkey->name); - abort(); - } -} - - -void rms_tagkey_fwrite(const rms_tagkey_type * tagkey , FILE *stream) { - if (tagkey->size > 1) - rms_util_fwrite_string("array" , stream); - rms_util_fwrite_string(rms_type_names[tagkey->rms_type] , stream); - rms_util_fwrite_string(tagkey->name , stream); - if (tagkey->size > 1) { - fwrite(&tagkey->size , sizeof tagkey->size , 1 , stream); - rms_util_fwrite_newline(stream); - } - rms_tagkey_fwrite_data(tagkey , stream); -} - -void rms_tagkey_fprintf(const rms_tagkey_type * tagkey, FILE *stream) { - fprintf(stream," <%s> %6d %s",tagkey->name , tagkey->size , rms_type_names[tagkey->rms_type]); - if (tagkey->size == 1) { - if (tagkey->rms_type == rms_int_type) - fprintf(stream, " = %d ",(( int *) tagkey->data)[0]); - else if (tagkey->rms_type == rms_char_type) - fprintf(stream, " = %s ",( char *) tagkey->data); - } - fprintf(stream,"\n"); -} - - -const char * rms_tagkey_get_name(const rms_tagkey_type *tagkey) { - return tagkey->name; -} - -void * rms_tagkey_get_data_ref(const rms_tagkey_type *tagkey) { - return tagkey->data; -} - - -void rms_tagkey_load(rms_tagkey_type *tagkey , bool endian_convert , FILE *stream, hash_type *type_map) { - rms_fread_realloc_tagkey(tagkey , endian_convert , stream , type_map); -} - - -bool rms_tagkey_char_eq(const rms_tagkey_type *tagkey , const char *keyvalue) { - bool eq = false; - if (tagkey->rms_type == rms_char_type) { - if (strcmp(keyvalue , tagkey->data) == 0) - eq = true; - } - return eq; -} - - -rms_tagkey_type * rms_tagkey_alloc_empty(bool endian_convert) { - - rms_tagkey_type *tagkey = malloc(sizeof *tagkey); - tagkey->alloc_size = 0; - tagkey->data_size = 0; - tagkey->size = 0; - tagkey->name = NULL; - tagkey->data = NULL; - tagkey->endian_convert = endian_convert; - tagkey->shared_data = false; - - return tagkey; - -} - - -static rms_tagkey_type * rms_tagkey_alloc_initialized(const char * name , int size , rms_type_enum rms_type , bool endian_convert) { - rms_tagkey_type *tagkey = rms_tagkey_alloc_empty(endian_convert); - tagkey->size = size; - tagkey->rms_type = rms_type; - tagkey->sizeof_ctype = rms_type_size[rms_type]; - tagkey->data_size = tagkey->size * tagkey->sizeof_ctype; - tagkey->name = util_alloc_string_copy(name); - return tagkey; -} - - -rms_tagkey_type * rms_tagkey_alloc_complete(const char * name , int size , rms_type_enum rms_type , const void * data , bool shared_data) { - rms_tagkey_type * tag = rms_tagkey_alloc_initialized(name , size , rms_type , false); - tag->shared_data = shared_data; - - rms_tagkey_alloc_data(tag); - rms_tagkey_set_data(tag , data); - - return tag; -} - - -int rms_tagkey_get_sizeof_ctype(const rms_tagkey_type * key) { - return key->sizeof_ctype; -} - - -rms_type_enum rms_tagkey_get_rms_type(const rms_tagkey_type * key) { - return key->rms_type; -} - - -ecl_type_enum rms_tagkey_get_ecl_type(const rms_tagkey_type * key) { - ecl_type_enum ecl_type; - switch (key->rms_type) { - case(rms_float_type): - ecl_type = ECL_FLOAT_TYPE; - break; - case(rms_double_type): - ecl_type = ECL_DOUBLE_TYPE; - break; - case(rms_int_type): - ecl_type = ECL_INT_TYPE; - break; - default: - fprintf(stderr,"%s: sorry rms_type: %d not implemented - aborting \n",__func__ , key->rms_type); - abort(); - } - return ecl_type; -} - - - - -void rms_tagkey_free(rms_tagkey_type *tagkey) { - if (tagkey->name != NULL) free(tagkey->name); - - if (!tagkey->shared_data) - if (tagkey->data != NULL) free(tagkey->data); - - free(tagkey); -} - - -rms_tagkey_type * rms_tagkey_alloc_byteswap() { - rms_tagkey_type *tagkey = rms_tagkey_alloc_initialized("byteswaptest" , 1 , rms_int_type , false); - rms_tagkey_alloc_data(tagkey); - ((int *) tagkey->data)[0] = 1; - return tagkey; -} - - -rms_tagkey_type * rms_tagkey_alloc_filetype(const char * filetype) { - rms_tagkey_type *tagkey = rms_tagkey_alloc_initialized("filetype" , 1 , rms_char_type , false); - rms_tagkey_set_data_size(tagkey , NULL , strlen(filetype)); - rms_tagkey_alloc_data(tagkey); - sprintf(tagkey->data , "%s" , filetype); - return tagkey; -} - - -rms_tagkey_type * rms_tagkey_alloc_parameter_name(const char * parameter_name) { - rms_tagkey_type *tagkey = rms_tagkey_alloc_initialized("name" , 1 , rms_char_type , false); - rms_tagkey_set_data_size(tagkey , NULL , strlen(parameter_name)); - rms_tagkey_alloc_data(tagkey); - sprintf(tagkey->data , "%s" , parameter_name); - return tagkey; -} - - -rms_tagkey_type * rms_tagkey_alloc_creationDate() { - const int len = strlen("08/05/2007 08:31:39"); - struct tm ts; - time_t now; - rms_tagkey_type *tagkey = rms_tagkey_alloc_initialized("creationDate" , 1 , rms_char_type , false); - - now = time(NULL); - localtime_r(&now , &ts); - - rms_tagkey_set_data_size(tagkey , NULL , len); - rms_tagkey_alloc_data(tagkey); - sprintf(tagkey->data , "%02d/%02d/%4d %02d:%02d:%02d" , - ts.tm_mday, - ts.tm_mon, - ts.tm_year + 1900, - ts.tm_hour, - ts.tm_min, - ts.tm_sec); - - return tagkey; -} - - -rms_tagkey_type * rms_tagkey_alloc_dim(const char * dim, int value) { - rms_tagkey_type *tagkey = rms_tagkey_alloc_initialized(dim , 1 , rms_int_type , false); - rms_tagkey_alloc_data(tagkey); - ((int *) tagkey->data)[0] = value; - return tagkey; -} - - -int rms_tagkey_get_size(const rms_tagkey_type * tagkey) { return tagkey->size; } - - -/** - This function will compare two tagkeys, and return true if they are - equal. If they differ in size/type/... or other fundamental ways a - false is immediately returned. -*/ - -bool rms_tagkey_cmp(const rms_tagkey_type * tagkey1 , const rms_tagkey_type * tagkey2) { - if (tagkey1->size != tagkey2->size) return false; - if (tagkey1->rms_type != tagkey2->rms_type) return false; - if (memcmp(tagkey1->data , tagkey1->data , tagkey1->size * tagkey1->sizeof_ctype) == 0) - return true; - else - return false; -} diff --git a/ThirdParty/Ert/librms/src/rms_type.c b/ThirdParty/Ert/librms/src/rms_type.c deleted file mode 100644 index 5d3e44a744..0000000000 --- a/ThirdParty/Ert/librms/src/rms_type.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_type.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -/*****************************************************************/ -/* A microscopic (purely internal) type object only used - for storing the hash type_map */ -/*****************************************************************/ - - - - -void rms_type_free(void *rms_t) { - free( (__rms_type *) rms_t); -} - - -static __rms_type * rms_type_set(__rms_type *rms_t , rms_type_enum rms_type , int sizeof_ctype) { - rms_t->rms_type = rms_type; - rms_t->sizeof_ctype = sizeof_ctype; - return rms_t; -} - - -__rms_type * rms_type_alloc(rms_type_enum rms_type, int sizeof_ctype) { - __rms_type *rms_t = malloc(sizeof *rms_t); - rms_type_set(rms_t , rms_type , sizeof_ctype); - return rms_t; -} - - -const void * rms_type_copyc(const void *__rms_t) { - const __rms_type *rms_t = (const __rms_type *) __rms_t; - __rms_type *new_t = rms_type_alloc(rms_t->rms_type , rms_t->sizeof_ctype); - return new_t; -} diff --git a/ThirdParty/Ert/librms/src/rms_util.c b/ThirdParty/Ert/librms/src/rms_util.c deleted file mode 100644 index 16dd6533bd..0000000000 --- a/ThirdParty/Ert/librms/src/rms_util.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'rms_util.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include - -#include - -#include - - - - -/* - This translates from the RMS data layout to "Fortan / ECLIPSE" data - layout. - - RMS: k index is running fastest *AND* backwards. - F90: i is running fastest, and k is running the 'normal' way. - - This function should be *THE ONLY* place in the code where explicit mention - is made to the RMS ordering sequence. -*/ - - -int rms_util_global_index_from_eclipse_ijk(int nx, int ny , int nz , int i , int j , int k) { - return i*ny*nz + j*nz + (nz - k - 1); -} - - - -void rms_util_set_fortran_data(void *_f90_data , const void * _rms_data, int sizeof_ctype , int nx, int ny , int nz) { - char *f90_data = (char *) _f90_data; - const char *rms_data = (const char *) _rms_data; - int i,j,k,rms_index, f90_index; - for (i=0; i < nx; i++) - for (j=0; j < ny; j++) - for (k= 0; k < nz; k++) { - rms_index = rms_util_global_index_from_eclipse_ijk(nx,ny,nz,i,j,k); - f90_index = i + j*nx + k*nx*ny; - memcpy(&f90_data[f90_index * sizeof_ctype] , &rms_data[rms_index * sizeof_ctype] , sizeof_ctype); - } -} - - - -void rms_util_read_fortran_data(const void *_f90_data , void * _rms_data, int sizeof_ctype , int nx, int ny , int nz) { - const char *f90_data = (const char *) _f90_data; - char *rms_data = (char *) _rms_data; - int i,j,k,rms_index, f90_index; - - for (i=0; i < nx; i++) - for (j=0; j < ny; j++) - for (k= 0; k < nz; k++) { - rms_index = rms_util_global_index_from_eclipse_ijk(nx,ny,nz,i,j,k); - f90_index = i + j*nx + k*nx*ny; - memcpy(&rms_data[rms_index * sizeof_ctype] , &f90_data[f90_index * sizeof_ctype] , sizeof_ctype); - } -} - - - -void rms_util_translate_undef(void * _data , int size , int sizeof_ctype , const void * old_undef , const void * new_undef) { - char * data = (char *) _data; - int i; - for (i=0; i < size; i++) { - if (memcmp( &data[i*sizeof_ctype] , old_undef , sizeof_ctype) == 0) - memcpy( &data[i*sizeof_ctype] , new_undef , sizeof_ctype); - } -} - - -void rms_util_fskip_string(FILE *stream) { - char c; - bool cont = true; - while (cont) { - fread(&c , 1 , 1 , stream); - if (c == 0) - cont = false; - } -} - - -int rms_util_fread_strlen(FILE *stream) { - long int init_pos = util_ftell(stream); - int len; - rms_util_fskip_string(stream); - len = util_ftell(stream) - init_pos; - util_fseek(stream , init_pos , SEEK_SET); - return len; -} - - -/* - max_length *includes* the trailing \0. -*/ -bool rms_util_fread_string(char *string , int max_length , FILE *stream) { - bool read_ok = true; - bool cont = true; - long int init_pos = util_ftell(stream); - int pos = 0; - while (cont) { - fread(&string[pos] , sizeof *string , 1 , stream); - if (string[pos] == 0) { - read_ok = true; - cont = false; - } else { - pos++; - if (max_length > 0) { - if (pos == max_length) { - read_ok = false; - util_fseek(stream , init_pos , SEEK_SET); - cont = false; - } - } - } - } - - return read_ok; -} - - -void rms_util_fwrite_string(const char * string , FILE *stream) { - fwrite(string , sizeof * string , strlen(string) , stream); - fputc('\0' , stream); -} - -void rms_util_fwrite_comment(const char * comment , FILE *stream) { - fputc('#' , stream); - fwrite(comment , sizeof * comment , strlen(comment) , stream); - fputc('#' , stream); - fputc('\0' , stream); -} - - -void rms_util_fwrite_newline(FILE *stream) { - return; -} - - -rms_type_enum rms_util_convert_ecl_type(ecl_type_enum ecl_type) { - rms_type_enum rms_type = rms_int_type; /* Shut up the compiler */ - switch (ecl_type) { - case(ECL_INT_TYPE): - rms_type = rms_int_type; - break; - case(ECL_FLOAT_TYPE): - rms_type = rms_float_type; - break; - case(ECL_DOUBLE_TYPE): - rms_type = rms_double_type; - break; - default: - util_abort("%s: Conversion ecl_type -> rms_type not supported for ecl_type:%s \n",__func__ , ecl_util_get_type_name(ecl_type)); - } - return rms_type; -} - - diff --git a/ThirdParty/Ert/librms/tests/CMakeLists.txt b/ThirdParty/Ert/librms/tests/CMakeLists.txt deleted file mode 100644 index 1e296b020f..0000000000 --- a/ThirdParty/Ert/librms/tests/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -if (STATOIL_TESTDATA_ROOT) - - add_executable( rms_file_test rms_file_test.c ) - target_link_libraries( rms_file_test rms test_util ) - - add_test( rms_file_test - ${EXECUTABLE_OUTPUT_PATH}/rms_file_test - ${PROJECT_SOURCE_DIR}/test-data/Statoil/config/rms_file_test/rms_file) - - set_property( TEST rms_file_test PROPERTY LABELS StatoilData ) - -endif() \ No newline at end of file diff --git a/ThirdParty/Ert/librms/tests/rms_file_test.c b/ThirdParty/Ert/librms/tests/rms_file_test.c deleted file mode 100644 index adbdc0ba1e..0000000000 --- a/ThirdParty/Ert/librms/tests/rms_file_test.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2014 Statoil ASA, Norway. - - The file 'rms_file_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include -#include -#include - -#include -#include - -#include -#include - - - -void test_rms_file_fread_alloc_data_tag(rms_file_type * rms_file) { - rms_tag_type * parameter_tag = rms_file_fread_alloc_tag(rms_file , "parameter" , NULL , NULL); - test_assert_not_NULL(parameter_tag); - test_assert_string_equal("parameter", rms_tag_get_name(parameter_tag)); - rms_tag_free(parameter_tag); -} - - -void test_rms_file_fread_alloc_data_tagkey(rms_file_type *rms_file) { - rms_tagkey_type * name_tagkey = rms_file_fread_alloc_data_tagkey(rms_file , "parameter" , NULL , NULL); - test_assert_not_NULL(name_tagkey); - test_assert_int_equal(rms_float_type, rms_tagkey_get_rms_type(name_tagkey)); - rms_tagkey_free(name_tagkey); -} - - -int main(int argc , char ** argv) { - const char * filename = argv[1]; - rms_file_type * rms_file = rms_file_alloc(filename , false); - test_assert_not_NULL(rms_file); - - test_rms_file_fread_alloc_data_tag(rms_file); - test_rms_file_fread_alloc_data_tagkey(rms_file); - - rms_file_free(rms_file); - exit(0); -} diff --git a/ThirdParty/Ert/libsched/CMakeLists.txt b/ThirdParty/Ert/libsched/CMakeLists.txt deleted file mode 100644 index 3edab07684..0000000000 --- a/ThirdParty/Ert/libsched/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_subdirectory( src ) -if (BUILD_APPLICATONS) - add_subdirectory( applications ) -endif() - -if (BUILD_TESTS) - add_subdirectory( tests ) -endif() diff --git a/ThirdParty/Ert/libsched/applications/CMakeLists.txt b/ThirdParty/Ert/libsched/applications/CMakeLists.txt deleted file mode 100644 index 83f41113b9..0000000000 --- a/ThirdParty/Ert/libsched/applications/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -link_directories( ${ERT_BINARY_DIR}/libsched/src ) - -include_directories( ${libutil_build_path} ) -include_directories( ${libutil_src_path} ) -include_directories( ${libsched_src_path} ) -include_directories( ${libecl_src_path} ) - -add_executable( sched_summary.x sched_summary.c ) - -set(program_list sched_summary.x) -foreach(prog ${program_list}) - target_link_libraries( ${prog} sched ecl ert_util ) - if (USE_RUNPATH) - add_runpath( ${prog} ) - endif() - #----------------------------------------------------------------- - if (SCHED_INSTALL_PREFIX) - set (destination ${SCHED_INSTALL_PREFIX}/bin) - else() - set (destination bin) - endif() - - if (INSTALL_ERT) - install(TARGETS ${prog} DESTINATION ${destination}) - if (INSTALL_GROUP) - install(CODE "EXECUTE_PROCESS(COMMAND chgrp ${INSTALL_GROUP} ${destination}/${prog})") - install(CODE "EXECUTE_PROCESS(COMMAND chmod g+w ${destination}/${prog})") - endif() - endif() -endforeach() diff --git a/ThirdParty/Ert/libsched/applications/get_well_list.c b/ThirdParty/Ert/libsched/applications/get_well_list.c deleted file mode 100644 index 1d5e9aec4e..0000000000 --- a/ThirdParty/Ert/libsched/applications/get_well_list.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'get_well_list.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include - -int main(int argc, char **argv) -{ - if(argc < 2) - { - printf("Usage: get_well_list.x my_sched_file.SCH\n"); - return 0; - } - - int num_wells; - char ** well_list; - - sched_file_type * sched_file = NULL; - history_type * history = NULL; - - - sched_file = sched_file_alloc(-1); - sched_file_parse(sched_file, -1 , argv[1]); - - - history = history_alloc_from_sched_file(sched_file); - - well_list = history_alloc_well_list(history, &num_wells); - - for(int well_nr = 0; well_nr < num_wells; well_nr++) - printf("%s\n", well_list[well_nr]); - - history_free(history); - sched_file_free(sched_file); - util_free_stringlist(well_list, num_wells); - - return 0; -} diff --git a/ThirdParty/Ert/libsched/applications/gruptree_test.c b/ThirdParty/Ert/libsched/applications/gruptree_test.c deleted file mode 100644 index 06fc7eed27..0000000000 --- a/ThirdParty/Ert/libsched/applications/gruptree_test.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gruptree_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include - -int main() -{ - gruptree_type * gruptree = gruptree_alloc(); - gruptree_register_grup(gruptree, "INJE", "FIELD"); - gruptree_register_well(gruptree, "WI1" , "INJE"); - gruptree_register_well(gruptree, "WI2" , "INJE"); - gruptree_register_well(gruptree, "WI3" , "INJE"); - gruptree_register_well(gruptree, "WI4" , "INJE"); - - gruptree_register_grup(gruptree, "PLATA", "FIELD"); - gruptree_register_grup(gruptree, "INJE", "PLATA"); - gruptree_register_grup(gruptree, "PROD", "PLATA"); - gruptree_register_well(gruptree, "WP1", "PROD"); - gruptree_register_well(gruptree, "WP2", "PROD"); - gruptree_register_well(gruptree, "WP3", "PROD"); - gruptree_register_well(gruptree, "WP4", "PROD"); - gruptree_register_well(gruptree, "WP5", "PROD"); - - gruptree_register_grup(gruptree, "PLATB", "FIELD"); - gruptree_register_well(gruptree, "WPB1", "PLATB"); - - gruptree_printf_grup_wells(gruptree, "FIELD"); - gruptree_printf_grup_wells(gruptree, "PLATA"); - gruptree_printf_grup_wells(gruptree, "PLATB"); - gruptree_printf_grup_wells(gruptree, "INJE"); - gruptree_printf_grup_wells(gruptree, "PROD"); - - printf("Letting PLATB be a subgroup of PLATA.\n"); - gruptree_register_grup(gruptree, "PLATB", "PLATA"); - gruptree_register_well(gruptree, "SVADA", "FIELD"); - - gruptree_printf_grup_wells(gruptree, "PLATA"); - gruptree_printf_grup_wells(gruptree, "FIELD"); - - printf("Trying to copy the gruptree...\n"); - gruptree_type * gruptree_cpy = gruptree_copyc(gruptree); - - printf("Freeing the old gruptree..\n"); - gruptree_free(gruptree); - - printf("Trying to access new gruptree..\n"); - gruptree_printf_grup_wells(gruptree_cpy, "FIELD"); - gruptree_printf_grup_wells(gruptree_cpy, "PLATA"); - gruptree_printf_grup_wells(gruptree_cpy, "INJE"); - - printf("Writing gruptree to disk..\n"); - FILE * stream = util_fopen("gruptree_stor.bin", "w"); - gruptree_fwrite(gruptree_cpy, stream); - - printf("Closing stream and free'ing gruptre..\n"); - fclose(stream); - gruptree_free(gruptree_cpy); - - printf("Reading gruptree from disk, hang on to yer helmet..\n"); - stream = util_fopen("gruptree_stor.bin", "r"); - gruptree = gruptree_fread_alloc(stream); - fclose(stream); - - printf("Trying to access new gruptree..\n"); - gruptree_printf_grup_wells(gruptree, "FIELD"); - gruptree_printf_grup_wells(gruptree, "PLATA"); - gruptree_printf_grup_wells(gruptree, "INJE"); - - printf("Cleaning up..\n"); - gruptree_free(gruptree); - - - return 0; -} diff --git a/ThirdParty/Ert/libsched/applications/perturb_history/group_rate.c b/ThirdParty/Ert/libsched/applications/perturb_history/group_rate.c deleted file mode 100644 index 71557b6664..0000000000 --- a/ThirdParty/Ert/libsched/applications/perturb_history/group_rate.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'group_rate.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define GROUP_RATE_ID 6681055 - - -struct group_rate_struct { - UTIL_TYPE_ID_DECLARATION; - char * name; - bool producer; - double_vector_type * base_rate; - double_vector_type * shift; - double_vector_type * min_shift; - double_vector_type * max_shift; - stringlist_type * min_shift_string; - stringlist_type * max_shift_string; - sched_phase_enum phase; - const time_t_vector_type * time_vector; - vector_type * well_rates; - const sched_history_type * sched_history; -}; - - - -void group_rate_update_wconhist( group_rate_type * group_rate , sched_kw_wconhist_type * kw, int restart_nr ) { - int well_nr; - for (well_nr = 0; well_nr < vector_get_size( group_rate->well_rates ); well_nr++) { - well_rate_type * well_rate = vector_iget( group_rate->well_rates , well_nr ); - well_rate_update_wconhist( well_rate ,kw , restart_nr ); - } -} - - -void group_rate_update_wconinje( group_rate_type * group_rate , sched_kw_wconinje_type * kw, int restart_nr ) { - int well_nr; - for (well_nr = 0; well_nr < vector_get_size( group_rate->well_rates ); well_nr++) { - well_rate_type * well_rate = vector_iget( group_rate->well_rates , well_nr ); - well_rate_update_wconinje( well_rate ,kw , restart_nr ); - } -} - - - - - -group_rate_type * group_rate_alloc(const sched_history_type * sched_history , const time_t_vector_type * time_vector , const char * name , const char * phase , const char * type_string , const char * filename) { - group_rate_type * group_rate = util_malloc( sizeof * group_rate , __func__); - UTIL_TYPE_ID_INIT( group_rate , GROUP_RATE_ID ); - group_rate->name = util_alloc_string_copy( name ); - group_rate->time_vector = time_vector; - group_rate->shift = double_vector_alloc(0,0); - group_rate->base_rate = double_vector_alloc(0,0); - group_rate->min_shift = double_vector_alloc(0 , 0); - group_rate->max_shift = double_vector_alloc(0 , 0); - group_rate->min_shift_string = stringlist_alloc_new(); - group_rate->max_shift_string = stringlist_alloc_new(); - group_rate->phase = sched_phase_type_from_string( phase ); - group_rate->sched_history = sched_history; - { - if (strcmp( type_string , "INJECTOR") == 0) - group_rate->producer = false; - else if ( strcmp( type_string , "PRODUCER") == 0) - group_rate->producer = true; - } - - fscanf_2ts( time_vector , filename , group_rate->min_shift_string , group_rate->max_shift_string ); - group_rate->well_rates = vector_alloc_new(); - return group_rate; -} - - -void group_rate_init( group_rate_type * group_rate ) { - - for (int iw = 0; iw < vector_get_size( group_rate->well_rates ); iw++) { - const well_rate_type * well_rate = vector_iget( group_rate->well_rates , iw ); - for (int tstep = 0; tstep < well_rate_get_length( well_rate ); tstep++) - double_vector_iadd( group_rate->base_rate , tstep , well_rate_iget_rate( well_rate , tstep )); - } - - for (int i = 0; i < stringlist_get_size( group_rate->min_shift_string ); i++) { - double_vector_iset( group_rate->min_shift , i , sscanfp( double_vector_safe_iget( group_rate->base_rate , i ) , stringlist_iget( group_rate->min_shift_string , i))); - double_vector_iset( group_rate->max_shift , i , sscanfp( double_vector_safe_iget( group_rate->base_rate , i ) , stringlist_iget( group_rate->max_shift_string , i))); - } - -} - - - - - - -static UTIL_SAFE_CAST_FUNCTION( group_rate , GROUP_RATE_ID ); - -void group_rate_free( group_rate_type * group_rate ) { - free( group_rate->name ); - double_vector_free( group_rate->shift ); - double_vector_free( group_rate->base_rate ); - double_vector_free( group_rate->min_shift ); - double_vector_free( group_rate->max_shift ); - vector_free( group_rate->well_rates ); - free( group_rate ); -} - - -void group_rate_free__( void * arg ) { - group_rate_type * group_rate = group_rate_safe_cast( arg ); - group_rate_free( group_rate ); -} - - - -bool group_rate_is_producer( const group_rate_type * group_rate ) { - return group_rate->producer; -} - -sched_phase_enum group_rate_get_phase( const group_rate_type * group_rate ) { - return group_rate->phase; -} - - -const char * group_rate_get_name( const group_rate_type * group_rate ) { - return group_rate->name; -} - - -double_vector_type * group_rate_get_shift( group_rate_type * group_rate ) { - return group_rate->shift; -} - - -void group_rate_add_well_rate( group_rate_type * group_rate , well_rate_type * well_rate) { - if (well_rate_get_phase( well_rate ) == group_rate->phase) { - char * key = util_alloc_sprintf("%s:%s" , well_rate_get_name( well_rate ) , sched_phase_type_string( group_rate->phase )); - vector_append_owned_ref( group_rate->well_rates , well_rate , well_rate_free__ ); - free( key ); - } -} - - - - -void group_rate_sample( group_rate_type * group_rate ) { - int length = time_t_vector_size( group_rate->time_vector ); - double * group_shift = util_malloc( length * sizeof * group_shift , __func__); - int * well_count = util_malloc( length * sizeof * well_count , __func__); - int num_wells = vector_get_size( group_rate->well_rates ); - int i,well_nr; - - for (i = 0; i < length; i++) { - group_shift[i] = 0; - well_count[i] = 0; - } - - for (well_nr=0; well_nr < num_wells; well_nr++) { - well_rate_type * well_rate = vector_iget( group_rate->well_rates , well_nr ); - well_rate_sample_shift( well_rate ); - { - const double * well_shift = double_vector_get_ptr( well_rate_get_shift( well_rate )); - for (i = 0; i < length; i++) { - group_shift[i] += well_shift[i]; - if (well_rate_well_open( well_rate , i )) - well_count[i] += 1; - } - } - } - - { - for (i = 0; i < length; i++) { - if (group_shift[i] > double_vector_iget( group_rate->max_shift , i)) { - double adjustment = -(group_shift[i] - double_vector_iget(group_rate->max_shift , i)) / well_count[i]; - for (well_nr = 0; well_nr < num_wells; well_nr++) { - well_rate_type * well_rate = vector_iget( group_rate->well_rates , well_nr ); - well_rate_ishift( well_rate , i , adjustment ); - } - } else if (group_shift[i] < double_vector_iget( group_rate->min_shift , i )) { - double adjustment = -(group_shift[i] - double_vector_iget(group_rate->min_shift , i)) / well_count[i]; - for (well_nr = 0; well_nr < num_wells; well_nr++) { - well_rate_type * well_rate = vector_iget( group_rate->well_rates , well_nr ); - well_rate_ishift( well_rate , i , adjustment ); - } - } - } - } - - - - free( well_count ); - free( group_shift ); - -} diff --git a/ThirdParty/Ert/libsched/applications/perturb_history/group_rate.h b/ThirdParty/Ert/libsched/applications/perturb_history/group_rate.h deleted file mode 100644 index d38e899909..0000000000 --- a/ThirdParty/Ert/libsched/applications/perturb_history/group_rate.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'group_rate.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GROUP_RATE_H -#define ERT_GROUP_RATE_H - -#include -#include -#include -#include - -typedef struct group_rate_struct group_rate_type; -group_rate_type * group_rate_alloc(const sched_history_type * sched_history , const time_t_vector_type * time_vector , const char * name , const char * phase, const char * type_string , const char * filename); -void group_rate_free__( void * arg ); -void group_rate_add_well_rate( group_rate_type * group_rate , well_rate_type * well_rate); -sched_phase_enum group_rate_get_phase( const group_rate_type * group_rate ); -void group_rate_sample( group_rate_type * group_rate ); -void group_rate_update_wconhist( group_rate_type * group_rate , sched_kw_wconhist_type * kw, int restart_nr ); -void group_rate_update_wconinje( group_rate_type * group_rate , sched_kw_wconinje_type * kw, int restart_nr ); -bool group_rate_is_producer( const group_rate_type * group_rate ); -void group_rate_init( group_rate_type * group_rate ); - -#endif diff --git a/ThirdParty/Ert/libsched/applications/perturb_history/pert.conf b/ThirdParty/Ert/libsched/applications/perturb_history/pert.conf deleted file mode 100644 index 18f71b015b..0000000000 --- a/ThirdParty/Ert/libsched/applications/perturb_history/pert.conf +++ /dev/null @@ -1,15 +0,0 @@ -DATA_FILE Example_01_base.data -SCHEDULE_FILE target.SCH -TARGET tmp/sched_%d.SCH -NUM_REALIZATIONS 100 -GROUP_RATE GROUP1 OIL PRODUCER GROUP1.min_max - -WELL_RATE GROUP1 OP_1 50 OP1.stat -WELL_RATE GROUP1 OP_2 50 OP1.stat -WELL_RATE GROUP1 OP_3 50 OP1.stat -WELL_RATE GROUP1 OP_4 50 OP1.stat -WELL_RATE GROUP1 OP_5 50 OP1.stat - - - ---GROUP_RATE GROUP WATER GROUP2.min_max diff --git a/ThirdParty/Ert/libsched/applications/perturb_history/pert_util.c b/ThirdParty/Ert/libsched/applications/perturb_history/pert_util.c deleted file mode 100644 index 511761036e..0000000000 --- a/ThirdParty/Ert/libsched/applications/perturb_history/pert_util.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'pert_util.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static inline int randint() { - return rand(); -} - - -void rand_dbl(int N , double max , double *R) { - int i; - for (i=0; i < N; i++) - R[i] = randint() * max / RAND_MAX; -} - - -double rand_normal(double mean , double std) { - const double pi = 3.141592653589; - double R[2]; - rand_dbl(2 , 1.0 , R); - return mean + std * sqrt(-2.0 * log(R[0])) * cos(2.0 * pi * R[1]); -} - - -void rand_stdnormal_vector(int size , double *R) { - int i; - for (i = 0; i < size; i++) - R[i] = rand_normal(0.0 , 1.0); -} - - - - -/*****************************************************************/ - -static void set_ts(const time_t_vector_type * time_vector , stringlist_type * stringlist , time_t start_date , time_t end_date , const char * string_value) { - int i; - for (i=0; i < time_t_vector_size( time_vector ); i++) { - time_t t = time_t_vector_iget( time_vector , i ); - if ((t >= start_date) && (t < end_date)) - stringlist_iset_copy( stringlist , i , string_value ); - } -} - -/** - File format: - - * - 12/07/2009 500 577 - 12/07/2009 - 16/09/2009 672 666 - 17/09/2009 - * 100 10% - - - 1. Both dates can be replaced with '*' - which is implied to mean - either the start date, or the end date. - - 2. The formatting of the data strings is 100% NAZI - no spaces - allowed. - - 3. The date intervals are half-open, [date1,date2). - - 4. The date lines can overlap - they are applied in line-order. - - 5. The last float value (i.e. 577 and 666 on the liness above) can - be a percent value; that should indicated with '%' immediately - following the number. The percent number should be in the - interval [0,100]. The bool vector tsp is updated to indicate - whether the data should be interpreted as percent or not. - -*/ - - -static void load_exit( FILE * stream , const char * filename) { - - fprintf(stderr," Something wrong around line:%d of file:%s\n",util_get_current_linenr( stream ) , filename ); - fprintf(stderr," Each line should be:\n date1 - date2 value\nwhere date should be formatted as 12/06/2003. \n"); - exit(1); - -} - - -void fscanf_2ts(const time_t_vector_type * time_vector , const char * filename , stringlist_type * s1 , stringlist_type * s2) { - time_t start_time = time_t_vector_get_first( time_vector ); - time_t end_time = time_t_vector_get_last( time_vector ) + 1; - - { - stringlist_clear( s1 ); - stringlist_clear( s2 ); - for (int i=0; i < time_t_vector_size( time_vector ); i++) { - stringlist_append_ref( s1 , NULL ); - stringlist_append_ref( s2 , NULL ); - } - } - - { - FILE * stream = util_fopen( filename , "r"); - char datestring1[32]; - char datestring2[32]; - char dash; - char value1string[32]; - char value2string[32]; - - while (true) { - int read_count = fscanf(stream , "%s %c %s %s %s" , datestring1 , &dash , datestring2, value1string , value2string); - if (read_count == 5) { - bool OK = true; - time_t t1 = -1; - time_t t2 = -1; - if (util_string_equal( datestring1 , "*")) - t1 = start_time; - else - OK = util_sscanf_date( datestring1 , &t1 ); - - if (util_string_equal( datestring2 , "*")) - t2 = end_time; - else - OK = (OK && util_sscanf_date( datestring2 , &t2 )); - - if (OK) { - set_ts( time_vector , s1 , t1 , t2 , value1string ); - set_ts( time_vector , s2 , t1 , t2 , value2string ); - } else - load_exit( stream , filename ); - - } else { - if (read_count == EOF) - break; - else - load_exit( stream , filename ); - } - } - fclose( stream ); - } -} - - -double sscanfp( double base_value , const char * value_string ) { - double value , parse_value; - char * error_ptr; - - if (value_string == NULL) - return 0; - - parse_value = strtod( value_string , &error_ptr); - if (error_ptr[0] == '%') - value = base_value * parse_value * 0.01; - else { - if (error_ptr[0] == '\0') - value = parse_value; - else { - value = 0; - util_exit("Failed to parse \'%s\' as valid number. \n",value_string ); - } - } - - return value; -} - - -/*****************************************************************/ - - - diff --git a/ThirdParty/Ert/libsched/applications/perturb_history/pert_util.h b/ThirdParty/Ert/libsched/applications/perturb_history/pert_util.h deleted file mode 100644 index aa0a0d41c2..0000000000 --- a/ThirdParty/Ert/libsched/applications/perturb_history/pert_util.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'pert_util.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_PERT_UTIL_H -#define ERT_PERT_UTIL_H -#include -#include -#include -#include - -void rand_dbl(int N , double max , double *R); -double rand_normal(double mean , double std); -void rand_stdnormal_vector(int size , double *R); -void fscanf_2ts(const time_t_vector_type * time_vector , const char * filename , stringlist_type * s1 , stringlist_type * s2); -double sscanfp( double base_value , const char * value_string ); - - -#endif diff --git a/ThirdParty/Ert/libsched/applications/perturb_history/perturb_history.c b/ThirdParty/Ert/libsched/applications/perturb_history/perturb_history.c deleted file mode 100644 index 5fd86a438c..0000000000 --- a/ThirdParty/Ert/libsched/applications/perturb_history/perturb_history.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'perturb_history.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/*****************************************************************/ - - -void perturb_wconhist( void * void_kw , int restart_nr , void * arg) { - sched_kw_wconhist_type * kw = sched_kw_wconhist_safe_cast( void_kw ); - { - hash_type * group_hash = hash_safe_cast( arg ); - hash_iter_type * group_iter = hash_iter_alloc( group_hash ); - while (!hash_iter_is_complete( group_iter )) { - group_rate_type * group_rate = hash_iter_get_next_value( group_iter ); - if (group_rate_is_producer( group_rate )) - group_rate_update_wconhist( group_rate , kw , restart_nr ); - } - } -} - - - -void perturb_wconinje( void * void_kw , int restart_nr , void * arg) { - sched_kw_wconinje_type * kw = sched_kw_wconinje_safe_cast( void_kw ); - { - hash_type * group_hash = hash_safe_cast( arg ); - hash_iter_type * group_iter = hash_iter_alloc( group_hash ); - while (!hash_iter_is_complete( group_iter )) { - group_rate_type * group_rate = hash_iter_get_next_value( group_iter ); - if (!group_rate_is_producer( group_rate )) - group_rate_update_wconinje( group_rate , kw , restart_nr ); - } - } -} - - - - -void config_init(config_parser_type * config ) { - config_item_type * item; - - config_add_key_value(config , "NUM_REALIZATIONS" , true , CONFIG_INT ); - config_add_key_value(config , "SCHEDULE_FILE" , true , CONFIG_EXISTING_FILE); - config_add_key_value(config , "DATA_FILE" , true , CONFIG_EXISTING_FILE); - config_add_key_value(config , "TARGET" , true , CONFIG_STRING ); - - - - item = config_add_item( config , "GROUP_RATE" , false , true ); /* Group name as part of parsing */ - config_item_set_argc_minmax(item , 4 , 4 , 4 , (const config_item_types[4]) { CONFIG_STRING, /* Group name */ - CONFIG_STRING , /* Phase */ - CONFIG_STRING , /* PRODUCER / INJECTOR */ - CONFIG_EXISTING_FILE}); /* File with min / max shift */ - config_item_set_indexed_selection_set( item , 1 , 3 , (const char *[3]) { "OIL" , "GAS" , "WATER"}); - config_item_set_indexed_selection_set( item , 2 , 2 , (const char *[2]) { "PRODUCER" , "INJECTOR"}); - - - - item = config_add_item( config , "WELL_RATE" , false , true ); /* Group name as part of parsing */ - config_item_set_argc_minmax(item , 4 , 4 , 4 , (const config_item_types[4]) { CONFIG_STRING, /* GROUP NAME */ - CONFIG_STRING , /* Well name */ - CONFIG_FLOAT , /* Corr_length (days) */ - CONFIG_EXISTING_FILE});/* File with mean , std shift */ -} - - - -void load_groups( const config_parser_type * config , const sched_file_type * sched_file , hash_type * group_rates , const sched_history_type * sched_history , const time_t_vector_type * time_vector ) { - int i; - for (i=0; i < config_get_occurences( config , "GROUP_RATE" ); i++) { - const char * group_name = config_iget( config , "GROUP_RATE" , i , 0 ); - const char * phase_string = config_iget( config , "GROUP_RATE" , i , 1 ); - const char * type_string = config_iget( config , "GROUP_RATE" , i , 2 ); - const char * min_max_file = config_iget( config , "GROUP_RATE" , i , 3 ); - - group_rate_type * group_rate = group_rate_alloc( sched_history , time_vector , group_name , phase_string , type_string , min_max_file ); - hash_insert_hash_owned_ref( group_rates , group_name , group_rate , group_rate_free__); - } - - - - for (i=0; i < config_get_occurences( config , "WELL_RATE" ); i++) { - const char * group_name = config_iget( config , "WELL_RATE" , i , 0 ); - const char * well_name = config_iget( config , "WELL_RATE" , i , 1 ); - double corr_length = config_iget_as_double( config , "WELL_RATE" , i , 2 ); - const char * stat_file = config_iget( config , "WELL_RATE" , i , 3 ); - - well_rate_type * well_rate; - group_rate_type * group_rate = hash_get( group_rates , group_name ); - well_rate = well_rate_alloc( sched_history , time_vector , well_name , corr_length , stat_file , group_rate_get_phase( group_rate) , group_rate_is_producer( group_rate )); - group_rate_add_well_rate( group_rate , well_rate ); - } - - { - hash_iter_type * group_iter = hash_iter_alloc( group_rates ); - while (!hash_iter_is_complete( group_iter )) { - group_rate_type * group_rate = hash_iter_get_next_value( group_iter ); - group_rate_init( group_rate ); - } - hash_iter_free( group_iter ); - } -} - - - - -void sample( hash_type * group_rates ) { - hash_iter_type * group_iter = hash_iter_alloc( group_rates ); - - while (!hash_iter_is_complete( group_iter )) { - group_rate_type * group_rate = hash_iter_get_next_value( group_iter ); - group_rate_sample( group_rate ); - } - - hash_iter_free( group_iter ); -} - -void debug (const time_t_vector_type * time_vector ) { - stringlist_type * s1 = stringlist_alloc_new(); - stringlist_type * s2 = stringlist_alloc_new(); - fscanf_2ts( time_vector , "/d/proj/bg/oseberg2/ressim/aoreln2/2001b/pert_hist/stat/test5/OSB/B-29_OIL.stat" , s1 , s2 ); - - for (int i = 0; i < stringlist_get_size( s1 ); i++) { - util_fprintf_date( time_t_vector_iget( time_vector , i ) , stdout); - printf(" %7s -> %7s \n",stringlist_iget(s1 , i) , stringlist_iget(s2,i)); - } - exit(1); -} - - -int main( int argc , char ** argv ) { - hash_type * group_rates = hash_alloc(); - config_parser_type * config = config_alloc(); - char * config_file; - { - char * config_base; - char * config_ext; - char * run_path; - - if (util_is_link( argv[1] )) { /* The command line argument given is a symlink - we start by changing to */ - /* the real location of the configuration file. */ - char * realpath = util_alloc_link_target( argv[1] ); - util_alloc_file_components(realpath , &run_path , &config_base , &config_ext); - free( realpath ); - } else - util_alloc_file_components( argv[1] , &run_path , &config_base , &config_ext); - - if (run_path != NULL) { - printf("Changing to directory: %s \n",run_path); - if (chdir( run_path) != 0) - util_exit("Hmmmm - failed to change to directory:%s \n",run_path); - } - config_file = util_alloc_filename(NULL , config_base , config_ext); - util_safe_free( config_base ); - util_safe_free( config_ext ); - util_safe_free( run_path ); - } - - config_init( config ); - config_parse(config , config_file , "--" , NULL , "DEFINE" , false , true ); - { - sched_history_type * sched_history = sched_history_alloc(":"); - const char * data_file = config_iget( config , "DATA_FILE" , 0 , 0 ); - const char * sched_file_name = config_iget( config , "SCHEDULE_FILE" , 0 , 0 ); - path_fmt_type * sched_fmt = path_fmt_alloc_path_fmt( config_iget( config , "TARGET" , 0 , 0) ); - const int num_realizations = config_iget_as_int(config , "NUM_REALIZATIONS" , 0 , 0 ); - msg_type * msg = msg_alloc("Creating file: ", false); - - time_t start_date = ecl_util_get_start_date( data_file ); - time_t_vector_type * time_vector; - /* Loading input and creating well/group objects. */ - { - sched_file_type * sched_file = sched_file_parse_alloc( sched_file_name , start_date ); - sched_history_update( sched_history , sched_file ); - - time_vector = sched_file_alloc_time_t_vector( sched_file ); - load_groups( config , sched_file ,group_rates , sched_history , time_vector ); - sched_file_free( sched_file ); - } - - - /* Sampling and creating output */ - { - int i; - msg_show( msg ); - for (i = 0; i < num_realizations; i++) { - //sched_file_type * sched_file = sched_file_alloc_copy( ); - sched_file_type * sched_file = sched_file_parse_alloc( sched_file_name , start_date ); - sample( group_rates ); - sched_file_update( sched_file , WCONHIST , perturb_wconhist , group_rates ); - sched_file_update( sched_file , WCONINJE , perturb_wconinje , group_rates ); - - { - char * new_file = path_fmt_alloc_file(sched_fmt , true , i ); - sched_file_fprintf( sched_file , new_file , false); - msg_update( msg , new_file ); - free( new_file ); - } - sched_file_free( sched_file ); - } - } - msg_free( msg , true ); - sched_history_free( sched_history ); - } - config_free( config ); - hash_free( group_rates ); -} diff --git a/ThirdParty/Ert/libsched/applications/perturb_history/well_rate.c b/ThirdParty/Ert/libsched/applications/perturb_history/well_rate.c deleted file mode 100644 index 788d91b2f1..0000000000 --- a/ThirdParty/Ert/libsched/applications/perturb_history/well_rate.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'well_rate.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WELL_RATE_ID 6681055 - - -struct well_rate_struct { - UTIL_TYPE_ID_DECLARATION; - char * name; - double corr_length; - bool producer; - double_vector_type * shift; - double_vector_type * mean_shift; - double_vector_type * std_shift; - stringlist_type * mean_shift_string; - stringlist_type * std_shift_string; - double_vector_type * rate; - double_vector_type * base_value; - bool_vector_type * percent_std; - sched_phase_enum phase; - const time_t_vector_type * time_vector; - const sched_history_type * sched_history; -}; - - - - - - -void well_rate_update_wconhist( well_rate_type * well_rate , sched_kw_wconhist_type * kw, int restart_nr ) { - double shift = double_vector_iget( well_rate->shift , restart_nr ); - switch (well_rate->phase) { - case(OIL): - sched_kw_wconhist_shift_orat( kw , well_rate->name , shift); - break; - case(GAS): - sched_kw_wconhist_shift_grat( kw , well_rate->name , shift); - break; - case(WATER): - sched_kw_wconhist_shift_wrat( kw , well_rate->name , shift); - break; - } -} - - -void well_rate_update_wconinje( well_rate_type * well_rate , sched_kw_wconinje_type * kw, int restart_nr ) { - sched_kw_wconinje_shift_surface_flow( kw , well_rate->name , double_vector_iget( well_rate->shift , restart_nr )); - return; -} - - - - -/* - a = exp(-(t_i - t_(i-1)) / corr_length) - y(i) = a*y(i - 1) + (1 - a) * N(mean(i) , std(i)) - -*/ - -void well_rate_sample_shift( well_rate_type * well_rate ) { - int size = time_t_vector_size( well_rate->time_vector ); - double * R = util_malloc( size * sizeof * R , __func__); - int i; - rand_stdnormal_vector( size , R ); - for (i=0; i < size; i++) - R[i] = R[i] * double_vector_iget( well_rate->std_shift , i ) + double_vector_iget( well_rate->mean_shift , i ); - - double_vector_iset( well_rate->shift , 0 , R[0]); - - for (i=1; i < size; i++) { - double dt = 1.0 * (time_t_vector_iget( well_rate->time_vector , i ) - time_t_vector_iget( well_rate->time_vector , i - 1)) / (24 * 3600); /* Days */ - double a = exp(-dt / well_rate->corr_length ); - double shift = a * double_vector_iget( well_rate->shift , i - 1 ) + (1 - a) * R[i]; - double base_rate = double_vector_safe_iget( well_rate->base_value , i); - - /* The time series is sampled - irrespective of whether the well is open or not. */ - - if ((shift + base_rate) < 0) - shift = -base_rate; - - if (sched_history_well_open( well_rate->sched_history , well_rate->name , i)) - double_vector_iset( well_rate->shift , i , shift ); - else - double_vector_iset( well_rate->shift , i , 0); - - } - free( R ); -} - -/* - Ensures that the final rate is >= 0; this might lead to a minor - violation of the parent-groups constraints. -*/ - -void well_rate_ishift( well_rate_type * well_rate , int index, double new_shift) { - if (sched_history_well_open( well_rate->sched_history , well_rate->name , index)) { - double base_rate = double_vector_safe_iget( well_rate->base_value , index); - double shift = double_vector_safe_iget( well_rate->shift , index) + new_shift; - - if ((base_rate + shift) < 0) - shift = -base_rate; - double_vector_iset( well_rate->shift , index , shift ); - } -} - - -double well_rate_iget_rate( const well_rate_type * well_rate , int report_step ) { - return double_vector_safe_iget( well_rate->base_value , report_step ); -} - -int well_rate_get_length( const well_rate_type * well_rate ) { - return double_vector_size( well_rate->base_value ); -} - - - -well_rate_type * well_rate_alloc(const sched_history_type * sched_history , const time_t_vector_type * time_vector , const char * name , double corr_length , const char * filename, sched_phase_enum phase, bool producer) { - well_rate_type * well_rate = util_malloc( sizeof * well_rate , __func__); - UTIL_TYPE_ID_INIT( well_rate , WELL_RATE_ID ); - well_rate->name = util_alloc_string_copy( name ); - well_rate->time_vector = time_vector; - well_rate->corr_length = corr_length; - well_rate->shift = double_vector_alloc(0,0); - well_rate->mean_shift = double_vector_alloc(0 , 0); - well_rate->std_shift = double_vector_alloc(0 , 0); - well_rate->mean_shift_string = stringlist_alloc_new(); - well_rate->std_shift_string = stringlist_alloc_new(); - well_rate->base_value = double_vector_alloc(0 , 0); - well_rate->rate = double_vector_alloc(0 , 0); - well_rate->phase = phase; - well_rate->sched_history= sched_history; - well_rate->percent_std = bool_vector_alloc( 0 , false ); - well_rate->producer = producer; - fscanf_2ts( time_vector , filename , well_rate->mean_shift_string , well_rate->std_shift_string); - - { - char * key; - if (well_rate->producer) { - switch(well_rate->phase) { - case (WATER): - key = util_alloc_sprintf("WWPRH%s%s" , sched_history_get_join_string( sched_history ) , well_rate->name ); - break; - case( GAS ): - key = util_alloc_sprintf("WGPRH%s%s" , sched_history_get_join_string( sched_history ) , well_rate->name ); - break; - case( OIL ): - key = util_alloc_sprintf("WOPRH%s%s" , sched_history_get_join_string( sched_history ) , well_rate->name ); - break; - default: - key = NULL; - util_abort("%s: unknown phase identitifier: %d \n",__func__ , well_rate->phase); - } - } else { - switch(well_rate->phase) { - case (WATER): - key = util_alloc_sprintf("WWIRH%s%s" , sched_history_get_join_string( sched_history ) , well_rate->name ); - break; - case( GAS ): - key = util_alloc_sprintf("WGIRH%s%s" , sched_history_get_join_string( sched_history ) , well_rate->name ); - break; - case( OIL ): - key = util_alloc_sprintf("WOIRH%s%s" , sched_history_get_join_string( sched_history ) , well_rate->name ); - break; - default: - util_abort("%s: unknown phase identitifier: %d \n",__func__ , well_rate->phase); - key = NULL; - } - } - - if (sched_history_has_key( sched_history , key)) { - sched_history_init_vector( sched_history , key , well_rate->base_value ); - well_rate_eval_stat( well_rate ); - } else - fprintf(stderr,"** Warning - schedule history does not have key:%s - suspicious?\n", key ); - - free( key ); - } - return well_rate; -} - - -bool well_rate_well_open( const well_rate_type * well_rate , int index ) { - return sched_history_well_open( well_rate->sched_history , well_rate->name , index ); -} - - -void well_rate_eval_stat( well_rate_type * well_rate ) { - for (int i = 0; i < stringlist_get_size( well_rate->mean_shift_string ); i++) { - double mean_shift = sscanfp( double_vector_safe_iget( well_rate->base_value , i ) , stringlist_iget( well_rate->mean_shift_string , i)); - double std_shift = sscanfp( double_vector_safe_iget( well_rate->base_value , i ) , stringlist_iget( well_rate->std_shift_string , i)); - - double_vector_iset( well_rate->mean_shift , i , mean_shift ); - double_vector_iset( well_rate->std_shift , i , std_shift); - } -} - - -static UTIL_SAFE_CAST_FUNCTION( well_rate , WELL_RATE_ID ); - - -void well_rate_free( well_rate_type * well_rate ) { - free( well_rate->name ); - double_vector_free( well_rate->shift ); - double_vector_free( well_rate->mean_shift ); - double_vector_free( well_rate->std_shift ); - double_vector_free( well_rate->base_value ); - bool_vector_free( well_rate->percent_std ); - free( well_rate ); -} - -void well_rate_free__( void * arg ) { - well_rate_type * well_rate = well_rate_safe_cast( arg ); - well_rate_free( well_rate ); -} - - - -sched_phase_enum well_rate_get_phase( const well_rate_type * well_rate ) { - return well_rate->phase; -} - - -const char * well_rate_get_name( const well_rate_type * well_rate ) { - return well_rate->name; -} - - -double_vector_type * well_rate_get_shift( well_rate_type * well_rate ) { - return well_rate->shift; -} diff --git a/ThirdParty/Ert/libsched/applications/perturb_history/well_rate.h b/ThirdParty/Ert/libsched/applications/perturb_history/well_rate.h deleted file mode 100644 index 65ea8cfe56..0000000000 --- a/ThirdParty/Ert/libsched/applications/perturb_history/well_rate.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'well_rate.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_WELL_RATE_H -#define ERT_WELL_RATE_H - -#include -#include -#include -#include -#include -#include - -typedef struct well_rate_struct well_rate_type; -well_rate_type * well_rate_alloc(const sched_history_type * sched_history , - const time_t_vector_type * time_vector , - const char * name , double corr_length , const char * filename, sched_phase_enum phase, bool producer); -void well_rate_free__( void * arg ); -double_vector_type * well_rate_get_shift( well_rate_type * well_rate ); -sched_phase_enum well_rate_get_phase( const well_rate_type * well_rate ); -const char * well_rate_get_name( const well_rate_type * well_rate ); -void well_rate_sample_shift( well_rate_type * well_rate ); -bool well_rate_well_open( const well_rate_type * well_rate , int index ); -void well_rate_ishift( well_rate_type * well_rate ,int index, double new_shift); -void well_rate_update_wconhist( well_rate_type * well_rate , sched_kw_wconhist_type * kw, int restart_nr ); -void well_rate_update_wconinje( well_rate_type * well_rate , sched_kw_wconinje_type * kw, int restart_nr ); -double well_rate_iget_rate( const well_rate_type * well_rate , int report_step ); -int well_rate_get_length( const well_rate_type * well_rate ); -void well_rate_eval_stat( well_rate_type * well_rate ); - -#endif diff --git a/ThirdParty/Ert/libsched/applications/sched_summary.c b/ThirdParty/Ert/libsched/applications/sched_summary.c deleted file mode 100644 index 460305fadc..0000000000 --- a/ThirdParty/Ert/libsched/applications/sched_summary.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_summary.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include - -#include - -#include -#include - - - - - - - -int main (int argc , char ** argv) { - time_t start_time; - if (argc < 3) - util_exit("usage: ECLIPSE.DATA SCHEDULE_FILE ...\n"); - { - const char * data_file = argv[1]; - const char * schedule_file = argv[2]; - start_time = ecl_util_get_start_date( data_file ); - { - sched_history_type * sched_history = sched_history_alloc( ":" ); - sched_file_type * sched_file = sched_file_alloc(start_time); - sched_file_parse(sched_file , schedule_file); - sched_history_update( sched_history , sched_file ); - - { - stringlist_type * key_list = stringlist_alloc_new(); - - for (int iarg=3; iarg < argc; iarg++) { - if( sched_history_has_key( sched_history , argv[iarg] )) - stringlist_append_ref( key_list , argv[iarg]); - else - fprintf(stderr,"** Warning the SCHEDULE file does not contain the key: %s \n",argv[iarg]); - } - - sched_history_fprintf( sched_history , key_list , stdout ); - stringlist_free( key_list ) ; - } - } - } -} diff --git a/ThirdParty/Ert/libsched/applications/sched_test.c b/ThirdParty/Ert/libsched/applications/sched_test.c deleted file mode 100644 index 1aa98b8200..0000000000 --- a/ThirdParty/Ert/libsched/applications/sched_test.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_test.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include - -#include -#include -#include -#include -#include - - - -int main(int argc, char **argv) -{ - time_t start_time; - start_time = util_make_date(1,1,2000); - start_time = util_make_date(1,1,1988); - sched_file_type * sched_file = sched_file_parse_alloc( argv[1] , start_time); - sched_history_type * sched_history = sched_history_alloc(":"); - sched_history_update( sched_history , sched_file ); - sched_history_install_index( sched_history ); - - sched_history_fprintf_group_structure( sched_history , 300 ); - printf("FOPRH %g \n",sched_history_iget( sched_history , "FOPRH" , 139)); - //printf("GWPRH:AN %g \n",sched_history_iget( sched_history , "GOPRH:AN" , 139)); - //printf("WWIRH:C-1 %g \n",sched_history_iget( sched_history , "WWIRH:C-1" , 139)); - //printf("WOPRH:C-15C %g \n",sched_history_iget( sched_history , "WOPRH:B-6A" , 300)); - //printf("WOPRH:C-15C %g \n",sched_history_iget( sched_history , "WOPRH:B-6A" , 400)); - - sched_history_free( sched_history ); - sched_file_free( sched_file ); -} diff --git a/ThirdParty/Ert/libsched/applications/update_ir.c b/ThirdParty/Ert/libsched/applications/update_ir.c deleted file mode 100644 index 2d6302d4b3..0000000000 --- a/ThirdParty/Ert/libsched/applications/update_ir.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'update_ir.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void scale_injectors(void * void_kw , int report_step , void * arg) { - sched_kw_wconinje_type * kw = sched_kw_wconinje_safe_cast( void_kw ); - hash_type * well_hash = hash_safe_cast( arg ); - hash_iter_type * hash_iter = hash_iter_alloc( well_hash ); - - - while ( !hash_iter_is_complete(hash_iter) ) { - const char * well = hash_iter_get_next_key( hash_iter ); - double scale_factor = hash_get_double( well_hash , well ); - - sched_kw_wconinje_scale_surface_flow(kw , well , scale_factor); - printf("Scaling injector: %s/%g \n",well , scale_factor); - } - hash_iter_free( hash_iter ); -} - - - -static hash_type * parse_multir( const char * multir_file ) { - parser_type * parser = parser_alloc(" \n\t",NULL ,NULL , NULL , NULL , NULL); - stringlist_type * tokens = parser_tokenize_file ( parser , multir_file , true ); - hash_type * hash = hash_alloc(); - int i; - - for (i = 0; i < stringlist_get_size(tokens); i += 2) { - const char * well = stringlist_iget( tokens , i); - const char * multir_st = stringlist_iget( tokens , i + 1); - double multir; - - if (util_sscanf_double( multir_st , &multir)) - hash_insert_double( hash , well , multir); - else - util_abort("%s: failed to parse: %s as double \n",__func__ , multir_st); - - } - stringlist_free( tokens ); - parser_free( parser ); - return hash; -} - - -void install_SIGNALS(void) { - signal(SIGSEGV , util_abort_signal); - signal(SIGINT , util_abort_signal); - signal(SIGKILL , util_abort_signal); -} - - - - -int main(int argc, char **argv) -{ - if(argc < 4) - { - printf("Usage: sched_test.x data_file my_sched_file.SCH update_ir.txt \n"); - return 0; - } - - time_t start_time; - int num_restart_files; - int last_restart_file; - char * data_file = argv[1]; - char * schedule_file = argv[2]; - char * multir_file = argv[3]; - - hash_type * hash; - sched_file_type * sched_file; - - start_time = ecl_util_get_start_date( data_file ); - sched_file = sched_file_parse_alloc( schedule_file , start_time); - unlink( schedule_file ); - hash = parse_multir( multir_file ); - sched_file_update(sched_file , WCONINJE , scale_injectors , hash); - sched_file_fprintf(sched_file , schedule_file ); - sched_file_free( sched_file ); - hash_free( hash ); - - - return 0; -} diff --git a/ThirdParty/Ert/libsched/include/ert/sched/group_history.h b/ThirdParty/Ert/libsched/include/ert/sched/group_history.h deleted file mode 100644 index 2b43b6ee2f..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/group_history.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'group_history.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GROUP_HISTORY_H -#define ERT_GROUP_HISTORY_H - -#ifdef __cplusplus -extern "C" { -#endif -#include -#include -#include - -typedef struct group_history_struct group_history_type; - - -bool group_history_group_exists( const group_history_type * group_history , int report_step); -group_history_type * group_history_alloc( const char * group_name , const time_t_vector_type * time , int report_step ); -void group_history_free( group_history_type * group_history ); -void group_history_free__( void * arg ); -void group_history_add_child(group_history_type * group_history , void * child_history , const char * child_name , int report_step ); -void group_history_init_child_names( group_history_type * group_history , int report_step , stringlist_type * child_names ); -const char * group_history_get_name( const group_history_type * group_history ); -void group_history_fprintf( const group_history_type * group_history , int report_step , bool recursive , FILE * stream ); - - -double group_history_iget_GOPRH( const void * __group_history , int report_step ); -double group_history_iget_GGPRH( const void * __group_history , int report_step ); -double group_history_iget_GWPRH( const void * __group_history , int report_step ); -double group_history_iget_GWCTH( const void * __group_history , int report_step ); -double group_history_iget_GGORH( const void * __group_history , int report_step ); - -double group_history_iget_GWPTH( const void * __group_history , int report_step ); -double group_history_iget_GOPTH( const void * __group_history , int report_step ); -double group_history_iget_GGPTH( const void * __group_history , int report_step ); - -double group_history_iget( const void * index , int report_step ); - -UTIL_IS_INSTANCE_HEADER( group_history ); - - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/group_index.h b/ThirdParty/Ert/libsched/include/ert/sched/group_index.h deleted file mode 100644 index 6bfef0be59..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/group_index.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'group_index.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GROUP_INDEX_H -#define ERT_GROUP_INDEX_H - -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include - -typedef struct group_index_struct group_index_type; - -group_index_type * group_index_alloc( const char * group_name , const char * variable , const void * state_ptr , sched_history_callback_ftype * func ); -void group_index_free( group_index_type * group_index ); -void group_index_free__( void * arg ); -sched_history_callback_ftype * group_index_get_callback( const group_index_type * group_index ); -const void * group_index_get_state__( const void * index ); -const void * group_index_get_state( const group_index_type * group_index ); -const char * group_index_get_name( const group_index_type * group_index ); -const char * group_index_get_variable( const group_index_type * group_index ); - - - -UTIL_IS_INSTANCE_HEADER( group_index ); -UTIL_SAFE_CAST_HEADER_CONST( group_index ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/gruptree.h b/ThirdParty/Ert/libsched/include/ert/sched/gruptree.h deleted file mode 100644 index 3a1344f540..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/gruptree.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gruptree.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_GRUPTREE_H -#define ERT_GRUPTREE_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - -typedef struct gruptree_struct gruptree_type; - -gruptree_type * gruptree_alloc(); -gruptree_type * gruptree_copyc(const gruptree_type *); -gruptree_type * gruptree_fread_alloc(FILE *); -void gruptree_fwrite(const gruptree_type *, FILE *); -void gruptree_free(gruptree_type *); - - -void gruptree_register_grup(gruptree_type *, const char *, const char *); -void gruptree_register_well(gruptree_type *, const char *, const char *); -bool gruptree_has_grup(const gruptree_type *, const char *); -char ** gruptree_alloc_grup_well_list(gruptree_type *, const char *, int *); -void gruptree_printf_grup_wells(gruptree_type *, const char *); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/history.h b/ThirdParty/Ert/libsched/include/ert/sched/history.h deleted file mode 100644 index e35c54ce46..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/history.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'history.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_HISTORY_H -#define ERT_HISTORY_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include -#include -#include - -#include - -#include - - -typedef enum { - SCHEDULE = 0, - REFCASE_SIMULATED = 1, /* ecl_sum_get_well_var( "WWCT" ); */ - REFCASE_HISTORY = 2, /* ecl_sum_get_well_var( "WWCTH" ); */ - HISTORY_SOURCE_INVALID = 10 -} history_source_type; - - - -typedef struct history_struct history_type; - - history_source_type history_get_source_type( const char * string_source ); - -// Manipulators. - void history_free(history_type *); - history_type * history_alloc_from_sched_file(const char * sep_string , const sched_file_type *); - history_type * history_alloc_from_refcase(const ecl_sum_type * refcase , bool use_h_keywords); - const char * history_get_source_string( history_source_type history_source ); - bool history_init_ts( const history_type * history , const char * summary_key , double_vector_type * value, bool_vector_type * valid); - -// Accessors. - time_t history_get_start_time( const history_type * history ); - int history_get_last_restart(const history_type *); - double history_get_var_from_sum_key(const history_type *, int, const char *, bool *); - double history_get_well_var(const history_type * , int, const char *, const char *, bool *); - double history_get_group_var(const history_type *, int, const char *, const char *, bool *); - void history_alloc_time_series_from_summary_key(const history_type *, const char *, double **, bool **); - time_t history_iget_node_start_time(const history_type *, int); - time_t history_iget_node_end_time(const history_type *, int); - int history_get_restart_nr_from_days(const history_type *, double days); - time_t history_get_time_t_from_restart_nr( const history_type * history , int restart_nr); - int history_get_restart_nr_from_time_t( const history_type * history , time_t time); - - UTIL_IS_INSTANCE_HEADER( history ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_blob.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_blob.h deleted file mode 100644 index b7a0b8f9eb..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_blob.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_blob.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_BLOB_H -#define ERT_SCHED_BLOB_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -typedef struct sched_blob_struct sched_blob_type; - - -void sched_blob_append_token( sched_blob_type * blob , const char * token ); -sched_blob_type * sched_blob_alloc( ); -void sched_blob_free( sched_blob_type * blob ); -void sched_blob_fprintf( const sched_blob_type * blob , FILE * stream ); -int sched_blob_get_size( const sched_blob_type * blob ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_file.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_file.h deleted file mode 100644 index 4a29160b4b..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_file.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_file.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_FILE_H -#define ERT_SCHED_FILE_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -#include -#include - -typedef struct sched_file_struct sched_file_type; -typedef struct sched_block_struct sched_block_type; - - -typedef void (sched_file_callback_ftype)( void * sched_kw , int restart_nr , void * arg); - -void sched_file_add_fixed_length_kw( sched_file_type * sched_file , const char * kw , int length ); -sched_file_type * sched_file_alloc(time_t); -sched_file_type * sched_file_safe_cast(void * ); -void sched_file_free(sched_file_type *); -void sched_file_parse(sched_file_type *, const char *); -void sched_file_parse_append(sched_file_type * , const char * ); -sched_file_type * sched_file_parse_alloc(const char * , time_t); -void sched_file_fprintf_i(const sched_file_type *, int, const char *); -void sched_file_fprintf(const sched_file_type * sched_file, const char * file); - -int sched_file_get_num_restart_files(const sched_file_type *); -int sched_file_get_restart_nr_from_time_t(const sched_file_type *, time_t); -int sched_file_get_restart_nr_from_days(const sched_file_type * , double ); -int sched_file_iget_block_size(const sched_file_type *, int); -int sched_file_time_t_to_restart_file(const sched_file_type *, time_t); - -time_t sched_file_iget_block_start_time(const sched_file_type *, int); -time_t sched_file_iget_block_end_time(const sched_file_type *, int); -double sched_file_iget_block_start_days(const sched_file_type * sched_file, int i); -double sched_file_iget_block_end_days(const sched_file_type * sched_file, int i); -double sched_file_get_sim_days(const sched_file_type * sched_file , int report_step); -time_t sched_file_get_sim_time(const sched_file_type * sched_file , int report_step); - -sched_kw_type * sched_file_ijget_block_kw_ref(const sched_file_type *, int, int); -int sched_file_get_restart_file_from_time_t(const sched_file_type * , time_t ); -void sched_file_summarize(const sched_file_type * , FILE * ); -sched_file_type * sched_file_alloc_copy(const sched_file_type * , bool); -time_t_vector_type * sched_file_alloc_time_t_vector( const sched_file_type * sched_file ); - -void sched_file_update_blocks(sched_file_type * sched_file, int restart1 , int restart2 , sched_kw_type_enum kw_type, sched_file_callback_ftype * callback, void * arg); -void sched_file_update(sched_file_type * sched_file, sched_kw_type_enum kw_type, sched_file_callback_ftype * callback, void * arg); -bool sched_file_well_open( const sched_file_type * sched_file , int restart_nr , const char * well_name ); -const char * sched_file_iget_filename( const sched_file_type * sched_file , int file_nr ); - - -int sched_block_get_size(const sched_block_type * block); -sched_kw_type * sched_block_iget_kw(sched_block_type * block, int i); -sched_block_type * sched_file_iget_block(const sched_file_type * sched_file, int i); - - - -double sched_file_well_wconhist_rate( const sched_file_type * sched_file , - int restart_nr , - const char * well_name); - -double sched_file_well_wconinje_rate( const sched_file_type * sched_file , - int restart_nr , - const char * well_name); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_history.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_history.h deleted file mode 100644 index dfdd35fa53..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_history.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_history.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_HISTORY_H -#define ERT_SCHED_HISTORY_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -#include - -typedef struct sched_history_struct sched_history_type; - - - time_t sched_history_iget_time_t( const sched_history_type * sched_history , int restart_nr ); - void sched_history_update( sched_history_type * sched_history, const sched_file_type * sched_file ); - sched_history_type * sched_history_alloc( const char * sep_string ); - void sched_history_free( sched_history_type * sched_history ); - double sched_history_iget( const sched_history_type * sched_history , const char * key , int report_step); - void sched_history_init_vector( const sched_history_type * sched_history , const char * key , double_vector_type * value); - void sched_history_fprintf_group_structure( sched_history_type * sched_history , int report_step ); - const char * sched_history_get_join_string( const sched_history_type * sched_history ); - void sched_history_fprintf_index_keys( const sched_history_type * sched_history , FILE * stream ); - bool sched_history_has_key( const sched_history_type * sched_history , const char * key); - void sched_history_fprintf( const sched_history_type * sched_history , const stringlist_type * key_list , FILE * stream); - bool sched_history_well_open( const sched_history_type * sched_history , const char * well_name , int report_step ); - bool sched_history_has_well( const sched_history_type * sched_history , const char * well_name); - bool sched_history_has_group( const sched_history_type * sched_history , const char * group_name); - bool sched_history_group_exists( const sched_history_type * sched_history , const char * group_name , int report_step ); - int sched_history_get_last_history( const sched_history_type * sched_history ); - bool sched_history_open( const sched_history_type * sched_history , const char * key , int report_step); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw.h deleted file mode 100644 index 854fb66dd1..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_H -#define ERT_SCHED_KW_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include -#include - -#include - -#include - -typedef struct sched_kw_struct sched_kw_type; - - - -/*****************************************************************/ - - - - void sched_kw_free__(void *); - const char * sched_kw_get_type_name( const sched_kw_type * sched_kw ); - sched_kw_type_enum sched_kw_get_type(const sched_kw_type *); - sched_kw_type * sched_kw_token_alloc(const stringlist_type * tokens, int * token_index, hash_type * fixed_length_table, bool * foundEND); - void sched_kw_fprintf(const sched_kw_type *, FILE *); - void sched_kw_free(sched_kw_type *); - - sched_kw_type * sched_kw_alloc_copy(const sched_kw_type * ); - sched_kw_type ** sched_kw_split_alloc_DATES(const sched_kw_type *, int *); - time_t sched_kw_get_new_time(const sched_kw_type *, time_t); - char ** sched_kw_alloc_well_list(const sched_kw_type *, int *); - hash_type * sched_kw_alloc_well_obs_hash(const sched_kw_type *); - void sched_kw_alloc_child_parent_list(const sched_kw_type *, char ***, char ***, int *); - void * sched_kw_get_data( sched_kw_type * kw); - const void * sched_kw_get_const_data( const sched_kw_type * kw); - void sched_kw_set_restart_nr( sched_kw_type * kw , int restart_nr); - const char * sched_kw_get_name( const sched_kw_type * kw); - bool sched_kw_has_well( const sched_kw_type * sched_kw , const char * well ); - bool sched_kw_well_open( const sched_kw_type * sched_kw , const char * well ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_compdat.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_compdat.h deleted file mode 100644 index 7bfdd246bb..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_compdat.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_compdat.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_COMPDAT_H -#define ERT_SCHED_KW_COMPDAT_H -#include - -#include -#include - -#include - -typedef struct sched_kw_compdat_struct sched_kw_compdat_type; - -sched_kw_compdat_type * sched_kw_compdat_alloc(); -void sched_kw_compdat_free(sched_kw_compdat_type * ); -void sched_kw_compdat_fprintf(const sched_kw_compdat_type * , FILE *); -sched_kw_compdat_type * sched_kw_compdat_fread_alloc(FILE *stream); -void sched_kw_compdat_fwrite(const sched_kw_compdat_type * , FILE *stream); - - -KW_HEADER(compdat) - - -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_dates.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_dates.h deleted file mode 100644 index ffe14ef9e6..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_dates.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_dates.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_DATES -#define ERT_SCHED_KW_DATES -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -#include - - -typedef struct sched_kw_dates_struct sched_kw_dates_type; - -sched_kw_dates_type * sched_kw_dates_fscanf_alloc(FILE * , bool *, const char * ); -void sched_kw_dates_fprintf(const sched_kw_dates_type * , FILE *); -void sched_kw_dates_free(sched_kw_dates_type * ); -void sched_kw_dates_fwrite(const sched_kw_dates_type * , FILE * ); -sched_kw_dates_type * sched_kw_dates_fread_alloc(FILE * ); - -int sched_kw_dates_get_size(const sched_kw_dates_type *); -sched_kw_dates_type * sched_kw_dates_alloc_from_time_t(time_t ); -time_t sched_kw_dates_iget_date(const sched_kw_dates_type *, int); -/*******************************************************************/ - - - -KW_HEADER(dates) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_gruptree.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_gruptree.h deleted file mode 100644 index c6b59f26b0..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_gruptree.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_gruptree.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_GRUPTREE_H -#define ERT_SCHED_KW_GRUPTREE_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include - -#include - -typedef struct sched_kw_gruptree_struct sched_kw_gruptree_type; - -//void sched_kw_gruptree_free (sched_kw_gruptree_type *); -//void sched_kw_gruptree_fprintf (const sched_kw_gruptree_type *, FILE * ); -void sched_kw_gruptree_alloc_child_parent_list(const sched_kw_gruptree_type *, char ***, char ***, int *); -void sched_kw_gruptree_init_child_parent_list( const sched_kw_gruptree_type * kw , stringlist_type * child , stringlist_type * parent); - -/*******************************************************************/ - - - -KW_HEADER(gruptree) - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_include.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_include.h deleted file mode 100644 index 64c23f3a55..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_include.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_include.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_INCLUDE_H -#define ERT_SCHED_KW_INCLDUE_H - -#include - -#include - -typedef struct sched_kw_include_struct sched_kw_include_type; - - -sched_kw_include_type * sched_kw_include_fscanf_alloc( FILE *, bool *, const char *); -void sched_kw_include_free(sched_kw_include_type * ); -void sched_kw_include_fprintf(const sched_kw_include_type * , FILE *); -void sched_kw_include_fwrite(const sched_kw_include_type *, FILE *); -sched_kw_include_type * sched_kw_include_fread_alloc( FILE *); - -KW_HEADER(include) - -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_tstep.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_tstep.h deleted file mode 100644 index 492ac80c5f..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_tstep.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_tstep.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_TSTEP -#define ERT_SCHED_KW_TSTEP -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include - -#include - -typedef struct sched_kw_tstep_struct sched_kw_tstep_type; - -sched_kw_tstep_type * sched_kw_tstep_fscanf_alloc(FILE *, bool *, const char *); -void sched_kw_tstep_free(sched_kw_tstep_type * ); -void sched_kw_tstep_fprintf(const sched_kw_tstep_type *, FILE *); -void sched_kw_tstep_fwrite(const sched_kw_tstep_type * , FILE *); -sched_kw_tstep_type * sched_kw_tstep_fread_alloc(FILE *); - -int sched_kw_tstep_get_size(const sched_kw_tstep_type *); -sched_kw_tstep_type * sched_kw_tstep_alloc_from_double(double); -double sched_kw_tstep_iget_step(const sched_kw_tstep_type *, int); -time_t sched_kw_tstep_get_new_time(const sched_kw_tstep_type *, time_t); -int sched_kw_tstep_get_length( const sched_kw_tstep_type * kw); - - -/*******************************************************************/ - - - -KW_HEADER(tstep) -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_untyped.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_untyped.h deleted file mode 100644 index c291ae5547..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_untyped.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_untyped.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_UNTYPED_H -#define ERT_SCHED_KW_UNTYPED_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include - -#include - -typedef struct sched_kw_untyped_struct sched_kw_untyped_type; - -sched_kw_untyped_type * sched_kw_untyped_alloc(const stringlist_type * tokens , int * token_index , int rec_len); -sched_kw_untyped_type * sched_kw_untyped_alloc_empty(const char * , int rec_len); -void sched_kw_untyped_fprintf(const sched_kw_untyped_type *, FILE *); -void sched_kw_untyped_free(sched_kw_untyped_type * ); -sched_kw_untyped_type * sched_kw_untyped_fread_alloc(FILE *); -void sched_kw_untyped_fwrite(const sched_kw_untyped_type * , FILE *); -void sched_kw_untyped_add_line(sched_kw_untyped_type * , const char *, bool); -void sched_kw_untyped_add_tokens( sched_kw_untyped_type * kw , const stringlist_type * tokens); -char ** sched_kw_untyped_iget_entries_alloc(const sched_kw_untyped_type *, int, int *); - -/*******************************************************************/ - -KW_FREE_HEADER(untyped) -KW_FPRINTF_HEADER(untyped) -KW_COPYC_HEADER(untyped) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconhist.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconhist.h deleted file mode 100644 index 712178b278..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconhist.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_wconhist.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_WCONHIST_H -#define ERT_SCHED_KW_WCONHIST_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include -#include -#include - -#include -#include - -typedef struct sched_kw_wconhist_struct sched_kw_wconhist_type; -typedef struct wconhist_state_struct wconhist_state_type; - -#define WCONHIST_DEFAULT_STATUS OPEN - -sched_kw_wconhist_type * sched_kw_wconhist_fscanf_alloc( FILE *, bool *, const char *); -void sched_kw_wconhist_free(sched_kw_wconhist_type * ); -void sched_kw_wconhist_fprintf(const sched_kw_wconhist_type * , FILE *); -void sched_kw_wconhist_fwrite(const sched_kw_wconhist_type *, FILE *); -sched_kw_wconhist_type * sched_kw_wconhist_fread_alloc( FILE *); -hash_type * sched_kw_wconhist_alloc_well_obs_hash(const sched_kw_wconhist_type *); -double sched_kw_wconhist_get_orat( sched_kw_wconhist_type * kw , const char * well_name); -void sched_kw_wconhist_scale_orat( sched_kw_wconhist_type * kw , const char * well_name, double factor); -void sched_kw_wconhist_set_surface_flow( sched_kw_wconhist_type * kw , const char * well_name , double orat); -bool sched_kw_wconhist_has_well( const sched_kw_wconhist_type * kw , const char * well_name); -bool sched_kw_wconhist_well_open( const sched_kw_wconhist_type * kw, const char * well_name); -void sched_kw_wconhist_shift_orat( sched_kw_wconhist_type * kw , const char * well_name, double shift_value); -void sched_kw_wconhist_shift_grat( sched_kw_wconhist_type * kw , const char * well_name, double shift_value); -void sched_kw_wconhist_shift_wrat( sched_kw_wconhist_type * kw , const char * well_name, double shift_value); -void sched_kw_wconhist_update_state(const sched_kw_wconhist_type * kw , wconhist_state_type * state , const char * well_name , int report_step ); - -void sched_kw_wconhist_init_well_list( const sched_kw_wconhist_type * kw , stringlist_type * well_list); - - - -void wconhist_state_free__( void * arg ); -wconhist_state_type * wconhist_state_alloc( const time_t_vector_type * time); -void wconhist_state_free( wconhist_state_type * wconhist ); - -double wconhist_state_iget_STAT( const void * state , int report_step ); - //well_status_enum wconhist_state_iget_status( const void * state , int report_step ); -well_cm_enum wconhist_state_iget_WMCTLH( const void * state , int report_step ); -double wconhist_state_iget_WBHPH( const void * state , int report_step ); -double wconhist_state_iget_WOPRH( const void * state , int report_step ); -double wconhist_state_iget_WGPRH( const void * state , int report_step ); -double wconhist_state_iget_WWPRH( const void * state , int report_step ); -double wconhist_state_iget_WWCTH(const void * state , int report_step ); -double wconhist_state_iget_WGORH(const void * state , int report_step ); -double wconhist_state_iget_WOPTH( const void * state , int report_step ); -double wconhist_state_iget_WWPTH( const void * state , int report_step ); -double wconhist_state_iget_WGPTH( const void * state , int report_step ); - -void sched_kw_wconhist_close_state(wconhist_state_type * state , int report_step ); - - -UTIL_SAFE_CAST_HEADER( sched_kw_wconhist ); -/*******************************************************************/ - - - -KW_HEADER(wconhist) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinj.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinj.h deleted file mode 100644 index f97d855326..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinj.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_wconinj.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_WCONINJ_H -#define ERT_SCHED_KW_WCONINJ_H - - -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -#include -#include - -#include - - -typedef struct sched_kw_wconinj_struct sched_kw_wconinj_type; - - -char ** sched_kw_wconinj_alloc_wells_copy( const sched_kw_wconinj_type * , int * ); - -/*******************************************************************/ - -KW_HEADER(wconinj) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinje.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinje.h deleted file mode 100644 index 436a56a86a..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinje.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_wconinje.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_WCONINJE_H -#define ERT_SCHED_KW_WCONINJE_H - - -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include -#include - -#include -#include - - -typedef struct sched_kw_wconinje_struct sched_kw_wconinje_type; -typedef struct wconinje_state_struct wconinje_state_type; - - -sched_phase_enum sched_kw_wconinje_get_phase( const sched_kw_wconinje_type * kw , const char * well_name); -bool sched_kw_wconinje_well_open( const sched_kw_wconinje_type * kw, const char * well_name); -char ** sched_kw_wconinje_alloc_wells_copy( const sched_kw_wconinje_type * , int * ); - -void sched_kw_wconinje_set_surface_flow( const sched_kw_wconinje_type * kw , const char * well, double surface_flow); -void sched_kw_wconinje_scale_surface_flow( const sched_kw_wconinje_type * kw , const char * well, double factor); -double sched_kw_wconinje_get_surface_flow( const sched_kw_wconinje_type * kw , const char * well); -bool sched_kw_wconinje_has_well( const sched_kw_wconinje_type * , const char * ); -sched_kw_wconinje_type * sched_kw_wconinje_safe_cast( void * arg ); -void sched_kw_wconinje_shift_surface_flow( const sched_kw_wconinje_type * kw , const char * well_name , double delta_surface_flow); -bool sched_kw_wconinje_buffer_fwrite( const sched_kw_wconinje_type * kw , const char * well_name , buffer_type * buffer); -bool sched_kw_wconinje_historical( const sched_kw_wconinje_type * kw ); - -void sched_kw_wconinje_close_state(wconinje_state_type * state , int report_step ); -void sched_kw_wconinje_update_state( const sched_kw_wconinje_type * kw , wconinje_state_type * state , const char * well_name , int report_step ); -void wconinje_state_free__( void * arg ); -wconinje_state_type * wconinje_state_alloc( const char * well_name , const time_t_vector_type * time); -void wconinje_state_free( wconinje_state_type * wconinje ); -double wconinje_state_iget_WGIRH( const void * __state , int report_step ); -double wconinje_state_iget_WWIRH( const void * __state , int report_step ); -void sched_kw_wconinje_init_well_list( const sched_kw_wconinje_type * kw , stringlist_type * well_list); - -/*******************************************************************/ - - - -KW_HEADER(wconinje) - - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinjh.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinjh.h deleted file mode 100644 index 2b4b7d9a64..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconinjh.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_wconinjh.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_WCONINJH_H -#define ERT_SCHED_KW_WCONINJH_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include -#include - -#include -#include - - - -typedef struct sched_kw_wconhist_struct sched_kw_wconinjh_type; -typedef struct wconinjh_state_struct wconinjh_state_type; - -sched_kw_wconinjh_type * sched_kw_wconinjh_fscanf_alloc( FILE *, bool *, const char *); -void sched_kw_wconinjh_free(sched_kw_wconinjh_type * ); -void sched_kw_wconinjh_fprintf(const sched_kw_wconinjh_type * , FILE *); -void sched_kw_wconinjh_fwrite(const sched_kw_wconinjh_type *, FILE *); -sched_kw_wconinjh_type * sched_kw_wconinjh_fread_alloc( FILE *); - -hash_type * sched_kw_wconinjh_alloc_well_obs_hash(const sched_kw_wconinjh_type *); - -void sched_kw_wconinjh_init_well_list( const sched_kw_wconinjh_type * kw , stringlist_type * well_list); -void sched_kw_wconinjh_update_state( const sched_kw_wconinjh_type * kw , wconinjh_state_type * state , const char * well_name , int report_step ); -void wconinjh_state_free__( void * arg ); -wconinjh_state_type * wconinjh_state_alloc( const time_t_vector_type * time); -void wconinjh_state_free( wconinjh_state_type * wconinjh ); -void sched_kw_wconinjh_close_state(wconinjh_state_type * state , int report_step ); - -sched_phase_enum wconinjh_state_iget_phase( const wconinjh_state_type * state , int report_step); -well_status_enum wconinjh_state_iget_status( const wconinjh_state_type * state , int report_step ); - - -double wconinjh_state_iget_WWIRH( const void * __state , int report_step) ; -double wconinjh_state_iget_WGIRH( const void * __state , int report_step) ; -double wconinjh_state_iget_WOIRH( const void * __state , int report_step) ; -double wconinjh_state_iget_WBHPH( const void * __state , int report_step) ; -double wconinjh_state_iget_WTHPH( const void * __state , int report_step) ; -double wconinjh_state_iget_WVPRH( const void * __state , int report_step) ; -int wconinjh_state_iget_vfp_table_nr( const wconinjh_state_type * state , int report_step) ; - -/*******************************************************************/ -KW_HEADER(wconinjh) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconprod.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconprod.h deleted file mode 100644 index 4ccd93a02c..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_wconprod.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_wconprod.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_WCONPROD_H -#define ERT_SCHED_KW_WCONPROD_H - - -#ifdef __cplusplus -extern "C" { -#endif -#include - - - typedef struct sched_kw_wconprod_struct sched_kw_wconprod_type; - - - char ** sched_kw_wconprod_alloc_wells_copy( const sched_kw_wconprod_type * , int * ); - void sched_kw_wconprod_init_well_list( const sched_kw_wconprod_type * kw , stringlist_type * well_list); - - - -KW_HEADER(wconprod) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_welspecs.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_welspecs.h deleted file mode 100644 index d07acef2a9..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_kw_welspecs.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_welspecs.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_KW_WELSPECS_H -#define ERT_SCHED_KW_WELSPECS_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -#include - -#include - - - -/*************************************************************/ - -typedef struct sched_kw_welspecs_struct sched_kw_welspecs_type; - - - -sched_kw_welspecs_type * sched_kw_welspecs_fscanf_alloc(FILE *, bool *, const char *); -sched_kw_welspecs_type * sched_kw_welspecs_fread_alloc(FILE *); -void sched_kw_welspecs_free(sched_kw_welspecs_type *); -void sched_kw_welspecs_fprintf(const sched_kw_welspecs_type *, FILE *); -void sched_kw_welspecs_fwrite(const sched_kw_welspecs_type *, FILE *); - -void sched_kw_welspecs_alloc_child_parent_list(const sched_kw_welspecs_type *, char ***, char ***, int *); -void sched_kw_welspecs_init_child_parent_list( const sched_kw_welspecs_type * kw , stringlist_type * child , stringlist_type * parent); -/*******************************************************************/ - - - -KW_HEADER(welspecs) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_macros.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_macros.h deleted file mode 100644 index f578e8ac82..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_macros.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_macros.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_MACROS_H_ -#define ERT_SCHED_MACROS_H_ - - - -/*********************************** -Macros for "voidifications" of the data handlers. - - - *_IMPL - The implementation - - *_HEADER - Header - - None. - Name. - -***********************************/ - -#define KW_FREE(KW) sched_kw_## KW ##_free__ -#define KW_FPRINTF(KW) sched_kw_## KW ##_fprintf__ -#define KW_COPYC(KW) sched_kw_## KW ##_copyc__ -#define KW_ALLOC(KW) sched_kw_## KW ##_alloc__ - -#define GET_DATA_HANDLERS(DH, KWNAME) \ -DH.token_alloc = KW_ALLOC( KWNAME) ; \ -DH.free = KW_FREE( KWNAME) ; \ -DH.fprintf = KW_FPRINTF( KWNAME) ; \ -DH.copyc = NULL/*KW_ALLOC_COPY(KWNAME)*/ ; - -/*******************************************************************/ - -#define KW_ALLOC_IMPL(KW) \ -void * sched_kw_## KW ##_alloc__(const stringlist_type * tokens , int * token_index ) \ -{ \ - return (void *) sched_kw_## KW ##_alloc(tokens , token_index); \ -} - - -#define KW_FPRINTF_IMPL(KW) \ -void sched_kw_## KW ##_fprintf__(const void * kw, FILE * stream) \ -{ \ - sched_kw_## KW ##_fprintf((const sched_kw_## KW ##_type *) kw, stream); \ -} \ - -#define KW_FREE_IMPL(KW) \ -void sched_kw_## KW ##_free__(void * kw) \ -{ \ - sched_kw_## KW ##_free((sched_kw_## KW ##_type *) kw);\ -} \ - - -#define KW_COPYC_IMPL(KW) \ -void * sched_kw_## KW ##_copyc__(const void * kw) { \ - return sched_kw_ ## KW ## _copyc(kw); \ -} - -#define KW_IMPL(KW) \ -KW_FREE_IMPL(KW) \ -KW_FPRINTF_IMPL(KW) \ -KW_ALLOC_IMPL(KW) \ -KW_COPYC_IMPL(KW) - - - -/*******************************************************************/ - -#define KW_ALLOC_HEADER(KW) \ -void * sched_kw_## KW ##_alloc__(const stringlist_type * tokens , int * token_index) ; \ - -#define KW_COPYC_HEADER(KW) \ -void * sched_kw_## KW ##_copyc__(const void *); \ - -#define KW_FPRINTF_HEADER(KW) \ -void sched_kw_## KW ##_fprintf__(const void *, FILE * ); \ - -#define KW_FREE_HEADER(KW) \ -void sched_kw_## KW ##_free__(void *); \ - -#endif - - -#define KW_HEADER(KW) \ -KW_FREE_HEADER(KW) \ -KW_FPRINTF_HEADER(KW) \ -KW_ALLOC_HEADER(KW) \ -KW_COPYC_HEADER(KW) diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_time.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_time.h deleted file mode 100644 index 179b27ed3f..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_time.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_time.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_TIME_H -#define ERT_SCHED_TIME_H -#ifdef __cplusplus -extern "C" { -#endif -#include - -typedef struct sched_time_struct sched_time_type; - -sched_time_type * sched_time_alloc( time_t date , double tstep_length , sched_time_enum time_type ); -void sched_time_free( sched_time_type * time_node ); -void sched_time_free__( void * arg ); -time_t sched_time_get_date( const sched_time_type * time_node ); -time_t sched_time_get_type( const sched_time_type * time_node ); -time_t sched_time_get_target( const sched_time_type * time_node , time_t current_time); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_types.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_types.h deleted file mode 100644 index a8b7b60cf1..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_types.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_types.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_TYPES_H -#define ERT_SCHED_TYPES_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** - Contains numerous typedefs for the types used in the sched_kw keywords. -*/ - - -/* - The two (supported) keywords used for time stepping. -*/ - -typedef enum { DATES_TIME = 1, - TSTEP_TIME = 2 } sched_time_enum; - - - -typedef double (sched_history_callback_ftype) (const void * , int); - - - - -typedef enum { INJECTOR = 1, - PRODUCER = 2 } well_state_well_type; - - - -/** - This enum is used for internalizing both the sched_kw_wconhist - keyword, and the sched_kw_wconinje keyword. Observe that the 'AUTO' - mode is only applicable when used in injector context. -*/ - - -typedef enum { DEFAULT = 0, - OPEN = 1, - STOP = 2, - SHUT = 3, - AUTO = 4 } well_status_enum; - - -/** - There is no default injector type. -*/ -typedef enum {WATER = 0 , - GAS = 1 , - OIL = 2 } sched_phase_enum; - - -/** - This enum is used to enumerate the different control modes. Observe - that the enum is used BOTH by the WCONHIST and the WCONINJE - keywords (only the enum value 'RESV' is actually shared between the - two keywords. - - The final element in the enum 'CM_SHUT' is only used internally; that - will never be in the schedule file. -*/ - -typedef enum {RESV = 0, /* Injector || Producer */ - RATE = 1, /* Injector */ - BHP = 2, /* Injector */ - THP = 3, /* Injector */ - GRUP = 4, /* Injector */ - ORAT = 5, /* Producer */ - WRAT = 6, /* Producrer */ - GRAT = 7, /* Producer */ - LRAT = 8, /* Producer */ - CM_SHUT = 100 } well_cm_enum; - - -#define CM_RATE_STRING "RATE" -#define CM_RESV_STRING "RESV" -#define CM_BHP_STRING "BHP" -#define CM_THP_STRING "THP" -#define CM_GRUP_STRING "GRUP" -#define CM_ORAT_STRING "ORAT" -#define CM_WRAT_STRING "WRAT" -#define CM_GRAT_STRING "GRAT" -#define CM_LRAT_STRING "LRAT" - - -/*****************************************************************/ - -#define FIELD_GROUP "FIELD" - -/*****************************************************************/ - - - -typedef enum {NONE = 0, - WCONHIST = 1, - DATES = 2, - COMPDAT = 4, - TSTEP = 8, - TIME = 16, /* Not implemented support */ - WELSPECS = 32, - GRUPTREE = 64, - INCLUDE = 128, - UNTYPED = 256, - WCONINJ = 512, - WCONINJE = 1024, - WCONINJH = 2048, - WCONPROD = 4096, - NUM_SCHED_KW_TYPES = 8192} sched_kw_type_enum; - - -sched_kw_type_enum sched_kw_type_from_string(const char * kw_name); -const char * sched_kw_type_name(sched_kw_type_enum kw_type); - -/*****************************************************************/ -sched_phase_enum sched_phase_type_from_string(const char * type_string); -const char * sched_phase_type_string(sched_phase_enum type); -const char * sched_types_get_status_string(well_status_enum status); -well_status_enum sched_types_get_status_from_string(const char * st_string); - -well_cm_enum sched_types_get_cm_from_string(const char * cm_string , bool wconhist); -const char * sched_types_get_cm_string( well_cm_enum cm ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/sched_util.h b/ThirdParty/Ert/libsched/include/ert/sched/sched_util.h deleted file mode 100644 index d7b0171955..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/sched_util.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_util.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_SCHED_UTIL_H -#define ERT_SCHED_UTIL_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include - -#include - -#define SCHED_KW_DEFAULT_ITEM "*" - -char * sched_util_alloc_line(FILE *, bool *); -void sched_util_parse_line(const char * , int * , char *** , int , bool *); - - -void sched_util_fprintf_int(bool , int , int , FILE *); -void sched_util_fprintf_dbl(bool , double , int , int , FILE *); -double sched_util_atof(const char *); -int sched_util_atoi(const char *); -void sched_util_fprintf_qst(bool , const char * , int , FILE *); -void sched_util_fprintf_tokenlist(int num_token , const char ** token_list , const bool * def); -void sched_util_skip_trailing_tokens( const stringlist_type * tokens , int * __token_index ); -void sched_util_skip_newline( const stringlist_type * tokens , int * __token_index ); -stringlist_type * sched_util_alloc_line_tokens( const stringlist_type * tokens , bool untyped , int num_tokens , int * __token_index); -void sched_util_init_default(const stringlist_type * line_tokens , bool * def); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/well_history.h b/ThirdParty/Ert/libsched/include/ert/sched/well_history.h deleted file mode 100644 index 617d4da657..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/well_history.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'well_history.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_WELL_HISTORY -#define ERT_WELL_HISTORY - -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include -#include -#include -#include - -typedef struct well_history_struct well_history_type; - - - - - bool well_history_is_producer( const well_history_type * well_history , int report_step ); - wconhist_state_type * well_history_get_wconhist( well_history_type * well_history ); - well_history_type * well_history_alloc( const char * well_name , const time_t_vector_type * time); - void well_history_free__(void * arg); - void well_history_add_keyword( well_history_type * well_history, const sched_kw_type * sched_kw , int report_step ); - const void * well_history_get_state_ptr( const well_history_type * well_history , sched_kw_type_enum kw_type ); - const char * well_history_get_name( const well_history_type * well_history ); - - sched_kw_type_enum well_history_iget_active_kw( const well_history_type * history , int report_step ); - double well_history_iget( well_index_type * index , int report_step ); - void well_history_set_parent( well_history_type * child_well , int report_step , const group_history_type * parent_group); - group_history_type * well_history_get_parent( well_history_type * child_well , int report_step ); - - bool well_history_well_open( const well_history_type * well_history , int report_step ); - double well_history_iget_WGPRH( const well_history_type * well_history , int report_step ); - double well_history_iget_WOPRH( const well_history_type * well_history , int report_step ); - double well_history_iget_WWPRH( const well_history_type * well_history , int report_step ); - - UTIL_IS_INSTANCE_HEADER( well_history ); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ThirdParty/Ert/libsched/include/ert/sched/well_index.h b/ThirdParty/Ert/libsched/include/ert/sched/well_index.h deleted file mode 100644 index 15c7cd1589..0000000000 --- a/ThirdParty/Ert/libsched/include/ert/sched/well_index.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'well_index.h' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#ifndef ERT_WELL_INDEX_H -#define ERT_WELL_INDEX_H - -#ifdef __cplusplus -extern "C" { -#endif -#include - -#include - -typedef struct well_index_struct well_index_type; - - -well_index_type * well_index_alloc( const char * well_name , const char * variable , const void * state_ptr , sched_kw_type_enum kw_type , sched_history_callback_ftype * func); -void well_index_free( well_index_type * well_index ); -void well_index_free__( void * arg ); -void well_index_add_type( well_index_type * index , sched_kw_type_enum kw_type , sched_history_callback_ftype * func); -sched_history_callback_ftype * well_index_get_callback( const well_index_type * well_index , sched_kw_type_enum kw_type); -const void * well_index_get_state__( const void * index ); -const void * well_index_get_state( const well_index_type * well_index ); -const char * well_index_get_name( const well_index_type * well_index ); -const char * well_index_get_variable( const well_index_type * well_index ); - - -UTIL_IS_INSTANCE_HEADER( well_index ); -UTIL_SAFE_CAST_HEADER_CONST( well_index ); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ThirdParty/Ert/libsched/src/CMakeLists.txt b/ThirdParty/Ert/libsched/src/CMakeLists.txt deleted file mode 100644 index f98e985b36..0000000000 --- a/ThirdParty/Ert/libsched/src/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -set( source_files sched_history.c group_index.c sched_time.c sched_blob.c well_index.c well_history.c group_history.c sched_types.c sched_kw.c sched_file.c sched_kw_untyped.c sched_kw_gruptree.c sched_kw_tstep.c sched_kw_dates.c sched_kw_wconhist.c sched_kw_wconinjh.c sched_kw_welspecs.c sched_util.c history.c sched_kw_wconprod.c sched_kw_wconinj.c sched_kw_wconinje.c sched_kw_compdat.c sched_kw_include.c gruptree.c) - -set( header_files sched_history.h sched_time.h group_index.h sched_blob.h well_index.h group_history.h well_history.h sched_types.h sched_file.h sched_kw.h sched_kw_untyped.h sched_kw_gruptree.h sched_kw_tstep.h sched_kw_dates.h sched_kw_wconhist.h sched_kw_wconinjh.h sched_kw_welspecs.h sched_util.h history.h sched_kw_wconprod.h sched_kw_wconinj.h sched_kw_wconinje.h sched_kw_compdat.h sched_kw_include.h sched_macros.h gruptree.h) - -include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) -include_directories( ${libutil_build_path} ) -include_directories( ${libutil_src_path} ) - -add_library( sched ${LIBRARY_TYPE} ${source_files} ) -set_target_properties( sched PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR} ) - -target_link_libraries( sched ert_util ecl) -if (USE_RUNPATH) - add_runpath( sched ) -endif() -#----------------------------------------------------------------- -if (INSTALL_ERT) - install(TARGETS sched DESTINATION ${CMAKE_INSTALL_LIBDIR}) - foreach(header ${header_files}) - install(FILES ../include/ert/sched/${header} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/ert/sched) - endforeach() -endif() - - diff --git a/ThirdParty/Ert/libsched/src/group_history.c b/ThirdParty/Ert/libsched/src/group_history.c deleted file mode 100644 index 50adb787bd..0000000000 --- a/ThirdParty/Ert/libsched/src/group_history.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'group_history.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#define GROUP_HISTORY_TYPE_ID 5100635 - - -struct group_history_struct { - UTIL_TYPE_ID_DECLARATION; - char * group_name; - bool well_group; /* If true this group contains wells, otehrwise it contains other groups. */ - const time_t_vector_type * time; - int start_time; /* At which report step was this group first defined? */ - size_t_vector_type * parent; - size_t_vector_type * children; - vector_type * children_storage; - int __active_step; /* Internal variable to ensure that several repeated calls to add_child / del_child work on the correct child_hash instance. */ -}; - -UTIL_SAFE_CAST_FUNCTION( group_history , GROUP_HISTORY_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION_CONST( group_history , GROUP_HISTORY_TYPE_ID ) -UTIL_IS_INSTANCE_FUNCTION( group_history , GROUP_HISTORY_TYPE_ID) - -group_history_type * group_history_alloc( const char * group_name , const time_t_vector_type * time , int report_step) { - group_history_type * group_history = util_malloc( sizeof * group_history ); - - UTIL_TYPE_ID_INIT( group_history , GROUP_HISTORY_TYPE_ID ); - - group_history->time = time; - group_history->group_name = util_alloc_string_copy( group_name ); - group_history->children_storage = vector_alloc_new(); - group_history->children = size_t_vector_alloc(0,0); - group_history->start_time = report_step; - /* - We install an empty child hash immediately - so the children - table will never contain NULL. - */ - { - hash_type * child_hash = hash_alloc(); - vector_append_owned_ref( group_history->children_storage , child_hash , hash_free__ ); - size_t_vector_iset_default( group_history->children , 0 , ( size_t ) child_hash ); - } - - - group_history->parent = size_t_vector_alloc(0, ( size_t ) NULL ); - group_history->__active_step = -1; - return group_history; -} - - - -void group_history_free( group_history_type * group_history ) { - vector_free( group_history->children_storage ); - size_t_vector_free( group_history->children ); - size_t_vector_free( group_history->parent ); - - free( group_history->group_name ); - free( group_history ); -} - - -bool group_history_group_exists( const group_history_type * group_history , int report_step) { - if ( report_step >= group_history->start_time) - return true; - else - return false; -} - - - -void group_history_free__( void * arg ){ - group_history_type * group_history = group_history_safe_cast( arg ); - group_history_free( group_history ); -} - - -static void group_history_set_parent( group_history_type * child_group , int report_step , const group_history_type * parent_group) { - size_t_vector_iset_default( child_group->parent , report_step , ( size_t ) parent_group); -} - - -static group_history_type * group_history_get_parent( group_history_type * child_group , int report_step ) { - return (group_history_type *) size_t_vector_safe_iget( child_group->parent , report_step ); -} - - - -static void group_history_ensure_private_child_list(group_history_type * group_history , int report_step) { - if (group_history->__active_step != report_step) { - /* - We wish to modify the child-parent relationships at this - report_step; and the internal flag __active_step tells us that - the current elemement in the children pointer table is not - created at this report step; i.e. we must create a new child - hash instance and install at this report step. - - For each repeated call the input parameter @report_step must - be >= @report_step from the previous call; otherwise things - will break hard. - */ - - hash_type * new_child_hash = hash_alloc(); /* Allocate the new new hash table, - and fill it up with the current list - of children. */ - { - hash_type * old_child_hash = ( hash_type * ) size_t_vector_safe_iget( group_history->children , report_step ); - hash_iter_type * old_iter = hash_iter_alloc( old_child_hash ); - while (!hash_iter_is_complete( old_iter )) { - const char * child_name = hash_iter_get_next_key( old_iter ); - void * child = hash_get( old_child_hash , child_name ); - - hash_insert_ref( new_child_hash , child_name , child ); - } - hash_iter_free( old_iter ); - } - - vector_append_owned_ref( group_history->children_storage , new_child_hash , hash_free__ ); /* Store it in the storge area. */ - size_t_vector_iset_default( group_history->children , report_step , ( size_t ) new_child_hash ); - group_history->__active_step = report_step; - } -} - - -static void group_history_del_child( group_history_type * group_history , const char * child_name , int report_step ) { - group_history_ensure_private_child_list( group_history , report_step ); - { - hash_type * child_hash = (hash_type *) size_t_vector_iget( group_history->children , report_step ); - hash_del( child_hash , child_name ); - } -} - - -void group_history_fprintf(const group_history_type * group_history , int report_step , bool recursive , FILE * stream ) { - fprintf(stream , "\n----------------------------------------------------------------------\n"); - fprintf(stream , "Group: %s \n",group_history->group_name); - - { - hash_type * child_hash = (hash_type *) size_t_vector_safe_iget( group_history->children , report_step ); - hash_iter_type * child_iter = hash_iter_alloc( child_hash ); - int counter = 0; - while (!hash_iter_is_complete( child_iter )) { - - const char * name = hash_iter_get_next_key( child_iter ); - const void * child = hash_get( child_hash , name ); - if ( group_history_is_instance( child )) - fprintf(stream , "%8s(G) ",name); - else - fprintf(stream , "%8s(W) ",name); - counter++; - if ((counter % 4) == 0) - fprintf(stream , "\n"); - - } - fprintf(stream , "\n----------------------------------------------------------------------\n"); - if (recursive) { - hash_iter_restart( child_iter ); - while (!hash_iter_is_complete( child_iter )) { - - const char * name = hash_iter_get_next_key( child_iter ); - const void * child = hash_get( child_hash , name ); - if ( group_history_is_instance( child )) - group_history_fprintf( child , report_step , recursive , stream ); - } - } - hash_iter_free( child_iter ); - } -} - - -void group_history_add_child(group_history_type * group_history , void * child_history , const char * child_name , int report_step ) { - bool well_child = well_history_is_instance( child_history ) ? true : false; - - - /* - If the child is already in a parent-child relationship; the child - must first be orphaned by removing it as a child from parents' child-list. - */ - - { - group_history_type * old_parent; - if (well_child) - old_parent = well_history_get_parent( child_history , report_step ); - else - old_parent = group_history_get_parent( child_history , report_step ); - - if (old_parent != NULL) - group_history_del_child( old_parent , child_name , report_step ); - } - - - group_history_ensure_private_child_list( group_history , report_step ); - /*1: Establishing the child relationship. */ - { - hash_type * child_hash; - child_hash = (hash_type *) size_t_vector_iget( group_history->children , report_step ); /* This should NOT use the safe_iget() function, because we always should work an per-report_step instance. */ - hash_insert_ref( child_hash , child_name , child_history); /* Establish parent -> child link. */ - } - - - /*2: Setting the opposite, i.e. parent <- child relationship. */ - if (well_child) - well_history_set_parent( child_history , report_step , group_history ); - else if (group_history_is_instance( child_history )) - group_history_set_parent( child_history , report_step , group_history ); - -} - - -void group_history_init_child_names( group_history_type * group_history , int report_step , stringlist_type * child_names ) { - stringlist_clear( child_names ); - { - hash_type * child_hash = (hash_type *) size_t_vector_safe_iget( group_history->children , report_step ); /* Get a pointer to child hash instance valid at this report_step. */ - hash_iter_type * child_iter = hash_iter_alloc( child_hash ); - while ( !hash_iter_is_complete( child_iter )) { - const char * child_name = hash_iter_get_next_key( child_iter ); - stringlist_append_copy( child_names , child_name ); - } - hash_iter_free( child_iter ); - } -} - - -const char * group_history_get_name( const group_history_type * group_history ) { - return group_history->group_name; -} - - -/*****************************************************************/ - -double group_history_iget_GOPRH( const void * __group_history , int report_step ) { - const group_history_type * group_history = group_history_safe_cast_const( __group_history ); - { - double GOPRH = 0; - - hash_type * child_hash = (hash_type *) size_t_vector_safe_iget( group_history->children , report_step ); /* Get a pointer to child hash instance valid at this report_step. */ - hash_iter_type * child_iter = hash_iter_alloc( child_hash ); - while ( !hash_iter_is_complete( child_iter )) { - const char * child_name = hash_iter_get_next_key( child_iter ); - const void * child = hash_get( child_hash , child_name ); - if (group_history_is_instance( child )) - GOPRH += group_history_iget_GOPRH( child , report_step ); - else { - double WOPRH = well_history_iget_WOPRH( child , report_step ); - GOPRH += WOPRH; - } - } - hash_iter_free( child_iter ); - - return GOPRH; - } -} - - - -double group_history_iget_GWPRH( const void * __group_history , int report_step ) { - const group_history_type * group_history = group_history_safe_cast_const( __group_history ); - { - double GWPRH = 0; - - hash_type * child_hash = (hash_type *) size_t_vector_safe_iget( group_history->children , report_step ); /* Get a pointer to child hash instance valid at this report_step. */ - hash_iter_type * child_iter = hash_iter_alloc( child_hash ); - while ( !hash_iter_is_complete( child_iter )) { - const char * child_name = hash_iter_get_next_key( child_iter ); - const void * child = hash_get( child_hash , child_name ); - if (group_history_is_instance( child )) - GWPRH += group_history_iget_GWPRH( child , report_step ); - else - GWPRH += well_history_iget_WWPRH( child , report_step ); - } - hash_iter_free( child_iter ); - - return GWPRH; - } -} - - - - -double group_history_iget_GGPRH( const void * __group_history , int report_step ) { - const group_history_type * group_history = group_history_safe_cast_const( __group_history ); - { - double GGPRH = 0; - - hash_type * child_hash = (hash_type *) size_t_vector_safe_iget( group_history->children , report_step ); /* Get a pointer to child hash instance valid at this report_step. */ - hash_iter_type * child_iter = hash_iter_alloc( child_hash ); - while ( !hash_iter_is_complete( child_iter )) { - const char * child_name = hash_iter_get_next_key( child_iter ); - const void * child = hash_get( child_hash , child_name ); - if (group_history_is_instance( child )) - GGPRH += group_history_iget_GGPRH( child , report_step ); - else - GGPRH += well_history_iget_WGPRH( child , report_step ); - } - hash_iter_free( child_iter ); - - return GGPRH; - } -} - - -double group_history_iget_GGPTH( const void * __group_history , int report_step ) { - const group_history_type * group_history = group_history_safe_cast_const( __group_history ); - double GGPTH = 0; - for (int tstep = 1; tstep <= report_step; tstep++) { - double days = (time_t_vector_iget( group_history->time , tstep ) - time_t_vector_iget( group_history->time , tstep - 1)) * 1.0 / 86400 ; - double rate = group_history_iget_GGPRH( __group_history , tstep ); - GGPTH += rate * days; - } - return GGPTH; -} - - -double group_history_iget_GOPTH( const void * __group_history , int report_step ) { - const group_history_type * group_history = group_history_safe_cast_const( __group_history ); - double GOPTH = 0; - for (int tstep = 1; tstep <= report_step; tstep++) { - double days = (time_t_vector_iget( group_history->time , tstep ) - time_t_vector_iget( group_history->time , tstep - 1)) * 1.0 / 86400 ; - double rate = group_history_iget_GOPRH( __group_history , tstep ); - GOPTH += rate * days; - } - return GOPTH; -} - - -double group_history_iget_GWPTH( const void * __group_history , int report_step ) { - const group_history_type * group_history = group_history_safe_cast_const( __group_history ); - double GWPTH = 0; - for (int tstep = 1; tstep <= report_step; tstep++) { - double days = (time_t_vector_iget( group_history->time , tstep ) - time_t_vector_iget( group_history->time , tstep - 1)) * 1.0 / 86400 ; - double rate = group_history_iget_GWPRH( __group_history , tstep ); - GWPTH += rate * days; - } - return GWPTH; -} - - - - -double group_history_iget_GGORH( const void * __group_history , int report_step ) { - double GGPRH = group_history_iget_GGPRH( __group_history , report_step ); - double GOPRH = group_history_iget_GOPRH( __group_history , report_step ); - - return GGPRH / GOPRH; -} - - - -double group_history_iget_GWCTH( const void * __group_history , int report_step ) { - double GWPRH = group_history_iget_GWPRH( __group_history , report_step ); - double GOPRH = group_history_iget_GOPRH( __group_history , report_step ); - - return GWPRH / GOPRH; -} - - - - - - -double group_history_iget( const void * index , int report_step ) { - const group_history_type * group_history = group_index_get_state__( index ); - sched_history_callback_ftype * func = group_index_get_callback( index ); - - return func( group_history , report_step ); -} diff --git a/ThirdParty/Ert/libsched/src/group_index.c b/ThirdParty/Ert/libsched/src/group_index.c deleted file mode 100644 index 1078242c10..0000000000 --- a/ThirdParty/Ert/libsched/src/group_index.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'group_index.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include -#include - -#include -#include - - -#define GROUP_INDEX_TYPE_ID 96580631 - - -struct group_index_struct { - UTIL_TYPE_ID_DECLARATION; - char * group_name; - char * variable; - const void * group_history; - sched_history_callback_ftype * func; -}; - - - - - -UTIL_IS_INSTANCE_FUNCTION( group_index , GROUP_INDEX_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION_CONST( group_index , GROUP_INDEX_TYPE_ID ) - - -group_index_type * group_index_alloc( const char * group_name , const char * variable , const void * group_history , sched_history_callback_ftype * func ) { - group_index_type * group_index = util_malloc( sizeof * group_index ); - - UTIL_TYPE_ID_INIT( group_index , GROUP_INDEX_TYPE_ID ); - - group_index->func = func; - group_index->group_history = group_history; - group_index->group_name = util_alloc_string_copy( group_name ); - group_index->variable = util_alloc_string_copy( variable ); - - - return group_index; -} - - -void group_index_free( group_index_type * index ) { - free( index->group_name ); - free( index->variable ); - free( index ); -} - - -void group_index_free__( void * arg ) { - group_index_free( (group_index_type *) arg ); -} - - - -sched_history_callback_ftype * group_index_get_callback( const group_index_type * group_index ) { - return group_index->func; -} - - -const char * group_index_get_name( const group_index_type * group_index ) { - return group_index->group_name; -} - -const char * group_index_get_variable( const group_index_type * group_index ) { - return group_index->variable; -} - - - -const void * group_index_get_state( const group_index_type * group_index ) { - return group_index->group_history; -} - - - -const void * group_index_get_state__( const void * index ) { - const group_index_type * group_index = group_index_safe_cast_const( index ); - return group_index_get_state( group_index ); -} - - diff --git a/ThirdParty/Ert/libsched/src/gruptree.c b/ThirdParty/Ert/libsched/src/gruptree.c deleted file mode 100644 index 67da8d5bb7..0000000000 --- a/ThirdParty/Ert/libsched/src/gruptree.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'gruptree.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include - -#include - - -/* - The gruptree struct is made for internalizing the - GRUPTREE keyword from a schedule section. - - It provides functions which allows for easy - manipulating of, and access to, the tree structure. - - Since the gruptree may change during simulation, - and the changes are usually only given in differences, - i.e. the whole gruptree is NOT restated, we provide a - way to easily create a new gruptree to reflect the changes. - - - - EXAMPLE: - - Schedule file: - ---------------------------- - - SKIPREST - .... - .... - - GRUPTREE - GRPA FIELD/ - GRPB FIELD/ - INJE GRPA/ - / - - TSTEP - 100 / - .... - .... - - GRUPTREE - INJE GRPB / - PROD GRPA / - / - - TSTEP - 200 / - ... - ... - ---------------------------- - - Now, after the first timestep, INJE is no longer - a subgroup of GRPA, but GRPB. However, the rest - of the GRUPTREE at the first time step is still - valid! Note also that a new group PROD has been - added. - - Suppose that you want to create two gruptree's - one for each time step. This can be done as follows. - - - C code: - ---------------------------- - - gruptree_type * tree_one = gruptree_alloc(); - gruptree_register_grup(tree_two, "GRPA", "FIELD"); - gruptree_register_grup(tree_two, "GRPB", "FIELD"); - gruptree_register_grup(tree_two, "INJE", "GRPA"); - - gruptree_type * tree_two = gruptree_copyc(tree_one); - gruptree_register_grup(tree_two, "INJE", "GRPB"); - gruptree_register_grup(tree_two, "PROD", "GRPA"); - - ..... - ..... - - gruptree_free(tree_one); - gruptree_free(tree_two); -*/ - - - -typedef struct grup_struct grup_type; -typedef struct well_struct well_type; - - - -struct grup_struct{ - bool isleaf; - bool isfield; /* Field node can have both wells and grups as children. */ - char * name; - - const grup_type * parent; - hash_type * children; /* If not a leaf grup, pointers to other grups, - if leaf grup, pointers to wells. Special case - for FIELD, which can contain both wells and - grups. */ -}; - - - -struct well_struct{ - char * name; - const grup_type * parent; -}; - - - -struct gruptree_struct{ - hash_type * grups; - hash_type * wells; -}; - - - -/*************************************************************************/ - - - -static grup_type * grup_alloc(const char * name, const grup_type * parent) -{ - grup_type * grup = util_malloc(sizeof * grup); - - grup->isleaf = true; - grup->isfield = false; - grup->name = util_alloc_string_copy(name); - grup->parent = parent; - grup->children = hash_alloc(); - - return grup; -} - - - -static void grup_free(grup_type * grup) -{ - free(grup->name); - hash_free(grup->children); - free(grup); -} - - - -static void grup_free__(void * grup) -{ - grup_free( (grup_type *) grup); -} - - - -static const char * grup_get_parent_name(const grup_type * grup) -{ - if(grup->parent != NULL) - return grup->parent->name; - else - return NULL; -} - - - -static well_type * well_alloc(const char * name, const grup_type * parent) -{ - well_type * well = util_malloc(sizeof * well); - well->name = util_alloc_string_copy(name); - well->parent = parent; - return well; -} - - -static void well_free(well_type * well) -{ - free(well->name); - free(well); -} - - - -static void well_free__(void * well) -{ - well_free( (well_type *) well); -} - - - -static const char * well_get_parent_name(const well_type * well) -{ - return well->parent->name; -} - - - -/** - This function is called recursively ... -*/ -static void gruptree_well_hash_iter__(gruptree_type * gruptree, const char * grupname, hash_type * well_hash) -{ - - if(!hash_has_key(gruptree->grups, grupname)) - util_abort("%s: Internal error - grupname %s is not in hash.\n", __func__, grupname); - - grup_type * grup = hash_get(gruptree->grups, grupname); - if(grup->isfield) - util_abort("%s: Internal error - no support for grups with isfield flag.\n", __func__); - - if(!grup->isleaf) - { - int size = hash_get_size(grup->children); - char ** keylist = hash_alloc_keylist(grup->children); - - for(int i=0; ichildren); - char ** keylist = hash_alloc_keylist(grup->children); - for(int i=0; iwells, keylist[i]); - hash_insert_ref(well_hash, keylist[i], well); - } - util_free_stringlist(keylist, size); - } -} - - - -static gruptree_type * gruptree_alloc_empty() -{ - gruptree_type * gruptree = util_malloc(sizeof * gruptree); - gruptree->grups = hash_alloc(); - gruptree->wells = hash_alloc(); - return gruptree; -} - - - -/*************************************************************************/ - - -gruptree_type * gruptree_alloc() -{ - gruptree_type * gruptree = gruptree_alloc_empty(); - - grup_type * field = grup_alloc("FIELD", NULL); - field->isfield = true; - hash_insert_hash_owned_ref(gruptree->grups, "FIELD", field, grup_free__); - - return gruptree; -} - - - -void gruptree_free(gruptree_type * gruptree) -{ - hash_free(gruptree->grups); - hash_free(gruptree->wells); - free(gruptree); -} - - - -void gruptree_register_grup(gruptree_type * gruptree, const char * name, const char * parent_name) -{ - grup_type * parent; - grup_type * newgrp; - - ////////////////////////////////////////////////////////// - - if(name == NULL) - util_abort("%s: Trying to insert group %s with NULL name - aborting.\n", __func__, name); - if(parent_name == NULL) - util_abort("%s: Trying to insert group %s with NULL parent - aborting.\n", __func__, name); - if(strcmp(name, parent_name) == 0) - util_abort("%s: Trying to insert group %s with itself as parent - aborting.\n", __func__, name); - - if(strcmp(name, "FIELD") == 0) - util_abort("%s: Internal error - insertion of group FIELD is not allowed - aborting.\n", __func__); - - ////////////////////////////////////////////////////////// - - if(!hash_has_key(gruptree->grups, parent_name)) - gruptree_register_grup(gruptree, parent_name, "FIELD"); - - parent = hash_get(gruptree->grups, parent_name); - - if(parent->isleaf && !parent->isfield && hash_get_size(parent->children) > 0) - { - util_abort("%s: Group %s contains wells, cannot contain other groups.\n", __func__, parent_name); - } - - if(hash_has_key(gruptree->grups, name)) - { - newgrp = hash_get(gruptree->grups, name); - hash_del(newgrp->parent->children, name); - - newgrp->parent = parent; - } - else - { - newgrp = grup_alloc(name, parent); - hash_insert_hash_owned_ref(gruptree->grups, name, newgrp, grup_free__); - } - - parent->isleaf = false; - hash_insert_ref(parent->children, name, newgrp); -} - - - -void gruptree_register_well(gruptree_type * gruptree, const char * name, const char * parent_name) -{ - grup_type * parent; - well_type * well; - - if(!hash_has_key(gruptree->grups, parent_name)) - gruptree_register_grup(gruptree, parent_name, "FIELD"); - - parent = hash_get(gruptree->grups, parent_name); - - if(!parent->isleaf && !parent->isfield) - util_abort("%s: Group %s is not FIELD and contains other groups, cannot contain wells.\n", __func__, parent_name); - - if(hash_has_key(gruptree->wells, name)) - { - well = hash_get(gruptree->wells, name); - hash_del(well->parent->children, name); - well->parent = parent; - } - else - { - well = well_alloc(name, parent); - hash_insert_hash_owned_ref(gruptree->wells, name, well, well_free__); - } - hash_insert_ref(well->parent->children, name, well); -} - - - -bool gruptree_has_grup(const gruptree_type * gruptree, const char * grupname) -{ - if(hash_has_key(gruptree->grups, grupname)) - { - return true; - } - else - { - return false; - } -} - - -char ** gruptree_alloc_grup_well_list(gruptree_type * gruptree, const char * grupname, int * num_wells) -{ - char ** well_names; - - if(!hash_has_key(gruptree->grups, grupname)) - util_abort("%s: Group %s is not present in the gruptree.\n", __func__, grupname); - - if(strcmp(grupname, "FIELD") == 0) - { - *num_wells = hash_get_size(gruptree->wells); - well_names = hash_alloc_keylist(gruptree->wells); - } - else - { - hash_type * well_hash = hash_alloc(); - gruptree_well_hash_iter__(gruptree, grupname, well_hash); - - *num_wells = hash_get_size(well_hash); - well_names = hash_alloc_keylist(well_hash); - - hash_free(well_hash); - } - - return well_names; -} - - - -gruptree_type * gruptree_copyc(const gruptree_type * gruptree) -{ - gruptree_type * gruptree_new = gruptree_alloc(); - - { - int num_grups = hash_get_size(gruptree->grups); - char ** grup_list = hash_alloc_keylist(gruptree->grups); - for(int i=0; igrups, grup_list[i]); - gruptree_register_grup(gruptree_new, grup_list[i], grup_get_parent_name(grup)); - } - util_free_stringlist(grup_list, num_grups); - } - - { - int num_wells = hash_get_size(gruptree->wells); - char ** well_list = hash_alloc_keylist(gruptree->wells); - for(int i=0; iwells, well_list[i]); - gruptree_register_well(gruptree_new, well_list[i], well_get_parent_name(well)); - } - util_free_stringlist(well_list, num_wells); - - } - - return gruptree_new; -} - - - -void gruptree_fwrite(const gruptree_type * gruptree, FILE * stream) -{ - { - int num_grups = hash_get_size(gruptree->grups); - char ** grup_list = hash_alloc_keylist(gruptree->grups); - - util_fwrite(&num_grups, sizeof num_grups, 1, stream, __func__); - - for(int i=0; igrups, grup_list[i]); - const char * parent_name = grup_get_parent_name(grup); - - util_fwrite_string(grup_list[i], stream); - util_fwrite_string(parent_name, stream); - } - util_free_stringlist(grup_list, num_grups); - } - - { - int num_wells = hash_get_size(gruptree->wells); - char ** well_list = hash_alloc_keylist(gruptree->wells); - - util_fwrite(&num_wells, sizeof num_wells, 1, stream, __func__); - - for(int i=0; iwells, well_list[i]); - const char * parent_name = well_get_parent_name(well); - util_fwrite_string(well_list[i], stream); - util_fwrite_string(parent_name, stream); - } - util_free_stringlist(well_list, num_wells); - - } - -} - - - -gruptree_type * gruptree_fread_alloc(FILE * stream) -{ - gruptree_type * gruptree = gruptree_alloc(); - { - int num_grups; - util_fread(&num_grups, sizeof num_grups, 1, stream, __func__); - for(int i=0; i - for more details. -*/ - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - - -#define HISTORY_TYPE_ID 66143109 - -struct history_struct{ - UTIL_TYPE_ID_DECLARATION; - const ecl_sum_type * refcase; /* ecl_sum instance used when the data are taken from a summary instance. Observe that this is NOT owned by history instance.*/ - const sched_file_type * sched_file; /* Not owned. */ - sched_history_type * sched_history; - history_source_type source; -}; - - -history_source_type history_get_source_type( const char * string_source ) { - history_source_type source_type = HISTORY_SOURCE_INVALID; - - if (strcmp( string_source , "REFCASE_SIMULATED") == 0) - source_type = REFCASE_SIMULATED; - else if (strcmp( string_source , "REFCASE_HISTORY") == 0) - source_type = REFCASE_HISTORY; - else if (strcmp( string_source , "SCHEDULE") == 0) - source_type = SCHEDULE; - else - util_abort("%s: Sorry source:%s not recognized\n",__func__ , string_source); - - return source_type; -} - - -const char * history_get_source_string( history_source_type history_source ) { - switch( history_source ) { - case( REFCASE_SIMULATED ): - return "REFCASE_SIMULATED"; - break; - case(REFCASE_HISTORY ): - return "REFCASE_HISTORY"; - break; - case(SCHEDULE ): - return "SCHEDULE"; - break; - default: - util_abort("%s: internal fuck up \n",__func__); - return NULL; - } -} - - -UTIL_IS_INSTANCE_FUNCTION( history , HISTORY_TYPE_ID ) - - -static history_type * history_alloc_empty( ) -{ - history_type * history = util_malloc(sizeof * history); - UTIL_TYPE_ID_INIT( history , HISTORY_TYPE_ID ); - history->refcase = NULL; - history->sched_history = NULL; - history->sched_file = NULL; - return history; -} - - - -/******************************************************************/ -// Exported functions for manipulating history_type. Acess functions further below. - - -void history_free(history_type * history) -{ - if (history->sched_history != NULL) - sched_history_free( history->sched_history ); - - free(history); -} - - -history_type * history_alloc_from_sched_file(const char * sep_string , const sched_file_type * sched_file) -{ - history_type * history = history_alloc_empty( ); - history->sched_file = sched_file; - history->sched_history = sched_history_alloc( sep_string ); - sched_history_update( history->sched_history , sched_file ); - history->source = SCHEDULE; - - return history; -} - - -history_type * history_alloc_from_refcase(const ecl_sum_type * refcase , bool use_h_keywords) { - history_type * history = history_alloc_empty( true ); - - history->refcase = refcase; /* This function does not really do anthing - it just sets the ecl_sum field of the history instance. */ - if (use_h_keywords) - history->source = REFCASE_HISTORY; - else - history->source = REFCASE_SIMULATED; - - return history; -} - - - - - -/******************************************************************/ -// Exported functions for accessing history_type. - - - - -int history_get_last_restart(const history_type * history) { - if (history->refcase != NULL) - return ecl_sum_get_last_report_step( history->refcase); - else - return sched_history_get_last_history( history->sched_history ); -} - - - - - - - - -bool history_init_ts( const history_type * history , const char * summary_key , double_vector_type * value, bool_vector_type * valid) { - bool initOK = false; - - double_vector_reset( value ); - bool_vector_reset( valid ); - bool_vector_set_default( valid , false); - - if (history->source == SCHEDULE) { - - for (int tstep = 0; tstep <= sched_history_get_last_history(history->sched_history); tstep++) { - if (sched_history_open( history->sched_history , summary_key , tstep)) { - initOK = true; - bool_vector_iset( valid , tstep , true ); - double_vector_iset( value , tstep , sched_history_iget( history->sched_history , summary_key , tstep)); - } else - bool_vector_iset( valid , tstep , false ); - } - - - } else { - - char * local_key; - if (history->source == REFCASE_HISTORY) { - /* Must create a new key with 'H' for historical values. */ - const ecl_smspec_type * smspec = ecl_sum_get_smspec( history->refcase ); - const char * join_string = ecl_smspec_get_join_string( smspec ); - ecl_smspec_var_type var_type = ecl_smspec_identify_var_type( summary_key ); - - if ((var_type == ECL_SMSPEC_WELL_VAR) || (var_type == ECL_SMSPEC_GROUP_VAR)) - local_key = util_alloc_sprintf( "%sH%s%s" , - ecl_sum_get_keyword( history->refcase , summary_key ) , - join_string , - ecl_sum_get_wgname( history->refcase , summary_key )); - else if (var_type == ECL_SMSPEC_FIELD_VAR) - local_key = util_alloc_sprintf( "%sH" , ecl_sum_get_keyword( history->refcase , summary_key )); - else - local_key = NULL; // If we try to get historical values of e.g. Region quantities it will fail. - } else - local_key = (char *) summary_key; - - if (local_key) { - if (ecl_sum_has_general_var( history->refcase , local_key )) { - for (int tstep = 0; tstep <= history_get_last_restart(history); tstep++) { - int time_index = ecl_sum_iget_report_end( history->refcase , tstep ); - if (time_index >= 0) { - double_vector_iset( value , tstep , ecl_sum_get_general_var( history->refcase , time_index , local_key )); - bool_vector_iset( valid , tstep , true ); - } else - bool_vector_iset( valid , tstep , false ); /* Did not have this report step */ - } - initOK = true; - } - - if (history->source == REFCASE_HISTORY) - free( local_key ); - } - } - return initOK; -} - - -time_t history_get_start_time( const history_type * history ) { - if (history->source == SCHEDULE) - return sched_history_iget_time_t( history->sched_history , 0); - else - return ecl_sum_get_start_time( history->refcase ); -} - - - -/* Uncertain about the first node - offset problems +++ ?? - Changed to use node_end_time() at svn ~ 2850 - - Changed to sched_history at svn ~2940 -*/ -time_t history_get_time_t_from_restart_nr( const history_type * history , int restart_nr) { - if (history->source == SCHEDULE) - return sched_history_iget_time_t( history->sched_history , restart_nr); - else { - if (restart_nr == 0) - return ecl_sum_get_start_time( history->refcase ); - else - return ecl_sum_get_report_time( history->refcase , restart_nr ); - } -} - - -int history_get_restart_nr_from_time_t( const history_type * history , time_t time) { - if (time == history_get_start_time( history )) - return 0; - else { - if (history->source == SCHEDULE) - return sched_file_get_restart_nr_from_time_t( history->sched_file , time ); - else { - int report_step = ecl_sum_get_report_step_from_time( history->refcase , time ); - if (report_step >= 1) - return report_step; - else { - int mday,year,month; - util_set_date_values_utc( time , &mday , &month , &year); - util_abort("%s: Date: %02d/%02d/%04d does not cooincide with any report time. Aborting.\n", __func__ , mday , month , year); - return -1; - } - } - } -} - - -int history_get_restart_nr_from_days( const history_type * history , double sim_days) { - if (history->source == SCHEDULE) - return sched_file_get_restart_nr_from_days( history->sched_file , sim_days); - else { - int report_step = ecl_sum_get_report_step_from_days( history->refcase , sim_days); - if (report_step >= 1) - return report_step; - else { - util_abort("%s: Days:%g does not cooincide with any report time. Aborting.\n", __func__ , sim_days); - return -1; - } - } -} - - - diff --git a/ThirdParty/Ert/libsched/src/sched_blob.c b/ThirdParty/Ert/libsched/src/sched_blob.c deleted file mode 100644 index 1c1b394924..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_blob.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_blob.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include - -#include -#include -#include - - - - - -struct sched_blob_struct { - char * buffer; - time_t start_time; - sched_time_type * time_step; /* Either a date into the 'future' - or a TSTEP. This is the end time of the blob.*/ -}; - - - -static void sched_blob_append_buffer( sched_blob_type * blob , const char * new_buffer ) { - blob->buffer = util_strcat_realloc( blob->buffer , new_buffer ); -} - - -void sched_blob_append_token( sched_blob_type * blob , const char * token ) { - char * new_buffer = util_calloc( (strlen(token) + 2) , sizeof * new_buffer ); - sched_blob_append_buffer( blob , new_buffer ); - free( new_buffer ); -} - - - -sched_blob_type * sched_blob_alloc() { - sched_blob_type * blob = util_malloc( sizeof * blob ); - blob->buffer = NULL; - blob->time_step = NULL; - return blob; -} - - -int sched_blob_get_size( const sched_blob_type * blob ) { - if (blob->buffer == NULL) - return 0; - else - return strlen( blob->buffer ); -} - - - -void sched_blob_free( sched_blob_type * blob ) { - util_safe_free( blob->buffer ); - if (blob->time_step != NULL) - sched_time_free( blob->time_step ); - free( blob ); -} - - - - -void sched_blob_fprintf( const sched_blob_type * blob , FILE * stream ) { - fprintf(stream , "%s" , blob->buffer ); -} diff --git a/ThirdParty/Ert/libsched/src/sched_file.c b/ThirdParty/Ert/libsched/src/sched_file.c deleted file mode 100644 index 4a54d02720..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_file.c +++ /dev/null @@ -1,1013 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_file.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* This sched_file.c contains code for internalizing an ECLIPSE - schedule file. - - Two structs are defined in this file: - - 1. The sched_file_struct, which can be accessed externaly - through various interface functions. - - 2. The sched_block_struct, which is for internal use. - - The internalization function 'sched_file_parse' splits the ECLIPSE - schedule file into a sequence of 'sched_block_type's, where a single - block contains one or more keywords. Except for the first block, which - is empty per definition, the last keyword in a block will always be - a timing keyword like DATES or TSTEP. Thus, the number of blocks in - the sched_file_struct will always cooincide with the number of - restart files in the ECLIPSE simulation. In order to make this work, - TSTEP and DATES keyword containing multiple data, are split into - a sequence of keywords. - - Note the following: - - 1. This implies that scheduling data after the last timing - keyword is irrelevant. This is similar to how ECLIPSE works. - - 2. Scheduling data after keyword END is ignored, since this - is interpreted as the end of the SCHEDULE section. - -*/ - -#define SCHED_FILE_TYPE_ID 677198 - -struct sched_block_struct { - vector_type * kw_list; /* A list of sched_kw's in the block. */ - time_t block_start_time; - time_t block_end_time; - hash_type * kw_hash; /* Hash table indexed with kw_name - containing vectors of kw instances . */ -}; - - - -struct sched_file_struct { - UTIL_TYPE_ID_DECLARATION; - hash_type * fixed_length_table; /* A hash table of keywords with a fixed length, i.e. not '/' terminated. */ - vector_type * kw_list; - vector_type * kw_list_by_type; - vector_type * blocks; /* A list of chronologically sorted sched_block_type's. */ - stringlist_type * files; /* The name of the files which have been parsed to generate this sched_file instance. */ - time_t start_time; /* The start of the simulation. */ - bool hasEND; -}; - - - -/************************************************************************/ - - - -static sched_block_type * sched_block_alloc_empty() -{ - sched_block_type * block = util_malloc(sizeof * block); - block->kw_list = vector_alloc_new(); - block->kw_hash = hash_alloc(); - return block; -} - - - - - -static void sched_block_free(sched_block_type * block) -{ - vector_free( block->kw_list ); - hash_free( block->kw_hash ); - free(block); -} - - - -static void sched_block_free__(void * block) -{ - sched_block_free( (sched_block_type *) block); -} - - - -static void sched_block_add_kw(sched_block_type * block, const sched_kw_type * kw) -{ - vector_append_ref(block->kw_list , kw ); - if (!hash_has_key( block->kw_hash , sched_kw_get_name( kw ))) - hash_insert_hash_owned_ref( block->kw_hash , sched_kw_get_name( kw ) , vector_alloc_new() , vector_free__); - - { - vector_type * kw_vector = hash_get( block->kw_hash , sched_kw_get_name( kw )); - vector_append_ref( kw_vector , kw ); - } -} - - -sched_kw_type * sched_block_iget_kw(sched_block_type * block, int i) -{ - return vector_iget( block->kw_list , i); -} - - - - - -static void sched_block_fprintf(const sched_block_type * block, FILE * stream) -{ - int i; - for (i=0; i < vector_get_size(block->kw_list); i++) { - const sched_kw_type * sched_kw = vector_iget_const( block->kw_list , i); - sched_kw_fprintf(sched_kw, stream); - } -} - - - -int sched_block_get_size(const sched_block_type * block) -{ - return vector_get_size(block->kw_list); -} - - - - - -static sched_kw_type * sched_block_get_last_kw_ref(sched_block_type * block) -{ - int last_index = vector_get_size( block->kw_list ) - 1; - return sched_block_iget_kw( block , last_index ); -} - - - -static void sched_file_add_block(sched_file_type * sched_file, sched_block_type * block) -{ - vector_append_owned_ref(sched_file->blocks , block , sched_block_free__); -} - - - -sched_block_type * sched_file_iget_block(const sched_file_type * sched_file, int i) -{ - return vector_iget(sched_file->blocks , i); -} - -/** - This is a fucking mess: - - block[0] start_time - start_time - block[1] start_time - time of first report, i.e. X0001 - block[2] X0001 - X0002 - .... - - The reason for this funny convention is to ensure one-to-one index - correspondance between the restart files and the sched_file blocks - (I think ...). -*/ - - - -static void sched_file_build_block_dates(sched_file_type * sched_file) -{ - int num_restart_files = sched_file_get_num_restart_files(sched_file); - time_t curr_time, new_time; - - if(num_restart_files < 1) - util_abort("%s: Error - empty sched_file - aborting.\n", __func__); - - /* Special case for block 0. */ - sched_block_type * sched_block = sched_file_iget_block(sched_file, 0); - sched_block->block_start_time = sched_file->start_time ; - sched_block->block_end_time = sched_file->start_time ; - - curr_time = sched_file->start_time; - for(int i=1; iblock_start_time = curr_time; - - sched_kw_type * timing_kw = sched_block_get_last_kw_ref(sched_block); - new_time = sched_kw_get_new_time(timing_kw, curr_time); - - if(curr_time > new_time) - util_abort("%s: Schedule file contains negative timesteps - aborting.\n",__func__); - - curr_time = new_time; - sched_block->block_end_time = curr_time; - } -} - - - - -/******************************************************************************/ - - - -static void sched_file_add_kw( sched_file_type * sched_file , const sched_kw_type * kw) { - vector_append_owned_ref( sched_file->kw_list , kw , sched_kw_free__); -} - - -static void sched_file_update_index( sched_file_type * sched_file ) { - int ikw; - - - /* By type index */ - { - if (sched_file->kw_list_by_type != NULL) - vector_free( sched_file->kw_list_by_type ); - sched_file->kw_list_by_type = vector_alloc_NULL_initialized( NUM_SCHED_KW_TYPES ); - for (ikw = 0; ikw < vector_get_size( sched_file->kw_list ); ikw++) { - const sched_kw_type * kw = vector_iget_const( sched_file->kw_list , ikw ); - sched_kw_type_enum type = sched_kw_get_type( kw ); - { - vector_type * tmp = vector_iget( sched_file->kw_list_by_type , type ); - - if (tmp == NULL) { - tmp = vector_alloc_new(); - vector_iset_owned_ref( sched_file->kw_list_by_type , type , tmp , vector_free__ ); - } - - vector_append_ref( tmp , kw ); - } - } - } - - - - /* Block based on restart number. */ - { - time_t current_time; - sched_block_type * current_block; - vector_clear( sched_file->blocks ); - - /* - Adding a pseudo block at the start which runs from the start of - time (i.e. EPOCH start 01/01/1970) to simulation start. - */ - current_block = sched_block_alloc_empty( 0 ); - current_block->block_start_time = sched_file->start_time;//-1; /* Need this funny node - hhmmmmmm */ - current_block->block_end_time = sched_file->start_time; - sched_file_add_block( sched_file , current_block ); - - current_block = sched_block_alloc_empty( 0 ); - current_block->block_start_time = sched_file->start_time; - current_time = sched_file->start_time; - - for (ikw = 0; ikw < vector_get_size( sched_file->kw_list ); ikw++) { - const sched_kw_type * kw = vector_iget_const( sched_file->kw_list , ikw ); - sched_kw_type_enum type = sched_kw_get_type( kw ); - { - sched_block_add_kw( current_block , kw ); - if(type == DATES || type == TSTEP || type == TIME) { - /** - Observe that when we enocunter a time-based keyword we do the following: - - 1. Finish the the current block by setting the end_time - field and add this block to the sched_file - structure. - - 2. Create a new block starting at current time. - - ------- - - Blocks are not actually added to the sched_file instance - before they are terminated with a DATES/TSTEP - keyword. This implies that keywords which come after the - last DATES/TSTEP keyword are lost. - */ - - current_time = sched_kw_get_new_time( kw , current_time ); - - /* Finishing off the current block, and adding it to the sched_file. */ - current_block->block_end_time = current_time; - sched_file_add_block( sched_file , current_block ); - - /* Creating a new block - not yet added to the sched_file. */ - current_block = sched_block_alloc_empty( vector_get_size( sched_file->blocks )); - current_block->block_start_time = current_time; - } - } - } - /* - Free the last block, which has not been added to the sched_file - object. - */ - sched_block_free( current_block ); - } -} - - - -void sched_file_add_fixed_length_kw( sched_file_type * sched_file , const char * kw , int length ) { - hash_insert_int( sched_file->fixed_length_table, kw , length ); -} - - - -static void sched_file_init_fixed_length( sched_file_type * sched_file ) { - sched_file_add_fixed_length_kw(sched_file , "NEXTSTEP" , 1); - sched_file_add_fixed_length_kw(sched_file , "RPTSCHED" , 1); - sched_file_add_fixed_length_kw(sched_file , "DRSDT" , 1); - sched_file_add_fixed_length_kw(sched_file , "SKIPREST" , 0); - sched_file_add_fixed_length_kw(sched_file , "NOECHO" , 0); - sched_file_add_fixed_length_kw(sched_file , "ECHO" , 0); - sched_file_add_fixed_length_kw(sched_file , "RPTRST" , 1); - sched_file_add_fixed_length_kw(sched_file , "TUNING" , 3); - sched_file_add_fixed_length_kw(sched_file , "WHISTCTL" , 1); - sched_file_add_fixed_length_kw(sched_file , "TIME" , 1); - sched_file_add_fixed_length_kw(sched_file , "VAPPARS" , 1); - sched_file_add_fixed_length_kw(sched_file , "NETBALAN" , 1); - sched_file_add_fixed_length_kw(sched_file , "WPAVE" , 1); - sched_file_add_fixed_length_kw(sched_file , "VFPTABL" , 1); - sched_file_add_fixed_length_kw(sched_file , "GUIDERAT" , 1); - sched_file_add_fixed_length_kw(sched_file , "MESSAGES" , 1); - sched_file_add_fixed_length_kw(sched_file , "LIFTOPT" , 1); -} - - -sched_file_type * sched_file_alloc(time_t start_time) -{ - sched_file_type * sched_file = util_malloc(sizeof * sched_file); - UTIL_TYPE_ID_INIT( sched_file , SCHED_FILE_TYPE_ID); - sched_file->kw_list = vector_alloc_new(); - sched_file->kw_list_by_type = NULL; - sched_file->blocks = vector_alloc_new(); - sched_file->files = stringlist_alloc_new(); - sched_file->start_time = start_time; - sched_file->fixed_length_table = hash_alloc(); - sched_file->hasEND = false; - sched_file_init_fixed_length( sched_file ); - { - char * fixed_length_file = getenv("SCHEDULE_FIXED_LENGTH"); - if ((fixed_length_file != NULL) && (util_entry_readable( fixed_length_file ))) { - FILE * stream = util_fopen(fixed_length_file , "r"); - char kw[32]; - int len; - bool OK = true; - - do { - if (fscanf(stream , "%s %d" , kw , &len) == 2) - sched_file_add_fixed_length_kw( sched_file , kw , len); - else - OK = false; - } while (OK); - fclose( stream); - } - } - return sched_file; -} - - -UTIL_SAFE_CAST_FUNCTION(sched_file , SCHED_FILE_TYPE_ID); - - -void sched_file_free(sched_file_type * sched_file) -{ - vector_free( sched_file->blocks ); - vector_free( sched_file->kw_list ); - if (sched_file->kw_list_by_type != NULL) - vector_free( sched_file->kw_list_by_type ); - - stringlist_free( sched_file->files ); - hash_free( sched_file->fixed_length_table ); - free(sched_file); -} - - -/** - This function will allocate a time_t_vector instance, which - contains all the time_t values for this schedule_file - starting - with the start_date. -*/ - -time_t_vector_type * sched_file_alloc_time_t_vector( const sched_file_type * sched_file ) { - time_t_vector_type * vector = time_t_vector_alloc(0,0); - int i; - time_t_vector_append( vector , sched_file->start_time ); - for (i=1; i < vector_get_size( sched_file->blocks ); i++) { - const sched_block_type * block = vector_iget_const( sched_file->blocks , i ); - time_t_vector_append( vector , block->block_end_time ); - } - return vector; -} - - -static stringlist_type * sched_file_tokenize( const char * filename ) { - stringlist_type * token_list; - basic_parser_type * parser = basic_parser_alloc(" \t" , /* Splitters */ - "\'\"" , /* Quoters */ - "\n" , /* Specials - splitters which will be kept. */ - "\r" , /* Delete set - these are just deleted. */ - "--" , /* Comment start */ - "\n"); /* Comment end */ - bool strip_quote_marks = false; - token_list = basic_parser_tokenize_file( parser , filename , strip_quote_marks ); - basic_parser_free( parser ); - - return token_list; -} - - -/** - This function parses 'further', i.e typically adding another - schedule file to the sched_file instance. -*/ - -void sched_file_parse_append(sched_file_type * sched_file , const char * filename) { - bool foundEND = false; - stringlist_type * token_list = sched_file_tokenize( filename ); - sched_kw_type * current_kw; - int token_index = 0; - do { - sched_util_skip_newline( token_list , &token_index ); - current_kw = sched_kw_token_alloc(token_list , &token_index , sched_file->fixed_length_table, &foundEND); - if (current_kw != NULL) { - sched_kw_type_enum type = sched_kw_get_type(current_kw); - if (type == DATES || type == TSTEP || type == TIME) { - int i , num_steps; - sched_kw_type ** sched_kw_dates = sched_kw_split_alloc_DATES(current_kw, &num_steps); - sched_kw_free(current_kw); - - for(i=0; ihasEND = true; - - stringlist_append_copy( sched_file->files , filename ); - sched_file_build_block_dates(sched_file); - sched_file_update_index( sched_file ); - stringlist_free( token_list ); -} - - -void sched_file_simple_parse( const char * filename , time_t start_time) { - stringlist_type * token_list = sched_file_tokenize( filename ); - const int num_tokens = stringlist_get_size( token_list ); - int token_index = 0; - do { - sched_kw_type_enum kw_type = sched_kw_type_from_string( stringlist_iget( token_list , token_index )); - if ((kw_type == DATES) || (kw_type == TSTEP)) { - - } - } while( token_index < num_tokens ); - - stringlist_free( token_list ); -} - - - -void sched_file_parse(sched_file_type * sched_file, const char * filename) -{ - /* - Add the first empty pseudo block - this runs from time -infty:start_date. - */ - sched_file_add_block(sched_file , sched_block_alloc_empty()); - sched_file_parse_append( sched_file , filename ); -} - - - -sched_file_type * sched_file_parse_alloc(const char * filename , time_t start_date) { - sched_file_type * sched_file = sched_file_alloc( start_date ); - sched_file_parse(sched_file , filename); - return sched_file; -} - - - -int sched_file_get_num_restart_files(const sched_file_type * sched_file) -{ - return vector_get_size(sched_file->blocks); -} - - - -static void sched_file_fprintf_i__(const sched_file_type * sched_file, int last_restart_file, const char * file , bool addEND) -{ - FILE * stream = util_fopen(file, "w"); - int num_restart_files = sched_file_get_num_restart_files(sched_file); - - - last_restart_file = util_int_min( last_restart_file , num_restart_files - 1); - - if (last_restart_file > num_restart_files) { - util_abort("%s: you asked for restart nr:%d - the last available restart nr is: %d \n",__func__ , last_restart_file , num_restart_files); - /* Must abort here because the calling scope is expecting to find last_restart_file. */ - } - - for(int i=0; i<= last_restart_file; i++) - { - const sched_block_type * sched_block = vector_iget_const( sched_file->blocks , i); - sched_block_fprintf(sched_block, stream); - } - - if (addEND) - fprintf(stream, "END\n"); - - fclose(stream); -} - - -void sched_file_fprintf_i(const sched_file_type * sched_file, int last_restart_file, const char * file) { - sched_file_fprintf_i__( sched_file , last_restart_file , file , true); -} - - -/* Writes the complete schedule file. */ -void sched_file_fprintf(const sched_file_type * sched_file, const char * file) -{ - int num_restart_files = sched_file_get_num_restart_files(sched_file); - sched_file_fprintf_i__( sched_file , num_restart_files - 1 , file , sched_file->hasEND); -} - - - - - -/* - const char * sched_file_get_filename(const sched_file_type * sched_file) { - return sched_file->filename; - } -*/ - - -int sched_file_get_restart_nr_from_time_t(const sched_file_type * sched_file, time_t time) -{ - int num_restart_files = sched_file_get_num_restart_files(sched_file); - for( int i=0; i time) { - int mday,year,month; - util_set_date_values_utc( time , &mday , &month , &year); - util_abort("%s: Date: %02d/%02d/%04d does not cooincide with any report time. Aborting.\n", __func__ , mday , month , year); - } else if (block_end_time == time) - return i; - } - - // If we are here, time did'nt correspond a restart file. Abort. - { - int mday,year,month; - util_set_date_values_utc( time , &mday , &month , &year); - util_abort("%s: Date: %02d/%02d/%04d does not cooincide with any report time. Aborting.\n", __func__ , mday , month , year); - } - return 0; -} - - -/** - This function finds the restart_nr for the a number of days after - simulation start. -*/ - -int sched_file_get_restart_nr_from_days(const sched_file_type * sched_file , double days) { - time_t time = sched_file_iget_block_start_time(sched_file, 0); - util_inplace_forward_days_utc( &time , days); - return sched_file_get_restart_nr_from_time_t(sched_file , time); -} - - - -time_t sched_file_iget_block_start_time(const sched_file_type * sched_file, int i) -{ - sched_block_type * block = sched_file_iget_block(sched_file, i); - return block->block_start_time; -} - - - -time_t sched_file_iget_block_end_time(const sched_file_type * sched_file, int i) -{ - sched_block_type * block = sched_file_iget_block(sched_file, i); - return block->block_end_time; -} - - -double sched_file_iget_block_start_days(const sched_file_type * sched_file, int i) -{ - sched_block_type * block = sched_file_iget_block(sched_file, i); - return util_difftime_days( sched_file->start_time , block->block_start_time ); -} - - -double sched_file_iget_block_end_days(const sched_file_type * sched_file, int i) -{ - sched_block_type * block = sched_file_iget_block(sched_file, i); - return util_difftime_days( sched_file->start_time , block->block_end_time ); -} - - -double sched_file_get_sim_days(const sched_file_type * sched_file , int report_step) { - return sched_file_iget_block_end_days( sched_file , report_step ); -} - - -time_t sched_file_get_sim_time(const sched_file_type * sched_file , int report_step) { - return sched_file_iget_block_end_time( sched_file , report_step ); -} - - -const char * sched_file_iget_filename( const sched_file_type * sched_file , int file_nr ) { - return stringlist_iget( sched_file->files , file_nr ); -} - - - - -int sched_file_iget_block_size(const sched_file_type * sched_file, int block_nr) -{ - sched_block_type * block = sched_file_iget_block(sched_file, block_nr); - return sched_block_get_size(block); -} - - - -sched_kw_type * sched_file_ijget_block_kw_ref(const sched_file_type * sched_file, int block_nr, int kw_nr) -{ - sched_block_type * block = sched_file_iget_block(sched_file, block_nr); - sched_kw_type * sched_kw = sched_block_iget_kw(block, kw_nr); - return sched_kw; -} - - - -static void __sched_file_summarize_line(int restart_nr , time_t start_time , time_t t , FILE * stream) { - double days = util_difftime( start_time , t , NULL , NULL , NULL , NULL) / (24 * 3600); - int mday , month , year; - - util_set_date_values_utc(t , &mday , &month , &year); - fprintf(stream , "%02d/%02d/%04d %7.1f days %04d \n", mday , month , year , days , restart_nr); -} - - - - -void sched_file_summarize(const sched_file_type * sched_file , FILE * stream) { - int len = sched_file_get_num_restart_files(sched_file); - time_t start_time = sched_file_iget_block_start_time(sched_file , 0); - for(int i=1; istart_time); - - for (ikw = 0; ikw < vector_get_size( src->kw_list ); ikw++) { - sched_kw_type * kw = vector_iget( src->kw_list , ikw ); - sched_file_add_kw( target , kw ); - } - - - { - int i; - for (i = 0; i < stringlist_get_size( src->files ); i++) { - if (deep_copy) - stringlist_append_copy( target->files , stringlist_iget(src->files , i)); - else - stringlist_append_ref( target->files , stringlist_iget(src->files , i)); - } - } - - sched_file_update_index( target ); - return target; -} - - -/*****************************************************************/ - - -static void sched_file_update_block(sched_block_type * block , - int restart_nr, - sched_kw_type_enum kw_type , - sched_file_callback_ftype * callback, - void * arg) { - int ikw; - for (ikw = 0; ikw < vector_get_size(block->kw_list); ikw++) { - sched_kw_type * sched_kw = sched_block_iget_kw( block , ikw); - if (sched_kw_get_type( sched_kw ) == kw_type) - callback( sched_kw_get_data( sched_kw) , restart_nr , arg); /* Calling back to 'user-space' to actually do the update. */ - } -} - - - -/** - This function is designed to facilitate 'user-space' update of the - keywords in the schedule file based on callbacks. The function is - called with two report steps, a type ID of the sched_kw type which - should be updated, and a function pointer which will be invoked on - all the relevant keywords. -*/ - - - -void sched_file_update_blocks(sched_file_type * sched_file, - int restart1 , - int restart2 , - sched_kw_type_enum kw_type, - sched_file_callback_ftype * callback, - void * callback_arg) { - - int restart_nr; - if (restart2 > sched_file_get_num_restart_files(sched_file)) - restart2 = sched_file_get_num_restart_files(sched_file) - 1; - - for (restart_nr = restart1; restart_nr <= restart2; restart_nr++) { - sched_block_type * sched_block = sched_file_iget_block( sched_file , restart_nr ); - sched_file_update_block( sched_block , restart_nr , kw_type , callback , callback_arg); - } -} - - - -/** - Update a complete schedule file by using callbacks to - 'user-space'. Say for instance you want to scale up the oilrate in - well P1. This could be achieved with the following code: - - -- This function is written by the user of the library - in a remote scope. - - void increase_orat_callback(void * void_kw , int restart_nr , void * arg) { - double scale_factor = *(( double * ) arg); - sched_kw_wconhist_type * kw = sched_kw_wconhist_safe_cast( void_kw ); - sched_kw_wconhist_scale_orat( wconhist_kw , "P1" , scale_factor); - } - - .... - .... - - sched_file_update(sched_file , WCONHIST , increase_orat_callback , &scale_factor); - - Observe the following about the callback: - - * The sched_kw input argument comes as a void pointer, and an - sched_kw_xxx_safe_cast() function should be used on input to - check. - - * The user-space level does *NOT* have access to the internals - of the sched_kw_xxxx type, so the library must provide - functions for the relevant state modifications. - - * The last argumnt (void * arg) - can of course be anything and - his brother. - -*/ - - -void sched_file_update(sched_file_type * sched_file, - sched_kw_type_enum kw_type, - sched_file_callback_ftype * callback, - void * callback_arg) { - - sched_file_update_blocks(sched_file , 1 , sched_file_get_num_restart_files(sched_file) - 1 , kw_type , callback , callback_arg); - -} - - - -/*****************************************************************/ -/** - This function will count the number of TSTEP / DATES keywords in a - schedule file, without actually internalizing the file. This - function 'should' be used for schedule files which we do not manage - to parse. -*/ - -int sched_file_step_count( const char * filename ) { - stringlist_type * token_list = sched_file_tokenize( filename ); - int token_index = 0; - int step_count = 0; - do { - const char * current_token = stringlist_iget( token_list , token_index ); - sched_kw_type_enum kw_type = sched_kw_type_from_string( current_token ); - - if (kw_type == DATES) { - sched_kw_type * sched_kw = sched_kw_token_alloc( token_list , &token_index , NULL , NULL); - const sched_kw_dates_type * dates_kw = sched_kw_get_data( sched_kw ); - step_count += sched_kw_dates_get_size( dates_kw ); - sched_kw_free( sched_kw ); - } else if (kw_type == TSTEP ) { - sched_kw_type * sched_kw = sched_kw_token_alloc( token_list , &token_index , NULL , NULL); - const sched_kw_tstep_type * tstep_kw = sched_kw_get_data( sched_kw ); - step_count += sched_kw_tstep_get_length( tstep_kw ); - sched_kw_free( sched_kw ); - } else - token_index++; - - } while ( token_index < stringlist_get_size( token_list )); - stringlist_free( token_list ); - return step_count; -} - - -/*****************************************************************/ - - -//void sched_file_merge( const char * filename , time_t start_date , time_t insert_date , bool append_string , const char * insert_string) { -// stringlist_type * token_list = sched_file_tokenize( filename ); -// int token_index = 0; -// int step_count = 0; -// bool has_date = false; -// -// do { -// time_t current_time = start_date; -// const char * current_token = stringlist_iget( token_list , token_index ); -// sched_kw_type_enum kw_type = sched_kw_type_from_string( current_token ); -// -// if ((kw_type == DATES) || (kw_type == TSTEP)) { -// int istep , num_step; -// sched_kw_type * sched_kw = sched_kw_token_alloc( token_list , &token_index , NULL); -// sched_kw_type ** split_kw = sched_kw_split_alloc_DATES( sched_kw , &num_step ); -// -// for (istep = 0; istep < num_step; istep++) { -// if (kw_type == DATES) { -// const sched_kw_dates_type * dates_kw = sched_kw_get_data( sched_kw ); -// current_time = sched_kw_dates_iget_date( dates_kw , 0 ); -// } -// if (current_time == insert_date) { -// /* -// We are currently looking at a DATES keyword EXACTLY at -// the date we should insert at. If append_string == false -// we let the new string go in immediately, otherwise we set -// has_date to true and continue one more time_step (then -// the current_time > insert_date test will kick in). -// */ -// has_date = true; -// if (!append_string) { -// -// } -// } -// } -// sched_kw_free( sched_kw ); -// -// } else -// token_index++; -// -// } while ( token_index < stringlist_get_size( token_list )); -// -//} -// - - -/*****************************************************************/ - - - -/** - Currently ONLY applicable to WCONHIST producers. - - -*/ - -bool sched_file_well_open( const sched_file_type * sched_file , - int restart_nr , - const char * well_name) { - - bool well_found = false; - bool well_open = false; - int block_nr = restart_nr; - while (!well_found && (block_nr >= 0)) { - sched_block_type * block = sched_file_iget_block( sched_file , block_nr ); - - if (hash_has_key( block->kw_hash , "WCONHIST")) { - const vector_type * wconhist_vector = hash_get( block->kw_hash , "WCONHIST"); - int i; - for (i=0; i < vector_get_size( wconhist_vector ); i++) { - const sched_kw_type * kw = vector_iget_const( wconhist_vector , i ); - if (sched_kw_has_well( kw , well_name )) { - well_found = true; - well_open = sched_kw_well_open( kw , well_name ); - } - } - } - - - if (hash_has_key( block->kw_hash , "WCONINJE")) { - const vector_type * wconinje_vector = hash_get( block->kw_hash , "WCONINJE"); - int i; - for (i=0; i < vector_get_size( wconinje_vector ); i++) { - const sched_kw_type * kw = vector_iget_const( wconinje_vector , i ); - if (sched_kw_has_well( kw , well_name )) { - well_found = true; - well_open = sched_kw_well_open( kw , well_name ); - } - } - } - - - - block_nr--; - } - return well_open; -} - - - - - -double sched_file_well_wconhist_rate( const sched_file_type * sched_file , - int restart_nr , - const char * well_name) { - double rate = -1; - bool well_found = false; - int block_nr = restart_nr; - - while (!well_found && (block_nr >= 0)) { - sched_block_type * block = sched_file_iget_block( sched_file , block_nr ); - - if (hash_has_key( block->kw_hash , "WCONHIST")) { - const vector_type * wconhist_vector = hash_get( block->kw_hash , "WCONHIST"); - int i; - for (i=0; i < vector_get_size( wconhist_vector ); i++) { - sched_kw_type * kw = vector_iget( wconhist_vector , i ); - if (sched_kw_has_well( kw , well_name )) { - well_found = true; - rate = sched_kw_wconhist_get_orat( sched_kw_get_data( kw ) , well_name ); - } - } - } - block_nr--; - } - return rate; -} - - - -double sched_file_well_wconinje_rate( const sched_file_type * sched_file , - int restart_nr , - const char * well_name) { - double rate = -1; - bool well_found = false; - int block_nr = restart_nr; - - while (!well_found && (block_nr >= 0)) { - sched_block_type * block = sched_file_iget_block( sched_file , block_nr ); - - if (hash_has_key( block->kw_hash , "WCONINJE")) { - const vector_type * wconhist_vector = hash_get( block->kw_hash , "WCONINJE"); - int i; - for (i=0; i < vector_get_size( wconhist_vector ); i++) { - sched_kw_type * kw = vector_iget( wconhist_vector , i ); - if (sched_kw_has_well( kw , well_name )) { - well_found = true; - rate = sched_kw_wconinje_get_surface_flow( sched_kw_get_data( kw ) , well_name ); - } - } - } - - block_nr--; - } - return rate; -} - diff --git a/ThirdParty/Ert/libsched/src/sched_history.c b/ThirdParty/Ert/libsched/src/sched_history.c deleted file mode 100644 index adb732ca85..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_history.c +++ /dev/null @@ -1,756 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_history.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -struct sched_history_struct { - hash_type * well_history; /* Hash table of well_history_type instances. */ - hash_type * group_history; - time_t_vector_type * time; - hash_type * index; - char * sep_string; - bool_vector_type * historical; /* This is meant to flag whether a certain report_step is "historical", or - if it is in prediction_mode; changing back and forth between the two - modes seem quite broken behaviour, but I guess it is perfectly - legitimate. */ - int last_history_step; /* The last historical report_step (i.e. the total length is 1+ this value). */ -}; - - -#define FIELD_GROUP "FIELD" - - - - - -/*****************************************************************/ - -well_history_type * sched_history_get_well( const sched_history_type * sched_history , const char * well_name ); - - - -static void sched_history_install_well_index( sched_history_type * sched_history , well_index_type * well_index , const char ** var_list , const char * well_name) { - int index = 0; - char * gen_key = NULL; - const char * var = var_list[ index ]; - bool first = true; - - while ( var != NULL ) { - gen_key = util_realloc_sprintf( gen_key , "%s%s%s" , var , sched_history->sep_string , well_name ); - - if (first) { - first = false; - hash_insert_hash_owned_ref( sched_history->index , gen_key , well_index , well_index_free__); - } else - hash_insert_ref( sched_history->index , gen_key , well_index ); - - index++; - var = var_list[ index ]; - } - - if (first) - util_abort("%s: internal error - empty var_list \n",__func__); - free( gen_key ); -} - - - -static void sched_history_install_group_index( sched_history_type * sched_history , group_index_type * group_index , const char ** var_list , const char * group_name) { - int index = 0; - char * gen_key = NULL; - const char * var = var_list[ index ]; - bool first = true; - - while ( var != NULL ) { - gen_key = util_realloc_sprintf( gen_key , "%s%s%s" , var , sched_history->sep_string , group_name ); - - if (first) { - first = false; - hash_insert_hash_owned_ref( sched_history->index , gen_key , group_index , group_index_free__); - } else - hash_insert_ref( sched_history->index , gen_key , group_index ); - - index++; - var = var_list[ index ]; - } - - if (first) - util_abort("%s: internal error - empty var_list \n",__func__); - free( gen_key ); -} - - - - - -#define VAR_LIST(...) (const char *[]) { __VA_ARGS__ , NULL } - -void sched_history_install_index( sched_history_type * sched_history ) { - /*1: Installing well based keys like WOPRH. */ - { - hash_iter_type * well_iter = hash_iter_alloc( sched_history->well_history ); - while (!hash_iter_is_complete( well_iter )) { - const char * well_name = hash_iter_get_next_key( well_iter ); - const well_history_type * well = hash_get( sched_history->well_history , well_name ); - - /* WOPR */ - { - well_index_type * well_index = well_index_alloc( well_name , "WOPRH" , well , WCONHIST , wconhist_state_iget_WOPRH ); - sched_history_install_well_index( sched_history , well_index , VAR_LIST("WOPR" , "WOPRH") , well_name); - } - - - /* WGPR */ - { - well_index_type * well_index = well_index_alloc( well_name , "WGPRH" , well , WCONHIST , wconhist_state_iget_WGPRH ); - sched_history_install_well_index( sched_history , well_index , VAR_LIST("WGPR" , "WGPRH") , well_name); - } - - - /* WWPR */ - { - well_index_type * well_index = well_index_alloc( well_name , "WWPRH" , well , WCONHIST , wconhist_state_iget_WWPRH ); - sched_history_install_well_index( sched_history , well_index , VAR_LIST("WWPR" , "WWPRH") , well_name); - } - - - /* WWCT */ - { - well_index_type * well_index = well_index_alloc( well_name , "WWCTH" , well , WCONHIST , wconhist_state_iget_WWCTH ); - sched_history_install_well_index( sched_history , well_index , VAR_LIST("WWCT" , "WWCTH") , well_name); - } - - /* WGOR */ - { - well_index_type * well_index = well_index_alloc( well_name , "WGORH" , well , WCONHIST , wconhist_state_iget_WGORH ); - sched_history_install_well_index( sched_history , well_index , VAR_LIST("WGOR" , "WGORH") , well_name); - } - - /* WGPT */ - { - well_index_type * well_index = well_index_alloc( well_name , "WGPTH" , well , WCONHIST , wconhist_state_iget_WGPTH ); - sched_history_install_well_index( sched_history , well_index , VAR_LIST("WGPT" , "WGPTH") , well_name); - } - - /* WOPT */ - { - well_index_type * well_index = well_index_alloc( well_name , "WOPTH" , well , WCONHIST , wconhist_state_iget_WOPTH ); - sched_history_install_well_index( sched_history , well_index , VAR_LIST("WOPT" , "WOPTH") , well_name); - } - - /* WWPT */ - { - well_index_type * well_index = well_index_alloc( well_name , "WWPTH" , well , WCONHIST , wconhist_state_iget_WWPTH ); - sched_history_install_well_index( sched_history , well_index , VAR_LIST("WWPT" , "WWPTH") , well_name); - } - - /* STAT */ - { - well_index_type * well_index = well_index_alloc( well_name , "STAT" , well , WCONHIST , wconhist_state_iget_STAT ); - sched_history_install_well_index( sched_history , well_index , VAR_LIST("STAT" ) , well_name); - } - - - /* WWIRH - this can be got from _either_ the WCONINJH keyowrord - or the WCONINJE keyword (provided the latter is in rate - controlled mode. ) */ - { - well_index_type * well_index = well_index_alloc( well_name , "WWIRH" , well , WCONINJH , wconinjh_state_iget_WWIRH ); /* The first type */ - well_index_add_type( well_index , WCONINJE , wconinje_state_iget_WWIRH ); /* The second type */ - sched_history_install_well_index( sched_history , well_index , VAR_LIST("WWIRH" , "WWIR") , well_name); - } - - /* WGIRH - this can be got from _either_ the WCONINJH keyowrord - or the WCONINJE keyword (provided the latter is in rate - controlled mode. ) */ - { - well_index_type * well_index = well_index_alloc( well_name , "WGIRH" , well , WCONINJH , wconinjh_state_iget_WGIRH ); /* The first type */ - well_index_add_type( well_index , WCONINJE , wconinje_state_iget_WGIRH ); /* The second type */ - sched_history_install_well_index( sched_history , well_index , VAR_LIST("WGIRH" , "WGIR") , well_name); - } - } - hash_iter_free( well_iter ); - } - - - - /*2: Installing group based indices */ - { - hash_iter_type * group_iter = hash_iter_alloc( sched_history->group_history ); - while (!hash_iter_is_complete( group_iter )) { - const char * group_name = hash_iter_get_next_key( group_iter ); - const group_history_type * group = hash_get( sched_history->group_history , group_name ); - - /* GOPR */ - { - group_index_type * group_index = group_index_alloc( group_name , "GOPRH" , group , group_history_iget_GOPRH ); - sched_history_install_group_index( sched_history , group_index , VAR_LIST("GOPR" , "GOPRH") , group_name); - } - - /* GGPR */ - { - group_index_type * group_index = group_index_alloc( group_name , "GGPRH" , group , group_history_iget_GGPRH ); - sched_history_install_group_index( sched_history , group_index , VAR_LIST("GGPR" , "GGPRH") , group_name); - } - - /* GWPR */ - { - group_index_type * group_index = group_index_alloc( group_name , "GWPRH" , group , group_history_iget_GWPRH ); - sched_history_install_group_index( sched_history , group_index , VAR_LIST("GWPR" , "GWPRH") , group_name); - } - - /* GWCT */ - { - group_index_type * group_index = group_index_alloc( group_name , "GWCTH" , group , group_history_iget_GWCTH ); - sched_history_install_group_index( sched_history , group_index , VAR_LIST("GWCT" , "GWCTH") , group_name); - } - - /* GGOR */ - { - group_index_type * group_index = group_index_alloc( group_name , "GGORH" , group , group_history_iget_GGORH ); - sched_history_install_group_index( sched_history , group_index , VAR_LIST("GGOR" , "GGORH") , group_name); - } - - /* GOPT */ - { - group_index_type * group_index = group_index_alloc( group_name , "GOPTH" , group , group_history_iget_GOPTH ); - sched_history_install_group_index( sched_history , group_index , VAR_LIST("GOPT" , "GOPTH") , group_name); - } - - /* GGPT */ - { - group_index_type * group_index = group_index_alloc( group_name , "GGPTH" , group , group_history_iget_GGPTH ); - sched_history_install_group_index( sched_history , group_index , VAR_LIST("GGPT" , "GGPTH") , group_name); - } - - /* GWPT */ - { - group_index_type * group_index = group_index_alloc( group_name , "GWPTH" , group , group_history_iget_GWPTH ); - sched_history_install_group_index( sched_history , group_index , VAR_LIST("GWPT" , "GWPTH") , group_name); - } - } - hash_iter_free( group_iter ); - } - - - /*3: Installing field based indices (which is just an alias to the FIELD group); */ - { - const group_history_type * group = hash_get( sched_history->group_history , FIELD_GROUP ); - const char * group_name = FIELD_GROUP; - - /* FWPRH */ - { - group_index_type * group_index = group_index_alloc( group_name , "GWPRH" , group , group_history_iget_GWPRH ); - hash_insert_hash_owned_ref( sched_history->index , "FWPRH" , group_index , group_index_free__ ); - hash_insert_ref( sched_history->index , "FWPR" , group_index); - } - - /* FOPRH */ - { - group_index_type * group_index = group_index_alloc( group_name , "GOPRH" , group , group_history_iget_GOPRH ); - hash_insert_hash_owned_ref( sched_history->index , "FOPRH" , group_index , group_index_free__ ); - hash_insert_ref( sched_history->index , "FOPR" , group_index); - } - - /* FGPRH */ - { - group_index_type * group_index = group_index_alloc( group_name , "GGPRH" , group , group_history_iget_GGPRH ); - hash_insert_hash_owned_ref( sched_history->index , "FGPRH" , group_index , group_index_free__ ); - hash_insert_ref( sched_history->index , "FGPR" , group_index); - } - - /* FWPTH */ - { - group_index_type * group_index = group_index_alloc( group_name , "GWPTH" , group , group_history_iget_GWPTH ); - hash_insert_hash_owned_ref( sched_history->index , "FWPTH" , group_index , group_index_free__ ); - hash_insert_ref( sched_history->index , "FWPT" , group_index); - } - - /* FOPTH */ - { - group_index_type * group_index = group_index_alloc( group_name , "GOPTH" , group , group_history_iget_GOPTH ); - hash_insert_hash_owned_ref( sched_history->index , "FOPTH" , group_index , group_index_free__ ); - hash_insert_ref( sched_history->index , "FOPT" , group_index); - } - - /* FGPTH */ - { - group_index_type * group_index = group_index_alloc( group_name , "GGPTH" , group , group_history_iget_GGPTH ); - hash_insert_hash_owned_ref( sched_history->index , "FGPTH" , group_index , group_index_free__ ); - hash_insert_ref( sched_history->index , "FGPT" , group_index); - } - - /* FGORH */ - { - group_index_type * group_index = group_index_alloc( group_name , "GGORH" , group , group_history_iget_GGORH ); - hash_insert_hash_owned_ref( sched_history->index , "FGORH" , group_index , group_index_free__ ); - hash_insert_ref( sched_history->index , "FGOR" , group_index); - } - - /* FWCTH */ - { - group_index_type * group_index = group_index_alloc( group_name , "GWCTH" , group , group_history_iget_GWCTH ); - hash_insert_hash_owned_ref( sched_history->index , "FWCTH" , group_index , group_index_free__ ); - hash_insert_ref( sched_history->index , "FWCT" , group_index); - } - } -} -#undef VAR_LIST - - - - -double sched_history_iget( const sched_history_type * sched_history , const char * key , int report_step) { - void * index = hash_get( sched_history->index , key ); - if (!bool_vector_safe_iget( sched_history->historical , report_step )) - fprintf(stderr,"** Warning - report step:%d is in the prediction phase - can NOT ask for historical data! \n",report_step); - - if (well_index_is_instance( index )) - return well_history_iget( index , report_step ); - else if (group_index_is_instance( index )) - return group_history_iget( index , report_step ); - else { - util_abort("%s: can not determine internal type of:%s - fatal internal error\n", __func__ , key); - return 0; - } -} - - - - - - -void sched_history_init_vector( const sched_history_type * sched_history , const char * key , double_vector_type * value) { - const bool * historical = bool_vector_get_ptr( sched_history->historical ); - double_vector_reset( value ); - for (int i=0; i < time_t_vector_size( sched_history->time ); i++) { - if (historical[i]) - double_vector_iset( value , i , sched_history_iget( sched_history , key , i)); - else - break; - } -} - - - -static void sched_history_realloc( sched_history_type * sched_history ) { - if (sched_history->well_history != NULL) - hash_free( sched_history->well_history ); - sched_history->well_history = hash_alloc(); - - if (sched_history->group_history != NULL) - hash_free( sched_history->group_history ); - sched_history->group_history = hash_alloc(); - - if (sched_history->historical != NULL) - bool_vector_free( sched_history->historical ); - sched_history->historical = bool_vector_alloc( 0 , true ); - - if (sched_history->time != NULL) - time_t_vector_free(sched_history->time); - sched_history->time = time_t_vector_alloc( 0 , 0 ); - sched_history->last_history_step = 0; -} - - - -time_t sched_history_iget_time_t( const sched_history_type * sched_history , int restart_nr ) { - return time_t_vector_iget( sched_history->time , restart_nr ); -} - - -sched_history_type * sched_history_alloc( const char * sep_string ) { - sched_history_type * sched_history = util_malloc( sizeof * sched_history ); - - sched_history->well_history = NULL; - sched_history->group_history = NULL; - sched_history->time = NULL; - sched_history->historical = NULL; - sched_history->index = hash_alloc(); - sched_history->sep_string = util_alloc_string_copy( sep_string ); - sched_history_realloc( sched_history ); - - return sched_history; -} - - - -void sched_history_free( sched_history_type * sched_history ) { - time_t_vector_free( sched_history->time ); - bool_vector_free( sched_history->historical ); - hash_free( sched_history->well_history ); - hash_free( sched_history->group_history ); - hash_free( sched_history->index ); - free( sched_history->sep_string ); - free( sched_history ); -} - - - -well_history_type * sched_history_get_well( const sched_history_type * sched_history , const char * well_name ) { - return hash_get( sched_history->well_history , well_name ); -} - - -group_history_type * sched_history_get_group( const sched_history_type * sched_history , const char * group_name ) { - return hash_get( sched_history->group_history , group_name ); -} - - - -static void sched_history_add_wells( sched_history_type * sched_history , const sched_kw_welspecs_type * welspecs , const stringlist_type * wells) { - for (int iw = 0; iw < stringlist_get_size( wells ); iw++) { - const char * well = stringlist_iget( wells , iw ); - if (!hash_has_key( sched_history->well_history , well)) - hash_insert_hash_owned_ref( sched_history->well_history , well , well_history_alloc( well , sched_history->time ), well_history_free__ ); - - /* Could possibly extract more information from the welspecs - keyword and update well_history object here, but it does not - seem to contain any more interesting info??? - */ - - } -} - - -static void sched_history_add_group( sched_history_type * sched_history , group_history_type * new_group, group_history_type * parent_group , int report_step ) { - hash_insert_hash_owned_ref( sched_history->group_history , group_history_get_name( new_group ) , new_group , group_history_free__ ); - if (parent_group == NULL) - parent_group = sched_history_get_group( sched_history , FIELD_GROUP ); - - group_history_add_child( parent_group , new_group , group_history_get_name( new_group ) , report_step ); -} - - -/** - Because the FIELD group is added without any parent; it does not - use the standard sched_history_group_add() function. */ - -static void sched_history_add_FIELD_group( sched_history_type * sched_history ) { - group_history_type * field_group = group_history_alloc( FIELD_GROUP , sched_history->time , 0 ); - hash_insert_hash_owned_ref( sched_history->group_history , FIELD_GROUP , field_group , group_history_free__ ); -} - - -void sched_history_fprintf_group_structure( sched_history_type * sched_history , int report_step ) { - group_history_type * field_group = sched_history_get_group( sched_history , FIELD_GROUP ); - group_history_fprintf( field_group , report_step , true ,stdout ); -} - - -static void sched_history_add_groups_gruptree( sched_history_type * sched_history , const sched_kw_gruptree_type * gruptree , int report_step , const stringlist_type * child_groups , const stringlist_type * parent_groups) { - for (int i = 0; i < stringlist_get_size( child_groups ); i++) { - const char * parent_group_name = stringlist_iget( parent_groups , i ); - const char * child_group_name = stringlist_iget( child_groups , i ); - group_history_type * parent_group; - group_history_type * child_group; - - - if (!hash_has_key( sched_history->group_history , parent_group_name )) - sched_history_add_group( sched_history , group_history_alloc( parent_group_name , sched_history->time , report_step) , NULL , report_step ); - parent_group = sched_history_get_group( sched_history , parent_group_name ); - - if (!hash_has_key( sched_history->group_history , child_group_name )) - sched_history_add_group( sched_history , group_history_alloc( child_group_name , sched_history->time , report_step ) , parent_group , report_step ); - child_group = sched_history_get_group( sched_history , child_group_name ); - - group_history_add_child( parent_group , child_group , child_group_name , report_step); - } -} - - -int sched_history_get_last_history( const sched_history_type * sched_history ) { - return sched_history->last_history_step; -} - - -static void sched_history_set_historical( sched_history_type * sched_history , int report_step ) { - bool_vector_iset_default( sched_history->historical , report_step , true ); - sched_history->last_history_step = report_step; -} - - -/** - When new wells are added with the WELSPECS keyword their parent - group is implicitly introduced as the second argument of the - WELSPEC keyword, in addition the GRUPTREE keyword will also - implicitly introduce groups. - - This functions creates group_history objects for all the groups - introduced by the WELSPECS keyword, and attach wells to them (the - input parameters @wells and @groups come driectly from the welspecs - keyword, via the sched_kw_welspecs_init_child_parent_list() - function. -*/ - - -static void sched_history_add_groups_welspecs( sched_history_type * sched_history , const sched_kw_welspecs_type * welspecs , int report_step , const stringlist_type * wells, const stringlist_type * groups) { - for (int i = 0; i < stringlist_get_size( groups ); i++) { - const char * group_name = stringlist_iget( groups , i ); - const char * well_name = stringlist_iget( wells , i ); - well_history_type * well = sched_history_get_well( sched_history , well_name ); - group_history_type * group; - if (!hash_has_key( sched_history->group_history , group_name )) - sched_history_add_group( sched_history , group_history_alloc( group_name , sched_history->time , report_step ) , NULL , report_step ); - - group = sched_history_get_group( sched_history , group_name ); - group_history_add_child( group , well , well_name , report_step); - } -} - - - - -void sched_history_update( sched_history_type * sched_history, const sched_file_type * sched_file ) { - - sched_history_realloc( sched_history ); - sched_history_add_FIELD_group( sched_history ); - { - int block_nr; - stringlist_type * well_list = stringlist_alloc_new(); - stringlist_type * group_list = stringlist_alloc_new(); - - for (block_nr = 0; block_nr < sched_file_get_num_restart_files( sched_file ); block_nr++) { - sched_block_type * block = sched_file_iget_block( sched_file , block_nr ); - int kw_nr; - int report_step = block_nr; - - time_t_vector_iset( sched_history->time , block_nr , sched_file_iget_block_end_time( sched_file , block_nr)); - for (kw_nr = 0; kw_nr < sched_block_get_size( block ); kw_nr++) { - sched_kw_type * kw = sched_block_iget_kw( block , kw_nr ); - sched_kw_type_enum kw_type = sched_kw_get_type( kw ); - - switch( kw_type ) { - case(WCONHIST): - { - const sched_kw_wconhist_type * wconhist = sched_kw_get_data( kw ); - sched_kw_wconhist_init_well_list( wconhist , well_list ); - int iw; - for (iw = 0; iw < stringlist_get_size( well_list ); iw++) { - const char * well_name = stringlist_iget( well_list , iw ); - well_history_type * well_history = sched_history_get_well( sched_history , well_name ); - well_history_add_keyword( well_history , kw , report_step ); - } - } - sched_history_set_historical( sched_history , block_nr ); - break; - case(WCONPROD): /* This is only added to turn the well OFF from WCONHIST behaviour. It is currently not - possible to query the well for anything when it is in WCONPROD state. */ - - { - const sched_kw_wconprod_type * wconprod = sched_kw_get_data( kw ); - sched_kw_wconprod_init_well_list( wconprod , well_list ); - int iw; - for (iw = 0; iw < stringlist_get_size( well_list ); iw++) { - const char * well_name = stringlist_iget( well_list , iw ); - well_history_type * well_history = sched_history_get_well( sched_history , well_name ); - well_history_add_keyword( well_history , kw , report_step); - } - } - bool_vector_iset_default( sched_history->historical , block_nr , false ); - break; - case(WCONINJE): - { - const sched_kw_wconinje_type * wconinje = sched_kw_get_data( kw ); - sched_kw_wconinje_init_well_list( wconinje , well_list ); - int iw; - for (iw = 0; iw < stringlist_get_size( well_list ); iw++) { - const char * well_name = stringlist_iget( well_list , iw ); - well_history_type * well_history = sched_history_get_well( sched_history , well_name ); - well_history_add_keyword( well_history , kw , report_step); - } - if (sched_kw_wconinje_historical( wconinje )) - sched_history_set_historical( sched_history , block_nr ); - } - break; - case(WCONINJH): - /* ... */ - sched_history_set_historical( sched_history , block_nr ); - break; - case(WELSPECS): - { - const sched_kw_welspecs_type * welspecs = sched_kw_get_data( kw ); - sched_kw_welspecs_init_child_parent_list( welspecs , well_list , group_list ); - sched_history_add_wells( sched_history , welspecs , well_list ); - sched_history_add_groups_welspecs( sched_history , welspecs , report_step , well_list , group_list ); - for (int iw = 0; iw < stringlist_get_size( well_list ); iw++) { - const char * well_name = stringlist_iget( well_list , iw ); - well_history_type * well_history = sched_history_get_well( sched_history , well_name ); - well_history_add_keyword( well_history , kw , report_step); - } - } - break; - case(GRUPTREE): - { - const sched_kw_gruptree_type * gruptree = sched_kw_get_data( kw ); - stringlist_type * parent_group_list = group_list; - stringlist_type * child_group_list = well_list; - - sched_kw_gruptree_init_child_parent_list( gruptree , child_group_list , parent_group_list ); - sched_history_add_groups_gruptree( sched_history , gruptree , report_step , well_list , group_list ); - } - break; - default: - /* */ - break; - } - } - } - stringlist_free( well_list ); - stringlist_free( group_list ); - } - sched_history_install_index( sched_history ); -} - - -const char * sched_history_get_join_string( const sched_history_type * sched_history ) { - return sched_history->sep_string; -} - - -bool sched_history_has_well( const sched_history_type * sched_history , const char * well_name) { - return hash_has_key( sched_history->well_history , well_name ); -} - -bool sched_history_has_group( const sched_history_type * sched_history , const char * group_name) { - return hash_has_key( sched_history->group_history , group_name ); -} - -bool sched_history_has_key( const sched_history_type * sched_history , const char * key) { - return hash_has_key( sched_history->index , key ); -} - -bool sched_history_well_open( const sched_history_type * sched_history , const char * well_name , int report_step ) { - const well_history_type * well_history = sched_history_get_well( sched_history , well_name ); - return well_history_well_open( well_history , report_step ); -} - - - -/** - Will take a general key as input, and return the result of - schd_history_well_open() or sched_history_group_exists() - respectively - depending on the type key refers to. -*/ - -bool sched_history_open( const sched_history_type * sched_history , const char * key , int report_step) { - if(hash_has_key(sched_history->index, key)) { - const void * index = hash_get(sched_history->index , key ); - if (well_index_is_instance( index )) { - const well_index_type * well_index = well_index_safe_cast_const( index ); - const char * well_name = well_index_get_name( well_index ); - return sched_history_well_open( sched_history , well_name , report_step); - } else if (group_index_is_instance( index )) { - const group_index_type * group_index = group_index_safe_cast_const( index ); - const char * group_name = group_index_get_name( group_index ); - return sched_history_group_exists( sched_history , group_name , report_step); - } else { - util_abort("%s: - hmm internal fuckup \n",__func__); - return false; - } - } - return false; -} - - - - - -/** - This function checks if the group @group exists (i.e. has been - defined with the GRUPTREE or WELSPECS keyword) at the report_step - @report_step; if the group does not exist in the schedule file - _AT_ALL_ - the function will fail HARD. Use the function - sched_history_has_group() to check if a group is in the schedule - file at all. -*/ - - -bool sched_history_group_exists( const sched_history_type * sched_history , const char * group_name , int report_step ) { - const group_history_type * group_history = sched_history_get_group( sched_history , group_name ); - return group_history_group_exists( group_history , report_step ); -} - - - -void sched_history_fprintf_index_keys( const sched_history_type * sched_history , FILE * stream ) { - hash_iter_type * iter = hash_iter_alloc( sched_history->index ); - int c = 0; - while (!hash_iter_is_complete( iter )) { - fprintf(stream , "%18s" , hash_iter_get_next_key( iter )); - c += 1; - if ((c % 6) == 0) - fprintf(stream , "\n"); - } - hash_iter_free( iter ); -} - - - - -void sched_history_fprintf( const sched_history_type * sched_history , const stringlist_type * key_list , FILE * stream) { - int step = 1; - time_t start_time = time_t_vector_iget( sched_history->time , 0); - int total_length = bool_vector_size( sched_history->historical ); - while (true) { - if (bool_vector_safe_iget( sched_history->historical , step)) { - { - int mday,month,year; - time_t t = time_t_vector_iget( sched_history->time , step ); - double days = (t - start_time) * 1.0 / 86400; - util_set_date_values_utc( t , &mday , &month , &year); - //fprintf(stream , "%02d-%02d-%4d " , mday , month , year ); - fprintf(stream , " %5.0f " , days); - } - - for (int ikey =0; ikey < stringlist_get_size( key_list ); ikey++) - fprintf(stream , "%16.3f " , sched_history_iget( sched_history , stringlist_iget( key_list , ikey) , step)); - - fprintf( stream, "\n"); - } else - break; // We have completed the historical period - and switched to prediction - step++; - - if (step == total_length) - break; - } -} - - diff --git a/ThirdParty/Ert/libsched/src/sched_kw.c b/ThirdParty/Ert/libsched/src/sched_kw.c deleted file mode 100644 index 8ca0a9c182..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw.c +++ /dev/null @@ -1,564 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* - The structure sched_kw_type is used for internalization - of arbitrary keywords in an ECLIPSE schedule file/section. - - Two structs are defined in this file: - - 1. The sched_kw_type, which can be accessed externaly - through various interface functions. - 2. The data_handlers_type, which provides an abstraction - for the data_handling of the various keywords. This - is for internal use only. - - Keywords from the ECLIPSE schedule are divided into three - different groups: - - 1. Fully internalized keywords, e.g. GRUPTREE. - Functions implementing the data_handlers and - more for these keywords are found in separate - files, e.g. sched_kw_gruptree.c. - - 2. Keywords which are known to have a fixed number - of records, but not having a full internal - representation. The number of records for these - keywords are specified in the function - get_fixed_record_length in the file - sched_kw_untyped.c - - 3. Keywords which are not implemented and have a - variable record length. These are handled - automatically by sched_kw_untyped.c. - -*/ - -typedef void * (data_token_alloc_proto) ( const stringlist_type * , int * ); -typedef void (data_free_proto) ( void *); -typedef void (data_fprintf_proto) ( const void *, FILE *); -typedef void * (alloc_copy_proto) ( const void *); - - -struct data_handlers_struct { - data_token_alloc_proto * token_alloc; - data_free_proto * free; - data_fprintf_proto * fprintf; - alloc_copy_proto * copyc; -}; - - -struct sched_kw_struct { - char * kw_name; - sched_kw_type_enum type; - int restart_nr; /* The block nr owning this instance. */ - - - /* Function pointers to work on the data pointer. */ - data_token_alloc_proto * alloc; - data_free_proto * free; - data_fprintf_proto * fprintf; - alloc_copy_proto * copyc; - - void * data; /* A void point pointer to a detailed implementation - i.e. sched_kw_wconhist. */ -}; - - - - - - - - - -/*****************************************************************/ - -/** - Nothing like a little manual inheritance.... -*/ - -static sched_kw_type * sched_kw_alloc_empty( const char * kw_name ) { - sched_kw_type * kw = util_malloc(sizeof * kw); - kw->kw_name = util_alloc_string_copy( kw_name ); - kw->type = sched_kw_type_from_string( kw_name ); - - switch( kw->type ) { - case(WCONHIST): - kw->alloc = sched_kw_wconhist_alloc__; - kw->free = sched_kw_wconhist_free__; - kw->fprintf = sched_kw_wconhist_fprintf__; - kw->copyc = sched_kw_wconhist_copyc__; - break; - case(DATES): - kw->alloc = sched_kw_dates_alloc__; - kw->free = sched_kw_dates_free__; - kw->fprintf = sched_kw_dates_fprintf__; - kw->copyc = sched_kw_dates_copyc__; - break; - case(TSTEP): - kw->alloc = sched_kw_tstep_alloc__; - kw->free = sched_kw_tstep_free__; - kw->fprintf = sched_kw_tstep_fprintf__; - kw->copyc = sched_kw_tstep_copyc__; - break; - case(COMPDAT): - kw->alloc = sched_kw_compdat_alloc__; - kw->free = sched_kw_compdat_free__; - kw->fprintf = sched_kw_compdat_fprintf__; - kw->copyc = sched_kw_compdat_copyc__; - break; - case(WELSPECS): - kw->alloc = sched_kw_welspecs_alloc__; - kw->free = sched_kw_welspecs_free__; - kw->fprintf = sched_kw_welspecs_fprintf__; - kw->copyc = sched_kw_welspecs_copyc__; - break; - case(GRUPTREE): - kw->alloc = sched_kw_gruptree_alloc__; - kw->free = sched_kw_gruptree_free__; - kw->fprintf = sched_kw_gruptree_fprintf__; - kw->copyc = sched_kw_gruptree_copyc__; - break; - case(INCLUDE): - kw->alloc = sched_kw_include_alloc__; - kw->free = sched_kw_include_free__; - kw->fprintf = sched_kw_include_fprintf__; - kw->copyc = sched_kw_include_copyc__; - break; - case(UNTYPED): - /** - Observe that the untyped keyword uses a custom allocator - function, because it needs to get the keyword length as extra - input. - */ - kw->alloc = NULL; - kw->free = sched_kw_untyped_free__; - kw->fprintf = sched_kw_untyped_fprintf__; - kw->copyc = sched_kw_untyped_copyc__; - break; - case(WCONINJ): - kw->alloc = sched_kw_wconinj_alloc__; - kw->free = sched_kw_wconinj_free__; - kw->fprintf = sched_kw_wconinj_fprintf__; - kw->copyc = sched_kw_wconinj_copyc__; - break; - case(WCONINJE): - kw->alloc = sched_kw_wconinje_alloc__; - kw->free = sched_kw_wconinje_free__; - kw->fprintf = sched_kw_wconinje_fprintf__; - kw->copyc = sched_kw_wconinje_copyc__; - break; - case(WCONINJH): - kw->alloc = sched_kw_wconinjh_alloc__; - kw->free = sched_kw_wconinjh_free__; - kw->fprintf = sched_kw_wconinjh_fprintf__; - kw->copyc = sched_kw_wconinjh_copyc__; - break; - case(WCONPROD): - kw->alloc = sched_kw_wconprod_alloc__; - kw->free = sched_kw_wconprod_free__; - kw->fprintf = sched_kw_wconprod_fprintf__; - kw->copyc = sched_kw_wconprod_copyc__; - break; - default: - util_abort("%s: unrecognized type:%d \n",__func__ , kw->type ); - } - return kw; -} - - - - -/* - This tries to check if kw_name is a valid keyword in an ECLIPSE - schedule file. It is essentially based on checking that there are - not more argeuments on the line: - - OK: - ------------------- - RPTSCHED - arg1 arg2 arg2 .... - - - Invalid: - ------------------- - RPTSCHED arg1 arg2 arg3 ... - - Quite naive .... -*/ -static void sched_kw_name_assert(const char * kw_name , FILE * stream) -{ - if(kw_name == NULL) { - fprintf(stderr,"** Parsing SCHEDULE file line-nr: %d \n",util_get_current_linenr(stream)); - util_abort("%s: Internal error - trying to dereference NULL pointer.\n",__func__); - } - - { - bool valid_kw = true; - for (int i = 0; i < strlen(kw_name); i++) - if (isspace(kw_name[i])) - valid_kw = false; - - if (!valid_kw) { - if (stream != NULL) - fprintf(stderr,"** Parsing SCHEDULE file line-nr: %d \n",util_get_current_linenr(stream)); - util_abort("%s: \"%s\" is not a valid schedule kw - aborting.\n",__func__ , kw_name); - } - } -} - - - - -static sched_kw_type ** sched_kw_tstep_split_alloc(const sched_kw_type * sched_kw, int * num_steps) -{ - *num_steps = sched_kw_tstep_get_size(sched_kw->data); - sched_kw_type ** sched_kw_tsteps = util_malloc(*num_steps * sizeof * sched_kw_tsteps); - - for(int i=0; i<*num_steps; i++) { - sched_kw_tsteps[i] = sched_kw_alloc_empty( "TSTEP" ); - double step = sched_kw_tstep_iget_step((const sched_kw_tstep_type *) sched_kw->data, i); - sched_kw_tsteps[i]->data = sched_kw_tstep_alloc_from_double(step); - } - - return sched_kw_tsteps; -} - - - -static sched_kw_type ** sched_kw_dates_split_alloc(const sched_kw_type * sched_kw, int * num_steps) -{ - *num_steps = sched_kw_dates_get_size(sched_kw->data); - sched_kw_type ** sched_kw_dates = util_malloc(*num_steps * sizeof * sched_kw_dates); - - for(int i=0; i<*num_steps; i++) { - sched_kw_dates[i] = sched_kw_alloc_empty( "DATES" ); - time_t date = sched_kw_dates_iget_date((const sched_kw_dates_type *) sched_kw->data, i); - sched_kw_dates[i]->data = sched_kw_dates_alloc_from_time_t(date); - } - return sched_kw_dates; -} -/*****************************************************************/ - - - - - -const char * sched_kw_get_type_name( const sched_kw_type * sched_kw ) { - return sched_kw_type_name( sched_kw->type ); -} - - -sched_kw_type_enum sched_kw_get_type(const sched_kw_type * sched_kw) -{ - return sched_kw->type; -} - - -static void sched_kw_alloc_data( sched_kw_type * kw , const stringlist_type * token_list , int * token_index , hash_type * fixed_length_table) { - if (kw->type == UNTYPED) { - int rec_len = -1; - if (hash_has_key( fixed_length_table , kw->kw_name )) - rec_len = hash_get_int( fixed_length_table , kw->kw_name ); - kw->data = sched_kw_untyped_alloc( token_list , token_index , rec_len ); - } else - kw->data = kw->alloc( token_list , token_index ); -} - - -sched_kw_type * sched_kw_token_alloc(const stringlist_type * token_list, int * token_index, hash_type * fixed_length_table, bool * foundEND) { - if (*token_index >= stringlist_get_size( token_list )) - return NULL; - else { - const char * kw_name = stringlist_iget( token_list , *token_index ); - (*token_index) += 1; - sched_kw_name_assert(kw_name , NULL); - if (strcmp(kw_name,"END") == 0) { - if (foundEND != NULL) - *foundEND = true; - - return NULL; - } else { - sched_kw_type * sched_kw = sched_kw_alloc_empty( kw_name ); - sched_kw->restart_nr = -1; - - sched_util_skip_newline( token_list , token_index ); - sched_kw_alloc_data( sched_kw , token_list , token_index , fixed_length_table); - - return sched_kw; - } - } -} - - -const char * sched_kw_get_name( const sched_kw_type * kw) { return kw->kw_name; } - - - -void sched_kw_set_restart_nr( sched_kw_type * kw , int restart_nr) { - kw->restart_nr = restart_nr; -} - - - -void sched_kw_free(sched_kw_type * sched_kw) -{ - sched_kw->free(sched_kw->data); - free(sched_kw->kw_name); - free(sched_kw); -} - - - -void sched_kw_free__(void * sched_kw_void) -{ - sched_kw_type * sched_kw = (sched_kw_type *) sched_kw_void; - sched_kw_free(sched_kw); -} - - - -/* - This will print the kw in ECLIPSE style formating. -*/ -void sched_kw_fprintf(const sched_kw_type * sched_kw, FILE * stream) -{ - sched_kw->fprintf(sched_kw->data, stream); -} - - - - - - - -/* - This function takes a kw related to timing, such as DATES or TSTEP - and converts it into a series of kw's with one timing event in each - kw. Note that TIME (ECL300 only) is not supported. -*/ -sched_kw_type ** sched_kw_split_alloc_DATES(const sched_kw_type * sched_kw, int * num_steps) -{ - switch(sched_kw_get_type(sched_kw)) - { - case(TSTEP): - return sched_kw_tstep_split_alloc(sched_kw, num_steps); - break; - case(DATES): - return sched_kw_dates_split_alloc(sched_kw, num_steps); - break; - case(TIME): - util_abort("%s: Sorry - no support for TIME kw yet. Please use TSTEP.\n", __func__); - return NULL; - break; - default: - util_abort("%s: Internal error - aborting.\n", __func__); - return NULL; - } -} - - - -time_t sched_kw_get_new_time(const sched_kw_type * sched_kw, time_t curr_time) -{ - time_t new_time = -1; - switch(sched_kw_get_type(sched_kw)) - { - case(TSTEP): - new_time = sched_kw_tstep_get_new_time((const sched_kw_tstep_type *) sched_kw->data, curr_time); - break; - case(DATES): - new_time = sched_kw_dates_iget_date((const sched_kw_dates_type *) sched_kw->data , 0); - break; - case(TIME): - util_abort("%s: Sorry - no support for TIME kw. Please use TSTEP.\n", __func__); - break; - default: - util_abort("%s: Internal error - trying to get time from non-timing kw - aborting.\n", __func__); - break; - } - - return new_time; -} - - - -char ** sched_kw_alloc_well_list(const sched_kw_type * sched_kw, int * num_wells) -{ - switch(sched_kw_get_type(sched_kw)) - { - case(WCONPROD): - return sched_kw_wconprod_alloc_wells_copy( (const sched_kw_wconprod_type *) sched_kw->data , num_wells); - break; - case(WCONINJE): - return sched_kw_wconinje_alloc_wells_copy( (const sched_kw_wconinje_type *) sched_kw->data , num_wells); - break; - case(WCONINJ): - return sched_kw_wconinj_alloc_wells_copy( (const sched_kw_wconinj_type *) sched_kw->data , num_wells); - break; - case(WCONHIST): - { - hash_type * well_obs = sched_kw_wconhist_alloc_well_obs_hash( (sched_kw_wconhist_type *) sched_kw->data); - *num_wells = hash_get_size(well_obs); - char ** well_list = hash_alloc_keylist(well_obs); - hash_free(well_obs); - return well_list; - } - break; - case(WCONINJH): - { - hash_type * well_obs = sched_kw_wconinjh_alloc_well_obs_hash( (sched_kw_wconinjh_type *) sched_kw->data); - *num_wells = hash_get_size(well_obs); - char ** well_list = hash_alloc_keylist(well_obs); - hash_free(well_obs); - return well_list; - } - break; - default: - util_abort("%s: Internal error - trying to get well list from non-well kw - aborting.\n", __func__); - return NULL; - } -} - - - -hash_type * sched_kw_alloc_well_obs_hash(const sched_kw_type * sched_kw) -{ - switch(sched_kw_get_type(sched_kw)) - { - case(WCONHIST): - { - return sched_kw_wconhist_alloc_well_obs_hash( (sched_kw_wconhist_type *) sched_kw->data); - } - case(WCONINJH): - { - return sched_kw_wconinjh_alloc_well_obs_hash( (sched_kw_wconinjh_type *) sched_kw->data); - } - default: - { - util_abort("%s: Internal error - trying to get well observations from non-history kw - aborting.\n", __func__); - return NULL; - } - } -} - - - -void sched_kw_alloc_child_parent_list(const sched_kw_type * sched_kw, char *** children, char *** parents, int * num_pairs) -{ - switch(sched_kw_get_type(sched_kw)) - { - case(GRUPTREE): - { - sched_kw_gruptree_alloc_child_parent_list((sched_kw_gruptree_type *) sched_kw->data, children, parents, num_pairs); - break; - } - case(WELSPECS): - { - sched_kw_welspecs_alloc_child_parent_list((sched_kw_welspecs_type *) sched_kw->data, children, parents, num_pairs); - break; - } - default: - { - util_abort("%s: Internal error - trying to get GRUPTREE from non-gruptre kw - aborting.\n", __func__); - } - } -} - - -/** - Only WCONHIST -*/ - -bool sched_kw_has_well( const sched_kw_type * sched_kw , const char * well ) { - sched_kw_type_enum type = sched_kw_get_type( sched_kw ); - if (type == WCONHIST) - return sched_kw_wconhist_has_well( sched_kw->data , well); - else if (type == WCONINJE) - return sched_kw_wconinje_has_well( sched_kw->data , well); - else - return false; -} - - - -/** - Only WCONHIST & WCONINJE -*/ - -bool sched_kw_well_open( const sched_kw_type * sched_kw , const char * well ) { - sched_kw_type_enum type = sched_kw_get_type( sched_kw ); - if (type == WCONHIST) - return sched_kw_wconhist_well_open( sched_kw->data , well); - else if (type == WCONINJE) - return sched_kw_wconinje_well_open( sched_kw->data , well); - else - return false; -} - - - -sched_kw_type * sched_kw_alloc_copy(const sched_kw_type * src) { - sched_kw_type * target = NULL; - - return target; -} - - -/* - Returns an untyped poiniter to the spesific implementation. Used by - the sched_file_update system. A bit careful with this one... -*/ - -void * sched_kw_get_data( sched_kw_type * kw) { - return kw->data; -} - -const void * sched_kw_get_const_data( const sched_kw_type * kw) { - return kw->data; -} - - diff --git a/ThirdParty/Ert/libsched/src/sched_kw_compdat.c b/ThirdParty/Ert/libsched/src/sched_kw_compdat.c deleted file mode 100644 index f4bd8101cc..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_compdat.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_compdat.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - - -#define COMPDAT_NUM_KW 14 -#define SCHED_KW_COMPDAT_ID 771882 - -typedef enum {X, Y , Z , FX , FY} well_dir_type; -#define WELL_DIR_DEFAULT Z -#define WELL_DIR_X_STRING "X" -#define WELL_DIR_Y_STRING "Y" -#define WELL_DIR_Z_STRING "Z" -#define WELL_DIR_FX_STRING "FX" -#define WELL_DIR_FY_STRING "FZ" - - - -typedef enum {OPEN , AUTO , SHUT} comp_state_type; -#define COMP_DEFAULT_STATE OPEN -#define COMP_OPEN_STRING "OPEN" -#define COMP_AUTO_STRING "AUTO" -#define COMP_SHUT_STRING "SHUT" - - - -/* - Structure to hold one line (typically one completed cell) in a compdat section. -*/ - -typedef struct { - char *well; /* Name of well */ - int i,j,k1,k2; /* The i,j,k coordinated of the perforated cell. */ - well_dir_type well_dir; /* Which direction does the well penetrate the grid block */ - comp_state_type state; /* What state is this completion in: AUTO|SHUT|OPEN */ - int sat_table; - double conn_factor; - double well_diameter; - double eff_perm; - double skin_factor; - double D_factor; - double r0; - - /* - def : Read as defaulted, not as defined. - */ - bool def[COMPDAT_NUM_KW]; -} comp_type; - - - -struct sched_kw_compdat_struct { - UTIL_TYPE_ID_DECLARATION; - vector_type * completions; -}; - - - -/** - make_lookup comp_get_state_string comp_get_state_from_string comp_state_type AUTO COMP_AUTO_STRING OPEN COMP_OPEN_STRING SHUT COMP_SHUT_STRING -*/ - - - -static char * comp_get_state_string(comp_state_type state) { - switch(state) { - case(AUTO): - return COMP_AUTO_STRING; - case(OPEN): - return COMP_OPEN_STRING; - case(SHUT): - return COMP_SHUT_STRING; - default: - util_abort("%s: internal error \n",__func__); - return NULL; - } -} - - - -static char * comp_get_dir_string(well_dir_type dir) { - switch(dir) { - case(X): - return WELL_DIR_X_STRING; - case(Y): - return WELL_DIR_Y_STRING; - case(Z): - return WELL_DIR_Z_STRING; - case(FX): - return WELL_DIR_FX_STRING; - case(FY): - return WELL_DIR_FY_STRING; - default: - util_abort("%s: internal fuckup \n",__func__); - return NULL; - } -} - - -static well_dir_type comp_get_well_dir_from_string(const char * well_dir) { - if (strcmp(well_dir , WELL_DIR_X_STRING) == 0) - return X; - else if (strcmp(well_dir , WELL_DIR_Y_STRING) == 0) - return Y; - else if (strcmp(well_dir , WELL_DIR_Z_STRING) == 0) - return Z; - else if (strcmp(well_dir , WELL_DIR_FX_STRING) == 0) - return FX; - else if (strcmp(well_dir , WELL_DIR_FY_STRING) == 0) - return FY; - else { - util_abort("%s: internal fuckup \n",__func__); - return -1; - } -} - - - -static comp_state_type comp_get_state_from_string(const char * state) { - if (strcmp(state , COMP_AUTO_STRING) == 0) - return AUTO; - else if (strcmp(state , COMP_OPEN_STRING) == 0) - return OPEN; - else if (strcmp(state , COMP_SHUT_STRING) == 0) - return SHUT; - else { - util_abort("%s: did not recognize:%s as valid completion state: (%s|%s|%s) \n",__func__ , state , COMP_AUTO_STRING , COMP_OPEN_STRING , COMP_SHUT_STRING); - return -1; - } -} - - - - - - -static void comp_sched_fprintf(const comp_type * comp , FILE *stream) { - fprintf(stream , " "); - sched_util_fprintf_qst(comp->def[0] , comp->well , 8 , stream); - sched_util_fprintf_int(comp->def[1] , comp->i , 4 , stream); - sched_util_fprintf_int(comp->def[2] , comp->j , 4 , stream); - sched_util_fprintf_int(comp->def[3] , comp->k1 , 4 , stream); - sched_util_fprintf_int(comp->def[4] , comp->k2 , 4 , stream); - sched_util_fprintf_qst(comp->def[5] , comp_get_state_string( comp->state ) , 4 , stream); - sched_util_fprintf_int(comp->def[6] , comp->sat_table , 6 , stream); - sched_util_fprintf_dbl(comp->def[7] , comp->conn_factor , 9 , 3 , stream); - sched_util_fprintf_dbl(comp->def[8] , comp->well_diameter , 9 , 3 , stream); - sched_util_fprintf_dbl(comp->def[9] , comp->eff_perm , 9 , 3 , stream); - sched_util_fprintf_dbl(comp->def[10], comp->skin_factor , 9 , 3 , stream); - sched_util_fprintf_dbl(comp->def[11], comp->D_factor , 9 , 3 , stream); - sched_util_fprintf_qst(comp->def[12], comp_get_dir_string( comp->well_dir) , 2 , stream); - sched_util_fprintf_dbl(comp->def[13], comp->r0 , 9 , 3 , stream); - fprintf(stream , " /\n"); -} - - - - -static comp_type * comp_alloc_empty( ) { - comp_type *node = util_malloc(sizeof * node); - node->well = NULL; - return node; -} - - -static comp_type * comp_alloc_from_tokens( const stringlist_type * line_tokens ) { - comp_type * comp = comp_alloc_empty(); - sched_util_init_default( line_tokens , comp->def ); - - - comp->well = util_alloc_string_copy(stringlist_iget( line_tokens , 0)); - comp->i = sched_util_atoi(stringlist_iget( line_tokens , 1)); - comp->j = sched_util_atoi(stringlist_iget( line_tokens , 2)); - comp->k1 = sched_util_atoi(stringlist_iget( line_tokens , 3)); - comp->k2 = sched_util_atoi(stringlist_iget( line_tokens , 4)); - - if (comp->def[5]) - comp->state = COMP_DEFAULT_STATE; - else - comp->state = comp_get_state_from_string( stringlist_iget( line_tokens , 5 )); - - comp->sat_table = sched_util_atoi(stringlist_iget( line_tokens , 6)); - comp->conn_factor = sched_util_atof(stringlist_iget( line_tokens , 7)); - comp->well_diameter = sched_util_atof(stringlist_iget( line_tokens , 8)); - comp->eff_perm = sched_util_atof(stringlist_iget( line_tokens , 9)); - comp->skin_factor = sched_util_atof(stringlist_iget( line_tokens , 10)); - comp->D_factor = sched_util_atof(stringlist_iget( line_tokens , 11)); - - if (comp->def[12]) - comp->well_dir = WELL_DIR_DEFAULT; - else - comp->well_dir = comp_get_well_dir_from_string( stringlist_iget( line_tokens , 12 )); - - comp->r0 = sched_util_atof(stringlist_iget( line_tokens , 13)); - return comp; -} - - - -static void comp_free(comp_type *comp) { - free(comp->well); - free(comp); -} - - -static void comp_free__(void *__comp) { - comp_type *comp = (comp_type *) __comp; - comp_free(comp); -} - - - - - -void sched_kw_compdat_fprintf(const sched_kw_compdat_type *kw , FILE *stream) { - fprintf(stream , "COMPDAT\n"); - { - int index; - for (index = 0; index < vector_get_size( kw->completions ); index++) { - const comp_type * comp = vector_iget_const( kw->completions , index ); - comp_sched_fprintf(comp , stream); - } - } - fprintf(stream , "/\n\n"); -} - - - -sched_kw_compdat_type * sched_kw_compdat_alloc_empty( ) { - sched_kw_compdat_type * kw = util_malloc(sizeof *kw ); - kw->completions = vector_alloc_new(); - UTIL_TYPE_ID_INIT( kw , SCHED_KW_COMPDAT_ID ); - return kw; -} - - -UTIL_SAFE_CAST_FUNCTION( sched_kw_compdat , SCHED_KW_COMPDAT_ID ) - -void sched_kw_compdat_add_comp( sched_kw_compdat_type * kw , comp_type * comp) { - vector_append_owned_ref(kw->completions , comp , comp_free__); -} - - -sched_kw_compdat_type * sched_kw_compdat_alloc(const stringlist_type * tokens , int * token_index ) { - sched_kw_compdat_type * kw = sched_kw_compdat_alloc_empty(); - int eokw = false; - do { - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , false , COMPDAT_NUM_KW , token_index ); - if (line_tokens == NULL) - eokw = true; - else { - comp_type * comp = comp_alloc_from_tokens( line_tokens ); - sched_kw_compdat_add_comp( kw , comp ); - stringlist_free( line_tokens ); - } - } - - while (!eokw); - return kw; -} - - - - - -void sched_kw_compdat_free(sched_kw_compdat_type * kw) { - vector_free(kw->completions); - free(kw); -} - - -sched_kw_compdat_type * sched_kw_compdat_copyc(const sched_kw_compdat_type * kw) { - util_abort("%s: not implemented ... \n",__func__); - return NULL; -} - - -/*****************************************************************/ -KW_IMPL(compdat) - diff --git a/ThirdParty/Ert/libsched/src/sched_kw_dates.c b/ThirdParty/Ert/libsched/src/sched_kw_dates.c deleted file mode 100644 index ed3e8f0806..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_dates.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_dates.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include - - -#define DATES_FMT " %d \'%s\' %4d / \n" // The format string used when writing dates the arguments are (day , month_string , year). - - -struct sched_kw_dates_struct { - vector_type * time_list; -}; - - -/*****************************************************************/ - - - -static sched_kw_dates_type * sched_kw_dates_alloc_empty() -{ - sched_kw_dates_type *dates = util_malloc(sizeof *dates); - dates->time_list = vector_alloc_new(); - return dates; -} - - - -static const char * get_month_string_from_int(int month_nr) -{ - switch(month_nr) - { - case(1): return "JAN"; - case(2): return "FEB"; - case(3): return "MAR"; - case(4): return "APR"; - case(5): return "MAY"; - case(6): return "JUN"; - case(7): return "JUL"; - case(8): return "AUG"; - case(9): return "SEP"; - case(10): return "OCT"; - case(11): return "NOV"; - case(12): return "DEC"; - default: - util_abort("%s: Internal error - %i is not a month nr.\n",__func__,month_nr); - return "ERR\0"; - } - -} - - -static time_t parse_time_t(const char * day_string , const char * month_string , const char * year_string) { - int mday , month , year; - time_t time = -1; - - month = ecl_util_get_month_nr(month_string); - if (month < 0) - util_abort("%s: failed to interpret:%s a month name \n",__func__ , month_string ); - - if (util_sscanf_int(day_string , &mday) && util_sscanf_int(year_string , &year)) - time = util_make_date_utc(mday , month , year); - else - util_abort("%s: fatal error when extracting date from:%s %s %s \n", __func__, day_string , month_string , year_string); - - return time; -} - - - - - - - - - -/*****************************************************************/ - - -sched_kw_dates_type * sched_kw_dates_alloc(const stringlist_type * tokens , int * token_index ) { - sched_kw_dates_type * kw = sched_kw_dates_alloc_empty(); - int eokw = false; - do { - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , false, 0 , token_index ); - if (line_tokens == NULL) - eokw = true; - else { - if (stringlist_get_size( line_tokens ) == 3) { - const char * day_string = stringlist_iget( line_tokens , 0 ); - const char * month_string = stringlist_iget( line_tokens , 1 ); - const char * year_string = stringlist_iget( line_tokens , 2 ); - - time_t date = parse_time_t( day_string , month_string , year_string ); - sched_time_type * time_node = sched_time_alloc( date , 0 , DATES_TIME ); - vector_append_owned_ref( kw->time_list , time_node , sched_time_free__ ); - } else { - stringlist_fprintf( line_tokens , " " , stdout ); - util_abort("%s: malformed DATES keyword\n",__func__); - } - stringlist_free( line_tokens ); - } - - } while (!eokw); - return kw; -} - - - - -void sched_kw_dates_fprintf(const sched_kw_dates_type *kw , FILE *stream) { - fprintf(stream,"DATES\n"); - { - int i; - for (i=0; i < vector_get_size( kw->time_list ); i++) { - const sched_time_type * time_node = vector_iget_const( kw->time_list , i ); - if (sched_time_get_type( time_node ) == DATES_TIME) { - time_t date = sched_time_get_date( time_node ); - int day, month, year; - util_set_date_values_utc(date, &day, &month, &year); - fprintf(stream , DATES_FMT , day, get_month_string_from_int(month), year ); - } else - util_abort("%s: internal type fuckup \n",__func__); - } - fprintf(stream , "/\n\n"); - } -} - - - -void sched_kw_dates_free(sched_kw_dates_type * kw) { - vector_free(kw->time_list); - free(kw); -} - - - -int sched_kw_dates_get_size(const sched_kw_dates_type * kw) -{ - return vector_get_size(kw->time_list); -} - - - -sched_kw_dates_type * sched_kw_dates_alloc_from_time_t(time_t date) -{ - sched_kw_dates_type * kw = sched_kw_dates_alloc_empty(); - sched_time_type * time_node = sched_time_alloc( date , 0 , DATES_TIME ); - vector_append_owned_ref(kw->time_list , time_node , sched_time_free__); - return kw; -} - - - -time_t sched_kw_dates_iget_date(const sched_kw_dates_type * kw, int i) -{ - const sched_time_type * time_node = vector_iget_const( kw->time_list , i ); - return sched_time_get_date( time_node ); -} - - - - -sched_kw_dates_type * sched_kw_dates_copyc(const sched_kw_dates_type * kw) { - util_abort("%s: not implemented ... \n",__func__); - return NULL; -} - - - - -/***********************************************************************/ - - - -KW_IMPL(dates) - diff --git a/ThirdParty/Ert/libsched/src/sched_kw_gruptree.c b/ThirdParty/Ert/libsched/src/sched_kw_gruptree.c deleted file mode 100644 index 5352772811..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_gruptree.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_gruptree.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include -#include - -#include -#include -#include - - -struct sched_kw_gruptree_struct -{ - hash_type * gruptree_hash; /* The use of hash implies that the ordering within one GRUPTREE instance is not retained. */ -}; - - - -/***********************************************************************/ - - - -static void sched_kw_gruptree_add_well(sched_kw_gruptree_type * kw , const char * child_group , const char * parent_group) { - hash_insert_string(kw->gruptree_hash, child_group , parent_group); -} - - -static sched_kw_gruptree_type * sched_kw_gruptree_alloc_empty() -{ - sched_kw_gruptree_type * kw = util_malloc(sizeof * kw); - kw->gruptree_hash = hash_alloc(); - - return kw; -}; - - - -/***********************************************************************/ - - -sched_kw_gruptree_type * sched_kw_gruptree_alloc(const stringlist_type * tokens , int * token_index ) { - sched_kw_gruptree_type * kw = sched_kw_gruptree_alloc_empty(); - int eokw = false; - do { - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , false , 0 , token_index ); - if (line_tokens == NULL) - eokw = true; - else { - const char * parent_group = "FIELD"; - const char * child_group = stringlist_iget( line_tokens , 0 ); - if (stringlist_get_size( line_tokens ) == 2) - parent_group = stringlist_iget( line_tokens , 1 ); - - sched_kw_gruptree_add_well(kw , child_group , parent_group ); - - stringlist_free( line_tokens ); - } - - } while (!eokw); - return kw; -} - - - -void sched_kw_gruptree_free(sched_kw_gruptree_type * kw) -{ - hash_free(kw->gruptree_hash); - free(kw); -}; - - -void sched_kw_gruptree_fprintf(const sched_kw_gruptree_type * kw, FILE * stream) -{ - - fprintf(stream, "GRUPTREE\n"); - { - const int num_keys = hash_get_size(kw->gruptree_hash); - char ** child_list = hash_alloc_keylist(kw->gruptree_hash); - int i; - - for (i = 0; i < num_keys; i++) { - const char * parent_name = hash_get_string(kw->gruptree_hash , child_list[i]); - fprintf(stream," '%s' '%s' /\n",child_list[i] , parent_name); - } - util_free_stringlist( child_list , num_keys ); - } - fprintf(stream,"/\n\n"); -}; - - - - -void sched_kw_gruptree_init_child_parent_list( const sched_kw_gruptree_type * kw , stringlist_type * child , stringlist_type * parent) { - stringlist_clear( child ); - stringlist_clear( parent ); - { - hash_iter_type * iter = hash_iter_alloc( kw->gruptree_hash ); - while (!hash_iter_is_complete( iter )) { - const char * child_group = hash_iter_get_next_key( iter ); - const char * parent_group = hash_get_string( kw->gruptree_hash , child_group ); - - stringlist_append_copy( child , child_group ); /* <- The iterator keys go out of scope when hash_iter_free() is called. */ - stringlist_append_ref( parent , parent_group ); - } - hash_iter_free( iter ); - } -} - - - - -void sched_kw_gruptree_alloc_child_parent_list(const sched_kw_gruptree_type * kw, char *** __children, char *** __parents, int * num_pairs) -{ - *num_pairs = hash_get_size(kw->gruptree_hash); - char ** children = hash_alloc_keylist(kw->gruptree_hash); - char ** parents = util_malloc(*num_pairs * sizeof * parents); - - for(int child_nr = 0; child_nr < *num_pairs; child_nr++) - { - parents[child_nr] = util_alloc_string_copy(hash_get_string(kw->gruptree_hash, children[child_nr])); - } - - *__children = children; - *__parents = parents; -} - - - -static sched_kw_gruptree_type * sched_kw_gruptree_copyc(const sched_kw_gruptree_type * src) { - sched_kw_gruptree_type * target = sched_kw_gruptree_alloc_empty(); - hash_iter_type * iter = hash_iter_alloc(src->gruptree_hash); - const char * kw = hash_iter_get_next_key(iter); - while (kw != NULL) { - char * parent_name = hash_get_string(src->gruptree_hash , kw); - hash_insert_string( target->gruptree_hash , kw , parent_name); - kw = hash_iter_get_next_key(iter); - } - hash_iter_free(iter); - return target; -} - - - -/***********************************************************************/ - -KW_IMPL(gruptree) diff --git a/ThirdParty/Ert/libsched/src/sched_kw_include.c b/ThirdParty/Ert/libsched/src/sched_kw_include.c deleted file mode 100644 index 11a58e8dd8..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_include.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_include.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - - -/** - This file implemtents support for the INCLUDE keyword in the - SCHEDULE files. Observe that the implementation is extremely - minimal, all it does is: - - 1. Recognize the INCLUDE keyword. - 2. Internalize the string representing the included file. - - It does NOT descent into any recursive parsing. The main reason to - have this support is to let the untyped parser "safely" read up to - the next "/" (that approach ill be completely fooled by path - separators in INCLUDE statements). -*/ - -#define SCHED_KW_INCLUDE_ID 1085006 - - -struct sched_kw_include_struct { - UTIL_TYPE_ID_DECLARATION; - char * include_file; /* The file to include ... */ -}; - - -static sched_kw_include_type * sched_kw_include_alloc_empty() { - sched_kw_include_type * kw = util_malloc( sizeof * kw ); - UTIL_TYPE_ID_INIT(kw , SCHED_KW_INCLUDE_ID); - kw->include_file = NULL; - return kw; -} - - -static void sched_kw_include_set_file( sched_kw_include_type * kw , const char * file) { - kw->include_file = util_alloc_string_copy( file ); -} - - - -sched_kw_include_type * sched_kw_include_alloc(const stringlist_type * tokens , int * token_index ) { - sched_kw_include_type * kw = sched_kw_include_alloc_empty(); - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , false , 0 , token_index ); - if (line_tokens == NULL) - util_abort("%s: fatal error when parsing INCLUDE \n",__func__); - - if (stringlist_get_size( line_tokens ) != 1) - util_abort("%s: fatal error when parsing INCLUDE \n",__func__); - - sched_kw_include_set_file( kw , stringlist_iget( line_tokens , 0 )); - - return kw; -} - - - - -void sched_kw_include_free( sched_kw_include_type * kw ) { - util_safe_free( kw->include_file ); - free( kw ); -} - - -void sched_kw_include_fprintf( const sched_kw_include_type * kw , FILE * stream ) { - fprintf(stream , "INCLUDE\n"); - fprintf(stream , " \'%s\' /\n\n" , kw->include_file); -} - - -sched_kw_include_type * sched_kw_include_copyc( const sched_kw_include_type * kw ) { - sched_kw_include_type * copy = sched_kw_include_alloc_empty(); - sched_kw_include_set_file( copy , kw->include_file ); - return copy; -} - - - -KW_IMPL(include) diff --git a/ThirdParty/Ert/libsched/src/sched_kw_tstep.c b/ThirdParty/Ert/libsched/src/sched_kw_tstep.c deleted file mode 100644 index b9ed608360..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_tstep.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_tstep.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include - -#include -#include -#include - - - -struct sched_kw_tstep_struct { - double_vector_type * tstep_list; -}; - - - -/*****************************************************************/ - - -static void sched_kw_tstep_add_tstep( sched_kw_tstep_type * kw, double tstep ) { - double_vector_append( kw->tstep_list , tstep ); -} - - -static void sched_kw_tstep_add_tstep_string( sched_kw_tstep_type * kw, const char * tstep_string) { - double tstep; - if (util_sscanf_double( tstep_string , &tstep )) - sched_kw_tstep_add_tstep(kw , tstep ); - else - util_abort("%s: failed to parse:%s as a floating point number \n",__func__ , tstep_string); -} - - - - - - -static sched_kw_tstep_type * sched_kw_tstep_alloc_empty(){ - sched_kw_tstep_type *tstep = util_malloc(sizeof * tstep ); - tstep->tstep_list = double_vector_alloc(0 , 0); - return tstep; -} - - - -/*****************************************************************/ - -sched_kw_tstep_type * sched_kw_tstep_alloc(const stringlist_type * tokens , int * token_index ) { - sched_kw_tstep_type * kw = sched_kw_tstep_alloc_empty(); - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , false , 0 , token_index ); - - if (line_tokens == NULL) - util_abort("%s: hmmmm - TSTEP keyword without and data \n",__func__); - else { - int i; - - for (i=0; i < stringlist_get_size( line_tokens ); i++) - sched_kw_tstep_add_tstep_string( kw , stringlist_iget( line_tokens , i )); - - stringlist_free( line_tokens ); - } - - return kw; -} - - -void sched_kw_tstep_fprintf(const sched_kw_tstep_type *kw , FILE *stream) { - fprintf(stream,"TSTEP\n "); - { - int i; - for (i=0; i < double_vector_size( kw->tstep_list ); i++) - fprintf(stream, "%7.3f", double_vector_iget( kw->tstep_list , i)); - } - fprintf(stream , " /\n\n"); -} - - - -void sched_kw_tstep_free(sched_kw_tstep_type * kw) { - double_vector_free(kw->tstep_list); - free(kw); -} - - - -int sched_kw_tstep_get_size(const sched_kw_tstep_type * kw) -{ - return double_vector_size(kw->tstep_list); -} - - - -sched_kw_tstep_type * sched_kw_tstep_alloc_from_double(double step) -{ - sched_kw_tstep_type * kw = sched_kw_tstep_alloc_empty(); - double_vector_append( kw->tstep_list , step ); - return kw; -} - -sched_kw_tstep_type * sched_kw_tstep_copyc(const sched_kw_tstep_type * kw) { - util_abort("%s: not implemented ... \n",__func__); - return NULL; -} - - - -double sched_kw_tstep_iget_step(const sched_kw_tstep_type * kw, int i) -{ - return double_vector_iget( kw->tstep_list , i ); -} - - -int sched_kw_tstep_get_length( const sched_kw_tstep_type * kw) { - return double_vector_size( kw->tstep_list ); -} - -time_t sched_kw_tstep_get_new_time(const sched_kw_tstep_type *kw, time_t curr_time) -{ - double step_days = sched_kw_tstep_iget_step(kw , 0); - time_t new_time = curr_time; - util_inplace_forward_days_utc(&new_time, step_days); - return new_time; -} - - -/*****************************************************************/ - -KW_IMPL(tstep) - - diff --git a/ThirdParty/Ert/libsched/src/sched_kw_untyped.c b/ThirdParty/Ert/libsched/src/sched_kw_untyped.c deleted file mode 100644 index 2439d9dc95..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_untyped.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_untyped.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include - -#include -#include - - - - -struct sched_kw_untyped_struct { - int rec_len; - char *kw_name; /* The name of the current keyword. */ - char *buffer; /* The content of the keyword is just appended in one char * pointer. */ -}; - - - -/*****************************************************************/ - -//static int get_fixed_record_length(const char * kw_name) -//{ -// -// if( strcmp(kw_name , "RPTSCHED") == 0) { return 1;} -// if( strcmp(kw_name , "DRSDT" ) == 0) { return 1;} -// if( strcmp(kw_name , "SKIPREST") == 0) { return 0;} -// if( strcmp(kw_name , "RPTRST" ) == 0) { return 1;} -// if( strcmp(kw_name , "TUNING" ) == 0) { return 3;} -// if( strcmp(kw_name , "WHISTCTL") == 0) { return 1;} -// if( strcmp(kw_name , "TIME" ) == 0) { return 1;} -// if( strcmp(kw_name , "VAPPARS" ) == 0) { return 1;} -// if( strcmp(kw_name , "NETBALAN") == 0) { return 1;} -// if( strcmp(kw_name , "WPAVE" ) == 0) { return 1;} -// if( strcmp(kw_name , "VFPTABL" ) == 0) { return 1;} -// if( strcmp(kw_name , "GUIDERAT") == 0) { return 1;} -// -// return -1; /* Can not use 0 - because some KW actually have 0 as a valid fixed value. */ -//} - - - -sched_kw_untyped_type * sched_kw_untyped_alloc_empty(const char * kw_name , int rec_len) { - sched_kw_untyped_type * kw = util_malloc(sizeof *kw ); - kw->kw_name = util_alloc_string_copy(kw_name); - kw->rec_len = rec_len; - kw->buffer = NULL; - return kw; -} - - - -/** This is exported for the keywords which are just a minimum extension of untyped. */ -void sched_kw_untyped_add_line(sched_kw_untyped_type * kw , const char *line, bool pad) { - if (pad) { - char * padded_line = util_alloc_sprintf(" %s\n" , line); - kw->buffer = util_strcat_realloc(kw->buffer , padded_line); - free(padded_line); - } else - kw->buffer = util_strcat_realloc(kw->buffer , line); -} - - - -/*****************************************************************/ - - -void sched_kw_untyped_add_tokens( sched_kw_untyped_type * kw , const stringlist_type * line_tokens) { - char * line_buffer = stringlist_alloc_joined_string( line_tokens , " "); - sched_kw_untyped_add_line(kw, line_buffer , true ); - free( line_buffer ); -} - - - - - -sched_kw_untyped_type * sched_kw_untyped_alloc(const stringlist_type * tokens , int * token_index , int rec_len) { - const char * kw_name = NULL; - - /* First part - get hold of the kw name */ - { - int kw_index = (*token_index) - 1; - do { - kw_name = stringlist_iget( tokens , kw_index); - if (util_string_isspace( kw_name )) - kw_name = NULL; /* Try again */ - kw_index--; - } while (kw_name == NULL && (kw_index >= 0)); - - if (kw_name == NULL) - util_abort("%s: internal error - failed to identify untyped kw name \n",__func__); - } - - - { - bool eokw = false; - sched_kw_untyped_type * kw = sched_kw_untyped_alloc_empty( kw_name , rec_len); - int line_nr = 0; - do { - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , true , 0 , token_index ); - line_nr++; - if (line_tokens == NULL) { - eokw = true; - if (line_nr < kw->rec_len) - util_abort("%s: premature end of keyword:%s \n",__func__ , kw_name); - } else { - sched_kw_untyped_add_tokens( kw , line_tokens ); - stringlist_free( line_tokens ); - } - - if (line_nr == kw->rec_len) - eokw = true; - - } while (!eokw); - return kw; - } -} - - - - -void sched_kw_untyped_fprintf(const sched_kw_untyped_type *kw , FILE *stream) { - fprintf(stream , "%s \n" , kw->kw_name); - { - if (kw->buffer != NULL) - fprintf(stream , "%s" , kw->buffer); - - if(kw->rec_len < 0) - fprintf(stream , "/\n\n"); - else - fprintf(stream, "\n\n"); - } -} - - - -void sched_kw_untyped_free(sched_kw_untyped_type * kw) { - util_safe_free(kw->buffer); - free(kw->kw_name); - free(kw); -} - -sched_kw_untyped_type * sched_kw_untyped_copyc(const sched_kw_untyped_type * kw) { - util_abort("%s: not implemented ... \n",__func__); - return NULL; -} - -/*****************************************************************/ - -KW_FREE_IMPL(untyped) -KW_FPRINTF_IMPL(untyped) -KW_COPYC_IMPL(untyped) - - - - - - - - - - diff --git a/ThirdParty/Ert/libsched/src/sched_kw_wconhist.c b/ThirdParty/Ert/libsched/src/sched_kw_wconhist.c deleted file mode 100644 index c5cfe31ed8..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_wconhist.c +++ /dev/null @@ -1,719 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_wconhist.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -/* - Define the maximum number of keywords in a WCONHIST record. - Note that this includes wet gas rate, which is only supported - by ECL 300. -*/ - -#define WCONHIST_NUM_KW 11 -#define SCHED_KW_WCONHIST_ID 771054 /* Very random intgere for checking type-cast. */ -#define WCONHIST_TYPE_ID 7752053 - - -typedef struct wconhist_well_struct wconhist_well_type; - - - -struct wconhist_well_struct{ - /* - def: Read as defaulted, not defined! - */ - bool def[WCONHIST_NUM_KW]; - - char * name; - well_status_enum status; - well_cm_enum cmode; - double orat; - double wrat; - double grat; - int vfptable; - double alift; - double thp; - double bhp; - double wgrat; -}; - - - -struct sched_kw_wconhist_struct{ - UTIL_TYPE_ID_DECLARATION; - vector_type * wells; -}; - - -/*****************************************************************/ - -/** - Contains values for ORAT, GRAT, .... for one well for the complete - history; this is orthogonal to the regualar sched_kw_wconhist - keyowrd which contains the same data for all (or at least many ...) - wells at one time instant. -*/ - -struct wconhist_state_struct { - UTIL_TYPE_ID_DECLARATION; - const time_t_vector_type * time; /* Shared vector with the report_step -> time_t mapping .*/ - int_vector_type * state; /* Contains values from the well_status_enum. */ - int_vector_type * cmode; /* Contains values from the well_cm_enum. */ - double_vector_type * oil_rate; - double_vector_type * water_rate; - double_vector_type * gas_rate; - int_vector_type * vfp_table; - double_vector_type * art_lift; - double_vector_type * thp; - double_vector_type * bhp; - double_vector_type * wgas_rate; -}; - - - -/*****************************************************************/ - - - -static wconhist_well_type * wconhist_well_alloc_empty( ) -{ - wconhist_well_type * well = util_malloc(sizeof * well); - well->name = NULL; - well->status = WCONHIST_DEFAULT_STATUS; - return well; -} - - - -static void wconhist_well_free(wconhist_well_type * well) -{ - free(well->name); - free(well); -} - - - -static void wconhist_well_free__(void * well) -{ - wconhist_well_free( (wconhist_well_type *) well); -} - - - -static void wconhist_well_fprintf(const wconhist_well_type * well, FILE * stream) -{ - fprintf(stream, " "); - sched_util_fprintf_qst(well->def[0], well->name , 8, stream); - sched_util_fprintf_qst(well->def[1], sched_types_get_status_string(well->status) , 4, stream); - sched_util_fprintf_qst(well->def[2], sched_types_get_cm_string(well->cmode) , 4, stream); - sched_util_fprintf_dbl(well->def[3], well->orat , 11, 3, stream); - sched_util_fprintf_dbl(well->def[4], well->wrat , 11, 3, stream); - sched_util_fprintf_dbl(well->def[5], well->grat , 11, 3, stream); - sched_util_fprintf_int(well->def[6], well->vfptable , 4 , stream); - sched_util_fprintf_dbl(well->def[7], well->alift , 11, 3, stream); - sched_util_fprintf_dbl(well->def[8], well->thp , 11, 3, stream); - sched_util_fprintf_dbl(well->def[9] , well->bhp , 11, 3, stream); - sched_util_fprintf_dbl(well->def[10], well->wgrat , 11, 3, stream); - fprintf(stream, "/\n"); -} - - - - - - -static wconhist_well_type * wconhist_well_alloc_from_tokens(const stringlist_type * line_tokens ) { - wconhist_well_type * well = wconhist_well_alloc_empty( ); - sched_util_init_default( line_tokens , well->def ); - - well->name = util_alloc_string_copy(stringlist_iget(line_tokens, 0)); - - if(!well->def[1]) - well->status = sched_types_get_status_from_string(stringlist_iget(line_tokens , 1)); - if (well->status == DEFAULT) - well->status = WCONHIST_DEFAULT_STATUS; - - - if(!well->def[2]) - well->cmode = sched_types_get_cm_from_string(stringlist_iget(line_tokens , 2) , true); - - well->orat = sched_util_atof(stringlist_iget(line_tokens , 3)); - well->wrat = sched_util_atof(stringlist_iget(line_tokens , 4)); - well->grat = sched_util_atof(stringlist_iget(line_tokens , 5)); - well->vfptable = sched_util_atoi(stringlist_iget(line_tokens , 6)); - well->alift = sched_util_atof(stringlist_iget(line_tokens , 7)); - well->thp = sched_util_atof(stringlist_iget(line_tokens , 8)); - well->bhp = sched_util_atof(stringlist_iget(line_tokens , 9)); - well->wgrat = sched_util_atof(stringlist_iget(line_tokens , 10)); - - return well; -} - - - - - - -static hash_type * wconhist_well_export_obs_hash(const wconhist_well_type * well) -{ - hash_type * obs_hash = hash_alloc(); - - if(!well->def[3]) - hash_insert_double(obs_hash, "WOPR", well->orat); - - if(!well->def[4]) - hash_insert_double(obs_hash, "WWPR", well->wrat); - - if(!well->def[5]) - hash_insert_double(obs_hash, "WGPR", well->grat); - - if(!well->def[8]) - hash_insert_double(obs_hash, "WTHP", well->thp); - - if(!well->def[9]) - hash_insert_double(obs_hash, "WBHP", well->bhp); - - if(!well->def[10]) - hash_insert_double(obs_hash, "WWGPR", well->wgrat); - - // Water cut. - if(!well->def[3] && !well->def[4]) - { - double wct; - if(well->orat + well->wrat > 0.0) - wct = well->wrat / (well->orat + well->wrat); - else - wct = 0.0; - - hash_insert_double(obs_hash, "WWCT", wct); - } - - // Gas oil ratio. - if(!well->def[3] && !well->def[5]) - { - double gor; - if(well->orat > 0.0) - { - gor = well->grat / well->orat; - hash_insert_double(obs_hash, "WGOR", gor); - } - } - - return obs_hash; -} - - -static void sched_kw_wconhist_add_well( sched_kw_wconhist_type * kw , wconhist_well_type * well) { - vector_append_owned_ref(kw->wells, well, wconhist_well_free__); -} - - - - -static sched_kw_wconhist_type * sched_kw_wconhist_alloc_empty() -{ - sched_kw_wconhist_type * kw = util_malloc(sizeof * kw); - UTIL_TYPE_ID_INIT( kw , SCHED_KW_WCONHIST_ID ); - kw->wells = vector_alloc_new(); - return kw; -} - - - -sched_kw_wconhist_type * sched_kw_wconhist_safe_cast( void * arg ) { - sched_kw_wconhist_type * kw = (sched_kw_wconhist_type * ) arg; - if (kw->__type_id == SCHED_KW_WCONHIST_ID) - return kw; - else { - util_abort("%s: runtime cast failed \n",__func__); - return NULL; - } -} - - - -/***********************************************************************/ - - - -sched_kw_wconhist_type * sched_kw_wconhist_alloc(const stringlist_type * tokens , int * token_index ) { - sched_kw_wconhist_type * kw = sched_kw_wconhist_alloc_empty(); - int eokw = false; - do { - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , false , WCONHIST_NUM_KW , token_index ); - if (line_tokens == NULL) - eokw = true; - else { - wconhist_well_type * well = wconhist_well_alloc_from_tokens( line_tokens ); - sched_kw_wconhist_add_well( kw , well ); - stringlist_free( line_tokens ); - } - - } while (!eokw); - return kw; -} - - -void sched_kw_wconhist_free(sched_kw_wconhist_type * kw) -{ - vector_free(kw->wells); - free(kw); -} - - - -void sched_kw_wconhist_fprintf(const sched_kw_wconhist_type * kw, FILE * stream) -{ - int size = vector_get_size(kw->wells); - - fprintf(stream, "WCONHIST\n"); - for(int i=0; iwells, i); - wconhist_well_fprintf(well, stream); - } - fprintf(stream,"/\n\n"); -} - - -/***********************************************************************/ - - - -hash_type * sched_kw_wconhist_alloc_well_obs_hash(const sched_kw_wconhist_type * kw) -{ - hash_type * well_hash = hash_alloc(); - - int num_wells = vector_get_size(kw->wells); - - for(int well_nr=0; well_nrwells, well_nr); - hash_type * obs_hash = wconhist_well_export_obs_hash(well); - hash_insert_hash_owned_ref(well_hash, well->name, obs_hash, hash_free__); - } - - return well_hash; -} - -sched_kw_wconhist_type * sched_kw_wconhist_copyc(const sched_kw_wconhist_type * kw) { - util_abort("%s: not implemented ... \n",__func__); - return NULL; -} - - - -/***********************************************************************/ -/* Functions exported for the sched_file_update api. */ - - - -/** Will return NULL if the well is not present. */ -static wconhist_well_type * sched_kw_wconhist_get_well( const sched_kw_wconhist_type * kw , const char * well_name) { - int size = vector_get_size(kw->wells); - wconhist_well_type * well = NULL; - int index = 0; - do { - wconhist_well_type * iwell = vector_iget( kw->wells , index); - if (strcmp( well_name , iwell->name ) == 0) - well = iwell; - - index++; - } while ((well == NULL) && (index < size)); - return well; -} - - -/*****************************************************************/ - - -double sched_kw_wconhist_get_orat( sched_kw_wconhist_type * kw , const char * well_name) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) - return well->orat; - else - return -1; -} - -void sched_kw_wconhist_scale_orat( sched_kw_wconhist_type * kw , const char * well_name, double factor) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) - well->orat *= factor; -} - -void sched_kw_wconhist_shift_orat( sched_kw_wconhist_type * kw , const char * well_name, double shift_value) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) { - well->orat += shift_value; - if (well->orat < 0) - well->orat = 0; - } -} - -void sched_kw_wconhist_set_orat( sched_kw_wconhist_type * kw , const char * well_name , double orat) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) - well->orat = orat; -} - -/*****************************************************************/ -/* WRAT functions */ - -double sched_kw_wconhist_get_wrat( sched_kw_wconhist_type * kw , const char * well_name) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) - return well->wrat; - else - return -1; -} - -void sched_kw_wconhist_scale_wrat( sched_kw_wconhist_type * kw , const char * well_name, double factor) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) - well->wrat *= factor; -} - -void sched_kw_wconhist_shift_wrat( sched_kw_wconhist_type * kw , const char * well_name, double shift_value) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) { - well->wrat += shift_value; - if (well->wrat < 0) - well->wrat = 0; - } -} - -void sched_kw_wconhist_set_wrat( sched_kw_wconhist_type * kw , const char * well_name , double wrat) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) - well->wrat = wrat; -} - -/*****************************************************************/ -/* GRAT functions */ - -double sched_kw_wconhist_get_grat( sched_kw_wconhist_type * kw , const char * well_name) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) - return well->grat; - else - return -1; -} - -void sched_kw_wconhist_scale_grat( sched_kw_wconhist_type * kw , const char * well_name, double factor) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) - well->grat *= factor; -} - -void sched_kw_wconhist_shift_grat( sched_kw_wconhist_type * kw , const char * well_name, double shift_value) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) { - well->grat += shift_value; - if (well->grat < 0) - well->grat = 0; - } -} - -void sched_kw_wconhist_set_grat( sched_kw_wconhist_type * kw , const char * well_name , double grat) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) - well->grat = grat; -} - - -/*****************************************************************/ - - -bool sched_kw_wconhist_has_well( const sched_kw_wconhist_type * kw , const char * well_name) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well == NULL) - return false; - else - return true; -} - -/** - This keyword checks if the well @well_name is open in this wconhist - instance. The check is quite simple: if the wconhist instance has - this well, and that well has status == OPEN AND a finite rate of at - least one phase - we return true, in ALL other cases we return - false. - - Observe that this function has no possibility to check well-names - +++ - if you ask for a non-existing well you will just get false. -*/ - - -bool sched_kw_wconhist_well_open( const sched_kw_wconhist_type * kw, const char * well_name) { - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well == NULL) - return false; - else { - /* OK - we have the well. */ - if (well->status == OPEN) { - /* The well seems to be open - any rates around? */ - if ((well->orat + well->grat + well->wrat) > 0.0) - return true; - else - return false; - } else - return false; - } -} - -/*****************************************************************/ - - -/** - Will update the input parameter @well_list to contain all the - well_names present in the current sced_kw_wconhist keyword. -*/ - -void sched_kw_wconhist_init_well_list( const sched_kw_wconhist_type * kw , stringlist_type * well_list) { - stringlist_clear( well_list ); - { - int iw; - for (iw = 0; iw < vector_get_size( kw->wells ); iw++) { - const wconhist_well_type * well = vector_iget_const( kw->wells , iw ); - stringlist_append_ref( well_list , well->name ); - } - } -} - - -/*****************************************************************/ - -static UTIL_SAFE_CAST_FUNCTION_CONST( wconhist_state , WCONHIST_TYPE_ID) -static UTIL_SAFE_CAST_FUNCTION( wconhist_state , WCONHIST_TYPE_ID) - - - - -static double well_util_total( const time_t_vector_type * time, const double_vector_type * rate , int report_step ) { - double total = 0; - for (int index = 1; index <= report_step; index++) { - /* It is a HARD assumption that the rate values in @rate are given as volume / day. */ - double days = (time_t_vector_iget( time , index ) - time_t_vector_iget( time , index - 1)) / 86400; - total += days * double_vector_iget( rate , index ); - } - - return total; -} - - -double wconhist_state_iget_WOPTH( const void * state , int report_step ) { - const wconhist_state_type * wconhist_state = wconhist_state_safe_cast_const( state ); - return well_util_total( wconhist_state->time , wconhist_state->oil_rate , report_step ); -} - - -double wconhist_state_iget_WGPTH( const void * state , int report_step ) { - const wconhist_state_type * wconhist_state = wconhist_state_safe_cast_const( state ); - return well_util_total( wconhist_state->time , wconhist_state->gas_rate , report_step ); -} - - -double wconhist_state_iget_WWPTH( const void * state , int report_step ) { - const wconhist_state_type * wconhist_state = wconhist_state_safe_cast_const( state ); - return well_util_total( wconhist_state->time , wconhist_state->water_rate , report_step ); -} - - -/* - Functions implementing the wconhist state; the naming convention - here should follow the one used in summary files, i.e. WOPR to get Oil Production Rate. -*/ - - -double wconhist_state_iget_WBHPH( const void * state , int report_step ) { - const wconhist_state_type * wconhist_state = wconhist_state_safe_cast_const( state ); - return double_vector_safe_iget( wconhist_state->bhp , report_step ); -} - - -double wconhist_state_iget_WOPRH( const void * state , int report_step ) { - const wconhist_state_type * wconhist_state = wconhist_state_safe_cast_const( state ); - return double_vector_safe_iget( wconhist_state->oil_rate , report_step ); -} - - -double wconhist_state_iget_WGPRH( const void * state , int report_step ) { - const wconhist_state_type * wconhist_state = wconhist_state_safe_cast_const( state ); - return double_vector_safe_iget( wconhist_state->gas_rate , report_step ); -} - - -double wconhist_state_iget_WWPRH( const void * state , int report_step ) { - const wconhist_state_type * wconhist_state = wconhist_state_safe_cast_const( state ); - return double_vector_safe_iget( wconhist_state->water_rate , report_step ); -} - - -double wconhist_state_iget_WWCTH( const void * state , int report_step ) { - double WWPR = wconhist_state_iget_WWPRH( state , report_step ); - double WOPR = wconhist_state_iget_WOPRH( state , report_step ); - - return WWPR / ( WWPR + WOPR ); -} - - -double wconhist_state_iget_WGORH(const void * state , int report_step ) { - double WGPR = wconhist_state_iget_WGPRH( state , report_step ); - double WOPR = wconhist_state_iget_WOPRH( state , report_step ); - return WGPR / WOPR; -} - - -/* - Uncertain about this memnonic?? -*/ - -well_cm_enum wconhist_state_iget_WMCTLH( const void * state , int report_step ) { - const wconhist_state_type * wconhist_state = wconhist_state_safe_cast_const( state ); - return int_vector_iget( wconhist_state->cmode , report_step ); -} - - -//well_status_enum wconhist_state_iget_status( const void * state , int report_step ) { - -// All callbacks return double ... should really be an enum value -double wconhist_state_iget_STAT( const void * state , int report_step ) { - const wconhist_state_type * wconhist_state = wconhist_state_safe_cast_const( state ); - return int_vector_iget( wconhist_state->state , report_step ); -} - - - -wconhist_state_type * wconhist_state_alloc( const time_t_vector_type * time) { - wconhist_state_type * wconhist = util_malloc( sizeof * wconhist ); - UTIL_TYPE_ID_INIT( wconhist , WCONHIST_TYPE_ID ); - - wconhist->time = time; - wconhist->state = int_vector_alloc( 0 , WCONHIST_DEFAULT_STATUS ); - wconhist->cmode = int_vector_alloc( 0 , 0 ); - - wconhist->oil_rate = double_vector_alloc( 0 , 0 ); - wconhist->gas_rate = double_vector_alloc( 0 , 0 ); - wconhist->water_rate = double_vector_alloc( 0 , 0 ); - - /* - The vfp_table and art_list keywords have an EXTREMELY ugly - DEFAULT behaviour - it changes as function of time: - - 1. The first occurence of a default value should be interpreted - as a '0'. - - 2. The second occurence of a default value should be interpreted - as 'No change prom previous value' - whatever that was. - - This behaviour is not properly supported in this implementation. - */ - - - wconhist->vfp_table = int_vector_alloc( 0 , 0 ); - wconhist->art_lift = double_vector_alloc( 0 , 0); - - wconhist->thp = double_vector_alloc( 0 , 0 ); - wconhist->bhp = double_vector_alloc( 0 , 0 ); - wconhist->wgas_rate = double_vector_alloc( 0 , 0 ); - - return wconhist; -} - - -void wconhist_state_free( wconhist_state_type * wconhist ) { - int_vector_free( wconhist->state ); - int_vector_free( wconhist->cmode ); - int_vector_free( wconhist->vfp_table ); - - double_vector_free( wconhist->oil_rate ); - double_vector_free( wconhist->gas_rate ); - double_vector_free( wconhist->water_rate ); - double_vector_free( wconhist->art_lift ); - double_vector_free( wconhist->thp ); - double_vector_free( wconhist->bhp ); - double_vector_free( wconhist->wgas_rate ); - - free( wconhist ); -} - - -void wconhist_state_free__( void * arg ) { - wconhist_state_free( wconhist_state_safe_cast( arg )); -} - - - -void sched_kw_wconhist_update_state(const sched_kw_wconhist_type * kw , wconhist_state_type * state , const char * well_name , int report_step ) { - - wconhist_well_type * well = sched_kw_wconhist_get_well( kw , well_name ); - if (well != NULL) { - - int_vector_iset_default( state->state , report_step , well->status ); - int_vector_iset_default( state->cmode , report_step , well->cmode ); - double_vector_iset_default( state->oil_rate , report_step , well->orat ); - double_vector_iset_default( state->water_rate , report_step , well->wrat ); - double_vector_iset_default( state->gas_rate , report_step , well->grat ); - int_vector_iset_default( state->vfp_table , report_step , well->vfptable ); - double_vector_iset_default( state->art_lift , report_step , well->alift ); - double_vector_iset_default( state->thp , report_step , well->thp ); - double_vector_iset_default( state->bhp , report_step , well->bhp ); - double_vector_iset_default( state->wgas_rate , report_step , well->wgrat ); - - } -} - - - -void sched_kw_wconhist_close_state( wconhist_state_type * state , int report_step ) { - int_vector_iset_default( state->state , report_step , SHUT ); /* SHUT or STOP?? This will fuck up a bit when what is actually happening is that the well goes over to - WCONPROD control, because the WCONPROD keyword is not internalized at all; so the well be stuck in this - status. */ - int_vector_iset_default( state->cmode , report_step , CM_SHUT ); - /* - If code ever ends up by querying one of the states below here - there is something wrong. - */ - - double_vector_iset_default( state->oil_rate , report_step , -1); - double_vector_iset_default( state->water_rate , report_step , -1); - double_vector_iset_default( state->gas_rate , report_step , -1); - int_vector_iset_default( state->vfp_table , report_step , -1); - double_vector_iset_default( state->art_lift , report_step , -1); - double_vector_iset_default( state->thp , report_step , -1); - double_vector_iset_default( state->bhp , report_step , -1); - double_vector_iset_default( state->wgas_rate , report_step , -1); - -} - - -KW_IMPL(wconhist) diff --git a/ThirdParty/Ert/libsched/src/sched_kw_wconinj.c b/ThirdParty/Ert/libsched/src/sched_kw_wconinj.c deleted file mode 100644 index fdfb0986b9..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_wconinj.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_wconinj.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include - -#include -#include -#include - - - -/** - This file implements a very basic support for the WCONINJ - keyword. It internalizes a list of well names, apart from that all - information is just tucked into a untyped keyword. - - This means that all the functionality which is supported by the - sched_kw_wconinj implementation is asking for well names. - - It is an independent implementation - but the original - implementation is PURE COPY AND PASTE from the WCONPROD - implementation. -*/ - - - - - -struct sched_kw_wconinj_struct { - sched_kw_untyped_type * untyped_kw; - stringlist_type * wells; -}; - - - - - -static sched_kw_wconinj_type * sched_kw_wconinj_alloc_empty(bool alloc_untyped) -{ - sched_kw_wconinj_type * kw = util_malloc(sizeof * kw); - kw->wells = stringlist_alloc_new(); - if (alloc_untyped) - kw->untyped_kw = sched_kw_untyped_alloc_empty("WCONINJ" , -1 /* -1: Variable length keyword */ ); - else - kw->untyped_kw = NULL; - return kw; -} - - - -void sched_kw_wconinj_free(sched_kw_wconinj_type * kw) -{ - stringlist_free(kw->wells); - sched_kw_untyped_free(kw->untyped_kw); -} - - -static void sched_kw_wconinj_add_well(sched_kw_wconinj_type * kw , const char * well) { - stringlist_append_copy(kw->wells , well); -} - - - - - -sched_kw_wconinj_type * sched_kw_wconinj_alloc(const stringlist_type * tokens , int * token_index ) { - sched_kw_wconinj_type * kw = sched_kw_wconinj_alloc_empty( true ); - int eokw = false; - do { - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , false , 0 , token_index ); - if (line_tokens == NULL) - eokw = true; - else { - char * well = util_alloc_dequoted_copy( stringlist_iget( line_tokens , 0 ) ); - sched_kw_wconinj_add_well(kw , well); - sched_kw_untyped_add_tokens(kw->untyped_kw , line_tokens); - stringlist_free( line_tokens ); - free( well ); - } - - } while (!eokw); - return kw; -} - - -void sched_kw_wconinj_fprintf(const sched_kw_wconinj_type * kw , FILE * stream) { - sched_kw_untyped_fprintf( kw->untyped_kw , stream ); -} - - -char ** sched_kw_wconinj_alloc_wells_copy( const sched_kw_wconinj_type * kw , int * num_wells) { - *num_wells = stringlist_get_size( kw->wells ); - return stringlist_alloc_char_copy( kw->wells ); -} - -sched_kw_wconinj_type * sched_kw_wconinj_copyc(const sched_kw_wconinj_type * kw) { - util_abort("%s: not implemented ... \n",__func__); - return NULL; -} - - - -/*****************************************************************/ - -KW_IMPL(wconinj) - diff --git a/ThirdParty/Ert/libsched/src/sched_kw_wconinje.c b/ThirdParty/Ert/libsched/src/sched_kw_wconinje.c deleted file mode 100644 index 767966238f..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_wconinje.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_wconinje.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -#define DEFAULT_INJECTOR_STATE OPEN - -#define SCHED_KW_WCONINJE_ID 99165 -#define WCONINJE_TYPE_ID 5705235 -#define WCONINJE_NUM_KW 10 -#define ECL_DEFAULT_KW "*" - - -struct sched_kw_wconinje_struct { - int __type_id; - vector_type * wells; /* A vector of wconinje_well_type instances. */ -}; - - - -typedef struct { - bool def[WCONINJE_NUM_KW]; /* Has the item been defaulted? */ - - char * name; /* This does NOT support well_name_root or well list notation. */ - sched_phase_enum injector_type; /* Injecting GAS/WATER/OIL */ - well_status_enum status; /* Well is open/shut/??? */ - well_cm_enum cmode; /* How is the well controlled? */ - double surface_flow; - double reservoir_flow; - double BHP_target; - double THP_target; - int vfp_table_nr; - double vapoil_conc; -} wconinje_well_type; - - - - - -struct wconinje_state_struct { - UTIL_TYPE_ID_DECLARATION; - char * well_name; - const time_t_vector_type * time; - int_vector_type * phase; /* Contains values from sched_phase_enum */ - int_vector_type * state; /* Contains values from the well_status_enum. */ - int_vector_type * cmode; /* Contains values from the well_cm_enum. */ - double_vector_type * surface_flow; - double_vector_type * reservoir_flow; - double_vector_type * bhp_limit; - double_vector_type * thp_limit; - int_vector_type * vfp_table_nr; - double_vector_type * vapoil; -}; - - - - -/*****************************************************************/ -/* Implemeentation of the internal wconinje_well_type data type. */ - - - - - - - - - - -static wconinje_well_type * wconinje_well_alloc_empty() -{ - wconinje_well_type * well = util_malloc(sizeof * well); - well->name = NULL; - return well; -} - - - -static void wconinje_well_free(wconinje_well_type * well) -{ - free(well->name); - free(well); -} - - - -static void wconinje_well_free__(void * well) -{ - wconinje_well_free( (wconinje_well_type *) well); -} - - - - - -static wconinje_well_type * wconinje_well_alloc_from_tokens(const stringlist_type * line_tokens ) { - wconinje_well_type * well = wconinje_well_alloc_empty(); - sched_util_init_default( line_tokens , well->def ); - - well->name = util_alloc_string_copy( stringlist_iget( line_tokens , 0 )); - well->injector_type = sched_phase_type_from_string(stringlist_iget(line_tokens , 1)); - well->cmode = sched_types_get_cm_from_string( stringlist_iget( line_tokens , 3 ) , false); - well->surface_flow = sched_util_atof( stringlist_iget( line_tokens , 4 )); - well->reservoir_flow = sched_util_atof(stringlist_iget(line_tokens , 5 )); - well->BHP_target = sched_util_atof(stringlist_iget(line_tokens , 6 )); - well->THP_target = sched_util_atof( stringlist_iget( line_tokens , 7 )); - well->vfp_table_nr = sched_util_atoi( stringlist_iget( line_tokens , 8)); - well->vapoil_conc = sched_util_atof( stringlist_iget( line_tokens , 9 )); - - well->status = sched_types_get_status_from_string( stringlist_iget( line_tokens , 2 )); - if (well->status == DEFAULT) - well->status = DEFAULT_INJECTOR_STATE; - return well; -} - - - -static void wconinje_well_fprintf(const wconinje_well_type * well, FILE * stream) -{ - fprintf(stream, " "); - sched_util_fprintf_qst(well->def[0], well->name , 8, stream); - sched_util_fprintf_qst(well->def[1], sched_phase_type_string(well->injector_type) , 5, stream); /* 5 ?? */ - sched_util_fprintf_qst(well->def[2], sched_types_get_status_string(well->status) , 4, stream); - sched_util_fprintf_qst(well->def[3], sched_types_get_cm_string(well->cmode) , 4, stream); - sched_util_fprintf_dbl(well->def[4], well->surface_flow , 11, 3, stream); - sched_util_fprintf_dbl(well->def[5], well->reservoir_flow , 11, 3, stream); - sched_util_fprintf_dbl(well->def[6], well->BHP_target , 11, 3, stream); - sched_util_fprintf_dbl(well->def[7], well->THP_target , 11, 3, stream); - sched_util_fprintf_int(well->def[8], well->vfp_table_nr , 4, stream); - sched_util_fprintf_dbl(well->def[9], well->vapoil_conc , 11, 3, stream); - fprintf(stream, "/ \n"); -} - - -/*****************************************************************/ - - - - -static sched_kw_wconinje_type * sched_kw_wconinje_alloc_empty() { - sched_kw_wconinje_type * kw = util_malloc(sizeof * kw); - kw->wells = vector_alloc_new(); - kw->__type_id = SCHED_KW_WCONINJE_ID; - return kw; -} - -sched_kw_wconinje_type * sched_kw_wconinje_safe_cast( void * arg ) { - sched_kw_wconinje_type * kw = (sched_kw_wconinje_type * ) arg; - if (kw->__type_id == SCHED_KW_WCONINJE_ID) - return kw; - else { - util_abort("%s: runtime cast failed \n",__func__); - return NULL; - } -} - - - - -void sched_kw_wconinje_free(sched_kw_wconinje_type * kw) -{ - vector_free( kw->wells ); - free(kw); -} - - -static void sched_kw_wconinje_add_well( sched_kw_wconinje_type * kw , const wconinje_well_type * well) { - vector_append_owned_ref(kw->wells , well , wconinje_well_free__); -} - - - - - -sched_kw_wconinje_type * sched_kw_wconinje_alloc(const stringlist_type * tokens , int * token_index ) { - sched_kw_wconinje_type * kw = sched_kw_wconinje_alloc_empty(); - int eokw = false; - do { - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , false , WCONINJE_NUM_KW , token_index ); - if (line_tokens == NULL) - eokw = true; - else { - wconinje_well_type * well = wconinje_well_alloc_from_tokens( line_tokens ); - sched_kw_wconinje_add_well( kw , well ); - stringlist_free( line_tokens ); - } - } while (!eokw); - return kw; -} - - - -void sched_kw_wconinje_fprintf(const sched_kw_wconinje_type * kw , FILE * stream) { - int size = vector_get_size(kw->wells); - - fprintf(stream, "WCONINJE\n"); - for(int i=0; iwells, i); - wconinje_well_fprintf(well, stream); - } - fprintf(stream,"/\n\n"); -} - - - -char ** sched_kw_wconinje_alloc_wells_copy( const sched_kw_wconinje_type * kw , int * num_wells) { - int size = vector_get_size(kw->wells); - - char ** well_names = util_malloc( size * sizeof * well_names ); - for(int i=0; iwells, i); - well_names[i] = util_alloc_string_copy(well->name); - } - *num_wells = size; - return well_names; -} - - - - -/*****************************************************************/ -/* Functions exporting content to be used with the sched_file_update - api. */ - -/** Will return NULL if the well is not present. */ -static wconinje_well_type * sched_kw_wconinje_get_well( const sched_kw_wconinje_type * kw , const char * well_name) { - int size = vector_get_size(kw->wells); - wconinje_well_type * well = NULL; - int index = 0; - do { - wconinje_well_type * iwell = vector_iget( kw->wells , index); - if (strcmp( well_name , iwell->name ) == 0) - well = iwell; - - index++; - } while ((well == NULL) && (index < size)); - return well; -} - - - -double sched_kw_wconinje_get_surface_flow( const sched_kw_wconinje_type * kw , const char * well_name) { - wconinje_well_type * well = sched_kw_wconinje_get_well( kw , well_name ); - if (well != NULL) - return well->surface_flow; - else - return -1; -} - -void sched_kw_wconinje_scale_surface_flow( const sched_kw_wconinje_type * kw , const char * well_name, double factor) { - wconinje_well_type * well = sched_kw_wconinje_get_well( kw , well_name ); - if (well != NULL) - well->surface_flow *= factor; -} - -void sched_kw_wconinje_set_surface_flow( const sched_kw_wconinje_type * kw , const char * well_name , double surface_flow) { - wconinje_well_type * well = sched_kw_wconinje_get_well( kw , well_name ); - if (well != NULL) - well->surface_flow = surface_flow; -} - - - -void sched_kw_wconinje_shift_surface_flow( const sched_kw_wconinje_type * kw , const char * well_name , double delta_surface_flow) { - wconinje_well_type * well = sched_kw_wconinje_get_well( kw , well_name ); - if (well != NULL) - well->surface_flow += delta_surface_flow; -} - - -sched_phase_enum sched_kw_wconinje_get_phase( const sched_kw_wconinje_type * kw , const char * well_name) { - wconinje_well_type * well = sched_kw_wconinje_get_well( kw , well_name ); - if (well != NULL) - return well->injector_type; - else - return -1; -} - - - -bool sched_kw_wconinje_has_well( const sched_kw_wconinje_type * kw , const char * well_name) { - wconinje_well_type * well = sched_kw_wconinje_get_well( kw , well_name ); - if (well == NULL) - return false; - else - return true; -} - - -sched_kw_wconinje_type * sched_kw_wconinje_copyc(const sched_kw_wconinje_type * kw) { - util_abort("%s: not implemented ... \n",__func__); - return NULL; -} - - -bool sched_kw_wconinje_well_open( const sched_kw_wconinje_type * kw, const char * well_name) { - wconinje_well_type * well = sched_kw_wconinje_get_well( kw , well_name ); - if (well == NULL) - return false; - else { - /* OK - we have the well. */ - - if (well->status == OPEN) { - /* The well seems to be open - any rates around? */ - if (well->surface_flow > 0) - return true; - else - return false; - } else - return false; } -} - -/*****************************************************************/ - - -/*****************************************************************/ - -wconinje_state_type * wconinje_state_alloc( const char * well_name , const time_t_vector_type * time) { - wconinje_state_type * wconinje = util_malloc( sizeof * wconinje); - UTIL_TYPE_ID_INIT( wconinje , WCONINJE_TYPE_ID ); - - wconinje->phase = int_vector_alloc( 0 , 0 ); - wconinje->state = int_vector_alloc( 0 , 0 ); /* Default wconinje state ? */ - wconinje->cmode = int_vector_alloc( 0 , 0 ); /* Default control mode ?? */ - wconinje->surface_flow = double_vector_alloc( 0 , 0 ); - wconinje->reservoir_flow = double_vector_alloc( 0 , 0 ); - wconinje->bhp_limit = double_vector_alloc( 0 , 0 ); - wconinje->thp_limit = double_vector_alloc( 0 , 0 ); - wconinje->vfp_table_nr = int_vector_alloc( 0 , 0 ); - wconinje->vapoil = double_vector_alloc( 0 ,0 ); - wconinje->time = time; - wconinje->well_name = util_alloc_string_copy( well_name ); - - return wconinje; -} - - -static UTIL_SAFE_CAST_FUNCTION( wconinje_state , WCONINJE_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION_CONST( wconinje_state , WCONINJE_TYPE_ID ) - -void wconinje_state_free( wconinje_state_type * wconinje ) { - - int_vector_free(wconinje->phase); - int_vector_free(wconinje->state); - int_vector_free(wconinje->cmode); - double_vector_free(wconinje->surface_flow); - double_vector_free(wconinje->reservoir_flow); - double_vector_free(wconinje->bhp_limit); - double_vector_free(wconinje->thp_limit); - int_vector_free(wconinje->vfp_table_nr); - double_vector_free(wconinje->vapoil); - free( wconinje->well_name ); - free( wconinje ); - -} - -void wconinje_state_free__( void * arg ) { - wconinje_state_free( wconinje_state_safe_cast( arg )); -} - - - -/** - This function asks for the historical water injection rate; however - this is the WCONINJE keyword, and it is NOT necessarily meaningful - to query this keyword for that rate. To be meaningfull we check the - following conditions: - - 1. We verify that the well is rate-controlled; then the behaviour - of the well should(??) coincide with that of wells specifed by - the WCONINJH keyword. - - 2. We verify that the injected phase is indeed water. - - If these conditions are not met 0 is returned, AND a warning is - written to stderr. -*/ - -double wconinje_state_iget_WWIRH( const void * __state , int report_step ) { - const wconinje_state_type * state = wconinje_state_safe_cast_const( __state ); - sched_phase_enum phase = int_vector_safe_iget( state->phase , report_step ); - well_cm_enum cmode = int_vector_safe_iget( state->cmode , report_step); - - if (( phase == WATER) && (cmode == RATE)) - return double_vector_safe_iget( state->surface_flow , report_step); - else { - if ( phase != WATER ) - fprintf(stderr,"** Warning you have asked for historical water injection rate in well:%s which is not a water injector.\n", state->well_name); - - if ( cmode != RATE ) - fprintf(stderr,"** Warning you have asked for historical water injection rate in well:%s which is not rate controlled - I have no clue?! \n" , state->well_name); - - return 0; - } -} - -/** - See comment above wconinje_state_get_WWIRH(); -*/ -double wconinje_state_iget_WGIRH( const void * __state , int report_step ) { - const wconinje_state_type * state = wconinje_state_safe_cast_const( __state ); - sched_phase_enum phase = int_vector_safe_iget( state->phase , report_step ); - well_cm_enum cmode = int_vector_safe_iget( state->cmode , report_step); - - if (( phase == GAS) && (cmode == RATE)) - return double_vector_safe_iget( state->surface_flow , report_step); - else { - if ( phase != GAS ) - fprintf(stderr,"** Warning you have asked for historical gas injection rate in well:%s(%d) which is not a gas injector.\n", state->well_name, report_step); - - if ( cmode != RATE ) - fprintf(stderr,"** Warning you have asked for historical gas injection rate in well:%s(%d) which is not rate controlled - I have no clue?! \n" , state->well_name, report_step); - - return 0; - } -} - -/** - Will update the input parameter @well_list to contain all the - well_names present in the current sced_kw_wconhist keyword. -*/ - -void sched_kw_wconinje_init_well_list( const sched_kw_wconinje_type * kw , stringlist_type * well_list) { - stringlist_clear( well_list ); - { - int iw; - for (iw = 0; iw < vector_get_size( kw->wells ); iw++) { - const wconinje_well_type * well = vector_iget_const( kw->wells , iw ); - stringlist_append_ref( well_list , well->name ); - } - } -} - - -/** - For production the WCONHIST keyword will (typically) be used for - the historical period, and WCONPROD for the predicton. This can be - used to differentiate between hisorical period and prediction - period. When it comes to injection things are not so clear; - typically the WCONINJE keyword is used both for prediction and - historical period. - - This function will check if all the wells (at least one) in the - WCONINJE keyword are rate-controlled, if so it is interpreted as - beeing in the historical period. -*/ - -bool sched_kw_wconinje_historical( const sched_kw_wconinje_type * kw ) { - bool historical = false; - int iw; - for (iw = 0; iw < vector_get_size( kw->wells ); iw++) { - const wconinje_well_type * well = vector_iget_const( kw->wells , iw ); - if (well->cmode == RATE) { - historical = true; - break; - } - } - return historical; -} - - - - - -void sched_kw_wconinje_update_state( const sched_kw_wconinje_type * kw , wconinje_state_type * state , const char * well_name , int report_step ) { - wconinje_well_type * well = sched_kw_wconinje_get_well( kw , well_name ); - if (well != NULL) { - int_vector_iset_default(state->phase , report_step , well->injector_type ); - int_vector_iset_default(state->state , report_step , well->status); - int_vector_iset_default(state->cmode , report_step , well->cmode); - double_vector_iset_default(state->surface_flow , report_step , well->surface_flow); - double_vector_iset_default(state->reservoir_flow , report_step , well->reservoir_flow); - double_vector_iset_default(state->bhp_limit , report_step , well->BHP_target); - double_vector_iset_default(state->thp_limit , report_step , well->THP_target); - int_vector_iset_default(state->vfp_table_nr , report_step , well->vfp_table_nr); - double_vector_iset_default(state->vapoil , report_step , well->vapoil_conc); - } -} - - -void sched_kw_wconinje_close_state(wconinje_state_type * state , int report_step ) { - fprintf(stderr,"** Warning: %s not implemented \n",__func__); - //int_vector_iset_default( state->state , report_step , SHUT ); /* SHUT or STOP ?? */ - //double_vector_iset_default(state->injection_rate , report_step , -1 ); - //double_vector_iset_default(state->bhp , report_step , -1 ); - //double_vector_iset_default(state->thp , report_step , -1 ); - //int_vector_iset_default(state->vfp_table_nr , report_step , -1 ); - //double_vector_iset_default(state->vapoil , report_step , -1 ); -} - - - - - -KW_IMPL(wconinje) diff --git a/ThirdParty/Ert/libsched/src/sched_kw_wconinjh.c b/ThirdParty/Ert/libsched/src/sched_kw_wconinjh.c deleted file mode 100644 index 42e954bb03..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_wconinjh.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_wconinjh.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define WCONINJH_TYPE_ID 88163977 -#define WCONINJH_NUM_KW 8 - - -struct sched_kw_wconhist_struct{ - vector_type * wells; -}; - - -typedef struct wconinjh_well_struct wconinjh_well_type; - - - -struct wconinjh_well_struct{ - /* - def: Read as defaulted, not defined! - */ - bool def[WCONINJH_NUM_KW]; - - char * name; - sched_phase_enum inj_phase; - well_status_enum status; - double inj_rate; - double bhp; - double thp; - int vfptable; - double vapdiscon; -}; - - -struct wconinjh_state_struct { - UTIL_TYPE_ID_DECLARATION; - const time_t_vector_type * time; - int_vector_type * phase; /* Contains values from sched_phase_enum */ - int_vector_type * state; /* Contains values from the well_status_enum. */ - double_vector_type * injection_rate; - double_vector_type * bhp; - double_vector_type * thp; - int_vector_type * vfp_table_nr; - double_vector_type * vapoil; -}; - - - -static wconinjh_well_type * wconinjh_well_alloc_empty() -{ - wconinjh_well_type * well = util_malloc(sizeof * well); - well->name = NULL; - return well; -} - - - -static void wconinjh_well_free(wconinjh_well_type * well) -{ - free(well->name); - free(well); -} - - - -static void wconinjh_well_free__(void * well) -{ - wconinjh_well_free( (wconinjh_well_type *) well); -} - - - -/** Will return NULL if the well is not present. */ -static wconinjh_well_type * sched_kw_wconinjh_get_well( const sched_kw_wconinjh_type * kw , const char * well_name) { - int size = vector_get_size(kw->wells); - wconinjh_well_type * well = NULL; - int index = 0; - do { - wconinjh_well_type * iwell = vector_iget( kw->wells , index); - if (strcmp( well_name , iwell->name ) == 0) - well = iwell; - - index++; - } while ((well == NULL) && (index < size)); - return well; -} - - -static void wconinjh_well_fprintf(const wconinjh_well_type * well, FILE * stream) -{ - fprintf(stream, " "); - sched_util_fprintf_qst(well->def[0], well->name , 8 , stream); - sched_util_fprintf_qst(well->def[1], sched_phase_type_string(well->inj_phase) , 5 , stream); - sched_util_fprintf_qst(well->def[2], sched_types_get_status_string(well->status) , 4 , stream); - sched_util_fprintf_dbl(well->def[3], well->inj_rate , 9 , 3 , stream); - sched_util_fprintf_dbl(well->def[4], well->bhp , 9 , 3 , stream); - sched_util_fprintf_dbl(well->def[5], well->thp , 9 , 3 , stream); - sched_util_fprintf_int(well->def[6], well->vfptable , 4 , stream); - sched_util_fprintf_dbl(well->def[7], well->vapdiscon , 9 , 3 , stream); - fprintf(stream, "/\n"); -} - - - - - - - - - -static wconinjh_well_type * wconinjh_well_alloc_from_tokens(const stringlist_type * line_tokens ) { - - wconinjh_well_type * well = wconinjh_well_alloc_empty(); - sched_util_init_default( line_tokens , well->def ); - - well->name = util_alloc_string_copy(stringlist_iget(line_tokens , 0)); - well->inj_phase = sched_phase_type_from_string(stringlist_iget(line_tokens , 1)); - well->status = sched_types_get_status_from_string(stringlist_iget(line_tokens , 2)); - well->inj_rate = sched_util_atof(stringlist_iget(line_tokens , 3)); - well->bhp = sched_util_atof(stringlist_iget(line_tokens , 4)); - well->thp = sched_util_atof(stringlist_iget(line_tokens , 5)); - well->vfptable = sched_util_atoi(stringlist_iget(line_tokens , 6)); - well->vapdiscon = sched_util_atof(stringlist_iget(line_tokens , 7)); - - return well; -} - - - -static hash_type * wconinjh_well_export_obs_hash(const wconinjh_well_type * well) { - hash_type * obs_hash = hash_alloc(); - - if(!well->def[3]) - { - switch(well->inj_phase) - { - case(WATER): - hash_insert_double(obs_hash, "WWIR", well->inj_rate); - break; - case(GAS): - hash_insert_double(obs_hash, "WGIR", well->inj_rate); - break; - case(OIL): - hash_insert_double(obs_hash, "WOIR", well->inj_rate); - break; - default: - break; - } - } - if(!well->def[4]) - hash_insert_double(obs_hash, "WBHP", well->bhp); - if(!well->def[5]) - hash_insert_double(obs_hash, "WTHP", well->thp); - - return obs_hash; -} - - -static void sched_kw_wconinjh_add_well( sched_kw_wconinjh_type * kw , wconinjh_well_type * well) { - vector_append_owned_ref(kw->wells , well , wconinjh_well_free__); -} - - - -static sched_kw_wconinjh_type * sched_kw_wconinjh_alloc_empty() -{ - sched_kw_wconinjh_type * kw = util_malloc(sizeof * kw); - kw->wells = vector_alloc_new(); - return kw; -} - - - -/***********************************************************************/ - - -sched_kw_wconinjh_type * sched_kw_wconinjh_alloc(const stringlist_type * tokens , int * token_index ) { - sched_kw_wconinjh_type * kw = sched_kw_wconinjh_alloc_empty(); - int eokw = false; - do { - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , false, WCONINJH_NUM_KW , token_index ); - if (line_tokens == NULL) - eokw = true; - else { - wconinjh_well_type * well = wconinjh_well_alloc_from_tokens( line_tokens ); - sched_kw_wconinjh_add_well( kw , well ); - stringlist_free( line_tokens ); - } - } while (!eokw); - return kw; -} - - -void sched_kw_wconinjh_free(sched_kw_wconinjh_type * kw) -{ - vector_free(kw->wells); - free(kw); -} - - - -void sched_kw_wconinjh_fprintf(const sched_kw_wconinjh_type * kw, FILE * stream) -{ - int size = vector_get_size(kw->wells); - - fprintf(stream, "WCONINJH\n"); - for(int i=0; iwells, i ); - wconinjh_well_fprintf(well, stream); - } - fprintf(stream,"/\n\n"); -} - - - - -/***********************************************************************/ - - - -hash_type * sched_kw_wconinjh_alloc_well_obs_hash(const sched_kw_wconinjh_type * kw) -{ - hash_type * well_hash = hash_alloc(); - - int num_wells = vector_get_size(kw->wells); - - for(int well_nr=0; well_nrwells, well_nr); - hash_type * obs_hash = wconinjh_well_export_obs_hash(well); - hash_insert_hash_owned_ref(well_hash, well->name, obs_hash, hash_free__); - } - - return well_hash; -} - -sched_kw_wconinjh_type * sched_kw_wconinjh_copyc(const sched_kw_wconinjh_type * kw) { - util_abort("%s: not implemented ... \n",__func__); - return NULL; -} - - -/*****************************************************************/ - -void sched_kw_wconinjh_init_well_list( const sched_kw_wconinjh_type * kw , stringlist_type * well_list) { - stringlist_clear( well_list ); - { - int iw; - for (iw = 0; iw < stringlist_get_size( well_list ); iw++) { - const wconinjh_well_type * well = vector_iget_const( kw->wells , iw ); - stringlist_append_ref( well_list , well->name ); - } - } -} - - - - -/*****************************************************************/ - -wconinjh_state_type * wconinjh_state_alloc( const time_t_vector_type* time) { - wconinjh_state_type * wconinjh = util_malloc( sizeof * wconinjh); - UTIL_TYPE_ID_INIT( wconinjh , WCONINJH_TYPE_ID ); - - wconinjh->time = time; - wconinjh->phase = int_vector_alloc( 0 , 0 ); - wconinjh->state = int_vector_alloc( 0 , 0 ); /* Default wconinjh state ? */ - wconinjh->injection_rate = double_vector_alloc( 0 , 0 ); - wconinjh->bhp = double_vector_alloc( 0 , 0 ); - wconinjh->thp = double_vector_alloc( 0 , 0 ); - wconinjh->vfp_table_nr = int_vector_alloc( 0 , 0 ); - wconinjh->vapoil = double_vector_alloc( 0 ,0 ); - - return wconinjh; -} - -UTIL_SAFE_CAST_FUNCTION( wconinjh_state , WCONINJH_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION_CONST( wconinjh_state , WCONINJH_TYPE_ID ) - -void wconinjh_state_free( wconinjh_state_type * wconinjh ) { - - int_vector_free( wconinjh->phase ); - int_vector_free( wconinjh->state ); - double_vector_free( wconinjh->injection_rate ); - double_vector_free( wconinjh->bhp ); - double_vector_free( wconinjh->thp ); - int_vector_free( wconinjh->vfp_table_nr ); - double_vector_free( wconinjh->vapoil ); - - free( wconinjh ); -} - - - -void wconinjh_state_free__( void * arg ) { - wconinjh_state_free( wconinjh_state_safe_cast( arg )); -} - - -/** - memnonic ?? -*/ - - -sched_phase_enum wconinjh_state_iget_phase( const wconinjh_state_type * state , int report_step) { - return int_vector_safe_iget( state->phase , report_step ); -} - - -well_status_enum wconinjh_state_iget_status( const wconinjh_state_type * state , int report_step ) { - return int_vector_safe_iget( state->state , report_step ); -} - -/** - Water injection rate - will return 0.0 if inj_phase == GAS. -*/ - -double wconinjh_state_iget_WWIRH( const void * __state , int report_step) { - const wconinjh_state_type * state = wconinjh_state_safe_cast_const( __state ); - if (wconinjh_state_iget_phase( state , report_step ) == WATER) - return double_vector_safe_iget( state->injection_rate , report_step); - else - return 0.0; -} - - -/** - Gas injection rate - will return 0.0 if inj_phase == WATER. -*/ - -double wconinjh_state_iget_WGIRH( const void * __state , int report_step) { - const wconinjh_state_type * state = wconinjh_state_safe_cast_const( __state ); - if (wconinjh_state_iget_phase( state , report_step ) == GAS) - return double_vector_safe_iget( state->injection_rate , report_step); - else - return 0.0; -} - - -/** - OIL injection rate - will return 0.0 if inj_phase == WATER|GAS -*/ - -double wconinjh_state_iget_WOIRH( const void * __state , int report_step) { - const wconinjh_state_type * state = wconinjh_state_safe_cast_const( __state ); - if (wconinjh_state_iget_phase( state , report_step ) == OIL) - return double_vector_safe_iget( state->injection_rate , report_step); - else - return 0.0; -} - - - -double wconinjh_state_iget_WBHPH( const void * __state , int report_step) { - const wconinjh_state_type * state = wconinjh_state_safe_cast_const( __state ); - return double_vector_safe_iget( state->bhp , report_step ); -} - - -double wconinjh_state_iget_WTHPH( const void * __state , int report_step) { - const wconinjh_state_type * state = wconinjh_state_safe_cast_const( __state ); - return double_vector_safe_iget( state->thp , report_step ); -} - -/** Memnonic ??*/ -double wconinjh_state_iget_WVPRH( const void * __state , int report_step) { - const wconinjh_state_type * state = wconinjh_state_safe_cast_const( __state ); - return double_vector_safe_iget( state->vapoil , report_step ); -} - - -int wconinjh_state_iget_vfp_table_nr( const wconinjh_state_type * state , int report_step) { - return int_vector_safe_iget( state->vfp_table_nr , report_step ); -} - - - - -void sched_kw_wconinjh_close_state(wconinjh_state_type * state , int report_step ) { - int_vector_iset_default( state->state , report_step , SHUT ); /* SHUT or STOP ?? */ - double_vector_iset_default(state->injection_rate , report_step , -1 ); - double_vector_iset_default(state->bhp , report_step , -1 ); - double_vector_iset_default(state->thp , report_step , -1 ); - int_vector_iset_default(state->vfp_table_nr , report_step , -1 ); - double_vector_iset_default(state->vapoil , report_step , -1 ); -} - - -void sched_kw_wconinjh_update_state( const sched_kw_wconinjh_type * kw , wconinjh_state_type * state , const char * well_name , int report_step ) { - wconinjh_well_type * well = sched_kw_wconinjh_get_well( kw , well_name ); - if (well != NULL) { - int_vector_iset_default(state->phase , report_step , well->inj_phase ); - int_vector_iset_default(state->state , report_step , well->status ); - double_vector_iset_default(state->injection_rate , report_step , well->inj_rate); - double_vector_iset_default(state->bhp , report_step , well->bhp); - double_vector_iset_default(state->thp , report_step , well->thp); - int_vector_iset_default(state->vfp_table_nr , report_step , well->vfptable); - double_vector_iset_default(state->vapoil , report_step , well->vapdiscon); - } -} - - - - -/***********************************************************************/ -KW_IMPL(wconinjh) diff --git a/ThirdParty/Ert/libsched/src/sched_kw_wconprod.c b/ThirdParty/Ert/libsched/src/sched_kw_wconprod.c deleted file mode 100644 index 07a9549544..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_wconprod.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_wconprod.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include - -#include -#include -#include - - - - -/** - This file implements a very basic support for the WCONPROD - keyword. It internalizes a list of well names, apart from that all - information is just tucked into a untyped keyword. - - This means that all the functionality which is sppurted by the - sched_kw_wconprod implementation is asking for well names. -*/ - - - - -struct sched_kw_wconprod_struct { - sched_kw_untyped_type * untyped_kw; - stringlist_type * wells; -}; - - - - - -static sched_kw_wconprod_type * sched_kw_wconprod_alloc_empty(bool alloc_untyped) -{ - sched_kw_wconprod_type * kw = util_malloc(sizeof * kw); - kw->wells = stringlist_alloc_new(); - if (alloc_untyped) - kw->untyped_kw = sched_kw_untyped_alloc_empty("WCONPROD" , -1 /* -1: Variable length keyword */); - else - kw->untyped_kw = NULL; - return kw; -} - - - -void sched_kw_wconprod_free(sched_kw_wconprod_type * kw) -{ - stringlist_free( kw->wells ); - sched_kw_untyped_free(kw->untyped_kw); - free( kw ); -} - - -static void sched_kw_wconprod_add_well(sched_kw_wconprod_type * kw , const char * well) { - stringlist_append_copy(kw->wells , well); -} - - - - - -sched_kw_wconprod_type * sched_kw_wconprod_alloc(const stringlist_type * tokens , int * token_index ) { - sched_kw_wconprod_type * kw = sched_kw_wconprod_alloc_empty( true ); - int eokw = false; - do { - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , true , 0 , token_index ); - if (line_tokens == NULL) - eokw = true; - else { - char * well = util_alloc_dequoted_copy( stringlist_iget( line_tokens , 0 ) ); - sched_kw_wconprod_add_well(kw , well); - sched_kw_untyped_add_tokens(kw->untyped_kw , line_tokens); - stringlist_free( line_tokens ); - free( well ); - } - - } while (!eokw); - return kw; -} - - -void sched_kw_wconprod_fprintf(const sched_kw_wconprod_type * kw , FILE * stream) { - sched_kw_untyped_fprintf( kw->untyped_kw , stream ); -} - - -char ** sched_kw_wconprod_alloc_wells_copy( const sched_kw_wconprod_type * kw , int * num_wells) { - *num_wells = stringlist_get_size( kw->wells ); - return stringlist_alloc_char_copy( kw->wells ); -} - - -sched_kw_wconprod_type * sched_kw_wconprod_copyc(const sched_kw_wconprod_type * kw) { - util_abort("%s: not implemented ... \n",__func__); - return NULL; -} - - -void sched_kw_wconprod_init_well_list( const sched_kw_wconprod_type * kw , stringlist_type * well_list) { - stringlist_clear( well_list ); - { - int iw; - for (iw = 0; iw < stringlist_get_size( kw->wells ); iw++) - stringlist_append_ref( well_list , stringlist_iget( kw->wells , iw) ); - } -} - - - -/*****************************************************************/ - -KW_IMPL(wconprod) - diff --git a/ThirdParty/Ert/libsched/src/sched_kw_welspecs.c b/ThirdParty/Ert/libsched/src/sched_kw_welspecs.c deleted file mode 100644 index c78a8fafda..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_kw_welspecs.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_kw_welspecs.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - - - -/* - TODO - - Create lookup STRING -> ENUM for all types and fix all strcmp! - -*/ - -/* - Define the maximum number of keywords in a WELSPEC record. - Note that this includes FrontSim and ECLIPSE 300 KWs. -*/ -#define WELSPECS_NUM_KW 16 -#define ECL_DEFAULT_KW "*" - - -#define DEFAULT_INFLOW_EQUATION IE_STD -#define DEFAULT_AUTO_SHUT_TYPE AS_SHUT -#define DEFAULT_CROSSFLOW_ABILITY CF_YES -#define DEFAULT_HDSTAT_TYPE HD_SEG - - -struct sched_kw_welspecs_struct -{ - vector_type * welspec_list; -}; - - -/* - See ECLIPSE Reference Manual, section WELSPECS for an explantion of - the members in the welspec_type struct. -*/ - -typedef enum {PH_OIL , PH_WAT , PH_GAS , PH_LIQ} phase_type; -#define PH_OIL_STRING "OIL" -#define PH_WAT_STRING "WATER" -#define PH_GAS_STRING "GAS" -#define PH_LIQ_STRING "LIQ" - - - -typedef enum {IE_STD, IE_NO, IE_RG, IE_YES, IE_PP, IE_GPP} inflow_eq_type; -#define IE_STD_STRING "STD" -#define IE_NO_STRING "NO" -#define IE_RG_STRING "R-G" -#define IE_YES_STRING "YES" -#define IE_PP_STRING "P-P" -#define IE_GPP_STRING "GPP" - - - -typedef enum {AS_STOP, AS_SHUT} auto_shut_type; -#define AS_STOP_STRING "STOP" -#define AS_SHUT_STRING "SHUT" - - - -typedef enum {CF_YES, CF_NO} crossflow_type; -#define CF_YES_STRING "YES" -#define CF_NO_STRING "NO" - -typedef enum {HD_SEG, HD_AVG} hdstat_head_type; -#define HD_SEG_STRING "SEG" -#define HD_AVG_STRING "AVG" - -typedef struct -{ - /* - def : Read as defaulted, not as defined. - */ - bool def[WELSPECS_NUM_KW]; - - char * name; - char * group; - int hh_i; - int hh_j; - double md; - phase_type phase; - double drain_rad; - inflow_eq_type inflow_eq; - auto_shut_type auto_shut; - crossflow_type crossflow; - int pvt_region; - hdstat_head_type hdstat_head; - int fip_region; - char * fs_kw1; - char * fs_kw2; - char * ecl300_kw; -} welspec_type; - - - -static char * get_phase_string(phase_type phase) -{ - switch(phase) - { - case(PH_OIL): - return PH_OIL_STRING; - case(PH_WAT): - return PH_WAT_STRING; - case(PH_GAS): - return PH_GAS_STRING; - case(PH_LIQ): - return PH_LIQ_STRING; - default: - return ECL_DEFAULT_KW; - } -}; - - - -static char * get_inflow_eq_string(inflow_eq_type eq) -{ - switch(eq) - { - case(IE_STD): - return IE_STD_STRING; - case(IE_NO): - return IE_NO_STRING; - case(IE_RG): - return IE_NO_STRING; - case(IE_YES): - return IE_YES_STRING; - case(IE_PP): - return IE_PP_STRING; - case(IE_GPP): - return IE_GPP_STRING; - default: - return ECL_DEFAULT_KW; - } -}; - - - -static char * get_auto_shut_string(auto_shut_type as) -{ - switch(as) - { - case(AS_STOP): - return AS_STOP_STRING; - case(AS_SHUT): - return AS_SHUT_STRING; - default: - return ECL_DEFAULT_KW; - } -}; - - - -static char * get_crossflow_string(crossflow_type cf) -{ - switch(cf) - { - case(CF_YES): - return CF_YES_STRING; - case(CF_NO): - return CF_NO_STRING; - default: - return ECL_DEFAULT_KW; - } -} - - - -static char * get_hdstat_head_string(hdstat_head_type hd) -{ - switch(hd) - { - case(HD_SEG): - return HD_SEG_STRING; - case(HD_AVG): - return HD_AVG_STRING; - default: - return ECL_DEFAULT_KW; - } -}; - - - -static inflow_eq_type get_inflow_eq_from_string(const char * string) -{ - if(strcmp(string , IE_STD_STRING) == 0) - return IE_STD; - else if(strcmp(string, IE_NO_STRING) == 0) - return IE_NO; - else if(strcmp(string, IE_RG_STRING) == 0) - return IE_RG; - else if(strcmp(string, IE_YES_STRING) == 0) - return IE_YES; - else if(strcmp(string, IE_PP_STRING) == 0) - return IE_PP; - else if(strcmp(string, IE_GPP_STRING) == 0) - return IE_GPP; - else if (strcmp(string , SCHED_KW_DEFAULT_ITEM) == 0) - return DEFAULT_INFLOW_EQUATION; - else - util_abort("%s: Inflow equation %s not recognized - aborting.\n",__func__, string); - return IE_STD; -} - - - -/* No default is defined according to the documentation. */ -static phase_type get_phase_from_string(const char * string) -{ - if(strcmp(string , PH_OIL_STRING) == 0) - return PH_OIL; - else if(strcmp(string, PH_WAT_STRING) == 0) - return PH_WAT; - else if(strcmp(string, PH_GAS_STRING) == 0) - return PH_GAS; - else if(strcmp(string, PH_LIQ_STRING) == 0) - return PH_LIQ; - else - util_abort("%s: Phase %s not recognized - aborting.\n",__func__,string); - return 0; -} - - - -static auto_shut_type get_auto_shut_from_string(const char * string) -{ - if(strcmp(string, AS_STOP_STRING) == 0) - return AS_STOP; - else if (strcmp(string,AS_SHUT_STRING) == 0) - return AS_SHUT; - else if (strcmp(string , SCHED_KW_DEFAULT_ITEM) == 0) - return DEFAULT_AUTO_SHUT_TYPE; - else - util_abort("%s: Automatic shut-in mode %s not recognized - aborting.\n",__func__,string); - return 0; -} - - - -static crossflow_type get_crossflow_from_string(const char * string) -{ - if(strcmp(string ,CF_YES_STRING) == 0) - return CF_YES; - else if(strcmp(string,CF_NO_STRING) == 0) - return CF_NO; - else if(strcmp(string,SCHED_KW_DEFAULT_ITEM) == 0) - return DEFAULT_CROSSFLOW_ABILITY; - else - util_abort("%s: Crossflow ability mode %s not recognized - aborting.\n",__func__,string); - return 0; -} - - - -static hdstat_head_type get_hdstat_head_from_string(const char * string) -{ - if(strcmp(string ,HD_SEG_STRING) == 0) - return HD_SEG; - else if(strcmp(string,HD_AVG_STRING) == 0) - return HD_AVG; - else if(strcmp(string,SCHED_KW_DEFAULT_ITEM) == 0) - return DEFAULT_HDSTAT_TYPE; - else - util_abort("%s: Hydrostatic head model %s not recognized - aborting.\n",__func__,string); - return 0; -} - - - -static void welspec_sched_fprintf(const welspec_type * ws, FILE * stream) -{ - fprintf(stream, " "); - sched_util_fprintf_qst(ws->def[0] , ws->name , 8, stream); - sched_util_fprintf_qst(ws->def[1] , ws->group , 8, stream); - sched_util_fprintf_int(ws->def[2] , ws->hh_i , 4, stream); - sched_util_fprintf_int(ws->def[3] , ws->hh_j , 4, stream); - sched_util_fprintf_dbl(ws->def[4] , ws->md , 8, 3, stream); - sched_util_fprintf_qst(ws->def[5] , get_phase_string(ws->phase) , 5, stream); - sched_util_fprintf_dbl(ws->def[6] , ws->drain_rad , 8, 3, stream); - sched_util_fprintf_qst(ws->def[7] , get_inflow_eq_string(ws->inflow_eq) , 3, stream); - sched_util_fprintf_qst(ws->def[8] , get_auto_shut_string(ws->auto_shut) , 4, stream); - sched_util_fprintf_qst(ws->def[9] , get_crossflow_string(ws->crossflow) , 3, stream); - sched_util_fprintf_int(ws->def[10] , ws->pvt_region , 4, stream); - sched_util_fprintf_qst(ws->def[11] , get_hdstat_head_string(ws->hdstat_head) , 3, stream); - sched_util_fprintf_int(ws->def[12] , ws->fip_region , 4, stream); - /* - sched_util_fprintf_qst(ws->def[13] , ws->fs_kw1 , 8, stream); - sched_util_fprintf_qst(ws->def[14] , ws->fs_kw2 , 8, stream); - sched_util_fprintf_qst(ws->def[15] , ws->ecl300_kw , 8, stream); - */ - fprintf(stream,"/\n"); -}; - - - -static welspec_type * welspec_alloc_empty() -{ - welspec_type *ws = util_malloc(sizeof *ws); - - ws->name = NULL; - ws->group = NULL; - ws->fs_kw1 = NULL; - ws->fs_kw2 = NULL; - ws->ecl300_kw = NULL; - - return ws; -} - - - - - - -static void welspec_free(welspec_type * ws) -{ - free(ws->group ); - util_safe_free(ws->fs_kw1 ); - util_safe_free(ws->fs_kw2 ); - util_safe_free(ws->ecl300_kw); - free(ws->name); - free(ws); -}; - - - -static void welspec_free__(void * __ws) -{ - welspec_type * ws = (welspec_type *) __ws; - welspec_free(ws); -}; - - - - -static welspec_type * welspec_alloc_from_tokens(const stringlist_type * line_tokens ) -{ - welspec_type * ws = welspec_alloc_empty(); - sched_util_init_default( line_tokens , ws->def ); - ws->name = util_alloc_string_copy(stringlist_iget( line_tokens , 0)); - - if(ws->def[1]) - ws->group = util_alloc_string_copy("FIELD"); - else - ws->group = util_alloc_string_copy(stringlist_iget( line_tokens , 1 )); - - ws->hh_i = sched_util_atoi(stringlist_iget( line_tokens , 2)); - ws->hh_j = sched_util_atoi(stringlist_iget( line_tokens , 3)); - ws->md = sched_util_atof(stringlist_iget( line_tokens , 4)); - ws->phase = get_phase_from_string(stringlist_iget( line_tokens , 5)); - ws->drain_rad = sched_util_atof(stringlist_iget( line_tokens , 6)); - ws->inflow_eq = get_inflow_eq_from_string(stringlist_iget( line_tokens , 7)); - ws->auto_shut = get_auto_shut_from_string(stringlist_iget( line_tokens , 8)); - ws->crossflow = get_crossflow_from_string(stringlist_iget( line_tokens , 9)); - ws->pvt_region = sched_util_atoi(stringlist_iget( line_tokens , 10)); - ws->hdstat_head = get_hdstat_head_from_string(stringlist_iget( line_tokens , 11)); - ws->fip_region = sched_util_atoi(stringlist_iget( line_tokens , 12)); - - ws->fs_kw1 = util_alloc_string_copy(stringlist_iget( line_tokens , 13)); /* Reserved for use with FRONTSIM */ - ws->fs_kw2 = util_alloc_string_copy(stringlist_iget( line_tokens , 14)); /* Reserved for use with FRONTSIM */ - ws->ecl300_kw = util_alloc_string_copy(stringlist_iget( line_tokens , 15)); /* Could not find this in the dcoumentation ...??? */ - - return ws; -}; - - - - - - -static sched_kw_welspecs_type * sched_kw_welspecs_alloc_empty() -{ - sched_kw_welspecs_type * kw = util_malloc(sizeof * kw ); - kw->welspec_list = vector_alloc_new(); - return kw; -}; - - -static void sched_kw_welspecs_add_well( sched_kw_welspecs_type * kw , const welspec_type * ws) { - vector_append_owned_ref( kw->welspec_list , ws , welspec_free__ ); -} - - -/*****************************************************************************/ - - -sched_kw_welspecs_type * sched_kw_welspecs_alloc(const stringlist_type * tokens , int * token_index ) { - sched_kw_welspecs_type * kw = sched_kw_welspecs_alloc_empty(); - int eokw = false; - do { - stringlist_type * line_tokens = sched_util_alloc_line_tokens( tokens , false , WELSPECS_NUM_KW , token_index ); - if (line_tokens == NULL) - eokw = true; - else { - welspec_type * well = welspec_alloc_from_tokens( line_tokens ); - sched_kw_welspecs_add_well( kw , well ); - stringlist_free( line_tokens ); - } - - } while (!eokw); - return kw; -} - - - - -void sched_kw_welspecs_free(sched_kw_welspecs_type * kw) -{ - vector_free(kw->welspec_list); - free(kw); -}; - - - -void sched_kw_welspecs_fprintf(const sched_kw_welspecs_type * kw, FILE * stream) -{ - fprintf(stream, "WELSPECS\n"); - int i; - for (i=0; i < vector_get_size( kw->welspec_list ); i++) { - const welspec_type * ws = vector_iget_const( kw->welspec_list , i ); - welspec_sched_fprintf(ws, stream); - } - fprintf(stream,"/\n\n"); -}; - - - - -void sched_kw_welspecs_init_child_parent_list( const sched_kw_welspecs_type * kw , stringlist_type * child , stringlist_type * parent) { - stringlist_clear( child ); - stringlist_clear( parent ); - { - for (int i=0; i < vector_get_size( kw->welspec_list ); i++) { - const welspec_type * well = vector_iget_const(kw->welspec_list , i); - stringlist_append_ref( child , well->name ); - - if (!well->def[1]) - stringlist_append_ref( parent , well->group ); - else - stringlist_append_ref( parent , FIELD_GROUP ); - - } - } -} - - - - -void sched_kw_welspecs_alloc_child_parent_list(const sched_kw_welspecs_type * kw, char *** __children, char *** __parents, int * num_pairs) -{ - int num_wells = vector_get_size(kw->welspec_list); - char ** children = util_malloc(num_wells * sizeof * children); - char ** parents = util_malloc(num_wells * sizeof * parents); - - for(int well_nr = 0; well_nr < num_wells; well_nr++) - { - const welspec_type * well = vector_iget_const(kw->welspec_list , well_nr); - children[well_nr] = util_alloc_string_copy(well->name); - if(!well->def[1]) - parents[well_nr] = util_alloc_string_copy(well->group); - else - parents[well_nr] = util_alloc_string_copy("FIELD"); - } - - *num_pairs = num_wells; - *__children = children; - *__parents = parents; -} - - -sched_kw_welspecs_type * sched_kw_welspecs_copyc(const sched_kw_welspecs_type * kw) { - util_abort("%s: not implemented ... \n",__func__); - return NULL; -} - - - -/***********************************************************************/ - -KW_IMPL(welspecs) diff --git a/ThirdParty/Ert/libsched/src/sched_time.c b/ThirdParty/Ert/libsched/src/sched_time.c deleted file mode 100644 index 612baae633..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_time.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_time.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include - -#include -#include - -/*****************************************************************/ - -/** - The sched_time_type is an attempt at unifiing the DATES and TSTEP - keywords; they are both related to stepping forward in time. For a - reasonable control over the timestepping we need (at least) two - pieces of information: - - 1. What is true time at the start/end of the current step. - 2. How long is the step. - - The DATES keywords give the true time at the end of the step, - whereas the TSTEP keyword gives the length of the step. -*/ - -#define SCHED_TIME_TYPE_ID 66195407 - -struct sched_time_struct { - UTIL_TYPE_ID_DECLARATION; - time_t date; - double tstep_length; /* Length of TSTEP - in days. */ - sched_time_enum time_type; -}; - - - - -sched_time_type * sched_time_alloc( time_t date , double tstep_length , sched_time_enum time_type ) { - sched_time_type * time_node = util_malloc( sizeof * time_node ); - UTIL_TYPE_ID_INIT( time_node , SCHED_TIME_TYPE_ID ); - time_node->time_type = time_type; - time_node->tstep_length = tstep_length; - time_node->date = date; - - return time_node; -} - -static UTIL_SAFE_CAST_FUNCTION( sched_time , SCHED_TIME_TYPE_ID ) - -void sched_time_free( sched_time_type * time_node ) { - free( time_node ); -} - -void sched_time_free__( void * arg ) { - sched_time_free( sched_time_safe_cast( arg )); -} - - -time_t sched_time_get_date( const sched_time_type * time_node ) { - return time_node->date; -} - - -/** - This function will return the true time at the end of this step, - for a time_node which represents a DATES instance the function will - just return the actual date, for a TSTEP it will step forward - starting at the input @current_time. -*/ - -time_t sched_time_get_target( const sched_time_type * time_node , time_t current_time) { - time_t target; - - switch( time_node->time_type ) { - case( DATES_TIME ): - target = time_node->date; - break; - case( TSTEP_TIME ): - target = current_time; - util_inplace_forward_days_utc( &target , time_node->tstep_length ); - break; - default: - util_abort("%s: invalid time_type value:%d \n",__func__ , time_node->time_type ); - } - - return target; -} - - - -time_t sched_time_get_type( const sched_time_type * time_node ) { - return time_node->time_type; -} - diff --git a/ThirdParty/Ert/libsched/src/sched_types.c b/ThirdParty/Ert/libsched/src/sched_types.c deleted file mode 100644 index 4d98aff14b..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_types.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_types.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include - -#include - -#define SCHED_KW_DEFAULT_ITEM "*" - - -#define TYPE_WATER_STRING "WATER" -#define TYPE_GAS_STRING "GAS" -#define TYPE_OIL_STRING "OIL" - -const char * sched_phase_type_string(sched_phase_enum type) { - switch (type) { - case(WATER): - return TYPE_WATER_STRING; - case(GAS): - return TYPE_GAS_STRING; - case(OIL): - return TYPE_OIL_STRING; - default: - return SCHED_KW_DEFAULT_ITEM; - } -} - -sched_phase_enum sched_phase_type_from_string(const char * type_string) { - if (strcmp(type_string , TYPE_WATER_STRING) == 0) - return WATER; - else if (strcmp(type_string , TYPE_GAS_STRING) == 0) - return GAS; - else if (strcmp(type_string , TYPE_OIL_STRING) == 0) - return OIL; - else { - util_abort("%s: Could not recognize:%s as injector phase. Valid values are: [%s, %s, %s] \n",__func__ , type_string , TYPE_WATER_STRING , TYPE_GAS_STRING , TYPE_OIL_STRING); - return 0; - } -} - - -/*****************************************************************/ - - -#define WCONHIST_STRING "WCONHIST" -#define DATES_STRING "DATES" -#define COMPDAT_STRING "COMPDAT" -#define TSTEP_STRING "TSTEP" -#define TIME_STRING "TIME" -#define WELSPECS_STRING "WELSPECS" -#define GRUPTREE_STRING "GRUPTREE" -#define INCLUDE_STRING "INCLUDE" -#define WCONINJ_STRING "WCONINJ" -#define WCONINJE_STRING "WCONINJE" -#define WCONINJH_STRING "WCONINJH" -#define WCONPROD_STRING "WCONPROD" - -#define UNTYPED_STRING "UNTYPED" - - - - - -/** - This function does a direct translation of a string name to - implementation type - i.e. an enum instance. Observe that - (currently) no case-normalization is performed. -*/ - -sched_kw_type_enum sched_kw_type_from_string(const char * kw_name) -{ - sched_kw_type_enum kw_type = UNTYPED; - - if ( strcmp(kw_name, GRUPTREE_STRING ) == 0) kw_type = GRUPTREE ; - else if( strcmp(kw_name, TSTEP_STRING ) == 0) kw_type = TSTEP ; - else if( strcmp(kw_name, INCLUDE_STRING ) == 0) kw_type = INCLUDE ; - else if( strcmp(kw_name, TIME_STRING ) == 0) kw_type = TIME ; - else if( strcmp(kw_name, DATES_STRING ) == 0) kw_type = DATES ; - else if( strcmp(kw_name, WCONHIST_STRING ) == 0) kw_type = WCONHIST ; - else if( strcmp(kw_name, WELSPECS_STRING ) == 0) kw_type = WELSPECS ; - else if( strcmp(kw_name, WCONINJ_STRING ) == 0) kw_type = WCONINJ ; - else if( strcmp(kw_name, WCONINJE_STRING ) == 0) kw_type = WCONINJE ; - else if( strcmp(kw_name, WCONINJH_STRING ) == 0) kw_type = WCONINJH ; - else if( strcmp(kw_name, WCONPROD_STRING ) == 0) kw_type = WCONPROD ; - else if( strcmp(kw_name, COMPDAT_STRING ) == 0) kw_type = COMPDAT ; - - return kw_type; -} - - -const char * sched_kw_type_name(sched_kw_type_enum kw_type) { - if ( kw_type == GRUPTREE ) return GRUPTREE_STRING ; - else if ( kw_type == TSTEP ) return TSTEP_STRING ; - else if ( kw_type == INCLUDE ) return INCLUDE_STRING ; - else if ( kw_type == TIME ) return TIME_STRING ; - else if ( kw_type == DATES ) return DATES_STRING ; - else if ( kw_type == WCONHIST ) return WCONHIST_STRING ; - else if ( kw_type == WELSPECS ) return WELSPECS_STRING ; - else if ( kw_type == WCONINJ ) return WCONINJ_STRING ; - else if ( kw_type == WCONINJE ) return WCONINJE_STRING ; - else if ( kw_type == WCONINJH ) return WCONINJH_STRING ; - else if ( kw_type == WCONPROD ) return WCONPROD_STRING ; - else if ( kw_type == COMPDAT ) return COMPDAT_STRING ; - - return UNTYPED_STRING; /* Unknown type */ -} - - -/*****************************************************************/ - -#define STATUS_OPEN_STRING "OPEN" -#define STATUS_STOP_STRING "STOP" -#define STATUS_SHUT_STRING "SHUT" -#define STATUS_AUTO_STRING "AUTO" - - -const char * sched_types_get_status_string(well_status_enum status) -{ - switch(status) { - case(OPEN): - return STATUS_OPEN_STRING; - case(STOP): - return STATUS_STOP_STRING; - case(SHUT): - return STATUS_SHUT_STRING; - case(AUTO): - return STATUS_AUTO_STRING; - case(DEFAULT): - return SCHED_KW_DEFAULT_ITEM; - default: - util_abort("%s: invalid status:%d \n",__func__ , status ); - return 0; - } -} - - - -well_status_enum sched_types_get_status_from_string(const char * st_string) -{ - if (strcmp( st_string , SCHED_KW_DEFAULT_ITEM ) == 0) - return DEFAULT; - /* - Must be checked by calling scope whether DEFAULT is a valid - return - and then subsequently apply the correct value. - */ - else if( strcmp(st_string, STATUS_OPEN_STRING) == 0) - return OPEN; - else if( strcmp(st_string, STATUS_STOP_STRING) == 0) - return STOP; - else if( strcmp(st_string, STATUS_SHUT_STRING) == 0) - return SHUT; - else if( strcmp(st_string, STATUS_AUTO_STRING) == 0) - return AUTO; - else - { - util_abort("%s: Could not recognize %s as a well status.\n", __func__, st_string); - return 0; - } -} - - -/*****************************************************************/ - - -const char * sched_types_get_cm_string( well_cm_enum cm ) { - switch(cm) { - case( RESV ): - return CM_RESV_STRING; - break; - case( RATE ): - return CM_RATE_STRING; - break; - case( BHP ): - return CM_BHP_STRING; - break; - case( THP ): - return CM_THP_STRING; - break; - case( GRUP ): - return CM_GRUP_STRING; - break; - case( ORAT ): - return CM_ORAT_STRING; - break; - case( WRAT ): - return CM_WRAT_STRING; - break; - case( GRAT ): - return CM_GRAT_STRING; - break; - case( LRAT ): - return CM_LRAT_STRING; - break; - default: - util_abort("%s: invalid value: %s \n", cm ); - return 0; - } -} - - - - -/** - Must use the strncmp(x,x,4) function for comparison, because - suddenly files with control mode 'GRUP ' appear; and ECLIPSE - appearantly eats that nicely. -*/ - - -well_cm_enum sched_types_get_cm_from_string(const char * cm_string , bool wconhist) -{ - if (wconhist) { - if( strcmp(cm_string, CM_ORAT_STRING) == 0) - return ORAT; - else if(strcmp(cm_string, CM_WRAT_STRING) == 0) - return WRAT; - else if(strcmp(cm_string, CM_GRAT_STRING) == 0) - return GRAT; - else if(strcmp(cm_string, CM_LRAT_STRING) == 0) - return LRAT; - else if(strcmp(cm_string, CM_RESV_STRING) == 0) - return RESV; - else { - util_abort("%s: Could not recognize %s as a control mode.\n", __func__, cm_string); - return 0; - } - } else { - if( strncmp(cm_string, CM_RATE_STRING , 4) == 0) - return RATE; - else if(strncmp(cm_string, CM_RESV_STRING , 4) == 0) - return RESV; - else if(strncmp(cm_string, CM_BHP_STRING , 4) == 0) - return BHP; - else if(strncmp(cm_string, CM_THP_STRING, 4) == 0) - return THP; - else if(strncmp(cm_string, CM_GRUP_STRING , 4) == 0) - return GRUP; - else { - util_abort("%s: Could not recognize \'%s\' as a control mode. Valid values are: [%s, %s, %s, %s, %s] \n", __func__, cm_string, - CM_RATE_STRING , CM_RESV_STRING , CM_BHP_STRING, CM_THP_STRING, CM_GRUP_STRING); - return 0; - } - } -} diff --git a/ThirdParty/Ert/libsched/src/sched_util.c b/ThirdParty/Ert/libsched/src/sched_util.c deleted file mode 100644 index 54667586aa..0000000000 --- a/ThirdParty/Ert/libsched/src/sched_util.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'sched_util.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include -#include - -#include -#include - -#include - -/** - This file implements small utility functions used by the rest of - the libsched library. -*/ - - -static const int strip_comment = 1; -static const int strip_space = 2; - - -static char * strip_line_alloc(const char * line) { - const char comment_char = '-'; - const char *space = " \t"; - const int strip_mode = strip_comment + strip_space; - char * new_line = NULL; - int offset, length,pos; - bool cont , quote_on , dash_on; /* The quote_on variable protects againts premature termination based on '/' in path specifications. */ - - /* Strip intial white-space */ - if (strip_mode & strip_space) - offset = strspn(line , space); - else - offset = 0; - - - dash_on = false; - quote_on = false; - cont = true; - length = 0; - if (line[offset] != '\0') { - pos = offset; - do { - if (line[pos] == '\'' || line[pos] == '"') - quote_on = !quote_on; - - if (strip_mode & strip_comment) { - if (!quote_on) { - if (line[pos] == comment_char) { - if (dash_on) { - cont = false; - length = pos - offset - 1; - } else - dash_on = true; - } else - dash_on = false; - } - } - - if (cont) { - if (pos == (strlen(line) - 1)) { - length = pos - offset + 1; - cont = false; - } - } - - if (cont) - pos++; - } while (cont); - - /* - Remove trailing space: - */ - - if (strip_mode & strip_space) { - if (offset + length > 0) { - while (line[offset + length - 1] == ' ') - length--; - } - } - - if (length > 0) - new_line = util_realloc_substring_copy(NULL , &line[offset] , length); - else - new_line = NULL; - - } - - return new_line; -} - - -/*****************************************************************/ - - - -char * sched_util_alloc_line(FILE *stream , bool *at_eof) { - char *tmp_line = util_fscanf_alloc_line(stream , at_eof); - char * line = strip_line_alloc( tmp_line ); - - free(tmp_line); - return line; -} - - - - - - -/** - * We parse up to the terminating '/' - but it is NOT included in the returned string - - The num_tokens variable is only used to fill up with defaults at the end. -*/ -stringlist_type * sched_util_alloc_line_tokens( const stringlist_type * tokens , bool untyped , int num_tokens , int * __token_index ) { - /** First part - identify the right start/end of the token list */ - stringlist_type * line_tokens = NULL; - int token_index = *__token_index; - int token_length = stringlist_get_size( tokens ); - int line_start; - int line_end; - bool at_eokw = false; - { - line_start = token_index; - const char * current_token; - { - bool at_eol = false; - do { - current_token = stringlist_iget( tokens , token_index ); - if (strcmp( current_token , "/" ) == 0) - at_eol = true; - - token_index++; - - // The schedule file is not correctly terminated with a "/". - if (token_index == token_length) - at_eol = true; - - } while (!at_eol); - } - line_end = token_index; - if ((line_end - line_start) == 1) - /* - This line *only* contained a terminating '/'. This marks the - end of the kewyord. - */ - at_eokw = true; - } - - - /* Second part - filling in with defaults+++ */ - if (!at_eokw) { - line_tokens = stringlist_alloc_new( ); - if (untyped) { /* In case of untyped we basically do nothing with the content - even keeping the trailing '/'. */ - int it; - for (it = line_start; it < line_end; it++) { - const char * token = stringlist_iget( tokens , it ); - stringlist_append_copy(line_tokens , token ); - } - } else { - int it; - for (it = line_start; it < (line_end - 1); it++) { - const char * token = stringlist_iget( tokens , it ); - char * dequoted_token = util_alloc_dequoted_copy( token ); - - if (util_string_equal( dequoted_token , SCHED_KW_DEFAULT_ITEM )) /* The item is just '*' */ - stringlist_append_copy(line_tokens , SCHED_KW_DEFAULT_ITEM ); - else { - char repeated_value[32]; - long int items; - if (sscanf(dequoted_token , "%ld*%s" , &items , repeated_value) == 2) { /* It is a '5*8.60' item - i.e. the value 8.60 repeated five times. */ - int counter = 0; - do { - stringlist_append_copy(line_tokens , repeated_value); - counter++; - } while ( counter < items ); - } else { - char * star_ptr = (char *) dequoted_token; - items = strtol(dequoted_token , &star_ptr , 10); /* The item is a repeated default: '5*' */ - if (star_ptr != token && util_string_equal( star_ptr , SCHED_KW_DEFAULT_ITEM )) { - for (int i=0; i < items; i++) - stringlist_append_copy( line_tokens , SCHED_KW_DEFAULT_ITEM ); - } else /* The item is a non-default value. */ - stringlist_append_copy(line_tokens , dequoted_token ); - } - } - free( dequoted_token ); - } - } - } - - - /** Skip trailing garbage */ - sched_util_skip_trailing_tokens( tokens , &token_index ); - sched_util_skip_newline( tokens , &token_index ); - - /* Append default items at the end until we have num_tokens length. */ - if (line_tokens != NULL) { - while (stringlist_get_size( line_tokens ) < num_tokens) - stringlist_append_copy( line_tokens , SCHED_KW_DEFAULT_ITEM ); - } - - *__token_index = token_index; - return line_tokens; -} - - - - -void sched_util_fprintf_default(int width , FILE * stream) { - fprintf(stream , "1*"); - for (int i=0; i < (width - 2); i++) - fputc(' ' , stream); -} - - -/** - All the sched_util_fprintf_xxx() functions start by putting out one - ' ', to ensure against overlapping fields. -*/ - - -void sched_util_fprintf_dbl(bool def, double value , int width , int dec , FILE *stream) { - fputc(' ' , stream); - if (def) - sched_util_fprintf_default( width , stream); - else - util_fprintf_double(value , width , dec , 'f' , stream); -} - - - -void sched_util_fprintf_int(bool def, int value , int width , FILE *stream) { - fputc(' ' , stream); - if (def) { - sched_util_fprintf_default( width , stream); - } else - util_fprintf_int(value , width , stream); -} - - -/* - The formatting is ridicolusly inflexible - don't touch this shit. -*/ - -void sched_util_fprintf_qst(bool def, const char *s , int width , FILE *stream) { - fputc(' ' , stream); - if (def) { - sched_util_fprintf_default( width , stream ); - } else { - for (int i=0; i < (width - strlen(s)); i++) - fputc(' ' , stream); - - fprintf(stream , "\'%s\'" , s); - } -} - - - -/** - The atof / atoi functions accept either 'NULL' or '*' as default - values, in that case numeric 0 is returned. -*/ - -double sched_util_atof(const char *token) { - if (token != NULL) { - double value = 0; - if (!util_string_equal( token , SCHED_KW_DEFAULT_ITEM)) { - if (!util_sscanf_double(token , &value)) - util_abort("%s: failed to parse:\"%s\" as floating point number. \n",__func__ , token); - } - return value; - } else - return 0.0; -} - - - -int sched_util_atoi(const char *token) { - if (token != NULL) { - int value = 0; - if (!util_string_equal( token , SCHED_KW_DEFAULT_ITEM)) { - if (!util_sscanf_int(token , &value)) - util_abort("%s: failed to parse:\"%s\" as integer \n",__func__ , token); - } - return value; - } else - return 0; -} - - - -/* Simple utility function used for debugging. */ -void sched_util_fprintf_tokenlist(int num_token , const char ** token_list , const bool * def) { - int i; - for (i = 0; i < num_token; i++) { - if (def[i]) - fprintf(stdout , " \'*\' " ); - else - fprintf(stdout , " \'%s\' " , token_list[i]); - } - fprintf(stdout , "\n"); -} - - - -/** - This should repeatedly skip tokens until the token_index points to - a newline. Should return with token_index pointing at the first newline character. -*/ - -void sched_util_skip_trailing_tokens( const stringlist_type * tokens , int * __token_index ) { - int token_index = *__token_index; - int len = stringlist_get_size( tokens ); - while ( (token_index < len) && (!stringlist_iequal( tokens , token_index , "\n"))) { - token_index++; - } - *__token_index = token_index; -} - - -void sched_util_skip_newline( const stringlist_type * tokens , int * __token_index ) { - int token_index = *__token_index; - int len = stringlist_get_size( tokens ); - while ( (token_index < len) && (stringlist_iequal( tokens , token_index , "\n"))) { - token_index++; - } - *__token_index = token_index; -} - - - - - -void sched_util_init_default(const stringlist_type * line_tokens , bool * def) { - int i; - for (i = 0; i < stringlist_get_size( line_tokens ); i++) { - if (util_string_equal( stringlist_iget( line_tokens , i ) , SCHED_KW_DEFAULT_ITEM)) - def[i] = true; - else - def[i] = false; - } -} diff --git a/ThirdParty/Ert/libsched/src/tests/sched_test_01.SCH b/ThirdParty/Ert/libsched/src/tests/sched_test_01.SCH deleted file mode 100644 index dd72f07a20..0000000000 --- a/ThirdParty/Ert/libsched/src/tests/sched_test_01.SCH +++ /dev/null @@ -1,2371 +0,0 @@ -SKIPREST - - -GRUPTREE - 'OREI' 'FIELD' / - 'TARB' 'FIELD' / - 'RFTWELLS' 'FIELD' / - 'NESS' 'FIELD' / - 'ORE' 'FIELD' / -/ - -WELSPECS - 'C-21' 'NESS' 21 27 1* 'OIL' 1* 1* 1* 'YES' 1* 1* 1* / -/ - -COMPDAT - 'C-21' 21 27 7 7 'OPEN' 1* 0.010 0.216 0.818 2* 'Y' 8.192 / - 'C-21' 21 27 8 8 'OPEN' 1* 0.037 0.216 3.030 2* 'Y' 8.931 / - 'C-21' 21 27 9 9 'OPEN' 1* 34.630 0.216 2817.208 2* 'Y' 8.436 / - 'C-21' 21 28 9 9 'OPEN' 1* 14.497 0.216 1168.521 2* 'Y' 8.105 / - 'C-21' 21 28 10 10 'OPEN' 1* 42.936 0.216 3544.366 2* 'Y' 8.995 / - 'C-21' 21 28 11 11 'OPEN' 1* 42.429 0.216 3500.982 2* 'Y' 8.977 / - 'C-21' 21 28 12 12 'OPEN' 1* 42.342 0.216 3495.926 2* 'Y' 9.002 / - 'C-21' 21 28 13 13 'OPEN' 1* 29.462 0.216 2431.726 2* 'Y' 8.990 / - 'C-21' 21 28 14 14 'OPEN' 1* 5.991 0.216 486.714 2* 'Y' 8.384 / - 'C-21' 21 28 15 15 'OPEN' 1* 46.367 0.216 3788.829 2* 'Y' 8.601 / - 'C-21' 21 28 16 16 'OPEN' 1* 32.257 0.216 2655.136 2* 'Y' 8.881 / -/ - -WCONHIST - 'C-21' 'OPEN' 'RESV' 1224.545 4.455 160283.364 1* 1* 1* 1* 1* / -/ - -DATES - 26 'OCT' 1993 / -/ - -WCONHIST - 'C-21' 'OPEN' 'RESV' 1387.167 4.833 181534.167 1* 1* 1* 1* 1* / -/ - -DATES - 01 'NOV' 1993 / -/ - -WCONHIST - 'C-21' 'OPEN' 'RESV' 1689.071 7.500 219186.718 1* 1* 1* 1* 1* / -/ - -DATES - 15 'NOV' 1993 / -/ - -WCONHIST - 'C-21' 'OPEN' 'RESV' 1873.813 7.750 242244.937 1* 1* 1* 1* 1* / -/ - -DATES - 01 'DEC' 1993 / -/ - -WCONHIST - 'C-21' 'OPEN' 'RESV' 1884.467 6.933 262115.000 1* 1* 1* 1* 1* / -/ - -DATES - 16 'DEC' 1993 / -/ - -WELSPECS - 'C-18AT2' 'NESS' 37 26 1* 'OIL' 1* 1* 1* 'YES' 1* 1* 1* / -/ - -COMPDAT - 'C-18AT2' 36 26 7 7 'OPEN' 1* 68.922 0.216 5481.595 2* 'X' 7.653 / - 'C-18AT2' 36 26 8 8 'OPEN' 1* 89.467 0.216 7026.742 2* 'X' 7.256 / - 'C-18AT2' 36 26 9 9 'OPEN' 1* 25.025 0.216 1958.073 2* 'X' 7.142 / - 'C-18AT2' 36 27 9 9 'OPEN' 1* 67.656 0.216 5325.417 2* 'X' 7.324 / - 'C-18AT2' 36 27 10 10 'OPEN' 1* 57.636 0.216 4508.869 2* 'X' 7.137 / - 'C-18AT2' 36 27 12 12 'OPEN' 1* 48.558 0.216 3834.346 2* 'Y' 7.423 / - 'C-18AT2' 36 27 13 13 'OPEN' 1* 76.818 0.216 6094.799 2* 'X' 7.574 / - 'C-18AT2' 36 27 14 14 'OPEN' 1* 78.248 0.216 6196.442 2* 'Y' 7.513 / - 'C-18AT2' 36 27 15 15 'OPEN' 1* 18.304 0.216 1476.768 2* 'X' 8.138 / - 'C-18AT2' 35 27 15 15 'OPEN' 1* 52.068 0.216 4153.243 2* 'Y' 7.749 / - 'C-18AT2' 35 27 16 16 'OPEN' 1* 5.124 0.216 404.276 2* 'Y' 7.395 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 1877.125 72.750 256186.375 1* 1* 1* 1* 1* / - 'C-21' 'OPEN' 'RESV' 1591.000 2.875 217475.000 1* 1* 1* 1* 1* / -/ - -DATES - 24 'DEC' 1993 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 1787.000 3.500 223750.750 1* 1* 1* 1* 1* / - 'C-21' 'OPEN' 'RESV' 2038.625 3.875 274779.250 1* 1* 1* 1* 1* / -/ - -DATES - 01 'JAN' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 1581.258 3.290 199459.420 1* 1* 1* 1* 1* / - 'C-21' 'OPEN' 'RESV' 1124.032 2.226 153597.742 1* 1* 1* 1* 1* / -/ - -DATES - 01 'FEB' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 2186.607 2.643 273473.857 1* 1* 1* 1* 1* / - 'C-21' 'OPEN' 'ORAT' 676.000 0.000 76898.000 1* 1* 1* 1* 1* / -/ - -DATES - 01 'MAR' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 2348.900 1.400 281540.300 1* 1* 1* 1* 1* / -/ - -DATES - 11 'MAR' 1994 / -/ - -WELSPECS - 'C-22' 'NESS' 25 10 1* 'OIL' 1* 1* 1* 'YES' 1* 1* 1* / -/ - -COMPDAT - 'C-22' 25 11 4 4 'OPEN' 1* 0.006 0.216 0.542 2* 'Y' 10.016 / - 'C-22' 25 11 5 5 'OPEN' 1* 47.218 0.216 3948.662 2* 'Y' 9.529 / - 'C-22' 25 11 6 6 'OPEN' 1* 49.888 0.216 4103.013 2* 'Y' 8.849 / - 'C-22' 25 11 7 7 'OPEN' 1* 44.747 0.216 3779.700 2* 'Y' 9.968 / - 'C-22' 25 11 8 8 'OPEN' 1* 46.326 0.216 3882.668 2* 'Y' 9.625 / - 'C-22' 25 11 9 9 'OPEN' 1* 14.678 0.216 1238.033 2* 'Y' 9.903 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 1736.429 1.143 214222.810 1* 1* 1* 1* 1* / -/ - -WCONINJH - 'C-22' 'GAS' 'OPEN' 479677.143 4* / -/ - -WEFAC - 'C-22' 0.050 1* / -/ - -DATES - 01 'APR' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 1754.233 1.033 222623.866 1* 1* 1* 1* 1* / -/ - -WCONINJH - 'C-22' 'GAS' 'OPEN' 558840.566 4* / -/ - -DATES - 01 'MAY' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 1620.290 1.032 203119.097 1* 1* 1* 1* 1* / -/ - -WCONINJH - 'C-22' 'GAS' 'OPEN' 651149.646 4* / -/ - -DATES - 01 'JUN' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 882.867 0.667 115927.967 1* 1* 1* 1* 1* / -/ - -WCONINJH - 'C-22' 'GAS' 'OPEN' 243341.733 4* / -/ - -DATES - 01 'JUL' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 1886.778 1.111 248306.333 1* 1* 1* 1* 1* / -/ - -WCONINJH - 'C-21' 'OIL' 'OPEN' 792.000 4* / - 'C-22' 'GAS' 'OPEN' 819116.111 4* / -/ - -DATES - 10 'JUL' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 1649.136 1.182 223808.136 1* 1* 1* 1* 1* / -/ - -WCONINJH - 'C-22' 'GAS' 'OPEN' 646226.818 4* / -/ - -DATES - 01 'AUG' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 1652.355 1.323 222730.581 1* 1* 1* 1* 1* / -/ - -WCONINJH - 'C-22' 'GAS' 'OPEN' 605224.871 4* / -/ - -DATES - 01 'SEP' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 1426.167 2.633 193760.133 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 156246.400 5* / -/ - -DATES - 01 'OCT' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 766.161 1.968 100942.774 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 18869.387 5* / -/ - -DATES - 01 'NOV' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 795.533 2.300 104841.267 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 90.467 5* / -/ - -DATES - 01 'DEC' 1994 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 195342.387 5* / -/ - -DATES - 01 'JAN' 1995 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 227.484 0.548 29827.323 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-21' 'OIL' 'OPEN' 'RATE' 193.000 4* 140.000 / - 'C-22' 'GAS' 'OPEN' 'RATE' 3.000 5* / -/ - -DATES - 01 'FEB' 1995 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 68.821 0.571 9703.643 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 99263.250 5* / -/ - -DATES - 01 'MAR' 1995 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 0.000 5* / -/ - -DATES - 05 'MAR' 1995 / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 154601.223 5* / -/ - -DATES - 01 'APR' 1995 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 80.700 0.067 10955.633 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 334557.733 5* / -/ - -DATES - 01 'MAY' 1995 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 11822.000 5* / -/ - -DATES - 03 'MAY' 1995 / -/ - -WELSPECS - 'C-19' 'NESS' 39 14 1* 'OIL' 1* 1* 1* 'YES' 1* 1* 1* / -/ - -COMPDAT - 'C-19' 35 23 13 13 'OPEN' 1* 229.211 0.216 17591.568 2* 'Y' 6.592 / - 'C-19' 35 23 14 14 'OPEN' 1* 42.518 0.216 3286.223 2* 'Y' 6.786 / - 'C-19' 35 24 15 15 'OPEN' 1* 49.616 0.216 3818.562 2* 'Y' 6.668 / - 'C-19' 35 24 16 16 'OPEN' 1* 148.076 0.216 11340.899 2* 'Y' 6.536 / - 'C-19' 35 25 16 16 'OPEN' 1* 0.164 0.216 12.543 2* 'Y' 6.514 / - 'C-19' 34 25 16 16 'OPEN' 1* 128.420 0.216 9830.735 2* 'Y' 6.523 / - 'C-19' 34 25 15 15 'OPEN' 1* 137.101 0.216 10497.277 2* 'Y' 6.528 / - 'C-19' 34 26 15 15 'OPEN' 1* 71.365 0.216 5444.541 2* 'Y' 6.433 / - 'C-19' 34 26 14 14 'OPEN' 1* 423.367 0.216 32285.266 2* 'Y' 6.421 / - 'C-19' 33 26 14 14 'OPEN' 1* 68.448 0.216 5231.526 2* 'Y' 6.481 / - 'C-19' 33 27 14 14 'OPEN' 1* 36.744 0.216 2805.661 2* 'Y' 6.455 / - 'C-19' 33 27 13 13 'OPEN' 1* 354.667 0.216 27036.137 2* 'Y' 6.411 / - 'C-19' 33 27 12 12 'OPEN' 1* 100.458 0.216 7650.032 2* 'Y' 6.385 / - 'C-19' 33 28 12 12 'OPEN' 1* 207.460 0.216 15797.470 2* 'Y' 6.383 / - 'C-19' 32 28 12 12 'OPEN' 1* 103.805 0.216 7940.809 2* 'Y' 6.504 / - 'C-19' 32 28 11 11 'OPEN' 1* 247.786 0.216 18955.656 2* 'Y' 6.505 / - 'C-19' 32 28 10 10 'OPEN' 1* 15.303 0.216 1169.531 2* 'Y' 6.479 / - 'C-19' 32 29 10 10 'OPEN' 1* 234.073 0.216 17885.273 2* 'Y' 6.473 / - 'C-19' 32 29 9 9 'OPEN' 1* 229.050 0.216 17487.535 2* 'Y' 6.452 / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 724.200 0.400 97579.200 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1539.000 0.200 217940.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 80904.400 5* / -/ - -DATES - 08 'MAY' 1995 / -/ - -WELOPEN - 'C-18AT2' 'SHUT' 5* / -/ - -WCONHIST - 'C-18AT2' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1397129.958 5* / -/ - -DATES - 01 'JUN' 1995 / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1231730.867 5* / -/ - -DATES - 01 'JUL' 1995 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 743.806 0.903 98001.065 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-21' 'OIL' 'OPEN' 'RATE' 185.000 4* 140.000 / - 'C-22' 'GAS' 'OPEN' 'RATE' 1056146.097 5* / -/ - -DATES - 01 'AUG' 1995 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1407.419 1.355 187173.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 828277.161 5* / -/ - -DATES - 01 'SEP' 1995 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1508.367 1.533 202018.233 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1143498.596 5* / -/ - -DATES - 01 'OCT' 1995 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1498.774 3.484 201044.645 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 747797.940 5* / -/ - -DATES - 01 'NOV' 1995 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1793.867 4.967 235738.933 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 6199.333 5* / -/ - -DATES - 01 'DEC' 1995 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1663.613 4.000 213511.581 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 25271.548 5* / -/ - -DATES - 01 'JAN' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1775.194 4.935 240048.999 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-21' 'OIL' 'OPEN' 'RATE' 631.000 4* 140.000 / - 'C-22' 'GAS' 'OPEN' 'RATE' 140338.484 5* / -/ - -DATES - 01 'FEB' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1652.724 2.241 222332.586 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 950214.931 5* / -/ - -DATES - 01 'MAR' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1725.484 9.290 230628.806 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 2084133.706 5* / -/ - -DATES - 01 'APR' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 526.000 6.167 71888.300 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1933211.663 5* / -/ - -DATES - 01 'MAY' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1013670.933 5* / -/ - -DATES - 14 'MAY' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 274.889 0.333 36549.611 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1589912.667 5* / -/ - -DATES - 01 'JUN' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1536.467 2.467 204058.100 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1554288.467 5* / -/ - -DATES - 01 'JUL' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1613.581 3.032 218370.516 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-21' 'OIL' 'OPEN' 'RATE' 218.000 4* 140.000 / - 'C-22' 'GAS' 'OPEN' 'RATE' 1235698.871 5* / -/ - -DATES - 01 'AUG' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1036.452 5.290 139989.097 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1371492.000 5* / -/ - -DATES - 01 'SEP' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1251.400 12.300 159855.400 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1322016.400 5* / -/ - -DATES - 01 'OCT' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1060.097 9.548 133908.323 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1416153.194 5* / -/ - -DATES - 01 'NOV' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 282.067 2.400 38423.667 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1457440.167 5* / -/ - -DATES - 01 'DEC' 1996 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 913.968 8.290 112852.935 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1271679.935 5* / -/ - -DATES - 01 'JAN' 1997 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1035.258 4.774 136802.323 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-21' 'WATER' 'OPEN' 'RATE' 30.000 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1639220.968 5* / -/ - -DATES - 01 'FEB' 1997 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1124.571 3.250 144670.929 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1550006.964 5* / -/ - -DATES - 01 'MAR' 1997 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1175.258 3.323 154152.548 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1482430.452 5* / -/ - -DATES - 01 'APR' 1997 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 431.567 1.167 59562.733 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1238856.135 5* / -/ - -DATES - 01 'MAY' 1997 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1466411.577 5* / -/ - -DATES - 27 'MAY' 1997 / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1364049.800 5* / -/ - -DATES - 01 'JUN' 1997 / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1101468.800 5* / -/ - -DATES - 01 'JUL' 1997 / -/ - -WCONHIST - 'C-21' 'OPEN' 'ORAT' 218.000 121.000 28240.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1478819.677 5* / -/ - -DATES - 01 'AUG' 1997 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 568.677 0.548 72328.065 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1380280.839 5* / -/ - -DATES - 01 'SEP' 1997 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1262.267 1.067 165176.733 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1439918.967 5* / -/ - -DATES - 01 'OCT' 1997 / -/ - -WELSPECS - 'C-5' 'NESS' 13 8 1* 'OIL' 1* 1* 1* 'YES' 1* 1* 1* / -/ - -COMPDAT - 'C-5' 13 8 14 14 'OPEN' 1* 13.245 0.216 1224.200 2* 'Y' 15.284 / - 'C-5' 13 8 15 15 'OPEN' 1* 39.248 0.216 3513.834 2* 'Y' 13.074 / - 'C-5' 13 8 16 16 'OPEN' 1* 38.694 0.216 3553.848 2* 'Y' 14.801 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1429.968 1.065 188085.065 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 11034.381 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1431240.968 5* / -/ - -DATES - 01 'NOV' 1997 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1258.786 1.000 163203.286 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 0.000 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1435134.286 5* / -/ - -DATES - 15 'NOV' 1997 / -/ - -WELSPECS - 'C-13AT2' 'NESS' 19 18 1* 'OIL' 1* 1* 1* 'YES' 1* 1* 1* / -/ - -COMPDAT - 'C-13AT2' 29 34 9 9 'OPEN' 1* 121.326 0.216 9346.453 2* 'X' 6.694 / - 'C-13AT2' 29 35 9 9 'OPEN' 1* 375.257 0.216 28875.219 2* 'X' 6.663 / - 'C-13AT2' 30 35 9 9 'OPEN' 1* 138.022 0.216 10675.971 2* 'X' 6.808 / - 'C-13AT2' 30 35 10 10 'OPEN' 1* 183.016 0.216 14241.644 2* 'X' 6.980 / - 'C-13AT2' 30 35 11 11 'OPEN' 1* 117.303 0.216 9168.256 2* 'X' 7.109 / - 'C-13AT2' 30 36 11 11 'OPEN' 1* 17.959 0.216 1424.767 2* 'X' 7.571 / - 'C-13AT2' 30 36 12 12 'OPEN' 1* 99.268 0.216 7846.105 2* 'X' 7.453 / - 'C-13AT2' 30 36 13 13 'OPEN' 1* 0.017 0.216 1.378 2* 'X' 7.801 / - 'C-13AT2' 31 36 13 13 'OPEN' 1* 0.037 0.216 3.027 2* 'X' 8.661 / - 'C-13AT2' 31 36 14 14 'OPEN' 1* 52.970 0.216 4373.898 2* 'X' 9.006 / - 'C-13AT2' 31 36 15 15 'OPEN' 1* 0.040 0.216 3.353 2* 'X' 9.478 / - 'C-13AT2' 31 36 16 16 'OPEN' 1* 0.045 0.216 3.729 2* 'X' 9.093 / -/ - -WCONHIST - 'C-13AT2' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1574.750 2.062 203144.500 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 1277878.125 5* / -/ - -DATES - 01 'DEC' 1997 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1146.290 2.355 151768.935 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-22' 'GAS' 'OPEN' 'RATE' 913591.742 5* / -/ - -DATES - 01 'JAN' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1288.792 3.500 175683.082 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 0.572 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1074695.633 5* / -/ - -DATES - 25 'JAN' 1998 / -/ - -WELSPECS - 'C-8T2K' 'NESS' 30 10 1* 'OIL' 1* 1* 1* 'YES' 1* 1* 1* / -/ - -COMPDAT - 'C-8T2K' 31 10 7 7 'OPEN' 1* 6.795 0.216 639.355 2* 'Y' 16.699 / - 'C-8T2K' 31 10 8 8 'OPEN' 1* 0.026 0.216 2.363 2* 'Y' 14.962 / - 'C-8T2K' 31 10 9 9 'OPEN' 1* 26.041 0.216 2400.479 2* 'Y' 15.069 / - 'C-8T2K' 31 11 9 9 'OPEN' 1* 4.488 0.216 435.816 2* 'Z' 19.631 / - 'C-8T2K' 31 11 10 10 'OPEN' 1* 30.057 0.216 2768.771 2* 'Y' 15.019 / - 'C-8T2K' 31 11 11 11 'OPEN' 1* 29.819 0.216 2787.005 2* 'Y' 16.142 / - 'C-8T2K' 31 11 12 12 'OPEN' 1* 29.203 0.216 2762.936 2* 'Y' 17.166 / - 'C-8T2K' 31 11 13 13 'OPEN' 1* 30.673 0.216 2781.058 2* 'Y' 13.895 / - 'C-8T2K' 31 11 14 14 'OPEN' 1* 29.100 0.216 2752.839 2* 'Y' 17.154 / - 'C-8T2K' 31 11 15 15 'OPEN' 1* 29.579 0.216 2764.073 2* 'Y' 16.128 / - 'C-8T2K' 31 11 16 16 'OPEN' 1* 29.467 0.216 2753.624 2* 'Y' 16.129 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1944.714 5.286 265860.567 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 3936.561 5* / - 'C-8T2K' 'GAS' 'OPEN' 'RATE' 378417.286 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 893178.580 5* / -/ - -DATES - 01 'FEB' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 845.964 2.643 114837.607 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 20041.754 5* / - 'C-8T2K' 'GAS' 'OPEN' 'RATE' 271288.035 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 1000.000 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 859225.321 5* / -/ - -DATES - 01 'MAR' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 686.613 0.548 84423.806 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 539.029 5* / - 'C-8T2K' 'GAS' 'OPEN' 'RATE' 0.000 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 150693.548 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1025833.516 5* / -/ - -DATES - 01 'APR' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 786.267 0.700 114509.967 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 395.357 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 258560.001 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 949555.735 5* / -/ - -DATES - 01 'MAY' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1838.839 9.484 303938.548 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 1510.949 5* / - 'C-8T2K' 'GAS' 'OPEN' 'RATE' 48.065 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 222492.613 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1088516.452 5* / -/ - -DATES - 01 'JUN' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 3037.091 16.636 590102.320 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 8662.463 5* / - 'C-8T2K' 'GAS' 'OPEN' 'RATE' 149.273 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 269844.182 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1011561.227 5* / -/ - -DATES - 23 'JUN' 1998 / -/ - -WELOPEN - 'C-8T2K' 'SHUT' 5* / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 2992.000 15.000 660209.125 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 0.000 5* / - 'C-8T2K' 'GAS' 'OPEN' 'RATE' 0.000 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 291418.500 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 945577.867 5* / -/ - -DATES - 01 'JUL' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 2096.968 28.452 511463.355 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 1905.761 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 296592.548 5* / - 'C-21' 'OIL' 'OPEN' 'RATE' 249.000 4* 140.000 / - 'C-22' 'GAS' 'OPEN' 'RATE' 989500.518 5* / -/ - -DATES - 01 'AUG' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 2014.161 32.355 499951.292 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 373.335 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 355086.097 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1104129.710 5* / -/ - -DATES - 01 'SEP' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 2393.300 29.333 573772.099 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 5477.893 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 344129.433 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1071732.435 5* / -/ - -DATES - 01 'OCT' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1663.742 12.806 572738.869 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 12534.623 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 390771.097 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1166055.161 5* / -/ - -DATES - 01 'NOV' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1243.867 10.400 410035.033 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 10580.132 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 343892.800 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 918766.369 5* / -/ - -DATES - 01 'DEC' 1998 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1218.226 10.516 398008.613 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 6268.938 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 394672.161 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1131794.869 5* / -/ - -DATES - 01 'JAN' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 669.806 6.290 265957.871 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 14613.365 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 695321.065 5* / - 'C-21' 'WATER' 'OPEN' 'RATE' 261.000 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1108820.841 5* / -/ - -DATES - 01 'FEB' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 632.679 1.750 219156.250 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 25185.743 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 477539.893 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1161119.179 5* / -/ - -DATES - 01 'MAR' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1279.839 3.645 454776.097 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 22290.146 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 360616.226 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1204084.645 5* / -/ - -DATES - 01 'APR' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1223.433 3.600 428480.033 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 25595.163 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 355382.067 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1387249.000 5* / -/ - -DATES - 01 'MAY' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1176.032 3.387 443610.967 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 28055.677 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 324908.129 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1297890.903 5* / -/ - -DATES - 01 'JUN' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 604.967 1.633 222805.065 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 12464.191 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 159622.133 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 594618.637 5* / -/ - -DATES - 01 'JUL' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 754.032 1.806 251992.452 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 39104.203 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 50033.452 5* / - 'C-21' 'GAS' 'OPEN' 'RATE' 56671.000 4* 0.000215135 / - 'C-22' 'GAS' 'OPEN' 'RATE' 1332732.258 5* / -/ - -DATES - 01 'AUG' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 30585.698 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 3580.645 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1130730.613 5* / -/ - -DATES - 01 'SEP' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 674.700 0.700 240749.333 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 16201.437 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 331169.467 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 768833.669 5* / -/ - -DATES - 01 'OCT' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 998.065 1.323 329109.355 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 13937.428 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 373573.613 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 844154.353 5* / -/ - -DATES - 01 'NOV' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1136.933 1.200 390925.767 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 20674.413 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 447641.432 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1001040.765 5* / -/ - -DATES - 01 'DEC' 1999 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1080.839 1.097 403727.065 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 25753.132 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 470490.324 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1017267.228 5* / -/ - -DATES - 01 'JAN' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1169.323 8.387 425524.034 1* 1* 1* 1* 1* / - 'C-21' 'OPEN' 'ORAT' 115.000 66.000 44716.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 52017.197 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 502873.225 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 944509.131 5* / -/ - -DATES - 01 'FEB' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1084.931 8.966 385280.690 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 48058.918 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 457486.414 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1015348.862 5* / -/ - -DATES - 01 'MAR' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 405.581 3.194 137765.161 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 46766.333 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 477722.484 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 798971.032 5* / -/ - -DATES - 01 'APR' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 713.933 6.433 262273.367 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 53853.466 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 483743.234 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 813487.798 5* / -/ - -DATES - 01 'MAY' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 647.935 5.419 227722.258 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 43736.787 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 460786.646 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 801484.387 5* / -/ - -DATES - 01 'JUN' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 777.033 4.600 241693.467 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 57244.080 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 448467.100 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 758476.800 5* / -/ - -DATES - 01 'JUL' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 977.065 4.548 250727.065 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 50720.655 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 492895.807 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 886439.968 5* / -/ - -DATES - 01 'AUG' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 819.419 4.032 206844.548 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 37957.494 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 503092.291 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 964582.835 5* / -/ - -DATES - 01 'SEP' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 506.567 2.900 140249.133 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 40924.206 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 414451.167 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 895560.002 5* / -/ - -DATES - 01 'OCT' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 841.194 5.452 403911.322 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 28618.119 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 538214.452 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 990095.157 5* / -/ - -DATES - 01 'NOV' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 527.333 1.267 199187.966 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 26082.540 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 513635.435 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 921066.669 5* / -/ - -DATES - 01 'DEC' 2000 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 242.097 0.419 88378.903 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 25390.255 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 521458.544 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 956081.871 5* / -/ - -DATES - 01 'JAN' 2001 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 33085.100 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 259986.386 5* / - 'C-21' 'OIL' 'OPEN' 'RATE' 408.000 4* 140.000 / - 'C-22' 'GAS' 'OPEN' 'RATE' 978383.099 5* / -/ - -DATES - 01 'FEB' 2001 / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 48205.999 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 0.000 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1149495.714 5* / -/ - -DATES - 08 'FEB' 2001 / -/ - -WELOPEN - 'C-19' 'SHUT' 0 0 0 2* / -/ - -COMPDAT - 'C-19' 39 14 6 6 'OPEN' 1* 25.266 0.216 1990.187 2* 'Y' 7.346 / - 'C-19' 39 15 6 6 'OPEN' 1* 53.485 0.216 4277.886 2* 'Y' 7.839 / - 'C-19' 39 15 7 7 'OPEN' 1* 104.233 0.216 8176.943 2* 'Y' 7.221 / - 'C-19' 39 15 8 8 'OPEN' 1* 0.338 0.216 26.100 2* 'Y' 6.719 / - 'C-19' 39 16 8 8 'OPEN' 1* 0.087 0.216 6.671 2* 'Y' 6.676 / - 'C-19' 38 16 8 8 'OPEN' 1* 0.131 0.216 10.099 2* 'Y' 6.670 / - 'C-19' 37 18 11 11 'OPEN' 1* 36.701 0.216 2834.485 2* 'Y' 6.765 / - 'C-19' 37 18 12 12 'OPEN' 1* 201.696 0.216 15589.941 2* 'Y' 6.788 / - 'C-19' 37 18 13 13 'OPEN' 1* 32.173 0.216 2482.740 2* 'Y' 6.742 / - 'C-19' 37 19 13 13 'OPEN' 1* 0.094 0.216 7.293 2* 'Y' 6.764 / - 'C-19' 36 19 13 13 'OPEN' 1* 86.499 0.216 6665.573 2* 'Y' 6.703 / - 'C-19' 36 19 14 14 'OPEN' 1* 0.278 0.216 21.410 2* 'Y' 6.649 / - 'C-19' 36 20 14 14 'OPEN' 1* 278.325 0.216 21398.139 2* 'Y' 6.639 / - 'C-19' 36 20 13 13 'OPEN' 1* 218.830 0.216 16861.514 2* 'Y' 6.700 / - 'C-19' 36 21 13 13 'OPEN' 1* 284.727 0.216 21878.511 2* 'Y' 6.624 / - 'C-19' 36 21 12 12 'OPEN' 1* 200.525 0.216 15398.416 2* 'Y' 6.607 / - 'C-19' 36 22 13 13 'OPEN' 1* 38.955 0.216 2991.239 2* 'Y' 6.605 / - 'C-19' 36 22 12 12 'OPEN' 1* 124.228 0.216 9534.560 2* 'Y' 6.593 / - 'C-19' 35 23 13 13 'OPEN' 1* 229.211 0.216 17591.568 2* 'Y' 6.592 / - 'C-19' 35 23 14 14 'OPEN' 1* 42.518 0.216 3286.223 2* 'Y' 6.786 / - 'C-19' 35 24 15 15 'OPEN' 1* 49.616 0.216 3818.562 2* 'Y' 6.668 / - 'C-19' 35 24 16 16 'OPEN' 1* 148.076 0.216 11340.899 2* 'Y' 6.536 / - 'C-19' 35 25 16 16 'OPEN' 1* 0.164 0.216 12.543 2* 'Y' 6.514 / - 'C-19' 34 25 16 16 'OPEN' 1* 128.420 0.216 9830.735 2* 'Y' 6.523 / - 'C-19' 34 25 15 15 'OPEN' 1* 137.101 0.216 10497.277 2* 'Y' 6.528 / - 'C-19' 34 26 15 15 'OPEN' 1* 71.365 0.216 5444.541 2* 'Y' 6.433 / - 'C-19' 34 26 14 14 'OPEN' 1* 423.367 0.216 32285.266 2* 'Y' 6.421 / - 'C-19' 33 26 14 14 'OPEN' 1* 68.448 0.216 5231.526 2* 'Y' 6.481 / - 'C-19' 33 27 14 14 'OPEN' 1* 36.744 0.216 2805.661 2* 'Y' 6.455 / - 'C-19' 33 27 13 13 'OPEN' 1* 354.667 0.216 27036.137 2* 'Y' 6.411 / - 'C-19' 33 27 12 12 'OPEN' 1* 100.458 0.216 7650.032 2* 'Y' 6.385 / - 'C-19' 33 28 12 12 'OPEN' 1* 207.460 0.216 15797.470 2* 'Y' 6.383 / - 'C-19' 32 28 12 12 'OPEN' 1* 103.805 0.216 7940.809 2* 'Y' 6.504 / - 'C-19' 32 28 11 11 'OPEN' 1* 247.786 0.216 18955.656 2* 'Y' 6.505 / - 'C-19' 32 28 10 10 'OPEN' 1* 15.303 0.216 1169.531 2* 'Y' 6.479 / - 'C-19' 32 29 10 10 'OPEN' 1* 234.073 0.216 17885.273 2* 'Y' 6.473 / - 'C-19' 32 29 9 9 'OPEN' 1* 229.050 0.216 17487.535 2* 'Y' 6.452 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 48219.119 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1011353.905 5* / -/ - -DATES - 01 'MAR' 2001 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1523.613 3.355 377079.903 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 44450.684 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 57961.419 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 806393.129 5* / -/ - -DATES - 01 'APR' 2001 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 3059.900 7.200 760971.400 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 30528.657 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 354455.933 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 694052.267 5* / -/ - -DATES - 01 'MAY' 2001 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 2687.355 5.452 775058.710 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 42701.446 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 529185.839 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 546850.484 5* / -/ - -DATES - 01 'JUN' 2001 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1218.133 1.533 433342.800 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 24848.297 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 293138.300 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 427921.300 5* / -/ - -DATES - 01 'JUL' 2001 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1113.839 44.581 440213.742 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 31708.122 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 451100.903 5* / - 'C-21' 'WATER' 'OPEN' 'RATE' 166.000 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 797749.744 5* / -/ - -DATES - 01 'AUG' 2001 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1288.387 46.903 718752.871 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 43430.110 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 512932.968 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 697510.258 5* / -/ - -DATES - 01 'SEP' 2001 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1363.800 59.133 705664.433 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 45018.711 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 503202.568 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 706524.433 5* / -/ - -DATES - 01 'OCT' 2001 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1393.355 64.806 745196.839 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 47425.574 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 531249.773 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 665642.871 5* / -/ - -DATES - 01 'NOV' 2001 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1252.133 57.833 642884.867 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 48107.967 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 539024.932 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 697369.600 5* / -/ - -DATES - 01 'DEC' 2001 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1058.065 2.194 425976.549 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 47502.032 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 538549.613 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 630823.806 5* / -/ - -DATES - 01 'JAN' 2002 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1076.516 0.903 537676.194 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 48660.038 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 476819.227 5* / - 'C-21' 'GAS' 'OPEN' 'RATE' 140756.000 4* 0.000215135 / - 'C-22' 'GAS' 'OPEN' 'RATE' 626401.806 5* / -/ - -DATES - 01 'FEB' 2002 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 1183.679 1.036 610370.393 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 36004.610 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 520335.967 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 694726.250 5* / -/ - -DATES - 01 'MAR' 2002 / -/ - -WCONHIST - 'C-19' 'OPEN' 'RESV' 652.720 0.760 340383.720 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 24264.599 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 405655.040 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 458198.200 5* / -/ - -DATES - 26 'MAR' 2002 / -/ - -WELSPECS - 'C-17D' 'NESS' 36 30 1* 'OIL' 1* 1* 1* 'YES' 1* 1* 1* / -/ - -COMPDAT - 'C-17D' 36 30 5 5 'OPEN' 1* 53.414 0.216 4126.272 2* 'Y' 6.772 / - 'C-17D' 36 31 5 5 'OPEN' 1* 7.861 0.216 603.112 2* 'Y' 6.584 / - 'C-17D' 36 31 6 6 'OPEN' 1* 0.075 0.216 5.840 2* 'Y' 7.062 / - 'C-17D' 36 31 7 7 'OPEN' 1* 77.855 0.216 6135.617 2* 'Y' 7.361 / - 'C-17D' 36 31 8 8 'OPEN' 1* 107.452 0.216 8206.291 2* 'Y' 6.460 / - 'C-17D' 37 31 8 8 'OPEN' 1* 15.268 0.216 1165.169 2* 'Y' 6.440 / - 'C-17D' 37 32 7 7 'OPEN' 1* 0.036 0.216 2.753 2* 'Y' 6.525 / - 'C-17D' 37 33 6 6 'OPEN' 1* 144.823 0.216 11093.169 2* 'Y' 6.539 / - 'C-17D' 37 33 5 5 'OPEN' 1* 240.429 0.216 18386.318 2* 'Y' 6.495 / - 'C-17D' 37 34 5 5 'OPEN' 1* 212.427 0.216 16247.310 2* 'Y' 6.499 / - 'C-17D' 37 34 4 4 'OPEN' 1* 47.838 0.216 3651.416 2* 'Y' 6.446 / - 'C-17D' 38 39 6 6 'OPEN' 1* 146.727 0.216 11248.045 2* 'Y' 6.561 / - 'C-17D' 38 40 6 6 'OPEN' 1* 222.667 0.216 17060.746 2* 'Y' 6.547 / - 'C-17D' 37 43 5 5 'OPEN' 1* 37.466 0.216 2867.317 2* 'Y' 6.516 / - 'C-17D' 37 43 4 4 'OPEN' 1* 248.842 0.216 19042.551 2* 'Y' 6.513 / - 'C-17D' 37 44 4 4 'OPEN' 1* 223.144 0.216 17067.840 2* 'Y' 6.501 / - 'C-17D' 37 44 5 5 'OPEN' 1* 122.738 0.216 9415.716 2* 'Y' 6.580 / - 'C-17D' 37 45 5 5 'OPEN' 1* 337.905 0.216 25852.387 2* 'Y' 6.508 / - 'C-17D' 37 45 6 6 'OPEN' 1* 71.841 0.216 5490.406 2* 'Y' 6.479 / - 'C-17D' 37 46 6 6 'OPEN' 1* 207.826 0.216 15880.383 2* 'Y' 6.474 / - 'C-17D' 37 46 5 5 'OPEN' 1* 132.209 0.216 10104.258 2* 'Y' 6.479 / - 'C-17D' 37 47 5 5 'OPEN' 1* 450.314 0.216 34420.406 2* 'Y' 6.483 / - 'C-17D' 37 48 5 5 'OPEN' 1* 253.673 0.216 19399.193 2* 'Y' 6.496 / - 'C-17D' 37 49 5 5 'OPEN' 1* 0.081 0.216 6.202 2* 'Y' 6.481 / - 'C-17D' 37 49 6 6 'OPEN' 1* 0.143 0.216 10.919 2* 'Y' 6.474 / - 'C-17D' 37 50 6 6 'OPEN' 1* 0.154 0.216 11.738 2* 'Y' 6.483 / - 'C-17D' 38 50 6 6 'OPEN' 1* 0.032 0.216 2.461 2* 'Y' 6.446 / - 'C-17D' 38 51 4 4 'OPEN' 1* 0.039 0.216 3.068 2* 'Y' 6.935 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 13.333 12.500 7337.167 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 7.500 0.000 1984.500 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 10823.693 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 4934.500 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 220494.500 5* / -/ - -DATES - 01 'APR' 2002 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 1430.567 80.500 341077.267 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1053.733 0.967 556946.400 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 32093.420 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 511044.367 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 760140.233 5* / -/ - -DATES - 01 'MAY' 2002 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 1035.935 41.710 377582.516 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 886.968 70.581 446392.193 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 36899.383 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 536468.548 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 691940.644 5* / -/ - -DATES - 01 'JUN' 2002 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 253.200 0.033 83361.100 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 850.300 104.133 574315.567 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 28361.940 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 430408.269 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 531053.567 5* / -/ - -DATES - 01 'JUL' 2002 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 74.581 0.000 21145.871 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 817.258 19.452 486586.675 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 22606.703 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 541137.806 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 0.000 5* / -/ - -DATES - 01 'AUG' 2002 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 0.000 0.000 19.613 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 811.161 11.161 496220.743 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 24811.485 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 630671.839 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 104471.129 5* / -/ - -DATES - 01 'SEP' 2002 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 661.133 57.300 412005.767 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 21819.563 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 569409.467 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 233.067 5* / -/ - -DATES - 01 'OCT' 2002 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 399.548 23.677 85037.742 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 723.161 129.548 480822.516 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 20918.064 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 615731.839 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 17718.129 5* / -/ - -DATES - 01 'NOV' 2002 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 290.800 6.300 174601.967 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 574.433 27.933 360413.733 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 11992.711 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 597995.067 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 4186.000 5* / -/ - -DATES - 01 'DEC' 2002 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 423.935 11.387 382036.258 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 813.645 43.194 527662.323 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 27290.653 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 568576.226 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1984.839 5* / -/ - -DATES - 01 'JAN' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 575.387 35.516 509974.548 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 641.419 78.000 413161.871 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 46915.403 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 610799.452 5* / - 'C-21' 'OIL' 'OPEN' 'RATE' 206.000 4* 140.000 / - 'C-22' 'GAS' 'OPEN' 'RATE' 122928.194 5* / -/ - -DATES - 01 'FEB' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 156.357 8.393 181800.929 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 830.964 102.143 530429.679 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 55980.850 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 662084.429 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 647112.609 5* / -/ - -DATES - 01 'MAR' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 0.161 0.000 585.000 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 669.258 85.387 425507.839 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 16919.533 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 653643.387 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 228890.742 5* / -/ - -DATES - 01 'APR' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 91.100 4.833 65637.933 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 609.367 89.767 430083.932 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 23347.952 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 524380.201 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 0.000 5* / -/ - -DATES - 01 'MAY' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 100.806 6.710 84103.516 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 522.323 82.581 340785.323 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 28703.622 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 423693.710 5* / -/ - -DATES - 01 'JUN' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 0.867 0.033 930.767 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 641.133 62.333 438901.933 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 30736.323 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 447400.633 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 15159.700 5* / -/ - -DATES - 01 'JUL' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 119.806 8.677 126503.548 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 665.710 65.710 387251.839 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 28296.093 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 637559.032 5* / - 'C-21' 'GAS' 'OPEN' 'RATE' 187518.000 4* 0.000215135 / - 'C-22' 'GAS' 'OPEN' 'RATE' 0.000 5* / -/ - -DATES - 01 'AUG' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 323.290 0.387 129316.000 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 804.839 68.806 600458.613 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 46596.784 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 562862.710 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 592031.903 5* / -/ - -DATES - 01 'SEP' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 307.400 0.267 150269.300 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 966.367 81.000 730195.570 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 66282.127 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 675212.033 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1091625.233 5* / -/ - -DATES - 01 'OCT' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 164.806 0.000 63481.226 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 905.129 90.903 824197.484 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 60133.631 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 553955.129 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 905042.353 5* / -/ - -DATES - 01 'NOV' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1213.000 107.000 1172024.254 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 75595.519 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 1091.938 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1354812.188 5* / -/ - -DATES - 17 'NOV' 2003 / -/ - -WELOPEN - 'C-13AT2' 'SHUT' 0 0 0 2* / -/ - -COMPDAT - 'C-13AT2' 22 27 15 15 'OPEN' 1* 68.994 0.216 5339.784 2* 'Y' 6.824 / - 'C-13AT2' 22 27 16 16 'OPEN' 1* 162.174 0.216 12530.677 2* 'Y' 6.778 / - 'C-13AT2' 22 28 16 16 'OPEN' 1* 31.885 0.216 2467.733 2* 'Y' 6.824 / - 'C-13AT2' 23 28 16 16 'OPEN' 1* 29.573 0.216 2285.517 2* 'Y' 6.784 / - 'C-13AT2' 23 28 15 15 'OPEN' 1* 29.634 0.216 2295.352 2* 'Y' 6.847 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 104.643 0.071 58672.785 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1079.929 98.786 1082911.929 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 71343.963 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 610784.857 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1431670.429 5* / -/ - -DATES - 01 'DEC' 2003 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 224.355 0.194 104331.742 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 854.097 78.839 594182.839 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 66903.877 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 621793.357 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1041548.161 5* / -/ - -DATES - 01 'JAN' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 165.839 54.710 126789.097 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 723.452 52.903 368399.258 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 64954.763 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 633223.032 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1037734.550 5* / -/ - -DATES - 01 'FEB' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 386.483 121.931 279919.725 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 890.138 44.931 488803.519 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 57010.221 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 600900.448 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1172543.413 5* / -/ - -DATES - 01 'MAR' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 466.194 125.000 432198.418 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1290.097 88.355 387124.323 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 16226.168 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 609270.387 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1114658.772 5* / -/ - -DATES - 01 'APR' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 0.000 0.000 0.000 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1168.067 64.000 435236.300 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 4452.067 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 617182.167 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1386763.400 5* / -/ - -DATES - 01 'MAY' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 276.581 99.548 218693.065 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1080.710 58.290 347040.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 2285.329 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 614213.194 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1616394.548 5* / -/ - -DATES - 01 'JUN' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 252.467 78.133 260664.467 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1006.267 49.733 375247.967 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 355.837 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 650779.167 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1605165.133 5* / -/ - -DATES - 01 'JUL' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 174.161 54.839 165662.290 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1128.581 80.194 386713.935 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 147.318 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 657043.226 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1864440.226 5* / -/ - -DATES - 01 'AUG' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 487.161 146.677 442460.000 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1057.000 131.871 389415.581 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 24.397 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 650134.226 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1804685.387 5* / -/ - -DATES - 01 'SEP' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 6.900 2.467 5354.400 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 951.233 127.333 314914.900 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 0.000 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 483098.467 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1158197.367 5* / -/ - -DATES - 01 'OCT' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 2.500 0.643 2266.143 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1313.929 130.357 442969.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 0.000 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 2463440.714 5* / -/ - -DATES - 15 'OCT' 2004 / -/ - -WELOPEN - 'C-17D' 'SHUT' 0 0 0 2* / -/ - -COMPDAT - 'C-17D' 37 32 7 7 'OPEN' 1* 0.036 0.216 2.753 2* 'Y' 6.525 / - 'C-17D' 37 33 6 6 'OPEN' 1* 144.823 0.216 11093.169 2* 'Y' 6.539 / - 'C-17D' 37 33 5 5 'OPEN' 1* 240.429 0.216 18386.318 2* 'Y' 6.495 / - 'C-17D' 37 34 5 5 'OPEN' 1* 212.427 0.216 16247.310 2* 'Y' 6.499 / - 'C-17D' 37 34 4 4 'OPEN' 1* 47.838 0.216 3651.416 2* 'Y' 6.446 / - 'C-17D' 38 39 6 6 'OPEN' 1* 146.727 0.216 11248.045 2* 'Y' 6.561 / - 'C-17D' 38 40 6 6 'OPEN' 1* 222.667 0.216 17060.746 2* 'Y' 6.547 / - 'C-17D' 37 43 5 5 'OPEN' 1* 37.466 0.216 2867.317 2* 'Y' 6.516 / - 'C-17D' 37 43 4 4 'OPEN' 1* 248.842 0.216 19042.551 2* 'Y' 6.513 / - 'C-17D' 37 44 4 4 'OPEN' 1* 223.144 0.216 17067.840 2* 'Y' 6.501 / - 'C-17D' 37 44 5 5 'OPEN' 1* 122.738 0.216 9415.716 2* 'Y' 6.580 / - 'C-17D' 37 45 5 5 'OPEN' 1* 337.905 0.216 25852.387 2* 'Y' 6.508 / - 'C-17D' 37 45 6 6 'OPEN' 1* 71.841 0.216 5490.406 2* 'Y' 6.479 / - 'C-17D' 37 46 6 6 'OPEN' 1* 207.826 0.216 15880.383 2* 'Y' 6.474 / - 'C-17D' 37 46 5 5 'OPEN' 1* 132.209 0.216 10104.258 2* 'Y' 6.479 / - 'C-17D' 37 47 5 5 'OPEN' 1* 450.314 0.216 34420.406 2* 'Y' 6.483 / - 'C-17D' 37 48 5 5 'OPEN' 1* 253.673 0.216 19399.193 2* 'Y' 6.496 / - 'C-17D' 37 49 5 5 'OPEN' 1* 0.081 0.216 6.202 2* 'Y' 6.481 / - 'C-17D' 37 49 6 6 'OPEN' 1* 0.143 0.216 10.919 2* 'Y' 6.474 / - 'C-17D' 37 50 6 6 'OPEN' 1* 0.154 0.216 11.738 2* 'Y' 6.483 / - 'C-17D' 38 50 6 6 'OPEN' 1* 0.032 0.216 2.461 2* 'Y' 6.446 / - 'C-17D' 38 51 4 4 'OPEN' 1* 0.039 0.216 3.068 2* 'Y' 6.935 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 687.941 150.471 473113.469 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1230.235 114.235 353778.000 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 130834.529 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1758995.059 5* / -/ - -DATES - 01 'NOV' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 530.667 199.033 420183.333 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1163.933 149.600 377031.933 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 25810.140 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 369752.801 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1468401.644 5* / -/ - -DATES - 01 'DEC' 2004 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 11.387 6.290 10531.871 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 289.903 42.290 97046.968 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 67840.581 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 0.000 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1096572.228 5* / -/ - -DATES - 01 'JAN' 2005 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 97.053 83.737 87742.474 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 942.632 134.684 226690.263 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 26636.079 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1519183.579 5* / -/ - -DATES - 20 'JAN' 2005 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 125.583 109.500 113940.750 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1081.667 167.500 300570.833 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 0.000 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 1300000.000 1* 600.000 3* / - 'C-22' 'GAS' 'OPEN' 'RATE' 562529.918 5* / -/ - -DATES - 01 'FEB' 2005 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 1.071 1.107 1109.821 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1087.679 179.750 395600.714 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 28442.948 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 1282130.357 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 524656.248 5* / -/ - -DATES - 01 'MAR' 2005 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 554.226 166.387 649349.935 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1173.774 169.548 576941.903 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 65629.595 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 1258322.258 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 0.000 5* / -/ - -DATES - 01 'APR' 2005 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 67.633 16.600 94114.333 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 1194.467 160.567 556157.433 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 60492.032 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 1249630.767 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 400465.133 5* / -/ - -DATES - 01 'MAY' 2005 / -/ - -WCONHIST - 'C-17D' 'OPEN' 'RESV' 7.290 1.290 2866.710 1* 1* 1* 1* 1* / - 'C-19' 'OPEN' 'RESV' 997.097 153.097 611673.452 1* 1* 1* 1* 1* / -/ - -WCONINJE - 'C-5' 'GAS' 'OPEN' 'RATE' 53075.411 5* / - 'C-13AT2' 'GAS' 'OPEN' 'RATE' 1242915.290 5* / - 'C-22' 'GAS' 'OPEN' 'RATE' 1766845.006 5* / -/ - -DATES - 01 'JUN' 2005 / -/ - -END diff --git a/ThirdParty/Ert/libsched/src/tests/sched_test_02.SCH b/ThirdParty/Ert/libsched/src/tests/sched_test_02.SCH deleted file mode 100644 index 6832f7b691..0000000000 --- a/ThirdParty/Ert/libsched/src/tests/sched_test_02.SCH +++ /dev/null @@ -1,24 +0,0 @@ -GRUPTREE - FOO FIELD / -/ - - -WCONHIST - 'OP_1' 'OPEN' 'ORAT' 7996.000 4.000 1.46402E+006 5* / - 'OP_2' 'OPEN' 'ORAT' 7998.000 2.000 1461075.000 5* / -/ - -DATES - 11 'JAN' 2000 / -/ - -WCONHIST - 'OP_3' 'OPEN' 'ORAT' 7999.000 1.000 1471824.000 5* / - 'OP_4' 'SHUT' 'ORAT' 2451.000 4252.000 453703.000 5* / - 'OP_5' 'SHUT' 'ORAT' 1186.000 6814.000 206655.000 5* / -/ - -DATES - 10 'FEB' 2000 / - 20 'FEB' 2000 / -/ diff --git a/ThirdParty/Ert/libsched/src/tests/sched_test_04.SCH b/ThirdParty/Ert/libsched/src/tests/sched_test_04.SCH deleted file mode 100644 index dd589e8574..0000000000 --- a/ThirdParty/Ert/libsched/src/tests/sched_test_04.SCH +++ /dev/null @@ -1,175 +0,0 @@ -SKIPREST - -RPTSCHED - RESTART=2 / - --- SET 'NO RESOLUTION' OPTION -DRSDT - 0 / - --- WELL SPECIFICATION DATA --- --- WELL GROUP LOCATION BHP PI --- NAME NAME I J DEPTH DEFN --- m -WELSPECS - 'WWI1' 'G' 1 1 -1 'WATER' / - 'WP1' 'G' 30 30 -1 'OIL' / -/ - - --- COMPLETION SPECIFICATION DATA --- --- WELL -LOCATION- OPEN/ SAT CONN WELL --- NAME I J K1 K2 SHUT TAB FACT DIAM --- m2 -COMPDAT - 'WWI1' 1 1 1 5 'OPEN' 0 -1 0.5 -1 0 0 / - 'WP1' 30 30 1 5 'OPEN' 0 -1 0.5 -1 0 0 / -/ - --- PRODUCTION WELL CONTROLS --- --- WELL OPEN/ CNTL OIL WATER GAS LIQU RES BHP.TARGET --- NAME SHUT MODE RATE RATE RATE RATE RATE PRESS --- sm3/day sm3/day sm3/day sm3/day rm3/day bar - --- USED IF THE WELL IS CONTROLED BY THE OIL RATE -WCONPROD - 'WP1' 'OPEN' 'LRAT' 3* 2000 1* 30 0 0 0 / --- 'WP2' 'OPEN' 'ORAT' 2000 4* 30 0 0 0 / --- 'WP3' 'OPEN' 'ORAT' 2000 4* 30 0 0 0 / --- 'WP4' 'OPEN' 'ORAT' 2000 4* 30 0 0 0 / -/ - --- INJECTION WELL CONTROLS --- --- WELL INJ OPEN/ CNTL FLOW BHP.TARGET --- NAME TYPE SHUT MODE RATE PRESS --- sm3/day bar -WCONINJE - 'WWI1' 'WAT' 'SHUT' 'RATE' 6000 1* 400 / -/ - - -RPTRST -BASIC=2 / - -DATES - 1 'FEB' 2004 / -/ ---END0001 - - -DATES - 1 'APR' 2005 / -/ ---END0002 - - -COMPDAT - 'WWI1' 1 1 1 5 'OPEN' 0 -1 0.5 -1 0 0 / - 'WP1' 30 30 1 5 'OPEN' 0 -1 0.5 -1 0 0 / -/ - - -WCONPROD - 'WP1' 'OPEN' 'LRAT' 3* 5500 1* 30 0 0 0 / - / -WCONINJE - 'WWI1' 'WAT' 'OPEN' 'RATE' 6000 1* 400 / -/ - - ---TSTEP ---5*91.3125 / ---456.5625 / -DATES - 1 'JUL' 2006 / -/ - ---END0003 - -COMPDAT - 'WWI1' 1 1 1 5 'OPEN' 0 -1 0.5 -1 0 0 / - 'WP1' 30 30 1 5 'OPEN' 0 -1 0.5 -1 0 0 / -/ - - ---TSTEP ---5*91.3125 / ---456.5625 / -DATES - 1 'OCT' 2007 / -/ ---END0004 - -COMPDAT - 'WWI1' 1 1 1 5 'OPEN' 0 -1 0.5 -1 0 0 / - 'WP1' 30 30 1 5 'OPEN' 0 -1 0.5 -1 0 0 / -/ - - ---TSTEP ---5*91.3125 / ---456.5625 / -DATES - 1 'JAN' 2009 / -/ ---END0005 - -COMPDAT - 'WWI1' 1 1 1 5 'OPEN' 0 -1 0.5 -1 0 0 / - 'WP1' 30 30 1 5 'OPEN' 0 -1 0.5 -1 0 0 / -/ - - ---TSTEP ---5*91.3125 / ---456.5625 / -DATES - 1 'APR' 2010 / -/ ---END0006 - -COMPDAT - 'WWI1' 1 1 1 5 'OPEN' 0 -1 0.5 -1 0 0 / - 'WP1' 30 30 1 5 'OPEN' 0 -1 0.5 -1 0 0 / -/ - - ---TSTEP ---91.3125 / ---456.5625 / -DATES - 1 'JUL' 2011 / -/ ---END0007 - -COMPDAT - 'WWI1' 1 1 1 5 'OPEN' 0 -1 0.5 -1 0 0 / - 'WP1' 30 30 1 5 'OPEN' 0 -1 0.5 -1 0 0 / -/ - ---TSTEP ---91.3125 / ---456.5625 / - -DATES - 1 'OCT' 2012 / -/ ---END0008 - -COMPDAT - 'WWI1' 1 1 1 5 'OPEN' 0 -1 0.5 -1 0 0 / - 'WP1' 30 30 1 5 'OPEN' 0 -1 0.5 -1 0 0 / -/ - ---TSTEP ---91.3125 / -DATES - 1 'JAN' 2013 / -/ ---END0009 - -END diff --git a/ThirdParty/Ert/libsched/src/well_history.c b/ThirdParty/Ert/libsched/src/well_history.c deleted file mode 100644 index 41f673a9dd..0000000000 --- a/ThirdParty/Ert/libsched/src/well_history.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'well_history.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - - -#define WELL_HISTORY_TYPE_ID 44431872 - - - /** - The following paradigm applies to the schedule files: - - o It is based on keywords which will apply until the next - occurence of the same keyword. - - o It is naturaly organized in blocks delimited by DATES / TSTEP - keywords. - - - Example - ------- - - DATES - 1 'JAN' 2000 / - - WCONHIST - 'OP_1' 'OPEN' 'ORAT' 7996.000 4.000 1.46402E+006 5* / - / - - DATES - 1 'FEB' 2000 / - - <--- What is the oil rate here? - - DATES - 1 'MAR' 2000 / - - - END - - - In this example an historical oil production rate of 7996 is - specified for immediately following the DATES keyword at - 1. 'JAN' - but what is the oil production rate at 15.th of - February? The point is that the 7996 rate applies until it is - set again, i.e. the DATES / TSTEP are not that suitable as block - units. - - - To support this behaviour the vector types from vector_template.c - are well suited; setting the default with - e.g. double_vector_set_default() will ascertain that the default - value is returned for all subsequent gets from the vector beyond - the set length. (That was clear ....) - -*/ - - - -struct well_history_struct { - UTIL_TYPE_ID_DECLARATION; - char * well_name; - int_vector_type * kw_type; /* This enum should be one of: NONE(default), WCONHIST , WCONINJE and WCONINJH (sched_kw_type_enum in sched_types.h). */ - size_t_vector_type * active_state; /* Contains pointer to the currently active of the xxx_state objects. The size_t_vector instance is abused to store pointer values (i.e. addresses). */ - wconhist_state_type * wconhist_state; - wconinje_state_type * wconinje_state; - wconinjh_state_type * wconinjh_state; - size_t_vector_type * parent; - bool_vector_type * well_open; -}; - - - -UTIL_SAFE_CAST_FUNCTION( well_history , WELL_HISTORY_TYPE_ID ) -static UTIL_SAFE_CAST_FUNCTION_CONST( well_history , WELL_HISTORY_TYPE_ID ) -UTIL_IS_INSTANCE_FUNCTION( well_history , WELL_HISTORY_TYPE_ID) - - -well_history_type * well_history_alloc( const char * well_name , const time_t_vector_type * time) { - well_history_type * well_history = util_malloc( sizeof * well_history ); - UTIL_TYPE_ID_INIT( well_history , WELL_HISTORY_TYPE_ID ); - well_history->well_name = util_alloc_string_copy( well_name ); - well_history->kw_type = int_vector_alloc(0 , NONE); - well_history->wconhist_state = wconhist_state_alloc( time ); - well_history->wconinje_state = wconinje_state_alloc( well_name , time ); - well_history->wconinjh_state = wconinjh_state_alloc( time ); - well_history->active_state = size_t_vector_alloc(0 , 0); - well_history->parent = size_t_vector_alloc(0 , 0); - well_history->well_open = bool_vector_alloc( 0 , false ); - return well_history; - } - - - -void well_history_set_parent( well_history_type * child_well , int report_step , const group_history_type * parent_group) { - size_t_vector_iset_default( child_well->parent , report_step , ( size_t ) parent_group); -} - -group_history_type * well_history_get_parent( well_history_type * child_well , int report_step ) { - return (group_history_type *) size_t_vector_safe_iget( child_well->parent , report_step ); -} - -void well_history_free( well_history_type * well_history ) { - free( well_history->well_name ); - int_vector_free( well_history->kw_type ); - wconhist_state_free( well_history->wconhist_state ); - wconinjh_state_free( well_history->wconinjh_state ); - wconinje_state_free( well_history->wconinje_state ); - size_t_vector_free( well_history->active_state ); - bool_vector_free( well_history->well_open ); - size_t_vector_free( well_history->parent ); - free( well_history ); -} - - -void well_history_free__( void * arg ) { - well_history_free( well_history_safe_cast( arg )); -} - - - - /*****************************************************************/ - - - - void well_history_add_keyword( well_history_type * well_history, const sched_kw_type * sched_kw , int report_step ) { - sched_kw_type_enum new_type = sched_kw_get_type( sched_kw ); - sched_kw_type_enum current_type = int_vector_safe_iget( well_history->kw_type , report_step ); - - if ((new_type != current_type) && (current_type != NONE)) { - /* - The well is changing type and we must "close" the current - status first. - */ - switch( current_type ) { - case( WCONHIST ): - sched_kw_wconhist_close_state( well_history->wconhist_state , report_step ); - break; - case( WCONINJH): - sched_kw_wconinjh_close_state( well_history->wconinjh_state , report_step ); - break; - case( WCONINJE): - sched_kw_wconinje_close_state( well_history->wconinje_state , report_step ); - break; - default: - break; - } - } - - int_vector_iset_default( well_history->kw_type , report_step , new_type ); - switch( new_type ) { - case(WCONHIST): - size_t_vector_iset_default( well_history->active_state , report_step , ( long ) well_history->wconhist_state ); - bool_vector_iset_default( well_history->well_open , report_step , sched_kw_wconhist_well_open( sched_kw_get_const_data( sched_kw ) , well_history->well_name )); - sched_kw_wconhist_update_state(sched_kw_get_const_data( sched_kw ) , well_history->wconhist_state , well_history->well_name , report_step ); - break; - case(WCONINJH): - size_t_vector_iset_default( well_history->active_state , report_step , ( long ) well_history->wconinjh_state ); - sched_kw_wconinjh_update_state(sched_kw_get_const_data( sched_kw ) , well_history->wconinjh_state , well_history->well_name , report_step ); - break; - case(WCONINJE): - size_t_vector_iset_default( well_history->active_state , report_step , ( long ) well_history->wconinje_state ); - bool_vector_iset_default( well_history->well_open , report_step , sched_kw_wconinje_well_open( sched_kw_get_const_data( sched_kw ) , well_history->well_name )); - sched_kw_wconinje_update_state(sched_kw_get_const_data( sched_kw ) , well_history->wconinje_state , well_history->well_name , report_step ); - break; - default: - break; - // Nothing wrong with this (I think) ?? - } - } - -/*****************************************************************/ - -wconhist_state_type * well_history_get_wconhist( well_history_type * well_history ) { - return well_history->wconhist_state; -} - -/*****************************************************************/ - - -sched_kw_type_enum well_history_iget_active_kw( const well_history_type * well_history , int report_step ) { - return int_vector_safe_iget( well_history->kw_type , report_step ); -} - - -const void * well_history_get_state_ptr( const well_history_type * well_history , sched_kw_type_enum kw_type ) { - switch( kw_type ) { - case(WCONHIST): - return well_history->wconhist_state; - break; - case(WCONINJH): - return well_history->wconinjh_state; - break; - case(WCONINJE): - return well_history->wconinje_state; - break; - default: - util_abort("%s: non-handled enum value \n",__func__); - return NULL; - } -} - - -const char * well_history_get_name( const well_history_type * well_history ) { - return well_history->well_name; -} - - -bool well_history_well_open( const well_history_type * well_history , int report_step ) { - return bool_vector_safe_iget( well_history->well_open , report_step ); -} - - - - - -double well_history_iget( well_index_type * index , int report_step ) { - const well_history_type * well_history = well_history_safe_cast_const( well_index_get_state( index )); - sched_kw_type_enum current_type = int_vector_safe_iget( well_history->kw_type , report_step ); - sched_history_callback_ftype * func = well_index_get_callback( index , current_type ); - - if (func != NULL) { - void * state_ptr = (void *) size_t_vector_safe_iget( well_history->active_state , report_step ); - return func( state_ptr , report_step ); - } else - return 0; /* Quite polite - just returning 0 for funny requests. */ -} - - - - -double well_history_iget_WOPRH( const well_history_type * well_history , int report_step ) { - sched_kw_type_enum current_type = int_vector_safe_iget( well_history->kw_type , report_step ); - if (current_type == WCONHIST) { - void * state_ptr = (void *) size_t_vector_safe_iget( well_history->active_state , report_step ); - return wconhist_state_iget_WOPRH( state_ptr , report_step ); - } else - return 0; /* If it is not in WCONHIST state we return 0 with no further ado. */ -} - - -double well_history_iget_WWPRH( const well_history_type * well_history , int report_step ) { - sched_kw_type_enum current_type = int_vector_safe_iget( well_history->kw_type , report_step ); - if (current_type == WCONHIST) { - void * state_ptr = (void *) size_t_vector_safe_iget( well_history->active_state , report_step ); - return wconhist_state_iget_WWPRH( state_ptr , report_step ); - } else - return 0; /* If it is not in WCONHIST state we return 0 with no further ado. */ -} - - -double well_history_iget_WGPRH( const well_history_type * well_history , int report_step ) { - sched_kw_type_enum current_type = int_vector_safe_iget( well_history->kw_type , report_step ); - if (current_type == WCONHIST) { - void * state_ptr = (void *) size_t_vector_safe_iget( well_history->active_state , report_step ); - return wconhist_state_iget_WGPRH( state_ptr , report_step ); - } else - return 0; /* If it is not in WCONHIST state we return 0 with no further ado. */ -} - - -bool well_history_is_producer( const well_history_type * well_history , int report_step ) { - bool producer = false; - sched_kw_type_enum current_type = int_vector_safe_iget( well_history->kw_type , report_step ); - switch( current_type ) { - case( WCONHIST ): - producer = true; - break; - case( WCONINJE) : - producer = false; - break; - case( WCONINJH ): - producer = false; - break; - default: - util_abort("%s: --- \n",__func__); - } - return producer; -} diff --git a/ThirdParty/Ert/libsched/src/well_index.c b/ThirdParty/Ert/libsched/src/well_index.c deleted file mode 100644 index d7d35a54e5..0000000000 --- a/ThirdParty/Ert/libsched/src/well_index.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - Copyright (C) 2011 Statoil ASA, Norway. - - The file 'well_index.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include -#include -#include - -#include -#include - - -#define WELL_INDEX_TYPE_ID 99780634 - -struct well_index_struct { - UTIL_TYPE_ID_DECLARATION; - const void * state_ptr; - char * well_name; - char * variable; /* Because many variables can be accessed both as eg WOPRH and WOPR the - variable might not match the name used when looking up this index. The - variable field should always contain the true historical (i.e. xxxxH) - variable, as that is the most correct way to access the values of the - schedule file. */ - int_vector_type * kw_type; - size_t_vector_type * func; -}; - - - - - -UTIL_IS_INSTANCE_FUNCTION( well_index , WELL_INDEX_TYPE_ID ) -UTIL_SAFE_CAST_FUNCTION_CONST( well_index , WELL_INDEX_TYPE_ID ) - - - -void well_index_add_type( well_index_type * index , sched_kw_type_enum kw_type , sched_history_callback_ftype * func) { - int_vector_append( index->kw_type , kw_type ); - size_t_vector_append( index->func , ( size_t ) func ); -} - - - -well_index_type * well_index_alloc( const char * well_name , const char * variable , const void * state_ptr , sched_kw_type_enum kw_type , sched_history_callback_ftype * func ) { - well_index_type * well_index = util_malloc( sizeof * well_index ); - - UTIL_TYPE_ID_INIT( well_index , WELL_INDEX_TYPE_ID ); - - well_index->well_name = util_alloc_string_copy( well_name ); - well_index->variable = util_alloc_string_copy( variable ); - well_index->kw_type = int_vector_alloc( 0 , 0 ); - well_index->func = size_t_vector_alloc( 0 , 0 ); - well_index->state_ptr = state_ptr; - - well_index_add_type( well_index , kw_type , func ); - return well_index; -} - - -void well_index_free( well_index_type * index ) { - size_t_vector_free( index->func ); - int_vector_free( index->kw_type ); - free( index->well_name ); - free( index->variable ); - free( index ); -} - - -void well_index_free__( void * arg ) { - well_index_free( (well_index_type *) arg ); -} - -const char * well_index_get_name( const well_index_type * well_index ) { - return well_index->well_name; -} - -const char * well_index_get_variable( const well_index_type * well_index ) { - return well_index->variable; -} - - - - -sched_history_callback_ftype * well_index_get_callback( const well_index_type * well_index , sched_kw_type_enum kw_type) { - sched_history_callback_ftype * func = NULL; - int iindex = 0; - while (true) { - if (int_vector_iget( well_index->kw_type , iindex) == kw_type) { - func = ( sched_history_callback_ftype *) size_t_vector_iget( well_index->func , iindex ); - break; - } - - - iindex++; - if (iindex == int_vector_size( well_index->kw_type )) - break; - } - - return func; -} - - - -const void * well_index_get_state( const well_index_type * well_index ) { - return well_index->state_ptr; -} - - - -const void * well_index_get_state__( const void * index ) { - const well_index_type * well_index = well_index_safe_cast_const( index ); - return well_index_get_state( well_index ); -} diff --git a/ThirdParty/Ert/libsched/tests/CMakeLists.txt b/ThirdParty/Ert/libsched/tests/CMakeLists.txt deleted file mode 100644 index 24d27ba2e2..0000000000 --- a/ThirdParty/Ert/libsched/tests/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -#add_executable( sched_load sched_load.c ) -#target_link_libraries( sched_load sched test_util ) -#add_test( sched_load ${EXECUTABLE_OUTPUT_PATH}/sched_load ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Heidrun/Schedule.sch ) - -#add_executable( sched_tokenize sched_tokenize.c ) -#target_link_libraries( sched_tokenize sched test_util ) -#add_test( sched_tokenize ${EXECUTABLE_OUTPUT_PATH}/sched_tokenize ${CMAKE_CURRENT_SOURCE_DIR}/test-data/token_test1 ) - -if (STATOIL_TESTDATA_ROOT) - add_executable( sched_history_summary sched_history_summary.c ) - target_link_libraries( sched_history_summary sched test_util ) - add_test( sched_history_summary1 ${EXECUTABLE_OUTPUT_PATH}/sched_history_summary ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE ) - add_test( sched_history_summary2 ${EXECUTABLE_OUTPUT_PATH}/sched_history_summary ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Snorre/SNORRE ) - - #set_property( TEST sched_load PROPERTY LABELS StatoilData) - set_property( TEST sched_history_summary1 PROPERTY LABELS StatoilData) - set_property( TEST sched_history_summary2 PROPERTY LABELS StatoilData) -endif() diff --git a/ThirdParty/Ert/libsched/tests/sched_history_summary.c b/ThirdParty/Ert/libsched/tests/sched_history_summary.c deleted file mode 100644 index 6f94d38d36..0000000000 --- a/ThirdParty/Ert/libsched/tests/sched_history_summary.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - Copyright (C) 2013 Statoil ASA, Norway. - - The file 'sched_history_summary.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ - -#include - -#include - -#include - -#include - - - -int main(int argc, char **argv) { - char * sum_case = argv[1]; - ecl_sum_type * refcase = ecl_sum_fread_alloc_case( sum_case , ":" ); - history_type * hist_h = history_alloc_from_refcase( refcase , true ); - history_type * hist_sim = history_alloc_from_refcase( refcase , false ); - - test_assert_true( history_is_instance( hist_h ) ); - test_assert_true( history_is_instance( hist_sim ) ); - test_assert_int_equal( history_get_last_restart( hist_sim ) , ecl_sum_get_last_report_step( refcase ) ); - test_assert_int_equal( history_get_last_restart( hist_h ) , ecl_sum_get_last_report_step( refcase ) ); - - { - double_vector_type * value_sim = double_vector_alloc(0 , 0); - double_vector_type * value_h = double_vector_alloc(0 , 0); - bool_vector_type * valid_sim = bool_vector_alloc( 0 , false ); - bool_vector_type * valid_h = bool_vector_alloc( 0 , false ); - - test_assert_true( history_init_ts( hist_sim , "FOPT" , value_sim , valid_sim )); - test_assert_true( history_init_ts( hist_h , "FOPT" , value_h , valid_h )); - { - int step; - for (step = 1; step < ecl_sum_get_last_report_step( refcase ); step++) { - test_assert_true( bool_vector_iget( valid_sim , step )); - test_assert_true( bool_vector_iget( valid_h , step )); - { - int time_index = ecl_sum_iget_report_end( refcase , step ); - test_assert_double_equal( ecl_sum_get_general_var( refcase , time_index , "FOPT" ) , double_vector_iget( value_sim , step )); - test_assert_double_equal( ecl_sum_get_general_var( refcase , time_index , "FOPTH" ) , double_vector_iget( value_h , step )); - } - } - } - bool_vector_free( valid_sim ); - bool_vector_free( valid_h ); - - double_vector_free( value_sim ); - double_vector_free( value_h ); - } - - - history_free( hist_h ); - history_free( hist_sim ); - ecl_sum_free( refcase ); - exit(0); -} diff --git a/ThirdParty/Ert/python/CMakeLists.txt b/ThirdParty/Ert/python/CMakeLists.txt index a032f3141c..954db0c30c 100644 --- a/ThirdParty/Ert/python/CMakeLists.txt +++ b/ThirdParty/Ert/python/CMakeLists.txt @@ -1,5 +1,5 @@ include(cmake/find_python_module.cmake) -include(cmake/python_module_versions.cmake) # finds version +include(cmake/python_package_versions.cmake) # finds version FIND_PACKAGE(PythonInterp 2.7 EXACT) if (NOT DEFINED PYTHON_EXECUTABLE) @@ -8,23 +8,12 @@ if (NOT DEFINED PYTHON_EXECUTABLE) endif() -python_module(numpy 1.7.1) +python_package(numpy 1.7.1) if (NOT DEFINED PY_numpy) message("numpy module not found - Python wrappers not enabled") return() endif() - -if (ERT_BUILD_GUI) - python_module(PyQt4 4.8.0) - if(NOT DEFINED PY_PyQt4) - message(SEND_ERROR "Cannot build GUI without PyQt4") - endif() - python_module( matplotlib 1.2.0 ) - python_module( pandas 0.15.1 ) - python_module( scipy 0.16.1 ) -endif() - if (EXISTS "/etc/debian_version") set( PYTHON_PACKAGE_PATH "dist-packages") else() diff --git a/ThirdParty/Ert/python/cmake/python_module_versions.cmake b/ThirdParty/Ert/python/cmake/python_module_versions.cmake deleted file mode 100644 index e34f9f8407..0000000000 --- a/ThirdParty/Ert/python/cmake/python_module_versions.cmake +++ /dev/null @@ -1,40 +0,0 @@ -# try import python module, if success, check its version, store as PY_module. -# the module is imported as-is, hence the case (e.g. PyQt4) must be correct. -function(python_module_version module) - set(PY_VERSION_ACCESSOR "__version__") - set(PY_module_name ${module}) - - if(${module} MATCHES "PyQt4") - set(PY_module_name "PyQt4.Qt") - set(PY_VERSION_ACCESSOR "PYQT_VERSION_STR") - endif() - - execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "import ${PY_module_name} as py_m; print(py_m.${PY_VERSION_ACCESSOR})" - RESULT_VARIABLE _${module}_fail# error code 0 if success - OUTPUT_VARIABLE _${module}_version# major.minor.patch - ERROR_VARIABLE stderr_output - OUTPUT_STRIP_TRAILING_WHITESPACE) - - if(NOT _${module}_fail) - set(PY_${module} ${_${module}_version})# local scope, for message - set(PY_${module} ${_${module}_version} PARENT_SCOPE) - endif() -endfunction() - - -# If we find the correct module and new enough version, set PY_package, where -# "package" is the given argument to the version we found else, display warning -# and do not set any variables. -function(python_module package version) - python_module_version(${package}) - - if(NOT DEFINED PY_${package}) - message("Could not find Python module " ${package}) - elseif(${PY_${package}} VERSION_LESS ${version}) - message(WARNING "Python module ${package} too old. " - "Wanted ${version}, found ${PY_${package}}") - else() - message(STATUS "Found ${package}. ${PY_${package}} >= ${version}") - set(PY_${package} ${version} PARENT_SCOPE) - endif() -endfunction() diff --git a/ThirdParty/Ert/python/cmake/python_package_versions.cmake b/ThirdParty/Ert/python/cmake/python_package_versions.cmake new file mode 100644 index 0000000000..309a8f679d --- /dev/null +++ b/ThirdParty/Ert/python/cmake/python_package_versions.cmake @@ -0,0 +1,46 @@ +# try import python module, if success, check its version, store as PY_module. +# the module is imported as-is, hence the case (e.g. PyQt4) must be correct. +function(python_package_version package) + set(PY_VERSION_ACCESSOR "__version__") + set(PY_package_name ${package}) + + if(${package} MATCHES "PyQt4") + set(PY_package_name "PyQt4.Qt") + set(PY_VERSION_ACCESSOR "PYQT_VERSION_STR") + endif() + + execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "import os.path; import inspect; import ${PY_package_name} as py_m; print(\"%s;%s\" % (py_m.${PY_VERSION_ACCESSOR} , os.path.dirname(os.path.dirname(inspect.getfile(py_m)))))" + RESULT_VARIABLE _${package}_fail# error code 0 if success + OUTPUT_VARIABLE stdout_output # major.minor.patch + ERROR_VARIABLE stderr_output + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(NOT _${package}_fail) + list(GET stdout_output 0 version) + set(PY_${package} ${version}) # local scope, for message + set(PY_${package} ${version} PARENT_SCOPE) + + list(GET stdout_output 1 path) + set(PY_${package}_PATH ${path}) # local scope, for message + set(PY_${package}_PATH ${path} PARENT_SCOPE) + endif() +endfunction() + + +# If we find the correct module and new enough version, set PY_package, where +# "package" is the given argument to the version we found else, display warning +# and do not set any variables. +function(python_package package version) + python_package_version(${package}) + + if(NOT DEFINED PY_${package}) + message("Could not find Python package " ${package}) + elseif(${PY_${package}} VERSION_LESS ${version}) + message(WARNING "Python package ${package} too old. " + "Wanted ${version}, found ${PY_${package}}") + else() + message(STATUS "Found ${package}. ${PY_${package}} >= ${version} in ${PY_${package}_PATH}") + set(PY_${package} ${version} PARENT_SCOPE) + set(PY_${package}_PATH ${PY_${package}_PATH} PARENT_SCOPE) + endif() +endfunction() diff --git a/ThirdParty/Ert/python/python/CMakeLists.txt b/ThirdParty/Ert/python/python/CMakeLists.txt index bf7bce2091..7c82391422 100644 --- a/ThirdParty/Ert/python/python/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/CMakeLists.txt @@ -1,8 +1,5 @@ +configure_file(test_env.py.in ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/test_env.py ) + add_subdirectory(cwrap) add_subdirectory( ert ) -if (BUILD_ERT) - if (ERT_BUILD_GUI) - add_subdirectory( ert_gui ) - endif() -endif() add_subdirectory( bin ) diff --git a/ThirdParty/Ert/python/python/bin/CMakeLists.txt b/ThirdParty/Ert/python/python/bin/CMakeLists.txt new file mode 100644 index 0000000000..0410f2a073 --- /dev/null +++ b/ThirdParty/Ert/python/python/bin/CMakeLists.txt @@ -0,0 +1,24 @@ +if (BUILD_ERT) + set(application_list + ert_tcp_server + ertshell + ert_upgrade_fs107 + ) + foreach(prog ${application_list} ) + file(COPY ${prog} DESTINATION ${EXECUTABLE_OUTPUT_PATH}) + endforeach() +endif() + + + +if (INSTALL_ERT) + set (destination ${CMAKE_INSTALL_PREFIX}/bin) + foreach(prog ${application_list} ) + install(PROGRAMS ${prog} DESTINATION ${destination}) + if (INSTALL_GROUP) + install(CODE "EXECUTE_PROCESS(COMMAND chgrp ${INSTALL_GROUP} ${destination}/${prog})") + install(CODE "EXECUTE_PROCESS(COMMAND chmod g+w ${destination}/${prog})") + endif() + endforeach() +endif() + diff --git a/ThirdParty/Ert/python/python/bin/ert_tcp_server b/ThirdParty/Ert/python/python/bin/ert_tcp_server new file mode 100644 index 0000000000..caa75d9da7 --- /dev/null +++ b/ThirdParty/Ert/python/python/bin/ert_tcp_server @@ -0,0 +1,53 @@ +#!/usr/bin/env python +import argparse +import socket +import sys + +from ert.server.ertrpcserver import ErtRPCServer + +default_port = 0 + +parser = argparse.ArgumentParser() + +parser.add_argument("--port", type=int, default=default_port, dest="port") +parser.add_argument("--host", default=socket.gethostname(), dest="host") +parser.add_argument("--localhost", default=False, action="store_true", dest="localhost") +parser.add_argument("--log-file", default="ert-server.log", dest="log_file") +parser.add_argument("--log-level", type=int, default=1, dest="log_level") +parser.add_argument("config_file") + +args = parser.parse_args() + +config_file = args.config_file +port = args.port +log_level = args.log_level + + +# By default the server will bind with the publicly available hostname +# socket.gethostname() - meaning that clients can connect from +# anywhere, but by using the --localhost switch the server can be +# instructed to only accept connections from localhost. +# +# On some computers the socket.gethostname() will not include the +# domain name; that will not work and we exit the server and ask the +# user to supply the full hostname using --host. + +if args.localhost: + host = "localhost" +else: + host = args.host + if host.count(".") == 0: + sys.exit("Sorry - could not determine FQDN for server - use the --host option to supply.") + +server = ErtRPCServer(config_file, host, port, log_requests=log_level > 1, verbose_queue=True) + +try: + print("ERT Server running on port: %d at host: %s" % (server.port, host)) + server.start() +except KeyboardInterrupt: + try: + server.stop() + print("ERT Server 'smoothly' killed the running jobs") + except Exception as e: + print("Unable to stop server 'gracefully'!") + raise e diff --git a/ThirdParty/Ert/python/python/bin/ert_upgrade_fs107 b/ThirdParty/Ert/python/python/bin/ert_upgrade_fs107 new file mode 100644 index 0000000000..4374b5dcfc --- /dev/null +++ b/ThirdParty/Ert/python/python/bin/ert_upgrade_fs107 @@ -0,0 +1,76 @@ +#!/usr/bin/env python +import sys +import os +import os.path + +from ert.config import ConfigParser, ContentTypeEnum, UnrecognizedEnum +from ert.enkf import TimeMap,EnkfFs +from ert.ecl import EclSum + +#TimeMap._upgrade107 = + + +def parse(config_file): + parser = ConfigParser( ) + item = parser.add("REFCASE", False ) + item.iset_type(0 , ContentTypeEnum.CONFIG_PATH ) + + item = parser.add("ENSPATH" , False ) + item.iset_type(0 , ContentTypeEnum.CONFIG_EXISTING_PATH ) + + content = parser.parse( config_file , unrecognized = UnrecognizedEnum.CONFIG_UNRECOGNIZED_IGNORE ) + if "REFCASE" in content: + refcase = EclSum( content.getValue( "REFCASE" )) + else: + refcase = None + + if "ENSPATH" in content: + path = content["ENSPATH"] + enspath = path[0].getPath( ) + else: + enspath = "storage" + + + return enspath , refcase + + +def upgrade(ens_path, refcase): + for case in os.listdir( ens_path ): + full_case = os.path.join( ens_path , case ) + if os.path.isdir( full_case ): + version = EnkfFs.diskVersion( full_case ) + try: + version = EnkfFs.diskVersion( full_case ) + except IOError: + print "The case:%s was ignored" % full_case + continue + + if version < 105: + print "Very old case: %s ignored - you should probably delete this" % full_case + continue + + if version < 107: + print "Upgrading %s to version 107" % full_case + + time_map_file = os.path.join( full_case , "files/time-map") + if os.path.isfile( time_map_file ): + time_map = TimeMap( time_map_file) + assert( isinstance( refcase , EclSum )) + time_map.upgrade107( refcase ) + time_map.fwrite( time_map_file ) + else: + print "No time-map file found" + + EnkfFs.updateVersion( full_case, version , 107 ) + fs = EnkfFs( full_case ) + + +if len(sys.argv) != 2: + sys.exit("Script must have exactly one argument: config_file") + +config_file = sys.argv[1] +ens_path , refcase = parse( config_file ) +if refcase: + print "Upgrading storage:%s with refcase:%s" % (ens_path , refcase.case ) +upgrade( ens_path , refcase ) + diff --git a/ThirdParty/Ert/python/python/bin/ertshell b/ThirdParty/Ert/python/python/bin/ertshell new file mode 100644 index 0000000000..e8d53e0a63 --- /dev/null +++ b/ThirdParty/Ert/python/python/bin/ertshell @@ -0,0 +1,35 @@ +#!/usr/bin/env python +import os +from PyQt4.QtGui import QApplication +import sys + +import ert_gui +from ert_gui.ertwidgets import resourceIcon +from ert_gui.shell import ErtShell +from ert_gui.tools import HelpCenter + + +if __name__ == '__main__': + if os.getenv("ERT_SHARE_PATH"): + ert_share_path = os.getenv("ERT_SHARE_PATH") + else: + ert_share_path = os.path.realpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../../share")) + + ert_gui.ertwidgets.img_prefix = ert_share_path + "/gui/img/" + + help_center = HelpCenter("ERT") + help_center.setHelpLinkPrefix(os.getenv("ERT_SHARE_PATH") + "/gui/help/") + + + app = QApplication(sys.argv) + app.setWindowIcon(resourceIcon("application/window_icon_cutout")) + + ert_shell = ErtShell() + if len(sys.argv) > 1: + ert_shell.onecmd('load_config %s' % sys.argv[1]) + + if len(sys.argv) > 2: + for workflow in sys.argv[2:]: + ert_shell.onecmd('workflows run %s' % workflow) + + ert_shell.cmdloop() \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/cwrap/basecclass.py b/ThirdParty/Ert/python/python/cwrap/basecclass.py index 3f7e008fb0..306a8375bd 100644 --- a/ThirdParty/Ert/python/python/cwrap/basecclass.py +++ b/ThirdParty/Ert/python/python/cwrap/basecclass.py @@ -14,16 +14,20 @@ # See the GNU General Public License at # for more details. +from __future__ import (absolute_import, division, + print_function, unicode_literals) + +import six + import ctypes from .metacwrap import MetaCWrap +@six.add_metaclass(MetaCWrap) class BaseCClass(object): - __metaclass__ = MetaCWrap - namespaces = {} def __init__(self, c_pointer, parent=None, is_reference=False): - if c_pointer == 0 or c_pointer is None: + if not c_pointer: raise ValueError("Must have a valid (not null) pointer value!") if c_pointer < 0: @@ -47,13 +51,6 @@ class BaseCClass(object): def _ad_str(self): return 'at 0x%x' % self._address() - @classmethod - def cNamespace(cls): - """ @rtype: CNamespace """ - if cls not in BaseCClass.namespaces: - BaseCClass.namespaces[cls] = CNamespace(cls.__name__) - return BaseCClass.namespaces[cls] - @classmethod def from_param(cls, c_class_object): if c_class_object is not None and not isinstance(c_class_object, BaseCClass): @@ -136,7 +133,7 @@ class BaseCClass(object): if not self.__is_reference: # Important to check the c_pointer; in the case of failed object creation # we can have a Python object with c_pointer == None. - if self.__c_pointer > 0: + if self.__c_pointer: self.free() def _invalidateCPointer(self): diff --git a/ThirdParty/Ert/python/python/cwrap/basecenum.py b/ThirdParty/Ert/python/python/cwrap/basecenum.py index df4ff8b1df..b86e1b0d64 100644 --- a/ThirdParty/Ert/python/python/cwrap/basecenum.py +++ b/ThirdParty/Ert/python/python/cwrap/basecenum.py @@ -14,12 +14,15 @@ # See the GNU General Public License at # for more details. +from __future__ import absolute_import, division, print_function, unicode_literals + +import six + import ctypes from .metacwrap import MetaCWrap - +@six.add_metaclass(MetaCWrap) class BaseCEnum(object): - __metaclass__ = MetaCWrap enum_namespace = {} def __init__(self, *args, **kwargs): @@ -48,6 +51,7 @@ class BaseCEnum(object): @classmethod def addEnum(cls, name, value): + name = str(name) if not isinstance(value, int): raise ValueError("Value must be an integer!") diff --git a/ThirdParty/Ert/python/python/cwrap/basecvalue.py b/ThirdParty/Ert/python/python/cwrap/basecvalue.py index f5711c5a63..2c9f582792 100644 --- a/ThirdParty/Ert/python/python/cwrap/basecvalue.py +++ b/ThirdParty/Ert/python/python/cwrap/basecvalue.py @@ -14,13 +14,18 @@ # See the GNU General Public License at # for more details. -from ctypes import pointer, c_long, c_int, c_bool, c_float, c_double, c_byte, \ - c_short, c_char, c_ubyte, c_ushort, c_uint, c_ulong +from __future__ import (absolute_import, division, + print_function, unicode_literals) + +import six + +from ctypes import (pointer, c_long, c_int, c_bool, c_float, c_double, c_byte, + c_short, c_char, c_ubyte, c_ushort, c_uint, c_ulong) from .metacwrap import MetaCWrap +@six.add_metaclass(MetaCWrap) class BaseCValue(object): - __metaclass__ = MetaCWrap DATA_TYPE = None LEGAL_TYPES = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, c_long, c_ulong, c_bool, c_char, c_float, c_double] diff --git a/ThirdParty/Ert/python/python/cwrap/cfile.py b/ThirdParty/Ert/python/python/cwrap/cfile.py index 69344bd165..f687a3e060 100644 --- a/ThirdParty/Ert/python/python/cwrap/cfile.py +++ b/ThirdParty/Ert/python/python/cwrap/cfile.py @@ -15,7 +15,8 @@ # for more details. import ctypes -from .prototype import Prototype +import six +from .prototype import Prototype, PrototypeError from .basecclass import BaseCClass class CFILE(BaseCClass): diff --git a/ThirdParty/Ert/python/python/cwrap/metacwrap.py b/ThirdParty/Ert/python/python/cwrap/metacwrap.py index 21ece69391..52ccb970ce 100644 --- a/ThirdParty/Ert/python/python/cwrap/metacwrap.py +++ b/ThirdParty/Ert/python/python/cwrap/metacwrap.py @@ -14,6 +14,10 @@ # See the GNU General Public License at # for more details. +from __future__ import (absolute_import, division, + print_function, unicode_literals) +import six + import re from types import MethodType @@ -59,4 +63,5 @@ class MetaCWrap(type): if attr.shouldBeBound(): method = MethodType(attr, None, cls) + #method = six.create_bound_method(attr, cls) setattr(cls, key, method) diff --git a/ThirdParty/Ert/python/python/ert/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/CMakeLists.txt index 708c201d2d..f6ccc6a6b0 100644 --- a/ThirdParty/Ert/python/python/ert/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/ert/CMakeLists.txt @@ -9,22 +9,6 @@ add_subdirectory(test) add_subdirectory(util) add_subdirectory(well) -IF (BUILD_ERT) - set( ERT_SITE_INIT_TARGET "" CACHE FILE "Name of optional external site init module for top level ert package") - if (EXISTS ${ERT_SITE_INIT_TARGET}) - message(STATUS "Using ert site init module: ${ERT_SITE_INIT_TARGET}") - install(FILES ${ERT_SITE_INIT_TARGET} DESTINATION ${PYTHON_INSTALL_PREFIX}/ert RENAME ert_site_init.py) - endif() - add_subdirectory(analysis) - add_subdirectory(config) - add_subdirectory(enkf) - add_subdirectory(job_queue) - add_subdirectory(rms) - add_subdirectory(sched) - add_subdirectory(server) -ENDIF() - - configure_file(ert_lib_info_build.py.in ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ert/__ert_lib_info.py ) configure_file(ert_lib_info_install.py.in ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ert_lib_info_install.py ) install(FILES ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ert_lib_info_install.py DESTINATION ${PYTHON_INSTALL_PREFIX}/ert RENAME __ert_lib_info.py) diff --git a/ThirdParty/Ert/python/python/ert/__init__.py b/ThirdParty/Ert/python/python/ert/__init__.py index 737a77b205..9b6111b954 100644 --- a/ThirdParty/Ert/python/python/ert/__init__.py +++ b/ThirdParty/Ert/python/python/ert/__init__.py @@ -57,7 +57,10 @@ before giving up completely. """ import os.path import sys + import warnings +warnings.simplefilter('always', DeprecationWarning) # see #1437 + from cwrap import load as cwrapload try: diff --git a/ThirdParty/Ert/python/python/ert/analysis/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/analysis/CMakeLists.txt deleted file mode 100644 index 5f20dd0a2a..0000000000 --- a/ThirdParty/Ert/python/python/ert/analysis/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - analysis_module.py - linalg.py -) - -add_python_package("python.ert.analysis." ${PYTHON_INSTALL_PREFIX}/ert/analysis/ "${PYTHON_SOURCES}" True) - -add_subdirectory(enums) diff --git a/ThirdParty/Ert/python/python/ert/analysis/__init__.py b/ThirdParty/Ert/python/python/ert/analysis/__init__.py deleted file mode 100644 index 58bae50467..0000000000 --- a/ThirdParty/Ert/python/python/ert/analysis/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file '__init__.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -import ert -from cwrap import Prototype -import ert.util - -class AnalysisPrototype(Prototype): - lib = ert.load("libanalysis") - - def __init__(self, prototype, bind=True): - super(AnalysisPrototype, self).__init__(AnalysisPrototype.lib, prototype, bind=bind) - - - -ANALYSIS_LIB = ert.load("libanalysis") - -from .enums import AnalysisModuleOptionsEnum, AnalysisModuleLoadStatusEnum - -from .analysis_module import AnalysisModule -from .linalg import Linalg diff --git a/ThirdParty/Ert/python/python/ert/analysis/analysis_module.py b/ThirdParty/Ert/python/python/ert/analysis/analysis_module.py deleted file mode 100644 index f73d0380a4..0000000000 --- a/ThirdParty/Ert/python/python/ert/analysis/analysis_module.py +++ /dev/null @@ -1,188 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'analysis_module.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCClass -from ert.util.rng import RandomNumberGenerator -from ert.analysis import AnalysisPrototype - -from ert.util import Matrix - -class AnalysisModule(BaseCClass): - TYPE_NAME = "analysis_module" - - _alloc_external = AnalysisPrototype("void* analysis_module_alloc_external(rng, char*)" , bind = False) - _alloc_internal = AnalysisPrototype("void* analysis_module_alloc_internal(rng, char*)" , bind = False) - _free = AnalysisPrototype("void analysis_module_free(analysis_module)") - _get_lib_name = AnalysisPrototype("char* analysis_module_get_lib_name(analysis_module)") - _get_module_internal = AnalysisPrototype("bool analysis_module_internal(analysis_module)") - _set_var = AnalysisPrototype("bool analysis_module_set_var(analysis_module, char*, char*)") - _get_table_name = AnalysisPrototype("char* analysis_module_get_table_name(analysis_module)") - _get_name = AnalysisPrototype("char* analysis_module_get_name(analysis_module)") - _check_option = AnalysisPrototype("bool analysis_module_check_option(analysis_module, long)") - _has_var = AnalysisPrototype("bool analysis_module_has_var(analysis_module, char*)") - _get_double = AnalysisPrototype("double analysis_module_get_double(analysis_module, char*)") - _get_int = AnalysisPrototype("int analysis_module_get_int(analysis_module, char*)") - _get_bool = AnalysisPrototype("bool analysis_module_get_bool(analysis_module, char*)") - _get_str = AnalysisPrototype("char* analysis_module_get_ptr(analysis_module, char*)") - _init_update = AnalysisPrototype("void analysis_module_init_update(analysis_module, bool_vector , matrix , matrix , matrix , matrix, matrix)") - _updateA = AnalysisPrototype("void analysis_module_updateA(analysis_module, matrix , matrix , matrix , matrix, matrix, matrix, void*)") - _initX = AnalysisPrototype("void analysis_module_initX(analysis_module, matrix , matrix , matrix , matrix , matrix, matrix, matrix)") - - - # The VARIABLE_NAMES field is a completly broken special case - # which only applies to the rml module. - VARIABLE_NAMES = { - "LAMBDA0": {"type": float, "description": "Initial Lambda"}, - "USE_PRIOR": {"type": bool, "description": "Use both Prior and Observation Variability"}, - "LAMBDA_REDUCE": {"type": float, "description": "Lambda Reduction Factor"}, - "LAMBDA_INCREASE": {"type": float, "description": "Lambda Incremental Factor"}, - "LAMBDA_MIN": {"type": float, "description": "Minimum Lambda"}, - "LOG_FILE": {"type": str, "description": "Log File"}, - "CLEAR_LOG": {"type": bool, "description": "Clear Existing Log File"}, - "LAMBDA_RECALCULATE": {"type": bool, "description": "Recalculate Lambda after each Iteration"}, - "ENKF_TRUNCATION": {"type": float, "description": "Singular value truncation"}, - "ENKF_NCOMP": {"type": int, "description": "ENKF_NCOMP"}, - "CV_NFOLDS": {"type": int, "description": "CV_NFOLDS"}, - "FWD_STEP_R2_LIMIT": {"type": float, "description": "FWD_STEP_R2_LIMIT"}, - "CV_PEN_PRESS": {"type": bool, "description": "CV_PEN_PRESS"} - } - - def __init__(self, rng , name = None , lib_name = None): - if name is None and lib_name is None: - raise ValueError("Must supply exactly one of lib or lib_name") - - if name and lib_name: - raise ValueError("Must supply exactly one of name or lib_name") - - if lib_name: - c_ptr = self._alloc_external(rng, lib_name ) - else: - c_ptr = self._alloc_internal( rng , name ) - if not c_ptr: - raise KeyError("Failed to load internal module:%s" % name) - - super(AnalysisModule, self).__init__(c_ptr) - - - def getVariableNames(self): - """ @rtype: list of str """ - items = [] - for name in AnalysisModule.VARIABLE_NAMES: - if self.hasVar(name): - items.append(name) - return items - - def getVariableValue(self, name): - """ @rtype: int or float or bool or str """ - variable_type = self.getVariableType(name) - if variable_type == float: - return self.getDouble(name) - elif variable_type == bool: - return self.getBool(name) - elif variable_type == str: - return self.getStr(name) - elif variable_type == int: - return self.getInt(name) - - def getVariableType(self, name): - """ :rtype: type """ - return AnalysisModule.VARIABLE_NAMES[name]["type"] - - def getVariableDescription(self, name): - """ :rtype: str """ - return AnalysisModule.VARIABLE_NAMES[name]["description"] - - def getVar(self, name): - return self.getVariableValue( name ) - - def free(self): - self._free( ) - - def __repr__(self): - nm = self.name() - tn = self.getTableName() - ln = self.getLibName() - mi = 'internal' if self.getInternal() else 'external' - ad = self._ad_str() - fmt = 'AnalysisModule(name = %s, table = %s, lib = %s, %s) %s' - return fmt % (nm, tn, ln, mi, ad) - - def getLibName(self): - return self._get_lib_name( ) - - def getInternal(self): - return self._get_module_internal( ) - - def __assertVar(self , var_name): - if not self.hasVar(var_name): - raise KeyError("Module does not support key:%s" % var_name) - - def setVar(self, var_name, value): - self.__assertVar( var_name ) - string_value = str(value) - return self._set_var(var_name, string_value) - - - def getTableName(self): - return self._get_table_name( ) - - def getName(self): - """ :rtype: str """ - return self.name() - - def name(self): - return self._get_name( ) - - def checkOption(self, flag): - return self._check_option(flag) - - def hasVar(self, var): - """ :rtype: bool """ - return self._has_var(var) - - def getDouble(self, var): - """ :rtype: float """ - self.__assertVar( var ) - return self._get_double(var) - - def getInt(self, var): - """ :rtype: int """ - self.__assertVar( var ) - return self._get_int(var) - - def getBool(self, var): - """ :rtype: bool """ - self.__assertVar( var ) - return self._get_bool(var) - - def getStr(self, var): - """ :rtype: str """ - self.__assertVar( var ) - return self._get_str(var) - - - def initUpdate(self, mask, S, R, dObs, E, D): - self._init_update(mask, S, R, dObs, E, D) - - - def updateA(self, A, S, R, dObs, E, D): - self._updateA(A, S, R, dObs, E, D, None) - - - def initX(self, A, S, R, dObs, E, D): - X = Matrix( A.columns() , A.columns()) - self._initX(X, A, S, R, dObs, E, D) - return X diff --git a/ThirdParty/Ert/python/python/ert/analysis/enums/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/analysis/enums/CMakeLists.txt deleted file mode 100644 index 55b145c74b..0000000000 --- a/ThirdParty/Ert/python/python/ert/analysis/enums/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - analysis_module_options_enum.py - analysis_module_load_status_enum.py -) - -add_python_package("python.ert.analysis.enums" ${PYTHON_INSTALL_PREFIX}/ert/analysis/enums "${PYTHON_SOURCES}" True) - - - diff --git a/ThirdParty/Ert/python/python/ert/analysis/enums/__init__.py b/ThirdParty/Ert/python/python/ert/analysis/enums/__init__.py deleted file mode 100644 index fecedb4bc1..0000000000 --- a/ThirdParty/Ert/python/python/ert/analysis/enums/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .analysis_module_options_enum import AnalysisModuleOptionsEnum -from .analysis_module_load_status_enum import AnalysisModuleLoadStatusEnum - diff --git a/ThirdParty/Ert/python/python/ert/analysis/enums/analysis_module_load_status_enum.py b/ThirdParty/Ert/python/python/ert/analysis/enums/analysis_module_load_status_enum.py deleted file mode 100644 index 285b85aa8b..0000000000 --- a/ThirdParty/Ert/python/python/ert/analysis/enums/analysis_module_load_status_enum.py +++ /dev/null @@ -1,35 +0,0 @@ - -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'analysis_module_load_status_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -from cwrap import BaseCEnum -from ert.analysis import ANALYSIS_LIB - - -class AnalysisModuleLoadStatusEnum(BaseCEnum): - TYPE_NAME = "analysis_module_load_status_enum" - LOAD_OK = None - DLOPEN_FAILURE = None - LOAD_SYMBOL_TABLE_NOT_FOUND = None - -AnalysisModuleLoadStatusEnum.addEnum("LOAD_OK", 0) -AnalysisModuleLoadStatusEnum.addEnum("DLOPEN_FAILURE", 1) -AnalysisModuleLoadStatusEnum.addEnum("LOAD_SYMBOL_TABLE_NOT_FOUND", 2) - - - - diff --git a/ThirdParty/Ert/python/python/ert/analysis/enums/analysis_module_options_enum.py b/ThirdParty/Ert/python/python/ert/analysis/enums/analysis_module_options_enum.py deleted file mode 100644 index 7a5e35c4f6..0000000000 --- a/ThirdParty/Ert/python/python/ert/analysis/enums/analysis_module_options_enum.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'analysis_module_options_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum -from ert.analysis import ANALYSIS_LIB - - -class AnalysisModuleOptionsEnum(BaseCEnum): - TYPE_NAME = "analysis_module_options_enum" - ANALYSIS_NEED_ED = None - ANALYSIS_USE_A = None - ANALYSIS_UPDATE_A = None - ANALYSIS_SCALE_DATA = None - ANALYSIS_ITERABLE = None - -AnalysisModuleOptionsEnum.addEnum("ANALYSIS_NEED_ED" , 1) -AnalysisModuleOptionsEnum.addEnum("ANALYSIS_USE_A" , 4) -AnalysisModuleOptionsEnum.addEnum("ANALYSIS_UPDATE_A" , 8) -AnalysisModuleOptionsEnum.addEnum("ANALYSIS_SCALE_DATA" , 16) -AnalysisModuleOptionsEnum.addEnum("ANALYSIS_ITERABLE" , 32) - - - - diff --git a/ThirdParty/Ert/python/python/ert/analysis/linalg.py b/ThirdParty/Ert/python/python/ert/analysis/linalg.py deleted file mode 100644 index 35782dfcd8..0000000000 --- a/ThirdParty/Ert/python/python/ert/analysis/linalg.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'linalg.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCClass -from ert.analysis import AnalysisPrototype - - -__all__ = ["numPC"] - -class Linalg(BaseCClass): - """ - The linalg class is a purely static class which mainly serves as a - namespace for a collection of ensemble based linear algebra - methods. - """ - _get_num_PC = AnalysisPrototype("int enkf_linalg_num_PC( matrix , double)" , bind = False) - - @staticmethod - def numPC(S , truncation): - if 0 < truncation <= 1: - return Linalg._get_num_PC( S , truncation ) - else: - raise ValueError("truncation must be in the interval (0,1]") - diff --git a/ThirdParty/Ert/python/python/ert/config/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/config/CMakeLists.txt deleted file mode 100644 index b0dcd2bb79..0000000000 --- a/ThirdParty/Ert/python/python/ert/config/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - schema_item.py - config_error.py - config_parser.py - config_content.py - config_settings.py - content_type_enum.py - unrecognized_enum.py -) - -add_python_package("python.ert.config" ${PYTHON_INSTALL_PREFIX}/ert/config "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/config/__init__.py b/ThirdParty/Ert/python/python/ert/config/__init__.py deleted file mode 100644 index c17a9349b9..0000000000 --- a/ThirdParty/Ert/python/python/ert/config/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file '__init__.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import Prototype -import ert -import ert.util - -class ConfigPrototype(Prototype): - lib = ert.load("libconfig") - - def __init__(self, prototype, bind=True): - super(ConfigPrototype, self).__init__(ConfigPrototype.lib, prototype, bind=bind) - -from .unrecognized_enum import UnrecognizedEnum -from .content_type_enum import ContentTypeEnum -from .config_error import ConfigError -from .schema_item import SchemaItem -from .config_content import ConfigContent , ContentItem, ContentNode -from .config_parser import ConfigParser -from .config_settings import ConfigSettings diff --git a/ThirdParty/Ert/python/python/ert/config/config_content.py b/ThirdParty/Ert/python/python/ert/config/config_content.py deleted file mode 100644 index 8a207bfcf7..0000000000 --- a/ThirdParty/Ert/python/python/ert/config/config_content.py +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'config_content.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import os.path - -from ert.config import UnrecognizedEnum, ContentTypeEnum, ConfigError, ConfigPrototype, SchemaItem -from cwrap import BaseCClass - - -class ContentNode(BaseCClass): - TYPE_NAME = "content_node" - - _iget = ConfigPrototype("char* config_content_node_iget( content_node , int)") - _size = ConfigPrototype("int config_content_node_get_size( content_node )") - _get_full_string = ConfigPrototype("char* config_content_node_get_full_string( content_node , char* )") - _iget_type = ConfigPrototype("config_content_type_enum config_content_node_iget_type( content_node , int)") - _iget_as_abspath = ConfigPrototype("char* config_content_node_iget_as_abspath( content_node , int)") - _iget_as_relpath = ConfigPrototype("char* config_content_node_iget_as_relpath( content_node , int)") - _iget_as_string = ConfigPrototype("char* config_content_node_iget( content_node , int)") - _iget_as_int = ConfigPrototype("int config_content_node_iget_as_int( content_node , int)") - _iget_as_double = ConfigPrototype("double config_content_node_iget_as_double( content_node , int)") - _iget_as_path = ConfigPrototype("char* config_content_node_iget_as_path( content_node , int)") - _iget_as_bool = ConfigPrototype("bool config_content_node_iget_as_bool( content_node , int)") - _iget_as_isodate = ConfigPrototype("time_t config_content_node_iget_as_isodate( content_node , int)") - - typed_get = { - ContentTypeEnum.CONFIG_STRING: _iget_as_string, - ContentTypeEnum.CONFIG_INT: _iget_as_int, - ContentTypeEnum.CONFIG_FLOAT: _iget_as_double, - ContentTypeEnum.CONFIG_PATH: _iget_as_path, - ContentTypeEnum.CONFIG_EXISTING_PATH: _iget_as_path, - ContentTypeEnum.CONFIG_BOOL: _iget_as_bool, - ContentTypeEnum.CONFIG_ISODATE: _iget_as_isodate - } - - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def __len__(self): - return self._size() - - def __assertIndex(self , index): - if isinstance(index, int): - if index < 0: - index += len(self) - - if not 0 <= index < len(self): - raise IndexError - return index - else: - raise TypeError("Invalid argument type: %s" % index) - - - def __getitem__(self, index): - index = self.__assertIndex(index) - - content_type = self._iget_type(index) - typed_get = self.typed_get[content_type] - return typed_get(self, index) - - def getPath(self , index = 0, absolute = True , relative_start = None): - index = self.__assertIndex(index) - content_type = self._iget_type(index) - if content_type in [ContentTypeEnum.CONFIG_EXISTING_PATH , ContentTypeEnum.CONFIG_PATH]: - if absolute: - return self._iget_as_abspath(index) - else: - if relative_start is None: - return self._iget_as_relpath(index) - else: - abs_path = self._iget_as_abspath(index) - return os.path.relpath( abs_path , relative_start ) - else: - raise TypeError("The getPath() method can only be called on PATH items") - - def content(self, sep=" "): - return self._get_full_string(sep) - - - def igetString(self , index): - index = self.__assertIndex(index) - return self._iget(index ) - - - def asList(self): - return [x for x in self] - - - -class ContentItem(BaseCClass): - TYPE_NAME = "content_item" - - _alloc = ConfigPrototype("void* config_content_item_alloc( schema_item , void* )" , bind = False ) - _size = ConfigPrototype("int config_content_item_get_size( content_item )") - _iget_content_node = ConfigPrototype("content_node_ref config_content_item_iget_node( content_item , int)") - _free = ConfigPrototype("void config_content_item_free( content_item )") - - def __init__(self , schema_item): - path_elm = None - c_ptr = self._alloc( schema_item , path_elm) - super( ContentItem, self).__init__(c_ptr) - - - def __len__(self): - return self._size() - - - def __getitem__(self, index): - if isinstance(index, int): - if index < 0: - index += len(self) - - if (index >= 0) and (index < len(self)): - return self._iget_content_node(index).setParent(self) - else: - raise IndexError - else: - raise TypeError("[] operator must have integer index") - - def last(self): - return self[-1] - - def getValue(self , item_index = -1 , node_index = 0): - node = self[item_index] - return node[node_index] - - - def free(self): - self._free( ) - - - -class ConfigContent(BaseCClass): - TYPE_NAME = "config_content" - - _free = ConfigPrototype("void config_content_free( config_content )") - _is_valid = ConfigPrototype("bool config_content_is_valid( config_content )") - _has_key = ConfigPrototype("bool config_content_has_item( config_content , char*)") - _get_item = ConfigPrototype("content_item_ref config_content_get_item( config_content , char*)") - _get_errors = ConfigPrototype("config_error_ref config_content_get_errors( config_content )") - _get_warnings = ConfigPrototype("stringlist_ref config_content_get_warnings( config_content )") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def __contains__(self , key): - return self._has_key(key) - - def setParser(self , parser): - self._parser = parser - - - def __getitem__(self , key): - if key in self: - item = self._get_item(key) - item.setParent( self ) - return item - else: - if key in self._parser: - schema_item = SchemaItem( key ) - return ContentItem( schema_item ) - else: - raise KeyError("No such key: %s" % key) - - - def hasKey(self,key): - return key in self - - - def getValue(self , key , item_index = -1 , node_index = 0): - item = self[key] - return item.getValue( item_index , node_index ) - - - def isValid(self): - return self._is_valid() - - - def free(self): - self._free() - - - def getErrors(self): - """ @rtype: ConfigError """ - return self._get_errors() - - - def getWarnings(self): - """ @rtype: ConfigError """ - return self._get_warnings( ) diff --git a/ThirdParty/Ert/python/python/ert/config/config_error.py b/ThirdParty/Ert/python/python/ert/config/config_error.py deleted file mode 100644 index 515adc8908..0000000000 --- a/ThirdParty/Ert/python/python/ert/config/config_error.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'enkf_fs.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from ert.config import ConfigPrototype -from cwrap import BaseCClass - - - -class ConfigError(BaseCClass): - TYPE_NAME = "config_error" - _free = ConfigPrototype("void config_error_free(config_error)") - _count = ConfigPrototype("int config_error_count(config_error)") - _iget = ConfigPrototype("char* config_error_iget(config_error, int)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def __getitem__(self, index): - """ @rtype: str """ - if not isinstance(index, int): - raise TypeError("Expected an integer") - - size = len(self) - if index >= size: - raise IndexError("Index out of range: %d < %d" % (index, size)) - - return self._iget(index) - - def __len__(self): - """ @rtype: int """ - return self._count() - - def free(self): - self._free() - diff --git a/ThirdParty/Ert/python/python/ert/config/config_parser.py b/ThirdParty/Ert/python/python/ert/config/config_parser.py deleted file mode 100644 index c4f75049f7..0000000000 --- a/ThirdParty/Ert/python/python/ert/config/config_parser.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'config_parser.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import sys -import os.path - -from ert.config import UnrecognizedEnum, ContentTypeEnum , ConfigContent, ConfigPrototype -from cwrap import BaseCClass - - -class ConfigParser(BaseCClass): - TYPE_NAME = "config_parser" - - _alloc = ConfigPrototype("void* config_alloc( )", bind=False) - _add = ConfigPrototype("schema_item_ref config_add_schema_item( config_parser , char* , bool)") - _free = ConfigPrototype("void config_free( config_parser )") - _parse = ConfigPrototype("config_content_obj config_parse( config_parser , char* , char* , char* , char* , hash , config_unrecognized_enum , bool )") - _get_schema_item = ConfigPrototype("schema_item_ref config_get_schema_item( config_parser , char*)") - _has_schema_item = ConfigPrototype("bool config_has_schema_item( config_parser , char*)") - - def __init__(self): - c_ptr = self._alloc() - super(ConfigParser, self).__init__(c_ptr) - - - def __contains__(self , keyword): - return self._has_schema_item( keyword ) - - - def add(self, keyword, required=False , value_type = None): - item = self._add(keyword, required).setParent( self ) - if value_type: - item.iset_type( 0 , value_type ) - - return item - - - def getSchemaItem(self , keyword): - if keyword in self: - item = self._get_schema_item(keyword) - item.setParent( self ) - else: - raise KeyError("Config parser does not have item:%s" % keyword) - - - def parse(self, config_file, comment_string="--", include_kw="INCLUDE", define_kw="DEFINE", - pre_defined_kw_map=None, unrecognized=UnrecognizedEnum.CONFIG_UNRECOGNIZED_WARN, validate=True): - """ @rtype: ConfigContent """ - - assert isinstance(unrecognized, UnrecognizedEnum) - - - if os.path.exists(config_file): - config_content = self._parse(config_file, comment_string, include_kw, define_kw, pre_defined_kw_map, unrecognized, validate) - config_content.setParser( self ) - - if not config_content.isValid(): - if validate: - sys.stderr.write("Errors parsing:%s \n" % config_file) - for count, error in enumerate(config_content.getErrors()): - sys.stderr.write(" %02d:%s\n" % (count , error)) - - raise ValueError("Parsing:%s failed" % config_file) - - return config_content - else: - raise IOError("File: %s does not exists" % config_file) - - - def free(self): - self._free() diff --git a/ThirdParty/Ert/python/python/ert/config/config_settings.py b/ThirdParty/Ert/python/python/ert/config/config_settings.py deleted file mode 100644 index 1536e27d5c..0000000000 --- a/ThirdParty/Ert/python/python/ert/config/config_settings.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright (C) 2017 Statoil ASA, Norway. -# -# The file 'config_settings.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCClass - -from ert.config import ConfigPrototype, ContentTypeEnum -from ert.config import SchemaItem - - -class ConfigSettings(BaseCClass): - TYPE_NAME = "config_settings" - _alloc = ConfigPrototype("void* config_settings_alloc(char*)", bind = False) - _free = ConfigPrototype("void config_settings_free(config_settings)") - - _add_setting = ConfigPrototype("bool config_settings_add_setting(config_settings , char* , config_content_type_enum, char*)") - _add_double_setting = ConfigPrototype("void config_settings_add_double_setting(config_settings , char* , double)") - _add_int_setting = ConfigPrototype("void config_settings_add_int_setting(config_settings , char* , int)") - _add_string_setting = ConfigPrototype("void config_settings_add_string_setting(config_settings , char* , char*)") - _add_bool_setting = ConfigPrototype("void config_settings_add_bool_setting(config_settings , char* , bool)") - _has_key = ConfigPrototype("bool config_settings_has_key(config_settings , char*)") - _get_type = ConfigPrototype("config_content_type_enum config_settings_get_value_type(config_settings, char*)") - _init_parser = ConfigPrototype("void config_settings_init_parser(config_settings, config_parser, bool)") - _apply = ConfigPrototype("void config_settings_apply(config_settings, config_content)") - _alloc_keys = ConfigPrototype("stringlist_obj config_settings_alloc_keys(config_settings)") - - _get = ConfigPrototype("char* config_settings_get_value(config_settings, char*)") - _get_int = ConfigPrototype("int config_settings_get_int_value(config_settings, char*)") - _get_double = ConfigPrototype("double config_settings_get_double_value(config_settings, char*)") - _get_bool = ConfigPrototype("bool config_settings_get_bool_value(config_settings, char*)") - - _set = ConfigPrototype("bool config_settings_set_value(config_settings, char*, char*)") - _set_int = ConfigPrototype("bool config_settings_set_int_value(config_settings, char*, int)") - _set_double = ConfigPrototype("bool config_settings_set_double_value(config_settings, char*, double)") - _set_bool = ConfigPrototype("bool config_settings_set_bool_value(config_settings, char*, bool)") - - - - - def __init__(self , root_key): - c_ptr = ConfigSettings._alloc( root_key ) - super(ConfigSettings, self).__init__(c_ptr) - - - def __contains__(self, key): - return self._has_key( key ) - - - def __getitem__(self,key): - if key in self: - value_type = self._get_type( key ) - if value_type == ContentTypeEnum.CONFIG_INT: - return self._get_int( key ) - - if value_type == ContentTypeEnum.CONFIG_FLOAT: - return self._get_double( key ) - - if value_type == ContentTypeEnum.CONFIG_BOOL: - return self._get_bool( key ) - - return self._get( key ) - else: - raise KeyError("Settings object does not support key:%s" % key) - - - def __setitem__(self, key, value): - if key in self: - value_type = self._get_type( key ) - - if value_type == ContentTypeEnum.CONFIG_INT: - self._set_int( key , value) - return - - if value_type == ContentTypeEnum.CONFIG_FLOAT: - self._set_double( key , value) - return - - if value_type == ContentTypeEnum.CONFIG_BOOL: - if type(value) is bool: - self._set_bool( key , value ) - return - else: - raise TypeError("Type of %s should be boolean" % key) - - if not self._set( key , value ): - raise TypeError("Setting %s=%s failed \n" % (key , value)) - else: - raise KeyError("Settings object does not support key:%s" % key) - - - - def free(self): - self._free( ) - - - def addSetting(self, key , value_type, initial_value): - if not self._add_setting( key , value_type , str(initial_value) ): - raise TypeError("Failed to add setting %s with initial value %s" % (key , initial_value)) - - - def addIntSetting(self, key , initial_value): - self._add_int_setting( key , initial_value ) - - def addDoubleSetting(self, key , initial_value): - self._add_double_setting( key , initial_value ) - - def addStringSetting(self, key , initial_value): - self._add_string_setting( key , initial_value ) - - def addBoolSetting(self, key , initial_value): - self._add_bool_setting( key , initial_value ) - - def initParser(self , parser, required = False): - self._init_parser( parser , required ) - - - def apply(self , config_content): - self._apply( config_content ) - - - def keys(self): - return self._alloc_keys( ) - - - def getType(self , key): - if key in self: - return self._get_type( key ) - else: - raise KeyError("No such key:%s" % key) diff --git a/ThirdParty/Ert/python/python/ert/config/content_type_enum.py b/ThirdParty/Ert/python/python/ert/config/content_type_enum.py deleted file mode 100644 index f5ba67e0b7..0000000000 --- a/ThirdParty/Ert/python/python/ert/config/content_type_enum.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'content_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCEnum - -class ContentTypeEnum(BaseCEnum): - TYPE_NAME = "config_content_type_enum" - CONFIG_STRING = None - CONFIG_INT = None - CONFIG_FLOAT = None - CONFIG_PATH = None - CONFIG_EXISTING_PATH = None - CONFIG_BOOL = None - CONFIG_CONFIG = None - CONFIG_BYTESIZE = None - CONFIG_EXECUTABLE = None - CONFIG_ISODATE = None - CONFIG_INVALID = None - -ContentTypeEnum.addEnum("CONFIG_STRING", 1) -ContentTypeEnum.addEnum("CONFIG_INT", 2) -ContentTypeEnum.addEnum("CONFIG_FLOAT", 4) -ContentTypeEnum.addEnum("CONFIG_PATH", 8) -ContentTypeEnum.addEnum("CONFIG_EXISTING_PATH", 16) -ContentTypeEnum.addEnum("CONFIG_BOOL", 32) -ContentTypeEnum.addEnum("CONFIG_CONFIG", 64) -ContentTypeEnum.addEnum("CONFIG_BYTESIZE", 128) -ContentTypeEnum.addEnum("CONFIG_EXECUTABLE", 256) -ContentTypeEnum.addEnum("CONFIG_ISODATE", 512) -ContentTypeEnum.addEnum("CONFIG_INVALID", 1024) diff --git a/ThirdParty/Ert/python/python/ert/config/schema_item.py b/ThirdParty/Ert/python/python/ert/config/schema_item.py deleted file mode 100644 index 551c14f9df..0000000000 --- a/ThirdParty/Ert/python/python/ert/config/schema_item.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# This file is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import ctypes - -from ert.util import UtilPrototype -from ert.config import ContentTypeEnum , ConfigPrototype -from cwrap import BaseCClass - - -class SchemaItem(BaseCClass): - TYPE_NAME = "schema_item" - - _alloc = ConfigPrototype("void* config_schema_item_alloc( char* , bool )", bind=False) - _free = ConfigPrototype("void config_schema_item_free( schema_item )") - _iget_type = ConfigPrototype("config_content_type_enum config_schema_item_iget_type( schema_item, int)") - _iset_type = ConfigPrototype("void config_schema_item_iset_type( schema_item , int , config_content_type_enum)") - _set_argc_minmax = ConfigPrototype("void config_schema_item_set_argc_minmax( schema_item , int , int)") - _add_alternative = ConfigPrototype("void config_schema_item_add_indexed_alternative(schema_item , int , char*)") - _set_deprecated = ConfigPrototype("void config_schema_item_set_deprecated(schema_item , char*)") - _valid_string = ConfigPrototype("bool config_schema_item_valid_string(config_content_type_enum , char*)", bind = False) - _sscanf_bool = UtilPrototype("bool util_sscanf_bool( char* , bool*)", bind = False) - - def __init__(self, keyword, required=False): - c_ptr = self._alloc(keyword, required) - super(SchemaItem, self).__init__(c_ptr) - - @classmethod - def validString(cls , value_type, value): - return cls._valid_string( value_type , value ) - - - - @classmethod - def convert(cls, value_type, value_string): - if cls.validString(value_type , value_string): - if value_type == ContentTypeEnum.CONFIG_INT: - return int(value_string) - - if value_type == ContentTypeEnum.CONFIG_FLOAT: - return float(value_string) - - if value_type == ContentTypeEnum.CONFIG_BOOL: - value = ctypes.c_bool() - SchemaItem._sscanf_bool( value_string , ctypes.byref( value )) - return value.value - - return value_string - else: - raise ValueError("Invalid string value: %s" % value_string) - - - - def iget_type( self, index): - """ @rtype: ContentTypeEnum """ - return self._iget_type(index) - - def iset_type( self, index, schema_type ): - """ - @type schema_type: ContentTypeEnum - """ - assert isinstance(schema_type, ContentTypeEnum) - self._iset_type(index, schema_type) - - def set_argc_minmax(self, minimum, maximum): - self._set_argc_minmax(minimum, maximum) - - - def initSelection(self , index , alternatives): - for alt in alternatives: - self.addAlternative( index , alt ) - - - def addAlternative(self , index , alt): - self._add_alternative( index , alt ) - - def setDeprecated(self , msg): - """This method can be used to mark this item as deprecated. - - If the deprecated item is used in a configuration file the - @msg will be added to the warnings of the ConfigContent - object, - """ - self._set_deprecated( msg ) - - - def free(self): - self._free() diff --git a/ThirdParty/Ert/python/python/ert/config/unrecognized_enum.py b/ThirdParty/Ert/python/python/ert/config/unrecognized_enum.py deleted file mode 100644 index 2a707e60a6..0000000000 --- a/ThirdParty/Ert/python/python/ert/config/unrecognized_enum.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'unrecognized_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCEnum - -class UnrecognizedEnum(BaseCEnum): - TYPE_NAME = "config_unrecognized_enum" - CONFIG_UNRECOGNIZED_IGNORE = None - CONFIG_UNRECOGNIZED_WARN = None - CONFIG_UNRECOGNIZED_ERROR = None - -UnrecognizedEnum.addEnum("CONFIG_UNRECOGNIZED_IGNORE", 0) -UnrecognizedEnum.addEnum("CONFIG_UNRECOGNIZED_WARN", 1) -UnrecognizedEnum.addEnum("CONFIG_UNRECOGNIZED_ERROR", 2) diff --git a/ThirdParty/Ert/python/python/ert/ecl/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/ecl/CMakeLists.txt index 45a545aa19..49605f4c5d 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/ert/ecl/CMakeLists.txt @@ -1,9 +1,7 @@ set(PYTHON_SOURCES __init__.py - ecl.py ecl_3d_file.py ecl_3dkw.py - ecl_case.py ecl_file.py ecl_file_view.py ecl_grav.py @@ -28,6 +26,8 @@ set(PYTHON_SOURCES ecl_sum_keyword_vector.py ecl_cmp.py ecl_sum_var_type.py + ecl_type.py + ecl_grid_generator.py ) add_python_package("python.ert.ecl" ${PYTHON_INSTALL_PREFIX}/ert/ecl "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/python/python/ert/ecl/__init__.py b/ThirdParty/Ert/python/python/ert/ecl/__init__.py index e5a506e337..feb2077c53 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/__init__.py +++ b/ThirdParty/Ert/python/python/ert/ecl/__init__.py @@ -28,6 +28,9 @@ wrap the content of the c-file ecl_xxx.c The main content is: ecl_kw/EclKW: This class holds one ECLIPSE keyword, like SWAT, in restart format. + ecl_type/EclDataType: This class is used to represent the data type + of the elements in EclKW. + ecl_file/EclFile: This class is used to load an ECLIPSE file in restart format, alternatively only parts of the file can be loaded. Internally it consists of a collection of EclKW @@ -36,6 +39,9 @@ wrap the content of the c-file ecl_xxx.c The main content is: ecl_grid/EclGrid: This will load an ECLIPSE GRID or EGRID file, and can then subsequently be used for queries about the grid. + ecl_grid_generator/EclGridGenerator: This can be used to generate various + grids. + ecl_sum/EclSum: This will load summary results from an ECLIPSE run; both data file(s) and the SMSPEC file. The EclSum object can be used as basis for queries on summary vectors. @@ -80,7 +86,8 @@ class EclPrototype(Prototype): ECL_LIB = ert.load("libecl") -from .ecl_util import EclFileEnum, EclFileFlagEnum, EclPhaseEnum, EclTypeEnum, EclUnitTypeEnum , EclUtil +from .ecl_util import EclFileEnum, EclFileFlagEnum, EclPhaseEnum, EclUnitTypeEnum , EclUtil +from .ecl_type import EclTypeEnum, EclDataType from .ecl_sum_var_type import EclSumVarType from .ecl_sum_tstep import EclSumTStep from .ecl_sum import EclSum #, EclSumVector, EclSumNode, EclSMSPECNode @@ -104,3 +111,4 @@ from .ecl_sum_node import EclSumNode from .ecl_sum_vector import EclSumVector from .ecl_npv import EclNPV , NPVPriceVector from .ecl_cmp import EclCmp +from .ecl_grid_generator import EclGridGenerator diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl.py b/ThirdParty/Ert/python/python/ert/ecl/ecl.py deleted file mode 100644 index 2f78a24430..0000000000 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl.py +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'ecl.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -""" -Convenience module importing all symbols in the ecl package. - -This module is purely for convenience; it explicitly imports all the -symbols from all the other modules into the common 'ecl' -namespace. The whole point of this excercise is to facilitate the -following construction: - - import ert.ecl.ecl as ecl <-- Import this module; and create the - namespace 'ecl' - ... - ... - sum = ecl.EclSum( "ECLIPSE.DATA") <-- Classes EclSum and EclGrid are now - grid = ecl.EclGrid("ECLIPSE.EGRID") accessible under the ecl namespace. - -It is not necessary to use the this module. See the doc/import.txt -document in the ert-python source distribution for more details of -module import and namespace resolution. -# """ -# import libecl -# from ecl_kw import EclKW -# from ecl_case import EclCase -# from ecl_file import EclFile -# from ecl_sum import EclSum -# from ecl_rft import EclRFTFile , EclRFT -# from ecl_rft_cell import EclRFTCell, EclPLTCell -# from ecl_grid import EclGrid -# from ecl_grav import EclGrav -# from ecl_subsidence import EclSubsidence -# from ecl_region import EclRegion -# from fortio import FortIO -# import ecl_util -# from ecl_util import * - -import os - -warning_message = """ - -The ecl namespace is deprecated and will go away. You are advised to -use one of these alternatives when importing the ert.ecl modules and -classes: - ---------------------------------------------------------------------- -Common prefix: -import ert.ecl as ecl - -Direct import of classes: -from ert.ecl import EclGrid,EclSum ---------------------------------------------------------------------- - -The environment variable ERT_SILENCE_WARNINGS is a colon separated -list which can be used to silence warnings. To silence this particular -warning set: - -ERT_SILENCE_WARNINGS = \"eclimport\" - -""" - - -from warnings import warn - -ert_silence_warnings = os.environ.get("ERT_SILENCE_WARNINGS") -if ert_silence_warnings: - silent_warnings = set( ert_silence_warnings.split(":")) -else: - silent_warnings = set() - -if not "eclimport" in silent_warnings: - warn(warning_message , DeprecationWarning) - - -from .ecl_sum import EclSum #, EclSumVector, EclSumNode, EclSMSPECNode -from .ecl_rft_cell import EclPLTCell, EclRFTCell -from .ecl_rft import EclRFT, EclRFTFile -from .ecl_kw import EclKW -from .ecl_file import EclFile -from .fortio import FortIO -from .ecl_grid import EclGrid -from .ecl_region import EclRegion -from .ecl_case import EclCase -from .ecl_subsidence import EclSubsidence -from .ecl_grav_calc import deltag, phase_deltag -from .ecl_grav import EclGrav diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_3dkw.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_3dkw.py index d62c1f0f18..edeb817086 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_3dkw.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_3dkw.py @@ -14,8 +14,10 @@ # See the GNU General Public License at # for more details. -from __future__ import print_function -from ecl_kw import EclKW +from __future__ import (absolute_import, division, + print_function, unicode_literals) + +from .ecl_kw import EclKW class Ecl3DKW(EclKW): """ @@ -64,18 +66,20 @@ class Ecl3DKW(EclKW): PERMX property. """ - - @classmethod - def create(cls , kw , grid , value_type , default_value = 0 , global_active = False): + def __init__(self, kw , grid , value_type , default_value = 0 , global_active = False): if global_active: size = grid.getGlobalSize() else: - size = grid.getNumActive( ) + size = grid.getNumActive( ) + super(Ecl3DKW , self).__init__( kw , size , value_type) + self.grid = grid + self.global_active = global_active + self.setDefault( default_value ) - new_kw = super(Ecl3DKW , cls).create( kw , size , value_type) - new_kw.grid = grid - new_kw.global_active = global_active - new_kw.setDefault( default_value ) + + @classmethod + def create(cls , kw , grid , value_type , default_value = 0 , global_active = False): + new_kw = Ecl3DKW(kw , grid , value_type , default_value , global_active) return new_kw @classmethod diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_case.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_case.py deleted file mode 100644 index 77d046e57b..0000000000 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_case.py +++ /dev/null @@ -1,190 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'ecl_case.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -""" -Implements EclCase class which is a container for one ECLIPSE case. - -This module is a pure Python module which does not directly invoke any -C based functions. -""" -import os -import warnings -from ert.ecl import EclRFTFile, EclGrid, EclSum, EclUtil - - - -class EclCase: - """ - Small container for one ECLIPSE case. - - Mostly a wrapper around an ECLIPSE datafile, along with properties - to load the corresponding summary, grid and rft files. In addition - there are methods run() and submit() to run the ECLIPSE - simulation. - """ - def __init__(self , input_case): - """ - Create a new case based on path/basename. - - The @input_case argument should be the basename of the ECLIPSE - case, it can contain an additional path component. The - @input_case argument can contain an extension, but that is not - necessary; it does not need to point an existing file. - - These are all valid: - - case1 = EclCase( "ECLIPSE" ) - case2 = EclCase( "relative/path/ECLIPSE.SMSPEC" ) - case3 = EclCase( "/absolute/path/simulation/ECLIPSE_3.xxx" ) - - """ - warnings.warn("The EclCase class is deprecated - instantiate the EclSum / EclGrid / ... classes directly." , DeprecationWarning) - - self.case = input_case - (path , tmp) = os.path.split( input_case ) - if path: - self.__path = os.path.abspath( path ) - else: - self.__path = os.getcwd() - (self.__base , self.ext) = os.path.splitext( tmp ) - - self.__sum = None - self.__grid = None - self.__data_file = None - self.__rft = None - - - @property - def datafile( self ): - """ - Will return the full path to the ECLIPSE data file. - - Observe that this method is purely about string manipulation; - i.e. it is not checked if the datafile actually exists. - """ - - if not self.__data_file: - self.__data_file = "%s/%s.DATA" % ( self.__path , self.__base ) - return self.__data_file - - - @property - def sum( self ): - """ - An EclSum instance for the current case; or None. - - Observe that accessing the summary of a running ECLIPSE - simulation, i.e. to check progress, is extremely error - prone. During the actual simulation the summary files on disk - are invalid a large part of the time, and an attempt to load - at these times will lead to an instant 'crash and burn'. - """ - if not self.__sum: - self.__sum = EclSum( self.case ) - return self.__sum - - - @property - def grid( self ): - """ - An EclGrid instance for the current case; or None. - """ - if not self.__grid: - self.__grid = EclGrid( self.case ) - return self.__grid - - - @property - def rft_file( self ): - """ - An EclRFTFile instance for the current case; or None. - """ - if not self.__rft: - self.__rft = EclRFTFile( self.case ) - return self.__rft - - - @property - def base( self ): - """ - Will return the ECLIPSE basename of the current case. - """ - return self.__base - - - @property - def path( self ): - """ - Will return the absolute path of the current case. - """ - return self.__path - - - def run( self, - ecl_cmd = None, - ecl_version = None, - driver = None, - driver_type = None, - driver_options = None, - blocking = False ): - """ - Will start an ECLIPSE simulation of the current case. - - The method has a long and nasty argument list, but all - arguments have sensible defaults, and you probably do not need - to enter any at all. The arguments are as follows: - - ecl_cmd: The command used to run ECLIPSE. This will - typically be a script of some kind. The command will be - called with three commandline arguments: version datafile - num_cpu - - ecl_version: The eclipse version you want to use, this - should be a string of the type "2010.2". - - driver: This should be an instance of Driver() from - ert.job_queue.driver. If driver is None the method will - create a new driver instance. - - driver_type: If the driver is none the method will create a - new driver instance, it will create a driver of this type - (i.e. LOCAL, LSF or RSH). - - driver_options: When creating a new driver, these options - will be used. - - blocking: If blocking is True the method will not return - before the simulation is complete, otherwise the method - will return immediately. If blocking is False the ECLIPSE - simulation will continue even if the python script - exits. - - Observe that there are some dependencies between the arguments: - - * If both driver and driver_type are present the existing - driver instance will be used, and the driver_type argument - will be ignored. - - * The driver_options argument will only be used when - creating a new driver instance, and will not be used to - modify an existing driver instance. - """ - import ert.job_queue.driver as queue_driver - - num_cpu = EclUtil.get_num_cpu( self.datafile ) - argv = [ecl_version , self.datafile , num_cpu] - - job = driver.submit( self.base , ecl_cmd , self.path , argv , blocking = blocking) - return job diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_file.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_file.py index e0eeb4f98a..b50cf38869 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_file.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_file.py @@ -39,7 +39,7 @@ import re import types import datetime import ctypes -import warnings + from cwrap import BaseCClass from ert.ecl import EclPrototype, EclKW, EclFileEnum, EclFileView from ert.util import CTime @@ -87,7 +87,7 @@ class EclFile(BaseCClass): @classmethod def restart_block( cls , filename , dtime = None , report_step = None): raise NotImplementedError("The restart_block implementation has been removed - open file normally and use EclFileView.") - + @classmethod @@ -174,8 +174,7 @@ class EclFile(BaseCClass): def __repr__(self): fn = self.getFilename() wr = ', read/write' if self._writable() else '' - ad = self._ad_str() - return 'EclFile("%s"%s) %s' % (fn,wr,ad) + return self._create_repr('"%s"%s' % (fn,wr)) def __init__( self , filename , flags = 0): @@ -209,7 +208,7 @@ class EclFile(BaseCClass): super(EclFile , self).__init__(c_ptr) self.global_view = self._get_global_view( ) self.global_view.setParent( self ) - + def save_kw( self , kw ): """ @@ -254,8 +253,16 @@ class EclFile(BaseCClass): self.close() - def blockView(self, kw , kw_index): - return self.global_view.blockView( kw , kw_index ) + def blockView(self, kw, kw_index): + if not kw in self: + raise KeyError('No such keyword "%s".' % kw) + ls = self.global_view.numKeywords(kw) + idx = kw_index + if idx < 0: + idx += ls + if 0 <= idx < ls: + return self.global_view.blockView(kw, idx) + raise IndexError('Index out of range, must be in [0, %d), was %d.' % (ls, kw_index)) def blockView2(self, start_kw , stop_kw , start_index): @@ -264,9 +271,9 @@ class EclFile(BaseCClass): def restartView( self, seqnum_index = None, report_step = None , sim_time = None , sim_days = None): return self.global_view.restartView( seqnum_index, report_step , sim_time, sim_days ) - - + + def select_block( self, kw , kw_index): raise NotImplementedError("The select_block implementation has been removed - use EclFileView") @@ -311,7 +318,7 @@ class EclFile(BaseCClass): is a non-unified restart file (or not a restart file at all), the method will do nothing and return False. """ - + @@ -343,10 +350,18 @@ class EclFile(BaseCClass): for swat in restart_file["SWAT"]: .... """ + if isinstance(index, int): + ls = len(self) + idx = index + if idx < 0: + idx += ls + if 0 <= idx < ls: + return self.global_view[idx] + else: + raise IndexError('Index must be in [0, %d), was: %d.' % (ls, index)) return self.global_view[index] - def iget_kw( self , index , copy = False): """ Will return EclKW instance nr @index. @@ -394,7 +409,7 @@ class EclFile(BaseCClass): def iget_named_kw( self , kw_name , index , copy = False): return self.global_view.iget_named_kw( kw_name , index ) - + def restart_get_kw( self , kw_name , dtime , copy = False): """Will return EclKW @kw_name from restart file at time @dtime. @@ -493,7 +508,7 @@ class EclFile(BaseCClass): header_dict = {} for index in range(len(self)): kw = self[index] - header_dict[ kw.name ] = True + header_dict[ kw.getName() ] = True return header_dict.keys() @@ -534,11 +549,12 @@ class EclFile(BaseCClass): probably be tricked by other file types also containing an INTEHEAD keyword. """ - dates = [] if self.has_kw('SEQNUM'): + dates = [] for index in range( self.num_named_kw( 'SEQNUM' )): dates.append( self.iget_restart_sim_time( index )) - else: + return dates + elif 'INTEHEAD' in self: # This is a uber-hack; should export the ecl_rsthead # object as ctypes structure. intehead = self["INTEHEAD"][0] @@ -546,8 +562,8 @@ class EclFile(BaseCClass): month = intehead[65] day = intehead[64] date = datetime.datetime( year , month , day ) - dates = [ date ] - return dates + return [ date ] + return None @property @@ -564,7 +580,7 @@ class EclFile(BaseCClass): """ return self.global_view.numKeywords( kw ) - + def has_kw( self , kw , num = 0): """ Check if current EclFile instance has a keyword @kw. @@ -572,11 +588,8 @@ class EclFile(BaseCClass): If the optional argument @num is given it will check if the EclFile has at least @num occurences of @kw. """ - num_named_kw = self.num_named_kw( kw ) - if num_named_kw > num: - return True - else: - return False + + return self.num_named_kw( kw ) > num def __contains__(self , kw): """ @@ -644,14 +657,8 @@ class EclFile(BaseCClass): """ Name of the file currently loaded. """ - return self._get_src_file( ) - - - @property - def name(self): - warnings.warn("The name property is deprecated - use getFilename( )" , DeprecationWarning) - return self.getFilename() - + fn = self._get_src_file() + return str(fn) if fn else '' def fwrite( self , fortio ): """ diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_file_view.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_file_view.py index 0e30b1d931..fc6626eff9 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_file_view.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_file_view.py @@ -1,6 +1,23 @@ -import types +# Copyright (C) 2017 Statoil ASA, Norway. +# +# This file is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. + +from __future__ import absolute_import, division, print_function, unicode_literals +from six import string_types from cwrap import BaseCClass -from ert.ecl import EclPrototype, EclKW +from ert.ecl import EclPrototype from ert.util import CTime class EclFileView(BaseCClass): @@ -13,7 +30,7 @@ class EclFileView(BaseCClass): _create_block_view = EclPrototype("ecl_file_view_ref ecl_file_view_add_blockview( ecl_file_view , char*, int )") _create_block_view2 = EclPrototype("ecl_file_view_ref ecl_file_view_add_blockview2( ecl_file_view , char*, char*, int )") _restart_view = EclPrototype("ecl_file_view_ref ecl_file_view_add_restart_view( ecl_file_view , int, int, time_t, double )") - + def __init__(self): raise NotImplementedError("Can not instantiate directly") @@ -23,7 +40,8 @@ class EclFileView(BaseCClass): return self._iget_kw( index ).setParent( parent = self ) - + def __repr__(self): + return 'EclFileView(size = %d) %s' % (len(self), self._ad_str()) def iget_named_kw(self, kw_name , index): if not kw_name in self: @@ -31,7 +49,7 @@ class EclFileView(BaseCClass): if index >= self.numKeywords( kw_name ): raise IndexError("Too large index: %d" % index) - + return self._iget_named_kw( kw_name , index ).setParent( parent = self ) @@ -64,12 +82,15 @@ class EclFileView(BaseCClass): .... """ - if isinstance( index , types.IntType): - if index < 0 or index >= len(self): - raise IndexError + if isinstance( index , int): + ls = len(self) + idx = index + if idx < 0: + idx += ls + if 0 <= idx < ls: + return self.__iget(idx) else: - kw = self.__iget( index ) - return kw + raise IndexError('Index must be in [0, %d), was: %d.' % (ls, index)) if isinstance( index , slice ): indices = index.indices( len(self) ) @@ -78,7 +99,9 @@ class EclFileView(BaseCClass): kw_list.append( self[i] ) return kw_list else: - if isinstance( index , types.StringType): + if isinstance( index , bytes): + index = index.decode('ascii') + if isinstance( index , string_types): if index in self: kw_index = index kw_list = [] @@ -93,55 +116,61 @@ class EclFileView(BaseCClass): def __len__(self): return self._get_size( ) - - + + def __contains__(self , kw): if self.numKeywords(kw) > 0: return True else: return False - + def numKeywords(self , kw): return self._get_num_named_kw( kw ) - + def uniqueSize(self): return self._get_unique_size( ) def blockView2(self , start_kw , stop_kw, start_index): + idx = start_index if start_kw: if not start_kw in self: raise KeyError("The keyword:%s is not in file" % start_kw) - if start_index >= self.numKeywords( start_kw ): - raise IndexError("Index too high") - + ls = self.numKeywords(start_kw) + if idx < 0: + idx += ls + if not (0 <= idx < ls): + raise IndexError('Index must be in [0, %d), was: %d.' % (ls, start_index)) + if stop_kw: if not stop_kw in self: raise KeyError("The keyword:%s is not in file" % stop_kw) - view = self._create_block_view2( start_kw , stop_kw , start_index ) + view = self._create_block_view2(start_kw, stop_kw, idx) view.setParent( parent = self ) return view - - + def blockView(self , kw , kw_index): num = self.numKeywords( kw ) if num == 0: raise KeyError("Unknown keyword: %s" % kw) - if kw_index >= num: - raise IndexError("Index too high") - + idx = kw_index + if idx < 0: + idx += num + + if not (0 <= idx < num): + raise IndexError('Index must be in [0, %d), was: %d.' % (num, kw_index)) + view = self._create_block_view( kw , kw_index ) view.setParent( parent = self ) return view - def restartView(self , seqnum_index = None, report_step = None , sim_time = None , sim_days = None): if report_step is None: report_step = -1 @@ -154,7 +183,7 @@ class EclFileView(BaseCClass): if seqnum_index is None: seqnum_index = -1 - + view = self._restart_view( seqnum_index , report_step , CTime( sim_time ) , sim_days ) if view is None: raise ValueError("No such restart block could be identiefied") diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_grid.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_grid.py index 28f9c998d9..75b01cc72a 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_grid.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_grid.py @@ -1,18 +1,18 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'ecl_grid.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. +# Copyright (C) 2011 Statoil ASA, Norway. +# +# The file 'ecl_grid.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. """ Module to load and query ECLIPSE GRID/EGRID files. @@ -25,14 +25,15 @@ wrapper around the ecl_grid.c implementation from the libecl library. """ import ctypes +import warnings import numpy import sys -import warnings import os.path import math +import itertools from cwrap import CFILE, BaseCClass from ert.util import IntVector -from ert.ecl import EclPrototype, EclTypeEnum, EclKW, FortIO, EclUnitTypeEnum +from ert.ecl import EclPrototype, EclDataType, EclKW, FortIO, EclUnitTypeEnum class EclGrid(BaseCClass): @@ -42,7 +43,7 @@ class EclGrid(BaseCClass): TYPE_NAME = "ecl_grid" _fread_alloc = EclPrototype("void* ecl_grid_load_case__( char* , bool )" , bind = False) - _grdecl_create = EclPrototype("ecl_grid_obj ecl_grid_alloc_GRDECL_kw( int , int , int , ecl_kw , ecl_kw , ecl_kw , ecl_kw)" , bind = False) + _grdecl_create = EclPrototype("ecl_grid_obj ecl_grid_alloc_GRDECL_kw( int , int , int , ecl_kw , ecl_kw , ecl_kw , ecl_kw)" , bind = False) _alloc_rectangular = EclPrototype("ecl_grid_obj ecl_grid_alloc_rectangular( int , int , int , double , double , double , int*)" , bind = False) _exists = EclPrototype("bool ecl_grid_exists( char* )" , bind = False) @@ -50,7 +51,7 @@ class EclGrid(BaseCClass): _get_cell_lgr = EclPrototype("ecl_grid_ref ecl_grid_get_cell_lgr1( ecl_grid , int )") _num_coarse_groups = EclPrototype("int ecl_grid_get_num_coarse_groups( ecl_grid )") _in_coarse_group1 = EclPrototype("bool ecl_grid_cell_in_coarse_group1( ecl_grid , int)") - _free = EclPrototype("void ecl_grid_free( ecl_grid )") + _free = EclPrototype("void ecl_grid_free( ecl_grid )") _get_nx = EclPrototype("int ecl_grid_get_nx( ecl_grid )") _get_ny = EclPrototype("int ecl_grid_get_ny( ecl_grid )") _get_nz = EclPrototype("int ecl_grid_get_nz( ecl_grid )") @@ -60,13 +61,13 @@ class EclGrid(BaseCClass): _get_name = EclPrototype("char* ecl_grid_get_name( ecl_grid )") _ijk_valid = EclPrototype("bool ecl_grid_ijk_valid(ecl_grid , int , int , int)") _get_active_index3 = EclPrototype("int ecl_grid_get_active_index3( ecl_grid , int , int , int)") - _get_global_index3 = EclPrototype("int ecl_grid_get_global_index3( ecl_grid , int , int , int)") - _get_active_index1 = EclPrototype("int ecl_grid_get_active_index1( ecl_grid , int )") - _get_active_fracture_index1 = EclPrototype("int ecl_grid_get_active_fracture_index1( ecl_grid , int )") - _get_global_index1A = EclPrototype("int ecl_grid_get_global_index1A( ecl_grid , int )") - _get_global_index1F = EclPrototype("int ecl_grid_get_global_index1F( ecl_grid , int )") + _get_global_index3 = EclPrototype("int ecl_grid_get_global_index3( ecl_grid , int , int , int)") + _get_active_index1 = EclPrototype("int ecl_grid_get_active_index1( ecl_grid , int )") + _get_active_fracture_index1 = EclPrototype("int ecl_grid_get_active_fracture_index1( ecl_grid , int )") + _get_global_index1A = EclPrototype("int ecl_grid_get_global_index1A( ecl_grid , int )") + _get_global_index1F = EclPrototype("int ecl_grid_get_global_index1F( ecl_grid , int )") _get_ijk1 = EclPrototype("void ecl_grid_get_ijk1( ecl_grid , int , int* , int* , int*)") - _get_ijk1A = EclPrototype("void ecl_grid_get_ijk1A( ecl_grid , int , int* , int* , int*)") + _get_ijk1A = EclPrototype("void ecl_grid_get_ijk1A( ecl_grid , int , int* , int* , int*)") _get_xyz3 = EclPrototype("void ecl_grid_get_xyz3( ecl_grid , int , int , int , double* , double* , double*)") _get_xyz1 = EclPrototype("void ecl_grid_get_xyz1( ecl_grid , int , double* , double* , double*)") _get_cell_corner_xyz1 = EclPrototype("void ecl_grid_get_cell_corner_xyz1( ecl_grid , int , int , double* , double* , double*)") @@ -84,12 +85,12 @@ class EclGrid(BaseCClass): _get_cell_dx = EclPrototype("double ecl_grid_get_cell_dx1( ecl_grid , int )") _get_cell_dy = EclPrototype("double ecl_grid_get_cell_dy1( ecl_grid , int )") _get_depth = EclPrototype("double ecl_grid_get_cdepth1( ecl_grid , int )") - _fwrite_grdecl = EclPrototype("void ecl_grid_grdecl_fprintf_kw( ecl_grid , ecl_kw , char* , FILE , double)") + _fwrite_grdecl = EclPrototype("void ecl_grid_grdecl_fprintf_kw( ecl_grid , ecl_kw , char* , FILE , double)") _load_column = EclPrototype("void ecl_grid_get_column_property( ecl_grid , ecl_kw , int , int , double_vector)") _get_top = EclPrototype("double ecl_grid_get_top2( ecl_grid , int , int )") _get_top1A = EclPrototype("double ecl_grid_get_top1A(ecl_grid , int )") - _get_bottom = EclPrototype("double ecl_grid_get_bottom2( ecl_grid , int , int )") - _locate_depth = EclPrototype("int ecl_grid_locate_depth( ecl_grid , double , int , int )") + _get_bottom = EclPrototype("double ecl_grid_get_bottom2( ecl_grid , int , int )") + _locate_depth = EclPrototype("int ecl_grid_locate_depth( ecl_grid , double , int , int )") _invalid_cell = EclPrototype("bool ecl_grid_cell_invalid1( ecl_grid , int)") _valid_cell = EclPrototype("bool ecl_grid_cell_valid1( ecl_grid , int)") _get_distance = EclPrototype("void ecl_grid_get_distance( ecl_grid , int , int , double* , double* , double*)") @@ -103,8 +104,8 @@ class EclGrid(BaseCClass): _global_kw_copy = EclPrototype("void ecl_grid_global_kw_copy( ecl_grid , ecl_kw , ecl_kw)") _create_volume_keyword = EclPrototype("ecl_kw_obj ecl_grid_alloc_volume_kw( ecl_grid , bool)") - - + + @classmethod def loadFromGrdecl(cls , filename): """Will create a new EclGrid instance from grdecl file. @@ -112,7 +113,7 @@ class EclGrid(BaseCClass): This function will scan the input file @filename and look for the keywords required to build a grid. The following keywords are required: - + SPECGRID ZCORN COORD In addition the function will look for and use the ACTNUM and @@ -128,11 +129,11 @@ class EclGrid(BaseCClass): if os.path.isfile(filename): with open(filename) as f: - specgrid = EclKW.read_grdecl(f, "SPECGRID", ecl_type=EclTypeEnum.ECL_INT_TYPE, strict=False) + specgrid = EclKW.read_grdecl(f, "SPECGRID", ecl_type=EclDataType.ECL_INT, strict=False) zcorn = EclKW.read_grdecl(f, "ZCORN") coord = EclKW.read_grdecl(f, "COORD") try: - actnum = EclKW.read_grdecl(f, "ACTNUM", ecl_type=EclTypeEnum.ECL_INT_TYPE) + actnum = EclKW.read_grdecl(f, "ACTNUM", ecl_type=EclDataType.ECL_INT) except ValueError: actnum = None @@ -154,7 +155,7 @@ class EclGrid(BaseCClass): return EclGrid( filename ) else: return EclGrid.loadFromGrdecl( filename ) - + @classmethod def create(cls , specgrid , zcorn , coord , actnum , mapaxes = None ): @@ -173,29 +174,25 @@ class EclGrid(BaseCClass): zcorn_kw = file.iget_named_kw( "ZCORN" , 0) coord_kw = file.iget_named_kw( "COORD" , 0) actnum_kw = file.iget_named_kw( "ACTNUM" , 0 ) - + grid = EclGrid.create( specgrid_kw , zcorn_kw , coord_kw , actnum_kw) - - If you are so inclined ... + + If you are so inclined ... """ return cls._grdecl_create( specgrid[0] , specgrid[1] , specgrid[2] , zcorn , coord , actnum , mapaxes ) - - - @classmethod - def create_rectangular(cls , dims , dV , actnum = None): - warnings.warn("The create_rectangular method is deprecated - use createRectangular( )" , DeprecationWarning) - return cls.createRectangular( dims , dV , actnum ) - - - @classmethod - def createRectangular(cls , dims , dV , actnum = None): + def createRectangular(cls, dims , dV , actnum = None): """ Will create a new rectangular grid. @dims = (nx,ny,nz) @dVg = (dx,dy,dz) - - With the default value @actnum == None all cells will be active, + + With the default value @actnum == None all cells will be active, """ + + warnings.warn("EclGrid.createRectangular is deprecated. " + + "Please used the similar method in EclGridGenerator!", + DeprecationWarning) + if actnum is None: ecl_grid = cls._alloc_rectangular( dims[0] , dims[1] , dims[2] , dV[0] , dV[1] , dV[2] , None ) else: @@ -204,7 +201,7 @@ class EclGrid(BaseCClass): for (index , value) in enumerate(actnum): tmp[index] = value actnum = tmp - + if not len(actnum) == dims[0] * dims[1] * dims[2]: raise ValueError("ACTNUM size mismatch: len(ACTNUM):%d Expected:%d" % (len(actnum) , dims[0] * dims[1] * dims[2])) ecl_grid = cls._alloc_rectangular( dims[0] , dims[1] , dims[2] , dV[0] , dV[1] , dV[2] , actnum.getDataPtr() ) @@ -216,7 +213,6 @@ class EclGrid(BaseCClass): return ecl_grid - def __init__(self , filename , apply_mapaxes = True): """ Will create a grid structure from an EGRID or GRID file. @@ -250,6 +246,12 @@ class EclGrid(BaseCClass): xyz_s = '%dx%dx%d' % (self.getNX(),self.getNY(),self.getNZ()) return self._create_repr('%s%s, global_size = %d, active_size = %d' % (name, xyz_s, g_size, a_size)) + def __len__(self): + """ + len(grid) wil return the total number of cells. + """ + return self._get_global_size( ) + def equal(self , other , include_lgr = True , include_nnc = False , verbose = False): """ Compare the current grid with the other grid. @@ -261,49 +263,7 @@ class EclGrid(BaseCClass): def dualGrid(self): """Is this grid dual porosity model?""" - return self._dual_grid( ) - - @property - def dual_grid( self ): - warnings.warn("The dual_grid property is deprecated - use dualGrid( ) method" , DeprecationWarning) - return self.dualGrid( ) - - - @property - def nx( self ): - warnings.warn("The nx property is deprecated - use getNX( ) method" , DeprecationWarning) - return self.getNX() - - @property - def ny( self ): - warnings.warn("The ny property is deprecated - use getNY( ) method" , DeprecationWarning) - return self.getNY() - - @property - def nz( self ): - warnings.warn("The nz property is deprecated - use getNZ( ) method" , DeprecationWarning) - return self.getNZ() - - @property - def size( self ): - warnings.warn("The size property is deprecated - use getGlobalSize( ) method" , DeprecationWarning) - return self.getGlobalSize( ) - - @property - def nactive( self ): - warnings.warn("The nactive property is deprecated - use getNumActive( ) method" , DeprecationWarning) - return self.getNumActive( ) - - @property - def nactive_fracture( self ): - warnings.warn("The nactive_fracture property is deprecated - use getNumActiveFracture( ) method" , DeprecationWarning) - return self.getNumActiveFracture( ) - - @property - def dims( self ): - warnings.warn("The dims property is deprecated - use getDims() method instead" , DeprecationWarning) - return self.getDims( ) - + return self._dual_grid( ) def getDims(self): """A tuple of four elements: (nx , ny , nz , nactive).""" @@ -312,7 +272,7 @@ class EclGrid(BaseCClass): self.getNZ( ) , self.getNumActive( ) ) - + def getNX(self): """ The number of elements in the x direction""" return self._get_nx( ) @@ -344,7 +304,7 @@ class EclGrid(BaseCClass): x = ctypes.c_double() y = ctypes.c_double() z = ctypes.c_double() - + if lower_left is None: i1 = 0 j1 = 0 @@ -356,22 +316,22 @@ class EclGrid(BaseCClass): if not 0 < j1 < self.getNY(): raise ValueError("lower_left j coordinate invalid") - + if upper_right is None: i2 = self.getNX() j2 = self.getNY() else: i2,j2 = upper_right - + if not 1 < i2 <= self.getNX(): raise ValueError("upper_right i coordinate invalid") if not 1 < j2 <= self.getNY(): raise ValueError("upper_right j coordinate invalid") - + if not i1 < i2: raise ValueError("Must have lower_left < upper_right") - + if not j1 < j2: raise ValueError("Must have lower_left < upper_right") @@ -396,22 +356,16 @@ class EclGrid(BaseCClass): def getName(self): """ - Name of the current grid. - + Name of the current grid, returns a string. + For the main grid this is the filename given to the constructor when loading the grid; for an LGR this is the name of the LGR. If the grid instance has been created with the create() classmethod this can be None. """ - return self._get_name( ) + n = self._get_name() + return str(n) if n else '' - - @property - def name( self ): - warnings.warn("The name property is deprecated - use getName() method instead" , DeprecationWarning) - return self.getName() - - def global_index( self , active_index = None, ijk = None): """ Will convert either active_index or (i,j,k) to global index. @@ -424,7 +378,7 @@ class EclGrid(BaseCClass): This method will convert @active_index or @ijk to a global index. Exactly one of the arguments @active_index, - @global_index or @ijk must be supplied. + @global_index or @ijk must be supplied. The method is used extensively internally in the EclGrid class; most methods which take coordinate input pass through @@ -440,34 +394,34 @@ class EclGrid(BaseCClass): if ijk: set_count += 1 - + if not set_count == 1: raise ValueError("Exactly one of the kewyord arguments active_index, global_index or ijk must be set") - + if not active_index is None: global_index = self._get_global_index1A( active_index ) elif ijk: nx = self.getNX() ny = self.getNY() nz = self.getNZ() - + i,j,k = ijk if not 0 <= i < nx: - raise IndexError("Invalid value i:%d Range: [%d,%d)" % (i , 0 , nx)) + raise IndexError("Invalid value i:%d Range: [%d,%d)" % (i , 0 , nx)) if not 0 <= j < ny: - raise IndexError("Invalid value j:%d Range: [%d,%d)" % (j , 0 , ny)) - + raise IndexError("Invalid value j:%d Range: [%d,%d)" % (j , 0 , ny)) + if not 0 <= k < nz: - raise IndexError("Invalid value k:%d Range: [%d,%d)" % (k , 0 , nz)) + raise IndexError("Invalid value k:%d Range: [%d,%d)" % (k , 0 , nz)) global_index = self._get_global_index3( i,j,k) else: if not 0 <= global_index < self.getGlobalSize(): - raise IndexError("Invalid value global_index:%d Range: [%d,%d)" % (global_index , 0 , self.getGlobalSize())) + raise IndexError("Invalid value global_index:%d Range: [%d,%d)" % (global_index , 0 , self.getGlobalSize())) return global_index - + def get_active_index( self , ijk = None , global_index = None): """ @@ -535,7 +489,7 @@ class EclGrid(BaseCClass): gi = self.__global_index( global_index = global_index , ijk = ijk , active_index = active_index) return self._valid_cell( gi ) - + def active( self , ijk = None , global_index = None): """ @@ -581,9 +535,9 @@ class EclGrid(BaseCClass): Find true position of cell center. Will return world position of the center of a cell in the - grid. The return value is a tuple of three elements: + grid. The return value is a tuple of three elements: (utm_x , utm_y , depth). - + The cells of a grid can be specified in three different ways: (i,j,k) : As a tuple of i,j,k values. @@ -592,21 +546,21 @@ class EclGrid(BaseCClass): global index is related to (i,j,k) as: global_index = i + j*nx + k*nx*ny - + active_index : A number in the range [0,nactive). - + For many of the EclGrid methods a cell can be specified using any of these three methods. Observe that one and only method is allowed: OK: - pos1 = grid.get_xyz( active_index = 100 ) - pos2 = grid.get_xyz( ijk = (10,20,7 )) + pos1 = grid.get_xyz( active_index = 100 ) + pos2 = grid.get_xyz( ijk = (10,20,7 )) Crash and burn: - pos3 = grid.get_xyz( ijk = (10,20,7 ) , global_index = 10) + pos3 = grid.get_xyz( ijk = (10,20,7 ) , global_index = 10) pos4 = grid.get_xyz() - + All the indices in the EclGrid() class are zero offset, this is in contrast to ECLIPSE which has an offset 1 interface. """ @@ -641,7 +595,7 @@ class EclGrid(BaseCClass): if not 0 <= k <= self.getNZ(): raise IndexError("Invalid K value:%d - valid range: [0,%d]" % (k , self.getNZ())) - + x = ctypes.c_double() y = ctypes.c_double() z = ctypes.c_double() @@ -653,9 +607,9 @@ class EclGrid(BaseCClass): """ Will look up xyz of corner nr @corner_nr - - lower layer: upper layer - + + lower layer: upper layer + 2---3 6---7 | | | | 0---1 4---5 @@ -668,16 +622,10 @@ class EclGrid(BaseCClass): self._get_cell_corner_xyz1( gi , corner_nr , ctypes.byref(x) , ctypes.byref(y) , ctypes.byref(z)) return (x.value , y.value , z.value) - - def get_corner_xyz(self, corner_nr , active_index = None , global_index = None , ijk = None): - warnings.warn("The get_corner_xyz() method has been renamed: getCellCorner()" , DeprecationWarning) - return self.getCellCorner(corner_nr , active_index , global_index , ijk) - - def getNodeXYZ(self , i,j,k): """ This function returns the position of Vertex (i,j,k). - + The coordinates are in the inclusive interval [0,nx] x [0,ny] x [0,nz]. """ nx = self.getNX() @@ -685,7 +633,7 @@ class EclGrid(BaseCClass): nz = self.getNZ() corner = 0 - + if i == nx: i -= 1 corner += 1 @@ -699,7 +647,7 @@ class EclGrid(BaseCClass): corner += 4 if self._ijk_valid( i , j , k): - return self.get_corner_xyz( corner , global_index = i + j*nx + k*nx*ny ) + return self.getCellCorner( corner , global_index = i + j*nx + k*nx*ny ) else: raise IndexError("Invalid coordinates: (%d,%d,%d) " % (i,j,k)) @@ -707,11 +655,11 @@ class EclGrid(BaseCClass): def getLayerXYZ(self , xy_corner , layer): nx = self.getNX() - + (j , i) = divmod(xy_corner , nx + 1) k = layer return self.getNodeXYZ(i,j,k) - + def distance( self , global_index1 , global_index2): @@ -755,7 +703,7 @@ class EclGrid(BaseCClass): """ Bottom of the reservoir; in the column (@i , @j). """ - return self._get_bottom( i , j ) + return self._get_bottom( i , j ) def locate_depth( self , depth , i , j ): """ @@ -815,7 +763,7 @@ class EclGrid(BaseCClass): def findCellXY(self , x, y , k): """Will find the i,j of cell with utm coordinates x,y. - + The @k input is the layer you are interested in, the allowed values for k are [0,nz]. If the coordinates (x,y) are found to be outside the grid a ValueError exception is raised. @@ -830,7 +778,7 @@ class EclGrid(BaseCClass): raise ValueError("Could not find the point:(%g,%g) in layer:%d" % (x,y,k)) else: raise IndexError("Invalid layer value:%d" % k) - + @staticmethod def d_cmp(a,b): @@ -839,7 +787,7 @@ class EclGrid(BaseCClass): def findCellCornerXY(self , x, y , k): """Will find the corner nr of corner closest to utm coordinates x,y. - + The @k input is the layer you are interested in, the allowed values for k are [0,nz]. If the coordinates (x,y) are found to be outside the grid a ValueError exception is raised. @@ -850,7 +798,7 @@ class EclGrid(BaseCClass): corner_shift = 4 else: corner_shift = 0 - + nx = self.getNX() x0,y0,z0 = self.getCellCorner( corner_shift , ijk = (i,j,k)) d0 = math.sqrt( (x0 - x)*(x0 - x) + (y0 - y)*(y0 - y)) @@ -871,7 +819,7 @@ class EclGrid(BaseCClass): l = [(d0 , c0) , (d1,c1) , (d2 , c2) , (d3,c3)] l.sort( EclGrid.d_cmp ) return l[0][1] - + def cell_regular(self, active_index = None , global_index = None , ijk = None): @@ -897,7 +845,7 @@ class EclGrid(BaseCClass): """ gi = self.__global_index( ijk = ijk , active_index = active_index , global_index = global_index) return self._get_cell_volume( gi) - + def cell_dz( self , active_index = None , global_index = None , ijk = None): """ @@ -929,11 +877,11 @@ class EclGrid(BaseCClass): dy = self._get_cell_dy( gi ) dz = self._get_cell_thickness( gi ) return (dx,dy,dz) - + def getNumLGR(self): - + """ How many LGRs are attached to this main grid? @@ -942,13 +890,8 @@ class EclGrid(BaseCClass): """ return self._num_lgr( ) - - @property - def num_lgr( self ): - warnings.warn("The num_lgr property is deprecated - use getNumLGR() method instead" , DeprecationWarning) - return self.getNumLGR() - + def has_lgr( self , lgr_name ): """ Query if the grid has an LGR with name @lgr_name. @@ -962,7 +905,7 @@ class EclGrid(BaseCClass): def get_lgr( self , lgr_name ): """ Get EclGrid instance with LGR content. - + Return an EclGrid instance based on the LGR named @lgr_name. The LGR grid instance is in most questions like an ordinary grid instance; the only difference is that it can not @@ -977,17 +920,17 @@ class EclGrid(BaseCClass): return lgr else: raise KeyError("No such LGR:%s" % lgr_name) - + def get_cell_lgr( self, active_index = None , global_index = None , ijk = None): """ Get EclGrid instance located in cell. - + Will query the current grid instance if the cell given by @active_index, @global_index or @ijk has been refined with an LGR. Will return None if the cell in question has not been refined, the return value can be used for further queries. - + See get_xyz() for documentation of the input parameters. """ gi = self.__global_index( ijk = ijk , active_index = active_index , global_index = global_index) @@ -998,7 +941,7 @@ class EclGrid(BaseCClass): else: raise IndexError("No LGR defined for this cell") - + def grid_value( self , kw , i , j , k): """ Will evalute @kw in location (@i,@j,@k). @@ -1032,7 +975,7 @@ class EclGrid(BaseCClass): initialized with a suitable default value. """ self._load_column( kw , i , j , column) - + def createKW( self , array , kw_name , pack): """ @@ -1048,29 +991,29 @@ class EclGrid(BaseCClass): if dims[0] == self.getNX() and dims[1] == self.getNY() and dims[2] == self.getNZ(): dtype = array.dtype if dtype == numpy.int32: - type = EclTypeEnum.ECL_INT_TYPE + type = EclDataType.ECL_INT elif dtype == numpy.float32: - type = EclTypeEnum.ECL_FLOAT_TYPE + type = EclDataType.ECL_FLOAT elif dtype == numpy.float64: - type = EclTypeEnum.ECL_DOUBLE_TYPE + type = EclDataType.ECL_DOUBLE else: sys.exit("Do not know how to create ecl_kw from type:%s" % dtype) - + if pack: size = self.getNumActive() else: size = self.getGlobalSize() - + if len(kw_name) > 8: # Silently truncate to length 8 - ECLIPSE has it's challenges. - kw_name = kw_name[0:8] + kw_name = kw_name[0:8] kw = EclKW( kw_name , size , type ) active_index = 0 global_index = 0 - for k in range( self.nz ): - for j in range( self.ny ): - for i in range( self.nx ): + for k in range( self.getNZ() ): + for j in range( self.getNY() ): + for i in range( self.getNX() ): if pack: if self.active( global_index = global_index ): kw[active_index] = array[i,j,k] @@ -1080,15 +1023,15 @@ class EclGrid(BaseCClass): kw[global_index] = int( array[i,j,k] ) else: kw[global_index] = array[i,j,k] - + global_index += 1 return kw raise ValueError("Wrong size / dimension on array") - + def coarse_groups(self): """ - Will return the number of coarse groups in this grid. + Will return the number of coarse groups in this grid. """ return self._num_coarse_groups( ) @@ -1118,12 +1061,12 @@ class EclGrid(BaseCClass): method: value = grid.grid_value( ecl_kw , i , j , k ) - + """ if len(ecl_kw) == self.getNumActive() or len(ecl_kw) == self.getGlobalSize(): array = numpy.ones( [ self.getGlobalSize() ] , dtype = ecl_kw.dtype) * default kwa = ecl_kw.array - if len(ecl_kw) == self.size: + if len(ecl_kw) == self.getGlobalSize(): for i in range(kwa.size): array[i] = kwa[i] else: @@ -1132,12 +1075,15 @@ class EclGrid(BaseCClass): if self.active( global_index = global_index ): array[global_index] = kwa[data_index] data_index += 1 - + array = array.reshape( [self.getNX() , self.getNY() , self.getNZ()] , order = 'F') return array else: - raise ValueError("Keyword: %s has invalid size(%d), must be either nactive:%d or nx*ny*nz:%d" % (ecl_kw.name , ecl_kw.size , self.nactive ,self.size)) - + err_msg_fmt = 'Keyword "%s" has invalid size %d; must be either nactive=%d or nx*ny*nz=%d' + err_msg = err_msg_fmt % (ecl_kw, len(ecl_kw), self.getNumActive(), + self.getGlobalSize()) + raise ValueError(err_msg) + def save_grdecl(self , pyfile, output_unit = EclUnitTypeEnum.ECL_METRIC_UNITS): """ Will write the the grid content as grdecl formatted keywords. @@ -1145,7 +1091,7 @@ class EclGrid(BaseCClass): Will only write the main grid. """ cfile = CFILE( pyfile ) - self._fprintf_grdecl( cfile , output_unit) + self._fprintf_grdecl2( cfile , output_unit) def save_EGRID( self , filename , output_unit = EclUnitTypeEnum.ECL_METRIC_UNITS): """ @@ -1159,7 +1105,7 @@ class EclGrid(BaseCClass): """ self._fwrite_GRID2( filename, output_unit ) - + def write_grdecl( self , ecl_kw , pyfile , special_header = None , default_value = 0): """ Writes an EclKW instance as an ECLIPSE grdecl formatted file. @@ -1167,8 +1113,8 @@ class EclGrid(BaseCClass): The input argument @ecl_kw must be an EclKW instance of size nactive or nx*ny*nz. If the size is nactive the inactive cells will be filled with @default_value; hence the function will - always write nx*ny*nz elements. - + always write nx*ny*nz elements. + The data in the @ecl_kw argument can be of type integer, float, double or bool. In the case of bool the default value must be specified as 1 (True) or 0 (False). @@ -1182,10 +1128,10 @@ class EclGrid(BaseCClass): pyfile.close() """ - + if len(ecl_kw) == self.getNumActive() or len(ecl_kw) == self.getGlobalSize(): cfile = CFILE( pyfile ) - self._fwrite_grdecl2( ecl_kw , special_header , cfile , default_value ) + self._fwrite_grdecl( ecl_kw , special_header , cfile , default_value ) else: raise ValueError("Keyword: %s has invalid size(%d), must be either nactive:%d or nx*ny*nz:%d" % (ecl_kw.getName() , len(ecl_kw) , self.getNumActive() , self.getGlobalSize())) @@ -1198,9 +1144,9 @@ class EclGrid(BaseCClass): def compressedKWCopy(self, kw): if len(kw) == self.getNumActive(): - return kw.copy( ) + return kw.copy( ) elif len(kw) == self.getGlobalSize(): - kw_copy = EclKW( kw.getName() , self.getNumActive() , kw.getEclType()) + kw_copy = EclKW( kw.getName() , self.getNumActive() , kw.data_type) self._compressed_kw_copy( kw_copy , kw) return kw_copy else: @@ -1210,7 +1156,7 @@ class EclGrid(BaseCClass): if len(kw) == self.getGlobalSize( ): return kw.copy( ) elif len(kw) == self.getNumActive(): - kw_copy = EclKW( kw.getName() , self.getGlobalSize() , kw.getEclType()) + kw_copy = EclKW( kw.getName() , self.getGlobalSize() , kw.data_type) kw_copy.assign( default_value ) self._global_kw_copy( kw_copy , kw) return kw_copy @@ -1219,7 +1165,7 @@ class EclGrid(BaseCClass): def exportACTNUMKw(self): - actnum = EclKW.create("ACTNUM" , self.getGlobalSize() , EclTypeEnum.ECL_INT_TYPE) + actnum = EclKW("ACTNUM" , self.getGlobalSize() , EclDataType.ECL_INT) self._init_actnum( actnum.getDataPtr() ) return actnum @@ -1239,7 +1185,7 @@ class EclGrid(BaseCClass): The oil in place calculation shown above could easily be implemented by iterating over the soil kw, however using the - volume keyword has two advantages: + volume keyword has two advantages: 1. The calculation of cell volumes is quite time consuming, by storing the results in a kw they can be reused. @@ -1250,9 +1196,6 @@ class EclGrid(BaseCClass): By default the kw will only have values for the active cells, but by setting the optional variable @active_size to False you will get volume values for all cells in the grid. - """ + """ return self._create_volume_keyword( active_size ) - - - diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_grid_generator.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_grid_generator.py new file mode 100644 index 0000000000..827ac6ac2d --- /dev/null +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_grid_generator.py @@ -0,0 +1,351 @@ +# Copyright (C) 2017 Statoil ASA, Norway. +# +# The file 'ecl_grid_generator.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. + +import itertools +import numpy + +from ert.util import IntVector +from ert.ecl import EclGrid, EclKW, EclDataType, EclPrototype + +class EclGridGenerator: + + _alloc_rectangular = EclPrototype("ecl_grid_obj ecl_grid_alloc_rectangular( int , int , int , double , double , double , int*)" , bind = False) + + @classmethod + def createRectangular(cls, dims , dV , actnum = None): + """ + Will create a new rectangular grid. @dims = (nx,ny,nz) @dVg = (dx,dy,dz) + + With the default value @actnum == None all cells will be active, + """ + if actnum is None: + ecl_grid = cls._alloc_rectangular( dims[0] , dims[1] , dims[2] , dV[0] , dV[1] , dV[2] , None ) + else: + if not isinstance(actnum , IntVector): + tmp = IntVector(initial_size = len(actnum)) + for (index , value) in enumerate(actnum): + tmp[index] = value + actnum = tmp + + if not len(actnum) == dims[0] * dims[1] * dims[2]: + raise ValueError("ACTNUM size mismatch: len(ACTNUM):%d Expected:%d" % (len(actnum) , dims[0] * dims[1] * dims[2])) + ecl_grid = cls._alloc_rectangular( dims[0] , dims[1] , dims[2] , dV[0] , dV[1] , dV[2] , actnum.getDataPtr() ) + + # If we have not succeeded in creatin the grid we *assume* the + # error is due to a failed malloc. + if ecl_grid is None: + raise MemoryError("Failed to allocated regualar grid") + + return ecl_grid + + @classmethod + def createSingleCellGrid(cls, corners): + """ + Provided with the corners of the grid in a similar manner as the eight + corners are output for a single cell, this method will create a grid + consisting of a single cell with the specified corners as its corners. + """ + + zcorn = [corners[i][2] for i in range(8)] + + flatten = lambda l : [elem for sublist in l for elem in sublist] + coord = [(corners[i], corners[i+4]) for i in range(4)] + coord = flatten(flatten(coord)) + + def constructFloatKW(name, values): + kw = EclKW(name, len(values), EclDataType.ECL_FLOAT) + for i in range(len(values)): + kw[i] = values[i] + return kw + + grid = EclGrid.create((1,1,1), constructFloatKW("ZCORN", zcorn), constructFloatKW("COORD", coord), None) + + if not corners == [grid.getCellCorner(i, 0) for i in range(8)]: + raise AssertionError("Failed to generate single cell grid. " + + "Did not end up the expected corners.") + + return grid + + @classmethod + def createGrid(cls, dims, dV, offset=1, + escape_origo_shift=(1,1,0), + irregular_offset=False, irregular=False, concave=False, + faults=False, scale=1, translation=(0,0,0), rotate=False, + misalign=False): + """ + Will create a new grid where each cell is a parallelogram (skewed by z-value). + The number of cells are given by @dims = (nx, ny, nz) and the dimention + of each cell by @dV = (dx, dy, dz). + + All cells are guaranteed to not be self-intersecting. Hence, no twisted + cells and somewhat meaningfull cells. + + @offset gives how much the layers should fluctuate or "wave" as you + move along the X-axis. + + @irregular_offset decides whether the offset should be constant or + increase by dz/2 every now and then. + + @irregular if true some of the layers will be inclining and others + declining at the start. + + @concave decides whether the cells are to be convex or not. In + particular, if set to False, all cells of the grid will be concave. + + @escape_origo_shift is used to prevent any cell of having corners in (0,0,z) + as there is a heuristic in ecl_grid.c that marks such cells as tainted. + + @faults decides if there are to be faults in the grid. + + @scale A positive number that scales the "lower" endpoint of all + coord's. In particular, @scale != 1 creates trapeziod cells in both the XZ + and YZ-plane. + + @translation the lower part of the grid is translated ("slided") by the specified + additive factor. + + @rotate the lower part of the grid is rotated 90 degrees around its + center. + + @misalign will toggle COORD's slightly in various directions to break + alignment + + Note that cells in the lowermost layer can have multiple corners + at the same point. + + For testing it should give good coverage of the various scenarios this + method can produce, by leting @dims be (10,10,10), @dV=(2,2,2), @offset=1, + and try all 4 different configurations of @concave and + @irregular_offset. + """ + + nx, ny, nz = dims + dx, dy, dz = dV + + # Validate arguments + if min(dims + dV) <= 0: + raise ValueError("Expected positive grid and cell dimentions") + + if offset < 0: + raise ValueError("Expected non-negative offset") + + if irregular and offset + (dz/2. if irregular_offset else 0) > dz: + raise AssertionError("Arguments can result in self-" + + "intersecting cells. Increase dz, deactivate eiter " + + "irregular or irregular_offset, or decrease offset to avoid " + + "any problems") + + verbose = lambda l : [elem for elem in l for i in range(2)][1:-1:] + flatten = lambda l : [elem for sublist in l for elem in sublist] + + # Compute zcorn + z = escape_origo_shift[2] + zcorn = [z]*(4*nx*ny) + for k in range(nz-1): + z = z+dz + local_offset = offset + (dz/2. if irregular_offset and k%2 == 0 else 0) + + layer = [] + for i in range(ny+1): + shift = ((i if concave else 0) + (k/2 if irregular else 0)) % 2 + path = [z if i%2 == shift else z+local_offset for i in range(nx+1)] + layer.append(verbose(path)) + + zcorn = zcorn + (2*flatten(verbose(layer))) + + z = z+dz + zcorn = zcorn + ([z]*(4*nx*ny)) + + if faults: + # Ensure that drop does not align with grid structure + drop = (offset+dz)/2. if abs(offset-dz/2.) > 0.2 else offset + 0.4 + zcorn = cls.__createFaults(nx, ny, nz, zcorn, drop) + + cls.assertZcorn(nx, ny, nz, zcorn) + + # Compute coord + coord = [] + for j, i in itertools.product(range(ny+1), range(nx+1)): + x, y = i*dx+escape_origo_shift[0], j*dy+escape_origo_shift[1] + coord = coord + [x, y, escape_origo_shift[2], x, y, z] + + # Apply transformations + lower_center = ( + nx*dx/2. + escape_origo_shift[0], + ny*dy/2. + escape_origo_shift[1] + ) + + if misalign: + coord = cls.__misalignCoord(coord, dims, dV) + + coord = cls.__scaleCoord(coord, scale, lower_center) + + if rotate: + coord = cls.__rotateCoord(coord, lower_center) + + coord = cls.__translateCoord(coord, translation) + + cls.assertCoord(nx, ny, nz, coord) + + # Construct grid + def constructFloatKW(name, values): + kw = EclKW(name, len(values), EclDataType.ECL_FLOAT) + for i in range(len(values)): + kw[i] = values[i] + return kw + + return EclGrid.create(dims, constructFloatKW("ZCORN", zcorn), constructFloatKW("COORD", coord), None) + + @classmethod + def __createFaults(cls, nx, ny, nz, zcorn, drop): + """ + Will create several faults consisting of all cells such that either its + i or j index is 1 modulo 3. + """ + + plane_size = 4*nx*ny + for x, y, z in itertools.product(range(nx), range(ny), range(nz)): + if x%3 != 1 and y%3 != 1: + continue + + corner = [0]*8 + corner[0] = 2*z*plane_size + 4*y*nx + 2*x + corner[1] = corner[0] + 1 + corner[2] = corner[0] + 2*nx + corner[3] = corner[2] + 1 + + for i in range(4, 8): + corner[i] = corner[i-4] + plane_size + + for c in corner: + zcorn[c] = zcorn[c] + drop + + return zcorn + + @classmethod + def assertZcorn(cls, nx, ny, nz, zcorn): + """ + + Raises an AssertionError if the zcorn is not as expected. In + patricular, it is verified that: + + - zcorn has the approperiate length (8*nx*ny*nz) and + - that no cell is twisted. + + """ + + if len(zcorn) != 8*nx*ny*nz: + raise AssertionError( + "Expected len(zcorn) to be %d, was %d" % + (8*nx*ny*nz, len(zcorn)) + ) + + plane_size = 4*nx*ny + for p in range(8*nx*ny*nz - plane_size): + if zcorn[p] > zcorn[p + plane_size]: + raise AssertionError( + "Twisted cell was created. " + + "Decrease offset or increase dz to avoid this!" + ) + + @classmethod + def __scaleCoord(cls, coord, scale, lower_center): + coord = numpy.array([ + map(float, coord[i:i+6:]) + for i in range(0, len(coord), 6) + ]) + origo = numpy.array(3*[0.] + list(lower_center) + [0]) + scale = numpy.array(3*[1.] + 2*[scale] + [1]) + + coord = scale * (coord-origo) + origo + return coord.flatten().tolist() + + @classmethod + def __misalignCoord(cls, coord, dims, dV): + nx, ny, nz = dims + + coord = numpy.array([ + map(float, coord[i:i+6:]) + for i in range(0, len(coord), 6) + ]) + + adjustment = numpy.array([ + (0, 0, 0, i*dV[0]/2., j*dV[1]/2., 0) for i, j in itertools.product([-1, 0, 1], repeat=2) + ]) + + for i, c in enumerate(coord): + # Leave the outermost coords alone + if i < nx+1 or i >= len(coord)-(nx+1): + continue + if i%(nx+1) in [0, nx]: + continue + + c += adjustment[i%len(adjustment)] + + return coord.flatten().tolist() + + @classmethod + def __rotateCoord(cls, coord, lower_center): + coord = numpy.array([ + map(float, coord[i:i+6:]) + for i in range(0, len(coord), 6) + ]) + + origo = numpy.array(3*[0.] + list(lower_center) + [0]) + coord -= origo + + for c in coord: + c[3], c[4] = -c[4], c[3] + + coord += origo + return coord.flatten().tolist() + + @classmethod + def __translateCoord(cls, coord, translation): + coord = numpy.array([ + map(float, coord[i:i+6:]) + for i in range(0, len(coord), 6) + ]) + translation = numpy.array(3*[0.] + list(translation)) + + coord = coord + translation + return coord.flatten().tolist() + + @classmethod + def assertCoord(cls, nx, ny, nz, coord): + """ + + Raises an AssertionError if the coord is not as expected. In + particular, it is verfied that: + + - coord has the approperiate length (6*(nx+1)*(ny+1)) and + - that all values are positive. + + """ + + if len(coord) != 6*(nx+1)*(ny+1): + raise AssertionError( + "Expected len(coord) to be %d, was %d" % + (6*(nx+1)*(ny+1), len(coord)) + ) + + if min(coord) < 0: + raise AssertionError("Negative COORD values was generated. " + + "This is likely due to a tranformation. " + + "Increasing the escape_origio_shift will most likely " + + "fix the problem") + + diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_kw.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_kw.py index 2ea130f0da..7678e61dba 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_kw.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_kw.py @@ -1,18 +1,18 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'ecl_kw.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. +# Copyright (C) 2011 Statoil ASA, Norway. +# +# The file 'ecl_kw.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. """ Support for working with one keyword from ECLIPSE file. @@ -22,11 +22,11 @@ of a simple header and blocks of data. A keyword typically looks like: 'SWAT ' 10000 'REAL' 0.05 0.08 0.08 0.10 0.11 0.11 0.10 0.09 - .... + .... I.e. it starts with of header consisting of a 8 characters name, a length and a datatype, immediately followed by the actual -data. +data. Altough the term "restart format" is used to describe the format, this particular format is not limited to restart files; it is (at least) @@ -37,24 +37,42 @@ files. This module also has (some) support for working with GRDECL The ecl_kw.py implementation wraps the ecl_kw.c implementation from the libecl library. """ + +from __future__ import absolute_import, division, print_function, unicode_literals + import ctypes -import types import warnings import numpy from cwrap import CFILE, BaseCClass +from ert.ecl import EclDataType from ert.ecl import EclTypeEnum, EclUtil, EclPrototype +def dump_type_deprecation_warning(): + warnings.warn("EclTypeEnum is deprecated. " + + "You should instead provide an EclDataType", + DeprecationWarning) -class classprop(object): - def __init__(self , f): - self.f = classmethod( f ) - - def __get__(self , *a): - return self.f.__get__(*a)() - +def constant_size_data_type(ecl_type): + return (ecl_type in [ + EclTypeEnum.ECL_CHAR_TYPE, + EclTypeEnum.ECL_FLOAT_TYPE, + EclTypeEnum.ECL_DOUBLE_TYPE, + EclTypeEnum.ECL_INT_TYPE, + EclTypeEnum.ECL_BOOL_TYPE, + EclTypeEnum.ECL_MESS_TYPE + ]) +def warn_and_cast_data_type(data_type): + if isinstance(data_type, EclDataType): + return data_type + if isinstance(data_type, EclTypeEnum): + if not constant_size_data_type(data_type): + raise ValueError("Cannot cast EclTypeEnum (%d) to EclDataType due " + "to non-constant size. Please provide an EclDataType instead.") + dump_type_deprecation_warning() + return EclDataType(data_type) class EclKW(BaseCClass): """ @@ -75,11 +93,11 @@ class EclKW(BaseCClass): int_kw_set = set( ["PVTNUM" , "FIPNUM" , "EQLNUM" , "FLUXNUM" , "MULTNUM" , "ACTNUM" , "SPECGRID" , "REGIONS"] ) TYPE_NAME = "ecl_kw" - _alloc_new = EclPrototype("void* ecl_kw_alloc( char* , int , ecl_type_enum )", bind = False) + _alloc_new = EclPrototype("void* ecl_kw_alloc_python( char* , int , ecl_data_type )", bind = False) _fread_alloc = EclPrototype("ecl_kw_obj ecl_kw_fread_alloc( fortio )" , bind = False) - _load_grdecl = EclPrototype("ecl_kw_obj ecl_kw_fscanf_alloc_grdecl_dynamic__( FILE , char* , bool , int )" , bind = False) + _load_grdecl = EclPrototype("ecl_kw_obj ecl_kw_fscanf_alloc_grdecl_dynamic_python( FILE , char* , bool , ecl_data_type )" , bind = False) _fseek_grdecl = EclPrototype("bool ecl_kw_grdecl_fseek_kw(char* , bool , FILE )" , bind = False) - + _sub_copy = EclPrototype("ecl_kw_obj ecl_kw_alloc_sub_copy( ecl_kw , char*, int , int)") _copyc = EclPrototype("ecl_kw_obj ecl_kw_alloc_copy( ecl_kw )") _slice_copyc = EclPrototype("ecl_kw_obj ecl_kw_alloc_slice_copy( ecl_kw , int , int , int )") @@ -103,6 +121,7 @@ class EclKW(BaseCClass): _fwrite = EclPrototype("void ecl_kw_fwrite( ecl_kw , fortio )") _get_header = EclPrototype("char* ecl_kw_get_header ( ecl_kw )") _set_header = EclPrototype("void ecl_kw_set_header_name ( ecl_kw , char*)") + _get_data_type = EclPrototype("ecl_data_type_obj ecl_kw_get_data_type_python(ecl_kw)"); _int_sum = EclPrototype("int ecl_kw_element_sum_int( ecl_kw )") _float_sum = EclPrototype("double ecl_kw_element_sum_float( ecl_kw )") @@ -114,12 +133,11 @@ class EclKW(BaseCClass): _equal = EclPrototype("bool ecl_kw_equal( ecl_kw , ecl_kw )") _equal_numeric = EclPrototype("bool ecl_kw_numeric_equal( ecl_kw , ecl_kw , double , double)") - _assert_binary = EclPrototype("bool ecl_kw_assert_binary_numeric( ecl_kw , ecl_kw )") + _assert_binary = EclPrototype("bool ecl_kw_size_and_numeric_type_equal( ecl_kw , ecl_kw )") _scale_int = EclPrototype("void ecl_kw_scale_int( ecl_kw , int )") _scale_float = EclPrototype("void ecl_kw_scale_float_or_double( ecl_kw , double )") _shift_int = EclPrototype("void ecl_kw_shift_int( ecl_kw , int )") _shift_float = EclPrototype("void ecl_kw_shift_float_or_double( ecl_kw , double )") - _assert_numeric = EclPrototype("bool ecl_kw_assert_numeric( ecl_kw )") _copy_data = EclPrototype("void ecl_kw_memcpy_data( ecl_kw , ecl_kw )") _set_int = EclPrototype("void ecl_kw_scalar_set_int( ecl_kw , int )") _set_float = EclPrototype("void ecl_kw_scalar_set_float_or_double( ecl_kw , double )") @@ -130,7 +148,7 @@ class EclKW(BaseCClass): _fix_uninitialized = EclPrototype("void ecl_kw_fix_uninitialized( ecl_kw ,int , int , int, int*)") _first_different = EclPrototype("int ecl_kw_first_different( ecl_kw , ecl_kw , int , double, double)") _resize = EclPrototype("void ecl_kw_resize( ecl_kw , int)") - + @classmethod def createCReference(cls, c_ptr, parent=None): ecl_kw = super(EclKW, cls).createCReference(c_ptr , parent = parent) @@ -150,8 +168,8 @@ class EclKW(BaseCClass): ecl_kw.__private_init() return ecl_kw - - + + @classmethod def add_int_kw(cls , kw): """Will add keyword @kw to the standard set of integer keywords.""" @@ -162,57 +180,29 @@ class EclKW(BaseCClass): """Will remove keyword @kw from the standard set of integer keywords.""" cls.int_kw_set.discard( kw ) - @classprop - def int_kw( cls ): - warnings.warn("The EclKW.int_kw class property has been deprecated - use class method: EclKW.intKeywords( )" , DeprecationWarning ) - return cls.intKeywords( ) - - @classmethod def intKeywords(cls): """Will return the current set of integer keywords.""" return cls.int_kw_set - - - @classmethod - def create( cls , name, size , data_type): - """ - Creates a brand new EclKW instance. - - This method will create a grand spanking new EclKW - instance. The instance will get name @name (silently truncated - to eight characters), @size elements and datatype @data_type. Using - this method you could create a SOIL keyword with: - - soil_kw = EclKW.create( "SOIL" , 10000 , ECL_FLOAT_TYPE ) - - """ - warnings.warn("The EclKW.create( ) method has been deprecated - use EclKW( %s , %s , %s )" % (name , size , data_type) , DeprecationWarning ) - return cls( name , size , data_type ) - - - - - def slice_copy( self , slice_range ): (start , stop , step) = slice_range.indices( len(self) ) if stop > start: return self._slice_copyc( start , stop , step) else: return None - + def copy( self ): """ Will create a deep copy of the current kw instance. """ return self._copyc( ) - - + + @classmethod def read_grdecl( cls , fileH , kw , strict = True , ecl_type = None): """ @@ -220,7 +210,7 @@ class EclKW(BaseCClass): This constructor can be used to load an EclKW instance from a grdecl formatted file; the input files for petrophysical - properties are typically given as grdecl files. + properties are typically given as grdecl files. The @file argument should be a Python filehandle to an open file. The @kw argument should be the keyword header you are @@ -236,7 +226,7 @@ class EclKW(BaseCClass): program to create grdecl files with more than 8 character length headers, this implementation will refuse to even try loading them. In that case you will have to rename the - keywords in your file - sorry. A TypeError exception + keywords in your file - sorry. A TypeError exception will be raised if @kw has more than 8 characters. The implementation in ert can read integer and float type @@ -247,12 +237,12 @@ class EclKW(BaseCClass): of presedence, is as follows: 1. The optional argument @ecl_type can be used to specify - the type: + the type: - special_int_kw = EclKW.read_grdecl( fileH , 'INTKW' , ecl_type = ECL_INT_TYPE ) + special_int_kw = EclKW.read_grdecl( fileH , 'INTKW' , ecl_type = ECL_INT ) - If ecl_type is different from ECL_INT_TYPE or - ECL_FLOAT_TYPE a TypeError exception will be raised. + If ecl_type is different from ECL_INT or + ECL_FLOAT a TypeError exception will be raised. If ecl_type == None (the default), the method will continue to point 2. or 3. to determine the correct type. @@ -262,44 +252,50 @@ class EclKW(BaseCClass): 'int_kw_set' the type will be ECL_INT_TYPE. pvtnum_kw = EclKW.read_grdecl( fileH , 'PVTNUM' ) - + Observe that (currently) no case conversions take place when checking the 'int_kw_set'. The current built in set is accesible through the int_kw property. - 3. Otherwise the default is float, i.e. ECL_FLOAT_TYPE. + 3. Otherwise the default is float, i.e. ECL_FLOAT. + EclKw reads grdecl with EclDataType poro_kw = EclKW.read_grdecl( fileH , 'PORO') - + Observe that since the grdecl files are quite weakly structured it is difficult to verify the integrity of the files, malformed input might therefor pass unnoticed before things blow up at a later stage. - + [1]: It is possible, but not recommended, to pass in None for @kw, in which case the method will load the first keyword it finds in the file. """ - + cfile = CFILE( fileH ) if kw: if len(kw) > 8: raise TypeError("Sorry keyword:%s is too long, must be eight characters or less." % kw) - + if ecl_type is None: if cls.int_kw_set.__contains__( kw ): - ecl_type = EclTypeEnum.ECL_INT_TYPE + ecl_type = EclDataType.ECL_INT else: - ecl_type = EclTypeEnum.ECL_FLOAT_TYPE + ecl_type = EclDataType.ECL_FLOAT - if not ecl_type in [EclTypeEnum.ECL_FLOAT_TYPE , EclTypeEnum.ECL_INT_TYPE]: - raise TypeError("The type:%d is invalid when loading keyword:%s" % (ecl_type , kw)) + ecl_type = warn_and_cast_data_type(ecl_type) + + if not isinstance(ecl_type, EclDataType): + raise TypeError("Expected EclDataType, was: %s" % type(ecl_type)) + + if not ecl_type in [EclDataType.ECL_FLOAT , EclDataType.ECL_INT]: + raise ValueError("The type:%s is invalid when loading keyword:%s" % (ecl_type.type_name, kw)) return cls._load_grdecl( cfile , kw , strict , ecl_type ) - + @classmethod def fseek_grdecl( cls , fileH , kw , rewind = False): """ @@ -309,7 +305,7 @@ class EclKW(BaseCClass): pointer will be positioned at the start of the kw, if the search fails the function will return false and the file pointer will be repositioned at the position it had prior to - the call. + the call. Only @kw instances which are found at the beginning of a line (with optional leading space characters) are considered, @@ -318,7 +314,7 @@ class EclKW(BaseCClass): -- PERMX EQUIL PERMX / - + The function will start searching from the current position in the file and forwards, if the optional argument @rewind is @@ -327,15 +323,6 @@ class EclKW(BaseCClass): """ cfile = CFILE( fileH ) return cls._fseek_grdecl( kw , rewind , cfile) - - - - @classmethod - def grdecl_load( cls , file , kw , ecl_type = EclTypeEnum.ECL_FLOAT_TYPE): - """Use read_grdecl() instead.""" - warnings.warn("The grdecl_load method has been renamed to read_grdecl()" , DeprecationWarning) - return cls.read_grdecl(file , kw , ecl_type ) - @classmethod @@ -373,42 +360,47 @@ class EclKW(BaseCClass): """ if len(name) > 8: raise ValueError("Sorry - maximum eight characters in keyword name") + + data_type = warn_and_cast_data_type(data_type) + + if not isinstance(data_type, EclDataType): + raise TypeError("Expected an EclDataType, received: %s" % + type(data_type)) + c_ptr = self._alloc_new( name , size , data_type ) super(EclKW, self).__init__(c_ptr) self.__private_init() - + def __private_init(self): self.data_ptr = None - ecl_type = self._get_type( ) - if ecl_type == EclTypeEnum.ECL_INT_TYPE: + if self.data_type.is_int(): self.data_ptr = self._int_ptr( ) - self.dtype = numpy.int32 + self.dtype = numpy.int32 self.str_fmt = "%8d" - elif ecl_type == EclTypeEnum.ECL_FLOAT_TYPE: + elif self.data_type.is_float(): self.data_ptr = self._float_ptr( ) self.dtype = numpy.float32 self.str_fmt = "%13.4f" - elif ecl_type == EclTypeEnum.ECL_DOUBLE_TYPE: + elif self.data_type.is_double(): self.data_ptr = self._double_ptr( ) - self.dtype = numpy.float64 + self.dtype = numpy.float64 self.str_fmt = "%13.4f" else: # Iteration not supported for CHAR / BOOL self.data_ptr = None self.dtype = None - if ecl_type == EclTypeEnum.ECL_CHAR_TYPE: + if self.data_type.is_char(): self.str_fmt = "%8s" - elif ecl_type == EclTypeEnum.ECL_BOOL_TYPE: + elif self.data_type.is_bool(): self.str_fmt = "%d" - else: + elif self.data_type.is_mess(): self.str_fmt = "%s" #"Message type" - - + else: + raise ValueError("Unknown EclDataType (%s)!" % self.data_type.type_name) - def sub_copy(self , offset , count , new_header = None): """ Will create a new block copy of the src keyword. @@ -423,25 +415,24 @@ class EclKW(BaseCClass): new1 = src.sub_copy(0 , 10, new_header = "NEW1") new2 = src.sub_copy(10 , -1 , new_header = "NEW2") - + If the count or index arguments are in some way invalid the method will raise IndexError. """ - if offset < 0 or offset >= self.size: - raise IndexError("Offset:%d invalid - valid range:[0,%d)" % (offset , self.size)) + if offset < 0 or offset >= len(self): + raise IndexError("Offset:%d invalid - valid range:[0,%d)" % (offset , len(self))) - if offset + count > self.size: + if offset + count > len(self): raise IndexError("Invalid value of (offset + count):%d" % (offset + count)) return self._sub_copy( new_header , offset , count ) - + def isNumeric(self): """ Will check if the keyword contains numeric data, i.e int, float or double. """ - return self._assert_numeric( ) - + return self.data_type.is_numeric() def ecl_kw_instance( self ): return True @@ -454,7 +445,7 @@ class EclKW(BaseCClass): """ return self._get_size( ) - + def __deep_copy__(self , memo): """ Python special routine used to perform deep copy. @@ -471,7 +462,7 @@ class EclKW(BaseCClass): length = self.__len__() if index < 0: # We allow one level of negative indexing - index += self.size + index += len(self) if index < 0 or index >= length: raise IndexError @@ -479,10 +470,9 @@ class EclKW(BaseCClass): if self.data_ptr: return self.data_ptr[ index ] else: - ecl_type = self.getEclType( ) - if ecl_type == EclTypeEnum.ECL_BOOL_TYPE: + if self.data_type.is_bool(): return self._iget_bool( index) - elif ecl_type == EclTypeEnum.ECL_CHAR_TYPE: + elif self.data_type.is_char(): return self._iget_char_ptr( index ) else: raise TypeError("Internal implementation error ...") @@ -496,11 +486,11 @@ class EclKW(BaseCClass): """ Function to support index based assignment: kw[index] = value """ - if isinstance( index , types.IntType): + if isinstance( index , int): length = len(self) if index < 0: # Will only wrap backwards once - index = self.size + index + index = len(self) + index if index < 0 or index >= length: raise IndexError @@ -508,10 +498,9 @@ class EclKW(BaseCClass): if self.data_ptr: self.data_ptr[ index ] = value else: - ecl_type = self.getEclType( ) - if ecl_type == EclTypeEnum.ECL_BOOL_TYPE: + if self.data_type.is_bool(): self._iset_bool( index , value) - elif ecl_type == EclTypeEnum.ECL_CHAR_TYPE: + elif self.data_type.is_char(): return self._iset_char_ptr( index , value) else: raise SystemError("Internal implementation error ...") @@ -526,7 +515,7 @@ class EclKW(BaseCClass): ################################################################# - + def __IMUL__(self , factor , mul = True): if self.isNumeric(): @@ -542,8 +531,7 @@ class EclKW(BaseCClass): if not mul: factor = 1.0 / factor - ecl_type = self.getEclType( ) - if ecl_type == EclTypeEnum.ECL_INT_TYPE: + if self.data_type.is_int(): if isinstance( factor , int ): self._scale_int( factor ) else: @@ -555,9 +543,9 @@ class EclKW(BaseCClass): raise TypeError("Only muliplication with scalar supported") else: raise TypeError("Not numeric type") - + return self - + def __IADD__(self , delta , add = True): if self.isNumeric(): @@ -575,8 +563,7 @@ class EclKW(BaseCClass): else: sign = -1 - ecl_type = self.getEclType( ) - if ecl_type == EclTypeEnum.ECL_INT_TYPE: + if self.data_type.is_int(): if isinstance( delta , int ): self._shift_int( delta * sign) else: @@ -588,7 +575,7 @@ class EclKW(BaseCClass): raise TypeError("Type mismatch") else: raise TypeError("Type / size mismatch") - + return self def __iadd__(self , delta): @@ -605,7 +592,7 @@ class EclKW(BaseCClass): ################################################################# - + def __abs__(self): if self.isNumeric(): copy = self.copy() @@ -613,9 +600,9 @@ class EclKW(BaseCClass): return copy else: raise TypeError("The __abs__() function is only implemented for numeric types") - - + + def __add__(self , delta): copy = self.copy() copy += delta @@ -630,8 +617,8 @@ class EclKW(BaseCClass): return copy def __rsub__( self , delta): - return self.__sub__( delta ) * -1 - + return self.__sub__( delta ) * -1 + def __mul__(self , factor): copy = self.copy() copy *= factor @@ -639,12 +626,12 @@ class EclKW(BaseCClass): def __rmul__(self , factor): return self.__mul__( factor ) - + def __div__(self , factor): copy = self.copy() copy /= factor return copy - + # No __rdiv__() def sum(self): @@ -654,21 +641,20 @@ class EclKW(BaseCClass): String: Raise ValueError exception. Bool: The number of true values """ - ecl_type = self.getEclType( ) - if ecl_type == EclTypeEnum.ECL_CHAR_TYPE: - raise ValueError("The keyword:%s is of string type - sum is not implemented" % self.get_name()) - elif ecl_type == EclTypeEnum.ECL_INT_TYPE: + if self.data_type.is_int(): return self._int_sum( ) - elif ecl_type == EclTypeEnum.ECL_FLOAT_TYPE: + elif self.data_type.is_float(): return self._float_sum( ) - elif ecl_type == EclTypeEnum.ECL_DOUBLE_TYPE: + elif self.data_type.is_double(): return self._float_sum( ) - elif ecl_type == EclTypeEnum.ECL_BOOL_TYPE: + elif self.data_type.is_bool(): sum = 0 for elm in self: if elm: sum += 1 return sum + else: + raise ValueError('The keyword "%s" is of string type - sum is not implemented' % self.getName()) @@ -680,7 +666,7 @@ class EclKW(BaseCClass): return self._assert_binary( other ) ################################################################# - + def assign(self , value , mask = None , force_active = False): """ Assign a value to current kw instance. @@ -698,7 +684,7 @@ class EclKW(BaseCClass): to only parts of the EclKW. In the example below we select all the elements with PORO below 0.10, and then assign EQLNUM value 88 to those cells: - + grid = ecl.EclGrid("ECLIPSE.EGRID") reg = ecl.EclRegion( grid , false ) init = ecl.EclFile("ECLIPSE.INIT") @@ -706,9 +692,9 @@ class EclKW(BaseCClass): poro = init["PORO"][0] eqlnum = init["EQLNUM"][0] reg.select_below( poro , 0.10 ) - + eqlnum.assign( 88 , mask = reg ) - + The EclRegion instance has two equivalent sets of selected indices; one consisting of active indices and one consisting of global indices. By default the assign() method will select @@ -732,8 +718,7 @@ class EclKW(BaseCClass): if mask: mask.set_kw( self , value , force_active ) else: - ecl_type = self.getEclType( ) - if ecl_type == EclTypeEnum.ECL_INT_TYPE: + if self.data_type.is_int(): if isinstance( value , int ): self._set_int( value ) else: @@ -754,7 +739,7 @@ class EclKW(BaseCClass): mask.iadd_kw( self , other , force_active ) else: return self.__iadd__( other ) - + def sub(self , other , mask = None , force_active = False): """ See method assign() for documentation of optional arguments @@ -804,7 +789,7 @@ class EclKW(BaseCClass): kw.apply( math.sin ) kw.apply( cutoff , arg = 0.10 ) - + See method assign() for documentation of optional arguments @mask and @force_active. """ @@ -818,10 +803,10 @@ class EclKW(BaseCClass): self.data_ptr[index] = func( self.data_ptr[index] ) else: if arg: - for i in range(self.size): + for i in range(len(self)): self.data_ptr[i] = func( self.data_ptr[i] , arg) else: - for i in range(self.size): + for i in range(len(self)): self.data_ptr[i] = func( self.data_ptr[i] ) @@ -879,61 +864,15 @@ class EclKW(BaseCClass): The number of bytes this keyword would occupy in a BINARY file. """ return self._get_fortio_size( ) - - - @property - def fortio_size(self): - warnings.warn("The fortio_size property is deprecated - use method fortIOSize()" , DeprecationWarning) - return self.fortIOSize() - - - @property - def size(self): - warnings.warn("The size property is deprecated - use built in len(..) " , DeprecationWarning) - return len(self) def setName( self , name ): if len(name) > 8: raise ValueError("Sorry: the name property must be max 8 characters long :-(") self._set_header( name ) - - def set_name( self , name ): - warnings.warn("The set_name method is deprectaed - use setName( )" , DeprecationWarning) - self.setName( name ); - - - def get_name( self ): - warnings.warn("The set_name method is deprectaed - use getName( )" , DeprecationWarning) - return self.getName() - - - name = property( get_name , set_name ) - def getName(self): - return self._get_header( ) - - - @property - def min_max( self ): - warnings.warn("The min_max property has been renamed to method getMinMax()" , DeprecationWarning) - return self.getMinMax() - - - @property - def max( self ): - warnings.warn("The max property has been renamed to method getMax()" , DeprecationWarning) - mm = self.getMinMax() - return mm[1] - - - @property - def min( self ): - warnings.warn("The min property has been renamed to method getMin()" , DeprecationWarning) - mm = self.getMinMax() - return mm[0] - - + n = self._get_header( ) + return str(n) if n else '' def resize(self , new_size): """ @@ -947,7 +886,7 @@ class EclKW(BaseCClass): # need to call the __private_init() method again. self.__private_init() - + def getMinMax(self): """ Will return a touple (min,max) for numerical types. @@ -955,16 +894,15 @@ class EclKW(BaseCClass): Will raise TypeError exception if the keyword is not of numerical type. """ - ecl_type = self.getEclType( ) - if ecl_type == EclTypeEnum.ECL_FLOAT_TYPE: + if self.data_type.is_float(): min_ = ctypes.c_float() max_ = ctypes.c_float() self._max_min_float( ctypes.byref( max_ ) , ctypes.byref( min_ )) - elif ecl_type == EclTypeEnum.ECL_DOUBLE_TYPE: + elif self.data_type.is_double(): min_ = ctypes.c_double() max_ = ctypes.c_double() self._max_min_double( ctypes.byref( max_ ) , ctypes.byref( min_ )) - elif ecl_type == EclTypeEnum.ECL_INT_TYPE: + elif self.data_type.is_int(): min_ = ctypes.c_int() max_ = ctypes.c_int() self._max_min_int( ctypes.byref( max_ ) , ctypes.byref( min_ )) @@ -976,47 +914,41 @@ class EclKW(BaseCClass): def getMax( self ): mm = self.getMinMax() return mm[1] - - + + def getMin( self ): mm = self.getMinMax() return mm[0] - - @property - def numeric(self): - warnings.warn("The numeric property has been renamed to method isNumeric()" , DeprecationWarning) - return self.isNumeric( ) - - @property def type( self ): return self.getEclType() @property - def type_name( self ): - return self.typeName( ) + def data_type( self ): + return self._get_data_type() - def typeName(self): - return EclUtil.type_name( self.getEclType( )) + @property + def type_name( self ): + return self.data_type.type_name + + def typeName( self ): + return self.data_type.type_name def getEclType(self): + warnings.warn("EclTypeEnum is deprecated. " + + "You should instead provide an EclDataType", + DeprecationWarning) + return self._get_type( ) - - + + @property - def header( self ): - return (self.name , self.size , self.type_name ) + def header(self): + return (self.getName(), len(self), self.typeName()) - - def iget( self , index ): - from warnings import warn - warn("The iget() method is deprecated use array notation: kw[index] instead.", DeprecationWarning) - return self.__getitem__( index ) - - @property def array(self): a = self.data_ptr @@ -1025,7 +957,7 @@ class EclKW(BaseCClass): a.__parent__ = self # Inhibit GC return a - + def str_data( self , width , index1 , index2 , fmt): """ Helper function for str() method. @@ -1040,7 +972,7 @@ class EclKW(BaseCClass): s+= "\n" return s - + def str(self , width = 5 , max_lines = 10 , fmt = None): """ Return string representation of kw for pretty printing. @@ -1059,19 +991,19 @@ class EclKW(BaseCClass): the elements. The implementation of the builtin method __str__() is based on this method. """ - s = "%-8s %8d %-4s\n" % (self.name , self.size , self.type_name) - lines = self.size / width + s = "%-8s %8d %-4s\n" % (self.getName() , len(self) , self.typeName()) + lines = len(self) // width if not fmt: fmt = self.str_fmt + " " if max_lines is None or lines <= max_lines: - s += self.str_data( width , 0 , self.size , fmt) + s += self.str_data( width , 0 , len(self) , fmt) else: - s1 = width * max_lines / 2 + s1 = width * max_lines // 2 s += self.str_data( width , 0 , s1 , fmt) s += " .... \n" - s += self.str_data( width , self.size - s1 , self.size , fmt) - + s += self.str_data( width , len(self) - s1 , len(self) , fmt) + return s def __str__(self): @@ -1097,7 +1029,7 @@ class EclKW(BaseCClass): ct = ctypes.c_int else: raise ValueError("Invalid type - numpy array only valid for int/float/double") - + ap = ctypes.cast(self.data_ptr, ctypes.POINTER(ct * len(self))) return numpy.frombuffer(ap.contents, dtype = self.dtype) @@ -1113,21 +1045,7 @@ class EclKW(BaseCClass): """ view = self.numpyView( ) return numpy.copy( view ) - - @property - def numpy_array( self ): - warnings.warn("The EclKW.numpy_array property has been deprecated - use method: numpyView( ) or numpyCopy( ) instead" , DeprecationWarning ) - if self.data_ptr: - a = self.array - value = numpy.zeros( a.size , dtype = self.dtype) - for i in range( a.size ): - value[i] = a[i] - - - - - def fwrite( self , fortio ): self._fwrite( fortio ) @@ -1140,20 +1058,20 @@ class EclKW(BaseCClass): opened file. In the example below we load the porosity from an existing GRDECL file, set all poro values below 0.05 to 0.00 and write back an updated GRDECL file. - + poro = ecl.EclKW.load_grdecl( open("poro1.grdecl" , "r") , "PORO" ) grid = ecl.EclGrid( "ECLIPSE.EGRID" ) reg = ecl.EclRegion( grid , False ) - + reg.select_below( poro , 0.05 ) poro.assign( 0.0 , mask = reg ) fileH = open( "poro2.grdecl" , "w") poro.write_grdecl( fileH ) fileH.close() - + """ - cfile = CFILE( file ) + cfile = CFILE( file ) self._fprintf_grdecl( cfile ) @@ -1190,25 +1108,24 @@ class EclKW(BaseCClass): def getDataPtr(self): - ecl_type = self.getEclType( ) - if ecl_type == EclTypeEnum.ECL_INT_TYPE: + if self.data_type.is_int(): return self._int_ptr( ) - elif ecl_type == EclTypeEnum.ECL_FLOAT_TYPE: + elif self.data_type.is_float(): return self._float_ptr( ) - elif ecl_type == EclTypeEnum.ECL_DOUBLE_TYPE: + elif self.data_type.is_double(): return self._double_ptr( ) else: raise ValueError("Only numeric types can export data pointer") - - def firstDifferent(kw1 , kw2 , offset = 0 , epsilon = 0 , abs_epsilon = None , rel_epsilon = None): - if len(kw1) != len(kw2): + + def firstDifferent(self , other , offset = 0 , epsilon = 0 , abs_epsilon = None , rel_epsilon = None): + if len(self) != len(other): raise ValueError("Keywords must have equal size") - if offset >= len(kw1): - raise IndexError("Offset:%d invalid - size:%d" % (offset , len(kw1))) + if offset >= len(self): + raise IndexError("Offset:%d invalid - size:%d" % (offset , len(self))) - if kw1.getEclType() != kw2.getEclType(): + if self.getEclType() != other.getEclType(): raise TypeError("The two keywords have different type") if abs_epsilon is None: @@ -1217,4 +1134,4 @@ class EclKW(BaseCClass): if rel_epsilon is None: rel_epsilon = epsilon - return kw1._first_different( kw2 , offset , abs_epsilon , rel_epsilon ) + return self._first_different( other , offset , abs_epsilon , rel_epsilon ) diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_npv.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_npv.py index 95232fe158..3645b29ca0 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_npv.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_npv.py @@ -29,7 +29,7 @@ class NPVParseKey(object): def __call__(self , matchObject): key = matchObject.group(1) smspecNode = self.baseCase.smspec_node( key ) - if smspecNode.is_total: + if smspecNode.isTotal(): var = key.replace(":" , "_") self.NPV.addKey( key , var ) return var + "[i]" diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_queue.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_queue.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_region.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_region.py index 1dbb1a1d37..c329f3bcff 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_region.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_region.py @@ -1,18 +1,18 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'ecl_region.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. +# Copyright (C) 2011 Statoil ASA, Norway. +# +# The file 'ecl_region.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. """ Module used to select cells based on many different criteria. @@ -26,10 +26,10 @@ When the selection process is complete the region instance can be queried for the corresponding list of indices. """ import ctypes -import warnings + from cwrap import BaseCClass from ert.ecl.faults import Layer -from ert.ecl import EclKW, EclTypeEnum, EclPrototype +from ert.ecl import EclKW, EclDataType, EclPrototype from ert.geo import CPolyline from ert.util import IntVector @@ -87,7 +87,7 @@ class EclRegion(BaseCClass): _scale_kw_float = EclPrototype("void ecl_region_scale_kw_float( ecl_region , ecl_kw , float, bool ) ") _scale_kw_double = EclPrototype("void ecl_region_scale_kw_double( ecl_region , ecl_kw , double , bool) ") - _free = EclPrototype("void ecl_region_free( ecl_region )") + _free = EclPrototype("void ecl_region_free( ecl_region )") _reset = EclPrototype("void ecl_region_reset( ecl_region )") _select_all = EclPrototype("void ecl_region_select_all( ecl_region )") _deselect_all = EclPrototype("void ecl_region_deselect_all( ecl_region )") @@ -101,8 +101,8 @@ class EclRegion(BaseCClass): _deselect_in_interval = EclPrototype("void ecl_region_deselect_in_interval( ecl_region, ecl_kw, float , float )") _invert_selection = EclPrototype("void ecl_region_invert_selection( ecl_region )") - _select_box = EclPrototype("void ecl_region_select_from_ijkbox(ecl_region , int , int , int , int , int , int)") - _deselect_box = EclPrototype("void ecl_region_deselect_from_ijkbox(ecl_region , int , int , int , int , int , int)") + _select_box = EclPrototype("void ecl_region_select_from_ijkbox(ecl_region , int , int , int , int , int , int)") + _deselect_box = EclPrototype("void ecl_region_deselect_from_ijkbox(ecl_region , int , int , int , int , int , int)") _imul_kw = EclPrototype("void ecl_region_kw_imul( ecl_region , ecl_kw , ecl_kw , bool)") _idiv_kw = EclPrototype("void ecl_region_kw_idiv( ecl_region , ecl_kw , ecl_kw , bool)") _iadd_kw = EclPrototype("void ecl_region_kw_iadd( ecl_region , ecl_kw , ecl_kw , bool)") @@ -163,7 +163,7 @@ class EclRegion(BaseCClass): _select_from_layer = EclPrototype("void ecl_region_select_from_layer( ecl_region , layer , int , int)") _deselect_from_layer = EclPrototype("void ecl_region_deselect_from_layer( ecl_region , layer , int , int)") - + def __init__(self , grid , preselect): """ Create a new region selector for cells in @grid. @@ -216,14 +216,14 @@ class EclRegion(BaseCClass): inplace & operator, i.e. reg1 &= reg2 - + will eventually call this method. """ if isinstance(other , EclRegion): self._intersect( other) else: raise TypeError("Ecl region can only intersect with other EclRegion instances") - + return self @@ -239,7 +239,7 @@ class EclRegion(BaseCClass): raise TypeError("Ecl region can only subtract with other EclRegion instances") return self - + def __ior__(self , other): """ @@ -257,7 +257,7 @@ class EclRegion(BaseCClass): self._combine( other) else: raise TypeError("Ecl region can only be combined with other EclRegion instances") - + return self def __iadd__(self , other): @@ -276,7 +276,7 @@ class EclRegion(BaseCClass): operator: new_reg = reg1 | reg2 - + """ new_region = self.copy() new_region.__ior__( other ) @@ -316,19 +316,19 @@ class EclRegion(BaseCClass): def union_with( self, other): """ Will update self with the union of @self and @other. - - See doscumentation of __ior__(). + + See doscumentation of __ior__(). """ return self.__ior__( other ) def intersect_with( self, other): """ Will update self with the intersection of @self and @other. - - See doscumentation of __iand__(). + + See doscumentation of __iand__(). """ return self.__iand__( other ) - + def copy( self ): return self.__deep_copy__( {} ) @@ -346,7 +346,7 @@ class EclRegion(BaseCClass): ################################################################## - + @select_method def select_more( self , ecl_kw , limit , intersect = False): """ @@ -365,13 +365,13 @@ class EclRegion(BaseCClass): swat_kw = restart_file["SWAT"][0] grid = ecl.EclGrid( "ECLIPSE.EGRID" ) region = ecl.EclRegion( grid , False ) - + region.select_more( swat_kw , 0.85 ) """ self._select_more( ecl_kw , limit ) - + def deselect_more( self , ecl_kw , limit): """ @@ -385,7 +385,7 @@ class EclRegion(BaseCClass): def select_less( self , ecl_kw , limit , intersect = False): """ Select all cells where keyword @ecl_kw is below @limit. - + See select_more() for further documentation. """ self._select_less( ecl_kw , limit ) @@ -393,7 +393,7 @@ class EclRegion(BaseCClass): def deselect_less( self , ecl_kw , limit): """ Deselect all cells where keyword @ecl_kw is below @limit. - + See select_more() for further documentation. """ self._deselect_less( ecl_kw , limit ) @@ -412,11 +412,13 @@ class EclRegion(BaseCClass): pvtnum_kw = init_file.iget_named_kw( "PVTNUM" , 0 ) grid = ecl.EclGrid( "ECLIPSE.GRID" ) region = ecl.EclRegion( grid , False ) - + region.select_equal( pvtnum_kw , 2 ) region.select_equal( pvtnum_kw , 4 ) """ + if not ecl_kw.data_type.is_int(): + raise ValueError("The select_equal method must have an integer valued keyword - got:%s" % ecl_kw.typeName( )) self._select_equal( ecl_kw , value ) @@ -426,6 +428,8 @@ class EclRegion(BaseCClass): See select_equal() for further documentation. """ + if not ecl_kw.data_type.is_int(): + raise ValueError("The select_equal method must have an integer valued keyword - got:%s" % ecl_kw.typeName( )) self._deselect_equal( ecl_kw , value ) @select_method @@ -436,8 +440,8 @@ class EclRegion(BaseCClass): Will select all the cells where EclKW instance @ecl_kw has value in the half-open interval [@lower_limit , @upper_limit). The input argument @ecl_kw must have size - nactive or nx*ny*nz, and it must be of type ECL_FLOAT_TYPE. - + nactive or nx*ny*nz, and it must be of type ECL_FLOAT_TYPE. + The following example will select all cells with porosity in the range [0.15,0.20): @@ -445,9 +449,9 @@ class EclRegion(BaseCClass): poro_kw = init_file.iget_named_kw( "PORO" , 0 ) grid = ecl.EclGrid( "ECLIPSE.GRID" ) region = ecl.EclRegion( grid , False ) - + region.select_in_range( poro_kw , 0.15, 0.20 ) - + """ self._select_in_interval( ecl_kw , lower_limit , upper_limit) @@ -494,7 +498,7 @@ class EclRegion(BaseCClass): def select_cmp_more( self , kw1 , kw2 , intersect = False): """ Will select all cells where kw2 > kw1. - + See select_cmp_less() for further documentation. """ self._select_cmp_more( kw1 , kw2 ) @@ -502,7 +506,7 @@ class EclRegion(BaseCClass): def deselect_cmp_more( self , kw1 , kw2): """ Will deselect all cells where kw2 > kw1. - + See select_cmp_less() for further documentation. """ self._deselect_cmp_more( kw1 , kw2 ) @@ -553,7 +557,7 @@ class EclRegion(BaseCClass): """ self.deselect_all() - @select_method + @select_method def select_deep( self , depth , intersect = False): """ Will select all cells below @depth. @@ -566,7 +570,7 @@ class EclRegion(BaseCClass): """ self._deselect_deep_cells(depth) - @select_method + @select_method def select_shallow( self, depth , intersect = False): """ Will select all cells above @depth. @@ -650,7 +654,7 @@ class EclRegion(BaseCClass): def deselect_box( self , ijk1 , ijk2 ): """ Will deselect all elements in box. - + See select_box() for further documentation. """ self._deselect_box( ijk1[0] , ijk2[0] , ijk1[1] , ijk2[1] , ijk1[2] , ijk2[2]) @@ -684,7 +688,7 @@ class EclRegion(BaseCClass): @select_method def select_kslice( self , k1 , k2 , intersect = False): """ - Will select all cells with k in [@k1, @k2]. @i1 and @i2 are zero offset. + Will select all cells with k in [@k1, @k2]. @i1 and @i2 are zero offset. """ self._select_kslice( k1,k2) @@ -745,7 +749,7 @@ class EclRegion(BaseCClass): def deselect_below_plane( self , n , p): """ Will deselect all the cells 'below' the plane defined by n & p. - + See method 'select_above_plane' for further documentation. """ (n_vec , p_vec) = self.__init_plane_select( n , p ) @@ -763,7 +767,7 @@ class EclRegion(BaseCClass): (100,100) the @points list should be: points = [(0,0) , (0,100) , (100,100) , (100,0)] - + The elements in the points list should be (utm_x, utm_y) values. These values will be compared with the centerpoints of the cells in the grid. The selection is based the top k=0 @@ -798,7 +802,7 @@ class EclRegion(BaseCClass): """ self._deselect_outside_polygon( CPolyline( init_points = points )) - + @select_method def selectTrue( self , ecl_kw , intersect = False): """ @@ -814,7 +818,7 @@ class EclRegion(BaseCClass): """ self._select_false( ecl_kw ) - + @select_method def selectFromLayer(self , layer , k , value, intersect = False): """Will select all the cells in in @layer with value @value - at @@ -834,10 +838,10 @@ class EclRegion(BaseCClass): if grid.getNY() != layer.getNY(): raise ValueError("NY dimension mismatch. Grid:%d layer:%d" % (grid.getNY() , layer.getNY())) - + self._select_from_layer( layer , k , value ) - + ################################################################# @@ -846,13 +850,13 @@ class EclRegion(BaseCClass): """ Helper function to apply a function with one scalar arg on target_kw. """ - type = target_kw.getEclType( ) - if func_dict.has_key( type ): - func = func_dict[ type ] + data_type = target_kw.data_type + if func_dict.has_key( data_type ): + func = func_dict[ data_type ] func( target_kw, scalar , force_active ) else: raise Exception("scalar_apply_kw() only supported for INT/FLOAT/DOUBLE") - + def iadd_kw( self , target_kw , delta_kw , force_active = False): """ The functions iadd_kw(), copy_kw(), set_kw(), scale_kw() and @@ -877,9 +881,9 @@ class EclRegion(BaseCClass): """ See usage documentation on iadd_kw(). """ - self.scalar_apply_kw( ecl_kw , shift , {EclTypeEnum.ECL_INT_TYPE : self._shift_kw_int, - EclTypeEnum.ECL_FLOAT_TYPE : self._shift_kw_float , - EclTypeEnum.ECL_DOUBLE_TYPE : self._shift_kw_double} , force_active) + self.scalar_apply_kw( ecl_kw , shift , {EclDataType.ECL_INT : self._shift_kw_int, + EclDataType.ECL_FLOAT : self._shift_kw_float , + EclDataType.ECL_DOUBLE : self._shift_kw_double} , force_active) def isub_kw( self , target_kw , delta_kw , force_active = False): if isinstance(delta_kw , EclKW): @@ -889,15 +893,15 @@ class EclRegion(BaseCClass): raise TypeError("Type mismatch") else: self.shift_kw( target_kw , -delta_kw , force_active = force_active) - + def scale_kw( self , ecl_kw , scale , force_active = False): """ See usage documentation on iadd_kw(). """ - self.scalar_apply_kw( ecl_kw , scale , {EclTypeEnum.ECL_INT_TYPE : self._scale_kw_int, - EclTypeEnum.ECL_FLOAT_TYPE : self._scale_kw_float , - EclTypeEnum.ECL_DOUBLE_TYPE : self._scale_kw_double} , force_active) + self.scalar_apply_kw( ecl_kw , scale , {EclDataType.ECL_INT : self._scale_kw_int, + EclDataType.ECL_FLOAT : self._scale_kw_float , + EclDataType.ECL_DOUBLE : self._scale_kw_double} , force_active) def imul_kw(self, target_kw , other , force_active = False): if isinstance(other , EclKW): @@ -927,21 +931,21 @@ class EclRegion(BaseCClass): self._copy_kw( target_kw , src_kw , force_active ) else: raise TypeError("Type mismatch") - + def set_kw( self , ecl_kw , value , force_active = False): """ See usage documentation on iadd_kw(). """ - self.scalar_apply_kw( ecl_kw , value , {EclTypeEnum.ECL_INT_TYPE : self._set_kw_int, - EclTypeEnum.ECL_FLOAT_TYPE : self._set_kw_float , - EclTypeEnum.ECL_DOUBLE_TYPE : self._set_kw_double} , force_active) + self.scalar_apply_kw( ecl_kw , value , {EclDataType.ECL_INT : self._set_kw_int, + EclDataType.ECL_FLOAT : self._set_kw_float , + EclDataType.ECL_DOUBLE : self._set_kw_double} , force_active) + - ################################################################# - def ecl_region_instance( ): + def ecl_region_instance(self): """ Helper function (attribute) to support run-time typechecking. """ @@ -965,7 +969,7 @@ class EclRegion(BaseCClass): global_list.setParent(self) return global_list - + def getIJKList(self): """ WIll return a Python list of (ij,k) tuples for the region. @@ -974,39 +978,8 @@ class EclRegion(BaseCClass): ijk_list = [] for g in global_list: ijk_list.append( self.grid.get_ijk( global_index = g ) ) - + return ijk_list - - - - - @property - def active_list(self): - warnings.warn("The active_list property is deprecated - use method \'getActiveList()\' instead." , DeprecationWarning) - return self.getActiveList() - - - @property - def global_list(self): - warnings.warn("The global_list property is deprecated - use method \'getGlobalList()\' instead." , DeprecationWarning) - return self.getGlobalList() - - - @property - def active_size( self ): - """ - Number of active cells in region. - """ - warnings.warn("The active_size property is deprecated - use \'len(getActiveList())\' instead." , DeprecationWarning) - return len(self.getActiveList()) - - @property - def global_size( self ): - """ - Number of global cells in region. - """ - warnings.warn("The global_size property is deprecated - use \'len(getGlobalList())\' instead." , DeprecationWarning) - return len(self.getGlobalList()) def contains_ijk( self , i,j,k): """ @@ -1028,7 +1001,7 @@ class EclRegion(BaseCClass): """ return self._contains_active( active_index ) - + def kw_index_list(self , ecl_kw , force_active): c_ptr = self._get_kw_index_list( ecl_kw , force_active) index_list = IntVector.createCReference( c_ptr, self ) @@ -1040,18 +1013,3 @@ class EclRegion(BaseCClass): def setName(self , name): self._set_name( name ) - - - def set_name( self , name ): - warnings.warn("The name property / set_name method is deprecated - use method \'setName()\' instead." , DeprecationWarning) - self.setName( name ) - - - def get_name( self ): - warnings.warn("The name property / get_name method is deprecated - use method \'getName()\' instead." , DeprecationWarning) - return self.getName( ) - - - name = property( get_name , set_name ) - - diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_rft.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_rft.py index 0499508e1a..e337a86a59 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_rft.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_rft.py @@ -17,8 +17,8 @@ Module for loading ECLIPSE RFT files. """ -import types -import warnings +from __future__ import absolute_import, division, print_function, unicode_literals + from cwrap import BaseCClass from ert.ecl import EclRFTCell, EclPLTCell, EclPrototype from ert.util import CTime @@ -74,7 +74,22 @@ class EclRFT(BaseCClass): def free(self): self._free( ) - + + def __repr__(self): + rs = [] + rs.append('completed_cells = %d' % len(self)) + rs.append('date = %s' % self.getDate()) + if self.is_RFT(): + rs.append('RFT') + if self.is_PLT(): + rs.append('PLT') + if self.is_SEGMENT(): + rs.append('SEGMENT') + if self.is_MSW(): + rs.append('MSW') + rstr = ', '.join(rs) + return self._create_repr(rstr) + def __len__(self): """ The number of completed cells in this RFT. @@ -106,31 +121,12 @@ class EclRFT(BaseCClass): return self._is_MSW( ) - @property - def type(self): - # Enum: ecl_rft_enum from ecl_rft_node.h - # RFT = 1 - # PLT = 2 - # Segment = 3 -- Not properly implemented - """ - Deprecated - use query methods: is_RFT(), is_PLT() and is_SEGMENT() instead. - """ - warnings.warn("The property type is deprecated, use the query methods is_RFT(), is_PLT() and is_SEGMENT() instead." , DeprecationWarning) - return self._get_type( ) - - def getWellName(self): """ The name of the well we are considering. """ return self._get_well( ) - @property - def well(self): - warnings.warn("The property well is deprecated, use the getWellName() method instead." , DeprecationWarning) - return self.getWellName( ) - - def getDate(self): """ The date when this RFT/PLT/... was recorded. @@ -138,22 +134,6 @@ class EclRFT(BaseCClass): ct = CTime(self._get_date( )) return ct.date() - - @property - def date(self): - warnings.warn("The property date is deprecated, use the getDate() instead." , DeprecationWarning) - return self.getDate() - - - @property - def size(self): - """ - The number of completed cells. - """ - warnings.warn("The property size is deprecated, use the built in len( ) function instead." , DeprecationWarning) - return len(self) - - def __cell_ref( self , cell_ptr ): if self.is_RFT(): return EclRFTCell.createCReference( cell_ptr , self ) @@ -164,7 +144,7 @@ class EclRFT(BaseCClass): def assert_cell_index( self , index ): - if isinstance( index , types.IntType): + if isinstance( index , int): length = self.__len__() if index < 0 or index >= length: raise IndexError @@ -325,13 +305,8 @@ class EclRFTFile(BaseCClass): Returns the total number of distinct wells in the RFT file. """ return self._get_num_wells( ) - - @property - def num_wells( self ): - warnings.warn("The property num_wells is deprecated, use the getNumWells() instead." , DeprecationWarning) - return self.getNumWells() - + def getHeaders(self): """ Returns a list of two tuples (well_name , date) for the whole file. @@ -339,14 +314,9 @@ class EclRFTFile(BaseCClass): header_list = [] for i in (range(self._get_size( None , CTime(-1)))): rft = self.iget( i ) - header_list.append( (rft.well , rft.date) ) + header_list.append( (rft.getWellName() , rft.getDate()) ) return header_list - @property - def headers(self): - warnings.warn("The property headers is deprecated, use the getHeaders() instead." , DeprecationWarning) - return self.getHeaders() - def iget(self , index): """ @@ -370,13 +340,7 @@ class EclRFTFile(BaseCClass): def free(self): self._free( ) - - - - - - - - - + def __repr__(self): + w = len(self) + return self._create_repr('wells = %d' % w) diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_rft_cell.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_rft_cell.py index 1933681c16..b7ce4a93dc 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_rft_cell.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_rft_cell.py @@ -14,7 +14,6 @@ # See the GNU General Public License at # for more details. -import warnings from cwrap import BaseCClass from ert.ecl import EclPrototype @@ -43,40 +42,9 @@ class RFTCell(BaseCClass): - def warn(self , old , new): - msg = """ - -The cell property:%s has been deprecated, and the method:%s() should -be used instead. Observe that the new method %s() returns coordinate -values starting at 0, whereas the old property %s returned values -starting at 1; hence you must adapt the calling code when you change -from %s -> %s() -""" % (old , new , new , old , old , new) - warnings.warn( msg , DeprecationWarning ) - def free(self): self._free( ) - @property - def i(self): - self.warn("i" , "get_i") - return self.get_i() + 1 - - @property - def j(self): - self.warn("j" , "get_j") - return self.get_j() + 1 - - @property - def k(self): - self.warn("k" , "get_k") - return self.get_k() + 1 - - @property - def ijk(self): - self.warn("ijk" , "get_ijk") - return (self.get_i() + 1 , self.get_j() + 1 , self.get_k() + 1) - def get_i(self): return self._get_i( ) @@ -110,7 +78,7 @@ class EclRFTCell(RFTCell): def __init__(self , i , j , k , depth , pressure , swat , sgas): c_ptr = self._alloc_RFT( i , j , k , depth , pressure , swat , sgas ) - super(RFTCell , self).__init__( c_ptr ) + super(EclRFTCell , self).__init__( c_ptr ) @property def swat(self): @@ -146,7 +114,7 @@ class EclPLTCell(RFTCell): def __init__(self , i , j , k , depth , pressure , orat , grat , wrat , conn_start ,conn_end, flowrate , oil_flowrate , gas_flowrate , water_flowrate ): c_ptr = self._alloc_PLT( i , j , k , depth , pressure , orat , grat , wrat , conn_start ,conn_end, flowrate , oil_flowrate , gas_flowrate , water_flowrate ) - super( RFTCell , self).__init__( c_ptr ) + super( EclPLTCell , self).__init__( c_ptr ) @property diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_smspec_node.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_smspec_node.py index ef21c26c88..8ee4469057 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_smspec_node.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_smspec_node.py @@ -1,4 +1,18 @@ -import warnings +# Copyright (C) 2016 Statoil ASA, Norway. +# +# This file is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. from cwrap import BaseCClass from ert.ecl import EclPrototype @@ -32,21 +46,6 @@ class EclSMSPECNode(BaseCClass): super(EclSMSPECNode, self).__init__(0) # null pointer raise NotImplementedError("Class can not be instantiated directly!") - @property - def is_total(self): - warnings.warn("The is_total property is deprecated - use method isTotal()" , DeprecationWarning) - return self.isTotal( ) - - @property - def is_rate(self): - warnings.warn("The is_rate property is deprecated - use method isRate()" , DeprecationWarning) - return self.isRate() - - @property - def is_historical(self): - warnings.warn("The is_historical property is deprecated - use method isHistorical()" , DeprecationWarning) - return self.isHistorical( ) - @property def unit(self): """ diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_sum.py index 457f9c1362..d4ad01a5fa 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_sum.py @@ -160,7 +160,6 @@ class EclSum(BaseCClass): else: super(EclSum, self).__init__(c_pointer) self.__private_init( ) - self.__str__ = self.__repr__ self._load_case = load_case @@ -584,7 +583,7 @@ class EclSum(BaseCClass): def blockedProduction(self , totalKey , timeRange): node = self.smspec_node(totalKey) - if node.is_total: + if node.isTotal(): total = DoubleVector() for t in timeRange: if t < CTime(self.start_time): diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_node.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_node.py index eb2f4ee1b0..ed4ccfc680 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_node.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_node.py @@ -1,4 +1,5 @@ -class EclSumNode: +class EclSumNode(object): + def __init__(self, mini_step, report_step, days, date, mpl_date, value): """ EclSumNode is a 'struct' with a summary value and time. @@ -23,5 +24,5 @@ class EclSumNode: self.date = date self.mpl_date = mpl_date - def __str__(self): - return "" % ( self.days, self.value ) \ No newline at end of file + def __repr__(self): + return "EclSumNode(days=%d, value=%g)" % (self.days, self.value) diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_vector.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_vector.py index de43cd8623..9c76452e5f 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_vector.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_vector.py @@ -1,3 +1,19 @@ +# Copyright (C) 2017 Statoil ASA, Norway. +# +# This file is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. + from __future__ import print_function import warnings from ert.ecl.ecl_sum_node import EclSumNode @@ -24,7 +40,7 @@ class EclSumVector(object): self.parent = parent self.key = key self.report_only = report_only - + if report_only: warnings.warn("The report_only flag to the EclSumVector will be removed" , DeprecationWarning) @@ -109,7 +125,7 @@ class EclSumVector(object): return self.__report_step - def __iget__( self, index ): + def __iget( self, index ): """ Will return an EclSumNode for element @index; should be called through the [] operator, otherwise you can come across @@ -151,7 +167,7 @@ class EclSumVector(object): if index < 0 or index > length: raise KeyError("Invalid index:%d out of range [0:%d)" % ( index, length)) else: - return self.__iget__(index) + return self.__iget(index) elif isinstance(index, slice): # Observe that the slice based lookup does __not__ return # a proper EclSumVector instance; it will merely return @@ -160,7 +176,7 @@ class EclSumVector(object): index = start sub_vector = [] while index < stop: - sub_vector.append(self.__iget__(index)) + sub_vector.append(self.__iget(index)) index += step return sub_vector @@ -172,7 +188,7 @@ class EclSumVector(object): Will return the first EclSumNode in this vector. """ self.assert_values() - return self.__iget__(0) + return self.__iget(0) @property def last( self ): @@ -182,7 +198,7 @@ class EclSumVector(object): self.assert_values() index = len(self.__values) - 1 - return self.__iget__(index) + return self.__iget(index) @property def last_value( self ): @@ -192,7 +208,7 @@ class EclSumVector(object): self.assert_values() index = len(self.__values) - 1 - return self.__iget__(index).value + return self.__iget(index).value def get_interp( self, days=None, date=None): @@ -258,7 +274,7 @@ class EclSumVector(object): time_index = self.first_gt_index(limit) print(time_index) if time_index >= 0: - return self.__iget__(time_index) + return self.__iget(time_index) else: return None @@ -283,6 +299,6 @@ class EclSumVector(object): """ time_index = self.first_lt_index(limit) if time_index >= 0: - return self.__iget__(time_index) + return self.__iget(time_index) else: return None diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_type.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_type.py new file mode 100644 index 0000000000..2778ab627f --- /dev/null +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_type.py @@ -0,0 +1,162 @@ +# Copyright (C) 2017 Statoil ASA, Norway. +# +# The file 'ecl_type.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. + +from cwrap import BaseCClass, BaseCEnum +from ert.ecl import EclPrototype + +class EclTypeEnum(BaseCEnum): + TYPE_NAME="ecl_type_enum" + ECL_CHAR_TYPE = None + ECL_FLOAT_TYPE = None + ECL_DOUBLE_TYPE = None + ECL_INT_TYPE = None + ECL_BOOL_TYPE = None + ECL_MESS_TYPE = None + +EclTypeEnum.addEnum("ECL_CHAR_TYPE" , 0 ) +EclTypeEnum.addEnum("ECL_FLOAT_TYPE" , 1 ) +EclTypeEnum.addEnum("ECL_DOUBLE_TYPE" , 2 ) +EclTypeEnum.addEnum("ECL_INT_TYPE" , 3 ) +EclTypeEnum.addEnum("ECL_BOOL_TYPE" , 4 ) +EclTypeEnum.addEnum("ECL_MESS_TYPE" , 5 ) + +#----------------------------------------------------------------- + +class EclDataType(BaseCClass): + + TYPE_NAME = "ecl_data_type" + + _alloc = EclPrototype("void* ecl_type_alloc_python(ecl_type_enum, size_t)", bind=False) + _alloc_from_type = EclPrototype("void* ecl_type_alloc_from_type_python(ecl_type_enum)", bind=False) + _alloc_from_name = EclPrototype("void* ecl_type_alloc_from_name_python(char*)", bind = False) + _free = EclPrototype("void ecl_type_free_python(ecl_data_type)") + _get_type = EclPrototype("ecl_type_enum ecl_type_get_type_python(ecl_data_type)") + _get_element_size = EclPrototype("size_t ecl_type_get_sizeof_ctype_python(ecl_data_type)") + _is_int = EclPrototype("bool ecl_type_is_int_python(ecl_data_type)") + _is_char = EclPrototype("bool ecl_type_is_char_python(ecl_data_type)") + _is_float = EclPrototype("bool ecl_type_is_float_python(ecl_data_type)") + _is_double = EclPrototype("bool ecl_type_is_double_python(ecl_data_type)") + _is_mess = EclPrototype("bool ecl_type_is_mess_python(ecl_data_type)") + _is_bool = EclPrototype("bool ecl_type_is_bool_python(ecl_data_type)") + _get_name = EclPrototype("char* ecl_type_get_name_python(ecl_data_type)") + _is_numeric = EclPrototype("bool ecl_type_is_numeric_python(ecl_data_type)") + _is_equal = EclPrototype("bool ecl_type_is_equal_python(ecl_data_type, ecl_data_type)") + + def __init__(self, type_enum = None, element_size = None, type_name = None): + self._assert_valid_arguments(type_enum, element_size, type_name) + + if type_name: + c_ptr = self._alloc_from_name(type_name) + elif not element_size: + c_ptr = self._alloc_from_type(type_enum) + else: + c_ptr = self._alloc(type_enum, element_size) + + super(EclDataType, self).__init__(c_ptr) + + def _assert_valid_arguments(self, type_enum, element_size, type_name): + if type_name is not None: + if type_enum is not None or element_size is not None: + raise ValueError("Type name given (%s). Expected both type_enum and element_size to be None") + elif type_enum is None: + raise ValueError("Both type_enum and type_name is None!") + + @property + def type(self): + return self._get_type() + + @property + def element_size(self): + return self._get_element_size() + + @property + def type_name(self): + return self._get_name() + + def free(self): + self._free() + + def is_int(self): + return self._is_int() + + def is_char(self): + return self._is_char() + + def is_float(self): + return self._is_float() + + def is_double(self): + return self._is_double() + + def is_mess(self): + return self._is_mess() + + def is_bool(self): + return self._is_bool() + + def is_numeric(self): + return self._is_numeric() + + def is_equal(self, other): + return self._is_equal(other) + + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.is_equal(other) + return False + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return hash((self.type, self. element_size)) + + @classmethod + def create_from_type_name(cls, name): + return EclDataType(type_name = name) + + # Enables one to fetch a type as EclDataType.ECL_XXXX + class classproperty(object): + + def __init__(self, fget): + self.fget = fget + + def __get__(self, owner_self, owner_cls): + return self.fget(owner_cls) + + @classproperty + def ECL_INT(cls): + return EclDataType(EclTypeEnum.ECL_INT_TYPE) + + @classproperty + def ECL_FLOAT(cls): + return EclDataType(EclTypeEnum.ECL_FLOAT_TYPE) + + @classproperty + def ECL_DOUBLE(cls): + return EclDataType(EclTypeEnum.ECL_DOUBLE_TYPE) + + @classproperty + def ECL_BOOL(cls): + return EclDataType(EclTypeEnum.ECL_BOOL_TYPE) + + @classproperty + def ECL_MESS(cls): + return EclDataType(EclTypeEnum.ECL_MESS_TYPE) + + @classproperty + def ECL_CHAR(cls): + return EclDataType(EclTypeEnum.ECL_CHAR_TYPE) diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_util.py b/ThirdParty/Ert/python/python/ert/ecl/ecl_util.py index a122029cc8..4be14720c7 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_util.py +++ b/ThirdParty/Ert/python/python/ert/ecl/ecl_util.py @@ -68,24 +68,6 @@ EclPhaseEnum.addEnum("ECL_GAS_PHASE" , 2 ) EclPhaseEnum.addEnum("ECL_WATER_PHASE" , 4 ) -#----------------------------------------------------------------- - -class EclTypeEnum(BaseCEnum): - TYPE_NAME="ecl_type_enum" - ECL_CHAR_TYPE = None - ECL_FLOAT_TYPE = None - ECL_DOUBLE_TYPE = None - ECL_INT_TYPE = None - ECL_BOOL_TYPE = None - ECL_MESS_TYPE = None - -EclTypeEnum.addEnum("ECL_CHAR_TYPE" , 0 ) -EclTypeEnum.addEnum("ECL_FLOAT_TYPE" , 1 ) -EclTypeEnum.addEnum("ECL_DOUBLE_TYPE" , 2 ) -EclTypeEnum.addEnum("ECL_INT_TYPE" , 3 ) -EclTypeEnum.addEnum("ECL_BOOL_TYPE" , 4 ) -EclTypeEnum.addEnum("ECL_MESS_TYPE" , 5 ) - #----------------------------------------------------------------- class EclUnitTypeEnum(BaseCEnum): @@ -119,7 +101,6 @@ EclFileFlagEnum.addEnum("ECL_FILE_WRITABLE" , 2 ) class EclUtil(object): _get_num_cpu = EclPrototype("int ecl_util_get_num_cpu( char* )", bind = False) _get_file_type = EclPrototype("ecl_file_enum ecl_util_get_file_type( char* , bool* , int*)" , bind = False) - _get_type_name = EclPrototype("char* ecl_util_get_type_name( int )" , bind = False) _get_start_date = EclPrototype("time_t ecl_util_get_start_date( char* )" , bind = False) _get_report_step = EclPrototype("int ecl_util_filename_report_nr( char* )" , bind = False) @@ -143,10 +124,6 @@ class EclUtil(object): file_type , fmt , step = EclUtil.inspectExtension( filename ) return file_type - @staticmethod - def type_name(ecl_type): - return EclUtil._get_type_name(ecl_type) - @staticmethod def get_start_date(datafile): return EclUtil._get_start_date(datafile).datetime() @@ -180,5 +157,4 @@ class EclUtil(object): get_num_cpu = EclUtil.get_num_cpu get_file_type = EclUtil.get_file_type -type_name = EclUtil.type_name get_start_date = EclUtil.get_start_date diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/fault.py b/ThirdParty/Ert/python/python/ert/ecl/faults/fault.py index 326ad0fc05..bc392ccaac 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/fault.py +++ b/ThirdParty/Ert/python/python/ert/ecl/faults/fault.py @@ -1,40 +1,39 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'fault.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. +# Copyright (C) 2014 Statoil ASA, Norway. +# +# The file 'fault.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. -from ert.ecl import EclTypeEnum -from ert.geo import Polyline , CPolyline , GeometryTools -from ert.util import stat +from ert.geo import Polyline, CPolyline, GeometryTools +from ert.util import stat from ert.util import Matrix from .fault_line import FaultLine -from .fault_segments import FaultSegment , SegmentMap +from .fault_segments import FaultSegment, SegmentMap class Layer(object): - def __init__(self, grid , K): - assert( isinstance(K , int) ) + def __init__(self, grid, K): + assert(isinstance(K, int)) self.__grid = grid self.__K = K self.__fault_lines = [] self.__segment_map = SegmentMap() self.__processed = False - - def addSegment(self , segment): - self.__segment_map.addSegment( segment ) + + def addSegment(self, segment): + self.__segment_map.addSegment(segment) self.__processed = False def __len__(self): @@ -45,7 +44,7 @@ class Layer(object): self.processSegments() return iter(self.__fault_lines) - def __getitem__(self , index): + def __getitem__(self, index): self.processSegments() return self.__fault_lines[index] @@ -59,8 +58,8 @@ class Layer(object): neighbor_cells += fl.getNeighborCells() return neighbor_cells - def getPolyline(self , name = None): - polyline = CPolyline( name = name) + def getPolyline(self, name=None): + polyline = CPolyline(name=name) for fl in self: polyline += fl.getPolyline() return polyline @@ -79,49 +78,50 @@ class Layer(object): def numLines(self): return len(self) - - # A fault can typically consist of several non connected fault - # segments; right after reading the fault input these can be in a - # complete mess: - # - # 1. The different part of the fault can be in random order. - # - # 2. Within each fault line the micro segments can be ordered in - # reverse. - # - # This method goes through some desparate heuristics trying to - # sort things out. - def __sortFaultLines(self): + """A fault can typically consist of several non connected fault + segments; right after reading the fault input these can be in + a complete mess: + + 1. The different part of the fault can be in random order. + + 2. Within each fault line the micro segments can be ordered in + reverse. + + This method goes through some desparate heuristics trying to sort + things out. + + """ + N = len(self.__fault_lines) - x = Matrix(N , 1) - y = Matrix(N , 1) + x = Matrix(N, 1) + y = Matrix(N, 1) for index,line in enumerate(self.__fault_lines): xc,yc = line.center() - + x[index,0] = xc y[index,0] = yc # y = beta[0] + beta[1] * x # = a + b * x - beta = stat.polyfit(2 , x , y) + beta = stat.polyfit(2, x, y) a = beta[0] b = beta[1] perm_list = [] for index,line in enumerate(self.__fault_lines): - x0 , y0 = line.center() + x0, y0 = line.center() d = x0 + b*(y0 - a) - perm_list.append((index , d)) - perm_list.sort(key = lambda x: x[1]) + perm_list.append((index, d)) + perm_list.sort(key=lambda x: x[1]) fault_lines = [] for (index,d) in perm_list: - fault_lines.append( self.__fault_lines[ index ]) - self.__fault_lines = fault_lines + fault_lines.append(self.__fault_lines[ index ]) + self.__fault_lines = fault_lines + - for line in self.__fault_lines: x1,y1 = line.startPoint() x2,y2 = line.endPoint() @@ -130,27 +130,27 @@ class Layer(object): if d1 > d2: line.reverse() - - - + + + def processSegments(self): if self.__processed: return while self.__segment_map: - fault_line = FaultLine(self.__grid , self.__K) - self.__fault_lines.append( fault_line ) + fault_line = FaultLine(self.__grid, self.__K) + self.__fault_lines.append(fault_line) current_segment = self.__segment_map.popStart() while current_segment: append = fault_line.tryAppend(current_segment) if not append: - fault_line = FaultLine(self.__grid , self.__K) - self.__fault_lines.append( fault_line ) + fault_line = FaultLine(self.__grid, self.__K) + self.__fault_lines.append(fault_line) fault_line.tryAppend(current_segment) - current_segment.next_segment = self.__segment_map.popNext( current_segment ) + current_segment.next_segment = self.__segment_map.popNext(current_segment) current_segment = current_segment.next_segment if len(self.__fault_lines) > 1: @@ -165,18 +165,18 @@ class Layer(object): class Fault(object): allowed_faces = ["X","Y","Z","I","J","K","X-","Y-","Z-","I-","J-","K-"] - def __init__(self, grid , name): + def __init__(self, grid, name): self.__grid = grid self.__name = name self.__layer_map = {} self.__layer_list = [] - (self.nx , self.ny , self.nz , nactive) = grid.dims - + (self.nx, self.ny, self.nz, nactive) = grid.getDims() + def __str__(self): return "Fault:%s" % self.__name - def __getitem__(self , K): + def __getitem__(self, K): if not self.hasLayer(K): self.addLayer(K) layer = self.__layer_map[K] @@ -191,40 +191,40 @@ class Fault(object): yield layer - def hasLayer(self , K): - return self.__layer_map.has_key( K ) + def hasLayer(self, K): + return self.__layer_map.has_key(K) - def addLayer(self , K): - layer = Layer(self.__grid , K) + def addLayer(self, K): + layer = Layer(self.__grid, K) self.__layer_map[K] = layer - self.__layer_list.append( layer ) - + self.__layer_list.append(layer) - def createSegment(self , I1 , I2 , J1 , J2 , face): - if face in ["X" , "I"]: + + def createSegment(self, I1, I2, J1, J2, face): + if face in ["X", "I"]: C1 = I1 + 1 + J1*(self.nx + 1) C2 = C1 + (1 + J2 - J1) * (self.nx + 1) - elif face in ["X-" , "I-"]: + elif face in ["X-", "I-"]: C1 = I1 + J1*(self.nx + 1) C2 = C1 + (1 + J2 - J1) * (self.nx + 1) - elif face in ["Y" , "J"]: + elif face in ["Y", "J"]: C1 = I1 + (J1 + 1) * (self.nx + 1) C2 = C1 + (1 + I2 - I1) - elif face in ["Y-" , "J-"]: + elif face in ["Y-", "J-"]: C1 = I1 + J1 * (self.nx + 1) C2 = C1 + (1 + I2 - I1) else: return None - - return FaultSegment(C1,C2) - - - def addRecord(self , I1 , I2 , J1 , J2 , K1 , K2 , face): + return FaultSegment(C1,C2) + + + + def addRecord(self, I1, I2, J1, J2, K1, K2, face): if not face in Fault.allowed_faces: raise ValueError("Invalid face:%s" % face) - + if I1 > I2: raise ValueError("Invalid I1 I2 indices") @@ -233,7 +233,7 @@ class Fault(object): if K1 > K2: raise ValueError("Invalid K1 K2 indices") - + if I1 < 0 or I1 >= self.nx: raise ValueError("Invalid I1:%d" % I1) if I2 < 0 or I2 >= self.nx: @@ -260,17 +260,17 @@ class Fault(object): if face in ["Z","K"]: if K1 != K2: raise ValueError("For face:%s we must have K1 == K2" % face) - + #----------------------------------------------------------------- - + for K in range(K1,K2+1): if not self.hasLayer(K): self.addLayer(K) layer = self.__layer_map[K] segment = self.createSegment(I1,I2,J1,J2,face) if segment: - layer.addSegment( segment ) - + layer.addSegment(segment) + def getName(self): return self.__name @@ -282,91 +282,64 @@ class Fault(object): neighbor_cells += layer.getNeighborCells() return neighbor_cells - - def getPolyline(self , k): - layer = self[k] - return layer.getPolyline( name = "Polyline[%s]" % self.getName() ) - - def getIJPolyline(self , k): + def getPolyline(self, k): + layer = self[k] + return layer.getPolyline(name="Polyline[%s]" % self.getName()) + + + def getIJPolyline(self, k): layer = self[k] return layer.getIJPolyline() - - def numLines( self , k): + + def numLines(self, k): layer = self[k] return layer.numLines() - - - def extendToFault(self , other_fault , k): - polyline = self.getIJPolyline(k) - - p0 = polyline[-2] - p1 = polyline[-1] - ray_dir = GeometryTools.lineToRay( p0 , p1 ) - intersections = GeometryTools.rayPolygonIntersections( p1 , ray_dir , other_fault.getIJPolyline(k)) - if intersections: - p2 = intersections[0][1] - return [p1 , (int(p2[0]) , int(p2[1])) ] - - p0 = polyline[1] - p1 = polyline[0] - ray_dir = GeometryTools.lineToRay( p0 , p1 ) - intersections = GeometryTools.rayPolygonIntersections( p1 , ray_dir , other_fault.getIJPolyline(k)) - if intersections: - if len(intersections) > 1: - d_list = [ GeometryTools.distance( p1 , p[1] ) for p in intersections ] - index = d_list.index( min(d_list) ) - else: - index = 0 - p2 = intersections[index][1] - return [p1 , (int(p2[0]) , int(p2[1])) ] - - raise ValueError("The fault %s can not be extended to intersect with:%s in layer:%d" % (self.getName() , other_fault.getName() , k+1 )) @staticmethod - def __rayIntersect(p0, p1 , polyline): - ray_dir = GeometryTools.lineToRay( p0 , p1 ) - intersections = GeometryTools.rayPolygonIntersections( p1 , ray_dir , polyline) + def __rayIntersect(p0, p1, polyline): + ray_dir = GeometryTools.lineToRay(p0, p1) + intersections = GeometryTools.rayPolygonIntersections(p1, ray_dir, polyline) if intersections: if len(intersections) > 1: - d_list = [ GeometryTools.distance( p1 , p[1] ) for p in intersections ] - index = d_list.index( min(d_list) ) + d_list = [ GeometryTools.distance(p1, p[1]) for p in intersections ] + index = d_list.index(min(d_list)) else: index = 0 p2 = intersections[index][1] - return [p1 , p2] + return [p1, p2] else: return None - def connectWithPolyline(self , polyline , k): + def connectWithPolyline(self, polyline, k): """ """ - if self.intersectsPolyline( polyline , k ): + if self.intersectsPolyline(polyline, k): return None else: - self_polyline = self.getPolyline( k ) + self_polyline = self.getPolyline(k) if len(self_polyline) > 0: - return self_polyline.connect( polyline ) + return self_polyline.connect(polyline) else: return None - def connect(self , target , k): + def connect(self, target, k): if isinstance(target, Fault): polyline = target.getPolyline(k) else: polyline = target - return self.connectWithPolyline( polyline , k ) + return self.connectWithPolyline(polyline, k) - def extendToPolyline(self , polyline , k): + def extendToPolyline(self, polyline, k): """Extends the fault until it intersects @polyline in layer @k. - The return value is a list [(x1,y1) , (x2,y2)] where (x1,y1) + The return value is a list [(x1,y1), (x2,y2)] where (x1,y1) is on the tip of the fault, and (x2,y2) is on the polyline. If the fault already intersects polyline None is returned, if no intersection is found a ValueError exception is raised. @@ -380,78 +353,77 @@ class Fault(object): +------------+ D | | | - | +-------C + | +-------C B-----+ | A - + The algorithm will then try to intersect the following rays with the polyline, the first match will return: - 1. (Pc , Pd) - 2. (Pb , Pa) - 3. (Pa , Pd) - 4. (Pd , Pa) + 1. (Pc, Pd) + 2. (Pb, Pa) + 3. (Pa, Pd) + 4. (Pd, Pa) The fault object is not directed in any way; i.e. in the case both (Pc,Pd) and (Pb,Pa) intersects the polyline it is impossible to know which intersection is returned, without actually consulting the construction of the fault object. """ - if self.intersectsPolyline(polyline , k): + if self.intersectsPolyline(polyline, k): return None - fault_polyline = self.getPolyline( k ) + fault_polyline = self.getPolyline(k) p0 = fault_polyline[-2] p1 = fault_polyline[-1] - extension = self.__rayIntersect(p0 , p1 , polyline) + extension = self.__rayIntersect(p0, p1, polyline) if extension: return extension - + p0 = fault_polyline[1] p1 = fault_polyline[0] - extension = self.__rayIntersect(p0 , p1 , polyline) + extension = self.__rayIntersect(p0, p1, polyline) if extension: return extension p0 = fault_polyline[0] p1 = fault_polyline[-1] - extension = self.__rayIntersect(p0 , p1 , polyline) + extension = self.__rayIntersect(p0, p1, polyline) if extension: return extension p0 = fault_polyline[-1] p1 = fault_polyline[0] - extension = self.__rayIntersect(p0 , p1 , polyline) + extension = self.__rayIntersect(p0, p1, polyline) if extension: return extension - raise ValueError("The fault %s can not be extended to intersect with polyline:%s in layer:%d" % (self.getName() , polyline.getName() , k+1)) + raise ValueError("The fault %s can not be extended to intersect with polyline:%s in layer:%d" % (self.getName(), polyline.getName(), k+1)) - - def intersectsPolyline(self , polyline , k): + + def intersectsPolyline(self, polyline, k): fault_line = self.getPolyline(k) - return fault_line.intersects( polyline ) + return fault_line.intersects(polyline) - def intersectsFault(self , other_fault , k): + def intersectsFault(self, other_fault, k): fault_line = other_fault.getPolyline(k) - return self.intersectsPolyline( fault_line , k ) + return self.intersectsPolyline(fault_line, k) - - def extendToFault(self , fault , k): + def extendToFault(self, fault, k): fault_line = fault.getPolyline(k) - return self.extendToPolyline(fault_line , k) + return self.extendToPolyline(fault_line, k) - def extendToEdge(self, edge , k): - if isinstance(edge , Fault): - return self.extendToFault( edge , k ) + def extendToEdge(self, edge, k): + if isinstance(edge, Fault): + return self.extendToFault(edge, k) else: - return self.extendToPolyline( edge , k ) - + return self.extendToPolyline(edge, k) - def extendToBBox(self , bbox , k , start = True): + + def extendToBBox(self, bbox, k, start=True): fault_polyline = self.getPolyline(k) if start: p0 = fault_polyline[1] @@ -459,9 +431,9 @@ class Fault(object): else: p0 = fault_polyline[-2] p1 = fault_polyline[-1] - + ray_dir = GeometryTools.lineToRay(p0,p1) - intersections = GeometryTools.rayPolygonIntersections( p1 , ray_dir , bbox) + intersections = GeometryTools.rayPolygonIntersections(p1, ray_dir, bbox) if intersections: p2 = intersections[0][1] if self.getName(): @@ -469,44 +441,44 @@ class Fault(object): else: name = None - return CPolyline( name = name , init_points = [(p1[0] , p1[1]) , p2]) + return CPolyline(name=name, init_points=[(p1[0], p1[1]), p2]) else: raise Exception("Logical error - must intersect with bounding box") - - - def endJoin(self , other , k): + + + def endJoin(self, other, k): fault_polyline = self.getPolyline(k) - if isinstance(other , Fault): + if isinstance(other, Fault): other_polyline = other.getPolyline(k) else: other_polyline = other - return GeometryTools.joinPolylines( fault_polyline , other_polyline ) - + return GeometryTools.joinPolylines(fault_polyline, other_polyline) - def connectPolylineOnto(self , polyline , k): - if self.intersectsPolyline( polyline , k): + + def connectPolylineOnto(self, polyline, k): + if self.intersectsPolyline(polyline, k): return None self_polyline = self.getPolyline(k) - return polyline.connect( self_polyline ) - + return polyline.connect(self_polyline) - def extendPolylineOnto(self , polyline , k): - if self.intersectsPolyline( polyline , k): + + def extendPolylineOnto(self, polyline, k): + if self.intersectsPolyline(polyline, k): return None if len(polyline) > 1: fault_polyline = self.getPolyline(k) - ext1 = self.__rayIntersect( polyline[-2] , polyline[-1] , fault_polyline ) - ext2 = self.__rayIntersect( polyline[0] , polyline[1] , fault_polyline ) - + ext1 = self.__rayIntersect(polyline[-2], polyline[-1], fault_polyline) + ext2 = self.__rayIntersect(polyline[0] , polyline[1] , fault_polyline) + if ext1 and ext2: - d1 = GeometryTools.distance( ext1[0] , ext1[1] ) - d2 = GeometryTools.distance( ext2[0] , ext2[1] ) + d1 = GeometryTools.distance(ext1[0], ext1[1]) + d2 = GeometryTools.distance(ext2[0], ext2[1]) if d1 < d2: return ext1 @@ -523,12 +495,12 @@ class Fault(object): @staticmethod - def intersectFaultRays(ray1 , ray2): + def intersectFaultRays(ray1, ray2): p1,dir1 = ray1 p2,dir2 = ray2 if p1 == p2: return [] - + dx = p2[0] - p1[0] dy = p2[1] - p1[1] if dx != 0: @@ -546,11 +518,11 @@ class Fault(object): else: xc = p1[0] yc = p2[1] - - coord_list = [p1 , (xc,yc) , p2] + + coord_list = [p1, (xc,yc), p2] else: coord_list = [p1,p2] - + return coord_list @@ -570,60 +542,60 @@ class Fault(object): # Horizontal line if p2[1] != p1[1]: raise Exception("Invalid direction") - + dy = 0 if p2[0] > p1[0]: dx = 1 else: dx = -1 - return [p2 , (dx,dy)] + return [p2, (dx,dy)] - - def getEndRays(self , k): + + def getEndRays(self, k): polyline = self.getIJPolyline(k) - + p0 = polyline[0] p1 = polyline[1] p2 = polyline[-2] p3 = polyline[-1] - return (Fault.intRay(p1,p0) , Fault.intRay(p2,p3)) + return (Fault.intRay(p1,p0), Fault.intRay(p2,p3)) + + + - - - @staticmethod - def joinFaults(fault1 , fault2 , k): + def joinFaults(fault1, fault2, k): fault1_rays = fault1.getEndRays(k) fault2_rays = fault2.getEndRays(k) - - if fault1.intersectsFault( fault2 , k ): + + if fault1.intersectsFault(fault2, k): return None count = 0 join = None try: - join = Fault.intersectFaultRays( fault1_rays[0] , fault2_rays[0] ) + join = Fault.intersectFaultRays(fault1_rays[0], fault2_rays[0]) count += 1 except ValueError: pass try: - join = Fault.intersectFaultRays( fault1_rays[0] , fault2_rays[1] ) + join = Fault.intersectFaultRays(fault1_rays[0], fault2_rays[1]) count += 1 except ValueError: pass try: - join = Fault.intersectFaultRays( fault1_rays[1] , fault2_rays[0] ) + join = Fault.intersectFaultRays(fault1_rays[1], fault2_rays[0]) count += 1 except ValueError: pass try: - join = Fault.intersectFaultRays( fault1_rays[1] , fault2_rays[1] ) + join = Fault.intersectFaultRays(fault1_rays[1], fault2_rays[1]) count += 1 except ValueError: pass @@ -631,14 +603,9 @@ class Fault(object): if count == 1: xy_list = [] for ij in join: - xyz = fault1.__grid.getNodeXYZ( ij[0] , ij[1] , k ) - xy_list.append( (xyz[0] , xyz[1]) ) + xyz = fault1.__grid.getNodeXYZ(ij[0], ij[1], k) + xy_list.append((xyz[0], xyz[1])) return xy_list else: - return fault1.endJoin( fault2 , k ) - #raise ValueError("Faults %s and %s could not be uniquely joined" % (fault1.getName() , fault2.getName())) - - - - + return fault1.endJoin(fault2, k) diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block.py b/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block.py index d21a94f303..4dc7545d4e 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block.py +++ b/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block.py @@ -51,6 +51,7 @@ class FaultBlock(BaseCClass): _get_global_index_list = EclPrototype("int_vector_ref fault_block_get_global_index_list(fault_block)") _trace_edge = EclPrototype("void fault_block_trace_edge( fault_block, double_vector , double_vector , int_vector)") _get_neighbours = EclPrototype("void fault_block_list_neighbours( fault_block , bool , geo_polygon_collection , int_vector)") + _free = EclPrototype("void fault_block_free__(fault_block)") def __init__(self , *args , **kwargs): diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block_layer.py b/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block_layer.py index 3b876f317a..e09b10462b 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block_layer.py +++ b/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block_layer.py @@ -16,7 +16,7 @@ from __future__ import print_function from cwrap import BaseCClass -from ert.ecl import EclTypeEnum, EclPrototype +from ert.ecl import EclDataType, EclPrototype from ert.ecl.faults import Fault class FaultBlockLayer(BaseCClass): @@ -92,7 +92,7 @@ class FaultBlockLayer(BaseCClass): """ ok = self._scan_keyword( fault_block_kw ) if not ok: - raise ValueError("The fault block keyword had wrong type/size: type:%s size:%d grid_size:%d" % (fault_block_kw.typeName() , len(fault_block_kw) , self.grid_ref.getGlobalSize())) + raise ValueError("The fault block keyword had wrong type/size: type:%s size:%d grid_size:%d" % (fault_block_kw.type_name , len(fault_block_kw) , self.grid_ref.getGlobalSize())) def loadKeyword(self , fault_block_kw): @@ -152,7 +152,7 @@ class FaultBlockLayer(BaseCClass): if len(kw) != self.grid_ref.getGlobalSize(): raise ValueError("The size of the target keyword must be equal to the size of the grid. Got:%d Expected:%d" % (len(kw) , self.grid_ref.getGlobalSize())) - if kw.getEclType() != EclTypeEnum.ECL_INT_TYPE: + if not kw.data_type.is_int(): raise TypeError("The target kewyord must be of integer type") self._export_kw( kw ) diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_collection.py b/ThirdParty/Ert/python/python/ert/ecl/faults/fault_collection.py index 4d03a1d160..b0d33daef4 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_collection.py +++ b/ThirdParty/Ert/python/python/ert/ecl/faults/fault_collection.py @@ -1,18 +1,18 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'fault_collection.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. +# Copyright (C) 2014 Statoil ASA, Norway. +# +# The file 'fault_collection.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. import re from .fault import Fault @@ -21,7 +21,7 @@ from ert.ecl import EclGrid comment_regexp = re.compile("--.*") def dequote(s): - if s[0] in ["'" , '"']: + if s[0] in ["'", '"']: if s[0] == s[-1]: return s[1:-1] else: @@ -31,57 +31,56 @@ def dequote(s): class FaultCollection(object): - def __init__(self , grid = None , *file_list): + def __init__(self, grid=None, *file_list): self.__fault_list = [] self.__fault_map = {} + self.__grid = grid - if grid is not None: - if not isinstance(grid , EclGrid): + if self.__grid is not None: + if not isinstance(self.__grid, EclGrid): raise ValueError("When supplying a list of files to load - you must have a grid") - for file in file_list: - self.load(grid , file) + self.load(self.__grid, file) - - def __contains__(self , fault_name): - return self.__fault_map.has_key( fault_name ) + def __contains__(self, fault_name): + return self.__fault_map.has_key(fault_name) def __len__(self): return len(self.__fault_list) - def __getitem__(self , index): - if isinstance(index , str): + def __getitem__(self, index): + if isinstance(index, str): return self.__fault_map[index] - elif isinstance(index , int): + elif isinstance(index, int): return self.__fault_list[index] else: raise TypeError("Argument must be fault name or number") def __iter__(self): return iter(self.__fault_list) - + def getGrid(self): return self.__grid - - def getFault(self , name): - return self.__getitem__(name) + + def getFault(self, name): + return self[name] - def hasFault(self , fault_name): + def hasFault(self, fault_name): return fault_name in self - + def addFault(self, fault): self.__fault_map[fault.getName()] = fault - self.__fault_list.append( fault ) - + self.__fault_list.append(fault) - def splitLine(self , line): + + def splitLine(self, line): tmp = line.split() if not tmp[-1] == "/": raise ValueError("Line:%s does not end with /" % line) @@ -98,31 +97,30 @@ class FaultCollection(object): K2 = int(tmp[6]) - 1 face = dequote(tmp[7]) - return (fault_name , I1,I2,J1,J2,K1,K2 , face) + return (fault_name, I1,I2,J1,J2,K1,K2, face) - - def loadFaults(self , grid , fileH): + + def loadFaults(self, grid, fileH): for line in fileH: - line = comment_regexp.sub("" , line) + line = comment_regexp.sub("", line) line = line.strip() if line == "/": break if line: - (name , I1 , I2 , J1 , J2 , K1 , K2 , face) = self.splitLine( line ) + (name, I1, I2, J1, J2, K1, K2, face) = self.splitLine(line) if not self.hasFault(name): - fault = Fault( grid , name) - self.addFault( fault ) + fault = Fault(grid, name) + self.addFault(fault) else: fault = self.getFault(name) - fault.addRecord(I1 , I2 , J1 , J2 , K1 , K2 , face) + fault.addRecord(I1, I2, J1, J2, K1, K2, face) - def load(self , grid , file_name): + def load(self, grid, file_name): with open(file_name) as fileH: for line in fileH: if line.startswith("FAULTS"): - self.loadFaults(grid , fileH) - + self.loadFaults(grid, fileH) diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/layer.py b/ThirdParty/Ert/python/python/ert/ecl/faults/layer.py index dc91705e43..75c246b64f 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/layer.py +++ b/ThirdParty/Ert/python/python/ert/ecl/faults/layer.py @@ -54,7 +54,7 @@ class Layer(BaseCClass): @classmethod def copy(cls , src): layer = Layer( src.getNX() , src.getNY()) - self._copy( layer , src ) + layer._copy( layer , src ) return layer @@ -184,10 +184,10 @@ class Layer(BaseCClass): i2,j2 = p2 if i1 == i2 or j1 == j2: if not 0 <= i2 <= nx: - raise ValueError("i value:%d invalid. Valid range: [0,%d] " % (i , i2)) + raise ValueError("i value:%d invalid. Valid range: [0,%d] " % (i1 , i2)) if not 0 <= j2 <= ny: - raise ValueError("i value:%d invalid. Valid range: [0,%d] " % (j , j2)) + raise ValueError("i value:%d invalid. Valid range: [0,%d] " % (j1 , j2)) self._add_ijbarrier( i1 , j1 , i2 , j2 ) p1 = p2 diff --git a/ThirdParty/Ert/python/python/ert/ecl/fortio.py b/ThirdParty/Ert/python/python/ert/ecl/fortio.py index 5929d126c2..2c680f4a9d 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/fortio.py +++ b/ThirdParty/Ert/python/python/ert/ecl/fortio.py @@ -51,17 +51,17 @@ class FortIO(BaseCClass): READ_AND_WRITE_MODE = 3 APPEND_MODE = 4 - _open_reader = EclPrototype("void* fortio_open_reader(char*, bool, bool)" , bind = False) - _open_writer = EclPrototype("void* fortio_open_writer(char*, bool, bool)" , bind = False) - _open_readwrite = EclPrototype("void* fortio_open_readwrite(char*, bool, bool)" , bind = False) - _open_append = EclPrototype("void* fortio_open_append(char*, bool, bool)" , bind = False) - _guess_fortran = EclPrototype("bool fortio_looks_like_fortran_file(char* , bool)" , bind = False) + _open_reader = EclPrototype("void* fortio_open_reader(char*, bool, bool)", bind=False) + _open_writer = EclPrototype("void* fortio_open_writer(char*, bool, bool)", bind=False) + _open_readwrite = EclPrototype("void* fortio_open_readwrite(char*, bool, bool)", bind=False) + _open_append = EclPrototype("void* fortio_open_append(char*, bool, bool)", bind=False) + _guess_fortran = EclPrototype("bool fortio_looks_like_fortran_file(char*, bool)", bind=False) _write_record = EclPrototype("void fortio_fwrite_record(fortio, char*, int)") _get_position = EclPrototype("long fortio_ftell(fortio)") _seek = EclPrototype("void fortio_fseek(fortio, long, int)") _close = EclPrototype("bool fortio_fclose(fortio)") - _truncate = EclPrototype("bool fortio_ftruncate(fortio , long)") + _truncate = EclPrototype("bool fortio_ftruncate(fortio, long)") _filename = EclPrototype("char* fortio_filename_ref(fortio)") @@ -85,14 +85,14 @@ class FortIO(BaseCClass): all the pressure keywords to another file: import sys - from ert.ecl import FortIO,ElcFile + from ert.ecl import FortIO, EclFile rst_file = EclFile(sys.argv[1]) - fortio = FortIO( "PRESSURE" , mode=FortIO.WRITE_MODE) + fortio = FortIO("PRESSURE", mode=FortIO.WRITE_MODE) for kw in rst_file: if kw.name() == "PRESSURE": - kw.write( fortio ) + kw.write(fortio) fortio.close() @@ -100,10 +100,9 @@ class FortIO(BaseCClass): method based on a context manager and the with statement. """ - if mode == FortIO.READ_MODE or mode == FortIO.APPEND_MODE or mode == FortIO.READ_AND_WRITE_MODE: - if not os.path.exists(file_name): - raise IOError("File '%s' does not exist!" % file_name) - + read_modes = (FortIO.READ_MODE, FortIO.APPEND_MODE, FortIO.READ_AND_WRITE_MODE) + if mode in read_modes and not os.path.exists(file_name): + raise IOError('No such file "%s".' % file_name) if mode == FortIO.READ_MODE: c_pointer = self._open_reader(file_name, fmt_file, endian_flip_header) elif mode == FortIO.WRITE_MODE: @@ -116,48 +115,49 @@ class FortIO(BaseCClass): raise UserWarning("Unknown mode: %d" % mode) self.__mode = mode - + if not c_pointer: + raise IOError('Failed to open FortIO file "%s".' % file_name) super(FortIO, self).__init__(c_pointer) def close(self): if self: - self._close( ) - self._invalidateCPointer( ) + self._close() + self._invalidateCPointer() def getPosition(self): """ @rtype: long """ - return self._get_position( ) + return self._get_position() - def truncate(self , size = None): + def truncate(self, size=None): """Will truncate the file to new size. If the method is called without a size argument the stream will be truncated to the current position. """ if size is None: - size = self.getPosition( ) + size = self.getPosition() - if not self._truncate( size ): - raise IOError("Truncate of fortran filehandle:%s failed" % self.filename() ) + if not self._truncate(size): + raise IOError("Truncate of fortran filehandle:%s failed" % self.filename()) def filename(self): - return self._filename( ) + return self._filename() - def seek(self, position , whence = 0): + def seek(self, position, whence=0): # SEEK_SET = 0 # SEEK_CUR = 1 # SEEK_END = 2 - self._seek(position , whence) + self._seek(position, whence) @classmethod - def isFortranFile(cls , filename , endian_flip = True): + def isFortranFile(cls, filename, endian_flip=True): """@rtype: bool @type filename: str @@ -167,7 +167,7 @@ class FortIO(BaseCClass): file written in fortran style. ASCII files will return false, even if they are structured as ECLIPSE keywords. """ - return cls._guess_fortran( filename , endian_flip ) + return cls._guess_fortran(filename, endian_flip) def free(self): @@ -176,7 +176,7 @@ class FortIO(BaseCClass): class FortIOContextManager(object): - def __init__(self , fortio): + def __init__(self, fortio): self.__fortio = fortio def __enter__(self): @@ -184,29 +184,24 @@ class FortIOContextManager(object): def __exit__(self, exc_type, exc_val, exc_tb): self.__fortio.close() - return False + return exc_type is not None -def openFortIO( file_name , mode = FortIO.READ_MODE , fmt_file = False , endian_flip_header = True): +def openFortIO(file_name, mode=FortIO.READ_MODE, fmt_file=False, endian_flip_header=True): """Will create FortIO based context manager for use with with. The with: statement and context managers is a good alternative in the situation where you need to ensure resource cleanup. import sys - from ert.ecl import FortIO,ElcFile + from ert.ecl import FortIO, EclFile rst_file = EclFile(sys.argv[1]) - with openFortIO( "PRESSURE" , mode = FortIO.WRITE_MODE) as fortio: + with openFortIO("PRESSURE", mode=FortIO.WRITE_MODE) as fortio: for kw in rst_file: if kw.name() == "PRESSURE": - kw.write( fortio ) + kw.write(fortio) """ - return FortIOContextManager( FortIO( file_name , mode = mode , fmt_file = fmt_file , endian_flip_header = endian_flip_header )) - - - - - - + return FortIOContextManager(FortIO(file_name, mode=mode, fmt_file=fmt_file, + endian_flip_header=endian_flip_header)) diff --git a/ThirdParty/Ert/python/python/ert/enkf/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/enkf/CMakeLists.txt deleted file mode 100644 index 06b481ddac..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - active_list.py - analysis_config.py - analysis_iter_config.py - custom_kw_config_set.py - ecl_config.py - enkf_fs.py - enkf_fs_manager.py - enkf_linalg.py - enkf_main.py - enkf_obs.py - enkf_simulation_runner.py - enkf_state.py - ensemble_config.py - ert_log.py - ert_run_context.py - ert_template.py - ert_templates.py - ert_workflow_list.py - key_manager.py - local_config.py - local_dataset.py - local_ministep.py - local_obsdata.py - local_obsdata_node.py - local_updatestep.py - meas_block.py - meas_data.py - model_config.py - node_id.py - obs_block.py - obs_data.py - plot_settings.py - hook_manager.py - hook_workflow.py - run_arg.py - runpath_list.py - site_config.py - state_map.py - summary_key_matcher.py - summary_key_set.py - forward_load_context.py - es_update.py -) - -add_python_package("python.ert.enkf" ${PYTHON_INSTALL_PREFIX}/ert/enkf "${PYTHON_SOURCES}" True) - -add_subdirectory(config) -add_subdirectory(data) -add_subdirectory(enums) -add_subdirectory(export) -add_subdirectory(observations) -add_subdirectory(plot) -add_subdirectory(plot_data) -add_subdirectory(util) diff --git a/ThirdParty/Ert/python/python/ert/enkf/__init__.py b/ThirdParty/Ert/python/python/ert/enkf/__init__.py deleted file mode 100644 index 91457ab6b8..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/__init__.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file '__init__.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -import ert -from cwrap import Prototype -import ert.util -import ert.geo -import ert.ecl -import ert.rms -import ert.analysis -import ert.sched -import ert.config -import ert.job_queue - -class EnkfPrototype(Prototype): - lib = ert.load("libenkf") - - def __init__(self, prototype, bind=True): - super(EnkfPrototype, self).__init__(EnkfPrototype.lib, prototype, bind=bind) - - - -ENKF_LIB = ert.load("libenkf") - -from .enums import * - -from .node_id import NodeId - -from .enkf_linalg import EnkfLinalg -from .util import TimeMap -from .state_map import StateMap -from .summary_key_set import SummaryKeySet -from .summary_key_matcher import SummaryKeyMatcher -from .custom_kw_config_set import CustomKWConfigSet -from .enkf_fs import EnkfFs - -from .ert_workflow_list import ErtWorkflowList -from .active_list import ActiveList -from .config import * -from .data import * - -from .local_dataset import LocalDataset -from .local_obsdata_node import LocalObsdataNode -from .local_obsdata import LocalObsdata -from .local_ministep import LocalMinistep -from .local_updatestep import LocalUpdateStep - -from .observations import * - -from .obs_block import ObsBlock -from .obs_data import ObsData -from .meas_block import MeasBlock -from .meas_data import MeasData - -from .analysis_iter_config import AnalysisIterConfig -from .analysis_config import AnalysisConfig -from .ecl_config import EclConfig - -from .ensemble_config import EnsembleConfig -from .enkf_obs import EnkfObs -from .enkf_state import EnKFState -from .ert_template import ErtTemplate -from .ert_templates import ErtTemplates -from .local_config import LocalConfig -from .model_config import ModelConfig -from .plot_settings import PlotSettings -from .site_config import SiteConfig -from .runpath_list import RunpathList, RunpathNode -from .hook_workflow import HookWorkflow -from .hook_manager import HookManager - -from .es_update import ESUpdate -from .enkf_simulation_runner import EnkfSimulationRunner -from .enkf_fs_manager import EnkfFsManager -from .run_arg import RunArg -from .ert_run_context import ErtRunContext -from .enkf_main import EnKFMain -from .ert_log import ErtLog -from .forward_load_context import ForwardLoadContext - -from ert.job_queue import ErtScript as ErtScript -from ert.job_queue import ErtPlugin as ErtPlugin, CancelPluginException as CancelPluginException diff --git a/ThirdParty/Ert/python/python/ert/enkf/active_list.py b/ThirdParty/Ert/python/python/ert/enkf/active_list.py deleted file mode 100644 index 520db63ed6..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/active_list.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'active_list.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf import ActiveMode - -class ActiveList(BaseCClass): - TYPE_NAME = "active_list" - - _alloc = EnkfPrototype("void* active_list_alloc()", bind = False) - _free = EnkfPrototype("void active_list_free(active_list)") - _add_index = EnkfPrototype("void active_list_add_index(active_list , int)") - _asize = EnkfPrototype("int active_list_get_active_size(active_list, int)") - _get_mode = EnkfPrototype("active_mode_enum active_list_get_mode(active_list)") - - def __init__(self): - c_ptr = self._alloc() - super(ActiveList, self).__init__(c_ptr) - - def getMode(self): - return self._get_mode() - - def addActiveIndex(self, index): - self._add_index(index) - - def getActiveSize(self, default_value): - """In mode PARTLY_ACTIVE, we return the size of the active set; In mode - INACTIVE 0 is returned and if the mode is ALL_ACTIVE, the input - default_value is returned. - """ - mode = self.getMode() - if mode == ActiveMode.PARTLY_ACTIVE: - return self._asize(0) - if mode == ActiveMode.INACTIVE: - return 0 - return default_value - - def free(self): - self._free() - - def __repr__(self): - size = '' - if self.getMode() == ActiveMode.PARTLY_ACTIVE: - size = ', active_size = %d' % self._asize(0) - cnt = 'mode = %s%s' % (self.getMode(), size) - return self._create_repr(cnt) diff --git a/ThirdParty/Ert/python/python/ert/enkf/analysis_config.py b/ThirdParty/Ert/python/python/ert/enkf/analysis_config.py deleted file mode 100644 index 3f6a004a3a..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/analysis_config.py +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'analysis_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf import AnalysisIterConfig -from ert.analysis import AnalysisModule -from ert.util import StringList - - -class AnalysisConfig(BaseCClass): - TYPE_NAME = "analysis_config" - _alloc = EnkfPrototype("void* analysis_config_alloc()", bind = False) - _free = EnkfPrototype("void analysis_config_free( analysis_config )") - _get_rerun = EnkfPrototype("int analysis_config_get_rerun( analysis_config )") - _set_rerun = EnkfPrototype("void analysis_config_set_rerun( analysis_config, bool)") - _get_rerun_start = EnkfPrototype("int analysis_config_get_rerun_start( analysis_config )") - _set_rerun_start = EnkfPrototype("void analysis_config_set_rerun_start( analysis_config, int)") - _get_log_path = EnkfPrototype("char* analysis_config_get_log_path( analysis_config)") - _set_log_path = EnkfPrototype("void analysis_config_set_log_path( analysis_config, char*)") - _get_merge_observations = EnkfPrototype("bool analysis_config_get_merge_observations(analysis_config)") - _set_merge_observations = EnkfPrototype("void analysis_config_set_merge_observations(analysis_config, bool)") - _get_iter_config = EnkfPrototype("analysis_iter_config_ref analysis_config_get_iter_config(analysis_config)") - _have_enough_realisations = EnkfPrototype("bool analysis_config_have_enough_realisations(analysis_config, int, int)") - _get_max_runtime = EnkfPrototype("int analysis_config_get_max_runtime(analysis_config)") - _set_max_runtime = EnkfPrototype("void analysis_config_set_max_runtime(analysis_config, int)") - _get_stop_long_running = EnkfPrototype("bool analysis_config_get_stop_long_running(analysis_config)") - _set_stop_long_running = EnkfPrototype("void analysis_config_set_stop_long_running(analysis_config, bool)") - _get_active_module_name = EnkfPrototype("char* analysis_config_get_active_module_name(analysis_config)") - _get_module_list = EnkfPrototype("stringlist_obj analysis_config_alloc_module_names(analysis_config)") - _get_module = EnkfPrototype("analysis_module_ref analysis_config_get_module(analysis_config, char*)") - _select_module = EnkfPrototype("bool analysis_config_select_module(analysis_config, char*)") - _has_module = EnkfPrototype("bool analysis_config_has_module(analysis_config, char*)") - _get_alpha = EnkfPrototype("double analysis_config_get_alpha(analysis_config)") - _set_alpha = EnkfPrototype("void analysis_config_set_alpha(analysis_config, double)") - _get_std_cutoff = EnkfPrototype("double analysis_config_get_std_cutoff(analysis_config)") - _set_std_cutoff = EnkfPrototype("void analysis_config_set_std_cutoff(analysis_config, double)") - _set_global_std_scaling = EnkfPrototype("void analysis_config_set_global_std_scaling(analysis_config, double)") - _get_global_std_scaling = EnkfPrototype("double analysis_config_get_global_std_scaling(analysis_config)") - - def __init__(self): - c_ptr = AnalysisConfig._alloc() - super(AnalysisConfig , self).__init__(c_ptr) - - - def get_rerun(self): - return self._get_rerun() - - def set_rerun(self, rerun): - self._set_rerun(rerun) - - def get_rerun_start(self): - return self._get_rerun_start() - - def set_rerun_start(self, index): - self._set_rerun_start(index) - - def get_log_path(self): - return self._get_log_path() - - def set_log_path(self, path): - self._set_log_path(path) - - def getEnkfAlpha(self): - """ :rtype: float """ - return self._get_alpha() - - def setEnkfAlpha(self, alpha): - self._set_alpha(alpha) - - def getStdCutoff(self): - """ :rtype: float """ - return self._get_std_cutoff() - - def setStdCutoff(self, std_cutoff): - self._set_std_cutoff(std_cutoff) - - def get_merge_observations(self): - return self._get_merge_observations() - - def set_merge_observations(self, merge_observations): - return self._set_merge_observations(merge_observations) - - def getAnalysisIterConfig(self): - """ @rtype: AnalysisIterConfig """ - return self._get_iter_config().setParent(self) - - def get_stop_long_running(self): - """ @rtype: bool """ - return self._get_stop_long_running() - - def set_stop_long_running(self, stop_long_running): - self._set_stop_long_running(stop_long_running) - - def get_max_runtime(self): - """ @rtype: int """ - return self._get_max_runtime() - - def set_max_runtime(self, max_runtime): - self._set_max_runtime(max_runtime) - - def free(self): - self._free() - - def activeModuleName(self): - """ :rtype: str """ - return self._get_active_module_name() - - def getModuleList(self): - """ :rtype: StringList """ - return self._get_module_list() - - def getModule(self, module_name): - """ @rtype: AnalysisModule """ - return self._get_module(module_name) - - def hasModule(self, module_name): - """ @rtype: bool """ - return self._has_module(module_name) - - - def selectModule(self, module_name): - """ @rtype: bool """ - return self._select_module(module_name) - - def getActiveModule(self): - """ :rtype: AnalysisModule """ - return self.getModule(self.activeModuleName()) - - def setGlobalStdScaling(self, std_scaling): - self._set_global_std_scaling(std_scaling) - - def getGlobalStdScaling(self): - return self._get_global_std_scaling() - - def haveEnoughRealisations(self, realizations, ensemble_size): - return self._have_enough_realisations(realizations, ensemble_size) - - diff --git a/ThirdParty/Ert/python/python/ert/enkf/analysis_iter_config.py b/ThirdParty/Ert/python/python/ert/enkf/analysis_iter_config.py deleted file mode 100644 index 91c9ff1250..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/analysis_iter_config.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'analysis_iter_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype - -class AnalysisIterConfig(BaseCClass): - TYPE_NAME = "analysis_iter_config" - - _alloc = EnkfPrototype("void* analysis_iter_config_alloc( )", bind = False) - _free = EnkfPrototype("void analysis_iter_config_free( analysis_iter_config )") - _set_num_iterations = EnkfPrototype("void analysis_iter_config_set_num_iterations(analysis_iter_config, int)") - _get_num_iterations = EnkfPrototype("int analysis_iter_config_get_num_iterations(analysis_iter_config)") - _get_num_retries = EnkfPrototype("int analysis_iter_config_get_num_retries_per_iteration(analysis_iter_config)") - _num_iterations_set = EnkfPrototype("bool analysis_iter_config_num_iterations_set(analysis_iter_config)") - _set_case_fmt = EnkfPrototype("void analysis_iter_config_set_case_fmt( analysis_iter_config , char* )") - _get_case_fmt = EnkfPrototype("char* analysis_iter_config_get_case_fmt( analysis_iter_config)") - _case_fmt_set = EnkfPrototype("bool analysis_iter_config_case_fmt_set(analysis_iter_config)") - - def __init__(self): - c_ptr = self._alloc() - super(AnalysisIterConfig , self).__init__(c_ptr) - - def getNumIterations(self): - """ @rtype: int """ - return self._get_num_iterations() - - def __len__(self): - """Returns number of iterations.""" - return self.getNumIterations() - - def setNumIterations(self, num_iterations): - self._set_num_iterations(num_iterations) - - def numIterationsSet(self): - return self._num_iterations_set() - - def getNumRetries(self): - """ @rtype: int """ - return self._get_num_retries() - - def getCaseFormat(self): - """ @rtype: str """ - return self._get_case_fmt() - - def setCaseFormat(self, case_fmt): - self._set_case_fmt(case_fmt) - - def caseFormatSet(self): - return self._case_fmt_set() - - def free(self): - self._free() - - def _short_case_fmt(self, maxlen=10): - fmt = getCaseFormat() - if len(fmt) <= maxlen: - return fmt - return fmt[:maxlen-2] + ".." - - def __repr__(self): - cfs = 'format = False' - if self.caseFormatSet(): - cfs = 'format = True' - fmt = self._short_case_fmt() - ret = 'AnalysisIterConfig(iterations = %d, retries = %d, fmt = %s, %s) at 0x%x' - its = len(self) - rets = self.getNumRetries() - return ret % (its, rets, fmt, cfs, self._address) diff --git a/ThirdParty/Ert/python/python/ert/enkf/config/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/enkf/config/CMakeLists.txt deleted file mode 100644 index c87926f16f..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/config/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - custom_kw_config.py - enkf_config_node.py - field_type_enum.py - field_config.py - gen_data_config.py - gen_kw_config.py - summary_config.py -) - -add_python_package("python.ert.enkf.config" ${PYTHON_INSTALL_PREFIX}/ert/enkf/config "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/enkf/config/__init__.py b/ThirdParty/Ert/python/python/ert/enkf/config/__init__.py deleted file mode 100644 index 55f02ef61e..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/config/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -from .custom_kw_config import CustomKWConfig -from .field_config import FieldConfig -from .field_type_enum import FieldTypeEnum -from .gen_data_config import GenDataConfig -from .gen_kw_config import GenKwConfig -from .summary_config import SummaryConfig -from .enkf_config_node import EnkfConfigNode - - -__all__ = ["FieldConfig", - "FieldTypeEnum", - "CustomKWConfig", - "GenKwConfig", - "GenDataConfig", - "EnkfConfigNode", - "SummaryConfig"] diff --git a/ThirdParty/Ert/python/python/ert/enkf/config/custom_kw_config.py b/ThirdParty/Ert/python/python/ert/enkf/config/custom_kw_config.py deleted file mode 100644 index df01cf71c1..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/config/custom_kw_config.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'field_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import sys - -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.util import StringList, IntegerHash - - -class CustomKWConfig(BaseCClass): - TYPE_NAME = "custom_kw_config" - - _alloc_empty = EnkfPrototype("void* custom_kw_config_alloc_empty(char*, char*, char*)", bind = False) - _alloc_with_definition = EnkfPrototype("void* custom_kw_config_alloc_with_definition(char*, integer_hash)", bind = False) - _get_name = EnkfPrototype("char* custom_kw_config_get_name(custom_kw_config)") - _get_result_file = EnkfPrototype("char* custom_kw_config_get_result_file(custom_kw_config)") - _get_output_file = EnkfPrototype("char* custom_kw_config_get_output_file(custom_kw_config)") - _parse_result_file = EnkfPrototype("bool custom_kw_config_parse_result_file(custom_kw_config, char*, stringlist)") - _has_key = EnkfPrototype("bool custom_kw_config_has_key(custom_kw_config, char*)") - _key_is_double = EnkfPrototype("bool custom_kw_config_key_is_double(custom_kw_config, char*)") - _index_of_key = EnkfPrototype("int custom_kw_config_index_of_key(custom_kw_config, char*)") - _size = EnkfPrototype("int custom_kw_config_size(custom_kw_config)") - _keys = EnkfPrototype("stringlist_obj custom_kw_config_get_keys(custom_kw_config)") - _free = EnkfPrototype("void custom_kw_config_free(custom_kw_config)") - - def __init__(self, key, result_file, output_file=None, definition=None): - """ - @type key: str - @type result_file: str - @type output_file: str - @type definition: dict - """ - - if definition is not None: - if result_file is not None and output_file is not None: - sys.stderr.write("[%s] Will ignore result file and output file when constructing with a definition." % self.__class__.__name__) - - type_hash = CustomKWConfig.convertDefinition(definition) - c_ptr = self._alloc_with_definition(key, type_hash) - else: - c_ptr = self._alloc_empty(key, result_file, output_file) - super(CustomKWConfig, self).__init__(c_ptr) - - def getName(self): - """ @rtype: str """ - return self.name() - - def name(self): - return self._get_name() - - def getResultFile(self): - """ @rtype: str """ - return self._get_result_file() - - def getOutputFile(self): - """ @rtype: str """ - return self._get_output_file() - - def parseResultFile(self, result_file, result): - """ @rtype: bool """ - return self._parse_result_file(result_file, result) - - def keyIsDouble(self, key): - """ @rtype: bool """ - return self._key_is_double(key) - - def indexOfKey(self, key): - """ @rtype: int """ - return self._index_of_key(key) - - def __contains__(self, item): - """ @rtype: bool """ - return self._has_key(item) - - def __len__(self): - """ @rtype: int """ - return self._size() - - def __iter__(self): - keys = self.getKeys() - index = 0 - while index < len(keys): - yield keys[index] - index += 1 - - def free(self): - self._free() - - def __repr__(self): - return 'CustomKWConfig(name = %s, len = %d) %s' % (self.name(), len(self), self._ad_str()) - - def getKeys(self): - """ @rtype: StringList """ - return self._keys() - - @classmethod - def convertDefinition(cls, definition): - """ @rtype: IntegerHash """ - type_hash = IntegerHash() - - for key, value_type in definition.iteritems(): - if value_type == float: - value_type = 1 - else: - value_type = 0 #str - type_hash[key] = value_type - return type_hash diff --git a/ThirdParty/Ert/python/python/ert/enkf/config/enkf_config_node.py b/ThirdParty/Ert/python/python/ert/enkf/config/enkf_config_node.py deleted file mode 100644 index c7101a1dff..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/config/enkf_config_node.py +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'enkf_config_node.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.config import FieldConfig, GenDataConfig, GenKwConfig, SummaryConfig, CustomKWConfig -from ert.enkf.enums import EnkfTruncationType, ErtImplType, LoadFailTypeEnum, EnkfVarType -from ert.ecl import EclGrid -from ert.util import PathFormat - -class EnkfConfigNode(BaseCClass): - TYPE_NAME = "enkf_config_node" - - _alloc_summary_node = EnkfPrototype("enkf_config_node_obj enkf_config_node_alloc_summary(char*, load_fail_type)", bind = False) - _alloc_field_node = EnkfPrototype("enkf_config_node_obj enkf_config_node_alloc_field(char*, ecl_grid, void*, bool)", bind = False) - _get_ref = EnkfPrototype("void* enkf_config_node_get_ref(enkf_config_node)") #todo: fix return type - _get_impl_type = EnkfPrototype("ert_impl_type_enum enkf_config_node_get_impl_type(enkf_config_node)") - _get_enkf_outfile = EnkfPrototype("char* enkf_config_node_get_enkf_outfile(enkf_config_node)") - _get_min_std_file = EnkfPrototype("char* enkf_config_node_get_min_std_file(enkf_config_node)") - _get_enkf_infile = EnkfPrototype("char* enkf_config_node_get_enkf_infile(enkf_config_node)") - _get_init_file = EnkfPrototype("char* enkf_config_node_get_FIELD_fill_file(enkf_config_node, path_fmt)") - _get_init_file_fmt = EnkfPrototype("char* enkf_config_node_get_init_file_fmt(enkf_config_node)") - _get_var_type = EnkfPrototype("enkf_var_type_enum enkf_config_node_get_var_type(enkf_config_node)") #todo: fix return type as enum - _get_key = EnkfPrototype("char* enkf_config_node_get_key(enkf_config_node)") - _get_obs_keys = EnkfPrototype("stringlist_ref enkf_config_node_get_obs_keys(enkf_config_node)") - _update_state_field = EnkfPrototype("void enkf_config_node_update_state_field(enkf_config_node, enkf_truncation_type_enum, double, double)") - _free = EnkfPrototype("void enkf_config_node_free(enkf_config_node)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def getImplementationType( self ): - """ @rtype: ErtImplType """ - return self._get_impl_type() - - def getVariableType( self ): - return self._get_var_type() - - def getPointerReference(self): - return self._get_ref() - - def getInitFile(self, model_config): - return self._enkf_config_node_get_init_file(model_config.getRunpathFormat()) - - # def get_min_std_file(self): - # return self._get_min_std_file() - - # def get_enkf_outfile(self): - # return self._get_enkf_outfile() - - def getFieldModelConfig(self): - """ @rtype: FieldConfig """ - return FieldConfig.createCReference(self._get_ref(), parent=self) - - def getDataModelConfig(self): - """ @rtype: GenDataConfig """ - return GenDataConfig.createCReference(self._get_ref(), parent=self) - - def getKeywordModelConfig(self): - """ @rtype: GenKWConfig """ - return GenKwConfig.createCReference(self._get_ref(), parent=self) - - def getCustomKeywordModelConfig(self): - """ @rtype: CustomKWConfig """ - return CustomKWConfig.createCReference(self._get_ref(), parent=self) - - # def get_enkf_infile(self): - # return self._get_enkf_infile() - - # def alloc_node(self): - # return EnkfNode(self) - - # def get_init_file_fmt(self): - # return self._get_init_file_fmt() - - def getObservationKeys(self): - """ @rtype: StringList """ - return self._get_obs_keys().setParent(self) - - def updateStateField(self, truncation, value_min, value_max): - assert isinstance(truncation, EnkfTruncationType) - self._update_state_field(truncation, value_min, value_max) - - @classmethod - def createSummaryConfigNode(cls, key, load_fail_type): - """ - @type key: str - @type load_fail_type: LoadFailTypeEnum - @rtype: EnkfConfigNode - """ - - assert isinstance(load_fail_type, LoadFailTypeEnum) - return cls._alloc_summary_node(key, load_fail_type) - - @classmethod - def createFieldConfigNode(cls, key, grid, trans_table = None, forward_init = False): - """ - @type grid: EclGrid - @rtype: EnkfConfigNode - """ - return cls._alloc_field_node(key, grid, trans_table, forward_init) - - def free(self): - self._free() - - def __repr__(self): - key = self.getKey() - vt = self.getVariableType() - imp = self.getImplementationType() - content = 'key = %s, var_type = %s, implementation = %s' % (key, vt, imp) - return self._create_repr(content) - - def getModelConfig(self): - implementation_type = self.getImplementationType() - - if implementation_type == ErtImplType.FIELD: - return self.getFieldModelConfig() - elif implementation_type == ErtImplType.GEN_DATA: - return self.getDataModelConfig() - elif implementation_type == ErtImplType.GEN_KW: - return self.getKeywordModelConfig() - elif implementation_type == ErtImplType.CUSTOM_KW: - return self.getCustomKeywordModelConfig() - elif implementation_type == ErtImplType.SUMMARY: - return SummaryConfig.createCReference(self.getPointerReference(), parent=self) - else: - print("[EnkfConfigNode::getModelConfig()] Unhandled implementation model type: %i" % implementation_type) - # raise NotImplementedError("Unknown model type: %i" % type) - - def getKey(self): - return self._get_key() diff --git a/ThirdParty/Ert/python/python/ert/enkf/config/field_config.py b/ThirdParty/Ert/python/python/ert/enkf/config/field_config.py deleted file mode 100644 index ce3594ca37..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/config/field_config.py +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# This file is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass - -from ert.enkf import EnkfPrototype -from ert.enkf.enums import EnkfFieldFileFormatEnum -from ert.ecl import EclGrid -from .field_type_enum import FieldTypeEnum - -class FieldConfig(BaseCClass): - TYPE_NAME = "field_config" - - _alloc = EnkfPrototype("void* field_config_alloc_empty(char* , ecl_grid , void* , bool)", bind = False) - _free = EnkfPrototype("void field_config_free( field_config )") - _get_type = EnkfPrototype("field_type_enum field_config_get_type(field_config)") - _get_truncation_mode = EnkfPrototype("int field_config_get_truncation_mode(field_config)") - _get_truncation_min = EnkfPrototype("double field_config_get_truncation_min(field_config)") - _get_truncation_max = EnkfPrototype("double field_config_get_truncation_max(field_config)") - _get_init_transform_name = EnkfPrototype("char* field_config_get_init_transform_name(field_config)") - _get_output_transform_name = EnkfPrototype("char* field_config_get_output_transform_name(field_config)") - _ijk_active = EnkfPrototype("bool field_config_ijk_active(field_config, int, int, int)") - _get_nx = EnkfPrototype("int field_config_get_nx(field_config)") - _get_ny = EnkfPrototype("int field_config_get_ny(field_config)") - _get_nz = EnkfPrototype("int field_config_get_nz(field_config)") - _get_grid = EnkfPrototype("ecl_grid_ref field_config_get_grid(field_config)") - _export_format = EnkfPrototype("enkf_field_file_format_enum field_config_default_export_format(char*)", bind = False) - _guess_filetype = EnkfPrototype("enkf_field_file_format_enum field_config_guess_file_type(char*)", bind = False) - - def __init__(self , kw , grid): - c_ptr = self._alloc( kw , grid , None , False ) - super(FieldConfig, self).__init__(c_ptr) - - @classmethod - def exportFormat(cls , filename): - export_format = cls._export_format( filename ) - if export_format in [ EnkfFieldFileFormatEnum.ECL_GRDECL_FILE , EnkfFieldFileFormatEnum.RMS_ROFF_FILE ]: - return export_format - else: - raise ValueError("Could not determine grdecl / roff format from:%s" % filename) - - @classmethod - def guessFiletype(cls, filename): - return cls._guess_filetype(filename) - - def get_type(self): - return self._get_type() - - def get_truncation_mode(self): - return self._get_truncation_mode() - - def get_truncation_min(self): - return self._get_truncation_min() - - def get_init_transform_name(self): - return self._get_init_transform_name() - - def get_output_transform_name(self): - return self._get_output_transform_name() - - def get_truncation_max(self): - return self._get_truncation_max() - - def get_nx(self): - return self._get_nx() - - def get_ny(self): - return self._get_ny() - - def get_nz(self): - return self._get_nz() - - def get_grid(self): - return self._get_grid() - - def ijk_active(self, i, j, k): - return self._ijk_active(i, j, k) - - def free(self): - self._free() - - def __repr__(self): - tp = self.get_type() - nx,ny,nz = self.get_nx(),self.get_ny(),self.get_nz() - cnt = 'type = %s, nx = %d, ny = %d, nz = %d' % (tp, nx,ny,nz) - return self._create_repr(cnt) diff --git a/ThirdParty/Ert/python/python/ert/enkf/config/gen_data_config.py b/ThirdParty/Ert/python/python/ert/enkf/config/gen_data_config.py deleted file mode 100644 index 0c832b7123..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/config/gen_data_config.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'gen_data_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.enums import GenDataFileType - - -class GenDataConfig(BaseCClass): - TYPE_NAME = "gen_data_config" - - _alloc = EnkfPrototype("void* gen_data_config_alloc_GEN_DATA_result( char* , gen_data_file_format_type)", bind = False) - _free = EnkfPrototype("void gen_data_config_free( gen_data_config )") - _get_output_format = EnkfPrototype("gen_data_file_format_type gen_data_config_get_output_format(gen_data_config)") - _get_input_format = EnkfPrototype("gen_data_file_format_type gen_data_config_get_input_format(gen_data_config)") - _get_template_file = EnkfPrototype("char* gen_data_config_get_template_file(gen_data_config)") - _get_template_key = EnkfPrototype("char* gen_data_config_get_template_key(gen_data_config)") - _get_initial_size = EnkfPrototype("int gen_data_config_get_initial_size(gen_data_config)") - _has_report_step = EnkfPrototype("bool gen_data_config_has_report_step(gen_data_config, int)") - _get_data_size = EnkfPrototype("int gen_data_config_get_data_size__(gen_data_config , int)") - _get_key = EnkfPrototype("char* gen_data_config_get_key(gen_data_config)") - _get_active_mask = EnkfPrototype("bool_vector_ref gen_data_config_get_active_mask(gen_data_config)") - _get_num_report_step = EnkfPrototype("int gen_data_config_num_report_step(gen_data_config)") - _iget_report_step = EnkfPrototype("int gen_data_config_iget_report_step(gen_data_config, int)") - - - def __init__(self, key , input_format = GenDataFileType.ASCII): - # Can currently only create GEN_DATA instances which should be used - # as result variables. - c_pointer = self._alloc( key , input_format ) - super(GenDataConfig, self).__init__(c_pointer) - - - def get_template_file(self): - return self._get_template_file() - - def get_template_key(self): - return self._get_template_key() - - def getDataSize(self , report_step): - data_size = self._get_data_size(report_step) - if data_size < 0: - raise ValueError("No data has been loaded for %s at report step:%d " % (self.getName() , report_step)) - else: - return data_size - - def getActiveMask(self): - return self._get_active_mask() - - def getName(self): - return self.name() - def name(self): - return self._get_key() - - def get_initial_size(self): - return self._get_initial_size() - - def getOutputFormat(self): - return self._get_output_format() - - def getInputFormat(self): - return self._get_input_format() - - def free(self): - self._free() - - def __repr__(self): - nm = self.name() - tk = self.get_template_key() - iz = self.get_initial_size() - return 'GenDataConfig(name = %s, template_key = %s, initial_size = %d) %s' % (nm, tk, iz, self._ad_str()) - - def hasReportStep(self, report_step): - """ @rtype: bool """ - return self._has_report_step(report_step) - - def getNumReportStep(self): - """ @rtype: int """ - return self._get_num_report_step() - - def getReportStep(self, index): - """ @rtype: int """ - return self._iget_report_step(index) - - def getReportSteps(self): - """ @rtype: list of int """ - return [self.getReportStep(index) for index in range(self.getNumReportStep())] diff --git a/ThirdParty/Ert/python/python/ert/enkf/config/gen_kw_config.py b/ThirdParty/Ert/python/python/ert/enkf/config/gen_kw_config.py deleted file mode 100644 index 9dba4a3665..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/config/gen_kw_config.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'gen_kw_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.util import StringList - - -class GenKwConfig(BaseCClass): - TYPE_NAME = "gen_kw_config" - - _free = EnkfPrototype("void gen_kw_config_free( gen_kw_config )") - _alloc_empty = EnkfPrototype("void* gen_kw_config_alloc_empty( char*, char* )", bind = False) - _get_template_file = EnkfPrototype("char* gen_kw_config_get_template_file(gen_kw_config)") - _set_template_file = EnkfPrototype("void gen_kw_config_set_template_file(gen_kw_config , char*)") - _get_parameter_file = EnkfPrototype("char* gen_kw_config_get_parameter_file(gen_kw_config)") - _set_parameter_file = EnkfPrototype("void gen_kw_config_set_parameter_file(gen_kw_config, char*)") - _alloc_name_list = EnkfPrototype("stringlist_obj gen_kw_config_alloc_name_list(gen_kw_config)") - _should_use_log_scale = EnkfPrototype("bool gen_kw_config_should_use_log_scale(gen_kw_config, int)") - _get_key = EnkfPrototype("char* gen_kw_config_get_key(gen_kw_config)") - _size = EnkfPrototype("int gen_kw_config_get_data_size(gen_kw_config)") - _iget_name = EnkfPrototype("char* gen_kw_config_iget_name(gen_kw_config, int)") - - - def __init__(self, key, template_file , parameter_file , tag_fmt = "<%s>"): - """ - @type key: str - @type tag_fmt: str - """ - c_ptr = self._alloc_empty(key, tag_fmt) - if c_ptr: - super(GenKwConfig, self).__init__(c_ptr) - else: - raise ValueError('Could not instantiate GenKwConfig with key="%s" and tag_fmt="%s"' % (key, tag_fmt)) - self._key = key - self._tag_fmt = tag_fmt - self.setTemplateFile(template_file) - self.setParameterFile(parameter_file) - self.__str__ = self.__repr__ - - - def setTemplateFile(self, template_file): - self._set_template_file(template_file) - - def getTemplateFile(self): - return self._get_template_file() - - def getParameterFile(self): - return self._get_parameter_file() - - def setParameterFile(self, parameter_file): - self._set_parameter_file(parameter_file) - - def getKeyWords(self): - """ @rtype: StringList """ - return self._alloc_name_list() - - def shouldUseLogScale(self, index): - """ @rtype: bool """ - return self._should_use_log_scale(index) - - def free(self): - self._free() - - def __repr__(self): - return 'GenKwConfig(key = "%s", tag_fmt = "%s") at 0x%x' % (self._key, self._tag_fmt, self._address()) - - def getKey(self): - """ @rtype: str """ - return self._get_key() - - def __len__(self): - return self._size() - - def __getitem__(self, index): - """ @rtype: str """ - return self._iget_name(index) - - def __iter__(self): - index = 0 - while index < len(self): - yield self[index] - index += 1 diff --git a/ThirdParty/Ert/python/python/ert/enkf/config/summary_config.py b/ThirdParty/Ert/python/python/ert/enkf/config/summary_config.py deleted file mode 100644 index f398b8ed3d..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/config/summary_config.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'field_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass - -class SummaryConfig(BaseCClass): - TYPE_NAME = "summary_config" - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def __repr__(self): - return 'SummaryConfig() %s' % self._ad_str() - - def free(self): - pass diff --git a/ThirdParty/Ert/python/python/ert/enkf/custom_kw_config_set.py b/ThirdParty/Ert/python/python/ert/enkf/custom_kw_config_set.py deleted file mode 100644 index 08ee7f1a6e..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/custom_kw_config_set.py +++ /dev/null @@ -1,47 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.config.custom_kw_config import CustomKWConfig - - -class CustomKWConfigSet(BaseCClass): - TYPE_NAME = "custom_kw_config_set" - - _alloc = EnkfPrototype("void* custom_kw_config_set_alloc()", bind = False) - _alloc_from_file = EnkfPrototype("void* custom_kw_config_set_alloc_from_file(char*)", bind = False) - _free = EnkfPrototype("void custom_kw_config_set_free(custom_kw_config_set)") - _reset = EnkfPrototype("void custom_kw_config_set_reset(custom_kw_config_set)") - _add_config = EnkfPrototype("void custom_kw_config_set_add_config(custom_kw_config_set, custom_kw_config)") - _update_config = EnkfPrototype("void custom_kw_config_set_update_config(custom_kw_config_set, custom_kw_config)") - _fwrite = EnkfPrototype("void custom_kw_config_set_fwrite(custom_kw_config_set, char*)") - _get_keys = EnkfPrototype("stringlist_obj custom_kw_config_set_get_keys_alloc(custom_kw_config_set)") - - def __init__(self, filename=None): - if filename is None: - c_ptr = self._alloc() - else: - c_ptr = self._alloc_from_file(filename) - super(CustomKWConfigSet, self).__init__(c_ptr) - - - def addConfig(self, config): - """ @type config: CustomKWConfig """ - assert isinstance(config, CustomKWConfig) - self._add_config(config) - - def getStoredConfigKeys(self): - """ @rtype: StringList """ - return self._get_keys() - - def updateConfig(self, config): - """ @type config: CustomKWConfig """ - self._update_config(config) - - def fwrite(self, filename): - """ @type filename: str """ - self._fwrite(filename) - - def reset(self): - self._reset() - - def free(self): - self._free() diff --git a/ThirdParty/Ert/python/python/ert/enkf/data/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/enkf/data/CMakeLists.txt deleted file mode 100644 index 8e2d82822b..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/data/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - custom_kw.py - enkf_node.py - field.py - gen_data.py - gen_kw.py -) - -add_python_package("python.ert.enkf.data" ${PYTHON_INSTALL_PREFIX}/ert/enkf/data "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/enkf/data/__init__.py b/ThirdParty/Ert/python/python/ert/enkf/data/__init__.py deleted file mode 100644 index 86fe547005..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/data/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -from .custom_kw import CustomKW -from .field import Field -from .gen_data import GenData -from .gen_kw import GenKw -from .enkf_node import EnkfNode - -__all__ = ["Field", - "CustomKW", - "GenKw", - "GenData", - "EnkfNode",] diff --git a/ThirdParty/Ert/python/python/ert/enkf/data/custom_kw.py b/ThirdParty/Ert/python/python/ert/enkf/data/custom_kw.py deleted file mode 100644 index dc7ad620a3..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/data/custom_kw.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'field_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.config import CustomKWConfig - - -class CustomKW(BaseCClass): - TYPE_NAME = "custom_kw" - - _alloc = EnkfPrototype("void* custom_kw_alloc(custom_kw_config)", bind = False) - _free = EnkfPrototype("void custom_kw_free(custom_kw)") - _fload = EnkfPrototype("bool custom_kw_fload(custom_kw, char*)") - _key_is_null = EnkfPrototype("bool custom_kw_key_is_null(custom_kw, char*)") - _iget_as_double = EnkfPrototype("double custom_kw_iget_as_double(custom_kw, int)") - _iget_as_string = EnkfPrototype("char* custom_kw_iget_as_string(custom_kw, int)") - _set_string = EnkfPrototype("void custom_kw_set_string(custom_kw, char*, char*)") - _set_double = EnkfPrototype("void custom_kw_set_double(custom_kw, char*, double)") - _get_config = EnkfPrototype("custom_kw_config_ref custom_kw_get_config(custom_kw)") - - def __init__(self, custom_kw_config): - assert isinstance(custom_kw_config, CustomKWConfig) - c_ptr = self._alloc(custom_kw_config) - if c_ptr: - super(CustomKW, self).__init__(c_ptr) - else: - raise ValueError('Unable to construct CustomKW with given config!') - - def fload(self, filename): - """ - @type filename: str - @rtype: bool - """ - return self._fload(filename) - - - def __getitem__(self, key): - """ @rtype: str or float """ - config = self.getConfig() - - if not key in config: - raise KeyError("The key: '%s' is not available!" % key) - - index = config.indexOfKey(key) - - if self._key_is_null(key): - return None - - if config.keyIsDouble(key): - return self._iget_as_double(index) - - return self._iget_as_string(index) - - def __setitem__(self, key, value): - """ - @type key: str - @type value: float|int|str - """ - - config = self.getConfig() - - if not key in config: - raise KeyError("The key: '%s' is not available!" % key) - - if isinstance(value, (float, int, long)): - self._set_double(key, value) - else: - self._set_string(key, str(value)) - - - def getConfig(self): - """ @rtype: CustomKWConfig """ - return self._get_config() - - def free(self): - self._free() - - def __repr__(self): - return 'CustomKw() %s' % self._ad_str() diff --git a/ThirdParty/Ert/python/python/ert/enkf/data/enkf_node.py b/ThirdParty/Ert/python/python/ert/enkf/data/enkf_node.py deleted file mode 100644 index 1d000572b3..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/data/enkf_node.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'enkf_node.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import sys -from ert.enkf.enums import ErtImplType -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype, EnkfFs, NodeId -from ert.enkf.data import GenKw, GenData, CustomKW, Field - -class EnkfNode(BaseCClass): - TYPE_NAME = "enkf_node" - _alloc = EnkfPrototype("void* enkf_node_alloc(enkf_config_node)", bind = False) - _alloc_private = EnkfPrototype("void* enkf_node_alloc_private_container(enkf_config_node)", bind = False) - _free = EnkfPrototype("void enkf_node_free(enkf_node)") - _get_name = EnkfPrototype("char* enkf_node_get_key(enkf_node)") - _value_ptr = EnkfPrototype("void* enkf_node_value_ptr(enkf_node)") - _try_load = EnkfPrototype("bool enkf_node_try_load(enkf_node, enkf_fs, node_id)") - _store = EnkfPrototype("bool enkf_node_store(enkf_node, enkf_fs, bool, node_id)") - _get_impl_type = EnkfPrototype("ert_impl_type_enum enkf_node_get_impl_type(enkf_node)") - - def __init__(self, config_node, private=False): - self._private = private - if private: - c_pointer = self._alloc_private(config_node) - else: - c_pointer = self._alloc(config_node) - - if c_pointer: - super(EnkfNode, self).__init__(c_pointer, config_node, True) - else: - p_err = 'private ' if private else '' - raise ValueError('Unable to create %sEnkfNode from given config node.' % p_err) - - @classmethod - def exportMany(cls , config_node , file_format , fs , iens_list , report_step = 0 , file_type = None , arg = None): - node = EnkfNode( config_node ) - for iens in iens_list: - filename = file_format % iens - node_id = NodeId( report_step , iens ) - if node.tryLoad(fs , node_id): - if node.export( filename , file_type = file_type , arg = arg): - print("%s[%03d] -> %s" % (config_node.getKey() , iens , filename)) - else: - sys.stderr.write("** ERROR: Could not load realisation:%d - export failed" % iens) - - - def export(self , filename , file_type = None , arg = None): - impl_type = self.getImplType() - if impl_type == ErtImplType.FIELD: - field_node = self.asField( ) - return field_node.export( filename , file_type = file_type , init_file = arg) - else: - raise NotImplementedError("The export method is only implemented for field") - - - - def valuePointer(self): - return self._value_ptr( ) - - - def getImplType(self): - """ @rtype: ert.enkf.enums.ert_impl_type_enum.ErtImplType """ - return self._get_impl_type( ) - - - def asGenData(self): - """ @rtype: GenData """ - impl_type = self.getImplType( ) - assert impl_type == ErtImplType.GEN_DATA - - return GenData.createCReference(self.valuePointer(), self) - - def asGenKw(self): - """ @rtype: GenKw """ - impl_type = self.getImplType( ) - assert impl_type == ErtImplType.GEN_KW - - return GenKw.createCReference(self.valuePointer(), self) - - def asCustomKW(self): - """ @rtype: CustomKW """ - impl_type = self.getImplType( ) - assert impl_type == ErtImplType.CUSTOM_KW - - return CustomKW.createCReference(self.valuePointer(), self) - - def asField(self): - """ @rtype: CustomKW """ - impl_type = self.getImplType( ) - assert impl_type == ErtImplType.FIELD - - return Field.createCReference(self.valuePointer(), self) - - def tryLoad(self, fs, node_id): - """ - @type fs: EnkfFS - @type node_id: NodeId - @rtype: bool - """ - if not isinstance(fs, EnkfFs): - raise TypeError('fs must be an EnkfFs, not %s' % type(fs)) - if not isinstance(node_id, NodeId): - raise TypeError('node_id must be a NodeId, not %s' % type(node_id)) - - return self._try_load(fs, node_id) - - def name(self): - """ @rtype: str """ - return self._get_name( ) - - def load(self, fs, node_id): - if not self.tryLoad(fs, node_id): - raise Exception("Could not load node: %s iens: %d report: %d" % (self.name(), node_id.iens, node_id.report_step)) - - def save(self, fs, node_id): - assert isinstance(fs, EnkfFs) - assert isinstance(node_id, NodeId) - - return self._store(fs, False, node_id) - - def free(self): - self._free( ) - - def __repr__(self): - pp = ', private' if self._private else '' - return 'EnkfNode(name = "%s"%s) %s' % (self.name(), pp, self._ad_str()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/data/field.py b/ThirdParty/Ert/python/python/ert/enkf/data/field.py deleted file mode 100644 index 431ba2086c..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/data/field.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'field.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import sys - -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.config import FieldConfig - - -class Field(BaseCClass): - TYPE_NAME = "field" - - _free = EnkfPrototype("void field_free( field )") - _ijk_get_double = EnkfPrototype("double field_ijk_get_double(field, int, int, int)") - _export = EnkfPrototype("void field_export(field, char* , fortio , enkf_field_file_format_enum , bool , char*)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - - def ijk_get_double(self, i, j, k): - return self._ijk_get_double(i, j, k) - - - def export(self , filename , file_type = None , init_file = None): - output_transform = False - if file_type is None: - try: - file_type = FieldConfig.exportFormat( filename ) - except ValueError: - sys.stderr.write("Sorry - could not infer output format from filename:%s\n" % filename) - return False - - self._export(filename , None , file_type , output_transform , init_file ) - return True - - - def free(self): - self._free() diff --git a/ThirdParty/Ert/python/python/ert/enkf/data/gen_data.py b/ThirdParty/Ert/python/python/ert/enkf/data/gen_data.py deleted file mode 100644 index 6275d4e4bd..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/data/gen_data.py +++ /dev/null @@ -1,62 +0,0 @@ -from cwrap import BaseCClass -from ert.util import DoubleVector -from ert.enkf import EnkfPrototype - - -class GenData(BaseCClass): - TYPE_NAME = "gen_data" - _alloc = EnkfPrototype("void* gen_data_alloc()", bind = False) - _free = EnkfPrototype("void gen_data_free(gen_data)") - _size = EnkfPrototype("int gen_data_get_size(gen_data)") - _iget = EnkfPrototype("double gen_data_iget_double(gen_data , int)"); - _export = EnkfPrototype("void gen_data_export(gen_data , char*, gen_data_file_format_type, fortio)") - _export_data = EnkfPrototype("void gen_data_export_data(gen_data , double_vector)") - - def __init__(self): - c_ptr = self._alloc() - if c_ptr: - super(GenData, self).__init__(c_ptr) - else: - raise ValueError('Unable to construct GenData object.') - - - def __len__(self): - """ @rtype: int """ - return self._size() - - - def free(self): - self._free( ) - - def __repr__(self): - return 'GenData(len = %d) %s' % (len(self), self._ad_str()) - - def export(self, file_name, file_format_type, fortio): - """ - @type: str - @type: GenDataFileType - @type: FortIO - """ - self._export(file_name, file_format_type, fortio) - - - def getData(self): - data = DoubleVector() - self._export_data( data ) - return data - - def __getitem__( self, idx ): - """Returns an item, or a list if idx is a slice. - Note: When idx is a slice it does not return a new GenData! - """ - ls = len(self) - if isinstance( idx, int ): - if idx < 0: - idx += ls - if 0 <= idx < ls: - return self._iget(idx) - raise IndexError('List index out of range.') - if isinstance( idx, slice ): - vec = self.getData() - return [vec[i] for i in range(*idx.indices(ls))] - raise TypeError('List indices must be integers, not %s.' % str(type(idx))) diff --git a/ThirdParty/Ert/python/python/ert/enkf/data/gen_kw.py b/ThirdParty/Ert/python/python/ert/enkf/data/gen_kw.py deleted file mode 100644 index 84bd4ef413..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/data/gen_kw.py +++ /dev/null @@ -1,152 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'gen_kw.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import os.path - -from cwrap import BaseCClass, CFILE - -from ert.util import DoubleVector -from ert.enkf import EnkfPrototype -from ert.enkf.config import GenKwConfig - - -class GenKw(BaseCClass): - TYPE_NAME = "gen_kw" - _alloc = EnkfPrototype("void* gen_kw_alloc(gen_kw_config)", bind = False) - _free = EnkfPrototype("void gen_kw_free(gen_kw_config)") - _export_parameters = EnkfPrototype("void gen_kw_write_export_file(gen_kw , FILE)") - _export_template = EnkfPrototype("void gen_kw_ecl_write_template(gen_kw , char* )") - _data_iget = EnkfPrototype("double gen_kw_data_iget(gen_kw, int, bool)") - _data_iset = EnkfPrototype("void gen_kw_data_iset(gen_kw, int, double)") - _set_values = EnkfPrototype("void gen_kw_data_set_vector(gen_kw, double_vector)") - _data_get = EnkfPrototype("double gen_kw_data_get(gen_kw, char*, bool)") - _data_set = EnkfPrototype("void gen_kw_data_set(gen_kw, char*, double)") - _size = EnkfPrototype("int gen_kw_data_size(gen_kw)") - _has_key = EnkfPrototype("bool gen_kw_data_has_key(gen_kw, char*)") - _ecl_write = EnkfPrototype("void gen_kw_ecl_write(gen_kw, char* , char* , FILE)") - _iget_key = EnkfPrototype("char* gen_kw_get_name(gen_kw, int)") - - - def __init__(self, gen_kw_config): - """ - @type gen_kw_config: GenKwConfig - """ - c_ptr = self._alloc(gen_kw_config) - - if c_ptr: - super(GenKw, self).__init__(c_ptr) - self.__str__ = self.__repr__ - else: - raise ValueError('Cannot issue a GenKw from the given keyword config: %s.' % str(gen_kw_config)) - - - def exportParameters(self, file_name): - """ @type: str """ - with open(file_name , "w") as py_file: - cfile = CFILE( py_file ) - self._export_parameters(cfile) - - - def exportTemplate(self, file_name): - """ @type: str """ - self._export_template(file_name) - - - def __getitem__(self, key): - """ - @type key: int or str - @rtype: float - """ - do_transform = False - if isinstance(key, str): - if not key in self: - raise KeyError("Key %s does not exist" % (key)) - return self._data_get(key, do_transform) - elif isinstance(key, int): - if not 0 <= key < len(self): - raise IndexError("Index out of range 0 <= %d < %d" % (key, len(self))) - return self._data_iget(key, do_transform) - else: - raise TypeError("Illegal type for indexing, must be int or str, got: %s" % (key)) - - - def __setitem__(self, key, value): - """ - @type key: int or str - @type value: float - """ - if isinstance(key, str): - if not key in self: - raise KeyError("Key %s does not exist" % (key)) - self._data_set(key, value) - elif isinstance(key, int): - if not 0 <= key < len(self): - raise IndexError("Index out of range 0 <= %d < %d" % (key, len(self))) - self._data_iset(key, value) - else: - raise TypeError("Illegal type for indexing, must be int or str, got: %s" % (key)) - - - def items(self): - do_transform = False - v = [] - for index in range(len(self)): - v.append( ( self._iget_key( index ) , - self._data_iget(index, do_transform)) ) - return v - - - def eclWrite(self , path , filename , export_file = None): - if not path is None: - if not os.path.isdir(path): - raise IOError("The directory:%s does not exist" % path) - if export_file: - with open(export_file , "w") as fileH: - self._ecl_write(path , filename , CFILE( fileH )) - else: - self._ecl_write( path , filename , None ) - - - def setValues(self , values): - if len(values) == len(self): - if isinstance(values , DoubleVector): - self._set_values( d ) - else: - d = DoubleVector() - for (index,v) in enumerate(values): - if isinstance(v, (int,long,float)): - d[index] = v - else: - raise TypeError("Values must numeric: %s is invalid" % v) - self._set_values( d ) - else: - raise ValueError("Size mismatch between GenKW and values") - - def __len__(self): - """ @rtype: int """ - return self._size( ) - - - def __contains__(self, item): - return self._has_key(item) - - - def free(self): - self._free() - - def __repr__(self): - return 'GenKw(len = %d) at 0x%x' % (len(self), self._address()) - - diff --git a/ThirdParty/Ert/python/python/ert/enkf/ecl_config.py b/ThirdParty/Ert/python/python/ert/enkf/ecl_config.py deleted file mode 100644 index 6b480cab30..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/ecl_config.py +++ /dev/null @@ -1,181 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'ecl_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from warnings import warn - -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.util import StringList -from ert.ecl import EclSum -from ert.ecl import EclGrid -from ert.util import UIReturn -from ert.sched import SchedFile - -class EclConfig(BaseCClass): - TYPE_NAME = "ecl_config" - - _alloc = EnkfPrototype("void* ecl_config_alloc( )", bind = False) - _free = EnkfPrototype("void ecl_config_free( ecl_config )") - _get_eclbase = EnkfPrototype("char* ecl_config_get_eclbase( ecl_config )") - _validate_eclbase = EnkfPrototype("ui_return_obj ecl_config_validate_eclbase( ecl_config , char*)") - _set_eclbase = EnkfPrototype("void ecl_config_set_eclbase( ecl_config , char*)") - _get_data_file = EnkfPrototype("char* ecl_config_get_data_file(ecl_config)") - _set_data_file = EnkfPrototype("void ecl_config_set_data_file(ecl_config , char*)") - _validate_data_file = EnkfPrototype("ui_return_obj ecl_config_validate_data_file(ecl_config , char*)") - _get_gridfile = EnkfPrototype("char* ecl_config_get_gridfile(ecl_config)") - _set_gridfile = EnkfPrototype("void ecl_config_set_grid(ecl_config, char*)") - _validate_gridfile = EnkfPrototype("ui_return_obj ecl_config_validate_grid(ecl_config, char*)") - _get_grid = EnkfPrototype("ecl_grid_ref ecl_config_get_grid(ecl_config)") - _get_schedule_file = EnkfPrototype("char* ecl_config_get_schedule_file(ecl_config)") - _set_schedule_file = EnkfPrototype("void ecl_config_set_schedule_file(ecl_config, char*, char*)") - _validate_schedule_file = EnkfPrototype("ui_return_obj ecl_config_validate_schedule_file(ecl_config, char*)") - _get_sched_file = EnkfPrototype("sched_file_ref ecl_config_get_sched_file(ecl_config)") - _get_init_section = EnkfPrototype("char* ecl_config_get_init_section(ecl_config)") - _set_init_section = EnkfPrototype("void ecl_config_set_init_section(ecl_config, char*)") - _validate_init_section = EnkfPrototype("ui_return_obj ecl_config_validate_init_section(ecl_config, char*)") - _get_refcase_name = EnkfPrototype("char* ecl_config_get_refcase_name(ecl_config)") - _get_refcase = EnkfPrototype("ecl_sum_ref ecl_config_get_refcase(ecl_config)") - _load_refcase = EnkfPrototype("void ecl_config_load_refcase(ecl_config, char*)") - _validate_refcase = EnkfPrototype("ui_return_obj ecl_config_validate_refcase(ecl_config, char*)") - _has_refcase = EnkfPrototype("bool ecl_config_has_refcase(ecl_config)") - _get_static_kw_list = EnkfPrototype("stringlist_ref ecl_config_get_static_kw_list(ecl_config)") - _clear_static_kw = EnkfPrototype("void ecl_config_clear_static_kw(ecl_config)") - _add_static_kw = EnkfPrototype("void ecl_config_add_static_kw(ecl_config, char*)") - _get_depth_unit = EnkfPrototype("char* ecl_config_get_depth_unit(ecl_config)") - _get_pressure_unit = EnkfPrototype("char* ecl_config_get_pressure_unit(ecl_config)") - - def __init__(self): - c_ptr = self._alloc() - if c_ptr: - super(EclConfig, self).__init__(c_ptr) - else: - raise RuntimeError('Internal error: Failed constructing EclConfig!') - - def free(self): - self._free() - - #----------------------------------------------------------------- - - def getEclBase(self): - """ @rtype: str """ - return self._get_eclbase() - - def validateEclBase(self , eclbase_fmt): - return self._validate_eclbase(eclbase_fmt) - - # Warning: You should probably use the EnkFMain.setEclBase() method to update the Eclipse basename format - def setEclBase(self , eclbase): - self._set_eclbase(eclbase) - - #----------------------------------------------------------------- - - def getDataFile(self): - return self._get_data_file() - - def setDataFile(self , datafile): - self._set_data_file( datafile) - - def validateDataFile( self , datafile ): - """ @rtype: UIReturn """ - return self._validate_data_file( datafile ) - - #----------------------------------------------------------------- - - def get_gridfile(self): - """ @rtype: str """ - return self._get_gridfile() - - def set_gridfile(self, gridfile): - self._set_gridfile(gridfile) - - def validateGridFile(self , gridfile): - return self._validate_gridfile(gridfile) - - def get_grid(self): - warning_message = "The method get_grid() is deprecated. Use getGrid() instead" - warn(warning_message) - return self.getGrid( ) - - def getGrid(self): - return self._get_grid() - - #----------------------------------------------------------------- - - def getScheduleFile(self): - return self._get_schedule_file() - - def setScheduleFile(self, schedule_file, target_file = None): - self._set_schedule_file(schedule_file, target_file) - - def validateScheduleFile(self , schedule_file): - return self._validate_schedule_file(schedule_file) - - def get_sched_file(self): - return self._get_sched_file() - - #----------------------------------------------------------------- - - def getInitSection(self): - return self._get_init_section() - - def setInitSection(self, init_section): - self._set_init_section(init_section) - - def validateInitSection(self, init_section): - return self._validate_init_section(init_section) - - #----------------------------------------------------------------- - - def getRefcaseName(self): - return self._get_refcase_name() - - def loadRefcase(self, refcase): - self._load_refcase(refcase) - - def getRefcase(self): - """ @rtype: EclSum """ - refcase = self._get_refcase() - if not refcase is None: - refcase.setParent(self) - - return refcase - - - def validateRefcase(self, refcase): - return self._validate_refcase(refcase) - - def hasRefcase(self): - """ @rtype: bool """ - return self._has_refcase() - - #----------------------------------------------------------------- - - def get_static_kw_list(self): - """ @rtype: StringList """ - return self._get_static_kw_list().setParent(self) - - def clear_static_kw(self): - self._clear_static_kw() - - def add_static_kw(self, kw): - self._add_static_kw(kw) - - #----------------------------------------------------------------- - - def getDepthUnit(self): - return self._get_depth_unit() - - def getPressureUnit(self): - return self._get_pressure_unit() diff --git a/ThirdParty/Ert/python/python/ert/enkf/enkf_fs.py b/ThirdParty/Ert/python/python/ert/enkf/enkf_fs.py deleted file mode 100644 index b75dcb4dac..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enkf_fs.py +++ /dev/null @@ -1,163 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'enkf_fs.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf import TimeMap, StateMap, SummaryKeySet, CustomKWConfigSet -from ert.enkf.enums import EnKFFSType - - -class EnkfFs(BaseCClass): - TYPE_NAME = "enkf_fs" - - _mount = EnkfPrototype("void* enkf_fs_mount(char* )", bind = False) - _exists = EnkfPrototype("bool enkf_fs_exists(char*)", bind = False) - _disk_version = EnkfPrototype("int enkf_fs_disk_version(char*)", bind = False) - _update_disk_version = EnkfPrototype("bool enkf_fs_update_disk_version(char*, int, int)", bind = False) - _decref = EnkfPrototype("int enkf_fs_decref(enkf_fs)") - _get_refcount = EnkfPrototype("int enkf_fs_get_refcount(enkf_fs)") - _has_node = EnkfPrototype("bool enkf_fs_has_node(enkf_fs, char*, int, int, int, int)") - _has_vector = EnkfPrototype("bool enkf_fs_has_vector(enkf_fs, char*, int, int, int)") - _fread_node = EnkfPrototype("void enkf_fs_fread_node(enkf_fs, buffer, char*, int, int, int, int)") - _fread_vector = EnkfPrototype("void enkf_fs_fread_vector(enkf_fs, buffer, char*, int, int, int)") - _get_case_name = EnkfPrototype("char* enkf_fs_get_case_name(enkf_fs)") - _is_read_only = EnkfPrototype("bool enkf_fs_is_read_only(enkf_fs)") - _get_writecount = EnkfPrototype("int enkf_fs_get_write_count(enkf_fs)") - _fsync = EnkfPrototype("void enkf_fs_fsync(enkf_fs)") - _create = EnkfPrototype("enkf_fs_ref enkf_fs_create_fs(char* , enkf_fs_type_enum , void* , bool)", bind = False) - _get_time_map = EnkfPrototype("time_map_ref enkf_fs_get_time_map(enkf_fs)") - _get_state_map = EnkfPrototype("state_map_ref enkf_fs_get_state_map(enkf_fs)") - _summary_key_set = EnkfPrototype("summary_key_set_ref enkf_fs_get_summary_key_set(enkf_fs)") - _config_kw_config_set = EnkfPrototype("custom_kw_config_set_ref enkf_fs_get_custom_kw_config_set(enkf_fs)") - - def __init__(self, mount_point): - c_ptr = self._mount(mount_point) - super(EnkfFs, self).__init__(c_ptr) - - self.__umounted = False # Keep track of umounting so we only do it once - - - @classmethod - def createCReference(cls, c_pointer, parent=None): - obj = super(EnkfFs, cls).createCReference(c_pointer, parent) - if not obj is None: - obj.__umounted = False - return obj - - - # def has_node(self, node_key, var_type, report_step, iens, state): - # return self._has_node(node_key, var_type, report_step, iens, state) - # - # def has_vector(self, node_key, var_type, iens, state): - # return self._has_vector(node_key, var_type, iens, state) - # - # - # def fread_node(self, key, type, step, member, value): - # buffer = Buffer(100) - # self._fread_node(buffer, key, type, step, member, value) - # - # def fread_vector(self, key, type, member, value): - # buffer = Buffer(100) - # self._fread_vector(buffer, key, type, member, value) - - def getTimeMap(self): - """ @rtype: TimeMap """ - self.__checkIfUmounted() - return self._get_time_map().setParent(self) - - def getStateMap(self): - """ @rtype: StateMap """ - self.__checkIfUmounted() - return self._get_state_map().setParent(self) - - def getCaseName(self): - """ @rtype: str """ - self.__checkIfUmounted() - return self._get_case_name() - - def isReadOnly(self): - """ @rtype: bool """ - self.__checkIfUmounted() - return self._is_read_only() - - def refCount(self): - self.__checkIfUmounted() - return self._get_refcount() - - def writeCount(self): - return self._get_writecount() - - @classmethod - def exists(cls, path): - return cls._exists(path) - - @classmethod - def diskVersion(cls, path): - disk_version = cls._disk_version(path) - if disk_version < 0: - raise IOError("No such filesystem: %s" % path) - return disk_version - - - @classmethod - def updateVersion(cls, path, src_version , target_version): - return cls._update_disk_version(path , src_version ,target_version) - - - @classmethod - def createFileSystem(cls, path, fs_type, arg=None , mount = False): - assert isinstance(path, str) - assert isinstance(fs_type, EnKFFSType) - fs = cls._create(path, fs_type, arg, mount) - return fs - - - def __checkIfUmounted(self): - if self.__umounted: - raise AssertionError("The EnkfFs instance has been umounted!") - - def umount(self): - if not self.__umounted: - self._decref() - self.__umounted = True - - def free(self): - self.umount() - - def __repr__(self): - cn = self.getCaseName() - wc = self.writeCount() - ad = self._ad_str() - return 'EnkfFs(case_name = %s, write_count = %d) %s' % (cn, wc, ad) - - def fsync(self): - self._fsync() - - def getSummaryKeySet(self): - """ @rtype: SummaryKeySet """ - return self._summary_key_set().setParent(self) - - def realizationList(self, state): - """ - Will return list of realizations with state == the specified state. - @type state: ert.enkf.enums.RealizationStateEnum - @rtype: ert.util.IntVector - """ - state_map = self.getStateMap() - return state_map.realizationList(state) - - def getCustomKWConfigSet(self): - """ @rtype: CustomKWConfigSet """ - return self._config_kw_config_set() diff --git a/ThirdParty/Ert/python/python/ert/enkf/enkf_fs_manager.py b/ThirdParty/Ert/python/python/ert/enkf/enkf_fs_manager.py deleted file mode 100644 index 3f609a7dcc..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enkf_fs_manager.py +++ /dev/null @@ -1,304 +0,0 @@ -import os.path -from cwrap import BaseCClass -from ert.enkf import EnkfFs, StateMap, TimeMap, RealizationStateEnum, EnkfInitModeEnum, EnkfPrototype -from ert.util import StringList, BoolVector - -import re - -def naturalSortKey(s, _nsre=re.compile('([0-9]+)')): - return [int(text) if text.isdigit() else text.lower() for text in re.split(_nsre, s)] - -class FileSystemRotator(object): - def __init__(self, capacity): - super(FileSystemRotator, self).__init__() - self._capacity = capacity - """:type: int""" - self._fs_list = [] - """:type: list of str""" - self._fs_map = {} - """:type: dict[str, EnkfFs]""" - - def __len__(self): - return len(self._fs_list) - - def addFileSystem(self, file_system, full_name): - if self.atCapacity(): - self.dropOldestFileSystem() - - self._fs_list.append(full_name) - self._fs_map[full_name] = file_system - - def dropOldestFileSystem(self): - if len(self._fs_list) > 0: - case_name = self._fs_list[0] - fs = self._fs_map[case_name] - fs.umount() - del self._fs_list[0] - del self._fs_map[case_name] - - - def atCapacity(self): - return len(self._fs_list) == self._capacity - - def __contains__(self, full_case_name): - return full_case_name in self._fs_list - - def __getitem__(self, case): - """ @rtype: EnkfFs """ - if isinstance(case, str): - return self._fs_map[case] - elif isinstance(case, int) and 0 <= case < len(self): - case_name = self._fs_list[case] - return self._fs_map[case_name] - else: - raise IndexError("Value '%s' is not a proper index or case name." % case) - - - def umountAll(self): - while len(self._fs_list) > 0: - self.dropOldestFileSystem() - - - -# For normal use from ert all filesystems will be located in the same -# folder in the filesystem - corresponding to the ENSPATH setting in -# the config file; in this implementation that setting is stored in -# the @mount_root field. Currently @mount_root is fixed to the value -# returned by EnKFMain.getMountPoint(), but in principle a different -# path could be sent as the the optional second argument to the -# getFS() method. - -class EnkfFsManager(BaseCClass): - TYPE_NAME = "enkf_fs_manager" - - _get_current_fs = EnkfPrototype("enkf_fs_ref enkf_main_get_fs_ref(enkf_fs_manager)") - _switch_fs = EnkfPrototype("void enkf_main_set_fs(enkf_fs_manager, enkf_fs, char*)") - _fs_exists = EnkfPrototype("bool enkf_main_fs_exists(enkf_fs_manager, char*)") - _alloc_caselist = EnkfPrototype("stringlist_obj enkf_main_alloc_caselist(enkf_fs_manager)") - _set_case_table = EnkfPrototype("void enkf_main_set_case_table(enkf_fs_manager, char*)") - _ensemble_size = EnkfPrototype("int enkf_main_get_ensemble_size(enkf_fs_manager)") - - _is_initialized = EnkfPrototype("bool enkf_main_is_initialized(enkf_fs_manager, bool_vector)") - _is_case_initialized = EnkfPrototype("bool enkf_main_case_is_initialized(enkf_fs_manager, char*, bool_vector)") - _initialize_from_scratch = EnkfPrototype("void enkf_main_initialize_from_scratch(enkf_fs_manager, enkf_fs , stringlist, bool_vector, enkf_init_mode_enum)") - _initialize_case_from_existing = EnkfPrototype("void enkf_main_init_case_from_existing(enkf_fs_manager, enkf_fs, int, enkf_fs)") - _custom_initialize_from_existing = EnkfPrototype("void enkf_main_init_current_case_from_existing_custom(enkf_fs_manager, enkf_fs, int, stringlist, bool_vector)") - _initialize_current_case_from_existing = EnkfPrototype("void enkf_main_init_current_case_from_existing(enkf_fs_manager, enkf_fs, int)") - - _alloc_readonly_state_map = EnkfPrototype("state_map_obj enkf_main_alloc_readonly_state_map(enkf_fs_manager, char*)") - _alloc_readonly_time_map = EnkfPrototype("time_map_obj enkf_main_alloc_readonly_time_map(enkf_fs_manager, char*)") - - DEFAULT_CAPACITY = 5 - - def __init__(self, enkf_main, capacity=DEFAULT_CAPACITY): - """ - @type enkf_main: ert.enkf.EnKFMain - @type capacity: int - """ - super(EnkfFsManager, self).__init__(enkf_main.from_param(enkf_main).value, parent=enkf_main, is_reference=True) - - self._fs_rotator = FileSystemRotator(capacity) - self._mount_root = enkf_main.getMountPoint() - - self._fs_type = enkf_main.getModelConfig().getFSType() - self._fs_arg = None - - self.getCurrentFileSystem() - - def _createFullCaseName(self, mount_root, case_name): - return os.path.join(mount_root, case_name) - - - def getFileSystem(self, case_name, mount_root=None): - """ - @rtype: EnkfFs - """ - if mount_root is None: - mount_root = self._mount_root - - full_case_name = self._createFullCaseName(mount_root, case_name) - - if not full_case_name in self._fs_rotator: - if not EnkfFs.exists(full_case_name): - if self._fs_rotator.atCapacity(): - self._fs_rotator.dropOldestFileSystem() - - EnkfFs.createFileSystem(full_case_name, self._fs_type, self._fs_arg) - - new_fs = EnkfFs(full_case_name) - self._fs_rotator.addFileSystem(new_fs, full_case_name) - - fs = self._fs_rotator[full_case_name] - - return fs - - def isCaseRunning(self, case_name, mount_root=None): - """ Returns true if case is mounted and write_count > 0 - @rtype: bool - """ - if self.isCaseMounted(case_name, mount_root): - case_fs = self.getFileSystem(case_name, mount_root) - return case_fs.writeCount() > 0 - return False - - - def caseExists(self, case_name): - """ @rtype: bool """ - return case_name in self.getCaseList() - - - def caseHasData(self, case_name): - """ @rtype: bool """ - case_has_data = False - state_map = self.getStateMapForCase(case_name) - - for state in state_map: - if state == RealizationStateEnum.STATE_HAS_DATA: - case_has_data = True - - return case_has_data - - - def getCurrentFileSystem(self): - """ Returns the currently selected file system - @rtype: EnkfFs - """ - current_fs = self._get_current_fs() - case_name = current_fs.getCaseName() - full_name = self._createFullCaseName(self._mount_root, case_name) - - if not full_name in self._fs_rotator: - self._fs_rotator.addFileSystem(current_fs, full_name) - else: - current_fs.umount() - - return self.getFileSystem(case_name, self._mount_root) - - - def umount(self): - self._fs_rotator.umountAll() - - - def getFileSystemCount(self): - return len(self._fs_rotator) - - - def getEnsembleSize(self): - """ @rtype: int """ - return self._ensemble_size( ) - - - def switchFileSystem(self, file_system): - """ - @type file_system: EnkfFs - """ - self._switch_fs(file_system, None) - - - def isCaseInitialized(self, case): - return self._is_case_initialized(case, None) - - def isInitialized(self): - """ @rtype: bool """ - return self._is_initialized(None) # what is the bool_vector mask??? - - - def getCaseList(self): - """ @rtype: list[str] """ - caselist = [case for case in self._alloc_caselist()] - return sorted(caselist, key=naturalSortKey) - - - def customInitializeCurrentFromExistingCase(self, source_case, source_report_step, member_mask, node_list): - """ - @type source_case: str - @type source_report_step: int - @type member_mask: ert.util.BoolVector - @type node_list: ert.util.StringList - """ - source_case_fs = self.getFileSystem(source_case) - self._custom_initialize_from_existing(source_case_fs, source_report_step, node_list, member_mask) - - def initializeCurrentCaseFromExisting(self, source_fs, source_report_step): - """ - @type source_fs: EnkfFs - @type source_report_step: int - """ - self._initialize_current_case_from_existing(source_fs, source_report_step) - - def initializeCaseFromExisting(self, source_fs, source_report_step, target_fs): - """ - @type source_fs: EnkfFs - @type source_report_step: int - @type target_fs: EnkfFs - """ - self._initialize_case_from_existing(source_fs, source_report_step, target_fs) - - def initializeCaseFromScratch(self, case, parameter_list, from_iens, to_iens, force_init=True): - """ - @type case: EnkfFs - @type parameter_list: ert.util.StringList - @type to_iens: int - @type from_iens: int - @type force_init: bool - """ - mask = BoolVector( initial_size = self.getEnsembleSize( ) , default_value = False ) - for iens in range(from_iens,to_iens+1): - mask[iens] = True - - if force_init: - init_mode = EnkfInitModeEnum.INIT_FORCE - else: - init_mode = EnkfInitModeEnum.INIT_CONDITIONAL - - self._initialize_from_scratch(case, parameter_list, mask , init_mode) - - - - def initializeFromScratch(self, parameter_list, from_iens, to_iens, force_init=True): - """ - @type parameter_list: ert.util.StringList - @type to_iens: int - @type from_iens: int - @type force_init: bool - """ - case = self.getCurrentFileSystem() - self.initializeCaseFromScratch(case, parameter_list, from_iens, to_iens, force_init) - - def isCaseMounted(self, case_name, mount_root=None): - """ - @type case_name: str - @type mount_root: str - @rtype: bool - """ - if mount_root is None: - mount_root = self._mount_root - - full_case_name = self._createFullCaseName(mount_root, case_name) - - return full_case_name in self._fs_rotator - - def getStateMapForCase(self, case): - """ - @type case: str - @rtype: StateMap - """ - if self.isCaseMounted(case): - fs = self.getFileSystem(case) - return fs.getStateMap() - else: - return self._alloc_readonly_state_map(case) - - def getTimeMapForCase(self, case): - """ - @type case: str - @rtype: TimeMap - """ - return self._alloc_readonly_time_map(case) - - def isCaseHidden(self, case_name): - """ - @rtype: bool - """ - return case_name.startswith(".") - diff --git a/ThirdParty/Ert/python/python/ert/enkf/enkf_linalg.py b/ThirdParty/Ert/python/python/ert/enkf/enkf_linalg.py deleted file mode 100644 index 5f04554d1e..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enkf_linalg.py +++ /dev/null @@ -1,20 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.util import Matrix , DoubleVector - -class EnkfLinalg(BaseCClass): - TYPE_NAME = "EnkfLinalg" - - _get_PC = EnkfPrototype("void enkf_linalg_get_PC(matrix, matrix, double, int, matrix, matrix, double_vector)", bind = False) - - @classmethod - def calculatePrincipalComponents(cls, S0, D_obs, truncation, ncomp, PC, PC_obs, singular_values): - assert isinstance(S0, Matrix) - assert isinstance(D_obs, Matrix) - assert isinstance(truncation, (float, int)) - assert isinstance(ncomp, int) - assert isinstance(PC, Matrix) - assert isinstance(PC_obs, Matrix) - assert isinstance(singular_values , DoubleVector) - - cls._get_PC(S0, D_obs, truncation, ncomp, PC, PC_obs , singular_values) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enkf_main.py b/ThirdParty/Ert/python/python/ert/enkf/enkf_main.py deleted file mode 100644 index 70b9fa3169..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enkf_main.py +++ /dev/null @@ -1,316 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'ecl_kw.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import ctypes -from cwrap import BaseCClass - -from ert.enkf import EnkfPrototype, AnalysisConfig, EclConfig, EnkfObs, EnKFState, LocalConfig, ModelConfig, EnsembleConfig, PlotSettings, SiteConfig, ENKF_LIB, EnkfSimulationRunner, EnkfFsManager, ErtWorkflowList, HookManager, HookWorkflow, ESUpdate -from ert.enkf.enums import EnkfInitModeEnum -from ert.enkf.key_manager import KeyManager -from ert.util import SubstitutionList, Log - - - -class EnKFMain(BaseCClass): - TYPE_NAME = "enkf_main" - _alloc = EnkfPrototype("void* enkf_main_bootstrap(char*, bool, bool)", bind = False) - _create_new_config = EnkfPrototype("void enkf_main_create_new_config(char* , char*, char* , int)", bind = False) - - _free = EnkfPrototype("void enkf_main_free(enkf_main)") - _get_ensemble_size = EnkfPrototype("int enkf_main_get_ensemble_size( enkf_main )") - _get_ens_config = EnkfPrototype("ens_config_ref enkf_main_get_ensemble_config( enkf_main )") - _get_model_config = EnkfPrototype("model_config_ref enkf_main_get_model_config( enkf_main )") - _get_local_config = EnkfPrototype("local_config_ref enkf_main_get_local_config( enkf_main )") - _get_analysis_config = EnkfPrototype("analysis_config_ref enkf_main_get_analysis_config( enkf_main)") - _get_site_config = EnkfPrototype("site_config_ref enkf_main_get_site_config( enkf_main)") - _get_ecl_config = EnkfPrototype("ecl_config_ref enkf_main_get_ecl_config( enkf_main)") - _get_plot_config = EnkfPrototype("plot_settings_ref enkf_main_get_plot_config( enkf_main)") - _set_eclbase = EnkfPrototype("ui_return_obj enkf_main_set_eclbase( enkf_main, char*)") - _set_datafile = EnkfPrototype("void enkf_main_set_data_file( enkf_main, char*)") - _get_schedule_prediction_file = EnkfPrototype("char* enkf_main_get_schedule_prediction_file( enkf_main )") - _set_schedule_prediction_file = EnkfPrototype("void enkf_main_set_schedule_prediction_file( enkf_main , char*)") - _get_data_kw = EnkfPrototype("subst_list_ref enkf_main_get_data_kw(enkf_main)") - _clear_data_kw = EnkfPrototype("void enkf_main_clear_data_kw(enkf_main)") - _add_data_kw = EnkfPrototype("void enkf_main_add_data_kw(enkf_main, char*, char*)") - _resize_ensemble = EnkfPrototype("void enkf_main_resize_ensemble(enkf_main, int)") - _del_node = EnkfPrototype("void enkf_main_del_node(enkf_main, char*)") - _get_obs = EnkfPrototype("enkf_obs_ref enkf_main_get_obs(enkf_main)") - _load_obs = EnkfPrototype("void enkf_main_load_obs(enkf_main, char* , bool)") - _get_pre_clear_runpath = EnkfPrototype("bool enkf_main_get_pre_clear_runpath(enkf_main)") - _set_pre_clear_runpath = EnkfPrototype("void enkf_main_set_pre_clear_runpath(enkf_main, bool)") - _iget_keep_runpath = EnkfPrototype("int enkf_main_iget_keep_runpath(enkf_main, int)") - _iset_keep_runpath = EnkfPrototype("void enkf_main_iset_keep_runpath(enkf_main, int, int_vector)") - _get_templates = EnkfPrototype("ert_templates_ref enkf_main_get_templates(enkf_main)") - _get_site_config_file = EnkfPrototype("char* enkf_main_get_site_config_file(enkf_main)") - _get_history_length = EnkfPrototype("int enkf_main_get_history_length(enkf_main)") - _get_observations = EnkfPrototype("void enkf_main_get_observations(enkf_main, char*, int, long*, double*, double*)") - _get_observation_count = EnkfPrototype("int enkf_main_get_observation_count(enkf_main, char*)") - _iget_state = EnkfPrototype("enkf_state_ref enkf_main_iget_state(enkf_main, int)") - _get_workflow_list = EnkfPrototype("ert_workflow_list_ref enkf_main_get_workflow_list(enkf_main)") - _get_hook_manager = EnkfPrototype("hook_manager_ref enkf_main_get_hook_manager(enkf_main)") - _get_user_config_file = EnkfPrototype("char* enkf_main_get_user_config_file(enkf_main)") - _get_mount_point = EnkfPrototype("char* enkf_main_get_mount_root( enkf_main )") - _export_field = EnkfPrototype("bool enkf_main_export_field(enkf_main, char*, char*, bool_vector, enkf_field_file_format_enum, int)") - _export_field_with_fs = EnkfPrototype("bool enkf_main_export_field_with_fs(enkf_main, char*, char*, bool_vector, enkf_field_file_format_enum, int, enkf_fs_manager)") - _load_from_forward_model = EnkfPrototype("int enkf_main_load_from_forward_model_from_gui(enkf_main, int, bool_vector, enkf_fs)") - _create_run_path = EnkfPrototype("void enkf_main_icreate_run_path(enkf_main , run_arg)") - _submit_simulation = EnkfPrototype("void enkf_main_isubmit_job(enkf_main , run_arg)") - _alloc_run_context_ENSEMBLE_EXPERIMENT= EnkfPrototype("ert_run_context_obj enkf_main_alloc_ert_run_context_ENSEMBLE_EXPERIMENT( enkf_main , enkf_fs , bool_vector , enkf_init_mode_enum , int)") - _get_runpath_list = EnkfPrototype("runpath_list_ref enkf_main_get_runpath_list(enkf_main)") - _add_node = EnkfPrototype("void enkf_main_add_node(enkf_main, enkf_config_node)") - - - - def __init__(self, model_config, strict = True, verbose = True): - c_ptr = self._alloc(model_config, strict, verbose) - super(EnKFMain, self).__init__(c_ptr) - - # The model_config argument can be None; the only reason to - # allow that possibility is to be able to test that the - # site-config loads correctly. - if model_config is None: - self.__simulation_runner = None - self.__fs_manager = None - self.__es_update = None - else: - self.__simulation_runner = EnkfSimulationRunner(self) - self.__fs_manager = EnkfFsManager(self) - self.__es_update = ESUpdate(self) - - - self.__key_manager = KeyManager(self) - - @staticmethod - def loadSiteConfig(): - """ - This method will load the site config file; the sole purpose - of this method is testing. - """ - EnKFMain( None ) - - - @classmethod - def createCReference(cls, c_pointer, parent=None): - obj = super(EnKFMain, cls).createCReference(c_pointer, parent) - obj.__simulation_runner = EnkfSimulationRunner(obj) - obj.__fs_manager = EnkfFsManager(obj) - return obj - - - @staticmethod - def createNewConfig(config_file, storage_path, dbase_type, num_realizations): - return EnKFMain._create_new_config(config_file, storage_path, dbase_type, num_realizations) - - def getRealisation(self , iens): - """ @rtype: EnKFState """ - if 0 <= iens < self.getEnsembleSize(): - return self._iget_state(iens).setParent(self) - else: - raise IndexError("iens value:%d invalid Valid range: [0,%d)" % (iens , self.getEnsembleSize())) - - - def set_eclbase(self, eclbase): - self._set_eclbase(eclbase) - - def umount(self): - if not self.__fs_manager is None: - self.__fs_manager.umount() - - def free(self): - self.umount() - self._free( ) - - def __repr__(self): - ens = self.getEnsembleSize() - cfg = self.getUserConfigFile() - cnt = 'ensemble_size = %d, config_file = %s' % (ens,cfg) - return self._create_repr(cnt) - - def getEnsembleSize(self): - """ @rtype: int """ - return self._get_ensemble_size( ) - - def resizeEnsemble(self, value): - self._resize_ensemble(value) - - def ensembleConfig(self): - """ @rtype: EnsembleConfig """ - return self._get_ens_config( ).setParent(self) - - def analysisConfig(self): - """ @rtype: AnalysisConfig """ - return self._get_analysis_config( ).setParent(self) - - def getModelConfig(self): - """ @rtype: ModelConfig """ - return self._get_model_config( ).setParent(self) - - def logh(self): - """ @rtype: Log """ - return self._get_logh( ).setParent(self) - - def getLocalConfig(self): - """ @rtype: LocalConfig """ - config = self._get_local_config( ).setParent(self) - config.initAttributes( self.ensembleConfig() , self.getObservations() , self.eclConfig().getGrid() ) - return config - - - def siteConfig(self): - """ @rtype: SiteConfig """ - return self._get_site_config( ).setParent(self) - - def eclConfig(self): - """ @rtype: EclConfig """ - return self._get_ecl_config( ).setParent(self) - - def plotConfig(self): - """ @rtype: PlotConfig """ - return self._get_plot_config( ).setParent(self) - - def set_datafile(self, datafile): - self._set_datafile(datafile) - - - def get_schedule_prediction_file(self): - schedule_prediction_file = self._get_schedule_prediction_file( ) - return schedule_prediction_file - - def set_schedule_prediction_file(self, file): - self._set_schedule_prediction_file(file) - - def getDataKW(self): - """ @rtype: SubstitutionList """ - return self._get_data_kw( ) - - def clearDataKW(self): - self._clear_data_kw( ) - - def addDataKW(self, key, value): - self._add_data_kw(key, value) - - - def getMountPoint(self): - return self._get_mount_point( ) - - - def del_node(self, key): - self._del_node(key) - - def getObservations(self): - """ @rtype: EnkfObs """ - return self._get_obs( ).setParent(self) - - def loadObservations(self , obs_config_file , clear = True): - self._load_obs(obs_config_file , clear) - - - def get_pre_clear_runpath(self): - pre_clear = self._get_pre_clear_runpath( ) - return pre_clear - - def set_pre_clear_runpath(self, value): - self._set_pre_clear_runpath(value) - - def iget_keep_runpath(self, iens): - ikeep = self._iget_keep_runpath(iens) - return ikeep - - def iset_keep_runpath(self, iens, keep_runpath): - self._iset_keep_runpath(iens, keep_runpath) - - def get_templates(self): - return self._get_templates( ).setParent(self) - - def get_site_config_file(self): - return self._get_site_config_file( ) - - def getUserConfigFile(self): - """ @rtype: str """ - config_file = self._get_user_config_file( ) - return config_file - - - def getHistoryLength(self): - return self._get_history_length( ) - - def getMemberRunningState(self, ensemble_member): - """ @rtype: EnKFState """ - return self._iget_state(ensemble_member).setParent(self) - - def get_observations(self, user_key, obs_count, obs_x, obs_y, obs_std): - return self._get_observations(user_key, obs_count, obs_x, obs_y, obs_std) - - def get_observation_count(self, user_key): - return self._get_observation_count(user_key) - - - def getESUpdate(self): - """ @rtype: ESUpdate """ - return self.__es_update - - def getEnkfSimulationRunner(self): - """ @rtype: EnkfSimulationRunner """ - return self.__simulation_runner - - def getEnkfFsManager(self): - """ @rtype: EnkfFsManager """ - return self.__fs_manager - - def getKeyManager(self): - """ :rtype: KeyManager """ - return self.__key_manager - - def getWorkflowList(self): - """ @rtype: ErtWorkflowList """ - return self._get_workflow_list( ).setParent(self) - - def getHookManager(self): - """ @rtype: HookManager """ - return self._get_hook_manager( ) - - def exportField(self, keyword, path, iactive, file_type, report_step, state, enkfFs): - """ - @type keyword: str - @type path: str - @type iactive: BoolVector - @type file_type: EnkfFieldFileFormatEnum - @type report_step: int - @type enkfFs: EnkfFs - - """ - assert isinstance(keyword, str) - return self._export_field_with_fs(keyword, path, iactive, file_type, report_step, state, enkfFs) - - def loadFromForwardModel(self, realization, iteration, fs): - """Returns the number of loaded realizations""" - return self._load_from_forward_model(iteration, realization, fs) - - def createRunPath(self , run_arg): - self._create_run_path( run_arg) - - def submitSimulation(self , run_arg): - self._submit_simulation( run_arg) - - - def getRunContextENSEMPLE_EXPERIMENT(self , fs , iactive , init_mode = EnkfInitModeEnum.INIT_CONDITIONAL , iteration = 0): - return self._alloc_run_context_ENSEMBLE_EXPERIMENT( fs , iactive , init_mode , iteration ) - - - def getRunpathList(self): - return self._get_runpath_list( ) - - def addNode(self, enkf_config_node): - self._add_node(enkf_config_node) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enkf_obs.py b/ThirdParty/Ert/python/python/ert/enkf/enkf_obs.py deleted file mode 100644 index 2049dcbc92..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enkf_obs.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'enkf_obs.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import os.path - -from cwrap import BaseCClass -from ert.util import StringList, IntVector -from ert.sched import History -from ert.ecl import EclSum , EclGrid -from ert.enkf import EnkfPrototype -from ert.enkf import EnkfFs, LocalObsdataNode , LocalObsdata, MeasData, ObsData -from ert.enkf.enums import EnkfObservationImplementationType - -from ert.enkf.observations import ObsVector - - -class EnkfObs(BaseCClass): - TYPE_NAME = "enkf_obs" - - _alloc = EnkfPrototype("void* enkf_obs_alloc( history , time_map , ecl_grid , ecl_sum , ens_config )", bind = False) - _free = EnkfPrototype("void enkf_obs_free( enkf_obs )") - _get_size = EnkfPrototype("int enkf_obs_get_size( enkf_obs )") - _load = EnkfPrototype("bool enkf_obs_load( enkf_obs , char*)") - _clear = EnkfPrototype("void enkf_obs_clear( enkf_obs )") - _alloc_typed_keylist = EnkfPrototype("stringlist_obj enkf_obs_alloc_typed_keylist(enkf_obs, enkf_obs_impl_type)") - _alloc_matching_keylist = EnkfPrototype("stringlist_obj enkf_obs_alloc_matching_keylist(enkf_obs, char*)") - _has_key = EnkfPrototype("bool enkf_obs_has_key(enkf_obs, char*)") - _obs_type = EnkfPrototype("enkf_obs_impl_type enkf_obs_get_type(enkf_obs, char*)") - _get_vector = EnkfPrototype("obs_vector_ref enkf_obs_get_vector(enkf_obs, char*)") - _iget_vector = EnkfPrototype("obs_vector_ref enkf_obs_iget_vector(enkf_obs, int)") - _iget_obs_time = EnkfPrototype("time_t enkf_obs_iget_obs_time(enkf_obs, int)") - _add_obs_vector = EnkfPrototype("void enkf_obs_add_obs_vector(enkf_obs, obs_vector)") - _get_obs_and_measure_data = EnkfPrototype("void enkf_obs_get_obs_and_measure_data(enkf_obs, enkf_fs, local_obsdata, int_vector, meas_data, obs_data)") - _create_all_active_obs = EnkfPrototype("local_obsdata_obj enkf_obs_alloc_all_active_local_obs( enkf_obs , char*)"); - _scale_correlated_std = EnkfPrototype("double enkf_obs_scale_correlated_std( enkf_obs , enkf_fs , int_vector , local_obsdata)"); - _local_scale_std = EnkfPrototype("void enkf_obs_local_scale_std( enkf_obs , local_obsdata , double)"); - - def __init__(self , ensemble_config , history = None , external_time_map = None , grid = None , refcase = None ): - c_ptr = self._alloc( history , external_time_map , grid , refcase , ensemble_config ) - super(EnkfObs, self).__init__(c_ptr) - - def __len__(self): - return self._get_size() - - def __contains__(self , key): - return self._has_key(key) - - def __iter__(self): - """ @rtype: ObsVector """ - iobs = 0 - while iobs < len(self): - vector = self[iobs] - yield vector - iobs += 1 - - - def __getitem__(self, key_or_index): - """ @rtype: ObsVector """ - if isinstance(key_or_index, str): - if self.hasKey(key_or_index): - return self._get_vector(key_or_index).setParent(self) - else: - raise KeyError("Unknown key: %s" % key_or_index) - elif isinstance(key_or_index, int): - idx = key_or_index - if idx < 0: - idx += len(self) - if 0 <= idx < len(self): - return self._iget_vector(idx).setParent(self) - else: - raise IndexError("Invalid index: %d. Valid range is [0, %d)." % (key_or_index, len(self))) - else: - raise TypeError("Key or index must be of type str or int, not %s." % str(type(key_or_index))) - - - def createLocalObsdata(self , key , add_active_steps = True): - # Use getAllActiveLocalObsdata() - raise NotImplementedError("Hmmm C function: enkf_obs_alloc_all_active_local_obs() removed") - - - - def getAllActiveLocalObsdata(self , key = "ALL-OBS"): - return self._create_all_active_obs( key ) - - - - def getTypedKeylist(self, observation_implementation_type): - """ - @type observation_implementation_type: EnkfObservationImplementationType - @rtype: StringList - """ - return self._alloc_typed_keylist(observation_implementation_type) - - def obsType(self , key): - if key in self: - return self._obs_type(key) - else: - raise KeyError("Unknown observation key:%s" % key) - - - def getMatchingKeys(self , pattern , obs_type = None): - """ - Will return a list of all the observation keys matching the input - pattern. The matching is based on fnmatch(). - """ - key_list = self._alloc_matching_keylist(pattern) - if obs_type: - new_key_list = [] - for key in key_list: - if self.obsType( key ) == obs_type: - new_key_list.append( key ) - return new_key_list - else: - return key_list - - - def hasKey(self, key): - """ @rtype: bool """ - return key in self - - - def getObservationTime(self, index): - """ @rtype: CTime """ - return self._iget_obs_time(index) - - - def addObservationVector(self, observation_vector): - assert isinstance(observation_vector, ObsVector) - - observation_vector.convertToCReference(self) - - self._add_obs_vector(observation_vector) - - def getObservationAndMeasureData(self, fs, local_obsdata, active_list, meas_data, obs_data): - assert isinstance(fs, EnkfFs) - assert isinstance(local_obsdata, LocalObsdata) - assert isinstance(active_list, IntVector) - assert isinstance(meas_data, MeasData) - assert isinstance(obs_data, ObsData) - - self._get_obs_and_measure_data(fs, local_obsdata, active_list, meas_data, obs_data) - - - def scaleCorrelatedStd( self , fs , local_obsdata , active_list): - return self._scale_correlated_std( fs , active_list , local_obsdata ) - - def localScaleStd( self , local_obsdata , scale_factor): - return self._local_scale_std(local_obsdata, scale_factor) - - def load(self , config_file): - if not os.path.isfile( config_file ): - raise IOError('The observation config file "%s" does not exist.' % config_file) - return self._load( config_file ) - - def clear(self): - self._clear() - - def free(self): - self._free() - - def __repr__(self): - return 'EnkfObs(len = %d) at 0x%x' % (len(self), self._address()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enkf_simulation_runner.py b/ThirdParty/Ert/python/python/ert/enkf/enkf_simulation_runner.py deleted file mode 100644 index 40cfc61cc8..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enkf_simulation_runner.py +++ /dev/null @@ -1,44 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfFs -from ert.enkf import EnkfPrototype -from ert.enkf.enums import EnkfInitModeEnum -from ert.util import BoolVector - - -class EnkfSimulationRunner(BaseCClass): - TYPE_NAME = "enkf_simulation_runner" - - _create_run_path = EnkfPrototype("bool enkf_main_create_run_path(enkf_simulation_runner, bool_vector, int)") - _run_simple_step = EnkfPrototype("int enkf_main_run_simple_step(enkf_simulation_runner, bool_vector, enkf_init_mode_enum, int)") - - def __init__(self, enkf_main): - assert isinstance(enkf_main, BaseCClass) - super(EnkfSimulationRunner, self).__init__(enkf_main.from_param(enkf_main).value, parent=enkf_main, is_reference=True) - self.ert = enkf_main - """:type: ert.enkf.EnKFMain """ - - def runSimpleStep(self, active_realization_mask, initialization_mode, iter_nr): - """ @rtype: int """ - assert isinstance(active_realization_mask, BoolVector) - assert isinstance(initialization_mode, EnkfInitModeEnum) - return self._run_simple_step(active_realization_mask, initialization_mode , iter_nr) - - def createRunPath(self, active_realization_mask, iter_nr): - """ @rtype: bool """ - assert isinstance(active_realization_mask, BoolVector) - return self._create_run_path(active_realization_mask, iter_nr) - - def runEnsembleExperiment(self, active_realization_mask=None): - """ @rtype: int """ - if active_realization_mask is None: - count = self.ert.getEnsembleSize() - active_realization_mask = BoolVector(default_value=True, initial_size=count) - - iter_nr = 0 - return self.runSimpleStep(active_realization_mask, EnkfInitModeEnum.INIT_CONDITIONAL, iter_nr) - - - def runWorkflows(self , runtime): - """:type ert.enkf.enum.HookRuntimeEnum""" - hook_manager = self.ert.getHookManager() - hook_manager.runWorkflows( runtime , self.ert ) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enkf_state.py b/ThirdParty/Ert/python/python/ert/enkf/enkf_state.py deleted file mode 100644 index e5b85d141a..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enkf_state.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'enkf_state.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.enums import EnkfInitModeEnum, EnkfVarType -from ert.job_queue import JobStatusType - - -class EnKFState(BaseCClass): - TYPE_NAME = "enkf_state" - _free = EnkfPrototype("void* enkf_state_free( enkf_state )") - _has_key = EnkfPrototype("bool enkf_state_has_node( enkf_state , char* )") - _get_node = EnkfPrototype("enkf_node_ref enkf_state_has_node( enkf_state , char* )") - _add_subst_kw = EnkfPrototype("void enkf_state_add_subst_kw( enkf_state , char* , char* , char*)") - _get_subst_list = EnkfPrototype("subst_list_ref enkf_state_get_subst_list( enkf_state )") - _get_ens_config = EnkfPrototype("ens_config_ref enkf_state_get_ensemble_config( enkf_state )") - _initialize = EnkfPrototype("void enkf_state_initialize( enkf_state , enkf_fs , stringlist , enkf_init_mode_enum)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - - def __getitem__(self , kw): - """ @rtype: ert.enkf.data.enkf_node.EnkfNode """ - if isinstance(kw , str): - if kw in self: - node = self._get_node( kw ) - node.setParent( self ) - return node - else: - raise KeyError("The state object does not have node:%s" % kw) - else: - raise TypeError("The kw type must be string. Input:%s" % kw) - - - def __contains__(self , kw): - return self._has_key( kw ) - - - def hasKey(self , kw): - """ @rtype: bool """ - return kw in self - - - def getNode(self , kw): - """ @rtype: ert.enkf.data.enkf_node.EnkfNode """ - return self[kw] - - - def free(self): - self._free( ) - - - def addSubstKeyword(self , key , value): - """ - Will add a key -> value pair which can be used for search replace - operations in the data file. Observe that the key will be - surrounded by \'<\' and \'>\'. - """ - doc_string = None - if isinstance(value , str): - self._add_subst_kw( key , value , doc_string ) - else: - raise TypeError("The value argument must be a string") - - def getDataKW(self): - """ - Will return the substitution map for this realisation. - """ - return self._get_subst_list( ) - - - def ensembleConfig(self): - """ @rtype: EnsembleConfig """ - return self._get_ens_config( ) - def initialize( self , fs , param_list = None , init_mode = EnkfInitModeEnum.INIT_CONDITIONAL): - if param_list is None: - ens_config = self.ensembleConfig( ) - param_list = ens_config.getKeylistFromVarType( EnkfVarType.PARAMETER ) - self._initialize( fs , param_list , init_mode ) diff --git a/ThirdParty/Ert/python/python/ert/enkf/ensemble_config.py b/ThirdParty/Ert/python/python/ert/enkf/ensemble_config.py deleted file mode 100644 index 29e8ab3c1d..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/ensemble_config.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'ensemble_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.util import StringList -from ert.enkf import EnkfPrototype, SummaryKeyMatcher -from ert.enkf.config import EnkfConfigNode, CustomKWConfig -from ert.enkf.enums import EnkfVarType, ErtImplType - - - -class EnsembleConfig(BaseCClass): - TYPE_NAME = "ens_config" - _alloc = EnkfPrototype("void* ensemble_config_alloc()" , bind = False) - _free = EnkfPrototype("void ensemble_config_free( ens_config )") - _has_key = EnkfPrototype("bool ensemble_config_has_key( ens_config , char* )") - _size = EnkfPrototype("int ensemble_config_get_size( ens_config)") - _get_node = EnkfPrototype("enkf_config_node_ref ensemble_config_get_node( ens_config , char*)") - _alloc_keylist = EnkfPrototype("stringlist_obj ensemble_config_alloc_keylist( ens_config )") - _add_summary = EnkfPrototype("enkf_config_node_ref ensemble_config_add_summary( ens_config, char*, int)") - _add_gen_kw = EnkfPrototype("enkf_config_node_ref ensemble_config_add_gen_kw( ens_config, char*)") - _add_field = EnkfPrototype("enkf_config_node_ref ensemble_config_add_field( ens_config, char*, ecl_grid)") - _alloc_keylist_from_var_type = EnkfPrototype("stringlist_obj ensemble_config_alloc_keylist_from_var_type(ens_config, enkf_var_type_enum)") - _alloc_keylist_from_impl_type = EnkfPrototype("stringlist_obj ensemble_config_alloc_keylist_from_impl_type(ens_config, ert_impl_type_enum)") - _add_node = EnkfPrototype("void ensemble_config_add_node( ens_config , enkf_config_node )") - _summary_key_matcher = EnkfPrototype("summary_key_matcher_ref ensemble_config_get_summary_key_matcher(ens_config)") - _add_defined_custom_kw = EnkfPrototype("enkf_config_node_ref ensemble_config_add_defined_custom_kw(ens_config, char*, integer_hash)") - - - - def __init__(self): - c_ptr = self._alloc( ) - super(EnsembleConfig , self).__init__(c_ptr) - - - def __len__(self): - return self._size( ) - - - def __getitem__(self , key): - """ @rtype: EnkfConfigNode """ - if key in self: - return self._get_node(key).setParent(self) - else: - raise KeyError("The key:%s is not in the ensemble configuration" % key) - - - def getNode(self, key): - return self[key] - - - def alloc_keylist(self): - """ @rtype: StringList """ - return self._alloc_keylist( ) - - def add_summary(self, key): - """ @rtype: EnkfConfigNode """ - return self._add_summary(key, 2).setParent(self) - - def add_gen_kw(self, key): - """ @rtype: EnkfConfigNode """ - return self._add_gen_kw(key).setParent(self) - - - def addNode(self , config_node): - assert isinstance(config_node , EnkfConfigNode) - self._add_node( config_node ) - config_node.setParent( self ) - - - def add_field(self, key, eclipse_grid): - """ @rtype: EnkfConfigNode """ - return self._add_field(key, eclipse_grid).setParent(self) - - def getKeylistFromVarType(self, var_mask): - """ @rtype: StringList """ - assert isinstance(var_mask, EnkfVarType) - return self._alloc_keylist_from_var_type(var_mask) - - def getKeylistFromImplType(self, ert_impl_type): - """ @rtype: StringList """ - assert isinstance(ert_impl_type, ErtImplType) - return self._alloc_keylist_from_impl_type(ert_impl_type) - - def __contains__(self, key): - return self._has_key( key) - - def getSummaryKeyMatcher(self): - """ @rtype: SummaryKeyMatcher """ - return self._summary_key_matcher( ) - - def free(self): - self._free( ) - - def addDefinedCustomKW(self, group_name, definition): - """ @rtype: EnkfConfigNode """ - if not group_name in self: - type_hash = CustomKWConfig.convertDefinition(definition) - self._add_defined_custom_kw(group_name, type_hash) - - return self[group_name] - diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/enkf/enums/CMakeLists.txt deleted file mode 100644 index 27be30d855..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - enkf_field_file_format_enum.py - enkf_fs_type_enum.py - enkf_init_modes_enum.py - enkf_obs_impl_type_enum.py - enkf_run_enum.py - enkf_truncation_type.py - enkf_var_type_enum.py - ert_impl_type_enum.py - load_fail_type_enum.py - realization_state_enum.py - gen_data_file_type_enum.py - active_mode_enum.py - hook_runtime_enum.py -) - -add_python_package("python.ert.enkf.enums" ${PYTHON_INSTALL_PREFIX}/ert/enkf/enums "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/__init__.py b/ThirdParty/Ert/python/python/ert/enkf/enums/__init__.py deleted file mode 100644 index d3b4382658..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -from .enkf_field_file_format_enum import EnkfFieldFileFormatEnum -from .load_fail_type_enum import LoadFailTypeEnum -from .enkf_var_type_enum import EnkfVarType -from .enkf_run_enum import EnkfRunType -from .enkf_obs_impl_type_enum import EnkfObservationImplementationType -from .ert_impl_type_enum import ErtImplType -from .enkf_init_modes_enum import EnkfInitModeEnum -from .realization_state_enum import RealizationStateEnum -from .enkf_truncation_type import EnkfTruncationType -from .enkf_fs_type_enum import EnKFFSType -from .gen_data_file_type_enum import GenDataFileType -from .active_mode_enum import ActiveMode -from .hook_runtime_enum import HookRuntime - -__all__ = ["EnkfFieldFileFormatEnum", - "LoadFailTypeEnum", - "EnkfVarType", - "EnkfRunType", - "EnkfObservationImplementationType", - "ErtImplType", - "EnkfInitModeEnum", - "RealizationStateEnum", - "EnkfTruncationType", - "EnKFFSType", - "GenDataFileType", - "ActiveMode", - "HookRuntime"] diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/active_mode_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/active_mode_enum.py deleted file mode 100644 index ec426fce66..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/active_mode_enum.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'content_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - -class ActiveMode(BaseCEnum): - TYPE_NAME = "active_mode_enum" - ALL_ACTIVE = None - INACTIVE = None - PARTLY_ACTIVE = None - - -ActiveMode.addEnum("ALL_ACTIVE", 1) -ActiveMode.addEnum("INACTIVE", 2) -ActiveMode.addEnum("PARTLY_ACTIVE", 3) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_field_file_format_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_field_file_format_enum.py deleted file mode 100644 index 5a05a11002..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_field_file_format_enum.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'enkf_field_file_format_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - -class EnkfFieldFileFormatEnum(BaseCEnum): - TYPE_NAME = "enkf_field_file_format_enum" - UNDEFINED_FORMAT = None - RMS_ROFF_FILE = None - ECL_KW_FILE = None - ECL_KW_FILE_ACTIVE_CELLS = None - ECL_KW_FILE_ALL_CELLS = None - ECL_GRDECL_FILE = None - ECL_FILE = None - FILE_FORMAT_NULL = None - -EnkfFieldFileFormatEnum.addEnum("UNDEFINED_FORMAT", 0) -EnkfFieldFileFormatEnum.addEnum("RMS_ROFF_FILE", 1) -EnkfFieldFileFormatEnum.addEnum("ECL_KW_FILE", 2) -EnkfFieldFileFormatEnum.addEnum("ECL_KW_FILE_ACTIVE_CELLS", 3) -EnkfFieldFileFormatEnum.addEnum("ECL_KW_FILE_ALL_CELLS", 4) -EnkfFieldFileFormatEnum.addEnum("ECL_GRDECL_FILE", 5) -EnkfFieldFileFormatEnum.addEnum("ECL_FILE", 6) -EnkfFieldFileFormatEnum.addEnum("FILE_FORMAT_NULL", 7) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_fs_type_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_fs_type_enum.py deleted file mode 100644 index 1a4a471dce..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_fs_type_enum.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'enkf_fs_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - - -class EnKFFSType(BaseCEnum): - TYPE_NAME = "enkf_fs_type_enum" - INVALID_DRIVER_ID = None - PLAIN_DRIVER_ID = None - BLOCK_FS_DRIVER_ID = None - -EnKFFSType.addEnum("INVALID_DRIVER_ID", 0) -EnKFFSType.addEnum("PLAIN_DRIVER_ID", 1005) -EnKFFSType.addEnum("BLOCK_FS_DRIVER_ID", 3001) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_init_modes_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_init_modes_enum.py deleted file mode 100644 index f19c6adc12..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_init_modes_enum.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'content_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - -class EnkfInitModeEnum(BaseCEnum): - TYPE_NAME = "enkf_init_mode_enum" - INIT_NONE = None - INIT_CONDITIONAL = None - INIT_FORCE = None - - -EnkfInitModeEnum.addEnum("INIT_NONE", 0) -EnkfInitModeEnum.addEnum("INIT_CONDITIONAL", 1) -EnkfInitModeEnum.addEnum("INIT_FORCE", 2) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_obs_impl_type_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_obs_impl_type_enum.py deleted file mode 100644 index a8abbffab9..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_obs_impl_type_enum.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'enkf_obs_impl_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - -class EnkfObservationImplementationType(BaseCEnum): - TYPE_NAME = "enkf_obs_impl_type" - GEN_OBS = None - SUMMARY_OBS = None - BLOCK_OBS = None - -EnkfObservationImplementationType.addEnum("GEN_OBS", 1) -EnkfObservationImplementationType.addEnum("SUMMARY_OBS", 2) -EnkfObservationImplementationType.addEnum("BLOCK_OBS", 3) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_run_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_run_enum.py deleted file mode 100644 index 9e23bdb208..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_run_enum.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'content_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - -class EnkfRunType(BaseCEnum): - TYPE_NAME = "enkf_run_mode_enum" - ENKF_ASSIMILATION = None - ENSEMBLE_EXPERIMENT = None - SMOOTHER_UPDATED = None - INIT_ONLY = None - - -EnkfRunType.addEnum("ENKF_ASSIMILATION" , 1) -EnkfRunType.addEnum("ENSEMBLE_EXPERIMENT" , 2) -EnkfRunType.addEnum("SMOOTHER_UPDATE" , 4) -EnkfRunType.addEnum("INIT_ONLY" , 8) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_truncation_type.py b/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_truncation_type.py deleted file mode 100644 index 326fa0b8a2..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_truncation_type.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'content_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - -class EnkfTruncationType(BaseCEnum): - TYPE_NAME = "enkf_truncation_type_enum" - TRUNCATE_NONE = None - TRUNCATE_MIN = None - TRUNCATE_MAX = None - -EnkfTruncationType.addEnum("TRUNCATE_NONE", 0) -EnkfTruncationType.addEnum("TRUNCATE_MIN", 1) -EnkfTruncationType.addEnum("TRUNCATE_MAX", 2) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_var_type_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_var_type_enum.py deleted file mode 100644 index 823b369326..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/enkf_var_type_enum.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'content_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - -class EnkfVarType(BaseCEnum): - TYPE_NAME = "enkf_var_type_enum" - INVALID_VAR = None - PARAMETER = None - DYNAMIC_STATE = None - DYNAMIC_RESULT = None - STATIC_STATE = None - INDEX_STATE = None - - -EnkfVarType.addEnum("INVALID_VAR", 0) -EnkfVarType.addEnum("PARAMETER", 1) -EnkfVarType.addEnum("DYNAMIC_STATE", 2) -EnkfVarType.addEnum("DYNAMIC_RESULT", 4) -EnkfVarType.addEnum("STATIC_STATE", 8) -EnkfVarType.addEnum("INDEX_STATE", 16) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/ert_impl_type_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/ert_impl_type_enum.py deleted file mode 100644 index 4d204f1ae8..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/ert_impl_type_enum.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'ert_impl_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - - -class ErtImplType(BaseCEnum): - TYPE_NAME = "ert_impl_type_enum" - INVALID = None - IMPL_TYPE_OFFSET = None - STATIC = None # MULTZ has been removed & MULTFLT - FIELD = None # WELL has been removed - GEN_KW = None # RELPERM has been removed & HAVANA_FAULT - CUSTOM_KW = None - SUMMARY = None # TPGZONE has been removed - GEN_DATA = None # PILOT_POINT has been removed - SURFACE = None - CONTAINER = None - - -ErtImplType.addEnum("INVALID", 0) -ErtImplType.addEnum("IMPL_TYPE_OFFSET", 100) -ErtImplType.addEnum("STATIC", 100) -ErtImplType.addEnum("FIELD", 104) -ErtImplType.addEnum("GEN_KW", 107) -ErtImplType.addEnum("CUSTOM_KW", 108) -ErtImplType.addEnum("SUMMARY", 110) -ErtImplType.addEnum("GEN_DATA", 113) -ErtImplType.addEnum("SURFACE", 114) -ErtImplType.addEnum("CONTAINER", 115) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/gen_data_file_type_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/gen_data_file_type_enum.py deleted file mode 100644 index 62fb9867c3..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/gen_data_file_type_enum.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'gen_data_file_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum -from ert.enkf import EnkfPrototype - - -class GenDataFileType(BaseCEnum): - TYPE_NAME = "gen_data_file_format_type" - GEN_DATA_UNDEFINED = None - ASCII = None # The file is ASCII file with a vector of numbers formatted with "%g" - ASCII_TEMPLATE = None # The data is inserted into a user defined template file. - BINARY_DOUBLE = None # The data is in a binary file with doubles. - BINARY_FLOAT = None # The data is in a binary file with floats. - -GenDataFileType.addEnum("GEN_DATA_UNDEFINED", 0) -GenDataFileType.addEnum("ASCII", 1) -GenDataFileType.addEnum("ASCII_TEMPLATE", 2) -GenDataFileType.addEnum("BINARY_DOUBLE", 3) -GenDataFileType.addEnum("BINARY_FLOAT", 4) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/hook_runtime_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/hook_runtime_enum.py deleted file mode 100644 index 45a1663b6d..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/hook_runtime_enum.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# The file 'hook_runtime_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - -class HookRuntime(BaseCEnum): - TYPE_NAME = "hook_runtime_enum" - PRE_SIMULATION = None - POST_SIMULATION = None - PRE_UPDATE = None - POST_UPDATE = None - - -HookRuntime.addEnum("PRE_SIMULATION" , 0) -HookRuntime.addEnum("POST_SIMULATION" , 1) -HookRuntime.addEnum("PRE_UPDATE" , 2) -HookRuntime.addEnum("POST_UPDATE" , 3) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/load_fail_type_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/load_fail_type_enum.py deleted file mode 100644 index b21808a453..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/load_fail_type_enum.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'content_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - -class LoadFailTypeEnum(BaseCEnum): - TYPE_NAME = "load_fail_type" - LOAD_FAIL_SILENT = None - LOAD_FAIL_WARN = None - LOAD_FAIL_EXIT = None - - -LoadFailTypeEnum.addEnum("LOAD_FAIL_SILENT", 0) -LoadFailTypeEnum.addEnum("LOAD_FAIL_WARN", 2) -LoadFailTypeEnum.addEnum("LOAD_FAIL_EXIT", 4) diff --git a/ThirdParty/Ert/python/python/ert/enkf/enums/realization_state_enum.py b/ThirdParty/Ert/python/python/ert/enkf/enums/realization_state_enum.py deleted file mode 100644 index 20ce63d7a9..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/enums/realization_state_enum.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'ert_impl_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum - -class RealizationStateEnum(BaseCEnum): - TYPE_NAME = "realisation_state_enum" - STATE_UNDEFINED = None - STATE_INITIALIZED = None - STATE_HAS_DATA = None - STATE_LOAD_FAILURE = None - STATE_PARENT_FAILURE = None - -RealizationStateEnum.addEnum("STATE_UNDEFINED", 1) -RealizationStateEnum.addEnum("STATE_INITIALIZED", 2) -RealizationStateEnum.addEnum("STATE_HAS_DATA", 4) -RealizationStateEnum.addEnum("STATE_LOAD_FAILURE", 8) -RealizationStateEnum.addEnum("STATE_PARENT_FAILURE", 16) diff --git a/ThirdParty/Ert/python/python/ert/enkf/ert_log.py b/ThirdParty/Ert/python/python/ert/enkf/ert_log.py deleted file mode 100644 index 499bf2c320..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/ert_log.py +++ /dev/null @@ -1,20 +0,0 @@ -from ert.enkf import EnkfPrototype - - -class ErtLog(object): - _init = EnkfPrototype("void ert_log_init_log(int, char*, bool)", bind=False) - _write_log = EnkfPrototype("void ert_log_add_message_py(int, char*)", bind=False) - _get_filename = EnkfPrototype("char* ert_log_get_filename()", bind=False) - - @classmethod - def init(cls, log_level, log_filename, verbose): - cls._init(log_level, log_filename, verbose) - - @classmethod - def log(cls, log_level, message): - cls._write_log(log_level, message) - - @classmethod - def getFilename(cls): - """ @rtype: string """ - return cls._get_filename() diff --git a/ThirdParty/Ert/python/python/ert/enkf/ert_run_context.py b/ThirdParty/Ert/python/python/ert/enkf/ert_run_context.py deleted file mode 100644 index f4f12757be..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/ert_run_context.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'enkf_fs.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf import TimeMap, StateMap, RunArg -from ert.util import PathFormat, StringList - -class ErtRunContext(BaseCClass): - TYPE_NAME = "ert_run_context" - - _alloc_runpath_list = EnkfPrototype("stringlist_obj ert_run_context_alloc_runpath_list(bool_vector, path_fmt, subst_list, int)", bind = False) - _alloc_runpath = EnkfPrototype("char* ert_run_context_alloc_runpath(int, path_fmt, subst_list, int)", bind = False) - _get_size = EnkfPrototype("int ert_run_context_get_size( ert_run_context )") - _free = EnkfPrototype("void ert_run_context_free( ert_run_context )") - _iget = EnkfPrototype("run_arg_ref ert_run_context_iget_arg( ert_run_context , int)") - _iens_get = EnkfPrototype("run_arg_ref ert_run_context_iens_get_arg( ert_run_context , int)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def __len__(self): - return self._get_size() - - def __getitem__(self , index): - if isinstance(index, int): - if 0 <= index < len(self): - run_arg = self._iget(index) - run_arg.setParent( self ) - return run_arg - else: - raise IndexError("Index:%d invalid. Legal range: [0,%d)" % (index , len(self))) - else: - raise TypeError("Invalid type - expetected integer") - - def iensGet(self , iens): - run_arg = self._iens_get(iens) - if run_arg is not None: - run_arg.setParent(self) - return run_arg - else: - raise ValueError("Run context does not have run argument for iens:%d" % iens) - - def free(self): - self._free() - - def __repr__(self): - return 'ErtRunContext(size = %d) %s' % (len(self), self._ad_str()) - - @classmethod - def createRunpathList(cls, mask, runpath_fmt, subst_list, iter=0): - """ @rtype: ert.util.stringlist.StringList """ - return cls._alloc_runpath_list(mask, runpath_fmt, subst_list, iter) - - - @classmethod - def createRunpath(cls, iens , runpath_fmt, subst_list, iter=0): - """ @rtype: str """ - return cls._alloc_runpath(iens, runpath_fmt, subst_list, iter) diff --git a/ThirdParty/Ert/python/python/ert/enkf/ert_template.py b/ThirdParty/Ert/python/python/ert/enkf/ert_template.py deleted file mode 100644 index 66df26159b..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/ert_template.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'ert_template.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype - - -class ErtTemplate(BaseCClass): - TYPE_NAME = "ert_template" - - _free = EnkfPrototype("void ert_template_free( ert_template )") - _get_template_file = EnkfPrototype("char* ert_template_get_template_file(ert_template)") - _get_target_file = EnkfPrototype("char* ert_template_get_target_file(ert_template)") - _get_args_as_string = EnkfPrototype("char* ert_template_get_args_as_string(ert_template)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def get_template_file(self): - """ @rtype: str """ - return self._get_template_file() - - def get_target_file(self): - """ @rtype: str """ - return self._get_target_file() - - def get_args_as_string(self): - """ @rtype: str """ - return self._get_args_as_string() - - def free(self): - self._free() diff --git a/ThirdParty/Ert/python/python/ert/enkf/ert_templates.py b/ThirdParty/Ert/python/python/ert/enkf/ert_templates.py deleted file mode 100644 index aa4d39ef5e..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/ert_templates.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'ert_templates.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype, ErtTemplate -from ert.util import StringList - - -class ErtTemplates(BaseCClass): - TYPE_NAME = "ert_templates" - - _free = EnkfPrototype("void ert_templates_free( ert_templates )") - _alloc_list = EnkfPrototype("stringlist_ref ert_templates_alloc_list(ert_templates)") - _get_template = EnkfPrototype("ert_template_ref ert_templates_get_template(ert_templates, char*)") - _clear = EnkfPrototype("void ert_templates_clear(ert_templates)") - _add_template = EnkfPrototype("ert_template_ref ert_templates_add_template(ert_templates, char*, char*, char*, char*)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def getTemplateNames(self): - """ @rtype: StringList """ - return self._alloc_list().setParent(self) - - def clear(self): - self._clear() - - def get_template(self, key): - """ @rtype: ErtTemplate """ - return self._get_template(key).setParent(self) - - def add_template(self, key, template_file, target_file, arg_string): - """ @rtype: ErtTemplate """ - return self._add_template(key, template_file, target_file, arg_string).setParent(self) - - def free(self): - self._free() diff --git a/ThirdParty/Ert/python/python/ert/enkf/ert_workflow_list.py b/ThirdParty/Ert/python/python/ert/enkf/ert_workflow_list.py deleted file mode 100644 index 9c1ee6726b..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/ert_workflow_list.py +++ /dev/null @@ -1,77 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.util import StringList, SubstitutionList -from ert.job_queue import Workflow, WorkflowJob - - -class ErtWorkflowList(BaseCClass): - TYPE_NAME = "ert_workflow_list" - - _alloc_namelist = EnkfPrototype("stringlist_obj ert_workflow_list_alloc_namelist(ert_workflow_list)") - _has_workflow = EnkfPrototype("bool ert_workflow_list_has_workflow(ert_workflow_list, char*)") - _get_workflow = EnkfPrototype("workflow_ref ert_workflow_list_get_workflow(ert_workflow_list, char*)") - _get_context = EnkfPrototype("subst_list_ref ert_workflow_list_get_context(ert_workflow_list)") - _add_job = EnkfPrototype("void ert_workflow_list_add_job(ert_workflow_list, char*, char*)") - _has_job = EnkfPrototype("bool ert_workflow_list_has_job(ert_workflow_list, char*)") - _get_job = EnkfPrototype("workflow_job_ref ert_workflow_list_get_job(ert_workflow_list, char*)") - _get_job_names = EnkfPrototype("stringlist_obj ert_workflow_list_get_job_names(ert_workflow_list)") - _free = EnkfPrototype("void ert_workflow_list_free(ert_workflow_list)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def getWorkflowNames(self): - """ @rtype: StringList """ - return self._alloc_namelist() - - def __contains__(self, workflow_name): - assert isinstance(workflow_name, str) - return self._has_workflow(workflow_name) - - def __getitem__(self, item): - """ @rtype: Workflow """ - if not item in self: - raise KeyError("Item '%s' is not in the list of available workflows." % item) - - return self._get_workflow(item).setParent(self) - - def getContext(self): - """ @rtype: SubstitutionList """ - return self._get_context() - - def free(self): - self._free() - - def __str__(self): - return 'ErtWorkflowList with jobs: %s' + str(self.getJobNames()) - - def addJob(self, job_name, job_path): - """ - @type job_name: str - @type job_path: str - """ - self._add_job(job_name, job_path) - - def hasJob(self, job_name): - """ - @type job_name: str - @rtype: bool - """ - return self._has_job(job_name) - - def getJob(self, job_name): - """ @rtype: WorkflowJob """ - return self._get_job(job_name) - - def getJobNames(self): - """ @rtype: StringList """ - return self._get_job_names() - - def getPluginJobs(self): - """ @rtype: list of WorkflowJob """ - plugins = [] - for job_name in self.getJobNames(): - job = self.getJob(job_name) - if job.isPlugin(): - plugins.append(job) - return plugins diff --git a/ThirdParty/Ert/python/python/ert/enkf/es_update.py b/ThirdParty/Ert/python/python/ert/enkf/es_update.py deleted file mode 100644 index eeed5b00a7..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/es_update.py +++ /dev/null @@ -1,35 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype - -class ESUpdate(BaseCClass): - TYPE_NAME="es_update" - _smoother_update = EnkfPrototype("bool enkf_main_smoother_update(es_update, enkf_fs, enkf_fs)") - - def __init__(self , ert): - assert isinstance(ert , BaseCClass) - super(ESUpdate, self).__init__(ert.from_param(ert).value , parent=ert , is_reference=True) - self.ert = ert - self.analysis_config = self.ert.analysisConfig( ) - - - def hasModule(self, name): - """ - Will check if we have analysis module @name. - """ - return self.analysis_config.hasModule( name ) - - - def getModule(self,name): - if self.hasModule( name ): - self.analysis_config.getModule( name ) - else: - raise KeyError("No such module:%s " % name) - - - def setGlobalStdScaling(self , weight): - self.analysis_config.setGlobalStdScaling( weight ) - - - - def smootherUpdate( self , data_fs , target_fs): - return self._smoother_update(data_fs , target_fs ) diff --git a/ThirdParty/Ert/python/python/ert/enkf/export/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/enkf/export/CMakeLists.txt deleted file mode 100644 index 54dca03101..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/export/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - arg_loader.py - custom_kw_collector.py - design_matrix_reader.py - gen_data_collector.py - gen_data_observation_collector.py - gen_kw_collector.py - misfit_collector.py - summary_collector.py - summary_observation_collector.py -) - -add_python_package("python.ert.enkf.export" ${PYTHON_INSTALL_PREFIX}/ert/enkf/export "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/enkf/export/__init__.py b/ThirdParty/Ert/python/python/ert/enkf/export/__init__.py deleted file mode 100644 index 6bd788d815..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/export/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -from .design_matrix_reader import DesignMatrixReader -from .summary_observation_collector import SummaryObservationCollector -from .summary_collector import SummaryCollector -from .gen_kw_collector import GenKwCollector -from .gen_data_collector import GenDataCollector -from .gen_data_observation_collector import GenDataObservationCollector -from .misfit_collector import MisfitCollector -from .custom_kw_collector import CustomKWCollector -from .arg_loader import ArgLoader - -__all__ = ["DesignMatrixReader", - "SummaryCollector", - "SummaryObservationCollector", - "GenKwCollector", - "MisfitCollector", - "CustomKWCollector", - "GenDataCollector", - "GenDataObservationCollector", - "ArgLoader"] - diff --git a/ThirdParty/Ert/python/python/ert/enkf/export/arg_loader.py b/ThirdParty/Ert/python/python/ert/enkf/export/arg_loader.py deleted file mode 100644 index ffb57dc1c1..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/export/arg_loader.py +++ /dev/null @@ -1,46 +0,0 @@ -from __future__ import print_function -import math -from pandas import DataFrame, MultiIndex -import numpy -from ert.enkf import ErtImplType, EnKFMain, EnkfFs, RealizationStateEnum, GenKwConfig -from ert.enkf.plot_data import EnsemblePlotGenData -from ert.util import BoolVector - - -class ArgLoader(object): - - @staticmethod - def load(filename , column_names = None): - rows = 0 - columns = 0 - with open(filename,"r") as fileH: - for line in fileH.readlines(): - rows += 1 - columns = max(columns , len( line.split()) ) - - if not column_names is None: - if len(column_names) <= columns: - columns = len(column_names) - else: - raise ValueError("To many coloumns in input") - - data = numpy.empty(shape=(rows , columns) , dtype=numpy.float64) - data.fill( numpy.nan ) - - row = 0 - with open(filename) as fileH: - for line in fileH.readlines(): - tmp = line.split( ) - print(tmp) - for column in range(columns): - data[row][column] = float(tmp[column]) - row += 1 - - - if column_names is None: - column_names = [] - for column in range(columns): - column_names.append( "Column%d" % column ) - - data_frame = DataFrame( data = data , columns = column_names) - return data_frame diff --git a/ThirdParty/Ert/python/python/ert/enkf/export/custom_kw_collector.py b/ThirdParty/Ert/python/python/ert/enkf/export/custom_kw_collector.py deleted file mode 100644 index e696c488d0..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/export/custom_kw_collector.py +++ /dev/null @@ -1,66 +0,0 @@ -from pandas import DataFrame -from ert.enkf import ErtImplType, EnKFMain, EnkfFs, RealizationStateEnum, CustomKWConfig, EnkfNode, NodeId -from ert.enkf.key_manager import KeyManager - - -class CustomKWCollector(object): - - @staticmethod - def getAllCustomKWKeys(ert): - """ @rtype: list of str """ - key_manager = KeyManager(ert) - return key_manager.customKwKeys() - - @staticmethod - def groupKeys(keys): - grouped_keys = {} - for key in keys: - name, keyword = key.split(":") - - if not name in grouped_keys: - grouped_keys[name] = [] - - grouped_keys[name].append(keyword) - - return grouped_keys - - - @staticmethod - def loadAllCustomKWData(ert, case_name, keys=None): - """ - @type ert: EnKFMain - @type case_name: str - @type keys: list of str - @rtype: DataFrame - """ - fs = ert.getEnkfFsManager().getFileSystem(case_name) - - realizations = fs.realizationList(RealizationStateEnum.STATE_HAS_DATA | RealizationStateEnum.STATE_INITIALIZED) - - custom_kw_keys = CustomKWCollector.getAllCustomKWKeys(ert) - - if keys is not None: - custom_kw_keys = [key for key in keys if key in custom_kw_keys] # ignore keys that doesn't exist - - custom_kw_data = DataFrame(index=realizations, columns=custom_kw_keys) - custom_kw_data.index.name = "Realization" - - custom_kw_keys = CustomKWCollector.groupKeys(custom_kw_keys) - - for name in custom_kw_keys: - ensemble_config_node = ert.ensembleConfig().getNode(name) - enkf_node = EnkfNode(ensemble_config_node) - - keys = custom_kw_keys[name] - - for realization_number in realizations: - node_id = NodeId(0, realization_number) - if enkf_node.tryLoad(fs, node_id): - custom_kw = enkf_node.asCustomKW() - - for key in keys: - value = custom_kw[key] - custom_kw_data["%s:%s" % (name, key)][realization_number] = value - - return custom_kw_data - diff --git a/ThirdParty/Ert/python/python/ert/enkf/export/design_matrix_reader.py b/ThirdParty/Ert/python/python/ert/enkf/export/design_matrix_reader.py deleted file mode 100644 index 0e31707f03..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/export/design_matrix_reader.py +++ /dev/null @@ -1,15 +0,0 @@ -import pandas as pd -from pandas import DataFrame - - -class DesignMatrixReader(object): - - @staticmethod - def loadDesignMatrix(filename): - """@rtype: DataFrame""" - dm = pd.read_csv(filename, delim_whitespace=True) - """ @type dm: pd.DataFrame """ - dm = dm.rename(columns={dm.columns[0]:"Realization"}) - dm = dm.set_index(["Realization"]) - - return dm diff --git a/ThirdParty/Ert/python/python/ert/enkf/export/gen_data_collector.py b/ThirdParty/Ert/python/python/ert/enkf/export/gen_data_collector.py deleted file mode 100644 index 867483999c..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/export/gen_data_collector.py +++ /dev/null @@ -1,45 +0,0 @@ -import math -from pandas import DataFrame, MultiIndex -import numpy -from ert.enkf import ErtImplType, EnKFMain, EnkfFs, RealizationStateEnum, GenKwConfig -from ert.enkf.plot_data import EnsemblePlotGenData -from ert.util import BoolVector - - -class GenDataCollector(object): - - @staticmethod - def loadGenData(ert, case_name, key, report_step): - """@type ert: EnKFMain - @type case_name: str - @type key: str - @type report_step: int - @rtype: DataFrame - - In the returned dataframe the realisation index runs along the - rows, and the gen_data element index runs vertically along the - columns. - """ - fs = ert.getEnkfFsManager().getFileSystem(case_name) - realizations = fs.realizationList( RealizationStateEnum.STATE_HAS_DATA ) - config_node = ert.ensembleConfig().getNode(key) - gen_data_config = config_node.getModelConfig() - - ensemble_data = EnsemblePlotGenData( config_node , fs , report_step ) - # The data size and active can only be inferred *after* the EnsembleLoad. - data_size = gen_data_config.getDataSize( report_step ) - active_mask = gen_data_config.getActiveMask() - - data_array = numpy.empty(shape=(data_size , len(realizations)) , dtype=numpy.float64) - data_array.fill( numpy.nan ) - for realization_index, realization_number in enumerate(realizations): - realization_vector = ensemble_data[realization_number] - - if len(realization_vector) > 0: # Must check because of a bug changing between different case with different states - for data_index in range(data_size): - if active_mask[data_index]: - value = realization_vector[data_index] - data_array[data_index][realization_index] = value - - return DataFrame( data = data_array , columns = realizations ) - diff --git a/ThirdParty/Ert/python/python/ert/enkf/export/gen_data_observation_collector.py b/ThirdParty/Ert/python/python/ert/enkf/export/gen_data_observation_collector.py deleted file mode 100644 index bde51f3353..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/export/gen_data_observation_collector.py +++ /dev/null @@ -1,73 +0,0 @@ -from pandas import DataFrame -from ert.enkf import EnKFMain, EnkfFs, EnkfObservationImplementationType - - -class GenDataObservationCollector(object): - - @staticmethod - def getAllObservationKeys(ert): - """ - @type ert: EnKFMain - @rtype: list of str - """ - enkf_obs = ert.getObservations() - observation_keys = enkf_obs.getTypedKeylist(EnkfObservationImplementationType.GEN_OBS) - return [key for key in observation_keys] - - @staticmethod - def getObservationKeyForDataKey(ert, data_key, data_report_step): - """ - @type ert: EnKFMain - @rtype: str - """ - observation_key = None - - enkf_obs = ert.getObservations() - for obs_vector in enkf_obs: - report_step = obs_vector.activeStep() - key = obs_vector.getDataKey() - - if key == data_key and report_step == data_report_step: - observation_key = obs_vector.getObservationKey() - - return observation_key - - - @staticmethod - def loadGenDataObservations(ert, case_name, key): - """ - @type ert: EnKFMain - @type case_name: str - @type key: name of an observation key - @rtype: DataFrame - """ - fs = ert.getEnkfFsManager().getFileSystem(case_name) - - available_observation_keys = GenDataObservationCollector.getAllObservationKeys(ert) - if not key in available_observation_keys: - raise KeyError("Key '%s' is not a valid observation key") - - columns = [key] - std_columns = ["STD_%s" % key] - - enkf_obs = ert.getObservations() - - index_set = set() - obs_vector = enkf_obs[key] - report_step = obs_vector.activeStep() - - obs_node = obs_vector.getNode(report_step) - # """ :type: ert.enkf.observations.GenObservation """ - - for obs_index in range(len(obs_node)): - index_set.add(obs_node.getIndex(obs_index)) - - index_list = sorted(list(index_set)) - data = DataFrame(index=index_list, columns=columns + std_columns) - - for obs_index, (value, std) in enumerate(obs_node): - data_index = obs_node.getIndex(obs_index) - data[key][data_index] = value - data["STD_%s" % key][data_index] = std - - return data diff --git a/ThirdParty/Ert/python/python/ert/enkf/export/gen_kw_collector.py b/ThirdParty/Ert/python/python/ert/enkf/export/gen_kw_collector.py deleted file mode 100644 index 00bc1417f5..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/export/gen_kw_collector.py +++ /dev/null @@ -1,73 +0,0 @@ -import math -from pandas import DataFrame, MultiIndex -import numpy -from ert.enkf import ErtImplType, EnKFMain, EnkfFs, RealizationStateEnum, GenKwConfig -from ert.enkf.key_manager import KeyManager -from ert.enkf.plot_data import EnsemblePlotGenKW -from ert.util import BoolVector - - -class GenKwCollector(object): - - @staticmethod - def createActiveList(ert, fs): - state_map = fs.getStateMap() - ens_mask = BoolVector(False, ert.getEnsembleSize()) - state_map.selectMatching(ens_mask, RealizationStateEnum.STATE_INITIALIZED | RealizationStateEnum.STATE_HAS_DATA) - active_list = BoolVector.createActiveList(ens_mask) - - return [iens for iens in active_list] - - @staticmethod - def getAllGenKwKeys(ert): - """ @rtype: list of str """ - key_manager = KeyManager(ert) - return key_manager.genKwKeys() - - @staticmethod - def loadAllGenKwData(ert, case_name, keys=None): - """ - @type ert: EnKFMain - @type case_name: str - @type keys: list of str - @rtype: DataFrame - """ - fs = ert.getEnkfFsManager().getFileSystem(case_name) - - realizations = GenKwCollector.createActiveList(ert, fs) - - gen_kw_keys = GenKwCollector.getAllGenKwKeys(ert) - - if keys is not None: - gen_kw_keys = [key for key in keys if key in gen_kw_keys] # ignore keys that doesn't exist - - gen_kw_array = numpy.empty(shape=(len(gen_kw_keys), len(realizations)), dtype=numpy.float64) - gen_kw_array.fill(numpy.nan) - - for column_index, key in enumerate(gen_kw_keys): - key, keyword = key.split(":") - - use_log_scale = False - if key.startswith("LOG10_"): - key = key[6:] - use_log_scale = True - - ensemble_config_node = ert.ensembleConfig().getNode(key) - ensemble_data = EnsemblePlotGenKW(ensemble_config_node, fs) - keyword_index = ensemble_data.getIndexForKeyword(keyword) - - for realization_index, realization_number in enumerate(realizations): - realization_vector = ensemble_data[realization_number] - - value = realization_vector[keyword_index] - - if use_log_scale: - value = math.log10(value) - - gen_kw_array[column_index][realization_index] = value - - gen_kw_data = DataFrame(data=numpy.transpose(gen_kw_array), index=realizations, columns=gen_kw_keys) - gen_kw_data.index.name = "Realization" - - return gen_kw_data - diff --git a/ThirdParty/Ert/python/python/ert/enkf/export/misfit_collector.py b/ThirdParty/Ert/python/python/ert/enkf/export/misfit_collector.py deleted file mode 100644 index fa0ebea40b..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/export/misfit_collector.py +++ /dev/null @@ -1,53 +0,0 @@ -from pandas import DataFrame -import numpy -from ert.enkf import EnKFMain, EnkfFs, RealizationStateEnum -from ert.enkf.key_manager import KeyManager -from ert.util import BoolVector - - -class MisfitCollector(object): - - @staticmethod - def createActiveList(ert, fs): - state_map = fs.getStateMap() - ens_mask = BoolVector(False, ert.getEnsembleSize()) - state_map.selectMatching(ens_mask, RealizationStateEnum.STATE_HAS_DATA) - active_list = BoolVector.createActiveList(ens_mask) - - return [iens for iens in active_list] - - @staticmethod - def getAllMisfitKeys(ert, sort_keys=True): - """ @rtype: list of str """ - key_manager = KeyManager(ert) - return key_manager.misfitKeys(sort_keys=sort_keys) - - @staticmethod - def loadAllMisfitData(ert, case_name): - """ - @type ert: EnKFMain - @type case_name: str - @rtype: DataFrame - """ - fs = ert.getEnkfFsManager().getFileSystem(case_name) - - realizations = MisfitCollector.createActiveList(ert, fs) - misfit_keys = MisfitCollector.getAllMisfitKeys(ert, sort_keys=False) - misfit_sum_index = len(misfit_keys) - 1 - - misfit_array = numpy.empty(shape=(len(misfit_keys), len(realizations)), dtype=numpy.float64) - misfit_array.fill(numpy.nan) - misfit_array[misfit_sum_index] = 0.0 - - for column_index, obs_vector in enumerate(ert.getObservations()): - - for realization_index, realization_number in enumerate(realizations): - misfit = obs_vector.getTotalChi2(fs, realization_number) - - misfit_array[column_index][realization_index] = misfit - misfit_array[misfit_sum_index][realization_index] += misfit - - misfit_data = DataFrame(data=numpy.transpose(misfit_array), index=realizations, columns=misfit_keys) - misfit_data.index.name = "Realization" - - return misfit_data diff --git a/ThirdParty/Ert/python/python/ert/enkf/export/summary_collector.py b/ThirdParty/Ert/python/python/ert/enkf/export/summary_collector.py deleted file mode 100644 index 322ad3d946..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/export/summary_collector.py +++ /dev/null @@ -1,67 +0,0 @@ -from pandas import DataFrame, MultiIndex -import numpy -from ert.enkf import ErtImplType, EnKFMain, EnkfFs, RealizationStateEnum -from ert.enkf.key_manager import KeyManager -from ert.enkf.plot_data import EnsemblePlotData -from ert.util import BoolVector - - -class SummaryCollector(object): - - @staticmethod - def createActiveList(ert, fs): - state_map = fs.getStateMap() - ens_mask = BoolVector(False, ert.getEnsembleSize()) - state_map.selectMatching(ens_mask, RealizationStateEnum.STATE_HAS_DATA) - active_list = BoolVector.createActiveList(ens_mask) - - return [iens for iens in active_list] - - @staticmethod - def getAllSummaryKeys(ert): - """ @rtype: list of str """ - key_manager = KeyManager(ert) - return key_manager.summaryKeys() - - @staticmethod - def loadAllSummaryData(ert, case_name, keys=None): - """ - @type ert: EnKFMain - @type case_name: str - @type keys: list of str - @rtype: DataFrame - """ - fs = ert.getEnkfFsManager().getFileSystem(case_name) - - time_map = fs.getTimeMap() - dates = [time_map[index].datetime() for index in range(1, len(time_map))] - realizations = SummaryCollector.createActiveList(ert, fs) - - summary_keys = SummaryCollector.getAllSummaryKeys(ert) - if keys is not None: - summary_keys = [key for key in keys if key in summary_keys] # ignore keys that doesn't exist - - summary_array = numpy.empty(shape=(len(summary_keys), len(realizations) * len(dates)), dtype=numpy.float64) - summary_array.fill(numpy.nan) - - for key_index, key in enumerate(summary_keys): - ensemble_config_node = ert.ensembleConfig().getNode(key) - ensemble_data = EnsemblePlotData(ensemble_config_node, fs) - summary_row = summary_array[key_index] - - for realization_index, realization_number in enumerate(realizations): - realization_vector = ensemble_data[realization_number] - column_index = realization_index * len(dates) - - for index in range(1, len(realization_vector)): - if realization_vector.isActive(index): - # assert time_map[index] == realization_vector.getTime(index) - # assert time_map[index].datetime() == dates[index - 1] - value = realization_vector.getValue(index) - summary_row[column_index + index - 1] = value - - - multi_index = MultiIndex.from_product([realizations, dates], names=["Realization", "Date"]) - summary_data = DataFrame(data=numpy.transpose(summary_array), index=multi_index, columns=summary_keys) - return summary_data - diff --git a/ThirdParty/Ert/python/python/ert/enkf/export/summary_observation_collector.py b/ThirdParty/Ert/python/python/ert/enkf/export/summary_observation_collector.py deleted file mode 100644 index 7eb9df6f31..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/export/summary_observation_collector.py +++ /dev/null @@ -1,65 +0,0 @@ -from pandas import DataFrame, MultiIndex -import numpy -from ert.enkf import ErtImplType, EnKFMain, EnkfFs, RealizationStateEnum, EnkfObservationImplementationType -from ert.enkf.key_manager import KeyManager -from ert.enkf.plot_data import EnsemblePlotData -from ert.util import BoolVector - - -class SummaryObservationCollector(object): - - @staticmethod - def getAllObservationKeys(ert): - """ - @type ert: EnKFMain - @rtype: list of str - """ - key_manager = KeyManager(ert) - return key_manager.summaryKeysWithObservations() - - @staticmethod - def loadObservationData(ert, case_name, keys=None): - """ - @type ert: EnKFMain - @type case_name: str - @type keys: list of str - @rtype: DataFrame - """ - fs = ert.getEnkfFsManager().getFileSystem(case_name) - - time_map = fs.getTimeMap() - dates = [time_map[index].datetime() for index in range(1, len(time_map))] - - summary_keys = SummaryObservationCollector.getAllObservationKeys(ert) - if keys is not None: - summary_keys = [key for key in keys if key in summary_keys] # ignore keys that doesn't exist - - columns = summary_keys - std_columns = ["STD_%s" % key for key in summary_keys] - - df = DataFrame(index=dates, columns=columns + std_columns) - - for key in summary_keys: - observation_keys = ert.ensembleConfig().getNode(key).getObservationKeys() - - for obs_key in observation_keys: - observations = ert.getObservations() - observation_data = observations[obs_key] - history_length = ert.getHistoryLength() - - for index in range(0, history_length): - if observation_data.isActive(index): - obs_time = observations.getObservationTime(index).datetime() - node = observation_data.getNode(index) - value = node.getValue() - std = node.getStandardDeviation() - - df[key][obs_time] = value - df["STD_%s" % key][obs_time] = std - - - return df - - @classmethod - def summaryKeyHasObservations(cls, ert, key): - return len(ert.ensembleConfig().getNode(key).getObservationKeys()) > 0 diff --git a/ThirdParty/Ert/python/python/ert/enkf/forward_load_context.py b/ThirdParty/Ert/python/python/ert/enkf/forward_load_context.py deleted file mode 100644 index 8c2f4d7335..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/forward_load_context.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# The file 'forward_load_context.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from ert.enkf import EnkfPrototype -from cwrap import BaseCClass - - -# The Python wrapping of the forward_load_context is extremely -# minimal; when creating the Python implementation the only purpose -# was to get an existing test through. - - -class ForwardLoadContext(BaseCClass): - TYPE_NAME = "forward_load_context" - _alloc = EnkfPrototype("void* forward_load_context_alloc( run_arg , bool , ecl_config , char* , stringlist )" , bind = False) - _select_step = EnkfPrototype("void forward_load_context_select_step( forward_load_context , int )") - _get_step = EnkfPrototype("int forward_load_context_get_load_step( forward_load_context)") - _free = EnkfPrototype("void forward_load_context_free( forward_load_context)") - - - def __init__(self , run_arg = None , load_summary = False , ecl_config = None , ecl_base = None , messages = None , report_step = None): - c_ptr = self._alloc(run_arg , load_summary , ecl_config , ecl_base , messages) - super(ForwardLoadContext, self).__init__(c_ptr) - if not report_step is None: - self.selectStep( report_step ) - - - def getLoadStep( self ): - return self._get_step( ) - - - def selectStep(self , report_step): - self._select_step( report_step) - - - def free(self): - self._free( ) - diff --git a/ThirdParty/Ert/python/python/ert/enkf/hook_manager.py b/ThirdParty/Ert/python/python/ert/enkf/hook_manager.py deleted file mode 100644 index 482aa3d71d..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/hook_manager.py +++ /dev/null @@ -1,54 +0,0 @@ -import os -import sys -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype - -class HookManager(BaseCClass): - TYPE_NAME = "hook_manager" - - _get_runpath_list_file = EnkfPrototype("char* hook_manager_get_runpath_list_file(hook_manager)") - _get_runpath_list = EnkfPrototype("runpath_list_ref hook_manager_get_runpath_list(hook_manager)") - _iget_hook_workflow = EnkfPrototype("hook_workflow_ref hook_manager_iget_hook_workflow(hook_manager, int)") - _size = EnkfPrototype("int hook_manager_get_size(hook_manager)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def __len__(self): - """ @rtype: int """ - return self._size() - - def __repr__(self): - return 'HookManager(size = %d) %s' % (len(self), self._ad_str()) - - def __getitem__(self, index): - """ @rtype: Hook workflow """ - assert isinstance(index, int) - if index < 0: - index += len(self) - if 0 <= index < len(self): - return self._iget_hook_workflow(index) - else: - raise IndexError("Invalid index. Valid range: [0, %d)." % len(self)) - - def checkRunpathListFile(self): - """ @rtype: bool """ - runpath_list_file = self._get_runpath_list_file() - - if not os.path.exists(runpath_list_file): - sys.stderr.write("** Warning: the file: %s with a list of runpath directories was not found - hook workflow will probably fail.\n" % runpath_list_file) - - def getRunpathList(self): - """ @rtype: RunpathList """ - return self._get_runpath_list() - - def runWorkflows(self , run_time , ert_self): - - workflow_list = ert_self.getWorkflowList() - for hook_workflow in self: - - if (hook_workflow.getRunMode() is not run_time): - continue - - workflow = hook_workflow.getWorkflow() - workflow.run(ert_self, context=workflow_list.getContext()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/hook_workflow.py b/ThirdParty/Ert/python/python/ert/enkf/hook_workflow.py deleted file mode 100644 index c17ffebfc6..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/hook_workflow.py +++ /dev/null @@ -1,20 +0,0 @@ -import os -import sys -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype, RunpathList - -class HookWorkflow(BaseCClass): - TYPE_NAME = "hook_workflow" - - _get_workflow = EnkfPrototype("workflow_ref hook_workflow_get_workflow(hook_workflow)") - _get_runmode = EnkfPrototype("hook_runtime_enum hook_workflow_get_run_mode(hook_workflow)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def getWorkflow(self): - """ @rtype: Workflow """ - return self._get_workflow() - - def getRunMode(self): - return self._get_runmode() diff --git a/ThirdParty/Ert/python/python/ert/enkf/key_manager.py b/ThirdParty/Ert/python/python/ert/enkf/key_manager.py deleted file mode 100644 index e86c65c5b2..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/key_manager.py +++ /dev/null @@ -1,172 +0,0 @@ -from ert.enkf import ErtImplType, GenKwConfig, CustomKWConfig - - -class KeyManager(object): - - def __init__(self, ert): - super(KeyManager, self).__init__() - """ - @type ert: ert.enkf.EnKFMain - """ - self.__ert = ert - - self.__all_keys = None - self.__all_keys_with_observations = None - self.__summary_keys = None - self.__summary_keys_with_observations = None - self.__gen_data_keys = None - self.__gen_data_keys_with_observations = None - self.__gen_kw_keys = None - self.__custom_kw_keys = None - self.__misfit_keys = None - - - def ert(self): - """ :rtype: ert.enkf.EnKFMain """ - return self.__ert - - def ensembleConfig(self): - """ :rtype: ert.enkf.EnsembleConfig """ - return self.ert().ensembleConfig() - - def summaryKeys(self): - """ :rtype: list of str """ - if self.__summary_keys is None: - self.__summary_keys = sorted([key for key in self.ensembleConfig().getKeylistFromImplType(ErtImplType.SUMMARY)], key=lambda k : k.lower()) - - return self.__summary_keys - - def summaryKeysWithObservations(self): - """ :rtype: list of str """ - if self.__summary_keys_with_observations is None: - self.__summary_keys_with_observations = sorted([key for key in self.summaryKeys() if len(self.ensembleConfig().getNode(key).getObservationKeys()) > 0], key=lambda k : k.lower()) - - return self.__summary_keys_with_observations - - def genKwKeys(self): - """ :rtype: list of str """ - if self.__gen_kw_keys is None: - gen_kw_keys = self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.GEN_KW) - gen_kw_keys = [key for key in gen_kw_keys] - - gen_kw_list = [] - for key in gen_kw_keys: - enkf_config_node = self.ert().ensembleConfig().getNode(key) - gen_kw_config = enkf_config_node.getModelConfig() - assert isinstance(gen_kw_config, GenKwConfig) - - for keyword_index, keyword in enumerate(gen_kw_config): - gen_kw_list.append("%s:%s" % (key, keyword)) - - if gen_kw_config.shouldUseLogScale(keyword_index): - gen_kw_list.append("LOG10_%s:%s" % (key, keyword)) - - self.__gen_kw_keys = sorted(gen_kw_list, key=lambda k : k.lower()) - - return self.__gen_kw_keys - - - def customKwKeys(self): - """ :rtype: list of str """ - if self.__custom_kw_keys is None: - custom_kw_keys = self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.CUSTOM_KW) - - keys = [] - for name in custom_kw_keys: - enkf_config_node = self.ert().ensembleConfig().getNode(name) - custom_kw_config = enkf_config_node.getModelConfig() - assert isinstance(custom_kw_config, CustomKWConfig) - - for key in custom_kw_config: - keys.append("%s:%s" % (name, key)) - - self.__custom_kw_keys = sorted([key for key in keys], key=lambda k : k.lower()) - - return self.__custom_kw_keys - - - def genDataKeys(self): - """ :rtype: list of str """ - if self.__gen_data_keys is None: - gen_data_keys = self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.GEN_DATA) - gen_data_list = [] - for key in gen_data_keys: - enkf_config_node = self.ert().ensembleConfig().getNode(key) - gen_data_config = enkf_config_node.getDataModelConfig() - - for report_step in gen_data_config.getReportSteps(): - gen_data_list.append("%s@%d" % (key, report_step)) - - self.__gen_data_keys = sorted(gen_data_list, key=lambda k : k.lower()) - - return self.__gen_data_keys - - def genDataKeysWithObservations(self): - """ :rtype: list of str """ - if self.__gen_data_keys_with_observations is None: - enkf_obs = self.ert().getObservations() - gen_data_obs_keys = [] - for obs_vector in enkf_obs: - report_step = obs_vector.activeStep() - key = obs_vector.getDataKey() - - gen_data_key = "%s@%d" % (key, report_step) - if gen_data_key in self.genDataKeys(): - gen_data_obs_keys.append(gen_data_key) - - self.__gen_data_keys_with_observations = gen_data_obs_keys - - return self.__gen_data_keys_with_observations - - def misfitKeys(self, sort_keys=True): - """ @rtype: list of str """ - if self.__misfit_keys is None: - keys = [] - for obs_vector in self.ert().getObservations(): - key = "MISFIT:%s" % obs_vector.getObservationKey() - keys.append(key) - - keys.append("MISFIT:TOTAL") - - self.__misfit_keys = sorted(keys, key=lambda k : k.lower()) if sort_keys else keys - - return self.__misfit_keys - - - def allDataTypeKeys(self): - """ :rtype: list of str """ - if self.__all_keys is None: - self.__all_keys = self.summaryKeys() + self.genKwKeys() + self.customKwKeys() + self.genDataKeys() - - return self.__all_keys - - def allDataTypeKeysWithObservations(self): - """ :rtype: list of str """ - if self.__all_keys_with_observations is None: - self.__all_keys_with_observations = self.summaryKeysWithObservations() + self.genDataKeysWithObservations() - - return self.__all_keys_with_observations - - def isKeyWithObservations(self, key): - """ :rtype: bool """ - return key in self.allDataTypeKeysWithObservations() - - def isSummaryKey(self, key): - """ :rtype: bool """ - return key in self.summaryKeys() - - def isGenKwKey(self, key): - """ :rtype: bool """ - return key in self.genKwKeys() - - def isCustomKwKey(self, key): - """ :rtype: bool """ - return key in self.customKwKeys() - - def isGenDataKey(self, key): - """ :rtype: bool """ - return key in self.genDataKeys() - - def isMisfitKey(self, key): - """ :rtype: bool """ - return key in self.misfitKeys() \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert/enkf/local_config.py b/ThirdParty/Ert/python/python/ert/enkf/local_config.py deleted file mode 100644 index 4324392f0c..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/local_config.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'local_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf import LocalUpdateStep -from ert.enkf.local_ministep import LocalMinistep -from ert.analysis import AnalysisModule - - -class LocalConfig(BaseCClass): - TYPE_NAME = "local_config" - - _free = EnkfPrototype("void local_config_free( local_config )") - _clear = EnkfPrototype("void local_config_clear( local_config )") - _get_updatestep = EnkfPrototype("local_updatestep_ref local_config_get_updatestep( local_config )") - _get_ministep = EnkfPrototype("local_ministep_ref local_config_get_ministep( local_config, char*)") - _create_ministep = EnkfPrototype("void local_config_alloc_ministep( local_config, char*, analysis_module)") - _attach_ministep = EnkfPrototype("void local_updatestep_add_ministep( local_updatestep, local_ministep)", bind = False) - _get_obsdata = EnkfPrototype("local_obsdata_ref local_config_get_obsdata( local_config, char*)") - _create_obsdata = EnkfPrototype("void local_config_alloc_obsdata( local_config, char*)") - _copy_obsdata = EnkfPrototype("local_obsdata_ref local_config_alloc_obsdata_copy( local_config, char*, char*)") - _has_obsdata = EnkfPrototype("bool local_config_has_obsdata( local_config, char*)") - _get_dataset = EnkfPrototype("local_dataset_ref local_config_get_dataset( local_config, char*)") - _create_dataset = EnkfPrototype("void local_config_alloc_dataset( local_config, char*)") - _copy_dataset = EnkfPrototype("local_dataset_ref local_config_alloc_dataset_copy( local_config, char*, char*)") - _has_dataset = EnkfPrototype("bool local_config_has_dataset( local_config, char*)") - _write_local_config_summary_file = EnkfPrototype("void local_config_summary_fprintf( local_config, char*)") - - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - - # The LocalConfig class is created as a reference to an existing - # underlying C structure by the method - # EnkFMain.local_config(). When the pointer to the C - # local_config_type object has been properly wrapped we 'decorate' - # the Python object with references to the ensemble_config , - # observations and grid. - # - # This implies that the Python object LocalConfig is richer than - # the underlying C object local_config_type; the extra attributes - # are only used for validation. - - def initAttributes(self , ensemble_config , obs , grid): - self.ensemble_config = ensemble_config - self.obs = obs - self.grid = grid - - - def __getObservations(self): - return self.obs - - def __getEnsembleConfig(self): - return self.ensemble_config - - def getGrid(self): - # The grid can be None - return self.grid - - def free(self): - self._free() - - def clear(self): - self._clear() - - def createMinistep(self, mini_step_key, analysis_module = None): - """ @rtype: Ministep """ - assert isinstance(mini_step_key, str) - if analysis_module: - assert isinstance(analysis_module, AnalysisModule) - self._create_ministep(mini_step_key, analysis_module) - return self.getMinistep(mini_step_key) - - def createObsdata(self, obsdata_key): - """ @rtype: Obsdata """ - assert isinstance(obsdata_key, str) - if self._has_obsdata(obsdata_key): - raise ValueError("Tried to add existing observation key:%s " % obsdata_key) - - self._create_obsdata(obsdata_key) - obsdata = self.getObsdata(obsdata_key) - obsdata.initObservations( self.__getObservations() ) - return obsdata - - - def copyObsdata(self, src_key, target_key): - """ @rtype: Obsdata """ - assert isinstance(src_key, str) - assert isinstance(target_key, str) - obsdata = self._copy_obsdata(src_key, target_key) - obsdata.initObservations( self.__getObservations() ) - return obsdata - - - def createDataset(self, dataset_key): - """ @rtype: Dataset """ - assert isinstance(dataset_key, str) - if self._has_dataset(dataset_key): - raise ValueError("Tried to add existing data key:%s " % dataset_key) - - self._create_dataset(dataset_key) - data = self.getDataset(dataset_key) - data.initEnsembleConfig( self.__getEnsembleConfig() ) - return data - - - def copyDataset(self, src_key, target_key): - """ @rtype: Dataset """ - assert isinstance(src_key, str) - assert isinstance(target_key, str) - data = self._copy_dataset(src_key, target_key) - data.initEnsembleConfig( self.__getEnsembleConfig() ) - return data - - - def getUpdatestep(self): - """ @rtype: UpdateStep """ - return self._get_updatestep() - - - def getMinistep(self, mini_step_key): - """ @rtype: Ministep """ - assert isinstance(mini_step_key, str) - return self._get_ministep(mini_step_key) - - def getObsdata(self, obsdata_key): - """ @rtype: Obsdata """ - assert isinstance(obsdata_key, str) - return self._get_obsdata(obsdata_key) - - def getDataset(self, dataset_key): - """ @rtype: Dataset """ - assert isinstance(dataset_key, str) - return self._get_dataset(dataset_key) - - - def attachMinistep(self, update_step, mini_step): - assert isinstance(mini_step, LocalMinistep) - assert isinstance(update_step, LocalUpdateStep) - self._attach_ministep(update_step, mini_step) - - - def writeSummaryFile(self, filename): - """ - Writes a summary of the local config object - The summary contains the Obsset with their respective - number of observations and the Datasets with the number of active indices - """ - assert isinstance(filename, str) - self._write_local_config_summary_file(filename) diff --git a/ThirdParty/Ert/python/python/ert/enkf/local_dataset.py b/ThirdParty/Ert/python/python/ert/enkf/local_dataset.py deleted file mode 100644 index a1b5e2af28..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/local_dataset.py +++ /dev/null @@ -1,88 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.ecl import EclRegion - -class LocalDataset(BaseCClass): - TYPE_NAME = "local_dataset" - - _alloc = EnkfPrototype("void* local_dataset_alloc(char*)", bind = False) - _size = EnkfPrototype("void* local_dataset_get_size(local_dataset)") - _has_key = EnkfPrototype("bool local_dataset_has_key(local_dataset, char*)") - _free = EnkfPrototype("void local_dataset_free(local_dataset)") - _name = EnkfPrototype("char* local_dataset_get_name(local_dataset)") - _add_node = EnkfPrototype("void local_dataset_add_node(local_dataset, char*)") - _del_node = EnkfPrototype("void local_dataset_del_node(local_dataset, char*)") - _active_list = EnkfPrototype("active_list_ref local_dataset_get_node_active_list(local_dataset, char*)") - - def __init__(self, name): - raise NotImplementedError("Class can not be instantiated directly!") - - - def initEnsembleConfig(self , config): - self.ensemble_config = config - - - def __len__(self): - """ @rtype: int """ - return self._size() - - def __contains__(self , key): - """ @rtype: bool """ - return self._has_key(key) - - def __delitem__(self, key): - assert isinstance(key, str) - if key in self: - self._del_node(key) - else: - raise KeyError('Unknown key "%s"' % key) - - def name(self): - return self._name() - def getName(self): - """ deprecated. @rtype: str """ - return self.name() - - def addNode(self, key): - assert isinstance(key, str) - if key in self.ensemble_config: - if not self._has_key(key): - self._add_node(key) - else: - raise KeyError('Tried to add existing data key "%s".' % key) - else: - raise KeyError('Tried to add data key "%s" not in ensemble.' % key) - - - def addNodeWithIndex(self, key, index): - assert isinstance(key, str) - assert isinstance(index, int) - - self.addNode( key ) - active_list = self.getActiveList(key) - active_list.addActiveIndex(index) - - - def addField(self, key, ecl_region): - assert isinstance(key, str) - assert isinstance(ecl_region, EclRegion) - - self.addNode( key ) - active_list = self.getActiveList(key) - active_region = ecl_region.getActiveList() - for i in active_region: - active_list.addActiveIndex(i) - - - def getActiveList(self, key): - """ @rtype: ActiveList """ - if key in self: - return self._active_list(key) - else: - raise KeyError('Local key "%s" not recognized.' % key) - - def free(self): - self._free() - - def __repr__(self): - return 'LocalDataset(name = %s, len = %d) at 0x%x' % (self.name(), len(self), self._address()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/local_ministep.py b/ThirdParty/Ert/python/python/ert/enkf/local_ministep.py deleted file mode 100644 index 39cd2352af..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/local_ministep.py +++ /dev/null @@ -1,64 +0,0 @@ -import ert.util -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype, LocalObsdata, LocalObsdataNode, LocalDataset - -class LocalMinistep(BaseCClass): - TYPE_NAME = "local_ministep" - - _alloc = EnkfPrototype("void* local_ministep_alloc(char*)", bind = False) - _add_node = EnkfPrototype("void local_ministep_add_obsdata_node(local_ministep, local_obsdata_node)") - _get_local_obs_data = EnkfPrototype("local_obsdata_ref local_ministep_get_obsdata(local_ministep)") - _get_local_data = EnkfPrototype("local_dataset_ref local_ministep_get_dataset(local_ministep , char*)") - _has_local_data = EnkfPrototype("bool local_ministep_has_dataset(local_ministep , char*)") - _free = EnkfPrototype("void local_ministep_free(local_ministep)") - _attach_obsdata = EnkfPrototype("void local_ministep_add_obsdata(local_ministep, local_obsdata)") - _attach_dataset = EnkfPrototype("void local_ministep_add_dataset(local_ministep, local_dataset)") - _name = EnkfPrototype("char* local_ministep_get_name(local_ministep)") - _data_size = EnkfPrototype("int local_ministep_get_num_dataset(local_ministep)") - - def __init__(self, ministep_key): - raise NotImplementedError("Class can not be instantiated directly!") - - # Will used the data keys; and ignore observation keys. - def __getitem__(self, data_key): - if isinstance(data_key, int): - raise TypeError('Keys must be strings, not int!') - if data_key in self: - return self._get_local_data(data_key) - else: - raise KeyError('No such data key: "%s"' % data_key) - - def __len__(self): - return self._data_size() - - def __contains__(self , data_key): - return self._has_local_data(data_key) - - def addNode(self, node): - assert isinstance(node, LocalObsdataNode) - self._add_node(node) - - def attachObsset(self, obs_set): - assert isinstance(obs_set, LocalObsdata) - self._attach_obsdata(obs_set) - - - def attachDataset(self, dataset): - assert isinstance(dataset, LocalDataset) - self._attach_dataset(dataset) - - def getLocalObsData(self): - """ @rtype: LocalObsdata """ - return self._get_local_obs_data() - - def name(self): - return self._name() - def getName(self): - """ deprecated. @rtype: str """ - return self.name() - - def free(self): - self._free() - - def __repr__(self): - return 'LocalMinistep(name = %s, len = %d) at 0x%x' % (self.name(), len(self), self._address()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/local_obsdata.py b/ThirdParty/Ert/python/python/ert/enkf/local_obsdata.py deleted file mode 100644 index df9f8456c9..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/local_obsdata.py +++ /dev/null @@ -1,148 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype, LocalObsdataNode - - -class LocalObsdata(BaseCClass): - TYPE_NAME = "local_obsdata" - - _alloc = EnkfPrototype("void* local_obsdata_alloc(char*)", bind = False) - _free = EnkfPrototype("void local_obsdata_free(local_obsdata)") - _size = EnkfPrototype("int local_obsdata_get_size(local_obsdata)") - _has_node = EnkfPrototype("bool local_obsdata_has_node(local_obsdata, char*)") - _add_node = EnkfPrototype("bool local_obsdata_add_node(local_obsdata, local_obsdata_node)") - _del_node = EnkfPrototype("void local_obsdata_del_node(local_obsdata, char*)") - _clear = EnkfPrototype("void local_dataset_clear(local_obsdata)") - _name = EnkfPrototype("char* local_obsdata_get_name(local_obsdata)") - _iget_node = EnkfPrototype("local_obsdata_node_ref local_obsdata_iget(local_obsdata, int)") - _get_node = EnkfPrototype("local_obsdata_node_ref local_obsdata_get(local_obsdata, char*)") - _active_list = EnkfPrototype("active_list_ref local_obsdata_get_node_active_list(local_obsdata, char*)") - - def __init__(self, name , obs = None): - # The obs instance should be a EnkFObs instance; some circular dependency problems - # by importing it right away. It is not really optional, but it is made optional - # here to be able to give a decent error message for old call sites which did not - # supply the obs argument. - if obs is None: - msg = """ - -The LocalObsdata constructor has recently changed, as a second -argument you should pass the EnkFObs instance with all the -observations. You can typically get this instance from the ert main -object as: - - obs = ert.getObservations() - local_obs = LocalObsData("YOUR-KEY" , obs) - -""" - raise Exception( msg ) - - assert isinstance(name, str) - - c_ptr = self._alloc(name) - if c_ptr: - super(LocalObsdata, self).__init__(c_ptr) - self.initObservations( obs ) - else: - raise ValueError('Unable to construct LocalObsdata with name "%s" from given obs.' % name) - - - def initObservations(self , obs): - self.obs = obs - - def __len__(self): - """ @rtype: int """ - return self._size() - - - def __getitem__(self, key): - """ @rtype: LocalObsdataNode """ - if isinstance(key , int): - if key < 0: - key += len(self) - if 0 <= key < len(self): - node_ = self._iget_node(key) - node_.setParent(self) - return node_ - else: - raise IndexError('Invalid index, valid range is [0, %d)' % len(self)) - else: - if key in self: - node_ = self._get_node(key) - node_.setParent(self) - return node_ - else: - raise KeyError('Unknown key "%s".' % key) - - def __iter__(self): - cur = 0 - while cur < len(self): - yield self[cur] - cur += 1 - - def __contains__(self, item): - """ @rtype: bool """ - if isinstance(item, str): - return self._has_node(item) - elif isinstance(item, LocalObsdataNode): - return self._has_node(item.getKey()) - - return False - - def __delitem__(self, key): - assert isinstance(key, str) - if key in self: - self._del_node(key) - else: - raise KeyError('Unknown key "%s".' % key) - - def addNode(self, key, add_all_timesteps = True): - """ @rtype: LocalObsdataNode """ - assert isinstance(key, str) - if key in self.obs: - node = LocalObsdataNode(key , add_all_timesteps) - if node not in self: - node.convertToCReference(self) - self._add_node(node) - return node - else: - raise KeyError("Tried to add existing observation key:%s " % key) - else: - raise KeyError("The observation node: %s is not recognized observation key" % key) - - - def addNodeAndRange(self, key, step_1, step_2): - """ @rtype: LocalObsdataNode """ - """ The time range will be removed in the future... """ - assert isinstance(key, str) - assert isinstance(step_1, int) - assert isinstance(step_2, int) - node = self.addNode( key ) - node.addRange(step_1, step_2) - return node - - - def clear(self): - self._clear() - - - def addObsVector(self , obs_vector): - self.addNode( obs_vector.getObservationKey() ) - - def name(self): - return self._name() - def getName(self): - """ deprecated. @rtype: str """ - return self.name() - - def getActiveList(self, key): - """ @rtype: ActiveList """ - if key in self: - return self._active_list(key) - else: - raise KeyError('Local key "%s" not recognized.' % key) - - def free(self): - self._free() - - def __repr__(self): - return 'LocalObsdata(len = %d, name = %s) at 0x%x' % (len(self), self.name(), self._address()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/local_obsdata_node.py b/ThirdParty/Ert/python/python/ert/enkf/local_obsdata_node.py deleted file mode 100644 index c3b47f384b..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/local_obsdata_node.py +++ /dev/null @@ -1,59 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype - -class LocalObsdataNode(BaseCClass): - TYPE_NAME = "local_obsdata_node" - - _alloc = EnkfPrototype("void* local_obsdata_node_alloc(char* , bool)", bind = False) - _free = EnkfPrototype("void local_obsdata_node_free(local_obsdata_node)") - _get_key = EnkfPrototype("char* local_obsdata_node_get_key(local_obsdata_node)") - _add_range = EnkfPrototype("void local_obsdata_node_add_range(local_obsdata_node, int, int)") - _add_step = EnkfPrototype("void local_obsdata_node_add_tstep(local_obsdata_node, int)") - _tstep_active = EnkfPrototype("bool local_obsdata_node_tstep_active(local_obsdata_node, int)") - _all_timestep_active = EnkfPrototype("bool local_obsdata_node_all_timestep_active(local_obsdata_node)") - _set_all_timestep_active = EnkfPrototype("void local_obsdata_node_set_all_timestep_active(local_obsdata_node, bool)") - _get_active_list = EnkfPrototype("active_list_ref local_obsdata_node_get_active_list(local_obsdata_node)") - - def __init__(self, obs_key , all_timestep_active = True): - if isinstance(obs_key, str): - c_ptr = self._alloc(obs_key , all_timestep_active) - if c_ptr: - super(LocalObsdataNode, self).__init__(c_ptr) - else: - raise ArgumentError('Unable to construct LocalObsdataNode with key = "%s".' % obs_key) - else: - raise TypeError('LocalObsdataNode needs string, not %s.' % str(type(obs_key))) - - def key(self): - return self._get_key() - def getKey(self): - return self.key() - - def addRange(self, step_1, step_2): - assert isinstance(step_1, int) - assert isinstance(step_2, int) - self._add_range(step_1, step_2) - - - def addTimeStep(self , step): - self._add_step( step ) - - - def free(self): - self._free() - - def __repr__(self): - return 'LocalObsdataNode(key = %s) %s' % (self.key(), self._ad_str()) - - def tstepActive(self , tstep): - return self._tstep_active(tstep) - - - def getActiveList(self): - return self._get_active_list() - - def allTimeStepActive(self): - return self._all_timestep_active() - - def setAllTimeStepActive(self, flag): - return self._set_all_timestep_active( flag ) diff --git a/ThirdParty/Ert/python/python/ert/enkf/local_updatestep.py b/ThirdParty/Ert/python/python/ert/enkf/local_updatestep.py deleted file mode 100644 index 5552533d05..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/local_updatestep.py +++ /dev/null @@ -1,43 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype, LocalMinistep - -class LocalUpdateStep(BaseCClass): - TYPE_NAME = "local_updatestep" - - _alloc = EnkfPrototype("void local_updatestep_alloc(char*)", bind = False) - _size = EnkfPrototype("int local_updatestep_get_num_ministep(local_updatestep)") - _iget_ministep = EnkfPrototype("local_ministep_ref local_updatestep_iget_ministep(local_updatestep, int)") - _free = EnkfPrototype("void local_updatestep_free(local_updatestep)") - _attach_ministep = EnkfPrototype("void local_updatestep_add_ministep(local_updatestep, local_ministep)") - _name = EnkfPrototype("char* local_updatestep_get_name(local_updatestep)") - - def __init__(self, updatestep_key): - raise NotImplementedError("Class can not be instantiated directly!") - - def __len__(self): - """ @rtype: int """ - return self._size() - - def __getitem__(self, index): - """ @rtype: LocalMinistep """ - if not isinstance(index, int): - raise TypeError('Keys must be ints, not %s' % str(type(index))) - if index < 0: - index += len(self) - if 0 <= index < len(self): - return self._iget_ministep(index) - else: - raise IndexError('Invalid index, valid range: [0, %d)' % len(self)) - - def attachMinistep(self, ministep): - assert isinstance(ministep, LocalMinistep) - self._attach_ministep(ministep) - - def name(self): - return self._name() - def getName(self): - """ deprecated. @rtype: str """ - return self.name() - - def free(self): - self._free(self) diff --git a/ThirdParty/Ert/python/python/ert/enkf/meas_block.py b/ThirdParty/Ert/python/python/ert/enkf/meas_block.py deleted file mode 100644 index da4d6ec125..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/meas_block.py +++ /dev/null @@ -1,98 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.obs_data import ObsData -from ert.util import Matrix, IntVector , BoolVector - - -class MeasBlock(BaseCClass): - TYPE_NAME = "meas_block" - - _alloc = EnkfPrototype("void* meas_block_alloc( char* , bool_vector , int)", bind = False) - _free = EnkfPrototype("void meas_block_free( meas_block )") - _get_active_ens_size = EnkfPrototype("int meas_block_get_active_ens_size( meas_block )") - _get_total_ens_size = EnkfPrototype("int meas_block_get_total_ens_size( meas_block )") - _get_total_obs_size = EnkfPrototype("int meas_block_get_total_obs_size( meas_block )") - _iget_value = EnkfPrototype("double meas_block_iget( meas_block , int , int)") - _iset_value = EnkfPrototype("void meas_block_iset( meas_block , int , int , double)") - _iget_mean = EnkfPrototype("double meas_block_iget_ens_mean( meas_block , int )") - _iget_std = EnkfPrototype("double meas_block_iget_ens_std( meas_block , int )") - _iens_active = EnkfPrototype("bool meas_block_iens_active( meas_block , int )") - - def __init__(self , obs_key , obs_size , ens_mask): - assert(isinstance(ens_mask , BoolVector)) - c_ptr = self._alloc( obs_key , ens_mask , obs_size ) - if c_ptr: - super(MeasBlock , self).__init__(c_ptr) - else: - raise ValueError('Unable to construct MeasBlock.') - - def __str__(self): - s = "" - for iobs in range(self.getObsSize()): - s += "[" - for iens in range(self.getTotalEnsSize()): - if self.iensActive(iens): - s += "%6.3g " % self[iobs,iens] - else: - s += " X " - - s += "]\n" - return s - - def getObsSize(self): - return self._get_total_obs_size() - - - def getActiveEnsSize(self): - return self._get_active_ens_size() - - - def getTotalEnsSize(self): - return self._get_total_ens_size() - - - def __assert_index(self , index): - if isinstance(index , tuple): - iobs,iens = index - if not 0 <= iobs < self.getObsSize(): - raise IndexError("Invalid iobs value:%d Valid range: [0,%d)" % (iobs , self.getObsSize())) - - if not 0 <= iens < self.getTotalEnsSize(): - raise IndexError("Invalid iens value:%d Valid range: [0,%d)" % (iobs , self.getTotalEnsSize())) - - if not self.iensActive( iens ): - raise ValueError("Ensemble member:%d is not active - can not be accessed in the MeasBlock()" % iens) - - return iobs,iens - else: - raise TypeError("The index argument must be 2-tuple") - - - def __setitem__(self, index, value): - iobs , iens = self.__assert_index(index) - self._iset_value( iens , iobs , value ) - - - def __getitem__(self, index): - iobs,iens = self.__assert_index(index) - return self._iget_value( iens , iobs ) - - def iensActive(self , iens): - return self._iens_active( iens ) - - - def free(self): - self._free() - - - def igetMean(self , iobs): - if 0 <= iobs < self.getObsSize(): - return self._iget_mean(iobs) - else: - raise IndexError("Invalid observation index:%d valid range: [0,%d)" % (iobs , self.getObsSize())) - - def igetStd(self , iobs): - if 0 <= iobs < self.getObsSize(): - return self._iget_std(iobs) - else: - raise IndexError("Invalid observation index:%d valid range: [0,%d)" % (iobs , self.getObsSize())) diff --git a/ThirdParty/Ert/python/python/ert/enkf/meas_data.py b/ThirdParty/Ert/python/python/ert/enkf/meas_data.py deleted file mode 100644 index 14ca5ebf10..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/meas_data.py +++ /dev/null @@ -1,99 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.obs_data import ObsData -from ert.util import Matrix, IntVector - - -class MeasData(BaseCClass): - TYPE_NAME = "meas_data" - - _alloc = EnkfPrototype("void* meas_data_alloc(bool_vector)", bind = False) - _free = EnkfPrototype("void meas_data_free(meas_data)") - _get_active_obs_size = EnkfPrototype("int meas_data_get_active_obs_size(meas_data)") - _get_active_ens_size = EnkfPrototype("int meas_data_get_active_ens_size( meas_data )") - _get_total_ens_size = EnkfPrototype("int meas_data_get_total_ens_size( meas_data )") - _get_num_blocks = EnkfPrototype("int meas_data_get_num_blocks( meas_data )") - _has_block = EnkfPrototype("bool meas_data_has_block( meas_data , char* )") - _get_block = EnkfPrototype("meas_block_ref meas_data_get_block( meas_data , char*)") - _allocS = EnkfPrototype("matrix_obj meas_data_allocS(meas_data)") - _add_block = EnkfPrototype("meas_block_ref meas_data_add_block(meas_data, char* , int , int)") - _iget_block = EnkfPrototype("meas_block_ref meas_data_iget_block( meas_data , int)") - - _deactivate_outliers = EnkfPrototype("void enkf_analysis_deactivate_std_zero(obs_data, meas_data)", bind = False) - - def __init__(self, ens_mask): - c_ptr = self._alloc(ens_mask) - if c_ptr: - super(MeasData, self).__init__(c_ptr) - else: - raise ValueError('Unable to construct MeasData from given ensemble mask of type %s.' % str(type(ens_mask))) - - def __len__(self): - return self._get_num_blocks() - - - def __contains__(self , index): - if isinstance(index , str): - return self._has_block(index) - else: - raise TypeError('The in operator expects a string argument, got "%s".' % str(index)) - - - def __getitem__(self , index): - if isinstance(index , str): - if index in self: - return self._get_block(index) - else: - raise KeyError('The obs block "%s" is not recognized' % index) - elif isinstance(index,int): - if index < 0: - index += len(self) - - if 0 <= index < len(self): - return self._iget_block(index) - else: - raise IndexError("Index out of range, should have 0 <= %d < %d." % (index, len(self))) - else: - raise TypeError("The index variable must string or integer") - - - def __repr__(self): - fmt = 'MeasData(len = %d, total ens = %d, active obs = %d, active ens = %d) at 0x%x' - return fmt % (len(self), self.getTotalEnsSize(), - self.getActiveObsSize(), self.getActiveEnsSize(), self._address()) - - def __str__(self): - return '\n'.join([str(block) for block in self]) - - - def createS(self): - """ @rtype: Matrix """ - S = self._allocS() - if S is None: - raise ValueError("Failed to create S active size : [%d,%d]" % (self.getActiveEnsSize() , self.activeObsSize( ))) - return S - - - def deactivateZeroStdSamples(self, obs_data): - assert isinstance(obs_data, ObsData) - self._deactivate_outliers(obs_data, self) - - - def addBlock(self , obs_key , report_step , obs_size): - return self._add_block( obs_key , report_step , obs_size ) - - - def activeObsSize(self): - return self._get_active_obs_size() - - - def getActiveEnsSize(self): - return self._get_active_ens_size() - - - def getTotalEnsSize(self): - return self._get_total_ens_size() - - - def free(self): - self._free() diff --git a/ThirdParty/Ert/python/python/ert/enkf/model_config.py b/ThirdParty/Ert/python/python/ert/enkf/model_config.py deleted file mode 100644 index fc262a4ed9..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/model_config.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'model_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.ecl import EclSum -from ert.enkf import EnkfPrototype -from ert.sched import HistorySourceEnum, SchedFile -from ert.job_queue import ForwardModel -from ert.util import PathFormat - - -class ModelConfig(BaseCClass): - TYPE_NAME = "model_config" - - _free = EnkfPrototype("void model_config_free( model_config )") - _get_forward_model = EnkfPrototype("forward_model_ref model_config_get_forward_model(model_config)") - _get_max_internal_submit = EnkfPrototype("int model_config_get_max_internal_submit(model_config)") - _set_max_internal_submit = EnkfPrototype("void model_config_set_max_internal_submit(model_config, int)") - _get_case_table_file = EnkfPrototype("char* model_config_get_case_table_file(model_config)") - _get_runpath_as_char = EnkfPrototype("char* model_config_get_runpath_as_char(model_config)") - _select_runpath = EnkfPrototype("bool model_config_select_runpath(model_config, char*)") - _set_runpath = EnkfPrototype("void model_config_set_runpath(model_config, char*)") - _get_enspath = EnkfPrototype("char* model_config_get_enspath(model_config)") - _get_fs_type = EnkfPrototype("enkf_fs_type_enum model_config_get_dbase_type(model_config)") - _get_history = EnkfPrototype("history_ref model_config_get_history(model_config)") - _get_history_source = EnkfPrototype("history_source_enum model_config_get_history_source(model_config)") - _select_history = EnkfPrototype("bool model_config_select_history(model_config, history_source_enum, sched_file, ecl_sum)") - _has_history = EnkfPrototype("bool model_config_has_history(model_config)") - _gen_kw_export_file = EnkfPrototype("char* model_config_get_gen_kw_export_file(model_config)") - _runpath_requires_iterations = EnkfPrototype("bool model_config_runpath_requires_iter(model_config)") - _get_jobname_fmt = EnkfPrototype("char* model_config_get_jobname_fmt(model_config)") - _get_runpath_fmt = EnkfPrototype("path_fmt_ref model_config_get_runpath_fmt(model_config)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - - def hasHistory(self): - return self._has_history() - - def get_history_source(self): - """ @rtype: HistorySourceEnum """ - return self._get_history_source() - - def set_history_source(self, history_source, sched_file, refcase): - """ - @type history_source: HistorySourceEnum - @type sched_file: SchedFile - @type refcase: EclSum - @rtype: bool - """ - assert isinstance(history_source, HistorySourceEnum) - assert isinstance(sched_file, SchedFile) - assert isinstance(refcase, EclSum) - return self._select_history(history_source, sched_file, refcase) - - - def get_max_internal_submit(self): - """ @rtype: int """ - return self._get_max_internal_submit() - - def set_max_internal_submit(self, max_value): - self._get_max_internal_submit(max_value) - - def getForwardModel(self): - """ @rtype: ForwardModel """ - return self._get_forward_model().setParent(self) - - def get_case_table_file(self): - """ @rtype: str """ - return self._get_case_table_file() - - def getRunpathAsString(self): - """ @rtype: str """ - return self._get_runpath_as_char() - - def selectRunpath(self, path_key): - """ @rtype: bool """ - return self._select_runpath(path_key) - - def setRunpath(self, path_format): - self._set_runpath(path_format) - - def free(self): - self._free() - - def getFSType(self): - return self._get_fs_type() - - def getGenKWExportFile(self): - """ @rtype: str """ - return self._gen_kw_export_file() - - def runpathRequiresIterations(self): - """ @rtype: bool """ - return self._runpath_requires_iterations() - - def getJobnameFormat(self): - """ @rtype: str """ - return self._get_jobname_fmt() - - def getEnspath(self): - """ @rtype: str """ - return self._get_enspath() - - def getRunpathFormat(self): - """ @rtype: PathFormat """ - return self._get_runpath_fmt() diff --git a/ThirdParty/Ert/python/python/ert/enkf/node_id.py b/ThirdParty/Ert/python/python/ert/enkf/node_id.py deleted file mode 100644 index 66ed856cf9..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/node_id.py +++ /dev/null @@ -1,23 +0,0 @@ -from ctypes import Structure, c_int -from cwrap import Prototype - -class NodeId(Structure): - """ - NodeId is specified in enkf_types.h - """ - _fields_ = [("report_step", c_int), - ("iens", c_int)] - - def __init__(self, report_step, realization_number): - """ - @type report_step: int - @type realization_number: int - """ - super(NodeId, self).__init__(report_step, realization_number) - - def __repr__(self): - rs = self.report_step - ie = self.iens - return 'NodeId(report_step = %d, iens = %d)' % (rs, ie) - -Prototype.registerType( "node_id" , NodeId ) diff --git a/ThirdParty/Ert/python/python/ert/enkf/obs_block.py b/ThirdParty/Ert/python/python/ert/enkf/obs_block.py deleted file mode 100644 index aa8cc97887..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/obs_block.py +++ /dev/null @@ -1,65 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.util import Matrix - - -class ObsBlock(BaseCClass): - TYPE_NAME = "obs_block" - - _alloc = EnkfPrototype("void* obs_block_alloc(char*, int, matrix, bool, double)", bind = False) - _free = EnkfPrototype("void obs_block_free(obs_block)") - _total_size = EnkfPrototype("int obs_block_get_size( obs_block )") - _active_size = EnkfPrototype("int obs_block_get_active_size( obs_block )") - _iset = EnkfPrototype("void obs_block_iset( obs_block , int , double , double)") - _iget_value = EnkfPrototype("double obs_block_iget_value( obs_block , int)") - _iget_std = EnkfPrototype("double obs_block_iget_std( obs_block , int)") - - def __init__(self , obs_key , obs_size , global_std_scaling=1.0): - error_covar = None - error_covar_owner = False - c_pointer = self._alloc(obs_key , obs_size , error_covar , error_covar_owner, global_std_scaling) - super(ObsBlock, self).__init__(c_pointer) - - - def totalSize(self): - return self._total_size() - - def activeSize(self): - return self.active() - def active(self): - return self._active_size() - def __len__(self): - """Returns the total size""" - return self.totalSize() - - def __setitem__(self , index , value): - if len(value) != 2: - raise TypeError("The value argument must be a two element tuple: (value , std)") - d, std = value - - if isinstance(index , int): - if index < 0: - index += len(self) - if 0 <= index < len(self): - self._iset(index, d, std) - else: - raise IndexError("Invalid index: %d. Valid range: [0,%d)" % (index , len(self))) - else: - raise TypeError("The index item must be integer, not %s." % str(type(index))) - - - def __getitem__(self , index): - if isinstance(index , int): - if index < 0: - index += len(self) - if 0 <= index < len(self): - value = self._iget_value(index) - std = self._iget_std(index) - return (value,std) - else: - raise IndexError("Invalid index:%d - valid range: [0,%d)" % (index , len(self))) - else: - raise TypeError("The index item must be integer, not %s." % str(type(index))) - - def free(self): - self._free() diff --git a/ThirdParty/Ert/python/python/ert/enkf/obs_data.py b/ThirdParty/Ert/python/python/ert/enkf/obs_data.py deleted file mode 100644 index e3a7693e58..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/obs_data.py +++ /dev/null @@ -1,93 +0,0 @@ -from types import NoneType -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.util import Matrix - - -class ObsData(BaseCClass): - TYPE_NAME = "obs_data" - - _alloc = EnkfPrototype("void* obs_data_alloc(double)", bind = False) - _free = EnkfPrototype("void obs_data_free(obs_data)") - _total_size = EnkfPrototype("int obs_data_get_total_size(obs_data)") - _scale = EnkfPrototype("void obs_data_scale(obs_data, matrix, matrix, matrix, matrix, matrix)") - _scale_matrix = EnkfPrototype("void obs_data_scale_matrix(obs_data, matrix)") - _scale_Rmatrix = EnkfPrototype("void obs_data_scale_Rmatrix(obs_data, matrix)") - _iget_value = EnkfPrototype("double obs_data_iget_value(obs_data, int)") - _iget_std = EnkfPrototype("double obs_data_iget_std(obs_data, int)") - _add_block = EnkfPrototype("obs_block_ref obs_data_add_block(obs_data , char* , int , matrix , bool)") - _allocdObs = EnkfPrototype("matrix_obj obs_data_allocdObs(obs_data)") - _allocR = EnkfPrototype("matrix_obj obs_data_allocR(obs_data)") - _allocD = EnkfPrototype("matrix_obj obs_data_allocD(obs_data , matrix , matrix)") - _allocE = EnkfPrototype("matrix_obj obs_data_allocE(obs_data , rng , int)") - - def __init__(self, global_std_scaling=1.0): - c_pointer = self._alloc(global_std_scaling) - super(ObsData, self).__init__(c_pointer) - - def __len__(self): - """ @rtype: int """ - return self._total_size() - - def __getitem__(self , index): - if index < 0: - index += len(self) - - if 0 <= index < len(self): - value = self._iget_value( index ) - std = self._iget_std( index ) - return (value,std) - - raise IndexError("Invalid index:%d valid range: [0,%d)" % (index , len(self))) - - - def __str__(self): - s = "" - for pair in self: - s += "(%g, %g)\n" % pair - return s - - def __repr__(self): - return 'ObsData(total_size = %d) at 0x%x' % (len(self), self._address()) - - def addBlock(self , obs_key , obs_size): - error_covar = None - error_covar_owner = False - return self._add_block(obs_key , obs_size , error_covar , error_covar_owner) - - - def createDObs(self): - """ @rtype: Matrix """ - return self._allocdObs() - - def createR(self): - """ @rtype: Matrix """ - return self._allocR() - - def createD(self , E , S): - """ @rtype: Matrix """ - return self._allocD(E , S) - - def createE( self , rng , active_ens_size): - """ @rtype: Matrix """ - return self._allocE(rng , active_ens_size) - - def scaleMatrix(self, m): - self._scale_matrix( m ) - - - def scaleRMatrix(self, R): - self._scale_Rmatrix( R ) - - - def scale(self, S, E=None, D=None, R=None, D_obs=None): - assert isinstance(S, Matrix) - assert isinstance(E, (Matrix, NoneType)) - assert isinstance(D, (Matrix, NoneType)) - assert isinstance(R, (Matrix, NoneType)) - assert isinstance(D_obs, (Matrix, NoneType)) - self._scale(S, E, D, R, D_obs) - - - def free(self): - self._free() diff --git a/ThirdParty/Ert/python/python/ert/enkf/observations/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/enkf/observations/CMakeLists.txt deleted file mode 100644 index d93d1d65f6..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/observations/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - block_observation.py - block_data_config.py - gen_observation.py - obs_vector.py - summary_observation.py -) - -add_python_package("python.ert.enkf.observations" ${PYTHON_INSTALL_PREFIX}/ert/enkf/observations "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/enkf/observations/__init__.py b/ThirdParty/Ert/python/python/ert/enkf/observations/__init__.py deleted file mode 100644 index 485088ff71..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/observations/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .summary_observation import SummaryObservation -from .gen_observation import GenObservation -from .block_data_config import BlockDataConfig -from .block_observation import BlockObservation -from .obs_vector import ObsVector diff --git a/ThirdParty/Ert/python/python/ert/enkf/observations/block_data_config.py b/ThirdParty/Ert/python/python/ert/enkf/observations/block_data_config.py deleted file mode 100644 index fe29b02556..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/observations/block_data_config.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# This file is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import NodeId, FieldConfig -from ert.enkf import EnkfPrototype -import ctypes - -class BlockDataConfig(BaseCClass): - TYPE_NAME = "block_data_config" - - def __init__(self): - raise NotImplementedError('Cannot instantiate BlockDataConfig!') - - @classmethod - def from_param(cls , instance): - if instance is None: - return ctypes.c_void_p() - elif isinstance(instance , FieldConfig): - return FieldConfig.from_param( instance ) - - # The Container class which is used to support summary based - # source in the BLOCK_OBS configuration is not yet supported - # in Python. - - #elif isinstance(instance , ContainerConfig): - # return ContainerConfig.from_param( instance ) - else: - raise ValueError("Currently ONLY field data is supported") diff --git a/ThirdParty/Ert/python/python/ert/enkf/observations/block_observation.py b/ThirdParty/Ert/python/python/ert/enkf/observations/block_observation.py deleted file mode 100644 index 81b6ef673f..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/observations/block_observation.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'block_obs.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf import NodeId, FieldConfig -from ert.enkf.observations import BlockDataConfig - - -class BlockObservation(BaseCClass): - TYPE_NAME = "block_obs" - - _alloc = EnkfPrototype("void* block_obs_alloc( char* , block_data_config , ecl_grid )", bind = False) - _free = EnkfPrototype("void block_obs_free( block_obs )") - _iget_i = EnkfPrototype("int block_obs_iget_i(block_obs, int)") - _iget_j = EnkfPrototype("int block_obs_iget_j( block_obs, int)") - _iget_k = EnkfPrototype("int block_obs_iget_k( block_obs , int)") - _get_size = EnkfPrototype("int block_obs_get_size( block_obs )") - _get_std = EnkfPrototype("double block_obs_iget_std( block_obs, int )") - _get_std_scaling = EnkfPrototype("double block_obs_iget_std_scaling( block_obs, int )") - _update_std_scaling = EnkfPrototype("void block_obs_update_std_scale(block_obs , double , active_list)") - _get_value = EnkfPrototype("double block_obs_iget_value( block_obs, int)") - _get_depth = EnkfPrototype("double block_obs_iget_depth( block_obs, int)") - _add_field_point = EnkfPrototype("void block_obs_append_field_obs( block_obs, int,int,int,double,double)") - _add_summary_point = EnkfPrototype("void block_obs_append_summary_obs( block_obs, int, int, int, double, double)") - _iget_data = EnkfPrototype("double block_obs_iget_data(block_obs, void*, int, node_id)") - - - - def __init__(self , obs_key , data_config , grid): - c_ptr = self._alloc( obs_key , data_config , grid ) - super(BlockObservation, self).__init__(c_ptr) - - - def getCoordinate(self, index): - """ @rtype: tuple of (int, int, int) """ - i = self._iget_i(index) - j = self._iget_j(index) - k = self._iget_k(index) - return i, j, k - - def __len__(self): - """ @rtype: int """ - return self._get_size() - - def __iter__(self): - cur = 0 - while cur < len(self): - yield cur - cur += 1 - - def addPoint(self , i,j,k , value , std , sum_key = None): - if sum_key is None: - self._add_field_point(i,j,k,value,std) - else: - self._add_summary_point(i,j,k,sum_key,value,std) - - - def getValue(self, index): - """ @rtype: float """ - return self._get_value(index) - - def getStd(self, index): - """ @rtype: float """ - return self._get_std(index) - - def getStdScaling(self , index): - """ @rtype: float """ - return self._get_std_scaling(index) - - def updateStdScaling(self , factor , active_list): - self._update_std_scaling(factor , active_list) - - - def getDepth(self, index): - """ @rtype: float """ - return self._get_depth(index) - - def getData(self, state, obs_index, node_id): - """ - @type state: c_void_p - @type obs_index: int - @type node_id: NodeId - @rtype: float """ - - return self._iget_data(state, obs_index, node_id) - - - def free(self): - self._free() - - def __repr__(self): - return 'BlockObservation(size = %d) at 0x%x' % (len(self), self._address()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/observations/gen_observation.py b/ThirdParty/Ert/python/python/ert/enkf/observations/gen_observation.py deleted file mode 100644 index 4214868546..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/observations/gen_observation.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'gen_observation.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import os.path - -from cwrap import BaseCClass -from ert.util import IntVector -from ert.enkf import EnkfPrototype -from ert.enkf import GenDataConfig - - -class GenObservation(BaseCClass): - TYPE_NAME = "gen_obs" - - _alloc = EnkfPrototype("void* gen_obs_alloc__(gen_data_config , char*)", bind = False) - _free = EnkfPrototype("void gen_obs_free(gen_obs)") - _load = EnkfPrototype("void gen_obs_load_observation(gen_obs , char*)") - _scalar_set = EnkfPrototype("void gen_obs_set_scalar(gen_obs , double , double)") - _get_std = EnkfPrototype("double gen_obs_iget_std(gen_obs, int)") - _get_value = EnkfPrototype("double gen_obs_iget_value(gen_obs, int)") - _get_std_scaling = EnkfPrototype("double gen_obs_iget_std_scaling(gen_obs, int)") - _get_size = EnkfPrototype("int gen_obs_get_size(gen_obs)") - _get_data_index = EnkfPrototype("int gen_obs_get_obs_index(gen_obs, int)") - _load_data_index = EnkfPrototype("void gen_obs_load_data_index(gen_obs , char*)") - _add_data_index = EnkfPrototype("void gen_obs_attach_data_index(gen_obs , int_vector)") - _update_std_scaling = EnkfPrototype("void gen_obs_update_std_scale(gen_obs , double , active_list)") - - def __init__(self , obs_key , data_config , scalar_value = None , obs_file = None , data_index = None): - c_ptr = self._alloc( data_config , obs_key ) - if c_ptr: - super(GenObservation, self).__init__(c_ptr) - else: - raise ValueError('Unable to construct GenObservation with given obs_key and data_config!') - - if scalar_value is None and obs_file is None: - raise ValueError("Exactly one the scalar_value and obs_file arguments must be present") - - if scalar_value is not None and obs_file is not None: - raise ValueError("Exactly one the scalar_value and obs_file arguments must be present") - - if obs_file is not None: - if not os.path.isfile( obs_file ): - raise IOError("The file with observation data:%s does not exist" % obs_file ) - else: - self._load( obs_file ) - else: - obs_value , obs_std = scalar_value - self._scalar_set( obs_value , obs_std ) - - if not data_index is None: - if os.path.isfile( data_index ): - self._load_data_index( data_index ) - else: - index_list = IntVector.active_list( data_index ) - self._add_data_index( index_list ) - - - def __len__(self): - return self._get_size() - - def __getitem__(self , obs_index): - if obs_index < 0: - obs_index += len(self) - - if 0 <= obs_index < len(self): - return (self.getValue(obs_index) , self.getStandardDeviation(obs_index)) - else: - raise IndexError("Invalid index. Valid range: [0,%d)" % len(self)) - - - def getValue(self, obs_index): - """ @rtype: float """ - return self._get_value(obs_index) - - def getStandardDeviation(self, obs_index): - """ @rtype: float """ - return self._get_std(obs_index) - - def getStdScaling(self, obs_index): - """ @rtype: float """ - return self._get_std_scaling(obs_index) - - def updateStdScaling(self , factor , active_list): - self._update_std_scaling(factor , active_list) - - - def getSize(self): - """ @rtype: float """ - return len(self) - - def getIndex(self, obs_index): - """ @rtype: int """ - return self.getDataIndex( obs_index ) - - def getDataIndex(self, obs_index): - return self._get_data_index(obs_index) - - def free(self): - self._free() - - def __repr__(self): - si = len(self) - ad = self._ad_str() - return 'GenObservation(size = %d) %s' % (si, ad) diff --git a/ThirdParty/Ert/python/python/ert/enkf/observations/obs_vector.py b/ThirdParty/Ert/python/python/ert/enkf/observations/obs_vector.py deleted file mode 100644 index 76823de656..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/observations/obs_vector.py +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'obs_vector.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.config import EnkfConfigNode -from ert.enkf.enums import EnkfObservationImplementationType -from ert.enkf.observations import BlockObservation, SummaryObservation, GenObservation - - -class ObsVector(BaseCClass): - TYPE_NAME = "obs_vector" - - _alloc = EnkfPrototype("void* obs_vector_alloc(enkf_obs_impl_type, char*, enkf_config_node, int)", bind = False) - _free = EnkfPrototype("void obs_vector_free( obs_vector )") - _get_state_kw = EnkfPrototype("char* obs_vector_get_state_kw( obs_vector )") - _get_key = EnkfPrototype("char* obs_vector_get_key( obs_vector )") - _iget_node = EnkfPrototype("void* obs_vector_iget_node( obs_vector, int)") - _get_num_active = EnkfPrototype("int obs_vector_get_num_active( obs_vector )") - _iget_active = EnkfPrototype("bool obs_vector_iget_active( obs_vector, int)") - _get_impl_type = EnkfPrototype("enkf_obs_impl_type obs_vector_get_impl_type( obs_vector)") - _install_node = EnkfPrototype("void obs_vector_install_node(obs_vector, int, void*)") - _get_next_active_step = EnkfPrototype("int obs_vector_get_next_active_step(obs_vector, int)") - _has_data = EnkfPrototype("bool obs_vector_has_data(obs_vector , bool_vector , enkf_fs)") - _get_config_node = EnkfPrototype("enkf_config_node_ref obs_vector_get_config_node(obs_vector)") - _get_total_chi2 = EnkfPrototype("double obs_vector_total_chi2(obs_vector, enkf_fs, int)") - _get_obs_key = EnkfPrototype("char* obs_vector_get_obs_key(obs_vector)") - _get_step_list = EnkfPrototype("int_vector_ref obs_vector_get_step_list(obs_vector)") - _create_local_node = EnkfPrototype("local_obsdata_node_obj obs_vector_alloc_local_node(obs_vector)") - - def __init__(self, observation_type, observation_key, config_node, num_reports): - """ - @type observation_type: EnkfObservationImplementationType - @type observation_key: str - @type config_node: EnkfConfigNode - @type num_reports: int - """ - assert isinstance(observation_type, EnkfObservationImplementationType) - assert isinstance(observation_key, str) - assert isinstance(config_node, EnkfConfigNode) - assert isinstance(num_reports, int) - c_ptr = self._alloc(observation_type, observation_key, config_node, num_reports) - super(ObsVector, self).__init__(c_ptr) - - - def getDataKey(self): - """ @rtype: str """ - return self._get_state_kw() - - def getObservationKey(self): - """ @rtype: str """ - return self.getKey() - - def getKey(self): - return self._get_key() - - def getObsKey(self): - return self._get_obs_key() - - - def getNode(self, index): - """ @rtype: SummaryObservation or BlockObservation or GenObservation""" - - pointer = self._iget_node(index) - - node_type = self.getImplementationType() - if node_type == EnkfObservationImplementationType.SUMMARY_OBS: - return SummaryObservation.createCReference(pointer, self) - elif node_type == EnkfObservationImplementationType.BLOCK_OBS: - return BlockObservation.createCReference(pointer, self) - elif node_type == EnkfObservationImplementationType.GEN_OBS: - return GenObservation.createCReference(pointer, self) - else: - raise AssertionError("Node type '%s' currently not supported!" % node_type) - - - def __iter__(self): - """ Iterate over active report steps; return node""" - cur = -1 - run = True - for step in self.getStepList(): - yield self.getNode( step ) - - - - def getStepList(self): - """ - Will return an IntVector with the active report steps. - """ - return self._get_step_list() - - def activeStep(self): - """Assuming the observation is only active for one report step, this - method will return that report step - if it is active for more - than one report step the method will raise an exception. - """ - step_list = self.getStepList() - if len(step_list): - return step_list[0] - else: - raise ValueError("The activeStep() method can *ONLY* be called for obervations with one active step") - - - def getActiveCount(self): - """ @rtype: int """ - return len(self) - def __len__(self): - return self._get_num_active() - - def isActive(self, index): - """ @rtype: bool """ - return self._iget_active(index) - - def getNextActiveStep(self, previous_step=-1): - """ @rtype: int """ - return self._get_next_active_step(previous_step) - - def getImplementationType(self): - """ @rtype: EnkfObservationImplementationType """ - return self._get_impl_type() - - def installNode(self, index, node): - assert isinstance(node, SummaryObservation) - node.convertToCReference(self) - self._install_node(index, node.from_param(node)) - - def getConfigNode(self): - """ @rtype: EnkfConfigNode """ - return self._get_config_node().setParent(self) - - - def createLocalObs(self): - """ - Will create a LocalObsDataNode instance with all timesteps set. - """ - return self._create_local_node() - - - def hasData(self, active_mask, fs): - """ @rtype: bool """ - return self._has_data(active_mask, fs) - - def free(self): - self._free() - - def __repr__(self): - dk = 'data_key = %s' % self.getDataKey() - kk = 'key = %s' % self.getKey() - ok = 'obs_key = %s' % self.getObsKey() - na = 'num_active = %d' % len(self) - return 'ObsVector(%s, %s, %s, %s) %s' % (na, kk, ok, dk, self._ad_str()) - - def getTotalChi2(self, fs, realization_number): - """ @rtype: float """ - return self._get_total_chi2(fs, realization_number) diff --git a/ThirdParty/Ert/python/python/ert/enkf/observations/summary_observation.py b/ThirdParty/Ert/python/python/ert/enkf/observations/summary_observation.py deleted file mode 100644 index f71e1a3c91..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/observations/summary_observation.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'summary_observation.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype - - -class SummaryObservation(BaseCClass): - TYPE_NAME = "summary_obs" - - _alloc = EnkfPrototype("void* summary_obs_alloc(char*, char*, double, double, char*, double)", bind = False) - _free = EnkfPrototype("void summary_obs_free(summary_obs)") - _get_value = EnkfPrototype("double summary_obs_get_value(summary_obs)") - _get_std = EnkfPrototype("double summary_obs_get_std(summary_obs)") - _get_std_scaling = EnkfPrototype("double summary_obs_get_std_scaling(summary_obs)") - _get_summary_key = EnkfPrototype("char* summary_obs_get_summary_key(summary_obs)") - _update_std_scale = EnkfPrototype("void summary_obs_update_std_scale(summary_obs , double , active_list)") - - - def __init__(self, summary_key, observation_key, value, std, auto_corrf_name=None, auto_corrf_param=0.0): - assert isinstance(summary_key, str) - assert isinstance(observation_key, str) - assert isinstance(value, float) - assert isinstance(std, float) - - if auto_corrf_name is not None: - assert isinstance(auto_corrf_name, str) - - assert isinstance(auto_corrf_param, float) - c_ptr = self._alloc(summary_key, observation_key, value, std, auto_corrf_name, auto_corrf_param) - if c_ptr: - super(SummaryObservation, self).__init__(c_ptr) - else: - raise ValueError('Unable to construct SummaryObservation with given configuration!') - - def getValue(self): - """ @rtype: float """ - return self._get_value() - - def getStandardDeviation(self): - """ @rtype: float """ - return self._get_std() - - def getStdScaling(self , index = 0): - """ @rtype: float """ - return self._get_std_scaling() - - def __len__(self): - return 1 - - - def getSummaryKey(self): - """ @rtype: str """ - return self._get_summary_key() - - - def updateStdScaling(self , factor , active_list): - self._update_std_scale(factor , active_list) - - - def free(self): - self._free() - - def __repr__(self): - sk = self.getSummaryKey() - va = self.getValue() - sd = self.getStandardDeviation() - sc = self.getStdScaling() - ad = self._address() - fmt = 'SummaryObservation(key = %s, value = %f, std = %f, std_scaling = %f) at 0x%x' - return fmt % (sk, va, sd, sc, ad) diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/enkf/plot/CMakeLists.txt deleted file mode 100644 index 4ce39c00f6..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - block_observation_data_fetcher.py - data_fetcher.py - ensemble_block_data_fetcher.py - ensemble_data_fetcher.py - ensemble_gen_data_fetcher.py - ensemble_gen_kw_fetcher.py - observation_data_fetcher.py - observation_gen_data_fetcher.py - pca_fetcher.py - refcase_data_fetcher.py -) - -add_python_package("python.ert.enkf.plot" ${PYTHON_INSTALL_PREFIX}/ert/enkf/plot "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/__init__.py b/ThirdParty/Ert/python/python/ert/enkf/plot/__init__.py deleted file mode 100644 index 75ecfa73b1..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -from .data_fetcher import DataFetcher -from .observation_data_fetcher import ObservationDataFetcher -from .refcase_data_fetcher import RefcaseDataFetcher -from .ensemble_data_fetcher import EnsembleDataFetcher -from .ensemble_block_data_fetcher import EnsembleBlockDataFetcher -from .block_observation_data_fetcher import BlockObservationDataFetcher -from .ensemble_gen_kw_fetcher import EnsembleGenKWFetcher -from .ensemble_gen_data_fetcher import EnsembleGenDataFetcher -from .observation_gen_data_fetcher import ObservationGenDataFetcher -from .pca_fetcher import PcaDataFetcher \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/block_observation_data_fetcher.py b/ThirdParty/Ert/python/python/ert/enkf/plot/block_observation_data_fetcher.py deleted file mode 100644 index a5ea24e4ee..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/block_observation_data_fetcher.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'block_observation_data_fetcher.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from ert.enkf import EnkfObservationImplementationType -from ert.enkf.observations import BlockObservation -from ert.enkf.plot import DataFetcher - - -class BlockObservationDataFetcher(DataFetcher): - def __init__(self, ert): - super(BlockObservationDataFetcher, self).__init__(ert) - self.__selected_report_step_index = None - - def setSelectedReportStepIndex(self, index): - self.__selected_report_step_index = index - - def fetchSupportedKeys(self): - observations = self.ert().getObservations() - string_list = observations.getTypedKeylist(EnkfObservationImplementationType.BLOCK_OBS) - return [key for key in string_list] - - def __fetchObservationData(self, block_observation): - assert isinstance(block_observation, BlockObservation) - - data = { - "continuous": False, - "x": [], - "y": [], - "std": [], - "min_y": None, - "max_y": None, - "min_x": None, - "max_x": None - } - - for index in block_observation: - std = block_observation.getStd(index) - y = block_observation.getDepth(index) - x = block_observation.getValue(index) - - data["std"].append(std) - data["y"].append(y) - data["x"].append(x) - - adjusted_x = self.adjustX(x, std) - - if data["min_x"] is None or data["min_x"] > adjusted_x: - data["min_x"] = adjusted_x - - if data["max_x"] is None or data["max_x"] < x + std: - data["max_x"] = x + std - - - if data["min_y"] is None or data["min_y"] > y: - data["min_y"] = y - - if data["max_y"] is None or data["max_y"] < y: - data["max_y"] = y - - return data - - @staticmethod - def adjustX(x, std): - if x >= 0: - return max(0, x - std) - - return x - std - - def hasData(self, key): - """ @rtype: bool """ - observations = self.ert().getObservations() - if not observations.hasKey(key): - return False - - return observations[key].getActiveCount() > 0 - - def fetchData(self, key, case=None): - observations = self.ert().getObservations() - assert observations.hasKey(key) - - observation_vector = observations[key] - - report_step_data = [] - for report_step in observation_vector: - block_observation = observation_vector.getNode(report_step) - data = self.__fetchObservationData(block_observation) - data["report_step"] = report_step - report_step_data.append(data) - - - if self.__selected_report_step_index is not None: - return report_step_data[self.__selected_report_step_index] - else: - return report_step_data - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/data_fetcher.py b/ThirdParty/Ert/python/python/ert/enkf/plot/data_fetcher.py deleted file mode 100644 index b67769f2dc..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/data_fetcher.py +++ /dev/null @@ -1,30 +0,0 @@ -from ert.enkf.enkf_main import EnKFMain - - -class DataFetcher(object): - def __init__(self, ert): - super(DataFetcher, self).__init__() - assert isinstance(ert, EnKFMain) - self.__ert = ert - self.__supported_keys = None - - def fetchData(self, key, case=None): - raise NotImplementedError() - - def ert(self): - return self.__ert - - def fetchSupportedKeys(self): - raise NotImplementedError() - - def getSupportedKeys(self): - if self.__supported_keys is None: - self.__supported_keys = self.fetchSupportedKeys() - return self.__supported_keys - - def supportsKey(self, key): - return key in self.getSupportedKeys() - - - - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_block_data_fetcher.py b/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_block_data_fetcher.py deleted file mode 100644 index 6b9e763088..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_block_data_fetcher.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'ensemble_block_data_fetcher.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from ert.enkf.enums import ErtImplType -from ert.enkf.plot import DataFetcher -from ert.enkf.plot_data import PlotBlockDataLoader, PlotBlockData - - -class EnsembleBlockDataFetcher(DataFetcher): - def __init__(self, ert): - super(EnsembleBlockDataFetcher, self).__init__(ert) - self.__selected_report_step_index = None - - def __fetchSimulationData(self, block_data): - """ - @type block_data: PlotBlockData - @rtype dict - """ - data = { - "x": [], - "y": [], - "min_x_values": [], - "max_x_values": [], - "min_y": None, - "max_y": None, - "min_x": None, - "max_x": None - } - - depth_vector = block_data.getDepth() - - for depth in depth_vector: - data["y"].append(depth) - data["min_x_values"].append(None) - data["max_x_values"].append(None) - - - min_y = min(data["y"]) - max_y = max(data["y"]) - - if data["min_y"] is None or data["min_y"] > min_y: - data["min_y"] = min_y - - if data["max_y"] is None or data["max_y"] < max_y: - data["max_y"] = max_y - - for block_vector in block_data: - x = [] - data["x"].append(x) - - for index in range(len(block_vector)): - value = block_vector[index] - x.append(value) - if data["min_x"] is None or data["min_x"] > value: - data["min_x"] = value - - if data["max_x"] is None or data["max_x"] < value: - data["max_x"] = value - - if data["min_x_values"][index] is None or data["min_x_values"][index] > value: - data["min_x_values"][index] = value - - if data["max_x_values"][index] is None or data["max_x_values"][index] < value: - data["max_x_values"][index] = value - - return data - - def fetchData(self, key, case=None): - enkf_fs = self.ert().getEnkfFsManager().getFileSystem(case) - observations = self.ert().getObservations() - assert observations.hasKey(key) - - observation_vector = observations[key] - - loader = PlotBlockDataLoader(observation_vector) - - report_step_data = [] - for report_step in observation_vector: - block_data = loader.load(enkf_fs, report_step) - data = self.__fetchSimulationData(block_data) - data["report_step"] = report_step - - report_step_data.append(data) - - if self.__selected_report_step_index is not None: - return report_step_data[self.__selected_report_step_index] - else: - return report_step_data - - def fetchSupportedKeys(self): - string_list = self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.SUMMARY) - return [key for key in string_list] - - def setSelectedReportStepIndex(self, index): - self.__selected_report_step_index = index - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_data_fetcher.py b/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_data_fetcher.py deleted file mode 100644 index d8828b631a..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_data_fetcher.py +++ /dev/null @@ -1,73 +0,0 @@ -from ert.enkf import EnsembleConfig -from ert.enkf.plot_data import EnsemblePlotData -from ert.enkf.enums import ErtImplType -from ert.enkf.plot.data_fetcher import DataFetcher - - -class EnsembleDataFetcher(DataFetcher): - def __init__(self, ert): - super(EnsembleDataFetcher, self).__init__(ert) - - def fetchSupportedKeys(self): - """ @rtype: list of str """ - return [key for key in self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.SUMMARY)] - - - def getEnsembleConfigNode(self, key): - """ @rtype: EnsembleConfig """ - ensemble_config = self.ert().ensembleConfig() - assert key in ensemble_config - return ensemble_config.getNode(key) - - - def fetchData(self, key, case=None): - ensemble_config_node = self.getEnsembleConfigNode(key) - enkf_fs = self.ert().getEnkfFsManager().getFileSystem(case) - ensemble_plot_data = EnsemblePlotData(ensemble_config_node, enkf_fs) - - data = { - "x": [], - "y": [], - "min_y_values": [], - "max_y_values": [], - "min_y": None, - "max_y": None, - "min_x": None, - "max_x": None - } - - time_map = enkf_fs.getTimeMap() - - for index in range(1, len(time_map)): - data["x"].append(time_map[index].ctime()) - data["min_y_values"].append(None) - data["max_y_values"].append(None) - - data["min_x"] = data["x"][0] - data["max_x"] = data["x"][len(data["x"]) - 1] - - - for vector in ensemble_plot_data: - y = [] - data["y"].append(y) - - # skip index 0 (not a valid simulation value...) - for index in range(len(vector) - 1): - if vector.isActive(index + 1): - y_value = vector.getValue(index + 1) - y.append(y_value) - - if data["min_y"] is None or data["min_y"] > y_value: - data["min_y"] = y_value - - if data["max_y"] is None or data["max_y"] < y_value: - data["max_y"] = y_value - - - if data["min_y_values"][index] is None or data["min_y_values"][index] > y_value: - data["min_y_values"][index] = y_value - - if data["max_y_values"][index] is None or data["max_y_values"][index] < y_value: - data["max_y_values"][index] = y_value - - return data diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_gen_data_fetcher.py b/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_gen_data_fetcher.py deleted file mode 100644 index c248169c36..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_gen_data_fetcher.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'ensemble_gen_data_fetcher.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from ert.enkf.plot_data import EnsemblePlotGenData -from ert.enkf.plot import DataFetcher - - -class EnsembleGenDataFetcher(DataFetcher): - def __init__(self, ert): - super(EnsembleGenDataFetcher, self).__init__(ert) - - def fetchSupportedKeys(self): - gen_data_list = [] - - return gen_data_list - - def getEnsembleConfigNode(self, key): - """ @rtype: EnsembleConfig """ - ensemble_config = self.ert().ensembleConfig() - assert key in ensemble_config - return ensemble_config.getNode(key) - - def fetchData(self, key, case=None): - key, report_step = key.split("@") - report_step = int(report_step) - - ensemble_config_node = self.getEnsembleConfigNode(key) - enkf_fs = self.ert().getEnkfFsManager().getFileSystem(case) - ensemble_plot_gen_data = EnsemblePlotGenData(ensemble_config_node, enkf_fs, report_step) - - data = {"x": [], - "y": [], - "min_y_values": [value for value in ensemble_plot_gen_data.getMinValues()], - "max_y_values": [value for value in ensemble_plot_gen_data.getMaxValues()], - "min_y": None, - "max_y": None, - "min_x": 0, - "max_x": None} - - data["x"] = [index for index in range(len(data["min_y_values"]))] - data["max_x"] = len(data["min_y_values"]) - 1 - - for vector in ensemble_plot_gen_data: - y = [] - data["y"].append(y) - - for value in vector: - y.append(value) - - if data["min_y"] is None or data["min_y"] > value: - data["min_y"] = value - - if data["max_y"] is None or data["max_y"] < value: - data["max_y"] = value - - - - return data - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_gen_kw_fetcher.py b/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_gen_kw_fetcher.py deleted file mode 100644 index 2dd7e1a942..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/ensemble_gen_kw_fetcher.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'ensemble_gen_kw_fetcher.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from ert.enkf.config.gen_kw_config import GenKwConfig -from ert.enkf.enums.ert_impl_type_enum import ErtImplType -from ert.enkf.plot import DataFetcher -from ert.enkf.plot_data import EnsemblePlotGenKW - - -class EnsembleGenKWFetcher(DataFetcher): - def __init__(self, ert): - super(EnsembleGenKWFetcher, self).__init__(ert) - - def fetchSupportedKeys(self): - gen_kw_keys = self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.GEN_KW) - gen_kw_list = [] - for key in gen_kw_keys: - enkf_config_node = self.ert().ensembleConfig().getNode(key) - model_config = enkf_config_node.getModelConfig() - assert isinstance(model_config, GenKwConfig) - - model_keys = model_config.getKeyWords() - for key_word in model_keys: - gen_kw_list.append("%s:%s" % (key, key_word)) - - return gen_kw_list - - - def getEnsembleConfigNode(self, key): - """ @rtype: EnsembleConfig """ - ensemble_config = self.ert().ensembleConfig() - assert key in ensemble_config - return ensemble_config.getNode(key) - - - def fetchData(self, key, case=None): - key, keyword = key.split(":") - ensemble_config_node = self.getEnsembleConfigNode(key) - enkf_fs = self.ert().getEnkfFsManager().getFileSystem(case) - ensemble_plot_gen_kw = EnsemblePlotGenKW(ensemble_config_node, enkf_fs) - keyword_index = ensemble_plot_gen_kw.getIndexForKeyword(keyword) - - use_log_scale = ensemble_plot_gen_kw.shouldUseLogScale(keyword_index) - - data = {"x": [0], - "y": [], - "min_y": None, - "max_y": None, - "min_x": 0, - "max_x": 0, - "use_log_scale": use_log_scale} - - for vector in ensemble_plot_gen_kw: - y = [] - data["y"].append(y) - - if len(vector) > keyword_index: - value = vector.getValue(keyword_index) - y.append(value) - - if data["min_y"] is None or data["min_y"] > value: - data["min_y"] = value - - if data["max_y"] is None or data["max_y"] < value: - data["max_y"] = value - - return data - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/observation_data_fetcher.py b/ThirdParty/Ert/python/python/ert/enkf/plot/observation_data_fetcher.py deleted file mode 100644 index c6e4830e81..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/observation_data_fetcher.py +++ /dev/null @@ -1,91 +0,0 @@ -from ert.enkf import EnkfObservationImplementationType -from ert.enkf.enums import ErtImplType -from ert.enkf.plot import DataFetcher - - -class ObservationDataFetcher(DataFetcher): - def __init__(self, ert): - super(ObservationDataFetcher, self).__init__(ert) - - def getObservationKeys(self): - observations = self.ert().getObservations() - keys = observations.getTypedKeylist(EnkfObservationImplementationType.SUMMARY_OBS) - keys = sorted(keys) - return keys - - def fetchSupportedKeys(self): - """ @rtype: list of str """ - return sorted([key for key in self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.SUMMARY)]) - - def __getObservationData(self, key, data): - observations = self.ert().getObservations() - assert observations.hasKey(key) - - observation_data = observations[key] - active_count = observation_data.getActiveCount() - - history_length = self.ert().getHistoryLength() - for index in range(0, history_length): - if observation_data.isActive(index): - x_value = int(observations.getObservationTime(index).ctime()) - data["x"].append(x_value) - - #: :type: SummaryObservation - node = observation_data.getNode(index) - - y_value = node.getValue() - std = node.getStandardDeviation() - data["y"].append(float(y_value)) - data["std"].append(float(std)) - - if data["min_x"] is None or data["min_x"] > x_value: - data["min_x"] = x_value - - if data["max_x"] is None or data["max_x"] < x_value: - data["max_x"] = x_value - - - adjusted_y = self.adjustY(y_value, std) - - if data["min_y"] is None or data["min_y"] > adjusted_y: - data["min_y"] = adjusted_y - - if data["max_y"] is None or data["max_y"] < y_value + std: - data["max_y"] = y_value + std - - if active_count == 1: - data["continuous"] = False - - @staticmethod - def adjustY(y, std): - if y >= 0: - return max(0, y - std) - - return y - std - - - def fetchData(self, key, case=None): - obs_keys = self.ert().ensembleConfig().getNode(key).getObservationKeys() - history_length = self.ert().getHistoryLength() - - data = {"continuous": True, - "x": None, - "y": None, - "std": None, - "min_y": None, - "max_y": None, - "min_x": None, - "max_x": None} - - if len(obs_keys) == 0: - return data - - data["x"] = [] - data["y"] = [] - data["std"] = [] - - for obs_key in obs_keys: - self.__getObservationData(obs_key, data) - - return data - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/observation_gen_data_fetcher.py b/ThirdParty/Ert/python/python/ert/enkf/plot/observation_gen_data_fetcher.py deleted file mode 100644 index 31c9a2eee5..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/observation_gen_data_fetcher.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'observation_gen_data_fetcher.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from ert.enkf.enums.ert_impl_type_enum import ErtImplType -from ert.enkf.plot import DataFetcher - - -class ObservationGenDataFetcher(DataFetcher): - def __init__(self, ert): - super(ObservationGenDataFetcher, self).__init__(ert) - - def fetchSupportedKeys(self): - gen_data_keys = self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.GEN_DATA) - gen_data_list = [] - for key in gen_data_keys: - obs_keys = self.ert().ensembleConfig().getNode(key).getObservationKeys() - for obs_key in obs_keys: - obs_vector = self.ert().getObservations()[obs_key] - for report_step in obs_vector.getStepList(): - gen_data_list.append("%s@%d" % (key, report_step)) - - return gen_data_list - - def __getObservationData(self, key, report_step): - data = {"continuous": True, - "x": [], - "y": [], - "std": [], - "min_y": None, - "max_y": None, - "min_x": None, - "max_x": None} - - observations = self.ert().getObservations() - assert observations.hasKey(key) - - gen_obs = observations[key].getNode(report_step) - - size = gen_obs.getSize() - - data["min_x"] = 0 - data["max_x"] = size - 1 - for index in range(0, size): - std = gen_obs.getStandardDeviation(index) - data["std"].append(std) - y_value = gen_obs.getValue(index) - data["y"].append(y_value) - - adjusted_y = self.adjustY(y_value, std) - - if data["min_y"] is None or data["min_y"] > adjusted_y: - data["min_y"] = adjusted_y - - if data["max_y"] is None or data["max_y"] < y_value + std: - data["max_y"] = y_value + std - - obs_index = gen_obs.getIndex(index) - data["x"].append(obs_index) - - return data - - - def getObsKeyForKey(self, key, key_report_step): - obs_keys = self.ert().ensembleConfig().getNode(key).getObservationKeys() - for obs_key in obs_keys: - obs_vector = self.ert().getObservations()[obs_key] - for report_step in obs_vector.getStepList(): - if report_step == key_report_step: - return obs_key - - raise UserWarning("Observation key for key '%s' not found!" % key) - - - def getAllObsKeysForKey(self, key): - key, report_step = key.split("@") - return self.ert().ensembleConfig().getNode(key).getObservationKeys() - - - def hasData(self, key): - """ @rtype: bool """ - key, report_step = key.split("@") - observations = self.ert().getObservations() - obs_key = self.getObsKeyForKey(key, int(report_step)) - if not observations.hasKey(obs_key): - return False - - return observations[obs_key].getActiveCount() > 0 - - def fetchData(self, key, case=None): - key, report_step = key.split("@") - - key_report_step = int(report_step) - obs_key = self.getObsKeyForKey(key, key_report_step) - - return self.__getObservationData(obs_key, key_report_step) - - - @staticmethod - def adjustY(y, std): - if y >= 0: - return max(0, y - std) - - return y - std diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/pca_fetcher.py b/ThirdParty/Ert/python/python/ert/enkf/plot/pca_fetcher.py deleted file mode 100644 index adbb256f34..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/pca_fetcher.py +++ /dev/null @@ -1,182 +0,0 @@ -from ert.enkf.plot import DataFetcher, ObservationGenDataFetcher, BlockObservationDataFetcher, EnsembleDataFetcher -from ert.enkf.plot_data import PcaPlotData -from ert.enkf.enums import RealizationStateEnum, EnkfObservationImplementationType -from ert.enkf import LocalObsdata, LocalObsdataNode, EnkfLinalg, MeasData, ObsData -from ert.util import Matrix, BoolVector, DoubleVector - - -class PcaDataFetcher(DataFetcher): - def __init__(self, ert): - super(PcaDataFetcher, self).__init__(ert) - self.__prior_singular_values = None - - def fetchSupportedKeys(self): - summary_keys = EnsembleDataFetcher(self.ert()).getSupportedKeys() - - keys = [] - for key in summary_keys: - obs_keys = self.ert().ensembleConfig().getNode(key).getObservationKeys() - if len(obs_keys) > 0: - keys.append(key) - - keys += BlockObservationDataFetcher(self.ert()).getSupportedKeys() - keys += ObservationGenDataFetcher(self.ert()).getSupportedKeys() - - return keys - - - def truncationOrNumberOfComponents(self, truncation_or_ncomp): - """ @rtype: (float, int) """ - truncation = -1 - ncomp = -1 - - if truncation_or_ncomp < 1: - truncation = truncation_or_ncomp - else: - ncomp = int(truncation_or_ncomp) - - return truncation, ncomp - - - def calculatePrincipalComponent(self, fs, local_obsdata, truncation_or_ncomp=3): - pc = Matrix(1, 1) - pc_obs = Matrix(1, 1) - singular_values = DoubleVector() - - state_map = fs.getStateMap() - ens_mask = BoolVector(False, self.ert().getEnsembleSize()) - state_map.selectMatching(ens_mask, RealizationStateEnum.STATE_HAS_DATA) - active_list = ens_mask.createActiveList( ) - - if len(ens_mask) > 0: - meas_data = MeasData(ens_mask) - obs_data = ObsData() - - self.ert().getObservations().getObservationAndMeasureData(fs, local_obsdata, active_list, meas_data, obs_data) - - meas_data.deactivateZeroStdSamples(obs_data) - - active_size = len(obs_data) - - if active_size > 0: - S = meas_data.createS() - D_obs = obs_data.createDObs() - - truncation, ncomp = self.truncationOrNumberOfComponents(truncation_or_ncomp) - - obs_data.scale(S, D_obs=D_obs) - EnkfLinalg.calculatePrincipalComponents(S, D_obs, truncation, ncomp, pc, pc_obs, singular_values) - if self.__prior_singular_values is None: - self.__prior_singular_values = singular_values - else: - for row in range(pc.rows()): - factor = singular_values[row]/self.__prior_singular_values[row] - pc.scaleRow( row , factor ) - pc_obs.scaleRow( row , factor ) - - - return PcaPlotData(local_obsdata.getName(), pc , pc_obs , singular_values) - return None - - - - def getAllObsKeys(self): - observations = self.ert().getObservations() - summary_obs_keys = observations.getTypedKeylist(EnkfObservationImplementationType.SUMMARY_OBS) - gen_data_obs_keys = observations.getTypedKeylist(EnkfObservationImplementationType.GEN_OBS) - block_obs_keys = observations.getTypedKeylist(EnkfObservationImplementationType.BLOCK_OBS) - - summary_obs_keys = [key for key in summary_obs_keys] - gen_data_obs_keys = [key for key in gen_data_obs_keys] - block_obs_keys = [key for key in block_obs_keys] - - return summary_obs_keys + gen_data_obs_keys + block_obs_keys - - - def getObsKeys(self, data_key): - ensemble_data_fetcher = EnsembleDataFetcher(self.ert()) - block_observation_data_fetcher = BlockObservationDataFetcher(self.ert()) - gen_data_observation_data_fetcher = ObservationGenDataFetcher(self.ert()) - - if ensemble_data_fetcher.supportsKey(data_key): - return self.ert().ensembleConfig().getNode(data_key).getObservationKeys() - elif block_observation_data_fetcher.supportsKey(data_key): - return [data_key] - elif gen_data_observation_data_fetcher.supportsKey(data_key): - return gen_data_observation_data_fetcher.getAllObsKeysForKey(data_key) - - - def filterObsKeys(self, obs_keys, fs): - active_mask = BoolVector(True, self.ert().getEnsembleSize()) - ert_obs = self.ert().getObservations() - - result = [] - for obs_key in obs_keys: - obsVector = ert_obs[obs_key] - if obsVector.hasData(active_mask, fs): - result.append(obs_key) - return result - - - def fetchData(self, obs_keys, case=None): - data = {"x": None, - "y": None, - "obs_y": None, - "min_y": None, - "max_y": None, - "min_x": None, - "max_x": None} - - fs = self.ert().getEnkfFsManager().getFileSystem(case) - obs_keys = self.filterObsKeys(obs_keys, fs) - - step_1 = 0 - step_2 = self.ert().getHistoryLength() - - local_obsdata = LocalObsdata("PCA Observations %s" % case) - - for obs_key in obs_keys: - if not obs_key in local_obsdata: - obs_node = LocalObsdataNode(obs_key) - obs_node.addRange(step_1, step_2) - local_obsdata.addNode(obs_node) - - if len(local_obsdata) > 0: - pca_data = self.calculatePrincipalComponent(fs, local_obsdata) - - if pca_data is not None: - data["x"] = [] - data["y"] = [] - data["obs_y"] = [] - - data["min_x"] = 1 - data["max_x"] = len(pca_data) - - component_number = 0 - for pca_vector in pca_data: - component_number += 1 - data["x"].append(component_number) - - obs_y = pca_vector.getObservation() - - if data["min_y"] is None or data["min_y"] > obs_y: - data["min_y"] = obs_y - - if data["max_y"] is None or data["max_y"] < obs_y: - data["max_y"] = obs_y - - data["obs_y"].append(obs_y) - for index, value in enumerate(pca_vector): - if len(data["y"]) == index: - data["y"].append([]) - - y = data["y"][index] - y.append(value) - - if data["min_y"] is None or data["min_y"] > value: - data["min_y"] = value - - if data["max_y"] is None or data["max_y"] < value: - data["max_y"] = value - - return data diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot/refcase_data_fetcher.py b/ThirdParty/Ert/python/python/ert/enkf/plot/refcase_data_fetcher.py deleted file mode 100644 index cc4d1ce158..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot/refcase_data_fetcher.py +++ /dev/null @@ -1,81 +0,0 @@ -from ert.ecl import EclSum, EclSumVector, EclSumNode -from ert.enkf.enums import ErtImplType -from ert.enkf.plot.data_fetcher import DataFetcher - - -class RefcaseDataFetcher(DataFetcher): - def __init__(self, ert): - super(RefcaseDataFetcher, self).__init__(ert) - self.report_times = {} - - - def hasRefcase(self): - """ @rtype: bool """ - return self.ert().eclConfig().hasRefcase() - - def getRefCase(self): - """ @rtype: EclSum """ - return self.ert().eclConfig().getRefcase() - - def getSummaryKeys(self): - """ @rtype: StringList """ - return self.ert().ensembleConfig().getKeylistFromImplType(ErtImplType.SUMMARY) - - - def fetchData(self, key, case=None): - data = {"x": None, - "y": None, - "min_y": None, - "max_y": None, - "min_x": None, - "max_x": None} - - if not self.hasRefcase(): - return data - - - refcase = self.getRefCase() - vector = refcase.get_vector(key, report_only=False) - - data["x"] = [] - data["y"] = [] - - for index in range(1, len(vector)): - node = vector[index] - - x_value = self.getReportStepTimeFromRefcase(refcase, node.report_step) - data["x"].append(int(x_value)) - - if data["min_x"] is None or data["min_x"] > x_value: - data["min_x"] = x_value - - if data["max_x"] is None or data["max_x"] < x_value: - data["max_x"] = x_value - - - value = node.value - data["y"].append(float(value)) - - if data["min_y"] is None or data["min_y"] > value: - data["min_y"] = value - - if data["max_y"] is None or data["max_y"] < value: - data["max_y"] = value - - return data - - - def getReportStepTimeFromRefcase(self, refcase, report_step): - if not report_step in self.report_times: - self.report_times[report_step] = EclSum.cNamespace().get_report_time(refcase, report_step).ctime() - - return self.report_times[report_step] - - - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/enkf/plot_data/CMakeLists.txt deleted file mode 100644 index b56289400e..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - ensemble_plot_data.py - ensemble_plot_data_vector.py - ensemble_plot_gen_data.py - ensemble_plot_gen_data_vector.py - ensemble_plot_gen_kw.py - ensemble_plot_gen_kw_vector.py - pca_plot_data.py - pca_plot_vector.py - plot_block_data.py - plot_block_data_loader.py - plot_block_vector.py -) - -add_python_package("python.ert.enkf.plot_data" ${PYTHON_INSTALL_PREFIX}/ert/enkf/plot_data "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/__init__.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/__init__.py deleted file mode 100644 index 5e957583af..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .ensemble_plot_data_vector import EnsemblePlotDataVector -from .ensemble_plot_data import EnsemblePlotData -from .plot_block_vector import PlotBlockVector -from .plot_block_data import PlotBlockData -from .plot_block_data_loader import PlotBlockDataLoader -from .ensemble_plot_gen_data_vector import EnsemblePlotGenDataVector -from .ensemble_plot_gen_data import EnsemblePlotGenData -from .ensemble_plot_gen_kw_vector import EnsemblePlotGenKWVector -from .ensemble_plot_gen_kw import EnsemblePlotGenKW -from .pca_plot_vector import PcaPlotVector -from .pca_plot_data import PcaPlotData - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_data.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_data.py deleted file mode 100644 index 937bfa4804..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_data.py +++ /dev/null @@ -1,54 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.config import EnkfConfigNode -from ert.enkf.enkf_fs import EnkfFs -from ert.util import BoolVector - - -class EnsemblePlotData(BaseCClass): - TYPE_NAME = "ensemble_plot_data" - - _alloc = EnkfPrototype("void* enkf_plot_data_alloc(enkf_config_node)", bind = False) - _load = EnkfPrototype("void enkf_plot_data_load(ensemble_plot_data, enkf_fs, char*, bool_vector)") - _size = EnkfPrototype("int enkf_plot_data_get_size(ensemble_plot_data)") - _get = EnkfPrototype("ensemble_plot_data_vector_ref enkf_plot_data_iget(ensemble_plot_data, int)") - _free = EnkfPrototype("void enkf_plot_data_free(ensemble_plot_data)") - - - def __init__(self, ensemble_config_node, file_system=None, user_index=None, input_mask=None): - assert isinstance(ensemble_config_node, EnkfConfigNode) - - c_pointer = self._alloc(ensemble_config_node) - super(EnsemblePlotData, self).__init__(c_pointer) - - if not file_system is None: - self.load(file_system, user_index, input_mask) - - - def load(self, file_system, user_index=None, input_mask=None): - assert isinstance(file_system, EnkfFs) - if not input_mask is None: - assert isinstance(input_mask, BoolVector) - - self._load(file_system, user_index, input_mask) - - def __len__(self): - """ @rtype: int """ - return self._size() - - def __getitem__(self, index): - """ @rtype: EnsemblePlotDataVector """ - return self._get(index) - - def __iter__(self): - cur = 0 - while cur < len(self): - yield self[cur] - cur += 1 - - - def free(self): - self._free() - - def __repr__(self): - return 'EnsemblePlotData(size = %d) %s' % (len(self), self._ad_str()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_data_vector.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_data_vector.py deleted file mode 100644 index 2293dc854d..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_data_vector.py +++ /dev/null @@ -1,35 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.util import CTime - - - -class EnsemblePlotDataVector(BaseCClass): - TYPE_NAME = "ensemble_plot_data_vector" - - _size = EnkfPrototype("int enkf_plot_tvector_size(ensemble_plot_data_vector)") - _get_value = EnkfPrototype("double enkf_plot_tvector_iget_value(ensemble_plot_data_vector, int)") - _get_time = EnkfPrototype("time_t enkf_plot_tvector_iget_time(ensemble_plot_data_vector, int)") - _is_active = EnkfPrototype("bool enkf_plot_tvector_iget_active(ensemble_plot_data_vector, int)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def __len__(self): - """ @rtype: int """ - return self._size() - - def getValue(self, index): - """ @rtype: float """ - return self._get_value(index) - - def getTime(self, index): - """ @rtype: CTime """ - return self._get_time(index) - - def isActive(self, index): - """ @rtype: bool """ - return self._is_active(index) - - def __repr__(self): - return 'EnsemblePlotDataVector(size = %d) %s' % (len(self), self._ad_str()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_data.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_data.py deleted file mode 100644 index 35e94f54e8..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_data.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'ensemble_plot_gen_data.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.config import EnkfConfigNode -from ert.enkf.enkf_fs import EnkfFs -from ert.enkf.enums.ert_impl_type_enum import ErtImplType -from ert.util import BoolVector, DoubleVector - - -class EnsemblePlotGenData(BaseCClass): - TYPE_NAME = "ensemble_plot_gen_data" - - _alloc = EnkfPrototype("void* enkf_plot_gendata_alloc(enkf_config_node)", bind = False) - _size = EnkfPrototype("int enkf_plot_gendata_get_size(ensemble_plot_gen_data)") - _load = EnkfPrototype("void enkf_plot_gendata_load(ensemble_plot_gen_data, enkf_fs, int, bool_vector)") - _get = EnkfPrototype("ensemble_plot_gen_data_vector_ref enkf_plot_gendata_iget(ensemble_plot_gen_data, int)") - _min_values = EnkfPrototype("double_vector_ref enkf_plot_gendata_get_min_values(ensemble_plot_gen_data)") - _max_values = EnkfPrototype("double_vector_ref enkf_plot_gendata_get_max_values(ensemble_plot_gen_data)") - _free = EnkfPrototype("void enkf_plot_gendata_free(ensemble_plot_gen_data)") - - def __init__(self, ensemble_config_node, file_system, report_step, input_mask=None): - assert isinstance(ensemble_config_node, EnkfConfigNode) - assert ensemble_config_node.getImplementationType() == ErtImplType.GEN_DATA - - c_ptr = self._alloc(ensemble_config_node) - if c_ptr: - super(EnsemblePlotGenData, self).__init__(c_ptr) - else: - raise ValueError('Unable to construct EnsemplePlotGenData from given config node!') - - self.__load(file_system, report_step, input_mask) - - - def __load(self, file_system, report_step, input_mask=None): - assert isinstance(file_system, EnkfFs) - if not input_mask is None: - assert isinstance(input_mask, BoolVector) - - self._load(file_system, report_step, input_mask) - - def __len__(self): - """ @rtype: int """ - return self._size() - - def __getitem__(self, index): - """ @rtype: EnsemblePlotGenDataVector """ - return self._get(index) - - def __iter__(self): - cur = 0 - while cur < len(self): - yield self[cur] - cur += 1 - - - def getMaxValues(self): - """ @rtype: DoubleVector """ - return self._max_values().setParent(self) - - def getMinValues(self): - """ @rtype: DoubleVector """ - return self._min_values().setParent(self) - - def free(self): - self._free() - - def __repr__(self): - return 'EnsemblePlotGenData(size = %d) %s' % (len(self), self._ad_str()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_data_vector.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_data_vector.py deleted file mode 100644 index e2590b7755..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_data_vector.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'ensemble_plot_gen_data_vector.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype - -class EnsemblePlotGenDataVector(BaseCClass): - TYPE_NAME = "ensemble_plot_gen_data_vector" - - _size = EnkfPrototype("int enkf_plot_genvector_get_size(ensemble_plot_gen_data_vector)") - _get_value = EnkfPrototype("double enkf_plot_genvector_iget(ensemble_plot_gen_data_vector, int)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def __len__(self): - """ @rtype: int """ - return self._size() - - def __repr__(self): - return 'EnsemblePlotGenDataVector(size = %d) %s' % (len(self), self._ad_str()) - - def getValue(self, index): - """ @rtype: float """ - return self[index] - - def __iter__(self): - cur = 0 - while cur < len(self): - yield self[cur] - cur += 1 - - def __getitem__(self, index): - """ @rtype: float """ - return self._get_value(index) diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_kw.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_kw.py deleted file mode 100644 index 9a4df23674..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_kw.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'ensemble_plot_gen_kw.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.config import EnkfConfigNode -from ert.enkf.enkf_fs import EnkfFs -from ert.enkf.enums.ert_impl_type_enum import ErtImplType -from ert.util import BoolVector -from ert.enkf.plot_data import EnsemblePlotGenKWVector - - -class EnsemblePlotGenKW(BaseCClass): - TYPE_NAME = "ensemble_plot_gen_kw" - - _alloc = EnkfPrototype("void* enkf_plot_gen_kw_alloc(enkf_config_node)", bind = False) - _size = EnkfPrototype("int enkf_plot_gen_kw_get_size(ensemble_plot_gen_kw)") - _load = EnkfPrototype("void enkf_plot_gen_kw_load(ensemble_plot_gen_kw, enkf_fs, bool, int, bool_vector)") - _get = EnkfPrototype("ensemble_plot_gen_kw_vector_ref enkf_plot_gen_kw_iget(ensemble_plot_gen_kw, int)") - _iget_key = EnkfPrototype("char* enkf_plot_gen_kw_iget_key(ensemble_plot_gen_kw, int)") - _get_keyword_count = EnkfPrototype("int enkf_plot_gen_kw_get_keyword_count(ensemble_plot_gen_kw)") - _should_use_log_scale = EnkfPrototype("bool enkf_plot_gen_kw_should_use_log_scale(ensemble_plot_gen_kw, int)") - _free = EnkfPrototype("void enkf_plot_gen_kw_free(ensemble_plot_gen_kw)") - - def __init__(self, ensemble_config_node, file_system, input_mask=None): - assert isinstance(ensemble_config_node, EnkfConfigNode) - assert ensemble_config_node.getImplementationType() == ErtImplType.GEN_KW - - c_pointer = self._alloc(ensemble_config_node) - super(EnsemblePlotGenKW, self).__init__(c_pointer) - - self.__load(file_system, input_mask) - - - def __load(self, file_system, input_mask=None): - assert isinstance(file_system, EnkfFs) - if not input_mask is None: - assert isinstance(input_mask, BoolVector) - - self._load(file_system, True, 0, input_mask) - - def __len__(self): - """ @rtype: int """ - return self._size() - - def __getitem__(self, index): - """ @rtype: EnsemblePlotGenKWVector """ - return self._get(index) - - def __iter__(self): - cur = 0 - while cur < len(self): - yield self[cur] - cur += 1 - - def getKeyWordCount(self): - """ @rtype: int """ - return self._get_keyword_count() - - def getKeyWordForIndex(self, index): - """ @rtype: str """ - return self._iget_key(index) - - def getIndexForKeyword(self, keyword): - """ @rtype: int """ - for index in range(self.getKeyWordCount()): - kw = self.getKeyWordForIndex(index) - if kw == keyword: - return index - return None - - def shouldUseLogScale(self, index): - """ @rtype: bool """ - return bool(self._should_use_log_scale(index)) - - def free(self): - self._free() - - def __repr__(self): - return 'EnsemblePlotGenKW(size = %d) %s' % (len(self), self._ad_str()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_kw_vector.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_kw_vector.py deleted file mode 100644 index 532677223b..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/ensemble_plot_gen_kw_vector.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'ensemble_plot_gen_kw_vector.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype - -class EnsemblePlotGenKWVector(BaseCClass): - TYPE_NAME = "ensemble_plot_gen_kw_vector" - - _size = EnkfPrototype("int enkf_plot_gen_kw_vector_get_size(ensemble_plot_gen_kw_vector)") - _get_value = EnkfPrototype("double enkf_plot_gen_kw_vector_iget(ensemble_plot_gen_kw_vector, int)") - - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def __len__(self): - """ @rtype: int """ - return self._size() - - def getValue(self, index): - """ @rtype: float """ - return self[index] - - def __iter__(self): - cur = 0 - while cur < len(self): - yield self[cur] - cur += 1 - - def __getitem__(self, index): - """ @rtype: float """ - return self._get_value(index) - - def __repr__(self): - return 'EnsemblePlotGenKWVector(size = %d) %s' % (len(self), self._ad_str()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/pca_plot_data.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/pca_plot_data.py deleted file mode 100644 index 5bad403329..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/pca_plot_data.py +++ /dev/null @@ -1,63 +0,0 @@ -from cwrap import BaseCClass - -from ert.enkf import EnkfPrototype -from ert.util import Matrix -from ert.enkf.plot_data import PcaPlotVector - - -class PcaPlotData(BaseCClass): - TYPE_NAME = "pca_plot_data" - - _alloc = EnkfPrototype("void* pca_plot_data_alloc(char*, matrix, matrix , double_vector)", bind = False) - _component_count = EnkfPrototype("int pca_plot_data_get_size(pca_plot_data)") - _realization_count = EnkfPrototype("int pca_plot_data_get_ens_size(pca_plot_data)") - _get = EnkfPrototype("pca_plot_vector_ref pca_plot_data_iget_vector(pca_plot_data, int)") - _get_name = EnkfPrototype("char* pca_plot_data_get_name(pca_plot_data)") - _get_singular_values = EnkfPrototype("double_vector_ref pca_plot_data_get_singular_values(pca_plot_data)") - _free = EnkfPrototype("void pca_plot_data_free(pca_plot_data)") - - def __init__(self, name, principal_component_matrix, observation_principal_component_matrix, singular_values): - assert isinstance(name, str) - assert isinstance(principal_component_matrix, Matrix) - assert isinstance(observation_principal_component_matrix, Matrix) - - c_pointer = self._alloc(name, principal_component_matrix, observation_principal_component_matrix , singular_values) - super(PcaPlotData, self).__init__(c_pointer) - - def componentCount(self): - return len(self) - def realizationCount(self): - return self._realization_count() - def name(self): - return self._get_name() - - def __len__(self): - """ @rtype: int """ - return self._component_count() - - - def __getitem__(self, index): - """ @rtype: PcaPlotVector """ - assert isinstance(index, int) - return self._get(index).setParent(self) - - def __iter__(self): - cur = 0 - while cur < len(self): - yield self[cur] - cur += 1 - - def getSingularValues(self): - """ @rtype: DoubleVector """ - return self._get_singular_values().setParent(self) - - def free(self): - self._free() - - def __repr__(self): - nm = self.name() - cc = len(self) - rc = self.realizationCount() - ad = self._ad_str() - fmt = 'PcaPlotData(name = %s, components = %d, realizations = %d) %s' - return fmt % (nm, cc, rc, ad) diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/pca_plot_vector.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/pca_plot_vector.py deleted file mode 100644 index 3db1936c22..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/pca_plot_vector.py +++ /dev/null @@ -1,64 +0,0 @@ -from cwrap import BaseCClass - -from ert.enkf import EnkfPrototype -from ert.util import Matrix - - -class PcaPlotVector(BaseCClass): - TYPE_NAME = "pca_plot_vector" - - _alloc = EnkfPrototype("void* pca_plot_vector_alloc(int, matrix, matrix)", bind = False) - _size = EnkfPrototype("int pca_plot_vector_get_size(pca_plot_vector)") - _get = EnkfPrototype("double pca_plot_vector_iget_sim_value(pca_plot_vector, int)") - _get_obs = EnkfPrototype("double pca_plot_vector_get_obs_value(pca_plot_vector)") - _get_singular_value = EnkfPrototype("double pca_plot_vector_get_singular_value(pca_plot_vector)") - _free = EnkfPrototype("void pca_plot_vector_free(pca_plot_vector)") - - - def __init__(self, component, principal_component_matrix, observation_principal_component_matrix): - assert isinstance(component, int) - assert isinstance(principal_component_matrix, Matrix) - assert isinstance(observation_principal_component_matrix, Matrix) - - c_pointer = self._alloc(component, principal_component_matrix, observation_principal_component_matrix) - super(PcaPlotVector, self).__init__(c_pointer) - - - def __len__(self): - """ @rtype: int """ - return self._size() - - - def __getitem__(self, index): - """ - @type index: int - @rtype: float - """ - assert isinstance(index, int) - return self._get(index) - - def __iter__(self): - cur = 0 - while cur < len(self): - yield self[cur] - cur += 1 - - def getObservation(self): - """ @rtype: float """ - return self._get_obs() - - def getSingularValue(self): - """ @rtype: float """ - return self._get_singular_value() - - - def free(self): - self._free() - - def __repr__(self): - si = len(self) - ob = self.getObservation() - sv = self.getSingularValue() - ad = self._ad_str() - fmt = 'PcaPlotVector(size = %d, observation = %f, singular = %f) %s' - return fmt % (si, ob, sv, ad) diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_data.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_data.py deleted file mode 100644 index 1e270aa954..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_data.py +++ /dev/null @@ -1,44 +0,0 @@ -from ert.enkf.plot_data import PlotBlockVector -from ert.util import DoubleVector - - -class PlotBlockData(object): - - def __init__(self, depth_vector): - """ - @type depth_vector: DoubleVector - """ - assert isinstance(depth_vector, DoubleVector) - self.__depth_vector = depth_vector - self.__plot_block_vectors = {} - - - def __len__(self): - """ @rtype: int """ - return len(self.__plot_block_vectors) - - - def __getitem__(self, index): - """ - @type index: int - @rtype: PlotBlockVector - """ - return self.__plot_block_vectors[index] - - def __iter__(self): - cur = 0 - keys = sorted(self.__plot_block_vectors.keys()) - while cur < len(keys): - yield self[keys[cur]] - cur += 1 - - def getDepth(self): - """ @rtype: DoubleVector """ - return self.__depth_vector - - - def addPlotBlockVector(self, vector): - """ - @type vector: PlotBlockVector - """ - self.__plot_block_vectors[vector.getRealizationNumber()] = vector diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_data_loader.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_data_loader.py deleted file mode 100644 index d59f2aee65..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_data_loader.py +++ /dev/null @@ -1,98 +0,0 @@ -from ert.enkf import RealizationStateEnum, EnkfNode, ErtImplType, NodeId -from ert.enkf.plot_data import PlotBlockData, PlotBlockVector -from ert.util import DoubleVector, BoolVector, ThreadPool - - -class PlotBlockDataLoader(object): - - def __init__(self, obs_vector): - """ - @type obs_vector: ObsVector - """ - if obs_vector is None: - raise ArgumentError('Cannot construct PlotBlockDataLoader without obs_vector. Was None.') - super(PlotBlockDataLoader, self).__init__() - self.__obs_vector = obs_vector - self.__permutation_vector = None - - - def getBlockObservation(self, report_step): - """ @rtype: BlockObservation """ - return self.__obs_vector.getNode(report_step) - - - def getDepthValues(self, report_step): - """ @rtype: DoubleVector """ - block_obs = self.getBlockObservation(report_step) - - depth = DoubleVector() - for index in block_obs: - value = block_obs.getDepth(index) - depth.append(value) - - return depth - - - def load(self, fs, report_step, input_mask=None): - """ - @type fs: EnkfFs - @type report_step: int - @type input_mask: BoolVector - @rtype: PlotBlockData - """ - - state_map = fs.getStateMap() - ensemble_size = len(state_map) - - if not input_mask is None: - mask = BoolVector.copy(input_mask) - else: - mask = BoolVector(False, ensemble_size) - - state_map.selectMatching(mask, RealizationStateEnum.STATE_HAS_DATA) - - depth = self.getDepthValues(report_step) - - self.__permutation_vector = depth.permutationSort() - depth.permute(self.__permutation_vector) - - plot_block_data = PlotBlockData(depth) - - thread_pool = ThreadPool() - for index in range(ensemble_size): - if mask[index]: - thread_pool.addTask(self.loadVector, plot_block_data, fs, report_step, index) - - thread_pool.nonBlockingStart() - thread_pool.join() - - return plot_block_data - - - def loadVector(self, plot_block_data, fs, report_step, realization_number): - """ - @type plot_block_data: PlotBlockData - @type fs: EnkfFs - @type report_step: int - @type realization_number: int - @rtype PlotBlockVector - """ - config_node = self.__obs_vector.getConfigNode() - - is_private_container = config_node.getImplementationType() == ErtImplType.CONTAINER - data_node = EnkfNode(config_node, private=is_private_container) - - node_id = NodeId(report_step, realization_number) - - if data_node.tryLoad(fs, node_id): - block_obs = self.getBlockObservation(report_step) - - data = DoubleVector() - for index in range(len(block_obs)): - value = block_obs.getData(data_node.valuePointer(), index, node_id) - data.append(value) - data.permute(self.__permutation_vector) - - plot_block_vector = PlotBlockVector(realization_number, data) - plot_block_data.addPlotBlockVector(plot_block_vector) - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_vector.py b/ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_vector.py deleted file mode 100644 index 855bdbb8a1..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_data/plot_block_vector.py +++ /dev/null @@ -1,39 +0,0 @@ -from ert.util import DoubleVector - - -class PlotBlockVector(object): - def __init__(self, realization_number, data): - """ - @type realization_number: int - @type data: DoubleVector - """ - super(PlotBlockVector, self).__init__() - - assert isinstance(data, DoubleVector) - - self.__realization_number = realization_number - self.__data = data - - def __len__(self): - """ @rtype: int """ - return len(self.__data) - - - def __getitem__(self, index): - """ @rtype: float """ - assert isinstance(index, int) - return self.__data[index] - - - def __iter__(self): - """ @rtype: float """ - cur = 0 - while cur < len(self): - yield self[cur] - cur += 1 - - - def getRealizationNumber(self): - """ @rtype: int """ - return self.__realization_number - diff --git a/ThirdParty/Ert/python/python/ert/enkf/plot_settings.py b/ThirdParty/Ert/python/python/ert/enkf/plot_settings.py deleted file mode 100644 index b9c7600590..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/plot_settings.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'plot_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.config import ConfigSettings -from ert.enkf import EnkfPrototype - -class PlotSettings(ConfigSettings): - TYPE_NAME = "plot_settings" - _init = EnkfPrototype("void plot_settings_init(plot_settings)") - - def __init__(self): - super(PlotSettings, self).__init__("PLOT_SETTING") - self._init( ) - - def getPath(self): - """ @rtype: str """ - return self["PATH"] - - def setPath(self, path): - self["PATH"] = path - - diff --git a/ThirdParty/Ert/python/python/ert/enkf/run_arg.py b/ThirdParty/Ert/python/python/ert/enkf/run_arg.py deleted file mode 100644 index 26fe077fa4..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/run_arg.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'run_arg.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype - -class RunArg(BaseCClass): - TYPE_NAME = "run_arg" - - _alloc_ENSEMBLE_EXPERIMENT = EnkfPrototype("run_arg_obj run_arg_alloc_ENSEMBLE_EXPERIMENT(enkf_fs , int, int, char*)", bind = False) - _free = EnkfPrototype("void run_arg_free(run_arg)") - _get_queue_index = EnkfPrototype("int run_arg_get_queue_index(run_arg)") - _is_submitted = EnkfPrototype("bool run_arg_is_submitted(run_arg)") - - def __init__(self): - raise NotImplementedError("Cannot instantiat RunArg directly!") - - @classmethod - def createEnsembleExperimentRunArg(cls, fs, iens, runpath, iter=0): - return cls._alloc_ENSEMBLE_EXPERIMENT(fs, iens, iter, runpath) - - def free(self): - self._free() - - def getQueueIndex(self): - return self._get_queue_index() - - def isSubmitted(self): - return self._is_submitted() - - def __repr__(self): - su = 'submitted' if self.isSubmitted() else 'not submitted' - qi = self.getQueueIndex() - return 'RunArg(queue_index = %d, %s) %s' % (qi, su, self._ad_str()) diff --git a/ThirdParty/Ert/python/python/ert/enkf/runpath_list.py b/ThirdParty/Ert/python/python/ert/enkf/runpath_list.py deleted file mode 100644 index af370d5df4..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/runpath_list.py +++ /dev/null @@ -1,86 +0,0 @@ -from collections import namedtuple -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype - -RunpathNode = namedtuple("RunpathNode", ["realization", "iteration", "runpath", "basename"]) - -class RunpathList(BaseCClass): - TYPE_NAME = "runpath_list" - _alloc = EnkfPrototype("void* runpath_list_alloc(char*)" , bind = False) - _free = EnkfPrototype("void runpath_list_free(runpath_list)") - _add = EnkfPrototype("void runpath_list_add(runpath_list, int, int, char*, char*)") - _clear = EnkfPrototype("void runpath_list_clear(runpath_list)") - _size = EnkfPrototype("int runpath_list_size(runpath_list)") - _iens = EnkfPrototype("int runpath_list_iget_iens(runpath_list, int)") - _iteration = EnkfPrototype("int runpath_list_iget_iter(runpath_list, int)") - _runpath = EnkfPrototype("char* runpath_list_iget_runpath(runpath_list, int)") - _basename = EnkfPrototype("char* runpath_list_iget_basename(runpath_list, int)") - _export = EnkfPrototype("void runpath_list_fprintf(runpath_list)") - - _get_export_file = EnkfPrototype("char* runpath_list_get_export_file(runpath_list)") - _set_export_file = EnkfPrototype("void runpath_list_set_export_file(runpath_list, char*)") - - def __init__(self, export_file): - c_ptr = self._alloc( export_file ) - if c_ptr: - super(RunpathList , self).__init__(c_ptr) - else: - raise ValueError('Could not construct RunpathList with export_file "%s".' % export_file) - - def __len__(self): - return self._size( ) - - def __getitem__(self, index): - """ @rtype: RunpathNode """ - ls = len(self) - if isinstance(index, int): - idx = index - if idx < 0: - idx += ls - if not 0 <= idx < ls: - raise IndexError("Index not in range: 0 <= %d < %d" % (index, ls)) - realization = self._iens(idx) - iteration = self._iteration(idx) - runpath = self._runpath(idx) - basename = self._basename(idx) - return RunpathNode(realization, iteration, runpath, basename) - elif isinstance(index, slice): - return [self[i] for i in range(*index.indices(ls))] - raise TypeError('List indices must be integers, not %s.' % str(type(index))) - - - def __iter__(self): - index = 0 - while index < len(self): - yield self[index] - index += 1 - - def getExportFile(self): - return self._get_export_file( ) - - - def setExportFile(self , export_file): - self._set_export_file( export_file ) - - - def add(self, realization_number, iteration_number, runpath, basename): - """ - @type realization_number: int - @type iteration_number: int - @type runpath: int - @type basename: int - """ - self._add(realization_number, iteration_number, runpath, basename) - - def clear(self): - self._clear( ) - - - def free(self): - self._free( ) - - def __repr__(self): - return 'RunpathList(size = %d) %s' % (len(self), self._ad_str()) - - def export(self): - self._export( ) diff --git a/ThirdParty/Ert/python/python/ert/enkf/site_config.py b/ThirdParty/Ert/python/python/ert/enkf/site_config.py deleted file mode 100644 index 5d28e2d192..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/site_config.py +++ /dev/null @@ -1,196 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'site_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.job_queue import JobQueue, ExtJoblist -from ert.util import StringList, Hash - - -class SiteConfig(BaseCClass): - TYPE_NAME = "site_config" - - _free = EnkfPrototype("void site_config_free( site_config )") - _get_queue_name = EnkfPrototype("char* site_config_get_queue_name(site_config)") - _get_lsf_queue = EnkfPrototype("char* site_config_get_lsf_queue(site_config)") - _set_lsf_queue = EnkfPrototype("void site_config_set_lsf_queue(site_config, char*)") - _get_max_running_lsf = EnkfPrototype("int site_config_get_max_running_lsf(site_config)") - _set_max_running_lsf = EnkfPrototype("void site_config_set_max_running_lsf(site_config, int)") - _get_lsf_request = EnkfPrototype("char* site_config_get_lsf_request(site_config)") - _set_lsf_request = EnkfPrototype("void site_config_set_lsf_request(site_config, char*)") - _get_rsh_command = EnkfPrototype("char* site_config_get_rsh_command(site_config)") - _set_rsh_command = EnkfPrototype("void site_config_set_rsh_command(site_config, char*)") - _get_max_running_rsh = EnkfPrototype("int site_config_get_max_running_rsh(site_config)") - _set_max_running_rsh = EnkfPrototype("void site_config_set_max_running_rsh(site_config, int)") - _get_rsh_host_list = EnkfPrototype("integer_hash_ref site_config_get_rsh_host_list(site_config)") - _clear_rsh_host_list = EnkfPrototype("void site_config_clear_rsh_host_list(site_config)") - _add_rsh_host = EnkfPrototype("void site_config_add_rsh_host(site_config, char*, int)") - _get_max_running_local = EnkfPrototype("int site_config_get_max_running_local(site_config)") - _set_max_running_local = EnkfPrototype("void site_config_set_max_running_local(site_config, int)") - _get_installed_jobs = EnkfPrototype("ext_joblist_ref site_config_get_installed_jobs(site_config)") - _get_max_submit = EnkfPrototype("int site_config_get_max_submit(site_config)") - _set_max_submit = EnkfPrototype("void site_config_set_max_submit(site_config, int)") - _get_license_root_path = EnkfPrototype("char* site_config_get_license_root_path(site_config)") - _set_license_root_path = EnkfPrototype("void site_config_set_license_root_path(site_config, char*)") - _get_job_script = EnkfPrototype("char* site_config_get_job_script(site_config)") - _set_job_script = EnkfPrototype("void site_config_set_job_script(site_config, char*)") - _get_env_hash = EnkfPrototype("string_hash_ref site_config_get_env_hash(site_config)") - _clear_env = EnkfPrototype("void site_config_clear_env(site_config)") - _setenv = EnkfPrototype("void site_config_setenv(site_config, char*, char*)") - _get_path_variables = EnkfPrototype("stringlist_ref site_config_get_path_variables(site_config)") - _get_path_values = EnkfPrototype("stringlist_ref site_config_get_path_values(site_config)") - _clear_pathvar = EnkfPrototype("void site_config_clear_pathvar(site_config)") - _update_pathvar = EnkfPrototype("void site_config_update_pathvar(site_config, char*, char*)") - _get_job_queue = EnkfPrototype("job_queue_ref site_config_get_job_queue(site_config)") - _queue_is_running = EnkfPrototype("bool site_config_queue_is_running(site_config)") - _get_location = EnkfPrototype("char* site_config_get_location(site_config)") - _has_driver = EnkfPrototype("bool site_config_has_queue_driver(site_config, char*)") - - - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def getQueueName(self): - """ @rtype: str """ - return self._get_queue_name( ) - - def setJobQueue(self, queue): - raise Exception("The function setJobQueue() is not properly implemented") - - - def hasDriver(self, driver_name): - return self._has_driver( driver_name ) - - - def getLsfQueue(self): - """ @rtype: str """ - return self._get_lsf_queue( ) - - def setLsfQueue(self, queue): - self._set_lsf_queue( queue) - - def getMaxRunningLsf(self): - """ @rtype: int """ - return self._get_max_running_lsf( ) - - def setMaxRunningLsf(self, max_running): - self._set_max_running_lsf( max_running) - - def getLsfRequest(self): - """ @rtype: str """ - return self._get_lsf_request( ) - - def setLsfRequest(self, lsf_request): - self._set_lsf_request( lsf_request) - - def clearRshHostList(self): - self._clear_rsh_host_list( ) - - def getRshCommand(self): - """ @rtype: str """ - return self._get_rsh_command( ) - - def set_rsh_command(self, rsh_command): - self._set_rsh_command( rsh_command) - - def getMaxRunningRsh(self): - """ @rtype: int """ - return self._get_max_running_rsh( ) - - def setMaxRunningRsh(self, max_running): - self._set_max_running_rsh( max_running) - - def getMaxRunningLocal(self): - """ @rtype: int """ - return self._get_max_running_local( ) - - def setMaxRunningLocal(self, max_running): - self._set_max_running_local( max_running) - - def get_job_script(self): - """ @rtype: str """ - return self._get_job_script( ) - - def set_job_script(self, job_script): - self._set_job_script( job_script) - - def get_env_hash(self): - """ @rtype: StringHash """ - return self._get_env_hash( ) - - def setenv(self, var, value): - self._setenv( var, value) - - def clear_env(self): - self._clear_env( ) - - def get_path_variables(self): - """ @rtype: StringList """ - return self._get_path_variables().setParent(self) - - def get_path_values(self): - """ @rtype: StringList """ - return self._get_path_values().setParent(self) - - def clear_pathvar(self): - self._clear_pathvar( ) - - def update_pathvar(self, pathvar, value): - self._update_pathvar( pathvar, value) - - def get_installed_jobs(self): - """ @rtype: ExtJoblist """ - return self._get_installed_jobs().setParent(self) - - def get_max_submit(self): - """ @rtype: int """ - return self._get_max_submit( ) - - def set_max_submit(self, max_value): - self._set_max_submit( max_value) - - def get_license_root_path(self): - """ @rtype: str """ - return self._get_license_root_path( ) - - def set_license_root_pathmax_submit(self, path): - self._set_license_root_path( path) - - def isQueueRunning(self): - """ @rtype: bool """ - return self._queue_is_running( ) - - def getJobQueue(self): - """ @rtype: JobQueue """ - return self._get_job_queue().setParent(self) - - def getRshHostList(self): - """ @rtype: IntegerHash """ - host_list = self._get_rsh_host_list() - return host_list - - def addRshHost(self, host, max_running): - self._add_rsh_host(host, max_running) - - def getLocation(self): - """ @rtype: str """ - return self._get_location() - - - def free(self): - self._free() - - diff --git a/ThirdParty/Ert/python/python/ert/enkf/state_map.py b/ThirdParty/Ert/python/python/ert/enkf/state_map.py deleted file mode 100644 index b6ba3c50d9..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/state_map.py +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'enkf_fs.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.enkf.enums import RealizationStateEnum -from ert.util import BoolVector - - -class StateMap(BaseCClass): - TYPE_NAME = "state_map" - - _alloc = EnkfPrototype("void* state_map_alloc()", bind = False) - _fread = EnkfPrototype("bool state_map_fread(state_map , char*)") - _fwrite = EnkfPrototype("void state_map_fwrite(state_map , char*)") - _equal = EnkfPrototype("bool state_map_equal(state_map , state_map)") - _free = EnkfPrototype("void state_map_free(state_map)") - _size = EnkfPrototype("int state_map_get_size(state_map)") - _iget = EnkfPrototype("realisation_state_enum state_map_iget(state_map, int)") - _iset = EnkfPrototype("void state_map_iset(state_map, int, realisation_state_enum)") - _select_matching = EnkfPrototype("void state_map_select_matching(state_map, bool_vector, realisation_state_enum)") - _is_read_only = EnkfPrototype("bool state_map_is_readonly(state_map)") - _is_legal_transition = EnkfPrototype("bool state_map_legal_transition(realisation_state_enum, realisation_state_enum)", bind = False) - - - - def __init__(self , filename = None): - c_ptr = self._alloc() - super(StateMap, self).__init__(c_ptr) - if filename: - self.load(filename) - - - def __len__(self): - """ @rtype: int """ - return self._size() - - def __iter__(self): - index = 0 - size = len(self) - - while index < size: - yield self[index] - index += 1 - - def __eq__(self , other): - return self._equal(other) - - - def __getitem__(self, index): - """ @rtype: RealizationStateEnum """ - if not isinstance(index, int): - raise TypeError("Expected an integer") - - size = len(self) - if index < 0: - index += size - if 0 <= index < size: - return self._iget(index) - raise IndexError("Invalid index. Valid range: [0, %d)" % size) - - - def __setitem__(self, index, value): - if self.isReadOnly(): - raise UserWarning("This State Map is read only!") - - if not isinstance(index, int): - raise TypeError("Expected an integer") - - if not isinstance(value, RealizationStateEnum): - raise TypeError("Expected a RealizationStateEnum") - - if index < 0: - index += len(self) - if index < 0: - raise IndexError("Index out of range: %d < 0" % index) - - self._iset(index, value) - - @classmethod - def isLegalTransition(cls, realization_state1, realization_state2): - """ @rtype: bool """ - - if not isinstance(realization_state1, RealizationStateEnum) or not isinstance(realization_state2, RealizationStateEnum): - raise TypeError("Expected a RealizationStateEnum") - - return cls._is_legal_transition(realization_state1, realization_state2) - - - def isReadOnly(self): - """ @rtype: bool """ - return self._is_read_only() - - def selectMatching(self, select_target, select_mask): - """ - @type select_target: BoolVector - @type select_mask: RealizationStateEnum - """ - assert isinstance(select_target, BoolVector) - assert isinstance(select_mask, RealizationStateEnum) - - self._select_matching(select_target, select_mask) - - - def realizationList(self , state_value): - """ - Will create a list of all realisations with state equal to state_value. - - @type state_value: RealizationStateEnum - @rtype: ert.util.IntVector - """ - mask = BoolVector(False, len(self)) - self.selectMatching(mask, state_value) - return BoolVector.createActiveList(mask) - - - - def free(self): - self._free() - - def __repr__(self): - ro = 'read only' if self.isReadOnly() else 'read/write' - return 'StateMap(size = %d, %s) %s' % (len(self), ro, self._ad_str()) - - def load(self,filename): - if not self._fread(filename): - raise IOError("Failed to load state map from:%s" % filename) - - - def save(self, filename): - self._fwrite(filename) diff --git a/ThirdParty/Ert/python/python/ert/enkf/summary_key_matcher.py b/ThirdParty/Ert/python/python/ert/enkf/summary_key_matcher.py deleted file mode 100644 index bc030a31d9..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/summary_key_matcher.py +++ /dev/null @@ -1,41 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.util import StringList - - -class SummaryKeyMatcher(BaseCClass): - TYPE_NAME = "summary_key_matcher" - - _alloc = EnkfPrototype("void* summary_key_matcher_alloc()", bind = False) - _free = EnkfPrototype("void summary_key_matcher_free(summary_key_matcher)") - _size = EnkfPrototype("int summary_key_matcher_get_size(summary_key_matcher)") - _add_key = EnkfPrototype("void summary_key_matcher_add_summary_key(summary_key_matcher, char*)") - _match_key = EnkfPrototype("bool summary_key_matcher_match_summary_key(summary_key_matcher, char*)") - _keys = EnkfPrototype("stringlist_obj summary_key_matcher_get_keys(summary_key_matcher)") - _is_required = EnkfPrototype("bool summary_key_matcher_summary_key_is_required(summary_key_matcher, char*)") - - def __init__(self): - c_ptr = self._alloc() - - super(SummaryKeyMatcher, self).__init__(c_ptr) - - def addSummaryKey(self, key): - assert isinstance(key, str) - return self._add_key(key) - - def __len__(self): - return self._size() - - def __contains__(self, key): - return self._match_key(key) - - def isRequired(self, key): - """ @rtype: bool """ - return self._is_required(key) - - def keys(self): - """ @rtype: StringList """ - return self._keys() - - def free(self): - self._free() diff --git a/ThirdParty/Ert/python/python/ert/enkf/summary_key_set.py b/ThirdParty/Ert/python/python/ert/enkf/summary_key_set.py deleted file mode 100644 index 81e294ba5c..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/summary_key_set.py +++ /dev/null @@ -1,51 +0,0 @@ -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.util import StringList - - -class SummaryKeySet(BaseCClass): - TYPE_NAME = "summary_key_set" - - _alloc = EnkfPrototype("void* summary_key_set_alloc()", bind = False) - _alloc_from_file = EnkfPrototype("void* summary_key_set_alloc_from_file(char*, bool)", bind = False) - _free = EnkfPrototype("void summary_key_set_free(summary_key_set)") - _size = EnkfPrototype("int summary_key_set_get_size(summary_key_set)") - _add_key = EnkfPrototype("bool summary_key_set_add_summary_key(summary_key_set, char*)") - _has_key = EnkfPrototype("bool summary_key_set_has_summary_key(summary_key_set, char*)") - _keys = EnkfPrototype("stringlist_obj summary_key_set_alloc_keys(summary_key_set)") - _is_read_only = EnkfPrototype("bool summary_key_set_is_read_only(summary_key_set)") - _fwrite = EnkfPrototype("void summary_key_set_fwrite(summary_key_set, char*)") - - def __init__(self, filename=None, read_only=False): - if filename is None: - c_ptr = self._alloc() - else: - c_ptr = self._alloc_from_file(filename, read_only) - - super(SummaryKeySet, self).__init__(c_ptr) - - def addSummaryKey(self, key): - assert isinstance(key, str) - return self._add_key(key) - - def __len__(self): - return self._size() - - def __contains__(self, key): - return self._has_key(key) - - def keys(self): - """ @rtype: StringList """ - return self._keys() - - def isReadOnly(self): - """ @rtype: bool """ - return self._is_read_only() - - - def writeToFile(self, filename): - assert isinstance(filename, str) - self._fwrite(filename) - - def free(self): - self._free() diff --git a/ThirdParty/Ert/python/python/ert/enkf/util/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/enkf/util/CMakeLists.txt deleted file mode 100644 index 7a0c3e95c6..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/util/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - time_map.py -) - -add_python_package("python.ert.enkf.util" ${PYTHON_INSTALL_PREFIX}/ert/enkf/util "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/enkf/util/__init__.py b/ThirdParty/Ert/python/python/ert/enkf/util/__init__.py deleted file mode 100644 index c3ce9ffc8a..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/util/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .time_map import TimeMap \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert/enkf/util/time_map.py b/ThirdParty/Ert/python/python/ert/enkf/util/time_map.py deleted file mode 100644 index 0da3a8e530..0000000000 --- a/ThirdParty/Ert/python/python/ert/enkf/util/time_map.py +++ /dev/null @@ -1,209 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'time_map.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import os -import errno - -from cwrap import BaseCClass -from ert.enkf import EnkfPrototype -from ert.util import CTime - - -class TimeMap(BaseCClass): - TYPE_NAME = "time_map" - - _fread_alloc_readonly = EnkfPrototype("void* time_map_fread_alloc_readonly(char*)", bind = False) - _alloc = EnkfPrototype("void* time_map_alloc()", bind = False) - _load = EnkfPrototype("bool time_map_fread(time_map , char*)") - _save = EnkfPrototype("void time_map_fwrite(time_map , char*)") - _fload = EnkfPrototype("bool time_map_fscanf(time_map , char*)") - _iget_sim_days = EnkfPrototype("double time_map_iget_sim_days(time_map, int)") - _iget = EnkfPrototype("time_t time_map_iget(time_map, int)") - _size = EnkfPrototype("int time_map_get_size(time_map)") - _try_update = EnkfPrototype("bool time_map_try_update(time_map , int , time_t)") - _is_strict = EnkfPrototype("bool time_map_is_strict( time_map )") - _set_strict = EnkfPrototype("void time_map_set_strict( time_map , bool)") - _lookup_time = EnkfPrototype("int time_map_lookup_time( time_map , time_t)") - _lookup_time_with_tolerance = EnkfPrototype("int time_map_lookup_time_with_tolerance( time_map , time_t , int , int)") - _lookup_days = EnkfPrototype("int time_map_lookup_days( time_map , double)") - _last_step = EnkfPrototype("int time_map_get_last_step( time_map )") - _upgrade107 = EnkfPrototype("void time_map_summary_upgrade107( time_map , ecl_sum )") - _free = EnkfPrototype("void time_map_free( time_map )") - - def __init__(self, filename = None): - c_ptr = self._alloc() - super(TimeMap, self).__init__(c_ptr) - if filename: - self.load(filename) - - - def load(self, filename): - if os.path.isfile( filename ): - self._load(filename) - else: - raise IOError(( errno.ENOENT , "File not found: %s" % filename)) - - - def fwrite(self, filename): - self._save(filename) - - - def fload(self , filename): - """ - Will load a timemap as a formatted file consisting of a list of dates: DD/MM/YYYY - """ - if os.path.isfile( filename ): - OK = self._fload(filename) - if not OK: - raise Exception("Error occured when loading timemap from:%s" % filename) - else: - raise IOError(( errno.ENOENT , "File not found: %s" % filename)) - - - - def isStrict(self): - return self._is_strict() - - - def setStrict(self , strict): - return self._set_strict(strict) - - - def getSimulationDays(self, step): - """ @rtype: double """ - if not isinstance(step, int): - raise TypeError("Expected an integer") - - size = len(self) - if step < 0 or step >= size: - raise IndexError("Index out of range: 0 <= %d < %d" % (step, size)) - - return self._iget_sim_days(step) - - - def __getitem__(self, index): - """ @rtype: CTime """ - if not isinstance(index, int): - raise TypeError("Expected an integer") - - size = len(self) - if index < 0 or index >= size: - raise IndexError("Index out of range: 0 <= %d < %d" % (index, size)) - - return self._iget(index) - - def __setitem__(self , index , time): - self.update( index , time ) - - - def update(self , index , time): - if self._try_update(index , CTime(time)): - return True - else: - if self.isStrict(): - raise Exception("Tried to update with inconsistent value") - else: - return False - - - - def __iter__(self): - cur = 0 - - while cur < len(self): - yield self[cur] - cur += 1 - - def __contains__(self , time): - index = self._lookup_time(CTime(time)) - if index >= 0: - return True - else: - return False - - - def lookupTime(self , time , tolerance_seconds_before = 0, tolerance_seconds_after = 0): - """Will look up the report step corresponding to input @time. - - If the tolerance arguments tolerance_seconds_before and - tolerance_seconds_after have the default value zero we require - an exact match between input time argument and the content of - the time map. - - If the tolerance arguments are supplied the function will - search through the time_map for the report step closest to the - time argument, which satisfies the tolerance criteria. - - With the call: - - lookupTime( datetime.date(2010,1,10) , 3600*24 , 3600*7) - - We will find the report step in the date interval 2010,1,9 - - 2010,1,17 which is closest to 2010,1,10. The tolerance limits - are inclusive. - - If no report step satisfying the criteria is found a - ValueError exception will be raised. - - """ - if tolerance_seconds_before == 0 and tolerance_seconds_after == 0: - index = self._lookup_time(CTime(time)) - else: - index = self._lookup_time_with_tolerance(CTime(time) , tolerance_seconds_before , tolerance_seconds_after) - - if index >= 0: - return index - else: - raise ValueError("The time:%s was not found in the time_map instance" % time) - - - def lookupDays(self , days): - index = self._lookup_days(days) - if index >= 0: - return index - else: - raise ValueError("The days: %s was not found in the time_map instance" % days) - - - def __len__(self): - """ @rtype: int """ - return self._size() - - def free(self): - self._free() - - def __repr__(self): - ls = len(self) - la = self.getLastStep() - st = 'strict' if self.isStrict() else 'not strict' - cnt = 'size = %d, last_step = %d, %s' % (ls, la, st) - return self._create_repr(cnt) - - def dump(self): - """ - Will return a list of tuples (step , CTime , days). - """ - step_list = [] - for step,t in enumerate(self): - step_list.append( (step , t , self.getSimulationDays( step )) ) - return step_list - - - def getLastStep(self): - return self._last_step() - - - def upgrade107(self, refcase): - self._upgrade107(refcase) diff --git a/ThirdParty/Ert/python/python/ert/geo/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/geo/CMakeLists.txt index 379d3df00d..c38229e4ca 100644 --- a/ThirdParty/Ert/python/python/ert/geo/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/ert/geo/CMakeLists.txt @@ -3,10 +3,11 @@ set(PYTHON_SOURCES cpolyline.py cpolyline_collection.py geometry_tools.py + geo_pointset.py + geo_region.py polyline.py xyz_io.py surface.py ) add_python_package("python.ert.geo" ${PYTHON_INSTALL_PREFIX}/ert/geo "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/geo/__init__.py b/ThirdParty/Ert/python/python/ert/geo/__init__.py index 0049bc6ea2..23a518af9a 100644 --- a/ThirdParty/Ert/python/python/ert/geo/__init__.py +++ b/ThirdParty/Ert/python/python/ert/geo/__init__.py @@ -19,7 +19,6 @@ Simple package for working with 2D geometry. """ import ert from cwrap import Prototype -import ert.util class GeoPrototype(Prototype): lib = ert.load("libert_geometry") @@ -28,7 +27,8 @@ class GeoPrototype(Prototype): super(GeoPrototype, self).__init__(GeoPrototype.lib, prototype, bind=bind) - +from .geo_pointset import GeoPointset +from .geo_region import GeoRegion from .cpolyline import CPolyline from .cpolyline_collection import CPolylineCollection from .polyline import Polyline diff --git a/ThirdParty/Ert/python/python/ert/geo/cpolyline.py b/ThirdParty/Ert/python/python/ert/geo/cpolyline.py index 42293f831e..24ef9f6c45 100644 --- a/ThirdParty/Ert/python/python/ert/geo/cpolyline.py +++ b/ThirdParty/Ert/python/python/ert/geo/cpolyline.py @@ -41,7 +41,7 @@ class CPolyline(BaseCClass): _equal = GeoPrototype("bool geo_polygon_equal( geo_polygon , geo_polygon )") - def __init__(self, name = None , init_points = []): + def __init__(self, name = None , init_points = ()): c_ptr = self._alloc_new( name ) super(CPolyline , self).__init__( c_ptr ) for (xc, yc) in init_points: diff --git a/ThirdParty/Ert/python/python/ert/geo/geo_pointset.py b/ThirdParty/Ert/python/python/ert/geo/geo_pointset.py new file mode 100644 index 0000000000..31c46ccef0 --- /dev/null +++ b/ThirdParty/Ert/python/python/ert/geo/geo_pointset.py @@ -0,0 +1,79 @@ +# Copyright (C) 2017 Statoil ASA, Norway. +# +# This file is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. +from cwrap import BaseCClass +from ert.geo import GeoPrototype + +class GeoPointset(BaseCClass): + TYPE_NAME = "geo_pointset" + + _alloc = GeoPrototype("void* geo_pointset_alloc(bool)", bind=False) + _free = GeoPrototype("void geo_pointset_free(geo_pointset)") + #_add_xyz = GeoPrototype("void geo_pointset_add_xyz(geo_pointset, double, double, double)") + _get_size = GeoPrototype("int geo_pointset_get_size(geo_pointset)") + #_iget_xy = GeoPrototype("void geo_pointset_iget_xy(geo_pointset, int, double*, double*)") + #_get_zcoord = GeoPrototype("double* geo_pointset_get_zcoord(geo_pointset)") + _equal = GeoPrototype("bool geo_pointset_equal(geo_pointset, geo_pointset)") + _iget_z = GeoPrototype("double geo_pointset_iget_z(geo_pointset, int)") + #_iset_z = GeoPrototype("void geo_pointset_iset_z(geo_pointset, int, double)") + #_memcpy = GeoPrototype("void geo_pointset_memcpy(geo_pointset, geo_pointset, bool)") + #_shift_z = GeoPrototype("void geo_pointset_shift_z(geo_pointset, double)") + #_assign_z = GeoPrototype("void geo_pointset_assign_z(geo_pointset, double)") + #_scale_z = GeoPrototype("void geo_pointset_scale_z(geo_pointset, double)") + #_imul = GeoPrototype("void geo_pointset_imul(geo_pointset, geo_pointset)") + #_iadd = GeoPrototype("void geo_pointset_iadd(geo_pointset, geo_pointset)") + #_isub = GeoPrototype("void geo_pointset_isub(geo_pointset, geo_pointset)") + #_isqrt = GeoPrototype("void geo_pointset_isqrt(geo_pointset)") + + + def __init__(self, external_z=False): + c_ptr = self._alloc(external_z) + if c_ptr: + super(GeoPointset, self).__init__(c_ptr) + else: + ext = 'external' if external_z else 'internal' + raise ValueError('Failed to construct GeoPointset with %s_z.' % ext) + + @staticmethod + def fromSurface(surface): + return surface.getPointset() + + def __eq__(self, other): + if isinstance(other, GeoPointset): + return self._equal(other) + return NotImplemented + + def __getitem__(self, key): + size = len(self) + if isinstance(key, int): + idx = key + if idx < 0: + idx += size + if 0 <= idx < size: + return self._iget_z(idx) + else: + raise IndexError('Invalid index, must be in [0, %d), was: %d.' % (size, key)) + else: + # TODO implement slicing? + raise ValueError('Index must be int, not %s.' % type(key)) + + def __len__(self): + return self._get_size() + + def __repr__(self): + return self._create_repr('len=%d' % len(self)) + + def free(self): + self._free() diff --git a/ThirdParty/Ert/python/python/ert/geo/geo_region.py b/ThirdParty/Ert/python/python/ert/geo/geo_region.py new file mode 100644 index 0000000000..648a0dabc7 --- /dev/null +++ b/ThirdParty/Ert/python/python/ert/geo/geo_region.py @@ -0,0 +1,121 @@ +# Copyright (C) 2017 Statoil ASA, Norway. +# +# This file is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. +from cwrap import BaseCClass +from ert.util import IntVector +from ert.geo import GeoPrototype +from .cpolyline import CPolyline +from ctypes import c_double + +cpair = c_double * 2 # this is a function that maps two doubles to a double* + +class GeoRegion(BaseCClass): + TYPE_NAME = "geo_region" + + _alloc = GeoPrototype("void* geo_region_alloc(geo_pointset, bool)", bind=False) + _free = GeoPrototype("void geo_region_free(geo_region)") + _reset = GeoPrototype("void geo_region_reset(geo_region)") + _get_index_list = GeoPrototype("int_vector_ref geo_region_get_index_list(geo_region)") + _select_inside_polygon = GeoPrototype("void geo_region_select_inside_polygon(geo_region, geo_polygon)") + _select_outside_polygon = GeoPrototype("void geo_region_select_outside_polygon(geo_region, geo_polygon)") + _deselect_inside_polygon = GeoPrototype("void geo_region_deselect_inside_polygon(geo_region, geo_polygon)") + _deselect_outside_polygon = GeoPrototype("void geo_region_deselect_outside_polygon(geo_region, geo_polygon)") + _select_above_line = GeoPrototype("void geo_region_select_above_line(geo_region, double*, double*)") + _select_below_line = GeoPrototype("void geo_region_select_below_line(geo_region, double*, double*)") + _deselect_above_line = GeoPrototype("void geo_region_deselect_above_line(geo_region, double*, double*)") + _deselect_below_line = GeoPrototype("void geo_region_deselect_below_line(geo_region, double*, double*)") + + + def __init__(self, pointset, preselect=False): + self._preselect = True if preselect else False + c_ptr = self._alloc(pointset, self._preselect) + if c_ptr: + super(GeoRegion, self).__init__(c_ptr) + else: + raise ValueError('Could not construct GeoRegion from pointset %s.' % pointset) + + + def getActiveList(self): + return self._get_index_list() + + def _assert_polygon(self, polygon): + if not isinstance(polygon, CPolyline): + raise ValueError('Need to select with a CPolyline, not %s.' + % type(polygon)) + + + def _construct_cline(self, line): + """Takes a line ((x1,y1), (x2,y2)) and returns two double[2]* but + reordered to (x1x2, y1y2). + """ + try: + p1, p2 = line + x1, y1 = map(float, p1) + x2, y2 = map(float, p2) + except Exception as err: + err_msg = 'Select with pair ((x1,y1), (x2,y2)), not %s (%s).' + raise ValueError(err_msg % (line, err)) + x1x2_ptr = cpair(x1, x2) + y1y2_ptr = cpair(y1, y2) + return x1x2_ptr, y1y2_ptr + + + def select_inside(self, polygon): + self._assert_polygon(polygon) + self._select_inside_polygon(polygon) + + def select_outside(self, polygon): + self._assert_polygon(polygon) + self._select_outside_polygon(polygon) + + def deselect_inside(self, polygon): + self._assert_polygon(polygon) + self._deselect_inside_polygon(polygon) + + def deselect_outside(self, polygon): + self._assert_polygon(polygon) + self._deselect_outside_polygon(polygon) + + + def select_above(self, line): + x_ptr, y_ptr = self._construct_cline(line) + self._select_above_line(x_ptr, y_ptr) + + def select_below(self, line): + x_ptr, y_ptr = self._construct_cline(line) + self._select_below_line(x_ptr, y_ptr) + + def deselect_above(self, line): + x_ptr, y_ptr = self._construct_cline(line) + self._deselect_above_line(x_ptr, y_ptr) + + def deselect_below(self, line): + x_ptr, y_ptr = self._construct_cline(line) + self._deselect_below_line(x_ptr, y_ptr) + + + def __len__(self): + """Returns the size of the active list, not the size of the + underlying pointset""" + return len(self._get_index_list()) + + def __repr__(self): + ls = len(self) + il = repr(self.getActiveList()) + pres = 'preselected' if self._preselect else 'not preselected' + return self._create_repr('size=%d, active_list=<%s>, %s' % (ls, il, pres)) + + def free(self): + self._free() diff --git a/ThirdParty/Ert/python/python/ert/geo/surface.py b/ThirdParty/Ert/python/python/ert/geo/surface.py index 799a1377c0..f16d18b8da 100644 --- a/ThirdParty/Ert/python/python/ert/geo/surface.py +++ b/ThirdParty/Ert/python/python/ert/geo/surface.py @@ -18,10 +18,11 @@ Create a polygon """ import os.path import ctypes +from numpy import zeros from cwrap import BaseCClass from ert.geo import GeoPrototype - +from ert.geo import GeoPointset class Surface(BaseCClass): TYPE_NAME = "surface" @@ -44,7 +45,8 @@ class Surface(BaseCClass): _imul = GeoPrototype("void geo_surface_imul( surface , surface )") _isub = GeoPrototype("void geo_surface_isub( surface , surface )") _isqrt = GeoPrototype("void geo_surface_isqrt( surface )") - _iget_xy = GeoPrototype("void geo_surface_iget_xy(surface, int, double*, double*)") + _iget_xy = GeoPrototype("void geo_surface_iget_xy(surface, int, double*, double*)") + _get_pointset = GeoPrototype("geo_pointset_ref geo_surface_get_pointset(surface)") def __init__(self, filename=None, nx=None, ny=None, xinc=None, yinc=None, @@ -158,7 +160,6 @@ class Surface(BaseCClass): self._isqrt( ) return self - def sqrt(self): """ @@ -183,7 +184,7 @@ class Surface(BaseCClass): """ self._write( filename ) - + def assign(self , value): """ @@ -201,28 +202,32 @@ class Surface(BaseCClass): self._iset_zvalue(index , value) else: - raise TypeError("Invalid index type:%s - must be integer" % index) + raise TypeError("Invalid index type:%s - must be integer" % index) - def __getitem__(self , index): if isinstance(index , int): - if index >= len(self): + idx = index + ls = len(self) + if idx < 0: + idx += ls + if 0 <= idx < ls: + return self._iget_zvalue(idx) + else: raise IndexError("Invalid index:%d - valid range [0,%d)" % (index , len(self))) - if index < 0: - index += len(self) - - return self._iget_zvalue( index) else: - raise TypeError("Invalid index type:%s - must be integer" % index) + raise TypeError("Invalid index type:%s - must be integer" % index) def getXY(self, index): + """Gets the index'th (x,y) coordinate""" if isinstance(index, int): - if index < 0: - index += len(self) - if index >= len(self) or index < 0: + idx = index + if idx < 0: + idx += len(self) + if not 0 <= idx < len(self): raise IndexError("Invalid index:%d - valid range [0,%d)" % (index, len(self))) + index = idx else: raise TypeError("Invalid index type:%s - must be integer" % index) @@ -234,12 +239,47 @@ class Surface(BaseCClass): def getNX(self): - return self._get_nx( ) + return self._get_nx() def getNY(self): - return self._get_ny( ) + return self._get_ny() + + def getPointset(self): + return self._get_pointset() + + def _assert_idx_or_i_and_j(self, idx, i, j): + if idx is None: + if i is None or j is None: + raise ValueError('idx is None, i and j must be ints, was %s and %s.' % (i, j)) + else: + if i is not None or j is not None: + raise ValueError('idx is set, i and j must be None, was %s and %s.' % (i, j)) + + + def getXYZ(self, idx=None, i=None, j=None): + """Returns a tuple of 3 floats, (x,y,z) for given global index, or i and j.""" + self._assert_idx_or_i_and_j(idx, i, j) + if idx is None: + nx, ny = self.getNX(), self.getNY() + i_idx, j_idx = i,j + if i_idx < 0: + i_idx += self.getNX() + if j_idx < 0: + j_idx += self.getNY() + if 0 <= i_idx < self.getNX() and 0 <= j_idx < self.getNY(): + idx = j_idx * self.getNX() + i_idx + else: + fmt = 'Index error: i=%d not in [0,nx=%d) or j=%d not in [0,ny=%d).' + raise IndexError(fmt % (i, nx, j, ny)) + x,y = self.getXY(idx) + z = self[idx] + return (x,y,z) def free(self): - self._free( ) + self._free() + + def __repr__(self): + cnt = 'nx=%d, ny=%d' % (self.getNX(), self.getNY()) + return self._create_repr(cnt) diff --git a/ThirdParty/Ert/python/python/ert/job_queue/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/job_queue/CMakeLists.txt deleted file mode 100644 index 4fd89b4318..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - driver.py - ert_plugin.py - ert_script.py - ext_job.py - ext_joblist.py - external_ert_script.py - forward_model.py - function_ert_script.py - job.py - job_status_type_enum.py - queue.py - job_queue_manager.py - workflow.py - workflow_job.py - workflow_joblist.py - workflow_runner.py -) - -add_python_package("python.ert.job_queue" ${PYTHON_INSTALL_PREFIX}/ert/job_queue "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/__init__.py b/ThirdParty/Ert/python/python/ert/job_queue/__init__.py deleted file mode 100644 index 82ab36a03e..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/__init__.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file '__init__.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -""" -The job_queue package contains modules and classes for running -external commands. -""" - -# Getting LSF to work properly is quite painful. The situation -# is a mix of build complexity and LSF specific requirements: -# -# 1. The LSF libraries are accessed from the libjob_queue.so -# library, but observe that the dependancy on the liblsf and -# libbat libraries is through dlopen(), i.e. runtime. This module -# will therefor load happily without access to the lsf libraries. -# -# If you at a later stage create a lsf driver the runtime -# environment must be able to locate the liblsf.so, libbat.so and -# libnsl.so shared libraries, either through LD_LIBRARY_PATH or -# other means. -# -# 2. To actually use LSF you need a whole list of environment -# variables to be set: LSF_BINDIR , LSF_LIBDIR , XLDF_UIDDIR , -# LSF_SERVERDIR, LSF_ENVDIR - this is an LSF requirement and not -# related to ERT or the Python bindings. The normal way to -# achieve this is by sourcing a shell script. -# -# If the environment variable LSF_HOME is set we set the -# remaining LSF variables according to: -# -# LSF_BINDIR = $LSF_HOME/bin -# LSF_LIBDIR = $LSF_HOME/lib -# XLSF_UIDDIR = $LSF_HOME/lib/uid -# LSF_SERVERDIR = $LSF_HOME/etc -# LSF_ENVDIR = $LSF_HOME/conf -# PATH = $PATH:$LSF_BINDIR -# -# Observe that none of these variables are modified if they -# already have a value, furthermore it should be observed that -# the use of an LSF_HOME variable is something invented with ERT, -# and not standard LSF approach. - - -import os -import ert -import ert.util -import ert.config -from cwrap import Prototype - -def setenv( var, value): - if not os.getenv(var): - os.environ[var] = value - -# Set up the full LSF environment - based onf LSF_HOME -LSF_HOME = os.getenv("LSF_HOME") -if LSF_HOME: - setenv("LSF_BINDIR", "%s/bin" % LSF_HOME) - setenv("LSF_LIBDIR", "%s/lib" % LSF_HOME) - setenv("XLSF_UIDDIR", "%s/lib/uid" % LSF_HOME) - setenv("LSF_SERVERDIR", "%s/etc" % LSF_HOME) - setenv("LSF_ENVDIR", "%s/conf" % LSF_HOME) # This is wrong: Statoil: /prog/LSF/conf - -JOB_QUEUE_LIB = ert.load("libjob_queue") - -class QueuePrototype(Prototype): - lib = ert.load("libjob_queue") - - def __init__(self, prototype, bind=True): - super(QueuePrototype, self).__init__(QueuePrototype.lib, prototype, bind=bind) - - -#from .job_status_type_enum import JobStatusType -from .job_status_type_enum import JobStatusType -from .job import Job -from .queue import JobQueue -from .job_queue_manager import JobQueueManager -from .driver import QueueDriverEnum, Driver, LSFDriver, RSHDriver, LocalDriver -from .ext_job import ExtJob -from .ext_joblist import ExtJoblist -from .forward_model import ForwardModel - -from .ert_script import ErtScript -from .ert_plugin import ErtPlugin, CancelPluginException -from .function_ert_script import FunctionErtScript -from .external_ert_script import ExternalErtScript - -from .workflow_job import WorkflowJob -from .workflow_joblist import WorkflowJoblist -from .workflow import Workflow -from .workflow_runner import WorkflowRunner diff --git a/ThirdParty/Ert/python/python/ert/job_queue/driver.py b/ThirdParty/Ert/python/python/ert/job_queue/driver.py deleted file mode 100644 index 2f6e58b39a..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/driver.py +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'driver.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -import ctypes -from cwrap import BaseCClass, BaseCEnum -from ert.job_queue import JOB_QUEUE_LIB, QueuePrototype -from ert.job_queue import Job - - -class QueueDriverEnum(BaseCEnum): - TYPE_NAME="queue_driver_enum" - NULL_DRIVER = None - LSF_DRIVER = None - LOCAL_DRIVER = None - RSH_DRIVER = None - TORQUE_DRIVER = None - -QueueDriverEnum.addEnum( "NULL_DRIVER" , 0 ) -QueueDriverEnum.addEnum( "LSF_DRIVER" , 1 ) -QueueDriverEnum.addEnum( "LOCAL_DRIVER" , 2 ) -QueueDriverEnum.addEnum( "RSH_DRIVER" , 3 ) -QueueDriverEnum.addEnum( "TORQUE_DRIVER" , 4 ) - - -LSF_DRIVER = QueueDriverEnum.LSF_DRIVER -RSH_DRIVER = QueueDriverEnum.RSH_DRIVER -LOCAL_DRIVER = QueueDriverEnum.LOCAL_DRIVER - - - -class Driver(BaseCClass): - TYPE_NAME = "driver" - _alloc = QueuePrototype("void* queue_driver_alloc( queue_driver_enum )" , bind = False) - _free = QueuePrototype("void queue_driver_free( driver )") - _set_option = QueuePrototype("void queue_driver_set_option( driver , char* , char*)") - _submit = QueuePrototype("void* queue_driver_submit_job( driver , char* , int , char* , char* , int , char**)") - _free_job = QueuePrototype("void queue_driver_free_job( driver , job )") - _get_status = QueuePrototype("int queue_driver_get_status( driver , job)") - _kill_job = QueuePrototype("void queue_driver_kill_job( driver , job )") - _get_max_running = QueuePrototype("int queue_driver_get_max_running( driver )") - _set_max_running = QueuePrototype("void queue_driver_set_max_running( driver , int)") - _get_name = QueuePrototype("char* queue_driver_get_name( driver )") - - def __init__( self, driver_type, max_running=1, options=None): - """ - Creates a new driver instance - """ - c_ptr = self._alloc( driver_type ) - super(Driver , self).__init__(c_ptr) - if options: - for (key, value) in options: - self.set_option(key, value) - self.set_max_running(max_running) - - - def set_option(self, option, value): - """ - Set the driver option @option to @value. - - If the option is succlessfully set the method will return True, - otherwise the method will return False. If the @option is not - recognized the method will return False. The supplied value - should be a string. - """ - return self._set_option(option, str(value)) - - - def is_driver_instance( self ): - return True - - - def submit( self, name, cmd, run_path, argList, num_cpu=1, blocking=False): - argc = len(argList) - argv = (ctypes.c_char_p * argc)() - argv[:] = map(str, argList) - - c_ptr = self._submit(cmd, num_cpu, run_path, name, argc, argv) - job = Job( c_ptr , self ) - if blocking: - job.block() - job = None - return job - - - def free_job( self, job ): - self._free_job(job) - - def get_status( self, job ): - status = self._get_status(job) - return status - - def kill_job( self, job ): - self._kill_job(job) - - def get_max_running( self ): - return self._get_max_running( ) - - def set_max_running( self, max_running ): - self._set_max_running(max_running) - - max_running = property(get_max_running, set_max_running) - - @property - def name(self): - return self._get_name(self) - - def free(self): - self._free( ) - - -class LSFDriver(Driver): - def __init__(self, - max_running, - lsf_server=None, - queue="normal", - resource_request=None): - # The strings should match the available keys given in the - # lsf_driver.h header file. - options = [("LSF_QUEUE", queue), - ("LSF_SERVER", lsf_server), - ("LSF_RESOURCE", resource_request )] - Driver.__init__(self, QueueDriverEnum.LSF_DRIVER, max_running=max_running, options=options) - - -class LocalDriver(Driver): - def __init__( self, max_running ): - Driver.__init__(self, QueueDriverEnum.LOCAL_DRIVER, max_running, options=[]) - - -class RSHDriver(Driver): - # Changing shell to bash can come in conflict with running ssh - # commands. - - def __init__( self, max_running, rsh_host_list, rsh_cmd="/usr/bin/ssh" ): - """ - @rsh_host_list should be a list of tuples like: (hostname , max_running) - """ - - options = [("RSH_CMD", rsh_cmd)] - for (host, host_max) in rsh_host_list: - options.append(("RSH_HOST", "%s:%d" % (host, host_max))) - Driver.__init__(self, QueueDriverEnum.RSH_DRIVER, max_running, options=options) - - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/ert_plugin.py b/ThirdParty/Ert/python/python/ert/job_queue/ert_plugin.py deleted file mode 100644 index b4b48e240c..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/ert_plugin.py +++ /dev/null @@ -1,48 +0,0 @@ -from .ert_script import ErtScript -from threading import Thread -import time - -class CancelPluginException(Exception): - def __init__(self, cancel_message): - super(CancelPluginException, self).__init__(cancel_message) - - -class ErtPlugin(ErtScript): - - def getArguments(self, parent=None): - """ @rtype: list """ - return [] - - def getName(self): - """ @rtype: str """ - return str(self.__class__) - - def getDescription(self): - """ @rtype: str """ - return "No description provided!" - - def checkIfCancelled(self): - if self.isCancelled(): - raise CancelPluginException("Plugin '%s' cancelled by user!" % self.getName()) - - def startCancellableThread(self, runFunction, cancelFunction): - runFunction.return_value = None - - def runFunctionWrapper(): - runFunction.return_value = runFunction() - - thread = Thread() - thread.run = runFunctionWrapper - thread.start() - - while thread.isAlive(): - if self.isCancelled(): - cancelFunction() - - try: - time.sleep(0.1) - except KeyboardInterrupt: - print("Plugin '%s' cancelled (CTRL+C)" % self.getName()) - self.cancel() - - return runFunction.return_value diff --git a/ThirdParty/Ert/python/python/ert/job_queue/ert_script.py b/ThirdParty/Ert/python/python/ert/job_queue/ert_script.py deleted file mode 100644 index ab90c88a95..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/ert_script.py +++ /dev/null @@ -1,116 +0,0 @@ -import inspect -import imp -import sys -import traceback - -class ErtScript(object): - - def __init__(self, ert): - """ - @type ert: EnKFMain - """ - super(ErtScript, self).__init__() - - if not hasattr(self, "run"): - raise UserWarning("ErtScript implementations must provide a method run(self, ert, ...)") - - self.__verbose = False - self.__ert = ert - - self.__is_cancelled = False - self.__failed = False - - def isVerbose(self): - return self.__verbose - - def ert(self): - """ @rtype: ert.enkf.EnKFMain """ - return self.__ert - - def isCancelled(self): - """ @rtype: bool """ - return self.__is_cancelled - - def hasFailed(self): - """ @rtype: bool """ - return self.__failed - - def cancel(self): - self.__is_cancelled = True - - def cleanup(self): - """ - Override to perform cleanup after a run. - """ - pass - - def initializeAndRun(self, argument_types, argument_values, verbose=False): - """ - @type argument_types: list of type - @type argument_values: list of string - @type verbose: bool - @rtype: unknown - """ - self.__verbose = verbose - self.__failed = False - - arguments = [] - for index, arg_value in enumerate(argument_values): - if index < len(argument_types): - arg_type = argument_types[index] - else: - arg_type = str - - if arg_value is not None: - arguments.append(arg_type(arg_value)) - else: - arguments.append(None) - - try: - return self.run(*arguments) - except AttributeError as e: - if not hasattr(self, "run"): - self.__failed = True - return "Script '%s' has not implemented a 'run' function" % self.__class__.__name__ - return self.defaultStackTrace(e) - except KeyboardInterrupt: - return "Script '%s' cancelled (CTRL+C)" % self.__class__.__name__ - except Exception as e: - return self.defaultStackTrace(e) - finally: - self.cleanup() - - - __module_count = 0 # Need to have unique modules in case of identical object naming in scripts - - def defaultStackTrace(self, error): - sys.stderr.write("The script '%s' caused an error while running:\n" % self.__class__.__name__) - self.__failed = True - stack_trace = traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback) - return "".join(stack_trace) - - @staticmethod - def loadScriptFromFile(path): - """ @rtype: type ErtScript """ - try: - m = imp.load_source("ErtScriptModule_%d" % ErtScript.__module_count, path) - ErtScript.__module_count += 1 - return ErtScript.__findErtScriptImplementations(m) - except Exception as e: - sys.stderr.write("The script '%s' caused an error during load:\n" % path) - traceback.print_exception(sys.exc_type, sys.exc_value, None) - return None - - @staticmethod - def __findErtScriptImplementations(module): - """ @rtype: ErtScript """ - result = [] - predicate = lambda member : inspect.isclass(member) and member.__module__ == module.__name__ - for name, member in inspect.getmembers(module, predicate): - if ErtScript in inspect.getmro(member): - result.append(member) - - if len(result) != 1: - raise UserWarning("Must have (only) one implementation of ErtScript in a module!") - - return result[0] \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert/job_queue/ext_job.py b/ThirdParty/Ert/python/python/ert/job_queue/ext_job.py deleted file mode 100644 index 23be5b3cf7..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/ext_job.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'ext_job.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import os.path - -from cwrap import BaseCClass -from ert.job_queue import QueuePrototype - - -class ExtJob(BaseCClass): - TYPE_NAME = "ext_job" - _alloc = QueuePrototype("void* ext_job_alloc(char*, char*, int)", bind = False) - _fscanf_alloc = QueuePrototype("void* ext_job_fscanf_alloc(char*, char*, bool, char* , bool)", bind = False) - _free = QueuePrototype("void ext_job_free( ext_job )") - _get_help_text = QueuePrototype("char* ext_job_get_help_text(ext_job)") - _get_name = QueuePrototype("char* ext_job_get_name(ext_job)") - _get_private_args_as_string = QueuePrototype("char* ext_job_get_private_args_as_string(ext_job)") - _set_private_args_as_string = QueuePrototype("void ext_job_set_private_args_from_string(ext_job, char*)") - _is_private = QueuePrototype("int ext_job_is_private(ext_job)") - _get_config_file = QueuePrototype("char* ext_job_get_config_file(ext_job)") - _set_config_file = QueuePrototype("void ext_job_set_config_file(ext_job, char*)") - _get_stdin_file = QueuePrototype("char* ext_job_get_stdin_file(ext_job)") - _set_stdin_file = QueuePrototype("void ext_job_set_stdin_file(ext_job, char*)") - _get_stdout_file = QueuePrototype("char* ext_job_get_stdout_file(ext_job)") - _set_stdout_file = QueuePrototype("void ext_job_set_stdout_file(ext_job, char*)") - _get_stderr_file = QueuePrototype("char* ext_job_get_stderr_file(ext_job)") - _set_stderr_file = QueuePrototype("void ext_job_set_stderr_file(ext_job, char*)") - _get_target_file = QueuePrototype("char* ext_job_get_target_file(ext_job)") - _set_target_file = QueuePrototype("void ext_job_set_target_file(ext_job, char*)") - _get_executable = QueuePrototype("char* ext_job_get_executable(ext_job)") - _set_executable = QueuePrototype("void ext_job_set_executable(ext_job, char*)") - _get_max_running = QueuePrototype("int ext_job_get_max_running(ext_job)") - _set_max_running = QueuePrototype("void ext_job_set_max_running(ext_job, int)") - _get_max_running_minutes = QueuePrototype("int ext_job_get_max_running_minutes(ext_job)") - _set_max_running_minutes = QueuePrototype("void ext_job_set_max_running_minutes(ext_job, int)") - _get_environment = QueuePrototype("void* ext_job_get_environment(ext_job)") - _set_environment = QueuePrototype("void ext_job_add_environment(ext_job, char*, char*)") - _clear_environment = QueuePrototype("void ext_job_clear_environment(ext_job)") - _save = QueuePrototype("void ext_job_save(ext_job)") - - - def __init__(self, config_file, private, name = None , license_root_path = None , search_PATH = True): - if os.path.isfile( config_file ): - if name is None: - name = os.path.basename( config_file ) - - c_ptr = self._fscanf_alloc(name, license_root_path, private, config_file , search_PATH) - super(ExtJob, self).__init__(c_ptr) - else: - raise IOError("No such file:%s" % config_file) - - def __str__(self): - return "ExtJob(%s, config_file = %s)" % (self.name() , self.get_config_file()) - - - def get_private_args_as_string(self): - return self._get_private_args_as_string( ) - - def set_private_args_as_string(self, args): - self._set_private_args_as_string( args) - - def get_help_text(self): - return self._get_help_text( ) - - def is_private(self): - return self._is_private( ) - - def get_config_file(self): - return self._get_config_file( ) - - def set_config_file(self, config_file): - self._set_config_file( config_file) - - def get_stdin_file(self): - return self._get_stdin_file( ) - - def set_stdin_file(self, filename): - self._set_stdin_file( filename) - - def get_stdout_file(self): - return self._get_stdout_file( ) - - def set_stdout_file(self, filename): - self._set_stdout_file( filename) - - def get_stderr_file(self): - return self._get_stderr_file( ) - - def set_stderr_file(self, filename): - self._set_stderr_file( filename) - - def get_target_file(self): - return self._get_target_file( ) - - def set_target_file(self, filename): - self._set_target_file( filename) - - def get_executable(self): - return self._get_executable( ) - - def set_executable(self, executable): - self._set_executable( executable) - - def get_max_running(self): - return self._get_max_running( ) - - def set_max_running(self, max_running): - self._set_max_running( max_running) - - def get_max_running_minutes(self): - return self._get_max_running_minutes( ) - - def set_max_running_minutes(self, min_value): - self._set_max_running_minutes(min_value) - - def get_environment(self): - return self._get_environment( ) #warn: fix return type - - def set_environment(self, key, value): - self._set_environment( key, value) - - def clear_environment(self): - self._clear_environment( ) - - def save(self): - self._save( ) - - def free(self): - self._free( ) - - def name(self): - return self._get_name( ) - - - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/ext_joblist.py b/ThirdParty/Ert/python/python/ert/job_queue/ext_joblist.py deleted file mode 100644 index 341bcb98ff..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/ext_joblist.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'ext_joblist.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.job_queue import QueuePrototype, ExtJob -from ert.util import StringList - - -class ExtJoblist(BaseCClass): - TYPE_NAME = "ext_joblist" - _free = QueuePrototype("void ext_joblist_free( ext_joblist )") - _alloc_list = QueuePrototype("stringlist_ref ext_joblist_alloc_list(ext_joblist)") - _get_job = QueuePrototype("ext_job_ref ext_joblist_get_job(ext_joblist, char*)") - _del_job = QueuePrototype("int ext_joblist_del_job(ext_joblist, char*)") - _has_job = QueuePrototype("int ext_joblist_has_job(ext_joblist, char*)") - _add_job = QueuePrototype("void ext_joblist_add_job(ext_joblist, char*, ext_joblist)") - _get_jobs = QueuePrototype("hash_ref ext_joblist_get_jobs(ext_joblist)") - _size = QueuePrototype("int ext_joblist_get_size(ext_joblist)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def get_jobs(self): - """ @rtype: Hash """ - jobs = self._get_jobs( ) - jobs.setParent(self) - return jobs - - def __len__(self): - return self._size( ) - - def __contains__(self , job): - return self._has_job(job) - - def __iter__(self): - names = self.getAvailableJobNames() - for job in names: - yield self[job] - - - def __getitem__(self, job): - if job in self: - return self._get_job(job).setParent(self) - - - def getAvailableJobNames(self): - """ @rtype: StringList """ - return self._alloc_list( ).setParent(self) - - def del_job(self, job): - return self._del_job(job) - - def has_job(self, job): - return job in self - - def get_job(self, job): - """ @rtype: ExtJob """ - return self[job] - - def add_job(self, job_name, new_job): - self._add_job(job_name, new_job) - - def free(self): - self._free( ) - - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/external_ert_script.py b/ThirdParty/Ert/python/python/ert/job_queue/external_ert_script.py deleted file mode 100644 index 6757115868..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/external_ert_script.py +++ /dev/null @@ -1,25 +0,0 @@ -from subprocess import Popen -from ert.job_queue import ErtScript - - -class ExternalErtScript(ErtScript): - - def __init__(self, ert, executable): - super(ExternalErtScript, self).__init__(ert) - - self.__executable = executable - self.__job = None - - def run(self, *args): - command = [self.__executable] - command.extend([str(arg) for arg in args]) - self.__job = Popen(command) - self.__job.wait() # This should not be here? - return None - - def cancel(self): - super(ExternalErtScript, self).cancel() - if self.__job is not None: - self.__job.terminate() - - self.__job.kill() diff --git a/ThirdParty/Ert/python/python/ert/job_queue/forward_model.py b/ThirdParty/Ert/python/python/ert/job_queue/forward_model.py deleted file mode 100644 index bccf108f97..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/forward_model.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'forward_model.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCClass -from ert.job_queue import ExtJob, QueuePrototype -from ert.util import StringList - - -class ForwardModel(BaseCClass): - TYPE_NAME = "forward_model" - _free = QueuePrototype("void forward_model_free( forward_model )") - _clear = QueuePrototype("void forward_model_clear(forward_model)") - _add_job = QueuePrototype("ext_job_ref forward_model_add_job(forward_model, char*)") - _alloc_joblist = QueuePrototype("stringlist_obj forward_model_alloc_joblist(forward_model)") - _iget_job = QueuePrototype("ext_job_ref forward_model_iget_job( forward_model, int)") - - def __init__(self): - raise NotImplementedError("Class can not be instantiated directly!") - - def joblist(self): - """ @rtype: StringList """ - return self._alloc_joblist( ) - - def iget_job(self, index): - """ @rtype: ExtJob """ - return self._iget_job(index).setParent(self) - - def add_job(self, name): - """ @rtype: ExtJob """ - return self._.add_job(name).setParent(self) - - def clear(self): - self._clear( ) - - def free(self): - self._free( ) - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/function_ert_script.py b/ThirdParty/Ert/python/python/ert/job_queue/function_ert_script.py deleted file mode 100644 index 58028a7dde..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/function_ert_script.py +++ /dev/null @@ -1,64 +0,0 @@ -import ert as ert_module -from cwrap import Prototype - -from ert.job_queue import ErtScript -from ert.util.stringlist import StringList - - -class _NonePrototype(Prototype): - lib = ert_module.load(None) - - def __init__(self, prototype, bind=True): - super(_NonePrototype, self).__init__(_NonePrototype.lib, prototype, bind=bind) - - -class FunctionErtScript(ErtScript): - - def __init__(self, ert, function_name, argument_types, argument_count): - super(FunctionErtScript, self).__init__(ert) - - parsed_argument_types = [] - - if ert is not None: - self.__function = _NonePrototype("void* %s(void*, stringlist)" % function_name) - - else: - for arg in argument_types: - if arg is bool: - parsed_argument_types.append("bool") - elif arg is str: - parsed_argument_types.append("char*") - elif arg is int: - parsed_argument_types.append("int") - elif arg is float: - parsed_argument_types.append("float") - else: - raise TypeError("Unknown type: %s" % arg) - - self.__function = _NonePrototype("void* %s(%s)" % (function_name, ", ".join(parsed_argument_types[:argument_count]))) - - - def run(self, *args): - ert = self.ert() - if ert is None: - # This is usually used for testing purposes without an ert instance - return self.__function(*args) - else: - str_args = StringList() - for arg in args: - str_args.append(arg) - - if hasattr(ert, "from_param"): - pointer = ert.from_param(ert) - else: - pointer = ert # ... - - return self.__function(pointer, str_args) - - def cancel(self): - # job is not cancellable and will just ignore the call - pass - - - - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/job.py b/ThirdParty/Ert/python/python/ert/job_queue/job.py deleted file mode 100644 index 1bf64cf834..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/job.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'job.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -import time -import datetime -from cwrap import BaseCClass -from ert.job_queue import JobStatusType - -# This class and the interplay between this class and the Driver and -# JobQueue classes is quite fragile; in particular the Job class -# internalizes a void * pointer to the completely driver specific job -# information - this is way too low level. - -class Job(BaseCClass): - TYPE_NAME = "job" - - def __init__(self, c_ptr , driver ): - self.driver = driver - self.submit_time = datetime.datetime.now() - super(Job , self).__init__( c_ptr ) - - - def free(self): - pass - - - def block( self ): - while True: - status = self.status() - if status == JobStatusType.JOB_QUEUE_DONE or status == JobStatusType.JOB_QUEUE_EXIT: - break - else: - time.sleep(1) - - def kill( self ): - self.driver.kill_job(self) - - - @property - def run_time( self ): - td = datetime.datetime.now() - self.submit_time - return td.seconds + td.days * 24 * 3600 - - @property - def status( self ): - st = self.driver.get_status(self) - return st - - @property - def running( self ): - status = self.driver.get_status(self) - if status == JobStatusType.JOB_QUEUE_RUNNING: - return True - else: - return False - - - @property - def pending( self ): - status = self.driver.get_status(self) - if status == JobStatusType.JOB_QUEUE_PENDING: - return True - else: - return False - - @property - def complete( self ): - status = self.driver.get_status(self) - if status == JobStatusType.JOB_QUEUE_DONE or status == JobStatusType.JOB_QUEUE_EXIT: - return True - else: - return False - - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/job_queue_manager.py b/ThirdParty/Ert/python/python/ert/job_queue/job_queue_manager.py deleted file mode 100644 index 5cf6bf0166..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/job_queue_manager.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'job_queue_manager.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -""" -Module implementing a queue for managing external jobs. - -""" -from cwrap import BaseCClass -from ert.job_queue import QueuePrototype, Job, JobStatusType - -class JobQueueManager(BaseCClass): - TYPE_NAME = "job_queue_manager" - _alloc = QueuePrototype("void* job_queue_manager_alloc( job_queue)", bind = False) - _free = QueuePrototype("void job_queue_manager_free( job_queue_manager )") - _start_queue = QueuePrototype("void job_queue_manager_start_queue( job_queue_manager , int , bool, bool)") - _get_num_waiting = QueuePrototype("int job_queue_manager_get_num_waiting( job_queue_manager )") - _get_num_running = QueuePrototype("int job_queue_manager_get_num_running( job_queue_manager )") - _get_num_success = QueuePrototype("int job_queue_manager_get_num_success( job_queue_manager )") - _get_num_failed = QueuePrototype("int job_queue_manager_get_num_failed( job_queue_manager )") - _is_running = QueuePrototype("bool job_queue_manager_is_running( job_queue_manager )") - _job_complete = QueuePrototype("bool job_queue_manager_job_complete( job_queue_manager , int)") - _job_running = QueuePrototype("bool job_queue_manager_job_running( job_queue_manager , int)") - - # Note, even if all realizations have finished, they need not all be failed or successes. - # That is how Ert report things. They can be "killed", which is neither success nor failure. - _job_failed = QueuePrototype("bool job_queue_manager_job_failed( job_queue_manager , int)") - _job_waiting = QueuePrototype("bool job_queue_manager_job_waiting( job_queue_manager , int)") - _job_success = QueuePrototype("bool job_queue_manager_job_success( job_queue_manager , int)") - - # The return type of the job_queue_manager_iget_job_status should - # really be the enum job_status_type_enum, but I just did not - # manage to get the prototyping right. Have therefor taken the - # return as an integer and convert it in the getJobStatus() - # method. - _job_status = QueuePrototype("int job_queue_manager_iget_job_status(job_queue_manager, int)") - - def __init__(self, queue): - c_ptr = self._alloc(queue) - super(JobQueueManager, self).__init__(c_ptr) - - - def startQueue(self , total_size , verbose = False , reset_queue = True): - self._start_queue( total_size , verbose , reset_queue) - - def getNumRunning(self): - return self._get_num_running( ) - - def getNumWaiting(self): - return self._get_num_waiting( ) - - def getNumSuccess(self): - return self._get_num_success( ) - - def getNumFailed(self): - return self._get_num_failed( ) - - def isRunning(self): - return self._is_running( ) - - def free(self): - self._free( ) - - def isJobComplete(self, job_index): - return self._job_complete( job_index ) - - def isJobRunning(self, job_index): - return self._job_running( job_index ) - - def isJobWaiting(self, job_index): - return self._job_waiting( job_index ) - - def didJobFail(self, job_index): - return self._job_failed( job_index ) - - def didJobSucceed(self, job_index): - return self._job_success( job_index ) - - def getJobStatus(self, job_index): - # See comment about return type in the prototype section at - # the top of class. - """ @rtype: ert.job_queue.job_status_type_enum.JobStatusType """ - int_status = self._job_status(job_index) - return JobStatusType( int_status ) - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/job_status_type_enum.py b/ThirdParty/Ert/python/python/ert/job_queue/job_status_type_enum.py deleted file mode 100644 index 9744293875..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/job_status_type_enum.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'job_status_type_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from cwrap import BaseCEnum -from ert.job_queue import JOB_QUEUE_LIB - - -class JobStatusType(BaseCEnum): - TYPE_NAME = "job_status_type_enum" - JOB_QUEUE_NOT_ACTIVE = None # This value is used in external query routines - for jobs which are (currently) not active. */ - JOB_QUEUE_WAITING = None # A node which is waiting in the internal queue. - JOB_QUEUE_SUBMITTED = None # Internal status: It has has been submitted - the next status update will (should) place it as pending or running. - JOB_QUEUE_PENDING = None # A node which is pending - a status returned by the external system. I.e LSF - JOB_QUEUE_RUNNING = None # The job is running - JOB_QUEUE_DONE = None # The job is done - but we have not yet checked if the target file is produced */ - JOB_QUEUE_EXIT = None # The job has exited - check attempts to determine if we retry or go to complete_fail */ - JOB_QUEUE_IS_KILLED = None # The job has been killed, following a JOB_QUEUE_DO_KILL - can restart. */ - JOB_QUEUE_DO_KILL = None # The the job should be killed, either due to user request, or automated measures - the job can NOT be restarted.. */ - JOB_QUEUE_SUCCESS = None - JOB_QUEUE_RUNNING_CALLBACK = None - JOB_QUEUE_FAILED = None - JOB_QUEUE_DO_KILL_NODE_FAILURE = None - JOB_QUEUE_STATUS_FAILURE = None - - -JobStatusType.addEnum("JOB_QUEUE_NOT_ACTIVE", 1) -JobStatusType.addEnum("JOB_QUEUE_WAITING", 4) -JobStatusType.addEnum("JOB_QUEUE_SUBMITTED", 8) -JobStatusType.addEnum("JOB_QUEUE_PENDING", 16) -JobStatusType.addEnum("JOB_QUEUE_RUNNING", 32) -JobStatusType.addEnum("JOB_QUEUE_DONE", 64) -JobStatusType.addEnum("JOB_QUEUE_EXIT", 128) -JobStatusType.addEnum("JOB_QUEUE_IS_KILLED", 4096) -JobStatusType.addEnum("JOB_QUEUE_DO_KILL", 8192) -JobStatusType.addEnum("JOB_QUEUE_SUCCESS", 16384) -JobStatusType.addEnum("JOB_QUEUE_RUNNING_CALLBACK", 32768) -JobStatusType.addEnum("JOB_QUEUE_FAILED", 65536) -JobStatusType.addEnum("JOB_QUEUE_DO_KILL_NODE_FAILURE", 131072) -JobStatusType.addEnum("JOB_QUEUE_STATUS_FAILURE", 262144) diff --git a/ThirdParty/Ert/python/python/ert/job_queue/queue.py b/ThirdParty/Ert/python/python/ert/job_queue/queue.py deleted file mode 100644 index e6a08747d1..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/queue.py +++ /dev/null @@ -1,260 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'job_queue.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -""" -Module implementing a queue for managing external jobs. - -""" -import sys -from types import StringType, IntType -import time -import ctypes - -from cwrap import BaseCClass,BaseCEnum - -from ert.job_queue import QueuePrototype -from ert.job_queue import Job, JobStatusType - - -class JobQueue(BaseCClass): - # If the queue is created with size == 0 that means that it will - # just grow as needed; for the queue layer to know when to exit - # you must call the function submit_complete() when you have no - # more jobs to submit. - # - # If the number of jobs is known in advance you can create the - # queue with a finite value for size, in that case it is not - # necessary to explitly inform the queue layer when all jobs have - # been submitted. - TYPE_NAME = "job_queue" - _alloc = QueuePrototype("void* job_queue_alloc( int , char* , char* , char* )" , bind = False) - _start_user_exit = QueuePrototype("bool job_queue_start_user_exit( job_queue )") - _get_user_exit = QueuePrototype("bool job_queue_get_user_exit( job_queue )") - _free = QueuePrototype("void job_queue_free( job_queue )") - _set_max_running = QueuePrototype("void job_queue_set_max_running( job_queue , int)") - _get_max_running = QueuePrototype("int job_queue_get_max_running( job_queue )") - _set_max_job_duration = QueuePrototype("void job_queue_set_max_job_duration( job_queue , int)") - _get_max_job_duration = QueuePrototype("int job_queue_get_max_job_duration( job_queue )") - _set_driver = QueuePrototype("void job_queue_set_driver( job_queue , void* )") - _add_job = QueuePrototype("int job_queue_add_job( job_queue , char* , void* , void* , void* , void* , int , char* , char* , int , char**)") - _kill_job = QueuePrototype("bool job_queue_kill_job( job_queue , int )") - _start_queue = QueuePrototype("void job_queue_run_jobs( job_queue , int , bool)") - _run_jobs = QueuePrototype("void job_queue_run_jobs_threaded(job_queue , int , bool)") - _sim_start = QueuePrototype("time_t job_queue_iget_sim_start( job_queue , int)") - _iget_driver_data = QueuePrototype("void* job_queue_iget_driver_data( job_queue , int)") - - _num_running = QueuePrototype("int job_queue_get_num_running( job_queue )") - _num_complete = QueuePrototype("int job_queue_get_num_complete( job_queue )") - _num_waiting = QueuePrototype("int job_queue_get_num_waiting( job_queue )") - _num_pending = QueuePrototype("int job_queue_get_num_pending( job_queue )") - - _is_running = QueuePrototype("bool job_queue_is_running( job_queue )") - _submit_complete = QueuePrototype("void job_queue_submit_complete( job_queue )") - _iget_sim_start = QueuePrototype("time_t job_queue_iget_sim_start( job_queue , int)") - _get_active_size = QueuePrototype("int job_queue_get_active_size( job_queue )") - _get_pause = QueuePrototype("bool job_queue_get_pause(job_queue)") - _set_pause_on = QueuePrototype("void job_queue_set_pause_on(job_queue)") - _set_pause_off = QueuePrototype("void job_queue_set_pause_off(job_queue)") - - # The return type of the job_queue_iget_job_status should really - # be the enum job_status_type_enum, but I just did not manage to - # get the prototyping right. Have therefor taken the return as an - # integer and convert it in the getJobStatus() method. - _get_job_status = QueuePrototype("int job_queue_iget_job_status(job_queue, int)") - - - def __init__(self, driver , max_submit=1, size=0): - """ - Short doc... - - The @size argument is used to say how many jobs the queue will - run, in total. - - size = 0: That means that you do not tell the queue in - advance how many jobs you have. The queue will just run - all the jobs you add, but you have to inform the queue in - some way that all jobs have been submitted. To achieve - this you should call the submit_complete() method when all - jobs have been submitted.# - - size > 0: The queue will know exactly how many jobs to run, - and will continue until this number of jobs have completed - - it is not necessary to call the submit_complete() method - in this case. - """ - - OK_file = None - status_file = None - exit_file = None - - c_ptr = self._alloc(max_submit, OK_file, status_file , exit_file) - super(JobQueue, self).__init__(c_ptr) - self.size = size - - self.driver = driver - self._set_driver(driver.from_param(driver)) - self.start( blocking=False ) - - - def kill_job(self, queue_index): - """ - Will kill job nr @index. - """ - self._kill_job( queue_index ) - - - def start( self, blocking=False): - verbose = False - self._run_jobs(self.size, verbose) - - - def submit( self, cmd, run_path, job_name, argv, num_cpu=1): - c_argv = (ctypes.c_char_p * len(argv))() - c_argv[:] = argv - - done_callback = None - callback_arg = None - retry_callback = None - exit_callback = None - - queue_index = self._add_job(cmd, - done_callback, - retry_callback, - exit_callback, - callback_arg, - num_cpu, - run_path, - job_name, - len(argv), - c_argv) - - return queue_index - - - def clear( self ): - pass - - def block_waiting( self ): - """ - Will block as long as there are waiting jobs. - """ - while self.num_waiting > 0: - time.sleep(1) - - def block(self): - """ - Will block as long as there are running jobs. - """ - while self.isRunning: - time.sleep(1) - - - def submit_complete( self ): - """ - Method to inform the queue that all jobs have been submitted. - - If the queue has been created with size == 0 the queue has no - way of knowing when all jobs have completed; hence in that - case you must call the submit_complete() method when all jobs - have been submitted. - - If you know in advance exactly how many jobs you will run that - should be specified with the size argument when creating the - queue, in that case it is not necessary to call the - submit_complete() method. - """ - self._submit_complete( ) - - - def isRunning(self): - return self._is_running( ) - - def num_running( self ): - return self._num_running( ) - - def num_pending( self ): - return self._.num_pending( ) - - def num_waiting( self ): - return self._num_waiting( ) - - def num_complete( self ): - return self._num_complete( ) - - def exists(self, index): - job = self.__getitem__(index) - if job: - return True - else: - return False - - def get_max_running( self ): - return self.driver.get_max_running() - - def set_max_running( self, max_running ): - self.driver.set_max_running(max_running) - - def get_max_job_duration(self): - return self._get_max_job_duration() - - def set_max_job_duration(self, max_duration): - self._set_max_job_duration(max_duration) - - def killAllJobs(self): - # The queue will not set the user_exit flag before the - # queue is in a running state. If the queue does not - # change to running state within a timeout the C function - # will return False, and that False value is just passed - # along. - user_exit = self._start_user_exit( ) - if user_exit: - while self.isRunning(): - time.sleep(0.1) - return True - else: - return False - - def igetSimStart(self, job_index): - return self._iget_sim_start( self , job_index ) - - - def getUserExit(self): - # Will check if a user_exit has been initated on the job. The - # queue can be queried about this status until a - # job_queue_reset() call is invoked, and that should not be - # done before the queue is recycled to run another batch of - # simulations. - return self._get_user_exit( ) - - def set_pause_on(self): - self._set_pause_on( ) - - def set_pause_off(self): - self._set_pause_off( ) - - def free(self): - self._free( ) - - def __len__(self): - return self._get_active_size( ) - - def getJobStatus(self, job_number): - # See comment about return type in the prototype section at - # the top of class. - """ @rtype: JobStatusType """ - int_status = self._get_job_status(job_number) - return JobStatusType( int_status ) - - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/workflow.py b/ThirdParty/Ert/python/python/ert/job_queue/workflow.py deleted file mode 100644 index c43b667242..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/workflow.py +++ /dev/null @@ -1,105 +0,0 @@ -import time -from ert.config import ConfigError -from cwrap import BaseCClass -from ert.job_queue import QueuePrototype, WorkflowJoblist, WorkflowJob -from ert.util import SubstitutionList - - -class Workflow(BaseCClass): - TYPE_NAME = "workflow" - _alloc = QueuePrototype("void* workflow_alloc(char*, workflow_joblist)" , bind = False) - _free = QueuePrototype("void workflow_free(workflow)") - _count = QueuePrototype("int workflow_size(workflow)") - _iget_job = QueuePrototype("workflow_job_ref workflow_iget_job(workflow, int)") - _iget_args = QueuePrototype("stringlist_ref workflow_iget_arguments(workflow, int)") - - _try_compile = QueuePrototype("bool workflow_try_compile(workflow, subst_list)") - _get_last_error = QueuePrototype("config_error_ref workflow_get_last_error(workflow)") - - def __init__(self, src_file, job_list): - """ - @type src_file: str - @type job_list: WorkflowJoblist - """ - c_ptr = self._alloc(src_file, job_list) - super(Workflow, self).__init__(c_ptr) - - self.__running = False - self.__cancelled = False - self.__current_job = None - - def __len__(self): - return self._count( ) - - def __getitem__(self, index): - """ - @type index: int - @rtype: tuple of (WorkflowJob, arguments) - """ - job = self._iget_job(index) - args = self._iget_args(index) - return job, args - - - def __iter__(self): - for index in range(len(self)): - yield self[index] - - def run(self, ert, verbose=False, context=None): - """ - @type ert: ert.enkf.enkf_main.EnKFMain - @type verbose: bool - @type context: SubstitutionList - @rtype: bool - """ - self.__running = True - success = self._try_compile(context) - - if success: - for job, args in self: - self.__current_job = job - if not self.__cancelled: - return_value = job.run(ert, args, verbose) - - if job.hasFailed(): - print(return_value) - - #todo store results? - - self.__current_job = None - self.__running = False - return success - - - def free(self): - self._free( ) - - def isRunning(self): - return self.__running - - def cancel(self): - if self.__current_job is not None: - self.__current_job.cancel() - - self.__cancelled = True - - def isCancelled(self): - return self.__cancelled - - def wait(self): - while self.isRunning(): - time.sleep(1) - - def getLastError(self): - """ @rtype: ConfigError """ - return self._get_last_error( ) - - @classmethod - def createCReference(cls, c_pointer, parent=None): - workflow = super(Workflow, cls).createCReference(c_pointer, parent) - workflow.__running = False - workflow.__cancelled = False - workflow.__current_job = None - return workflow - - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/workflow_job.py b/ThirdParty/Ert/python/python/ert/job_queue/workflow_job.py deleted file mode 100644 index 2baef729cc..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/workflow_job.py +++ /dev/null @@ -1,181 +0,0 @@ -import os - -from cwrap import BaseCClass -from ert.job_queue import QueuePrototype, ErtScript, FunctionErtScript, ErtPlugin, ExternalErtScript -from ert.config import ContentTypeEnum - - -class WorkflowJob(BaseCClass): - TYPE_NAME = "workflow_job" - _alloc = QueuePrototype("void* workflow_job_alloc(char*, bool)", bind= False) - _alloc_parser = QueuePrototype("config_parser_obj workflow_job_alloc_config( )", bind= False) - _alloc_from_file = QueuePrototype("workflow_job_obj workflow_job_config_alloc( char* , config_parser , char*)", bind= False) - _free = QueuePrototype("void workflow_job_free(workflow_job)") - _name = QueuePrototype("char* workflow_job_get_name(workflow_job)") - _internal = QueuePrototype("bool workflow_job_internal(workflow_job)") - _is_internal_script = QueuePrototype("bool workflow_job_is_internal_script(workflow_job)") - _get_internal_script = QueuePrototype("char* workflow_job_get_internal_script_path(workflow_job)") - _get_function = QueuePrototype("char* workflow_job_get_function(workflow_job)") - _get_module = QueuePrototype("char* workflow_job_get_module(workflow_job)") - _get_executable = QueuePrototype("char* workflow_job_get_executable(workflow_job)") - _min_arg = QueuePrototype("int workflow_job_get_min_arg(workflow_job)") - _max_arg = QueuePrototype("int workflow_job_get_max_arg(workflow_job)") - _arg_type = QueuePrototype("config_content_type_enum workflow_job_iget_argtype(workflow_job, int)") - - - - @classmethod - def configParser(cls): - return cls._alloc_parser( ) - - @classmethod - def fromFile(cls , config_file , name = None , parser = None): - if os.path.isfile( config_file ) and os.access( config_file , os.R_OK): - if parser is None: - parser = cls.configParser( ) - - if name is None: - name = os.path.basename( config_file ) - - # NB: Observe argument reoredring. - return cls._alloc_from_file( name , parser , config_file ) - else: - raise IOError("Could not open config_file:%s" % config_file) - - - def __init__(self, name, internal=True): - c_ptr = self._alloc(name, internal) - super(WorkflowJob, self).__init__(c_ptr) - - self.__script = None - """ :type: ErtScript """ - self.__running = False - - def isInternal(self): - """ @rtype: bool """ - return self._internal( ) - - def name(self): - """ @rtype: str """ - return self._name() - - def minimumArgumentCount(self): - """ @rtype: int """ - return self._min_arg() - - def maximumArgumentCount(self): - """ @rtype: int """ - return self._max_arg( ) - - def functionName(self): - """ @rtype: str """ - return self._get_function( ) - - def module(self): - """ @rtype: str """ - return self._get_module( ) - - def executable(self): - """ @rtype: str """ - return self._get_executable( ) - - def isInternalScript(self): - """ @rtype: bool """ - return self._is_internal_script( ) - - def getInternalScriptPath(self): - """ @rtype: str """ - return self._get_internal_script( ) - - def isPlugin(self): - """ @rtype: bool """ - if self.isInternalScript(): - script_obj = ErtScript.loadScriptFromFile(self.getInternalScriptPath()) - return script_obj is not None and issubclass(script_obj, ErtPlugin) - - return False - - - def argumentTypes(self): - """ @rtype: list of type """ - - result = [] - for index in range(self.maximumArgumentCount()): - t = self._arg_type(index) - if t == ContentTypeEnum.CONFIG_BOOL: - result.append(bool) - elif t == ContentTypeEnum.CONFIG_FLOAT: - result.append(float) - elif t == ContentTypeEnum.CONFIG_INT: - result.append(int) - elif t == ContentTypeEnum.CONFIG_STRING: - result.append(str) - else: - result.append(None) - - return result - - - def run(self, ert, arguments, verbose=False): - """ - @type ert: ert.enkf.enkf_main.EnKFMain - @type arguments: list of str - @type verbose: bool - @rtype: ctypes.c_void_p - """ - self.__running = True - - min_arg = self.minimumArgumentCount() - if min_arg > 0 and len(arguments) < min_arg: - raise UserWarning("The job: %s requires at least %d arguments, %d given." % (self.name(), min_arg, len(arguments))) - - max_arg = self.maximumArgumentCount() - if 0 < max_arg < len(arguments): - raise UserWarning("The job: %s can only have %d arguments, %d given." % (self.name(), max_arg, len(arguments))) - - - if self.isInternalScript(): - script_obj = ErtScript.loadScriptFromFile(self.getInternalScriptPath()) - self.__script = script_obj(ert) - result = self.__script.initializeAndRun(self.argumentTypes(), arguments, verbose=verbose) - - elif self.isInternal() and not self.isInternalScript(): - self.__script = FunctionErtScript(ert, self.functionName(), self.argumentTypes(), argument_count=len(arguments)) - result = self.__script.initializeAndRun(self.argumentTypes(), arguments, verbose=verbose) - - elif not self.isInternal(): - self.__script = ExternalErtScript(ert, self.executable()) - result = self.__script.initializeAndRun(self.argumentTypes(), arguments, verbose=verbose) - - else: - raise UserWarning("Unknown script type!") - - self.__running = False - return result - - def cancel(self): - if self.__script is not None: - self.__script.cancel() - - def isRunning(self): - return self.__running - - def isCancelled(self): - return self.__script.isCancelled() - - def hasFailed(self): - """ @rtype: bool """ - return self.__script.hasFailed() - - def free(self): - self._free( ) - - - @classmethod - def createCReference(cls, c_pointer, parent=None): - workflow = super(WorkflowJob, cls).createCReference(c_pointer, parent) - workflow.__script = None - workflow.__running = False - return workflow - - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/workflow_joblist.py b/ThirdParty/Ert/python/python/ert/job_queue/workflow_joblist.py deleted file mode 100644 index e5001d1b5d..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/workflow_joblist.py +++ /dev/null @@ -1,66 +0,0 @@ -import os -from cwrap import BaseCClass -from ert.job_queue import QueuePrototype, WorkflowJob - - -class WorkflowJoblist(BaseCClass): - TYPE_NAME = "workflow_joblist" - _alloc = QueuePrototype("void* workflow_joblist_alloc()" , bind = False) - _free = QueuePrototype("void workflow_joblist_free(workflow_joblist)") - _add_job = QueuePrototype("void workflow_joblist_add_job(workflow_joblist, workflow_job)") - _add_job_from_file = QueuePrototype("bool workflow_joblist_add_job_from_file(workflow_joblist, char*, char*)") - _has_job = QueuePrototype("bool workflow_joblist_has_job(workflow_joblist, char*)") - _get_job = QueuePrototype("workflow_job_ref workflow_joblist_get_job(workflow_joblist, char*)") - _count = QueuePrototype("workflow_job_ref workflow_joblist_get_job(workflow_joblist, char*)") - - def __init__(self): - c_ptr = self._alloc( ) - super(WorkflowJoblist, self).__init__(c_ptr) - - - def addJob(self, job): - """ @type job: WorkflowJob """ - job.convertToCReference(self) - self._add_job(job) - - - def addJobFromFile(self, name, filepath): - """ - @type name: str - @type filepath: str - @rtype: bool - """ - if not os.path.exists(filepath): - raise UserWarning("Job file '%s' does not exist!" % filepath) - - return self._add_job_from_file(name, filepath) - - - def __contains__(self, item): - """ - @type item: str or WorkflowJob - @rtype: bool - """ - - if isinstance(item, WorkflowJob): - item = item.name() - - return self._has_job(item) - - - def __getitem__(self, item): - """ - @type item: str - @rtype: WorkflowJob - """ - - if not item in self: - return None - - return self._get_job(item) - - - - def free(self): - self._free( ) - diff --git a/ThirdParty/Ert/python/python/ert/job_queue/workflow_runner.py b/ThirdParty/Ert/python/python/ert/job_queue/workflow_runner.py deleted file mode 100644 index a281c0d738..0000000000 --- a/ThirdParty/Ert/python/python/ert/job_queue/workflow_runner.py +++ /dev/null @@ -1,63 +0,0 @@ -from threading import Thread -from ert.job_queue import Workflow -from ert.util.substitution_list import SubstitutionList - - -class WorkflowRunner(object): - def __init__(self, workflow, ert=None, context=None): - """ - @type workflow: Workflow - @type ert: ert.enkf.EnKFMain - @type context: SubstitutionList - """ - super(WorkflowRunner, self).__init__() - - self.__workflow = workflow - self.__ert = ert - - if context is None: - context = SubstitutionList() - - self.__context = context - self.__workflow_result = None - - def run(self): - workflow_thread = Thread(name="ert_gui_workflow_thread") - workflow_thread.setDaemon(True) - workflow_thread.run = self.__runWorkflow - workflow_thread.start() - - def __runWorkflow(self): - self.__workflow_result = self.__workflow.run(self.__ert, context=self.__context) - - def isRunning(self): - """ @rtype: bool """ - return self.__workflow.isRunning() - - def isCancelled(self): - """ @rtype: bool """ - return self.__workflow.isCancelled() - - def cancel(self): - if self.isRunning(): - self.__workflow.cancel() - - def wait(self): - self.__workflow.wait() - - def workflowResult(self): - """ @rtype: bool or None """ - return self.__workflow_result - - def workflowError(self): - """ @rtype: str """ - error = self.__workflow.getLastError() - - error_message = "" - - for error_line in error: - error_message += error_line + "\n" - - return error_message - - diff --git a/ThirdParty/Ert/python/python/ert/rms/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/rms/CMakeLists.txt deleted file mode 100644 index d1aab7db53..0000000000 --- a/ThirdParty/Ert/python/python/ert/rms/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - librms.py - rms.py -) - -add_python_package("python.ert.rms" ${PYTHON_INSTALL_PREFIX}/ert/rms "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/rms/__init__.py b/ThirdParty/Ert/python/python/ert/rms/__init__.py deleted file mode 100644 index 1178612a7d..0000000000 --- a/ThirdParty/Ert/python/python/ert/rms/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -import ert -import ert.util -import ert.geo -import ert.ecl - -RMS_LIB = ert.load("librms") diff --git a/ThirdParty/Ert/python/python/ert/rms/librms.py b/ThirdParty/Ert/python/python/ert/rms/librms.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/python/ert/rms/rms.py b/ThirdParty/Ert/python/python/ert/rms/rms.py deleted file mode 100644 index 6feca3459e..0000000000 --- a/ThirdParty/Ert/python/python/ert/rms/rms.py +++ /dev/null @@ -1 +0,0 @@ -import librms diff --git a/ThirdParty/Ert/python/python/ert/server/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/server/CMakeLists.txt deleted file mode 100644 index 8ea8e29f02..0000000000 --- a/ThirdParty/Ert/python/python/ert/server/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - ertrpcclient.py - ertrpcserver.py - simulation_context.py -) - -add_python_package("python.ert.server" ${PYTHON_INSTALL_PREFIX}/ert/server "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/server/__init__.py b/ThirdParty/Ert/python/python/ert/server/__init__.py deleted file mode 100644 index 7138833de3..0000000000 --- a/ThirdParty/Ert/python/python/ert/server/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .simulation_context import SimulationContext -from .ertrpcclient import ErtRPCClient -from .ertrpcserver import ErtRPCServer diff --git a/ThirdParty/Ert/python/python/ert/server/ertrpcclient.py b/ThirdParty/Ert/python/python/ert/server/ertrpcclient.py deleted file mode 100644 index 89eea54b53..0000000000 --- a/ThirdParty/Ert/python/python/ert/server/ertrpcclient.py +++ /dev/null @@ -1,228 +0,0 @@ -import socket -from xmlrpclib import ServerProxy, Fault - -FAULT_CODES = {1: UserWarning, - 2: KeyError, - 3: IndexError, - 4: LookupError, - 5: TypeError - } - - -def convertFault(fault): - if fault.faultCode in FAULT_CODES: - fault_type = FAULT_CODES[fault.faultCode] - raise fault_type(fault.faultString) - else: - raise fault - - -class ErtRPCClient(object): - def __init__(self, host, port, verbose=False): - self._server_proxy = ServerProxy("http://%s:%s" % (host, port), allow_none=True, verbose=verbose) - socket.setdefaulttimeout(180) # 3 minutes - - def ertVersion(self): - """ - Returns a version tuple: (major, minor, micro) - @rtype: tuple - """ - return tuple(self._server_proxy.ertVersion()) - - def getTimeMap(self, target_case_name): - """ - Returns a list of datetime objects for the named target case name - @type target_case_name: str - @rtype: list of datetime - """ - return self._server_proxy.getTimeMap(target_case_name) - - - def isRunning(self): - """ - Returns True if a simulation batch has been started and is running. - @rtype: bool - """ - return self._server_proxy.isRunning() - - - def isInitializationCaseAvailable(self): - """ - Returns True if the initialization case is prepared and ready to run simulations. - @rtype: bool - """ - return self._server_proxy.isInitializationCaseAvailable() - - - def startSimulationBatch(self, initialization_case_name, simulation_count): - """ - Start a simulation batch. Will prepare a batch that will run for the specified number of realizations. - Will fail if the server is already running a batch or no initialization case is available. - @param initialization_case_name: The case containing geo realizations - @type initialization_case_name: str - @type simulation_count: int - """ - try: - self._server_proxy.startSimulationBatch(initialization_case_name, simulation_count) - except Fault as f: - raise convertFault(f) - - - def addSimulation(self, target_case_name, geo_id, pert_id, sim_id, keywords): - """ - Start a simulation. - @type target_case_name: str - @type geo_id: int - @type pert_id: - @type sim_id: int - @type keywords: dict[str, list] - @raise UserWarning if the server is not ready to receive simulations - @raise UserWarning if the server is already running a simulation with the same id as sim_id - """ - try: - self._server_proxy.addSimulation(target_case_name, geo_id, pert_id, sim_id, keywords) - except Fault as f: - raise convertFault(f) - - - def isRealizationFinished(self, sim_id): - """ - Returns true if the realization is finished running. - @type sim_id: int - @rtype: bool - """ - return self._server_proxy.isRealizationFinished(sim_id) - - def didRealizationSucceed(self, sim_id): - """ - Check if the realization successfully finished running. - @type sim_id: int - @rtype: bool - """ - return self._server_proxy.didRealizationSucceed(sim_id) - - def didRealizationFail(self, sim_id): - """ - Check if the realization failed while running. - @type sim_id: int - @rtype: bool - """ - return self._server_proxy.didRealizationFail(sim_id) - - def getGenDataResult(self, target_case_name, sim_id, report_step, keyword): - """ - Retrieve a GenData result from a target case - @type target_case_name: str - @type sim_id: int - @type report_step: int - @type keyword: str - @rtype: list[float] - @raise KeyError if the server was unable to recognize the keyword - @raise UserWarning if the server was unable to load the data - @raise UserWarning if the simulation (with sim_id) is still running - @raise UserWarning if the keyword is not of the correct type - """ - try: - return self._server_proxy.getGenDataResult(target_case_name, sim_id, report_step, keyword) - except Fault as f: - raise convertFault(f) - - def getCustomKWResult(self, target_case_name, sim_id, keyword): - """ - Retrieve a CustomKW result from the target case. - @type target_case_name: str - @type sim_id: int - @type keyword: str - @rtype: dict[str, Union[float,str]] - @raise KeyError if the server was unable to recognize the keyword - @raise UserWarning if the server was unable to load the data - @raise UserWarning if the simulation (with sim_id) is still running - @raise UserWarning if the keyword is not of the correct type - """ - try: - return self._server_proxy.getCustomKWResult(target_case_name, sim_id, keyword) - except Fault as f: - raise convertFault(f) - - def isCustomKWKey(self, key): - """ - Check if a key is of CustomKW type - @param key: The key to check - @type key: str - @rtype: bool - """ - return self._server_proxy.isCustomKWKey(key) - - def isGenDataKey(self, key): - """ - Check if a key is of CustomKW type - @param key: The key to check - @type key: str - @rtype: bool - """ - return self._server_proxy.isGenDataKey(key) - - - def prototypeStorage(self, group_name, storage_definition): - """ - Define the CustomKW with group name and fields with types. - @param group_name: The group name for the CustomKW - @type group_name: str - @param storage_definition: A dictionary with field names (keywords) and types (str or float) - @type storage_definition: dict[str, type] - @raise UserWarning if the group name already exists - @raise TypeError if the type of a keyword/field is unsupported - """ - - converted = {} - for key, value in storage_definition.iteritems(): - if value in (float, str): - value_name = value.__name__ - else: - raise TypeError("Unsupported data type for key: '%s', not one of (float, str): '%s'" % (key, value)) - converted[key] = value_name - try: - self._server_proxy.prototypeStorage(group_name, converted) - except Fault as f: - raise convertFault(f) - - - def storeGlobalData(self, target_case_name, group_name, keyword, value): - """ - Store a value as a CustomKW with group name and keyword. The value will - be stored in all simulations that at least has been initialized. - @param target_case_name: Name of target case - @type target_case_name: str - @param group_name: The name of the CustomKW group - @type group_name: str - @param keyword: The name of the CustomKW keyword - @type keyword: str - @param value: The value to store - @type value: float|int|str - @raise UserWarning if there were issues with the storing - """ - try: - self._server_proxy.storeGlobalData(target_case_name, group_name, keyword, value) - except Fault as f: - raise convertFault(f) - - - def storeSimulationData(self, target_case_name, group_name, keyword, value, sim_id): - """ - Store a single value in a single simulation as a CustomKW with groupname and keyword. - @param target_case_name: Name of target case - @type target_case_name: str - @param group_name: The name of the CustomKW group - @type group_name: str - @param keyword: The name of the CustomKW keyword - @type keyword: str - @param value: The value to store - @type value: float|int|str - @param sim_id: The simulation id (index) - @type sim_id: int - """ - try: - self._server_proxy.storeSimulationData(target_case_name, group_name, keyword, value, sim_id) - except Fault as f: - raise convertFault(f) - diff --git a/ThirdParty/Ert/python/python/ert/server/ertrpcserver.py b/ThirdParty/Ert/python/python/ert/server/ertrpcserver.py deleted file mode 100644 index 09422f69e0..0000000000 --- a/ThirdParty/Ert/python/python/ert/server/ertrpcserver.py +++ /dev/null @@ -1,342 +0,0 @@ -import os -from SimpleXMLRPCServer import SimpleXMLRPCServer -from threading import Lock -from xmlrpclib import Fault - -from ert import Version -from ert.enkf import EnKFMain, NodeId -from ert.enkf.config import CustomKWConfig -from ert.enkf.data import EnkfNode, CustomKW -from ert.enkf.enums import RealizationStateEnum, EnkfVarType, ErtImplType -from ert.server import SimulationContext -from ert.server.ertrpcclient import FAULT_CODES - - -def checkRealizationState(state): - return state == RealizationStateEnum.STATE_INITIALIZED or state == RealizationStateEnum.STATE_HAS_DATA - - -class Session: - def __init__(self): - self.init_case_name = None - """ :type: str """ - - self.simulation_context = None - """ :type: SimulationContext """ - - self.batch_number = 0 - self.lock = Lock() - - -INVERSE_FAULT_CODES = {value:key for key, value in FAULT_CODES.iteritems()} - -def createFault(error, message): - error_code = INVERSE_FAULT_CODES[error] - return Fault(error_code, message) - - - -class ErtRPCServer(SimpleXMLRPCServer): - def __init__(self, config, host="localhost", port=0, log_requests=False, verbose_queue=False): - SimpleXMLRPCServer.__init__(self, (host, port), allow_none=True, logRequests=log_requests) - self._host = host - self._verbose_queue = verbose_queue - # https: server.socket = ssl.wrap_socket(srv.socket, ...) - - if isinstance(config, EnKFMain): - self._config = config - self._config_file = config.getUserConfigFile() - else: - if os.path.exists(config): - self._config = EnKFMain(config) - self._config_file = config - else: - raise IOError("The ert config file: %s does not exist" % config) - - self._session = Session() - - self.register_function(self.ertVersion) - self.register_function(self.getTimeMap) - self.register_function(self.isRunning) - self.register_function(self.isInitializationCaseAvailable) - self.register_function(self.startSimulationBatch) - self.register_function(self.addSimulation) - self.register_function(self.isRealizationFinished) - self.register_function(self.didRealizationSucceed) - self.register_function(self.didRealizationFail) - self.register_function(self.getGenDataResult) - self.register_function(self.getCustomKWResult) - self.register_function(self.isCustomKWKey) - self.register_function(self.isGenDataKey) - self.register_function(self.prototypeStorage) - self.register_function(self.storeGlobalData) - self.register_function(self.storeSimulationData) - - @property - def port(self): - return self.server_address[1] - - @property - def host(self): - return self._host - - @property - def ert(self): - return self._config - - def start(self): - self.serve_forever() - - def stop(self): - if self._session.simulation_context is not None: - if self._session.simulation_context.isRunning(): - self.ert.siteConfig().getJobQueue().killAllJobs() - self.shutdown() - self.server_close() - self._config = None - - def ertVersion(self): - return Version.currentVersion().versionTuple() - - def getTimeMap(self, target_case_name): - enkf_fs_manager = self.ert.getEnkfFsManager() - enkf_fs = enkf_fs_manager.getFileSystem(target_case_name) - time_map = enkf_fs.getTimeMap() - return [time_step.datetime() for time_step in time_map] - - def isRunning(self): - if self._session.simulation_context is not None: - return self._session.simulation_context.isRunning() - return False - - def isRealizationFinished(self, iens): - if self._session.simulation_context is None: - raise createFault(UserWarning, "The simulation batch has not been initialized") - - if self._session.simulation_context.isRealizationQueued(iens): - return self._session.simulation_context.isRealizationFinished(iens) - return False - - def didRealizationSucceed(self, iens): - if self._session.simulation_context is not None and self._session.simulation_context.isRealizationQueued(iens): - return self._session.simulation_context.didRealizationSucceed(iens) - return False - - def didRealizationFail(self, iens): - if self._session.simulation_context is not None and self._session.simulation_context.isRealizationQueued(iens): - return self._session.simulation_context.didRealizationFail(iens) - return False - - - def isInitializationCaseAvailable(self): - return self._session.init_case_name is not None - - - def startSimulationBatch(self, initialization_case_name, simulation_count): - with self._session.lock: - if not self.isRunning(): - self._session.simulation_context = None - self._session.init_case_name = initialization_case_name - - self.ert.addDataKW("", str(self._session.batch_number)) - self.ert.addDataKW("", str(self._session.batch_number)) - self._session.batch_number += 1 - self._session.simulation_context = SimulationContext(self.ert, simulation_count, verbose=self._verbose_queue) - - - def _getInitializationCase(self): - return self.ert.getEnkfFsManager().getFileSystem(self._session.init_case_name) - - - def addSimulation(self, target_case_name, geo_id, pert_id, iens, keywords): - if not self.isRunning(): - raise createFault(UserWarning, "The server is not ready to receive simulations. Have you called startSimulationBatch() first?") - - if self._session.simulation_context.isRealizationQueued(iens): - raise createFault(UserWarning, "Simulation with id: '%d' is already running." % iens) - - state = self.ert.getRealisation(iens) - state.addSubstKeyword("GEO_ID", "%d" % geo_id) - target_fs = self.ert.getEnkfFsManager().getFileSystem(target_case_name) - self._initializeRealization(target_fs, geo_id, iens, keywords) - self._session.simulation_context.addSimulation(iens, target_fs) - - if not target_case_name.startswith("."): - self.ert.getEnkfFsManager().switchFileSystem(target_fs) - - - def _initializeRealization(self, target_fs, geo_id, iens, keywords): - ens_config = self.ert.ensembleConfig() - - for kw in ens_config.getKeylistFromVarType(EnkfVarType.PARAMETER): - if not kw in keywords: - config_node = ens_config[kw] - data_node = EnkfNode( config_node ) - init_id = NodeId(0, geo_id) - run_id = NodeId(0, iens) - data_node.load(self._getInitializationCase(), init_id) - data_node.save(target_fs, run_id) - - for key, value in keywords.iteritems(): - config_node = ens_config[kw] - data_node = EnkfNode( config_node ) - - gen_kw = data_node.asGenKw() - gen_kw.setValues(value) - - run_id = NodeId(0, iens) - data_node.save(target_fs, run_id) - - target_fs.fsync() - state_map = target_fs.getStateMap() - state_map[iens] = RealizationStateEnum.STATE_INITIALIZED - - - def getGenDataResult(self, target_case_name, iens, report_step, keyword): - ensemble_config = self.ert.ensembleConfig() - - if not self.isRealizationFinished(iens): - raise createFault(UserWarning, "The simulation with id: %d is still running." % iens) - - if keyword in ensemble_config: - enkf_config_node = self.ert.ensembleConfig().getNode(keyword) - node = EnkfNode(enkf_config_node) - - if not node.getImplType() == ErtImplType.GEN_DATA: - raise createFault(UserWarning, "The keyword is not a GenData keyword.") - - gen_data = node.asGenData() - - fs = self.ert.getEnkfFsManager().getFileSystem(target_case_name) - node_id = NodeId(report_step, iens) - if node.tryLoad(fs, node_id): - data = gen_data.getData() - return data.asList() - else: - raise createFault(UserWarning, "Unable to load data for iens: %d report_step: %d kw: %s for case: %s" % (iens, report_step, keyword, target_case_name)) - else: - raise createFault(KeyError, "The keyword: %s is not recognized" % keyword) - - - def getCustomKWResult(self, target_case_name, iens, keyword): - ensemble_config = self.ert.ensembleConfig() - - if not self.isRealizationFinished(iens): - raise createFault(UserWarning, "The simulation with id: %d is still running." % iens) - - if keyword in ensemble_config: - enkf_config_node = self.ert.ensembleConfig().getNode(keyword) - node = EnkfNode(enkf_config_node) - - if not node.getImplType() == ErtImplType.CUSTOM_KW: - raise createFault(UserWarning, "The keyword is not a CustomKW keyword.") - - custom_kw = node.asCustomKW() - - fs = self.ert.getEnkfFsManager().getFileSystem(target_case_name) - node_id = NodeId(0, iens) - if node.tryLoad(fs, node_id): - config = custom_kw.getConfig() - result = {} - for key in config.getKeys(): - result[key] = custom_kw[key] - return result - else: - raise createFault(UserWarning, "Unable to load data for iens: %d kw: %s for case: %s" % (iens, keyword, target_case_name)) - else: - raise createFault(KeyError, "The keyword: %s is not recognized" % keyword) - - def getFailedCount(self): - if self._session.simulation_context is not None: - return self._session.simulation_context.getNumFailed() - else: - return 0 - - def getRunningCount(self): - if self._session.simulation_context is not None: - return self._session.simulation_context.getNumRunning() - else: - return 0 - - def getSuccessCount(self): - if self._session.simulation_context is not None: - return self._session.simulation_context.getNumSuccess() - else: - return 0 - - def getWaitingCount(self): - if self._session.simulation_context is not None: - return self._session.simulation_context.getNumWaiting() - else: - return 0 - - def getBatchNumber(self): - return self._session.batch_number - - def isCustomKWKey(self, key): - ensemble_config = self.ert.ensembleConfig() - return key in ensemble_config.getKeylistFromImplType(ErtImplType.CUSTOM_KW) - - def isGenDataKey(self, key): - ensemble_config = self.ert.ensembleConfig() - return key in ensemble_config.getKeylistFromImplType(ErtImplType.GEN_DATA) - - - def prototypeStorage(self, group_name, storage_definition): - ensemble_config = self.ert.ensembleConfig() - - if group_name in ensemble_config.getKeylistFromImplType(ErtImplType.CUSTOM_KW): - raise createFault(UserWarning, "The CustomKW with group name: '%s' already exist!" % group_name) - - converted_definition = {} - for key, value in storage_definition.iteritems(): - if value == "str": - converted_definition[key] = str - elif value == "float": - converted_definition[key] = float - else: - raise createFault(TypeError, "Unknown type: '%s' for key '%s'" % (value, key)) - - enkf_config_node = ensemble_config.addDefinedCustomKW(group_name, converted_definition) - self.ert.addNode(enkf_config_node) - - def storeGlobalData(self, target_case_name, group_name, keyword, value): - fs = self.ert.getEnkfFsManager().getFileSystem(target_case_name) - enkf_config_node = self.ert.ensembleConfig().getNode(group_name) - enkf_node = EnkfNode(enkf_config_node) - self._updateCustomKWConfigSet(fs, enkf_config_node) - - realizations = fs.realizationList(RealizationStateEnum.STATE_INITIALIZED | RealizationStateEnum.STATE_HAS_DATA) - - for realization_number in realizations: - self._storeData(enkf_node, fs, group_name, keyword, value, realization_number) - - def storeSimulationData(self, target_case_name, group_name, keyword, value, sim_id): - fs = self.ert.getEnkfFsManager().getFileSystem(target_case_name) - enkf_config_node = self.ert.ensembleConfig().getNode(group_name) - enkf_node = EnkfNode(enkf_config_node) - self._updateCustomKWConfigSet(fs, enkf_config_node) - - self._storeData(enkf_node, fs, group_name, keyword, value, sim_id) - - def _updateCustomKWConfigSet(self, fs, enkf_config_node): - ckwcs = fs.getCustomKWConfigSet() - ckwcs.addConfig(enkf_config_node.getCustomKeywordModelConfig()) - - - def _storeData(self, enkf_node, fs, group_name, keyword, value, realization_number): - node_id = NodeId(0, realization_number) - enkf_node.tryLoad(fs, node_id) # Fetch any data from previous store calls - custom_kw = enkf_node.asCustomKW() - custom_kw[keyword] = value - - if not enkf_node.save(fs, node_id): - raise createFault(UserWarning, "Unable to store data for group: '%s' and key: '%s' into realization: '%d'" % (group_name, keyword, realization_number)) - - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert/server/simulation_context.py b/ThirdParty/Ert/python/python/ert/server/simulation_context.py deleted file mode 100644 index e344c15d17..0000000000 --- a/ThirdParty/Ert/python/python/ert/server/simulation_context.py +++ /dev/null @@ -1,95 +0,0 @@ -from ert.enkf import ENKF_LIB -from ert.enkf.ert_run_context import ErtRunContext -from ert.enkf.run_arg import RunArg -from ert.job_queue import JobQueueManager -from ert.util import ArgPack, CThreadPool - - -class SimulationContext(object): - def __init__(self, ert, size, verbose=False): - self._ert = ert - """ :type: ert.enkf.EnKFMain """ - self._size = size - - max_runtime = ert.analysisConfig().get_max_runtime() - job_queue = ert.siteConfig().getJobQueue() - job_queue.set_max_job_duration(max_runtime) - - self._queue_manager = JobQueueManager(job_queue) - self._queue_manager.startQueue(size, verbose=verbose) - self._run_args = {} - """ :type: dict[int, RunArg] """ - - self._thread_pool = CThreadPool(8) - self._thread_pool.addTaskFunction("submitJob", ENKF_LIB, "enkf_main_isubmit_job__") - - - def addSimulation(self, iens, target_fs): - if iens >= self._size: - raise UserWarning("Realization number out of range: %d >= %d" % (iens, self._size)) - - if iens in self._run_args: - raise UserWarning("Realization number: '%d' already queued" % iens) - - runpath_fmt = self._ert.getModelConfig().getRunpathFormat() - member = self._ert.getRealisation(iens) - runpath = ErtRunContext.createRunpath(iens , runpath_fmt, member.getDataKW( )) - run_arg = RunArg.createEnsembleExperimentRunArg(target_fs, iens, runpath) - - self._ert.createRunPath(run_arg) - - self._run_args[iens] = run_arg - self._thread_pool.submitJob(ArgPack(self._ert, run_arg)) - - - def isRunning(self): - return self._queue_manager.isRunning() - - - def getNumRunning(self): - return self._queue_manager.getNumRunning() - - - def getNumSuccess(self): - return self._queue_manager.getNumSuccess() - - - def getNumFailed(self): - return self._queue_manager.getNumFailed() - - def getNumWaiting(self): - return self._queue_manager.getNumWaiting() - - - def didRealizationSucceed(self, iens): - queue_index = self._run_args[iens].getQueueIndex() - return self._queue_manager.didJobSucceed(queue_index) - - - def didRealizationFail(self, iens): - # For the purposes of this class, a failure should be anything (killed job, etc) that is not an explicit success. - return not self.didRealizationSucceed(iens) - - - def isRealizationQueued(self, iens): - return iens in self._run_args - - - def isRealizationFinished(self, iens): - run_arg = self._run_args[iens] - - if run_arg.isSubmitted(): - queue_index = run_arg.getQueueIndex() - return self._queue_manager.isJobComplete(queue_index) - else: - return False - - def __repr__(self): - running = 'running' if self.isRunning() else 'not running' - numRunn = self.getNumRunning() - numSucc = self.getNumSuccess() - numFail = self.getNumFailed() - numWait = self.getNumWaiting() - fmt = '%s, #running = %d, #success = %d, #failed = %d, #waiting = %d' - fmt = fmt % (running, numRunn, numSucc, numFail, numWait) - return 'SimulationContext(%s)' % fmt diff --git a/ThirdParty/Ert/python/python/ert/test/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/test/CMakeLists.txt index 36a244aa8a..3bb95d6c6b 100644 --- a/ThirdParty/Ert/python/python/ert/test/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/ert/test/CMakeLists.txt @@ -8,6 +8,7 @@ set(PYTHON_SOURCES test_area.py temp_area.py path_context.py + lint_test_case.py ) add_python_package("python.ert.test" ${PYTHON_INSTALL_PREFIX}/ert/test "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/python/python/ert/test/__init__.py b/ThirdParty/Ert/python/python/ert/test/__init__.py index a6e32a5a82..cc522e3733 100644 --- a/ThirdParty/Ert/python/python/ert/test/__init__.py +++ b/ThirdParty/Ert/python/python/ert/test/__init__.py @@ -6,6 +6,7 @@ from .test_area import TestArea , TestAreaContext from .temp_area import TempArea , TempAreaContext from .ert_test_runner import ErtTestRunner from .path_context import PathContext +from .lint_test_case import LintTestCase try: from .ert_test_context import ErtTestContext, ErtTest except ImportError: diff --git a/ThirdParty/Ert/python/python/ert/test/ert_test_context.py b/ThirdParty/Ert/python/python/ert/test/ert_test_context.py index ab2fffe14d..dd89c5a720 100644 --- a/ThirdParty/Ert/python/python/ert/test/ert_test_context.py +++ b/ThirdParty/Ert/python/python/ert/test/ert_test_context.py @@ -1,17 +1,17 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'test_work_area.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at +# Copyright (C) 2013 Statoil ASA, Norway. +# +# The file 'test_work_area.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at # for more details. import os.path diff --git a/ThirdParty/Ert/python/python/ert/test/extended_testcase.py b/ThirdParty/Ert/python/python/ert/test/extended_testcase.py index 31ad8e3de7..90da55c510 100644 --- a/ThirdParty/Ert/python/python/ert/test/extended_testcase.py +++ b/ThirdParty/Ert/python/python/ert/test/extended_testcase.py @@ -2,6 +2,7 @@ import numbers import os import os.path import traceback +import sys try: from unittest2 import TestCase @@ -12,6 +13,21 @@ from .source_enumerator import SourceEnumerator from ert.util import installAbortSignals from ert.util import Version +TESTDATA_ROOT = None +SHARE_ROOT = None +SOURCE_ROOT = None +BUILD_ROOT = None +try: + from test_env import * + assert( os.path.isdir( TESTDATA_ROOT )) + assert( os.path.isdir( SOURCE_ROOT )) + assert( os.path.isdir( BUILD_ROOT )) + if not SHARE_ROOT is None: + assert( os.path.isdir( SHARE_ROOT )) +except ImportError: + sys.stderr.write("Warning: could not import file test_env.py - this might lead to test failures.") + + class _AssertNotRaisesContext(object): def __init__(self, test_class): @@ -42,19 +58,17 @@ class ExtendedTestCase(TestCase): super(ExtendedTestCase , self).__init__(*args , **kwargs) - def assertFloatEqual(self, first, second, msg=None): - - if msg is None: - msg = "Value %f and %f are not almost equal!" % (first, second) - - if isinstance(first, numbers.Number) and isinstance(second, numbers.Number): - tolerance = 1e-6 - diff = abs(first - second) + def assertFloatEqual(self, first, second, msg=None, tolerance=1e-6): + try: + f_first, f_second = float(first), float(second) + diff = abs(f_first - f_second) scale = max(1, abs(first) + abs(second)) - + if msg is None: + msg = "Floats not equal: |%f - %f| > %g" % (f_first, f_second, tolerance) self.assertTrue(diff < tolerance * scale, msg=msg) - else: - self.fail("Elements not comparable as float: %s and %s" % (first, second)) + except TypeError: + self.fail("Cannot compare as floats: %s (%s) and %s (%s)" % + (first, type(first), second, type(second))) def assertAlmostEqualList(self, first, second, msg=None): @@ -108,7 +122,7 @@ class ExtendedTestCase(TestCase): return buffer1 == buffer2 def assertEnumIsFullyDefined(self, enum_class, enum_name, source_path, verbose=False): - enum_values = SourceEnumerator.findEnumerators(enum_name, source_path) + enum_values = SourceEnumerator.findEnumerators(enum_name, os.path.join( SOURCE_ROOT , source_path)) for identifier, value in enum_values: if verbose: @@ -119,82 +133,15 @@ class ExtendedTestCase(TestCase): self.assertEqual(class_value, value, "Enum value for identifier: %s does not match: %s != %s" % (identifier, class_value, value)) - def setTestDataRoot(self, testdata_root): - self.__testdata_root = testdata_root - if not os.path.exists(self.__testdata_root): - raise IOError("Path:%s not found" % self.__testdata_root) - - def setShareRoot(self, share_root): - self.__share_root = share_root - if not os.path.exists(self.__share_root): - raise IOError("Path: %s not found" % self.__share_root) - - - def createTestPath(self, path, testdata_root=None): - if testdata_root is None and self.__testdata_root is None: - file_path = os.path.realpath(__file__) - build_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../test-data/")) - site_packages_build_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../../../test-data/")) - src_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../test-data/")) - env_root = os.getenv("ERT_TEST_ROOT_PATH") - - if env_root is not None and os.path.exists(env_root): - root = os.path.realpath(env_root) - elif os.path.exists(build_root): - root = os.path.realpath(build_root) - elif os.path.exists(site_packages_build_root): - root = os.path.realpath(site_packages_build_root) - elif os.path.exists(src_root): - root = os.path.realpath(src_root) - else: - root = None - - self.setTestDataRoot(root) - - root_path = self.__testdata_root - if testdata_root is not None: - if not os.path.exists(testdata_root): - raise IOError("Path: %s not found" % testdata_root) - - root_path = testdata_root - - return os.path.realpath(os.path.join(root_path , path)) - - - def createSharePath(self, path, share_root=None): - if share_root is None and self.__share_root is None: - self.setShareRoot(ExtendedTestCase.findShareRoot()) - - root_path = self.__share_root - if share_root is not None: - if not os.path.exists(share_root): - raise IOError("Path: %s not found" % share_root) - - root_path = share_root - - return os.path.realpath(os.path.join(root_path , path)) - + @staticmethod + def createSharePath(path): + return os.path.realpath(os.path.join(SHARE_ROOT , path)) + @staticmethod - def findShareRoot(): - file_path = os.path.realpath(__file__) - build_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../share/")) - site_packages_build_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../../../share/")) - src_root = os.path.realpath(os.path.join(os.path.dirname(file_path), "../../../../share/")) - env_root = os.getenv("ERT_SHARE_PATH") + def createTestPath(path): + return os.path.realpath(os.path.join(TESTDATA_ROOT , path)) - if env_root is not None and os.path.exists(env_root): - root = os.path.realpath(env_root) - elif os.path.exists(build_root): - root = os.path.realpath(build_root) - elif os.path.exists(site_packages_build_root): - root = os.path.realpath(site_packages_build_root) - elif os.path.exists(src_root): - root = os.path.realpath(src_root) - else: - root = None - - return root def assertNotRaises(self, func=None): diff --git a/ThirdParty/Ert/python/python/ert/test/lint_test_case.py b/ThirdParty/Ert/python/python/ert/test/lint_test_case.py new file mode 100644 index 0000000000..069c6f4af3 --- /dev/null +++ b/ThirdParty/Ert/python/python/ert/test/lint_test_case.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# Copyright (C) 2017 Statoil ASA, Norway. +# +# This file is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. + +import sys +import fnmatch +import os +import unittest +try: + from pylint import epylint as lint +except ImportError: + sys.stderr.write("Could not import pylint module - lint based testing will be skipped\n") + lint = None + + +class LintTestCase(unittest.TestCase): + """This class is a test case for linting.""" + + LINT_ARGS = ['-d', 'R,C,W'] + \ + ['--extension-pkg-whitelist=numpy'] + + + @staticmethod + def _get_lintable_files(paths, whitelist=()): + """Recursively traverses all folders in paths for *.py files""" + matches = [] + for folder in paths: + for root, _, filenames in os.walk(folder): + for filename in fnmatch.filter(filenames, '*.py'): + if filename not in whitelist: + matches.append(os.path.join(root, filename)) + return matches + + + def assertLinted(self, paths, whitelist=()): # noqa + """Takes a path to a folder or a list of paths to folders and recursively finds + all *.py files within that folder except the ones with filenames in whitelist. + + Will assert lint.lint(fname) == 0 for every *.py file found. + """ + if lint is None: + self.skipTest("pylint not installed") + + if isinstance(paths, str): + paths = [paths] + files = self._get_lintable_files(paths, whitelist=whitelist) + for f in files: + self.assertEqual(0, lint.lint(f, self.LINT_ARGS), 'Linting required for %s' % f) diff --git a/ThirdParty/Ert/python/python/ert/test/source_enumerator.py b/ThirdParty/Ert/python/python/ert/test/source_enumerator.py index 7fde930a43..e0c76300f1 100644 --- a/ThirdParty/Ert/python/python/ert/test/source_enumerator.py +++ b/ThirdParty/Ert/python/python/ert/test/source_enumerator.py @@ -2,41 +2,6 @@ import os import re class SourceEnumerator(object): - @classmethod - def findDevRoot(cls, root_directory_name = ".", verbose=False): - dev_root = os.path.dirname(os.path.realpath(__file__)) - while True: - if verbose: - print("Looking at: %s" % dev_root) - - dev_path = os.path.join(dev_root , root_directory_name) - if os.path.exists( os.path.join(dev_path, root_directory_name, "libecl", "include", "ert", "ecl", "ecl_region.h") ): - dev_root = os.path.join(dev_root , root_directory_name) - if verbose: - print("break: %s" % dev_path) - break - - head, tail = os.path.split(dev_root) - dev_root = head - if tail == "": - raise ValueError("Source root: '%s' not found!" % root_directory_name) - - if verbose: - print("Returning: %s " % dev_root) - - return dev_root - - - @classmethod - def findSourceFile(cls, path): - dev_root = SourceEnumerator.findDevRoot() - - source_file = os.path.join(dev_root, path) - - if not os.path.exists(source_file): - raise ValueError("File not found: %s:%s" % (path , source_file)) - - return source_file @classmethod def removeComments(cls, code_string): @@ -44,6 +9,7 @@ class SourceEnumerator(object): code_string = re.sub(re.compile("//.*?\n" ) ,"" ,code_string) # remove all occurance singleline comments (//COMMENT\n ) from string return code_string + @classmethod def findEnum(cls, enum_name, full_source_file_path): with open(full_source_file_path, "r") as f: @@ -61,8 +27,8 @@ class SourceEnumerator(object): @classmethod - def findEnumerators(cls, enum_name, source_file_path): - enum_text = SourceEnumerator.findEnum(enum_name, SourceEnumerator.findSourceFile(source_file_path)) + def findEnumerators(cls, enum_name, source_file): + enum_text = SourceEnumerator.findEnum(enum_name, source_file) enumerator_pattern = re.compile("(\w+?)\s*?=\s*?(\d+)") diff --git a/ThirdParty/Ert/python/python/ert/util/__init__.py b/ThirdParty/Ert/python/python/ert/util/__init__.py index 4666961e76..96b963f10a 100644 --- a/ThirdParty/Ert/python/python/ert/util/__init__.py +++ b/ThirdParty/Ert/python/python/ert/util/__init__.py @@ -36,6 +36,9 @@ The modules included in the util package are: """ +from __future__ import (absolute_import, division, + print_function, unicode_literals) + import ert from cwrap import Prototype diff --git a/ThirdParty/Ert/python/python/ert/util/bool_vector.py b/ThirdParty/Ert/python/python/ert/util/bool_vector.py index 9e68cd699a..88ea0edb24 100644 --- a/ThirdParty/Ert/python/python/ert/util/bool_vector.py +++ b/ThirdParty/Ert/python/python/ert/util/bool_vector.py @@ -14,9 +14,6 @@ # See the GNU General Public License at # for more details. - -import warnings - from ert.util import VectorTemplate, UtilPrototype @@ -98,25 +95,6 @@ class BoolVector(VectorTemplate): """ return cls._create_active_mask(range_string) - @classmethod - def active_mask(cls, range_string): - """ - Will create a BoolVector instance with the values from @range_string. - - The range_string input should be of the type "1,3-5,9,17", - i.e. integer values separated by commas, and dashes to - represent ranges. If the input string contains ANY invalid - characters the returned active list will be empty: - - "1,4-7,10" => {F,T,F,F,T,T,T,T,F,F,T} - "1,4-7,10X" => {} - - The empty list will evaluate to false - @rtype: BoolVector - """ - warnings.warn("The active_mask(cls, rangs_string) method has been renamed: createActiveMask(cls, rangs_string)", DeprecationWarning) - return cls._create_active_mask(range_string) - def updateActiveMask(self, range_string): """ Updates a bool vector based on a range string. diff --git a/ThirdParty/Ert/python/python/ert/util/profiler.py b/ThirdParty/Ert/python/python/ert/util/profiler.py index 0493689bfc..ab35189cc9 100644 --- a/ThirdParty/Ert/python/python/ert/util/profiler.py +++ b/ThirdParty/Ert/python/python/ert/util/profiler.py @@ -1,4 +1,10 @@ -import StringIO +from __future__ import absolute_import, division, print_function, unicode_literals + +try: + from StringIO import StringIO +except ImportError: + from io import StringIO + import cProfile import pstats import sys @@ -18,7 +24,7 @@ class Profiler(object): def stopProfiler(cls, sort_method="cumulative"): if cls.__profiler is not None: cls.__profiler.disable() - stream = StringIO.StringIO() + stream = StringIO() stats_printer = pstats.Stats(cls.__profiler, stream=stream).sort_stats(sort_method) stats_printer.print_stats() cls.__profiler = None diff --git a/ThirdParty/Ert/python/python/ert/util/stringlist.py b/ThirdParty/Ert/python/python/ert/util/stringlist.py index e4de156c68..25432da8a9 100644 --- a/ThirdParty/Ert/python/python/ert/util/stringlist.py +++ b/ThirdParty/Ert/python/python/ert/util/stringlist.py @@ -30,9 +30,9 @@ be an iterable consisting of strings, and the strings property will return a normal python list of string objects, used in this way you hardly need to notice that the StringList class is at play. """ - +from __future__ import absolute_import, division, print_function, unicode_literals +from six import string_types from ert.util import UtilPrototype -from types import StringType, IntType from cwrap import BaseCClass @@ -76,13 +76,17 @@ class StringList(BaseCClass): c_ptr = self._alloc() super(StringList, self).__init__(c_ptr) - if initial: - for s in initial: - if isinstance(s, StringType): - self.append(s) - else: - raise TypeError("Item: %s not a string" % s) + self._append_all(initial) + + def _append_all(self, lst): + for s in lst: + if isinstance(s, bytes): + s.decode('ascii') + if isinstance(s, string_types): + self.append(s) + else: + raise TypeError('Item is not a string: "%s".' % s) def __eq__(self , other): @@ -101,7 +105,7 @@ class StringList(BaseCClass): def __setitem__(self, index, value): - if isinstance(index, IntType): + if isinstance(index, int): length = len(self) if index < 0: # Will only wrap backwards once @@ -109,7 +113,9 @@ class StringList(BaseCClass): if index < 0 or index >= length: raise IndexError("index must be in range %d <= %d < %d" % (0, index, len(self))) - if isinstance(value, StringType): + if isinstance(value, bytes): + value = value.decode('ascii') + if isinstance(value, string_types): self._iset(index, value) else: raise TypeError("Item: %s not string type" % value) @@ -122,7 +128,7 @@ class StringList(BaseCClass): The __getitem__ method supports negative, i.e. from the right, indexing; but not slices. """ - if isinstance(index, IntType): + if isinstance(index, int): length = len(self) if index < 0: index += length @@ -143,7 +149,9 @@ class StringList(BaseCClass): def __iadd__(self , other): - if isinstance(other , str): + if isinstance(other, bytes): + other.decode('ascii') + if isinstance(other , string_types): raise TypeError("Can not add strings with + - use append()") for s in other: self.append( s ) @@ -157,7 +165,9 @@ class StringList(BaseCClass): def __ior__(self , other): - if isinstance(other , str): + if isinstance(other, bytes): + other.decode('ascii') + if isinstance(other , string_types): raise TypeError("Can not | with string.") for s in other: if not s in self: @@ -203,6 +213,12 @@ class StringList(BaseCClass): buffer += "]" return buffer + def __repr__(self): + return 'StringList(size = %d) %s' % (len(self), self._ad_str()) + + def empty(self): + """Returns true if and only if list is empty.""" + return len(self) == 0 def pop(self): """ @@ -210,10 +226,10 @@ class StringList(BaseCClass): Will raise IndexError if list is empty. """ - if len(self): + if not self.empty(): return self._pop() else: - raise IndexError("pop() failed - the list is empty") + raise IndexError("List empty. Cannot call pop().") def append(self, s): @@ -221,11 +237,13 @@ class StringList(BaseCClass): Appends a new string @s to list. If the input argument is not a string the string representation will be appended. """ - if isinstance(s, StringType): + if isinstance(s, bytes): + s.decode('ascii') + if isinstance(s, string_types): self._append(s) else: self._append(str(s)) - + @property def strings(self): @@ -245,10 +263,10 @@ class StringList(BaseCClass): """ Will return the last element in list. Raise IndexError if empty. """ - if len(self) > 0: + if not self.empty(): return self._last() else: - raise IndexError("The list is empty") + raise IndexError("List empty. No such element last().") def sort(self, cmp_flag=0): @@ -267,21 +285,24 @@ class StringList(BaseCClass): def index(self, value): """ @rtype: int """ - assert isinstance(value, str) - return self._find_first( value) + if isinstance(value, bytes): + value.decode('ascii') + if isinstance(value, string_types): + return self._find_first(value) + raise KeyError('Cannot index by "%s", lst.index() needs a string.' % str(type(value))) def free(self): self._free() def front(self): - if len(self) > 0: + if not self.empty(): return self._front() else: - raise IndexError + raise IndexError('List empty. No such element front().') def back(self): - if len(self) > 0: + if not self.empty(): return self._back() else: - raise IndexError + raise IndexError('List empty. No such element back().') diff --git a/ThirdParty/Ert/python/python/ert/util/ui_return.py b/ThirdParty/Ert/python/python/ert/util/ui_return.py index e0bad99bdb..d498863188 100644 --- a/ThirdParty/Ert/python/python/ert/util/ui_return.py +++ b/ThirdParty/Ert/python/python/ert/util/ui_return.py @@ -14,10 +14,13 @@ # See the GNU General Public License at # for more details. +from __future__ import (absolute_import, division, + print_function, unicode_literals) + from cwrap import BaseCClass from ert.util import UtilPrototype -from enums import UIReturnStatusEnum - +from .enums import UIReturnStatusEnum + class UIReturn(BaseCClass): TYPE_NAME = "ui_return" diff --git a/ThirdParty/Ert/python/python/ert/util/vector_template.py b/ThirdParty/Ert/python/python/ert/util/vector_template.py index 31085903c5..fbb9f048b8 100644 --- a/ThirdParty/Ert/python/python/ert/util/vector_template.py +++ b/ThirdParty/Ert/python/python/ert/util/vector_template.py @@ -40,8 +40,9 @@ The C-level has implementations for several fundamental types like float and size_t not currently implemented in the Python version. """ +from __future__ import absolute_import, division, print_function, unicode_literals + import sys -from types import IntType, SliceType from cwrap import CFILE, BaseCClass from ert.util import UtilPrototype @@ -178,14 +179,14 @@ class VectorTemplate(BaseCClass): """ s = "" - lines = len(self) / width + lines = len(self) // width if not fmt: fmt = self.default_format + " " if max_lines is None or lines <= max_lines: s += self.str_data(width, 0, len(self), fmt) else: - s1 = width * max_lines / 2 + s1 = width * max_lines // 2 s += self.str_data(width, 0, s1, fmt) s += " .... \n" s += self.str_data(width, len(self) - s1, len(self), fmt) @@ -203,7 +204,7 @@ class VectorTemplate(BaseCClass): """ Implements read [] operator - @index can be slice instance. """ - if isinstance(index, IntType): + if isinstance(index, int): length = len(self) idx = index if idx < 0: @@ -213,7 +214,7 @@ class VectorTemplate(BaseCClass): return self._iget(idx) else: raise IndexError('Index must be in range %d <= %d < %d.' % (0, index, length)) - elif isinstance(index, SliceType): + elif isinstance(index, slice): return self.strided_copy(index) else: raise TypeError("Index should be integer or slice type.") @@ -223,7 +224,7 @@ class VectorTemplate(BaseCClass): Implements write [] operator - @index must be integer or slice. """ ls = len(self) - if isinstance(index, IntType): + if isinstance(index, int): idx = index if idx < 0: idx += ls @@ -232,7 +233,7 @@ class VectorTemplate(BaseCClass): for i in range(*index.indices(ls)): self[i] = value else: - raise TypeError("Index should be integer type, not %s." % type(index)) + raise TypeError("Index should be integer type") ################################################################## # Mathematical operations: @@ -559,3 +560,88 @@ class VectorTemplate(BaseCClass): vector = cls( ) vector.initRange( min_value , max_value , delta ) return vector + + def _strided_copy(self, *_): + raise NotImplementedError() + def _rshift(self, *_): + raise NotImplementedError() + def _lshift(self, *_): + raise NotImplementedError() + def _alloc(self, *_): + raise NotImplementedError() + def _element_size(self, *_): + raise NotImplementedError() + def _contains(self, *_): + raise NotImplementedError() + def _pop(self, *_): + raise NotImplementedError() + def default_format(self, *_): + raise NotImplementedError() + def _iget(self, *_): + raise NotImplementedError() + def _iset(self, *_): + raise NotImplementedError() + def _inplace_add(self, *_): + raise NotImplementedError() + def _shift(self, *_): + raise NotImplementedError() + def _alloc_copy(self, *_): + raise NotImplementedError() + def _inplace_mul(self, *_): + raise NotImplementedError() + def _scale(self, *_): + raise NotImplementedError() + def _memcpy(self, *_): + raise NotImplementedError() + def _assign(self, *_): + raise NotImplementedError() + def _size(self, *_): + raise NotImplementedError() + def _fprintf(self, *_): + raise NotImplementedError() + def _get_max(self, *_): + raise NotImplementedError() + def _get_min(self, *_): + raise NotImplementedError() + def _get_min_index(self, *_): + raise NotImplementedError() + def _get_max_index(self, *_): + raise NotImplementedError() + def _append(self, *_): + raise NotImplementedError() + def _idel_block(self, *_): + raise NotImplementedError() + def _sort(self, *_): + raise NotImplementedError() + def _rsort(self, *_): + raise NotImplementedError() + def _reset(self, *_): + raise NotImplementedError() + def _safe_iget(self, *_): + raise NotImplementedError() + def _set_read_only(self, *_): + raise NotImplementedError() + def _get_read_only(self, *_): + raise NotImplementedError() + def _set_default(self, *_): + raise NotImplementedError() + def _get_default(self, *_): + raise NotImplementedError() + def _free(self, *_): + raise NotImplementedError() + def _permute(self, *_): + raise NotImplementedError() + def _sort_perm(self, *_): + raise NotImplementedError() + def _rsort_perm(self, *_): + raise NotImplementedError() + def _select_unique(self, *_): + raise NotImplementedError() + def _element_sum(self, *_): + raise NotImplementedError() + def _get_data_ptr(self, *_): + raise NotImplementedError() + def _count_equal(self, *_): + raise NotImplementedError() + def _init_range(self, *_): + raise NotImplementedError() diff --git a/ThirdParty/Ert/python/python/ert/util/version.py b/ThirdParty/Ert/python/python/ert/util/version.py index 7b2e2d5abf..b17bb6b056 100644 --- a/ThirdParty/Ert/python/python/ert/util/version.py +++ b/ThirdParty/Ert/python/python/ert/util/version.py @@ -46,6 +46,15 @@ class Version(object): def __str__(self): return self.versionString() + def __repr__(self): + major, minor, micro = self.versionTuple() + commit = self._git_commit_short() + status = 'production' + if self.isDevelVersion(): + status = 'development' + fmt = 'Version(major=%d, minor=%d, micro="%s", commit="%s", status="%s")' + return fmt % (major, minor, micro, commit, status) + @cmp_method def __eq__(self, other): return self.versionTuple() == other.versionTuple() diff --git a/ThirdParty/Ert/python/python/ert/well/well_connection.py b/ThirdParty/Ert/python/python/ert/well/well_connection.py index a4870ff2d8..9b42d21694 100644 --- a/ThirdParty/Ert/python/python/ert/well/well_connection.py +++ b/ThirdParty/Ert/python/python/ert/well/well_connection.py @@ -81,7 +81,7 @@ class WellConnection(BaseCClass): msw = ' (multi segment)' if self.isMultiSegmentWell() else '' dir = WellConnectionDirectionEnum(self.direction()) addr = self._address() - return 'WellConnection(%s %s%s%s, direction = %s) at 0x%x' % (ijk, frac, open_, msw, dir, addr) + return 'WellConnection(%s %s%s%s, rates = (O:%s,G:%s,W:%s), direction = %s) at 0x%x' % (ijk, frac, open_, msw, self.oilRate(), self.gasRate(), self.waterRate(), dir, addr) def gasRate(self): return self._gas_rate() diff --git a/ThirdParty/Ert/python/python/ert_gui/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/CMakeLists.txt deleted file mode 100644 index 6aa1647efb..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - about_dialog.py - ert_splash.py - ertnotifier.py - ertplot.py - gert_main.py - main_window.py - newconfig.py -) - -add_python_package("python.ert_gui" ${PYTHON_INSTALL_PREFIX}/ert_gui "${PYTHON_SOURCES}" True) - -add_subdirectory(ertwidgets) -add_subdirectory(ide) -add_subdirectory(plottery) -add_subdirectory(shell) -add_subdirectory(simulation) -add_subdirectory(tools) diff --git a/ThirdParty/Ert/python/python/ert_gui/README.txt b/ThirdParty/Ert/python/python/ert_gui/README.txt deleted file mode 100644 index 8341e4c175..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/README.txt +++ /dev/null @@ -1,43 +0,0 @@ -How to develop/run the GUI: - -You can run the gui in two ways: - -1a There are CMakeLists.txt files all the ways through the gui filesystem, - and if you build the ert distribution you will get file hierarchy - xxxx/build/python/ert_gui beside the xxxx/build/python/ert hierarchy. - - This is the way the gui should be organized when installed, to invoke the - gui this way: - - gert -v xxxx/build - - Observe that the 'xxxx' part must be an ABSOLUTE path, otherwise the - frontend script will search in the default installation directory. - - -1b Alternatively you can use the gert command to invoke the gui in the source - directory: - - gert -v xxxx/python - - Observe only one 'python' above. - - - -2. You can invoke gui as a python module directly from the source, without - going through the gert frontend script. This requires that set several - environment variables: - - ERT_SITE_CONFIG -> /project/res/etc/ERT/site-config - ERT_SHARE_PATH -> xxxx/libenkf/applications/ert_gui/share - LD_LIBRARY_PATH -> xxxx/build/lib64 - - And in addition you must source the local_csh file in - xxxx/python/test to set the PYTHONPATH correctly. - - -About the ERT_SHARE_PATH variable: the correct value for the ERT_SHARE_PATH -variable is currently xxxx/libenkf/applications/ert_gui/share, so if -you are using alternative 2 you get this one correctly, whereas if you use -alternative 1 it will be set to a generally incorrect value by the gert -frontend script. diff --git a/ThirdParty/Ert/python/python/ert_gui/__init__.py b/ThirdParty/Ert/python/python/ert_gui/__init__.py deleted file mode 100644 index 07c404d1fd..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -import sys -import warnings - -REQUIRED_VERSION_HEX = 0x02070000 - - -if sys.hexversion < REQUIRED_VERSION_HEX: - raise Exception("ERT GUI Python requires at least version 2.7 of Python") - -import os -import matplotlib - -def headless(): - return "DISPLAY" not in os.environ - -if headless(): - matplotlib.use("Agg") -else: - matplotlib.use("Qt4Agg") - - -from .ertnotifier import ERT -from .ertnotifier import configureErtNotifier diff --git a/ThirdParty/Ert/python/python/ert_gui/about_dialog.py b/ThirdParty/Ert/python/python/ert_gui/about_dialog.py deleted file mode 100644 index f63e7fc7ab..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/about_dialog.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# This file is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from PyQt4.QtCore import Qt, QSize -from PyQt4.QtGui import QDialog, QVBoxLayout, QPushButton, QHBoxLayout, QLabel, QFont -from ert.util import Version -from ert_gui.ertwidgets import resourceImage - - -class AboutDialog(QDialog): - - def __init__(self, parent): - QDialog.__init__(self, parent) - - self.setWindowTitle("About") - self.setModal(True) - self.setFixedSize(QSize(600, 480)) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowCancelButtonHint) - - main_layout = QVBoxLayout() - - main_layout.addLayout(self.createTopLayout()) - main_layout.addLayout(self.createGplLayout()) - main_layout.addLayout(self.createButtonLayout()) - - self.setLayout(main_layout) - - - def createTopLayout(self): - top_layout = QHBoxLayout() - - image_label = QLabel() - image = resourceImage("splash.jpg") - image_label.setPixmap(image.scaled(200, 240, Qt.KeepAspectRatio)) - - top_layout.addWidget(image_label) - - top_layout.addLayout(self.createInfoLayout(), 1) - - return top_layout - - @staticmethod - def createInfoLayout(): - info_layout = QVBoxLayout() - - ert = QLabel() - ert.setAlignment(Qt.AlignHCenter) - - title_font = QFont() - title_font.setPointSize(40) - ert.setFont(title_font) - ert.setText("ERT") - - info_layout.addWidget(ert) - info_layout.addStretch(1) - ert_title = QLabel() - ert_title.setAlignment(Qt.AlignHCenter) - ert_title.setText("Ensemble based Reservoir Tool") - info_layout.addWidget(ert_title) - - version = QLabel() - version.setAlignment(Qt.AlignHCenter) - version.setText("Version: %s" % Version.getVersion()) - info_layout.addWidget(version) - - timestamp = QLabel() - timestamp.setAlignment(Qt.AlignHCenter) - timestamp.setText("Build time: %s" % Version.getBuildTime()) - info_layout.addWidget(timestamp) - - git_commit = QLabel() - git_commit.setAlignment(Qt.AlignHCenter) - git_commit.setText("Git commit hash: %s" % Version.getGitCommit(short=True)) - info_layout.addWidget(git_commit) - - info_layout.addStretch(5) - - return info_layout - - - def createGplLayout(self): - gpl = QLabel() - gpl.setText("ERT 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.

\ - \ - ERT 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 at www.gnu.org for more details. ") - gpl.setWordWrap(True) - gpl_layout = QVBoxLayout() - gpl_layout.addWidget(gpl) - return gpl_layout - - def createButtonLayout(self): - button_layout = QHBoxLayout() - - close_button = QPushButton("Close") - close_button.clicked.connect(self.accept) - - button_layout.addStretch() - button_layout.addWidget(close_button) - button_layout.addStretch() - - return button_layout diff --git a/ThirdParty/Ert/python/python/ert_gui/ert_splash.py b/ThirdParty/Ert/python/python/ert_gui/ert_splash.py deleted file mode 100644 index 07dbf7b284..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ert_splash.py +++ /dev/null @@ -1,106 +0,0 @@ -from PyQt4.QtCore import Qt -from PyQt4.QtGui import QSplashScreen, QApplication, QColor, QPen, QFont - -from ert_gui.ertwidgets import resourceImage - - -class ErtSplash(QSplashScreen): - def __init__(self): - QSplashScreen.__init__(self) - self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.SplashScreen) - - splash_width = 720 - splash_height = 400 - - desktop = QApplication.desktop() - screen = desktop.screenGeometry(desktop.primaryScreen()).size() - - screen_width, screen_height = screen.width(), screen.height() - x = screen_width / 2 - splash_width / 2 - y = screen_height / 2 - splash_height / 2 - self.setGeometry(x, y, splash_width, splash_height) - - - self.splash_image = resourceImage("splash.jpg") - - self.ert = "ERT" - self.ert_title = "Ensemble based Reservoir Tool" - self.version = "Version string" - self.timestamp = "Timestamp string" - self.copyright = u"Copyright \u00A9 2017 Statoil ASA, Norway" - - - def drawContents(self, painter): - """ @type painter: QPainter """ - w = self.width() - h = self.height() - - margin = 10 - - background = QColor(210, 211, 215) - text_color = QColor(0, 0, 0) - foreground = QColor(255, 255, 255) - - painter.setBrush(background) - painter.fillRect(0, 0, w, h, background) - - - pen = QPen() - pen.setWidth(2) - pen.setColor(foreground) - - - painter.setPen(pen) - painter.drawRect(0, 0, w - 1, h - 1) - - image_width = self.splash_image.width() - image_height = self.splash_image.height() - aspect = float(image_width) / float(image_height) - - scaled_height = h - 2 * margin - scaled_width = scaled_height * aspect - - painter.drawRect(margin, margin, scaled_width, scaled_height) - painter.drawPixmap(margin, margin, scaled_width, scaled_height, self.splash_image) - - text_x = scaled_width + 2 * margin - top_offset = margin - text_area_width = w - scaled_width - 2 * margin - - painter.setPen(text_color) - - - text_size = 150 - font = QFont("Serif") - font.setStyleHint(QFont.Serif) - font.setPixelSize(text_size) - painter.setFont(font) - painter.drawText(text_x, margin + top_offset, text_area_width, text_size, Qt.AlignHCenter | Qt.AlignCenter, self.ert) - - top_offset += text_size + 2 * margin - text_size = 25 - font.setPixelSize(text_size) - painter.setFont(font) - painter.drawText(text_x, top_offset, text_area_width, text_size, Qt.AlignHCenter | Qt.AlignCenter, self.ert_title) - - top_offset += text_size + 4 * margin - text_size = 20 - font.setPixelSize(text_size) - painter.setFont(font) - painter.drawText(text_x, top_offset, text_area_width, text_size, Qt.AlignHCenter | Qt.AlignCenter, self.version) - - top_offset += text_size + margin - text_size = 15 - font.setPixelSize(text_size) - painter.setFont(font) - painter.drawText(text_x, top_offset, text_area_width, text_size, Qt.AlignHCenter | Qt.AlignCenter, self.timestamp) - - - text_size = 12 - font.setPixelSize(text_size) - painter.setFont(font) - painter.drawText(text_x, h - text_size - margin - 5, text_area_width, text_size + 5, Qt.AlignHCenter | Qt.AlignCenter, self.copyright) - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ertnotifier.py b/ThirdParty/Ert/python/python/ert_gui/ertnotifier.py deleted file mode 100644 index fd80d6de65..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertnotifier.py +++ /dev/null @@ -1,50 +0,0 @@ -from ert.enkf import EnKFMain -from PyQt4.QtCore import QObject, pyqtSignal, pyqtSlot - -class ErtNotifier(QObject): - ertChanged = pyqtSignal() - - def __init__(self, ert, config_file, parent=None): - QObject.__init__(self, parent) - self._ert = ert - self._config_file = config_file - - def _checkErt(self): - if self._ert is None: - raise ValueError("Ert is undefined.") - - @property - def ert(self): - """ @rtype: EnKFMain """ - self._checkErt() - return self._ert - - - @property - def config_file(self): - """ @rtype: str """ - self._checkErt() - return self._config_file - - pyqtSlot() - def emitErtChange(self): - self._checkErt() - self.ertChanged.emit() - - pyqtSignal() - def reloadERT(self, config_file): - import sys - import os - python_executable = sys.executable - ert_gui_main = sys.argv[0] - - self._ert.free() - os.execl(python_executable, python_executable, ert_gui_main, config_file) - - -ERT = ErtNotifier(None, None) -""" @type: ErtNotifier """ - -def configureErtNotifier(ert, config_file): - ERT._ert = ert - ERT._config_file = config_file diff --git a/ThirdParty/Ert/python/python/ert_gui/ertplot.py b/ThirdParty/Ert/python/python/ert_gui/ertplot.py deleted file mode 100644 index cfe0116333..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertplot.py +++ /dev/null @@ -1,87 +0,0 @@ - -import sys -import os -from PyQt4.QtGui import QApplication -import time -from ert.enkf import EnKFMain -from ert.util import Version -from ert_gui.ert_splash import ErtSplash -from ert_gui.ertwidgets import resourceIcon -from ert_gui.tools.plot.plot_window import PlotWindow - - -import ert_gui.ertwidgets - -if os.getenv("ERT_SHARE_PATH"): - ert_share_path = os.getenv("ERT_SHARE_PATH") -else: - # If the ERT_SHARE_PATH variable is not set we try to use the - # source location relative to the location of the current file; - # assuming we are in the source directory. Will not work if we are - # in an arbitrary build directory. - ert_share_path = os.path.realpath( os.path.join( os.path.dirname( os.path.abspath( __file__)) , "../../../share")) - -ert_gui.ertwidgets.img_prefix = ert_share_path + "/gui/img/" - - -def main(argv): - - app = QApplication(argv) #Early so that QT is initialized before other imports - app.setWindowIcon(resourceIcon("application/window_icon_cutout")) - - if len(argv) == 1: - sys.stderr.write("Missing configuration file") - sys.exit(1) - - config_file = argv[1] - strict = True - - if not os.path.exists(config_file): - print("Can not run without a configuration file.") - sys.exit(1) - - if os.path.isdir(config_file): - print("The specified configuration file is a directory!") - sys.exit(1) - - - splash = ErtSplash() - splash.version = "Version %s" % Version.getVersion() - splash.timestamp = Version.getBuildTime() - - splash.show() - splash.repaint() - - now = time.time() - - - ert = EnKFMain(config_file, strict=strict, verbose=False) - ert_gui.configureErtNotifier(ert, config_file) - - window = PlotWindow(ert, None) - - sleep_time = 2 - (time.time() - now) - - if sleep_time > 0: - time.sleep(sleep_time) - - window.show() - splash.finish(window) - window.activateWindow() - window.raise_() - finished_code = app.exec_() - - ert.free() - - sys.exit(finished_code) - - -if __name__ == "__main__": - main(sys.argv) - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/CMakeLists.txt deleted file mode 100644 index 70bad08451..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - activelabel.py - analysismoduleselector.py - analysismodulevariablespanel.py - caselist.py - caseselector.py - checklist.py - closabledialog.py - customdialog.py - legend.py - listeditbox.py - pathchooser.py - searchbox.py - stringbox.py - summarypanel.py - validateddialog.py - validationsupport.py -) - -add_python_package("python.ert_gui.ertwidgets" ${PYTHON_INSTALL_PREFIX}/ert_gui/ertwidgets "${PYTHON_SOURCES}" True) - -add_subdirectory(models) diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/__init__.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/__init__.py deleted file mode 100644 index 22b33f8907..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/__init__.py +++ /dev/null @@ -1,74 +0,0 @@ -from PyQt4 import QtGui, QtCore - -img_prefix = "" - -def addHelpToWidget(widget, link): - original_enter_event = widget.enterEvent - - def enterEvent(event): - original_enter_event(event) - try: - from ert_gui.tools import HelpCenter - HelpCenter.getHelpCenter("ERT").setHelpMessageLink(link) - except AttributeError: - pass - - widget.enterEvent = enterEvent - - -def showWaitCursorWhileWaiting(func): - """A function decorator to show the wait cursor while the function is working.""" - - def wrapper(*arg): - QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) - try: - res = func(*arg) - return res - except: - raise - finally: - QtGui.QApplication.restoreOverrideCursor() - - return wrapper - - -def resourceIcon(name): - """Load an image as an icon""" - # print("Icon used: %s" % name) - return QtGui.QIcon(img_prefix + name) - - -def resourceStateIcon(on, off): - """Load two images as an icon with on and off states""" - icon = QtGui.QIcon() - icon.addPixmap(resourceImage(on), state=QtGui.QIcon.On) - icon.addPixmap(resourceImage(off), state=QtGui.QIcon.Off) - return icon - - -def resourceImage(name): - """Load an image as a Pixmap""" - return QtGui.QPixmap(img_prefix + name) - - -def resourceMovie(name): - """ @rtype: QMovie """ - movie = QtGui.QMovie(img_prefix + name) - movie.start() - return movie - - -from .legend import Legend -from .validationsupport import ValidationSupport -from .closabledialog import ClosableDialog -from .analysismoduleselector import AnalysisModuleSelector -from .activelabel import ActiveLabel -from .searchbox import SearchBox -from .caseselector import CaseSelector -from .caselist import CaseList -from .checklist import CheckList -from .stringbox import StringBox -from .listeditbox import ListEditBox -from .customdialog import CustomDialog -from .summarypanel import SummaryPanel -from .pathchooser import PathChooser diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/activelabel.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/activelabel.py deleted file mode 100644 index 10d9532320..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/activelabel.py +++ /dev/null @@ -1,28 +0,0 @@ -from PyQt4.QtGui import QLabel, QFont - -from ert_gui.ertwidgets import addHelpToWidget - - -class ActiveLabel(QLabel): - def __init__(self, model, help_link=""): - QLabel.__init__(self) - - addHelpToWidget(self, help_link) - self._model = model - - font = self.font() - font.setWeight(QFont.Bold) - self.setFont(font) - - self._model.valueChanged.connect(self.updateLabel) - - self.updateLabel() - - - def updateLabel(self): - """Retrieves data from the model and inserts it into the edit line""" - model_value = self._model.getValue() - if model_value is None: - model_value = "" - - self.setText(str(model_value)) diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/analysismoduleselector.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/analysismoduleselector.py deleted file mode 100644 index 94de4b503f..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/analysismoduleselector.py +++ /dev/null @@ -1,71 +0,0 @@ -from PyQt4.QtCore import QMargins, Qt -from PyQt4.QtGui import QWidget, QHBoxLayout, QComboBox, QToolButton - -from ert_gui.ertwidgets import addHelpToWidget, ClosableDialog, resourceIcon -from ert_gui.ertwidgets.models.ertmodel import getCurrentAnalysisModuleName, getAnalysisModuleNames -from ert_gui.ertwidgets.analysismodulevariablespanel import AnalysisModuleVariablesPanel - - -class AnalysisModuleSelector(QWidget): - def __init__(self, iterable=False, load_all = False, help_link=""): - QWidget.__init__(self) - self._iterable = iterable - - addHelpToWidget(self, help_link) - - layout = QHBoxLayout() - - analysis_module_combo = QComboBox() - - self._module_names = getAnalysisModuleNames(self._iterable) - if load_all: - self._module_names += getAnalysisModuleNames(not self._iterable) - - for module_name in self._module_names: - analysis_module_combo.addItem(module_name) - - self._current_module_name = self._getCurrentAnalysisModuleName() - if self._current_module_name is not None: - analysis_module_combo.setCurrentIndex(self._module_names.index(self._current_module_name)) - - analysis_module_combo.currentIndexChanged[int].connect(self.analysisModuleChanged) - - variables_popup_button = QToolButton() - variables_popup_button.setIcon(resourceIcon("ide/small/cog_edit.png")) - variables_popup_button.clicked.connect(self.showVariablesPopup) - variables_popup_button.setMaximumSize(20, 20) - - layout.addWidget(analysis_module_combo, 0, Qt.AlignLeft) - layout.addWidget(variables_popup_button, 0, Qt.AlignLeft) - layout.setContentsMargins(QMargins(0, 0, 0, 0)) - layout.addStretch() - - self.setLayout(layout) - - def analysisModuleChanged(self, index): - self._current_module_name = self._module_names[index] - - def _getCurrentAnalysisModuleName(self): - active_name = getCurrentAnalysisModuleName() - modules = self._module_names - - if active_name in modules: - return active_name - elif "STD_ENKF" in modules and not self._iterable: - return "STD_ENKF" - elif "RML_ENKF" in modules and self._iterable: - return "RML_ENKF" - elif len(modules) > 0: - return modules[0] - - return None - - def getSelectedAnalysisModuleName(self): - return self._current_module_name - - def showVariablesPopup(self): - if self.getSelectedAnalysisModuleName() is not None: - variable_dialog = AnalysisModuleVariablesPanel(self.getSelectedAnalysisModuleName()) - dialog = ClosableDialog("Edit variables", variable_dialog, self.parent()) - - dialog.exec_() diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/analysismodulevariablespanel.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/analysismodulevariablespanel.py deleted file mode 100644 index 30cb70780f..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/analysismodulevariablespanel.py +++ /dev/null @@ -1,142 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'analysismodulevariablespanel.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from functools import partial - -from PyQt4.QtCore import QString -from PyQt4.QtGui import QDoubleSpinBox, QWidget, QFormLayout, QCheckBox, QLineEdit, QHBoxLayout, QSpinBox, QLabel - -from ert_gui.ertwidgets.models.analysismodulevariablesmodel import AnalysisModuleVariablesModel - - -class AnalysisModuleVariablesPanel(QWidget): - def __init__(self, analysis_module_name, parent=None): - QWidget.__init__(self, parent) - - self._analysis_module_name = analysis_module_name - - layout = QFormLayout() - variable_names = AnalysisModuleVariablesModel.getVariableNames(self._analysis_module_name) - - if len(variable_names) == 0: - label = QString("No variables found to edit") - boxlayout = QHBoxLayout() - layout.addRow(label, boxlayout) - - else: - analysis_module_variables_model = AnalysisModuleVariablesModel - self.blockSignals(True) - - variable_names2 = self.sortVariables(variable_names) - for variable_name in variable_names2: - variable_type = analysis_module_variables_model.getVariableType(variable_name) - variable_value = analysis_module_variables_model.getVariableValue(self._analysis_module_name, - variable_name) - - label_name = analysis_module_variables_model.getVariableLabelName(variable_name) - if variable_type == bool: - spinner = self.createCheckBox(variable_name, variable_value, variable_type) - - elif variable_type == float: - spinner = self.createDoubleSpinBox(variable_name, variable_value, variable_type, - analysis_module_variables_model) - - elif variable_type == str: - spinner = self.createLineEdit(variable_name, variable_value, variable_type) - - elif variable_type == int: - spinner = self.createSpinBox(variable_name, variable_value, variable_type, - analysis_module_variables_model) - - layout.addRow(label_name, spinner) - if variable_name == "LAMBDA0": - label = QLabel( - " Initial Lambda of -1.00 signifies that the value will be calculated") - layout.addRow(label, None) - - self.setLayout(layout) - self.blockSignals(False) - - def sortVariables(self, variable_list): - analysis_module_variables_model = AnalysisModuleVariablesModel - sorted_list = ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"] - result = [] - for name in variable_list: - pos = analysis_module_variables_model.getVariablePosition(name) - sorted_list.insert(pos, name) - sorted_list.__delitem__(pos + 1) - - for item in sorted_list: - if item != "#": - result.append(item) - - return result - - def createSpinBox(self, variable_name, variable_value, variable_type, analysis_module_variables_model): - spinner = QSpinBox() - spinner.setMinimumWidth(75) - spinner.setMaximum(analysis_module_variables_model.getVariableMaximumValue(variable_name)) - spinner.setMinimum(analysis_module_variables_model.getVariableMinimumValue(variable_name)) - spinner.setSingleStep(analysis_module_variables_model.getVariableStepValue(variable_name)) - if variable_value is not None: - spinner.setValue(variable_value) - spinner.valueChanged.connect(partial(self.valueChanged, variable_name, variable_type, spinner)) - return spinner - - def createLineEdit(self, variable_name, variable_value, variable_type): - spinner = QLineEdit() - if variable_value == "None": - spinner.setText("") - else: - spinner.setText(variable_value) - spinner.editingFinished.connect(partial(self.valueChanged, variable_name, variable_type, spinner)) - return spinner - - def createCheckBox(self, variable_name, variable_value, variable_type): - spinner = QCheckBox() - spinner.setChecked(variable_value) - spinner.clicked.connect(partial(self.valueChanged, variable_name, variable_type, spinner)) - return spinner - - def createDoubleSpinBox(self, variable_name, variable_value, variable_type, analysis_module_variables_model): - spinner = QDoubleSpinBox() - spinner.setMinimumWidth(75) - spinner.setMaximum(analysis_module_variables_model.getVariableMaximumValue(variable_name)) - spinner.setMinimum(analysis_module_variables_model.getVariableMinimumValue(variable_name)) - spinner.setSingleStep(analysis_module_variables_model.getVariableStepValue(variable_name)) - spinner.setValue(variable_value) - spinner.valueChanged.connect(partial(self.valueChanged, variable_name, variable_type, spinner)) - return spinner; - - def valueChanged(self, variable_name, variable_type, variable_control): - value = None - if variable_type == bool: - assert isinstance(variable_control, QCheckBox) - value = variable_control.isChecked() - elif variable_type == float: - assert isinstance(variable_control, QDoubleSpinBox) - value = variable_control.value() - elif variable_type == str: - assert isinstance(variable_control, QLineEdit) - value = variable_control.text() - value = str(value).strip() - if len(value) == 0: - value = None - elif variable_type == int: - assert isinstance(variable_control, QSpinBox) - value = variable_control.value() - - if value is not None: - AnalysisModuleVariablesModel.setVariableValue(self._analysis_module_name, variable_name, value) diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/caselist.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/caselist.py deleted file mode 100644 index da09206cd7..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/caselist.py +++ /dev/null @@ -1,114 +0,0 @@ -from PyQt4.QtCore import QSize -from PyQt4.QtGui import QListWidget, QMessageBox, QAbstractItemView, QWidget, QVBoxLayout, QLabel -from PyQt4.QtGui import QToolButton, QHBoxLayout - -from ert_gui import ERT -from ert_gui.ertwidgets import addHelpToWidget -from ert_gui.ertwidgets.models.ertmodel import getAllCases, selectOrCreateNewCase -from ert_gui.ertwidgets.validateddialog import ValidatedDialog -from ert_gui.ertwidgets import resourceIcon - - -class AddRemoveWidget(QWidget): - """ - A simple class that provides to vertically positioned buttons for adding and removing something. - The addFunction and removeFunction functions must be provided. - """ - - def __init__(self, addFunction=None, removeFunction=None, horizontal=False): - QWidget.__init__(self) - - self.addButton = QToolButton(self) - self.addButton.setIcon(resourceIcon("add")) - self.addButton.setIconSize(QSize(16, 16)) - self.addButton.clicked.connect(addFunction) - - self.removeButton = QToolButton(self) - self.removeButton.setIcon(resourceIcon("remove")) - self.removeButton.setIconSize(QSize(16, 16)) - self.removeButton.clicked.connect(removeFunction) - - if horizontal: - self.buttonLayout = QHBoxLayout() - else: - self.buttonLayout = QVBoxLayout() - - self.buttonLayout.setMargin(0) - - if horizontal: - self.buttonLayout.addStretch(1) - - self.buttonLayout.addWidget(self.addButton) - self.buttonLayout.addWidget(self.removeButton) - - if not horizontal: - self.buttonLayout.addStretch(1) - else: - self.buttonLayout.addSpacing(2) - - self.setLayout(self.buttonLayout) - - def enableAddButton(self, state): - """Enable or disable the add button""" - self.addButton.setEnabled(state) - - def enableRemoveButton(self, state): - """Enable or disable the remove button""" - self.removeButton.setEnabled(state) - -class CaseList(QWidget): - - def __init__(self): - QWidget.__init__(self) - - addHelpToWidget(self, "init/case_list") - - layout = QVBoxLayout() - - self._list = QListWidget(self) - self._list.setMinimumHeight(100) - self._list.setMaximumHeight(250) - self._default_selection_mode = self._list.selectionMode() - self.setSelectable(False) - - layout.addWidget(QLabel("Available Cases:")) - layout.addWidget(self._list) - - self._addRemoveWidget = AddRemoveWidget(self.addItem, self.removeItem, horizontal=True) - self._addRemoveWidget.enableRemoveButton(False) - layout.addWidget(self._addRemoveWidget) - - self._title = "New keyword" - self._description = "Enter name of keyword:" - - self.setLayout(layout) - - ERT.ertChanged.connect(self.updateList) - self.updateList() - - def setSelectable(self, selectable): - if selectable: - self._list.setSelectionMode(self._default_selection_mode) - else: - self._list.setSelectionMode(QAbstractItemView.NoSelection) - - - def addItem(self): - dialog = ValidatedDialog("New case", "Enter name of new case:", getAllCases()) - new_case_name = dialog.showAndTell() - if not new_case_name == "": - selectOrCreateNewCase(new_case_name) - - def removeItem(self): - message = "Support for removal of items has not been implemented!" - QMessageBox.information(self, "Not implemented!", message) - - - def updateList(self): - """Retrieves data from the model and inserts it into the list""" - case_list = getAllCases() - - self._list.clear() - - for case in case_list: - self._list.addItem(case) diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/caseselector.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/caseselector.py deleted file mode 100644 index f3afd9f529..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/caseselector.py +++ /dev/null @@ -1,55 +0,0 @@ -from PyQt4.QtGui import QComboBox - -from ert_gui import ERT -from ert_gui.ertwidgets import addHelpToWidget -from ert_gui.ertwidgets.models.ertmodel import getAllCases, selectOrCreateNewCase, getCurrentCaseName, getAllInitializedCases - - -class CaseSelector(QComboBox): - def __init__(self, update_ert=True, show_only_initialized=False, ignore_current=False, help_link="init/current_case_selection"): - QComboBox.__init__(self) - self._update_ert = update_ert # If true current case of ert will be change - self._show_only_initialized = show_only_initialized # only show initialized cases - self._ignore_current = ignore_current # ignore the currently selected case if it changes - - - addHelpToWidget(self, help_link) - self.setSizeAdjustPolicy(QComboBox.AdjustToContents) - - self.populate() - - self.currentIndexChanged[int].connect(self.selectionChanged) - ERT.ertChanged.connect(self.populate) - - def _getAllCases(self): - if self._show_only_initialized: - return getAllInitializedCases() - else: - return getAllCases() - - def selectionChanged(self, index): - if self._update_ert: - assert 0 <= index < self.count(), "Should not happen! Index out of range: 0 <= %i < %i" % (index, self.count()) - - item = self._getAllCases()[index] - selectOrCreateNewCase(item) - - def populate(self): - block = self.signalsBlocked() - self.blockSignals(True) - - case_list = self._getAllCases() - self.clear() - - for case in case_list: - self.addItem(case) - - current_index = 0 - current_case = getCurrentCaseName() - if current_case in case_list: - current_index = case_list.index(current_case) - - if current_index != self.currentIndex() and not self._ignore_current: - self.setCurrentIndex(current_index) - - self.blockSignals(block) diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/checklist.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/checklist.py deleted file mode 100644 index 4220e9ac34..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/checklist.py +++ /dev/null @@ -1,174 +0,0 @@ -from PyQt4.QtCore import QSize, Qt -from PyQt4.QtGui import QToolButton, QHBoxLayout, QLabel, QListWidget -from PyQt4.QtGui import QWidget, QVBoxLayout, QListWidgetItem, QMenu, QAbstractItemView - -from ert_gui.ertwidgets import addHelpToWidget, SearchBox, resourceIcon - - -class CheckList(QWidget): - def __init__(self, model, label="", help_link="", custom_filter_button=None): - """ - :param custom_filter_button: if needed, add a button that opens a custom filter menu. Useful when search alone - isn't enough to filter the list. - :type custom_filter_button: QToolButton - """ - QWidget.__init__(self) - - self._model = model - - if help_link != "": - addHelpToWidget(self, help_link) - - layout = QVBoxLayout() - - self._createCheckButtons() - - self._list = QListWidget() - self._list.setContextMenuPolicy(Qt.CustomContextMenu) - self._list.setSelectionMode(QAbstractItemView.ExtendedSelection) - - self._search_box = SearchBox() - - check_button_layout = QHBoxLayout() - - check_button_layout.setMargin(0) - check_button_layout.setSpacing(0) - check_button_layout.addWidget(QLabel(label)) - check_button_layout.addStretch(1) - check_button_layout.addWidget(self._checkAllButton) - check_button_layout.addWidget(self._uncheckAllButton) - - layout.addLayout(check_button_layout) - layout.addWidget(self._list) - - """ - Inserts the custom filter button, if provided. The caller is responsible for all related actions. - """ - if custom_filter_button is not None: - search_bar_layout = QHBoxLayout() - search_bar_layout.addWidget(self._search_box) - search_bar_layout.addWidget(custom_filter_button) - layout.addLayout(search_bar_layout) - else: - layout.addWidget(self._search_box) - - self.setLayout(layout) - - self._checkAllButton.clicked.connect(self.checkAll) - self._uncheckAllButton.clicked.connect(self.uncheckAll) - self._list.itemChanged.connect(self.itemChanged) - self._search_box.filterChanged.connect(self.filterList) - self._list.customContextMenuRequested.connect(self.showContextMenu) - - self._model.selectionChanged.connect(self.modelChanged) - self._model.modelChanged.connect(self.modelChanged) - - self.modelChanged() - - def _createCheckButtons(self): - self._checkAllButton = QToolButton() - self._checkAllButton.setIcon(resourceIcon("checked")) - self._checkAllButton.setIconSize(QSize(16, 16)) - self._checkAllButton.setToolButtonStyle(Qt.ToolButtonIconOnly) - self._checkAllButton.setAutoRaise(True) - self._checkAllButton.setToolTip("Select all") - self._uncheckAllButton = QToolButton() - self._uncheckAllButton.setIcon(resourceIcon("notchecked")) - self._uncheckAllButton.setIconSize(QSize(16, 16)) - self._uncheckAllButton.setToolButtonStyle(Qt.ToolButtonIconOnly) - self._uncheckAllButton.setAutoRaise(True) - self._uncheckAllButton.setToolTip("Unselect all") - - def itemChanged(self, item): - """@type item: QListWidgetItem""" - if item.checkState() == Qt.Checked: - self._model.selectValue(str(item.text())) - elif item.checkState() == Qt.Unchecked: - self._model.unselectValue(str(item.text())) - else: - raise AssertionError("Unhandled checkstate!") - - def modelChanged(self): - self._list.clear() - - items = self._model.getList() - - for item in items: - list_item = QListWidgetItem(item) - list_item.setFlags(list_item.flags() | Qt.ItemIsUserCheckable) - - if self._model.isValueSelected(item): - list_item.setCheckState(Qt.Checked) - else: - list_item.setCheckState(Qt.Unchecked) - - self._list.addItem(list_item) - - self.filterList(self._search_box.filter()) - - def setSelectionEnabled(self, enabled): - self.setEnabled(enabled) - self._checkAllButton.setEnabled(enabled) - self._uncheckAllButton.setEnabled(enabled) - - def filterList(self, filter): - filter = filter.lower() - - for index in range(0, self._list.count()): - item = self._list.item(index) - text = str(item.text()).lower() - - if filter == "": - item.setHidden(False) - elif filter in text: - item.setHidden(False) - else: - item.setHidden(True) - - def checkAll(self): - """ - Checks all visible items in the list. - """ - for index in range(0, self._list.count()): - item = self._list.item(index) - if not item.isHidden(): - self._model.selectValue(str(item.text())) - - def uncheckAll(self): - """ - Unchecks all items in the list, visible or not - """ - self._model.unselectAll() - - def checkSelected(self): - items = [] - for item in self._list.selectedItems(): - items.append(str(item.text())) - - for item in items: - self._model.selectValue(item) - - def uncheckSelected(self): - items = [] - for item in self._list.selectedItems(): - items.append(str(item.text())) - - for item in items: - self._model.unselectValue(item) - - def showContextMenu(self, point): - p = self._list.mapToGlobal(point) - menu = QMenu() - check_selected = menu.addAction("Check selected") - uncheck_selected = menu.addAction("Uncheck selected") - menu.addSeparator() - clear_selection = menu.addAction("Clear selection") - - selected_item = menu.exec_(p) - - if selected_item == check_selected: - self.checkSelected() - elif selected_item == uncheck_selected: - self.uncheckSelected() - elif selected_item == clear_selection: - self._list.clearSelection() diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/closabledialog.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/closabledialog.py deleted file mode 100644 index b5f20599f1..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/closabledialog.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# The file 'closabledialog.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from PyQt4.QtCore import Qt -from PyQt4.QtGui import QDialog, QVBoxLayout, QLayout, QPushButton, QHBoxLayout - - -class ClosableDialog(QDialog): - - def __init__(self, title, widget, parent=None): - QDialog.__init__(self, parent) - - self.setWindowTitle(title) - self.setModal(True) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowCancelButtonHint) - - - layout = QVBoxLayout() - layout.setSizeConstraint(QLayout.SetFixedSize) # not resizable!!! - layout.addWidget(widget) - - self.__button_layout = QHBoxLayout() - self.close_button = QPushButton("Close") - self.close_button.setObjectName("CLOSE") - self.close_button.clicked.connect(self.accept) - self.__button_layout.addStretch() - self.__button_layout.addWidget(self.close_button) - - layout.addStretch() - layout.addLayout(self.__button_layout) - - self.setLayout(layout) - - - def disableCloseButton(self): - self.close_button.setEnabled(False) - - def enableCloseButton(self): - self.close_button.setEnabled(True) - - def keyPressEvent(self, q_key_event): - if not self.close_button.isEnabled() and q_key_event.key() == Qt.Key_Escape: - pass - else: - QDialog.keyPressEvent(self, q_key_event) - - def addButton(self, caption, listner): - button = QPushButton(caption) - button.setObjectName(str(caption).capitalize()) - self.__button_layout.insertWidget(1,button) - button.clicked.connect(listner) - - def toggleButton(self, caption, enabled): - button = self.findChild(QPushButton,str(caption).capitalize()) - if button is not None: - button.setEnabled(enabled) - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/customdialog.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/customdialog.py deleted file mode 100644 index 1f6e3cffc8..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/customdialog.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'customdialog.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from PyQt4.QtCore import Qt, QSize, SIGNAL -from PyQt4.QtGui import QDialog, QColor, QFormLayout, QLabel, QWidget, QDialogButtonBox, QLayout - - -class CustomDialog(QDialog): - INVALID_COLOR = QColor(255, 235, 235) - - def __init__(self, title="Title", description="Description", parent=None): - QDialog.__init__(self, parent) - - self._option_list = [] - """ :type: list of QWidget """ - - self.setModal(True) - self.setWindowTitle(title) - - self.layout = QFormLayout() - self.layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) - self.layout.setSizeConstraint(QLayout.SetFixedSize) - - label = QLabel(description) - label.setAlignment(Qt.AlignHCenter) - - self.layout.addRow(self.createSpace(5)) - self.layout.addRow(label) - self.layout.addRow(self.createSpace(10)) - - self.ok_button = None - - self.setLayout(self.layout) - - def notValid(self, msg): - """Called when the name is not valid.""" - self.ok_button.setEnabled(False) - - def valid(self): - """Called when the name is valid.""" - self.ok_button.setEnabled(True) - - def optionValidationChanged(self): - valid = True - for option in self._option_list: - if hasattr(option, "isValid"): - if not option.isValid(): - valid = False - self.notValid("One or more options are incorrectly set!") - - if valid: - self.valid() - - def showAndTell(self): - """ - Shows the dialog modally and returns the true or false (accept/reject) - @rtype: bool - """ - self.optionValidationChanged() - return self.exec_() - - def createSpace(self, size=5): - """Creates a widget that can be used as spacing on a panel.""" - qw = QWidget() - qw.setMinimumSize(QSize(size, size)) - - return qw - - def addSpace(self, size=10): - """ Add some vertical spacing """ - space_widget = self.createSpace(size) - self.layout.addRow("", space_widget) - - def addLabeledOption(self, label, option_widget): - """ - @type option_widget: QWidget - """ - self._option_list.append(option_widget) - - if hasattr(option_widget, "validationChanged"): - option_widget.validationChanged.connect(self.optionValidationChanged) - - if hasattr(option_widget, "getValidationSupport"): - validation_support = option_widget.getValidationSupport() - validation_support.validationChanged.connect(self.optionValidationChanged) - - self.layout.addRow("%s:" % label, option_widget) - - def addWidget(self, widget, label=""): - if not label.endswith(":"): - label = "%s:" % label - self.layout.addRow(label, widget) - - def addButtons(self): - buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) - self.ok_button = buttons.button(QDialogButtonBox.Ok) - self.ok_button.setEnabled(False) - - self.layout.addRow(self.createSpace(10)) - self.layout.addRow(buttons) - - self.connect(buttons, SIGNAL('accepted()'), self.accept) - self.connect(buttons, SIGNAL('rejected()'), self.reject) diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/legend.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/legend.py deleted file mode 100644 index c7c7221e7e..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/legend.py +++ /dev/null @@ -1,61 +0,0 @@ -from PyQt4.QtCore import QSize -from PyQt4.QtGui import QWidget, QPainter, QHBoxLayout, QLabel - - -class LegendMarker(QWidget): - """A widget that shows a colored box""" - def __init__(self, color): - QWidget.__init__(self) - - self.setMaximumSize(QSize(12, 12)) - self.setMinimumSize(QSize(12, 12)) - - self.color = color - - def paintEvent(self, paintevent): - """Paints the box""" - painter = QPainter(self) - - rect = self.contentsRect() - rect.setWidth(rect.width() - 1) - rect.setHeight(rect.height() - 1) - painter.drawRect(rect) - - rect.setX(rect.x() + 1) - rect.setY(rect.y() + 1) - painter.fillRect(rect, self.color) - -class Legend(QWidget): - """Combines a LegendMarker with a label""" - def __init__(self, legend, color): - QWidget.__init__(self) - - self.setMinimumWidth(140) - self.setMaximumHeight(25) - - self.legend = legend - - layout = QHBoxLayout() - layout.setMargin(0) - - self.legend_marker = LegendMarker(color) - self.legend_marker.setToolTip(legend) - - layout.addWidget(self.legend_marker) - self.legend_label = QLabel(legend) - layout.addWidget(self.legend_label) - layout.addStretch() - - self.setLayout(layout) - - def setLegend(self, legend): - self.legend_label.setText(legend) - - def updateLegend(self, *args): - legend_text = self.legend % args - self.legend_label.setText(legend_text) - self.legend_marker.setToolTip(legend_text) - - def setColor(self, color): - self.legend_marker.color = color - self.legend_marker.update() \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/listeditbox.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/listeditbox.py deleted file mode 100644 index bfdf415503..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/listeditbox.py +++ /dev/null @@ -1,186 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'pathchooser.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from PyQt4.QtCore import Qt, QSize -from PyQt4.QtGui import QHBoxLayout, QLineEdit, QCompleter, QToolButton, QInputDialog, QMessageBox, QWidget - -from ert_gui.ertwidgets import resourceIcon -from ert_gui.ertwidgets.validationsupport import ValidationSupport - - -class AutoCompleteLineEdit(QLineEdit): - # http://blog.elentok.com/2011/08/autocomplete-textbox-for-multiple.html - def __init__(self, items, parent=None): - super(AutoCompleteLineEdit, self).__init__(parent) - - self._separators = [",", " "] - - self._completer = QCompleter(items, self) - self._completer.setWidget(self) - self._completer.activated[str].connect(self.__insertCompletion) - self._completer.setCaseSensitivity(Qt.CaseInsensitive) - - self.__keysToIgnore = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab] - - def __insertCompletion(self, completion): - extra = len(completion) - len(self._completer.completionPrefix()) - extra_text = completion[-extra:] - extra_text += ', ' - self.setText(self.text() + extra_text) - - def textUnderCursor(self): - text = self.text() - text_under_cursor = '' - i = self.cursorPosition() - 1 - while i >= 0 and text[i] not in self._separators: - text_under_cursor = text[i] + text_under_cursor - i -= 1 - return text_under_cursor - - def keyPressEvent(self, event): - if self._completer.popup().isVisible(): - if event.key() in self.__keysToIgnore: - event.ignore() - return - - super(AutoCompleteLineEdit, self).keyPressEvent(event) - - completion_prefix = self.textUnderCursor() - if completion_prefix != self._completer.completionPrefix(): - self.__updateCompleterPopupItems(completion_prefix) - if len(event.text()) > 0 and len(completion_prefix) > 0: - self._completer.complete() - if len(completion_prefix) == 0: - self._completer.popup().hide() - - def __updateCompleterPopupItems(self, completionPrefix): - self._completer.setCompletionPrefix(completionPrefix) - self._completer.popup().setCurrentIndex(self._completer.completionModel().index(0, 0)) - - -class ListEditBox(QWidget): - ITEM_DOES_NOT_EXIST_MSG = "The item: '%s' is not a possible choice." - NO_ITEMS_SPECIFIED_MSG = "The list must contain at least one item or * (for all)." - DEFAULT_MSG = "A list of comma separated case names or * for all." - - def __init__(self, possible_items): - QWidget.__init__(self) - - self._editing = True - self._possible_items = possible_items - - self._list_edit_line = AutoCompleteLineEdit(possible_items, self) - self._list_edit_line.setMinimumWidth(350) - - layout = QHBoxLayout() - layout.setMargin(0) - - layout.addWidget(self._list_edit_line) - - dialog_button = QToolButton(self) - dialog_button.setIcon(resourceIcon("ide/small/add")) - dialog_button.setIconSize(QSize(16, 16)) - dialog_button.clicked.connect(self.addChoice) - - layout.addWidget(dialog_button) - - self.setLayout(layout) - - self._validation_support = ValidationSupport(self) - self._valid_color = self._list_edit_line.palette().color(self._list_edit_line.backgroundRole()) - - self._list_edit_line.setText("") - self._editing = False - - self._list_edit_line.editingFinished.connect(self.validateList) - self._list_edit_line.textChanged.connect(self.validateList) - - self.validateList() - - def getListText(self): - text = str(self._list_edit_line.text()) - text = "".join(text.split()) - return text - - def getItems(self): - text = self.getListText() - items = text.split(",") - - if len(items) == 1 and items[0] == "*": - items = self._possible_items - - return [item for item in items if len(item) > 0] - - def validateList(self): - """Called whenever the list is modified""" - palette = self._list_edit_line.palette() - - items = self.getItems() - - valid = True - message = "" - - if len(items) == 0: - valid = False - message = ListEditBox.NO_ITEMS_SPECIFIED_MSG - else: - for item in items: - if item not in self._possible_items: - valid = False - message = ListEditBox.ITEM_DOES_NOT_EXIST_MSG % item - - validity_type = ValidationSupport.WARNING - - if not valid: - color = ValidationSupport.ERROR_COLOR - else: - color = self._valid_color - - self._validation_support.setValidationMessage(message, validity_type) - self._list_edit_line.setToolTip(message) - palette.setColor(self._list_edit_line.backgroundRole(), color) - - self._list_edit_line.setPalette(palette) - - if valid: - self._list_edit_line.setToolTip(ListEditBox.DEFAULT_MSG) - - def addChoice(self): - if len(self._possible_items) == 0: - QMessageBox.information(self, "No items", "No items available for selection!") - else: - item, ok = QInputDialog.getItem(self, - "Select a case", - "Select a case to add to the case list:", - self._possible_items) - - if ok: - item = str(item).strip() - text = str(self._list_edit_line.text()).rstrip() - - if len(text) == 0: - text = item + ", " - elif text.endswith(","): - text += " " + item - else: - text += ", " + item - - self._list_edit_line.setText(text) - - def getValidationSupport(self): - return self._validation_support - - def isValid(self): - return self._validation_support.isValid() diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/CMakeLists.txt deleted file mode 100644 index 3adbff2348..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - activerealizationsmodel.py - all_cases_model.py - analysismodulevariablesmodel.py - ertmodel.py - ertsummary.py - path_model.py - selectable_list_model.py - targetcasemodel.py - valuemodel.py -) - -add_python_package("python.ert_gui.ertwidgets.models" ${PYTHON_INSTALL_PREFIX}/ert_gui/ertwidgets/models "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/activerealizationsmodel.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/activerealizationsmodel.py deleted file mode 100644 index fe6bf34032..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/activerealizationsmodel.py +++ /dev/null @@ -1,33 +0,0 @@ -from ert.util import BoolVector -from ert_gui.ertwidgets.models.valuemodel import ValueModel -from ert_gui.ertwidgets.models.ertmodel import getRealizationCount - - -class ActiveRealizationsModel(ValueModel): - def __init__(self): - ValueModel.__init__(self, self.getDefaultValue()) - self._custom = False - - def setValue(self, active_realizations): - if active_realizations is None or active_realizations.strip() == "" or active_realizations == self.getDefaultValue(): - self._custom = False - ValueModel.setValue(self, self.getDefaultValue()) - else: - self._custom = True - ValueModel.setValue(self, active_realizations) - - def getDefaultValue(self): - size = getRealizationCount() - return "0-%d" % (size - 1) - - def getActiveRealizationsMask(self): - count = getRealizationCount() - - mask = BoolVector(default_value=False, initial_size = count) - if not mask.updateActiveMask(self.getValue()): - raise ValueError('Error while parsing range string "%s"!' % self.getValue()) - - if len(mask) != count: - raise ValueError("Mask size changed %d != %d!" % (count, len(mask))) - - return mask diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/all_cases_model.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/all_cases_model.py deleted file mode 100644 index f9cb08a395..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/all_cases_model.py +++ /dev/null @@ -1,69 +0,0 @@ -from PyQt4.QtCore import QAbstractItemModel, QModelIndex, Qt, QVariant - -from ert_gui.ertwidgets.models.ertmodel import getAllCases - - -class AllCasesModel(QAbstractItemModel): - - def __init__(self): - QAbstractItemModel.__init__(self) - self.__data = [] - - def index(self, row, column, parent=None, *args, **kwargs): - return self.createIndex(row, column, parent) - - def parent(self, index=None): - return QModelIndex() - - def rowCount(self, parent=None, *args, **kwargs): - items = self.getAllItems() - return len(items) - - def columnCount(self, QModelIndex_parent=None, *args, **kwargs): - return 1 - - - def data(self, index, role=None): - assert isinstance(index, QModelIndex) - - if index.isValid(): - items = self.getAllItems() - row = index.row() - item = items[row] - - if role == Qt.DisplayRole: - return item - - return QVariant() - - def itemAt(self, index): - assert isinstance(index, QModelIndex) - - if index.isValid(): - row = index.row() - return self.getAllItems()[row] - - return None - - - def getAllItems(self): - return getAllCases() - - - def indexOf(self, item): - items = self.getAllItems() - - if item in items: - - return items.index(item) - - return -1 - - - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/analysismodulevariablesmodel.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/analysismodulevariablesmodel.py deleted file mode 100644 index 98d56c9732..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/analysismodulevariablesmodel.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'analysismodulevariablesmodel.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from ert.analysis.analysis_module import AnalysisModule -from ert_gui import ERT -from ert_gui.ertwidgets.models.ertmodel import getRealizationCount - -class AnalysisModuleVariablesModel(object): - - _VARIABLE_NAMES = { - "LAMBDA0": {"type": float, "min": -1, "max": 10000000000000, "step":1.0, "labelname":"Initial Lambda", "pos":0}, - "USE_PRIOR": {"type": bool, "labelname":"Use both Prior and Observation Variability", "pos":1}, - "LAMBDA_REDUCE": {"type": float, "min": 0, "max": 1, "step":0.1, "labelname":"Lambda Reduction Factor", "pos":2}, - "LAMBDA_INCREASE": {"type": float, "min": 1, "max": 10, "step":0.1, "labelname":"Lambda Incremental Factor", "pos":3}, - "LAMBDA_MIN": {"type": float, "min": 0, "max": 10, "step":0.1, "labelname":"Minimum Lambda", "pos":4}, - "LOG_FILE": {"type": str, "labelname":"Log File", "pos":5}, - "CLEAR_LOG": {"type": bool, "labelname":"Clear Existing Log File", "pos":6}, - "LAMBDA_RECALCULATE": {"type": bool, "labelname":"Recalculate Lambda after each Iteration", "pos":7}, - "ENKF_TRUNCATION" :{"type": float, "min": 0, "max": 1, "step":0.1, "labelname":"Singular value truncation", "pos":9}, - "CV_NFOLDS": {"type": int, "min": 2, "max": 9999, "step":1.0, "labelname":"CV_NFOLDS", "pos":11}, - "FWD_STEP_R2_LIMIT":{"type": float, "min": -1, "max": 100, "step":1.0, "labelname":"FWD_STEP_R2_LIMIT", "pos":12}, - "CV_PEN_PRESS": {"type": bool, "labelname":"CV_PEN_PRESS", "pos":13} - } - - @classmethod - def getVariableNames(cls, analysis_module_name): - """ @rtype: list of str """ - analysis_module = ERT.ert.analysisConfig().getModule(analysis_module_name) - assert isinstance(analysis_module, AnalysisModule) - items = [] - for name in cls._VARIABLE_NAMES: - if analysis_module.hasVar(name): - items.append(name) - return items - - @classmethod - def getVariableType(cls, name): - return cls._VARIABLE_NAMES[name]["type"] - - @classmethod - def getVariableMaximumValue(cls, name): - if name == "CV_NFOLDS": - return getRealizationCount() - 1 - - return cls._VARIABLE_NAMES[name]["max"] - - @classmethod - def getVariableMinimumValue(cls, name): - return cls._VARIABLE_NAMES[name]["min"] - - @classmethod - def getVariableStepValue(cls, name): - return cls._VARIABLE_NAMES[name]["step"] - - @classmethod - def getVariableLabelName(cls, name): - return cls._VARIABLE_NAMES[name]["labelname"] - - @classmethod - def getVariablePosition(cls, name): - return cls._VARIABLE_NAMES[name]["pos"] - - @classmethod - def setVariableValue(cls, analysis_module_name, name, value): - analysis_module = ERT.ert.analysisConfig().getModule(analysis_module_name) - result = analysis_module.setVar(name, str(value)) - - @classmethod - def getVariableValue(cls, analysis_module_name, name): - """ @rtype: int or float or bool or str """ - analysis_module = ERT.ert.analysisConfig().getModule(analysis_module_name) - variable_type = cls.getVariableType(name) - if variable_type == float: - return analysis_module.getDouble(name) - elif variable_type == bool: - return analysis_module.getBool(name) - elif variable_type == str: - return analysis_module.getStr(name) - elif variable_type == int: - return analysis_module.getInt(name) diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/ertmodel.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/ertmodel.py deleted file mode 100644 index 2309faff59..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/ertmodel.py +++ /dev/null @@ -1,172 +0,0 @@ -from ert.analysis.analysis_module import AnalysisModule -from ert.analysis.enums.analysis_module_options_enum import AnalysisModuleOptionsEnum -from ert.enkf import RealizationStateEnum, EnkfVarType -from ert.job_queue import WorkflowRunner -from ert.util import BoolVector, StringList -from ert_gui import ERT -from ert_gui.ertwidgets import showWaitCursorWhileWaiting - - -def getRealizationCount(): - return ERT.ert.getEnsembleSize() - - -def getAllCases(): - """ @rtype: list[str] """ - fs = ERT.ert.getEnkfFsManager().getCurrentFileSystem() - case_list = ERT.ert.getEnkfFsManager().getCaseList() - return [str(case) for case in case_list if not ERT.ert.getEnkfFsManager().isCaseHidden(case)] - - -def caseExists(case_name): - """ @rtype: bool """ - return str(case_name) in getAllCases() - - -def caseIsInitialized(case_name): - """ @rtype: bool """ - return ERT.ert.getEnkfFsManager().isCaseInitialized(case_name) - - -def getAllInitializedCases(): - """ @rtype: list[str] """ - return [case for case in getAllCases() if caseIsInitialized(case)] - - -def getCurrentCaseName(): - """ @rtype: str """ - return str(ERT.ert.getEnkfFsManager().getCurrentFileSystem().getCaseName()) - - -def getHistoryLength(): - """ @rtype: int """ - return ERT.ert.getHistoryLength() - - -@showWaitCursorWhileWaiting -def selectOrCreateNewCase(case_name): - if getCurrentCaseName() != case_name: - fs = ERT.ert.getEnkfFsManager().getFileSystem(case_name) - ERT.ert.getEnkfFsManager().switchFileSystem(fs) - ERT.emitErtChange() - - -def caseHasDataAndIsNotRunning(case): - """ @rtype: bool """ - case_has_data = False - state_map = ERT.ert.getEnkfFsManager().getStateMapForCase(case) - - for state in state_map: - if state == RealizationStateEnum.STATE_HAS_DATA: - case_has_data = True - break - - return case_has_data and not caseIsRunning(case) - - -def getAllCasesWithDataAndNotRunning(): - """ @rtype: list[str] """ - return [case for case in getAllCases() if caseHasDataAndIsNotRunning(case)] - - -def caseIsRunning(case): - """ @rtype: bool """ - return ERT.ert.getEnkfFsManager().isCaseRunning(case) - - -def getAllCasesNotRunning(): - """ @rtype: list[str] """ - return [case for case in getAllCases() if not caseIsRunning(case)] - - -def getCaseRealizationStates(case_name): - """ @rtype: list[ert.enkf.enums.RealizationStateEnum] """ - state_map = ERT.ert.getEnkfFsManager().getStateMapForCase(case_name) - return [state for state in state_map] - - -@showWaitCursorWhileWaiting -def initializeCurrentCaseFromScratch(parameters, members): - selected_parameters = StringList(parameters) - for member in members: - member = int(member.strip()) - ERT.ert.getEnkfFsManager().initializeFromScratch(selected_parameters, member, member) - - ERT.emitErtChange() - - -@showWaitCursorWhileWaiting -def initializeCurrentCaseFromExisting(source_case, target_case, source_report_step, parameters, members): - if caseExists(source_case) and caseIsInitialized(source_case) and caseExists(target_case): - total_member_count = getRealizationCount() - - member_mask = BoolVector.createFromList(total_member_count, members) - selected_parameters = StringList(parameters) - - ERT.ert.getEnkfFsManager().customInitializeCurrentFromExistingCase(source_case, source_report_step, member_mask, - selected_parameters) - - ERT.emitErtChange() - - -def getParameterList(): - """ @rtype: list[str] """ - return [str(p) for p in ERT.ert.ensembleConfig().getKeylistFromVarType(EnkfVarType.PARAMETER)] - - -def getRunPath(): - """ @rtype: str """ - return ERT.ert.getModelConfig().getRunpathAsString() - - -def getNumberOfIterations(): - """ @rtype: int """ - return ERT.ert.analysisConfig().getAnalysisIterConfig().getNumIterations() - - -def setNumberOfIterations(iteration_count): - """ @type iteration_count: int """ - if iteration_count != getNumberOfIterations(): - ERT.ert.analysisConfig().getAnalysisIterConfig().setNumIterations(iteration_count) - ERT.emitErtChange() - - -def getWorkflowNames(): - """ @rtype: list[str] """ - return sorted(ERT.ert.getWorkflowList().getWorkflowNames(), key=str.lower) - - -def createWorkflowRunner(workflow_name): - """ @rtype: WorkflowRunner """ - workflow_list = ERT.ert.getWorkflowList() - - workflow = workflow_list[workflow_name] - context = workflow_list.getContext() - return WorkflowRunner(workflow, ERT.ert, context) - - -def getAnalysisModules(iterable=False): - """ @rtype: list[ert.analysis.AnalysisModule]""" - module_names = ERT.ert.analysisConfig().getModuleList() - - modules = [] - for module_name in module_names: - module = ERT.ert.analysisConfig().getModule(module_name) - module_is_iterable = module.checkOption(AnalysisModuleOptionsEnum.ANALYSIS_ITERABLE) - - if iterable == module_is_iterable: - modules.append(module) - - return sorted(modules, key=AnalysisModule.getName) - -def getAnalysisModuleNames(iterable=False): - """ @rtype: list[str] """ - modules = getAnalysisModules(iterable) - return [module.getName() for module in modules] - - -def getCurrentAnalysisModuleName(): - """ @rtype: str """ - return ERT.ert.analysisConfig().activeModuleName() - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/ertsummary.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/ertsummary.py deleted file mode 100644 index 5ad142c39b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/ertsummary.py +++ /dev/null @@ -1,58 +0,0 @@ -from ert.enkf.enums.enkf_obs_impl_type_enum import EnkfObservationImplementationType -from ert.enkf.enums.enkf_var_type_enum import EnkfVarType -from ert_gui import ERT - -class ErtSummary(object): - - def getForwardModels(self): - """ @rtype: list of str """ - forward_model = ERT.ert.getModelConfig().getForwardModel() - return [job for job in forward_model.joblist()] - - def getParameters(self): - """ @rtype: list of str """ - parameters = ERT.ert.ensembleConfig().getKeylistFromVarType(EnkfVarType.PARAMETER) - return sorted([parameter for parameter in parameters], key=lambda k : k.lower()) - - - def getObservations(self): - """ @rtype: list of str """ - gen_obs = ERT.ert.getObservations().getTypedKeylist(EnkfObservationImplementationType.GEN_OBS) - - - summary_obs = ERT.ert.getObservations().getTypedKeylist(EnkfObservationImplementationType.SUMMARY_OBS) - - keys = [] - summary_keys_count = {} - summary_keys = [] - for key in summary_obs: - data_key = ERT.ert.getObservations()[key].getDataKey() - - if not data_key in summary_keys_count: - summary_keys_count[data_key] = 1 - summary_keys.append(data_key) - else: - summary_keys_count[data_key] += 1 - - if key == data_key: - keys.append(key) - else: - keys.append("%s [%s]" % (key, data_key)) - - # keys = [] - # for key in summary_keys: - # count = summary_keys_count[key] - # if count > 1: - # #keys.append("%s (%d)" % (key, count)) - # keys.append("%s" % key) - # else: - # keys.append(key) - - obs_keys = [observation for observation in gen_obs] + summary_keys - return sorted(obs_keys, key=lambda k : k.lower()) - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/path_model.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/path_model.py deleted file mode 100644 index d755aff584..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/path_model.py +++ /dev/null @@ -1,48 +0,0 @@ -from ert_gui.ertwidgets.models.valuemodel import ValueModel - - -class PathModel(ValueModel): - def __init__(self, default_path, is_required=True, must_be_a_directory=False, must_be_a_file=True, - must_exist=False, must_be_absolute=False, must_be_executable=False): - ValueModel.__init__(self, default_path) - - self._path_is_required = is_required - self._path_must_be_a_directory = must_be_a_directory - self._path_must_be_a_file = must_be_a_file - self._path_must_be_executable = must_be_executable - self._path_must_exist = must_exist - self._path_must_be_absolute = must_be_absolute - - def pathIsRequired(self): - """ @rtype: bool """ - return self._path_is_required - - def pathMustBeADirectory(self): - """ @rtype: bool """ - return self._path_must_be_a_directory - - def pathMustBeAFile(self): - """ @rtype: bool """ - return self._path_must_be_a_file - - def pathMustBeExecutable(self): - """ @rtype: bool """ - return self._path_must_be_executable - - def pathMustExist(self): - """ @rtype: bool """ - return self._path_must_exist - - def pathMustBeAbsolute(self): - """ @rtype: bool """ - return self._path_must_be_absolute - - def getPath(self): - """ @rtype: str """ - return self.getValue() - - def setPath(self, value): - """ - @type value: str - """ - self.setValue(value) diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/selectable_list_model.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/selectable_list_model.py deleted file mode 100644 index d386efeca1..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/selectable_list_model.py +++ /dev/null @@ -1,43 +0,0 @@ -from PyQt4.QtCore import QObject, pyqtSignal - - -class SelectableListModel(QObject): - modelChanged = pyqtSignal() - selectionChanged = pyqtSignal() - - def __init__(self, items): - QObject.__init__(self) - self._selection = {} - self._items = items - - def getList(self): - return self._items - - def isValueSelected(self, value): - return self._selection.get(value, True) - - def selectValue(self, value): - self._setSelectState(value, True) - self.selectionChanged.emit() - - def unselectValue(self, value): - self._setSelectState(value, False) - self.selectionChanged.emit() - - def unselectAll(self): - for item in self.getList(): - self._setSelectState(item, False) - - self.selectionChanged.emit() - - def selectAll(self): - for item in self.getList(): - self._setSelectState(item, True) - - self.selectionChanged.emit() - - def getSelectedItems(self): - return [item for item in self.getList() if self.isValueSelected(item)] - - def _setSelectState(self, key, state): - self._selection[key] = state diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/targetcasemodel.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/targetcasemodel.py deleted file mode 100644 index 6e63798bb1..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/targetcasemodel.py +++ /dev/null @@ -1,36 +0,0 @@ -from ert_gui import ERT -from ert_gui.ertwidgets.models.ertmodel import getCurrentCaseName -from ert_gui.ertwidgets.models.valuemodel import ValueModel - - -class TargetCaseModel(ValueModel): - def __init__(self, format_mode=False): - self._format_mode = format_mode - self._custom = False - ValueModel.__init__(self, self.getDefaultValue()) - ERT.ertChanged.connect(self._caseChanged) - - def setValue(self, target_case): - if target_case is None or target_case.strip() == "" or target_case == self.getDefaultValue(): - self._custom = False - ValueModel.setValue(self, self.getDefaultValue()) - else: - self._custom = True - ValueModel.setValue(self, target_case) - - def getDefaultValue(self): - """ @rtype: str """ - if self._format_mode: - if ERT.ert.analysisConfig().getAnalysisIterConfig().caseFormatSet(): - return ERT.ert.analysisConfig().getAnalysisIterConfig().getCaseFormat() - else: - case_name = getCurrentCaseName() - return "%s_%%d" % case_name - else: - case_name = getCurrentCaseName() - return "%s_smoother_update" % case_name - - - def _caseChanged(self): - if not self._custom: - ValueModel.setValue(self, self.getDefaultValue()) diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/valuemodel.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/valuemodel.py deleted file mode 100644 index e968bc1b80..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/valuemodel.py +++ /dev/null @@ -1,20 +0,0 @@ -from PyQt4.QtCore import QObject, pyqtSignal, pyqtSlot - -class ValueModel(QObject): - valueChanged = pyqtSignal(str) - - def __init__(self, value=""): - super(ValueModel, self).__init__() - self._value = value - - def getValue(self): - """ @rtype: str """ - return self._value - - @pyqtSlot(str) - def setValue(self, value): - self._value = value - self.valueChanged.emit(value) - - def __repr__(self): - return 'ValueModel(QObject)(value = "%s")' % self._value diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/pathchooser.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/pathchooser.py deleted file mode 100644 index e8846e0f26..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/pathchooser.py +++ /dev/null @@ -1,207 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'pathchooser.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import os -import re -from PyQt4.QtCore import QSize -from PyQt4.QtGui import QLineEdit, QToolButton, QFileDialog, QWidget, QHBoxLayout - -from ert_gui.ertwidgets import resourceIcon, addHelpToWidget -from ert_gui.ertwidgets.validationsupport import ValidationSupport - - -class PathChooser(QWidget): - """ - PathChooser: shows, enables choosing of and validates paths. - The data structure expected and sent to the models getValue and setValue is a string. - """ - - PATH_DOES_NOT_EXIST_MSG = "The specified path does not exist." - FILE_IS_NOT_EXECUTABLE_MSG = "The specified file is not an executable." - PATH_IS_NOT_A_FILE_MSG = "The specified path must be a file." - PATH_IS_NOT_ABSOLUTE_MSG = "The specified path must be an absolute path." - PATH_IS_NOT_A_DIRECTORY_MSG = "The specified path must be a directory." - REQUIRED_FIELD_MSG = "A path is required." - -# UNDEFINED = 0 -# REQUIRED = 1 -# FILE = 2 -# DIRECTORY = 4 -# MUST_EXIST = 8 -# EXECUTABLE = 16 - - def __init__(self, model, help_link=""): - """ - :type model: ert_gui.ertwidgets.models.path_model.PathModel - :param help_link: str - """ - QWidget.__init__(self) - addHelpToWidget(self, help_link) - self._validation_support = ValidationSupport(self) - - self._editing = True - - layout = QHBoxLayout() - layout.setMargin(0) - - self._path_line = QLineEdit() - self._path_line.setMinimumWidth(250) - - layout.addWidget(self._path_line) - - dialog_button = QToolButton(self) - dialog_button.setIcon(resourceIcon("ide/small/folder")) - dialog_button.setIconSize(QSize(16, 16)) - dialog_button.clicked.connect(self.selectPath) - layout.addWidget(dialog_button) - - self.valid_color = self._path_line.palette().color(self._path_line.backgroundRole()) - - self._path_line.setText(os.getcwd()) - self._editing = False - - self._model = model - self._model.valueChanged.connect(self.getPathFromModel) - - self._path_line.editingFinished.connect(self.validatePath) - self._path_line.editingFinished.connect(self.contentsChanged) - self._path_line.textChanged.connect(self.validatePath) - - self.setLayout(layout) - self.getPathFromModel() - - - def isPathValid(self, path): - """ @rtype: tuple of (bool, str) """ - path = path.strip() - path_exists = os.path.exists(path) - is_file = os.path.isfile(path) - is_directory = os.path.isdir(path) - is_executable = os.access(path, os.X_OK) - is_absolute = os.path.isabs(path) - - valid = True - message = "" - - if path == "": - if self._model.pathIsRequired(): - valid = False - message = PathChooser.REQUIRED_FIELD_MSG - elif not path_exists: - if self._model.pathMustExist(): - valid = False - message = PathChooser.PATH_DOES_NOT_EXIST_MSG - #todo: check if new (non-existing) file has directory or file format? - elif path_exists: - if self._model.pathMustBeExecutable() and is_file and not is_executable: - valid = False - message = PathChooser.FILE_IS_NOT_EXECUTABLE_MSG - elif self._model.pathMustBeADirectory() and not is_directory: - valid = False - message = PathChooser.PATH_IS_NOT_A_DIRECTORY_MSG - elif self._model.pathMustBeAbsolute() and not is_absolute: - valid = False - message = PathChooser.PATH_IS_NOT_ABSOLUTE_MSG - elif self._model.pathMustBeAFile() and not is_file: - valid = False - message = PathChooser.PATH_IS_NOT_A_FILE_MSG - - return valid, message - - - def validatePath(self): - """Called whenever the path is modified""" - palette = self._path_line.palette() - - valid, message = self.isPathValid(self.getPath()) - - validity_type = ValidationSupport.WARNING - - if not valid: - color = ValidationSupport.ERROR_COLOR - else: - color = self.valid_color - - self._validation_support.setValidationMessage(message, validity_type) - self._path_line.setToolTip(message) - palette.setColor(self._path_line.backgroundRole(), color) - - self._path_line.setPalette(palette) - - - def getPath(self): - """Returns the path""" - return os.path.expanduser(str(self._path_line.text()).strip()) - - def pathExists(self): - """Returns True if the entered path exists""" - return os.path.exists(self.getPath()) - - def selectPath(self): - """Pops up the 'select a file/directory' dialog""" - # todo: This probably needs some reworking to work properly with different scenarios... (file + dir) - self._editing = True - current_directory = self.getPath() - - #if not os.path.exists(currentDirectory): - # currentDirectory = "~" - - if self._model.pathMustBeAFile(): - current_directory = QFileDialog.getOpenFileName(self, "Select a file path", current_directory) - else: - current_directory = QFileDialog.getExistingDirectory(self, "Select a directory", current_directory) - - if not current_directory == "": - if not self._model.pathMustBeAbsolute(): - cwd = os.getcwd() - match = re.match(cwd + "/(.*)", current_directory) - if match: - current_directory = match.group(1) - - self._path_line.setText(current_directory) - self._model.setPath(self.getPath()) - - self._editing = False - - - def contentsChanged(self): - """Called whenever the path is changed.""" - path_is_valid, message = self.isPathValid(self.getPath()) - - if not self._editing and path_is_valid: - self._model.setPath(self.getPath()) - - - def getPathFromModel(self): - """Retrieves data from the model and inserts it into the edit line""" - self._editing = True - - path = self._model.getPath() - if path is None: - path = "" - - self._path_line.setText("%s" % path) - self._editing = False - - - def getValidationSupport(self): - return self._validation_support - - def isValid(self): - return self._validation_support.isValid() - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/searchbox.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/searchbox.py deleted file mode 100644 index 52b8a76a40..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/searchbox.py +++ /dev/null @@ -1,69 +0,0 @@ -from PyQt4.QtCore import pyqtSignal, Qt -from PyQt4.QtGui import QLineEdit, QColor - - -class SearchBox(QLineEdit): - passive_color = QColor(194, 194, 194) - - filterChanged = pyqtSignal(['PyQt_PyObject']) - - def __init__(self): - QLineEdit.__init__(self) - - self.setToolTip("Type to search!") - self.active_color = self.palette().color(self.foregroundRole()) - self.disable_search = True - self.presentSearch() - self.textChanged.connect(self.__emitFilterChanged) - - def __emitFilterChanged(self, filter): - self.filterChanged.emit(self.filter()) - # self.emit(SIGNAL('filterChanged(PyQt_PyObject)'), self.filter()) - - def filter(self): - if self.disable_search: - return "" - else: - return str(self.text()) - - def presentSearch(self): - """Is called to present the greyed out search""" - self.disable_search = True - self.setText("Search") - palette = self.palette() - palette.setColor(self.foregroundRole(), self.passive_color) - self.setPalette(palette) - - def activateSearch(self): - """Is called to remove the greyed out search""" - self.disable_search = False - self.setText("") - palette = self.palette() - palette.setColor(self.foregroundRole(), self.active_color) - self.setPalette(palette) - - def enterSearch(self): - """Called when the line edit gets the focus""" - if str(self.text()) == "Search": - self.activateSearch() - - def exitSearch(self): - """Called when the line edit looses focus""" - if str(self.text()) == "": - self.presentSearch() - - def focusInEvent(self, focus_event): - QLineEdit.focusInEvent(self, focus_event) - self.enterSearch() - - def focusOutEvent(self, focus_event): - QLineEdit.focusOutEvent(self, focus_event) - self.exitSearch() - - - def keyPressEvent(self, key_event): - if key_event.key() == Qt.Key_Escape: - self.clear() - self.clearFocus() - else: - QLineEdit.keyPressEvent(self, key_event) \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/stringbox.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/stringbox.py deleted file mode 100644 index bdb6c32628..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/stringbox.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# The file 'stringbox.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -from PyQt4.QtGui import QPalette, QLineEdit -from ert_gui.ertwidgets import ValidationSupport, addHelpToWidget -from ert_gui.ertwidgets.models.valuemodel import ValueModel - - -class StringBox(QLineEdit): - """StringBox shows a string. The data structure expected and sent to the getter and setter is a string.""" - - def __init__(self, model, help_link="", default_string="", continuous_update=False): - """ - :type model: ValueModel - :type help_link: str - :type default_string: str - :type continuous_update: bool - """ - QLineEdit.__init__(self) - addHelpToWidget(self, help_link) - self.setMinimumWidth(250) - self._validation = ValidationSupport(self) - self._validator = None - self._model = model - - self.editingFinished.connect(self.stringBoxChanged) - self.editingFinished.connect(self.validateString) - - if continuous_update: - self.textChanged.connect(self.stringBoxChanged) - - self.textChanged.connect(self.validateString) - - self._valid_color = self.palette().color(self.backgroundRole()) - self.setText(default_string) - - self._model.valueChanged.connect(self.modelChanged) - self.modelChanged() - - def validateString(self): - string_to_validate = str(self.text()) - - if self._validator is not None: - status = self._validator.validate(string_to_validate) - - palette = QPalette() - if not status: - palette.setColor(self.backgroundRole(), ValidationSupport.ERROR_COLOR) - self.setPalette(palette) - self._validation.setValidationMessage(str(status), ValidationSupport.EXCLAMATION) - else: - palette.setColor(self.backgroundRole(), self._valid_color) - self.setPalette(palette) - self._validation.setValidationMessage("") - - def emitChange(self, q_string): - self.textChanged.emit(str(q_string)) - - def stringBoxChanged(self): - """Called whenever the contents of the editline changes.""" - text = str(self.text()) - if text == "": - text = None - - self._model.setValue(text) - - def modelChanged(self): - """Retrieves data from the model and inserts it into the edit line""" - text = self._model.getValue() - if text is None: - text = "" - - self.setText(str(text)) - - def setValidator(self, validator): - self._validator = validator - - def setAlignment(self, flag): - self.setAlignment(flag) - - def getValidationSupport(self): - return self._validation - - def isValid(self): - return self._validation.isValid() - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/summarypanel.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/summarypanel.py deleted file mode 100644 index 38946a43a7..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/summarypanel.py +++ /dev/null @@ -1,100 +0,0 @@ -from PyQt4.QtCore import Qt -from PyQt4.QtGui import QFrame, QLabel, QVBoxLayout, QHBoxLayout, QScrollArea, QWidget, QGridLayout - -from ert_gui.ertwidgets.models.ertsummary import ErtSummary - - -class SummaryTemplate(object): - def __init__(self, title): - super(SummaryTemplate, self).__init__() - - self.text = "" - self.__finished = False - self.startGroup(title) - - - def startGroup(self, title): - if not self.__finished: - style = "display: inline-block; width: 150px; vertical-align: top; float: left" - self.text += "
\n" % style - self.addTitle(title) - - def addTitle(self, title): - if not self.__finished: - style = "font-size: 16px; font-weight: bold; font-variant: small-caps;" - self.text += "
%s
" % (style, title) - - def addRow(self, value): - if not self.__finished: - style = "text-indent: 5px;" - self.text += "
%s
" % (style, value) - - def endGroup(self): - if not self.__finished: - self.text += "

\n" - - def getText(self): - if not self.__finished: - self.__finished = True - self.endGroup() - return "%s" % self.text - - -class SummaryPanel(QFrame): - def __init__(self, parent=None): - QFrame.__init__(self, parent) - - self.setMinimumWidth(250) - self.setMinimumHeight(150) - - widget = QWidget() - self.layout = QHBoxLayout() - widget.setLayout(self.layout) - - - scroll = QScrollArea() - scroll.setWidgetResizable(True) - scroll.setWidget(widget) - - layout = QGridLayout() - layout.addWidget(scroll) - - self.setLayout(layout) - self.updateSummary() - - - def updateSummary(self): - summary = ErtSummary() - - text = SummaryTemplate("Forward Model") - - for job in summary.getForwardModels(): - text.addRow(job) - - - self.addColumn(text.getText()) - - text = SummaryTemplate("Parameters") - for parameters in summary.getParameters(): - text.addRow(parameters) - - self.addColumn(text.getText()) - - text = SummaryTemplate("Observations") - for observations in summary.getObservations(): - text.addRow(observations) - - self.addColumn(text.getText()) - - - def addColumn(self, text): - layout = QVBoxLayout() - text_widget = QLabel(text) - text_widget.setWordWrap(True) - text_widget.setTextFormat(Qt.RichText) - layout.addWidget(text_widget) - layout.addStretch(1) - - self.layout.addLayout(layout) - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/validateddialog.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/validateddialog.py deleted file mode 100644 index 8f017e06d2..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/validateddialog.py +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'validateddialog.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from PyQt4.QtCore import Qt, QSize, SIGNAL -from PyQt4.QtGui import QDialog, QColor, QFormLayout, QLabel, QWidget, QDialogButtonBox, QLineEdit, QComboBox, QLayout - - -class ValidatedDialog(QDialog): - """ - A dialog for creating a validated new value. Performs validation of name against a provided. - Can be used to select from the list or for creating a new value that is not on the list. - - """ - - INVALID_COLOR = QColor(255, 235, 235) - - def __init__(self, title="Title", description="Description", unique_names=None, choose_from_list=False): - QDialog.__init__(self) - self.setModal(True) - self.setWindowTitle(title) - # self.setMinimumWidth(250) - # self.setMinimumHeight(150) - - if unique_names is None: - unique_names = [] - - self.unique_names = unique_names - self.choose_from_list = choose_from_list - - self.layout = QFormLayout() - self.layout.setSizeConstraint(QLayout.SetFixedSize) - - label = QLabel(description) - label.setAlignment(Qt.AlignHCenter) - - self.layout.addRow(self.createSpace(5)) - self.layout.addRow(label) - self.layout.addRow(self.createSpace(10)) - - buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) - self.ok_button = buttons.button(QDialogButtonBox.Ok) - self.ok_button.setEnabled(False) - - if choose_from_list: - self.param_name_combo = QComboBox() - self.connect(self.param_name_combo, SIGNAL('currentIndexChanged(QString)'), self.validateChoice) - for item in unique_names: - self.param_name_combo.addItem(item) - self.layout.addRow("Job:", self.param_name_combo) - else: - self.param_name = QLineEdit(self) - self.param_name.setFocus() - self.connect(self.param_name, SIGNAL('textChanged(QString)'), self.validateName) - self.validColor = self.param_name.palette().color(self.param_name.backgroundRole()) - - self.layout.addRow("Name:", self.param_name) - - self.layout.addRow(self.createSpace(10)) - - self.layout.addRow(buttons) - - self.connect(buttons, SIGNAL('accepted()'), self.accept) - self.connect(buttons, SIGNAL('rejected()'), self.reject) - - self.setLayout(self.layout) - - def notValid(self, msg): - """Called when the name is not valid.""" - self.ok_button.setEnabled(False) - palette = self.param_name.palette() - palette.setColor(self.param_name.backgroundRole(), self.INVALID_COLOR) - self.param_name.setToolTip(msg) - self.param_name.setPalette(palette) - - def valid(self): - """Called when the name is valid.""" - self.ok_button.setEnabled(True) - palette = self.param_name.palette() - palette.setColor(self.param_name.backgroundRole(), self.validColor) - self.param_name.setToolTip("") - self.param_name.setPalette(palette) - - def validateName(self, value): - """Called to perform validation of a name. For specific needs override this function and call valid() and notValid(msg).""" - value = str(value) - - if value == "": - self.notValid("Can not be empty!") - elif not value.find(" ") == -1: - self.notValid("No spaces allowed!") - elif value in self.unique_names: - self.notValid("Name must be unique!") - else: - self.valid() - - def validateChoice(self, choice): - """Only called when using selection mode.""" - self.ok_button.setEnabled(not choice == "") - - def getName(self): - """Return the new name chosen by the user""" - if self.choose_from_list: - return str(self.param_name_combo.currentText()) - else: - return str(self.param_name.text()) - - def showAndTell(self): - """Shows the dialog and returns the result""" - if self.exec_(): - return str(self.getName()).strip() - - return "" - - def createSpace(self, size=5): - """Creates a widget that can be used as spacing on a panel.""" - qw = QWidget() - qw.setMinimumSize(QSize(size, size)) - - return qw diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/validationsupport.py b/ThirdParty/Ert/python/python/ert_gui/ertwidgets/validationsupport.py deleted file mode 100644 index dd586a3c75..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/validationsupport.py +++ /dev/null @@ -1,110 +0,0 @@ -from PyQt4.QtCore import Qt, QPoint, QObject, pyqtSignal - -from PyQt4.QtGui import QWidget, QVBoxLayout, QSizePolicy, QFrame, QColor, QLabel - - -class ErrorPopup(QWidget): - error_template = ("" - "" - "" - "%s" - "
Warning:
" - "") - - def __init__(self): - QWidget.__init__(self, None, Qt.ToolTip) - self.resize(300, 50) - - self.setContentsMargins(0, 0, 0, 0) - layout = QVBoxLayout() - layout.setMargin(0) - - self._error_widget = QLabel("") - self._error_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum) - self._error_widget.setFrameStyle(QFrame.Box) - self._error_widget.setWordWrap(True) - self._error_widget.setScaledContents(True) - # self.warning_widget.setAlignment(Qt.AlignHCenter) - self._error_widget.setTextFormat(Qt.RichText) - layout.addWidget(self._error_widget) - - self.setLayout(layout) - - def presentError(self, widget, error): - assert isinstance(widget, QWidget) - - self._error_widget.setText(ErrorPopup.error_template % error) - self.show() - - size_hint = self.sizeHint() - rect = widget.rect() - p = widget.mapToGlobal(QPoint(rect.left(), rect.top())) - - self.setGeometry(p.x(), p.y() - size_hint.height() - 5, size_hint.width(), size_hint.height()) - - self.raise_() - - -class ValidationSupport(QObject): - STRONG_ERROR_COLOR = QColor(255, 215, 215) - ERROR_COLOR = QColor(255, 235, 235) - INVALID_COLOR = QColor(235, 235, 255) - - WARNING = "warning" - EXCLAMATION = "ide/small/exclamation" - - validationChanged = pyqtSignal(bool) - - def __init__(self, validation_target): - """ @type validation_target: QWidget """ - QObject.__init__(self) - - self._validation_target = validation_target - self._validation_message = None - self._validation_type = None - self._error_popup = ErrorPopup() - - self._originalEnterEvent = validation_target.enterEvent - self._originalLeaveEvent = validation_target.leaveEvent - self._originalHideEvent = validation_target.hideEvent - - def enterEvent(event): - self._originalEnterEvent(event) - - if not self.isValid(): - self._error_popup.presentError(self._validation_target, self._validation_message) - - validation_target.enterEvent = enterEvent - - def leaveEvent(event): - self._originalLeaveEvent(event) - - if self._error_popup is not None: - self._error_popup.hide() - - validation_target.leaveEvent = leaveEvent - - def hideEvent(hide_event): - self._error_popup.hide() - self._originalHideEvent(hide_event) - - validation_target.hideEvent = hideEvent - - def setValidationMessage(self, message, validation_type=WARNING): - """Add a warning or information icon to the widget with a tooltip""" - message = message.strip() - if message == "": - self._validation_type = None - self._validation_message = None - self._error_popup.hide() - self.validationChanged.emit(True) - - else: - self._validation_type = validation_type - self._validation_message = message - if self._validation_target.hasFocus() or self._validation_target.underMouse(): - self._error_popup.presentError(self._validation_target, self._validation_message) - self.validationChanged.emit(False) - - def isValid(self): - return self._validation_message is None diff --git a/ThirdParty/Ert/python/python/ert_gui/gert_main.py b/ThirdParty/Ert/python/python/ert_gui/gert_main.py deleted file mode 100644 index d688a8965d..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/gert_main.py +++ /dev/null @@ -1,255 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'gert_main.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -# -------------------------------------------------------------------------------- -# This file is the main script of the ert with graphical UI, e.g. gert or -# ert_gui. To run successfully the ert GUI requires a quite well prepared -# environment. This includes the following: -# -# 1. A Python interpreter with the the ctypes library available. -# -# 2. The program must be able to locate all the required shared libraries with -# no fuss. This includes: -# -# o The ert libraries libecl.so, libenkf.so, libutil.so, librms.so, -# libsched.so, libconfig.so -# -# o The libraries used by the ert libraries, this includes liblapack.so, -# libz.so, libblas.so, libpthread.so and in some cases the libg2c.so -# library. -# -# o The lsf libraries libbat, liblsf and also libnsl. In the current -# implementation the dependance on the lsf libraries is hard, this should -# be relaxed so that the lsf libraries are not linked before an attempt to -# actually use lsf is made. -# When an attempt is actually made to use LSF the additional environment -# variables LSF_LIBDIR, XLSF_UIDDIR, LSF_SERVERDIR, LSF_ENVDIR and -# LSF_BINDIR must also be set. That is an LSF requirement and not -# related to ert as such. These variables can naturally be set from the -# site config file. -# -# -# 3. The program must be able to locate all the necessary Python modules, in -# short this means that the directory containing the ert/ and ert_gui/ -# directories must be on Python path, i.e. the import statements -# -# import ert -# import ert_gui -# -# should just work. -# -# 4. The environment variable GERT_SHARE_PATH should be set to point to the -# /share directory of the current gert installation. The /share directory -# contains html help files and images/icons. -# -# 5. The environment variable ERT_SITE_CONFIG must be set to point to the site -# wide configuration file. -# -# -# Now the important point is that this python script WILL NOT PERFORM ANY -# SPECIAL HOOPS TO TRY TO LOCATE THE REQUIRED FILES, i.e. the environment must -# be fully prepared prior to invoking this script. This will typically involve: -# -# 1. Update the LD_LIBRARY_PATH variable to contain directories with all the -# required shared libraries. -# -# 2. Update the PYTHONPATH variable to contain the directory containg ert/ and -# ert_gui/ directories. -# -# 3. Set the environment variabel GERT_SHARE_PATH to point to the directory -# containg the /share files for the current gert installation. -# -# 4. Set the environment variable ERT_SITE_CONFIG to point to the location of -# the site configuration file. -# -# An example shell script achieving this could look like: -# -# -------------------- -------------------- -# #!/bin/bash -# -# # The LSF libraries are installed in directory /site/LSF/7.0/linux/lib, this -# # directory must be included in the LD_LIBRARY_PATH variable. Furthermore we -# # assume that the ERT libraries like libecl.so and libenkf.so are located in -# # /opt/ert/lib, then LD_LIBRARY_PATH will be updated as: -# -# export LD_LIBRARY_PATH=/site/LSF/7.0/linux/lib:/opt/ert/lib:$LD_LIBRARY_PATH -# -# # The python modules ert and ert_gui are located in /opt/ert/python, so we -# # update PYTHONPATH as: -# -# export PYTHONPATH=/opt/ert/python:$PYTHONPATH -# -# # The shared gert files are installed in /opt/ert/share; this directory can -# # in principle be shared among gert versions built for different operating -# # system versions: -# -# export ERT_SHARE_PATH=/opt/ert/share -# -# # The ERT site configuration file is assumed to be in -# # /opt/ert/etc/site-config, i.e. we set the variable ERT_SITE_CONFIG as: -# -# export ERT_SITE_CONFIG=/opt/ert/etc/site-config -# -# # Now the environment should be fully initialized, and we are ready to invoke -# # the gert_main.py script, i.e. this file: -# -# exec python /opt/ert/python/ert_gui/gert_main.py $@ -# -# -------------------- -------------------- - -import os -import sys -import time - -from PyQt4.QtCore import Qt -from PyQt4.QtGui import QApplication, QFileDialog - -import ert_gui.ertwidgets -from ert.enkf import EnKFMain -from ert.util import Version -from ert_gui.ert_splash import ErtSplash -from ert_gui.ertwidgets import SummaryPanel, resourceIcon -from ert_gui.main_window import GertMainWindow -from ert_gui.simulation.simulation_panel import SimulationPanel -from ert_gui.tools import HelpCenter -from ert_gui.tools.export import ExportTool -from ert_gui.tools.help import HelpTool -from ert_gui.tools.ide import IdeTool -from ert_gui.tools.load_results import LoadResultsTool -from ert_gui.tools.manage_cases import ManageCasesTool -from ert_gui.tools.plot import PlotTool -from ert_gui.tools.plugins import PluginHandler, PluginsTool -from ert_gui.tools.run_analysis import RunAnalysisTool -from ert_gui.tools.workflows import WorkflowsTool - -if os.getenv("ERT_SHARE_PATH"): - ert_share_path = os.getenv("ERT_SHARE_PATH") -else: - # If the ERT_SHARE_PATH variable is not set we try to use the - # source location relative to the location of the current file; - # assuming we are in the source directory. Will not work if we are - # in an arbitrary build directory. - ert_share_path = os.path.realpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../../share")) - -ert_gui.ertwidgets.img_prefix = ert_share_path + "/gui/img/" - -from ert_gui.newconfig import NewConfigurationDialog - - -def main(argv): - app = QApplication(argv) # Early so that QT is initialized before other imports - app.setWindowIcon(resourceIcon("application/window_icon_cutout")) - - if len(argv) == 1: - config_file = QFileDialog.getOpenFileName(None, "Open Configuration File") - - config_file = str(config_file) - - if len(config_file) == 0: - print("-----------------------------------------------------------------") - print("-- You must supply the name of configuration file as the first --") - print("-- commandline argument: --") - print("-- --") - print("-- bash% gert --") - print("-- --") - print("-- If the configuration file does not exist, gert will create --") - print("-- create a new configuration file. --") - print("-----------------------------------------------------------------") - - sys.exit(1) - else: - config_file = argv[1] - - help_center = HelpCenter("ERT") - help_center.setHelpLinkPrefix(os.getenv("ERT_SHARE_PATH") + "/gui/help/") - help_center.setHelpMessageLink("welcome_to_ert") - - strict = True - - verbose = False - verbose_var = os.getenv("ERT_VERBOSE", "False") - lower_verbose_var = verbose_var.lower() - if lower_verbose_var == "true": - verbose = True - - if not os.path.exists(config_file): - print("Trying to start new config") - new_configuration_dialog = NewConfigurationDialog(config_file) - success = new_configuration_dialog.exec_() - if not success: - print("Can not run without a configuration file.") - sys.exit(1) - else: - config_file = new_configuration_dialog.getConfigurationPath() - dbase_type = new_configuration_dialog.getDBaseType() - num_realizations = new_configuration_dialog.getNumberOfRealizations() - storage_path = new_configuration_dialog.getStoragePath() - - EnKFMain.createNewConfig(config_file, storage_path, dbase_type, num_realizations) - strict = False - - if os.path.isdir(config_file): - print("The specified configuration file is a directory!") - sys.exit(1) - - splash = ErtSplash() - splash.version = "Version %s" % Version.getVersion() - splash.timestamp = Version.getBuildTime() - - splash.show() - splash.repaint() - - now = time.time() - - ert = EnKFMain(config_file, strict=strict, verbose=verbose) - ert_gui.configureErtNotifier(ert, config_file) - - window = GertMainWindow() - window.setWidget(SimulationPanel()) - - plugin_handler = PluginHandler(ert, ert.getWorkflowList().getPluginJobs(), window) - - help_tool = HelpTool("ERT", window) - - window.addDock("Configuration Summary", SummaryPanel(), area=Qt.BottomDockWidgetArea) - window.addTool(IdeTool(os.path.basename(config_file), help_tool)) - window.addTool(PlotTool()) - window.addTool(ExportTool()) - window.addTool(WorkflowsTool()) - window.addTool(ManageCasesTool()) - window.addTool(PluginsTool(plugin_handler)) - window.addTool(RunAnalysisTool()) - window.addTool(LoadResultsTool()) - window.addTool(help_tool) - - sleep_time = 2 - (time.time() - now) - - if sleep_time > 0: - time.sleep(sleep_time) - - window.show() - splash.finish(window) - window.activateWindow() - window.raise_() - finished_code = app.exec_() - - ert.free() - - sys.exit(finished_code) - - -if __name__ == "__main__": - main(sys.argv) diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/ide/CMakeLists.txt deleted file mode 100644 index d0813f8eb8..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - highlighter.py - keyword.py - parameter.py -) - -add_python_package("python.ert_gui.ide" ${PYTHON_INSTALL_PREFIX}/ert_gui/ide "${PYTHON_SOURCES}" True) - -add_subdirectory(completers) -add_subdirectory(keywords) -add_subdirectory(wizards) diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/completers/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/ide/completers/CMakeLists.txt deleted file mode 100644 index 5d773c0064..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/completers/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - path_completer.py -) - -add_python_package("python.ert_gui.ide.completers" ${PYTHON_INSTALL_PREFIX}/ert_gui/ide/completers "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/completers/path_completer.py b/ThirdParty/Ert/python/python/ert_gui/ide/completers/path_completer.py deleted file mode 100644 index e38efce4b9..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/completers/path_completer.py +++ /dev/null @@ -1,71 +0,0 @@ -import os - - -class PathItem(object): - def __init__(self, value): - super(PathItem, self).__init__() - #: :type: str - self.value = value - - - def __str__(self): - return self.value - - def __gt__(self, other): - assert isinstance(other, PathItem) - - if self.value.endswith("/") and not other.value.endswith("/"): - return True - elif not self.value.endswith("/") and other.value.endswith("/"): - return False - else: - return self.value.lower() > other.value.lower() - - def __eq__(self, other): - return self.value == other.value - - def __lt__(self, other): - return not (self == other or self > other) - - def __le__(self, other): - return self == other or not self > other - - def __ge__(self, other): - return self == other or self > other - - - -class PathCompleter(object): - def __init__(self): - super(PathCompleter, self).__init__() - - - def completeOptions(self, path_prefix): - - root, entry_prefix = os.path.split(path_prefix) - - if os.path.isdir(root): - if not root.startswith("/"): - root_path = "./%s/" % root - else: - root_path = "%s/" % root - else: - if root == "": - root_path = "./" - else: - root_path = root - - entries = os.listdir(root_path) - - - result = [] - for entry in entries: - if entry.startswith(entry_prefix): - full_path = os.path.join(root, entry) - if os.path.isdir(full_path): - full_path += "/" - result.append(PathItem(full_path)) - - - result = sorted(result) - return [str(item) for item in result] diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/highlighter.py b/ThirdParty/Ert/python/python/ert_gui/ide/highlighter.py deleted file mode 100644 index 24f0064c66..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/highlighter.py +++ /dev/null @@ -1,105 +0,0 @@ -import re -from PyQt4.QtGui import QSyntaxHighlighter, QTextCharFormat, QColor, QTextBlockUserData - -from ert_gui.ide.keywords import ErtKeywords -from ert_gui.ide.keywords.configuration_line_builder import ConfigurationLineBuilder -from ert_gui.ide.keywords.data import Keyword - - -class ConfigurationLineUserData(QTextBlockUserData): - def __init__(self, configuration_line): - QTextBlockUserData.__init__(self) - self.configuration_line = configuration_line - -class KeywordHighlighter(QSyntaxHighlighter): - def __init__(self, document): - QSyntaxHighlighter.__init__(self, document) - - self.clb = ConfigurationLineBuilder(ErtKeywords()) - - - self.comment_format = QTextCharFormat() - self.comment_format.setForeground(QColor(0, 128, 0)) - self.comment_format.setFontItalic(True) - - self.keyword_format = QTextCharFormat() - self.keyword_format.setForeground(QColor(200, 100, 0)) - # self.keyword_format.setFontWeight(QFont.Bold) - - self.error_format = QTextCharFormat() - # self.error_format.setForeground(QColor(255, 0, 0)) - self.error_format.setUnderlineStyle(QTextCharFormat.WaveUnderline) - self.error_format.setUnderlineColor(QColor(255, 0, 0)) - - self.search_format = QTextCharFormat() - self.search_format.setBackground(QColor(220, 220, 220)) - - self.builtin_format = QTextCharFormat() - self.builtin_format.setForeground(QColor(0, 170, 227)) - - self.search_string = "" - - - def formatKeyword(self, keyword, validation_status): - assert isinstance(keyword, Keyword) - if keyword.hasKeywordDefinition(): - keyword_format = QTextCharFormat(self.keyword_format) - - if not validation_status: - keyword_format.merge(self.error_format) - - self.formatToken(keyword, keyword_format) - else: - self.formatToken(keyword, self.error_format) - - - def highlightBlock(self, complete_block): - block = unicode(complete_block) - - self.clb.processLine(block) - - - if self.clb.hasComment(): - self.setFormat(self.clb.commentIndex(), len(block) - self.clb.commentIndex(), self.comment_format) - - if not self.clb.hasConfigurationLine(): - count = len(block) - - if self.clb.hasComment(): - count = self.clb.commentIndex() - - self.setFormat(0, count, self.error_format) - - - if self.clb.hasConfigurationLine(): - cl = self.clb.configurationLine() - self.setCurrentBlockUserData(ConfigurationLineUserData(cl)) - - self.formatKeyword(cl.keyword(), cl.validationStatusForToken(cl.keyword())) - - arguments = cl.arguments() - - for argument in arguments: - if not argument.hasArgumentDefinition(): - pass - - elif argument.argumentDefinition().isBuiltIn(): - self.formatToken(argument, self.builtin_format) - - if not cl.validationStatusForToken(argument): - self.formatToken(argument, self.error_format) - - - if self.search_string != "": - for match in re.finditer("(%s)" % self.search_string, complete_block): - self.setFormat(match.start(1), match.end(1) - match.start(1), self.search_format) - - - def setSearchString(self, string): - if self.search_string != unicode(string): - self.search_string = unicode(string) - self.rehighlight() - - - def formatToken(self, token, highlight_format): - self.setFormat(token.fromIndex(), token.count(), highlight_format) \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keyword.py b/ThirdParty/Ert/python/python/ert_gui/ide/keyword.py deleted file mode 100644 index ec234f2028..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keyword.py +++ /dev/null @@ -1,96 +0,0 @@ -from ert_gui.ide.parameter import Parameter - - -class Keyword(object): - def __init__(self, keyword, start, end): - super(Keyword, self).__init__() - #: :type: str - self.keyword = keyword - #: :type: int - self.start = start - #: :type: int - self.end = end - #: :type: list of Parameter - self.parameter_list = [] - #: :type: bool - self.error = False - #: :type: str - self.error_message = "" - - self.handler = None - - - @property - def length(self): - return self.end - self.start - - def addParameter(self, value, start, end): - self.parameter_list.append(Parameter(value, start, end)) - - def parameterCount(self): - return len(self.parameter_list) - - def parameters(self): - """ @rtype: list of Parameter """ - return self.parameter_list - - def __getitem__(self, item): - """ @rtype: Parameter """ - assert isinstance(item, int) - return self.parameter_list[item] - - def hasError(self): - """ @rtype: bool """ - parameter_error = False - - for param in self.parameter_list: - if param.error: - parameter_error = True - - return self.error or parameter_error - - - - def mergeParameters(self, from_parameter): - parameters = self.parameter_list[from_parameter:] - self.parameter_list = self.parameter_list[0:from_parameter - 1] - - value = " ".join([p.value for p in parameters]) - start = parameters[0].start - end = parameters[len(parameters) - 1].end - - self.parameter_list.append(Parameter(value, start, end)) - - def errorMessage(self): - errors = [] - - if self.error: - errors.append(self.error_message) - - for parameter in self.parameter_list: - if parameter.error: - errors.append(parameter.error_message) - - return "\n".join(errors) - - def parameterIndexForPosition(self, position_in_block): - index = 0 - - if position_in_block <= self.end: - return -1 - - for parameter in self.parameter_list: - if parameter.start <= position_in_block <= parameter.end: - return index - index += 1 - - if self.parameterCount() > 0: - if position_in_block < self.parameter_list[0].start: - return 0 - elif position_in_block > self.parameter_list[self.parameterCount() - 1].end: - return self.parameterCount() - - if self.parameterCount() == 0: - return 0 - - return -1 \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/CMakeLists.txt deleted file mode 100644 index 99afed7609..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - analysis_module_keywords.py - configuration_line_builder.py - configuration_line_parser.py - eclipse_keywords.py - enkf_control_keywords.py - ensemble_keywords.py - ert_keywords.py - parametrization_keywords.py - plot_keywords.py - queue_system_keywords.py - run_keywords.py - simulation_control_keywords.py - workflow_keywords.py - qc_keywords.py - unix_environment_keywords.py - advanced_keywords.py -) - -add_python_package("python.ert_gui.ide.keywords" ${PYTHON_INSTALL_PREFIX}/ert_gui/ide/keywords "${PYTHON_SOURCES}" True) - -add_subdirectory(data) -add_subdirectory(definitions) diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/__init__.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/__init__.py deleted file mode 100644 index c355513387..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .configuration_line_parser import ConfigurationLineParser -from .ert_keywords import ErtKeywords diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/advanced_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/advanced_keywords.py deleted file mode 100644 index 676ede7415..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/advanced_keywords.py +++ /dev/null @@ -1,56 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, KeywordDefinition, ConfigurationLineDefinition, PathArgument, StringArgument -from ert_gui.ide.keywords.definitions.proper_name_argument import ProperNameArgument - - -class AdvancedKeywords(object): - def __init__(self, ert_keywords): - super(AdvancedKeywords, self).__init__() - self.group = "Advanced" - - ert_keywords.addKeyword(self.addDefine()) - ert_keywords.addKeyword(self.addSchedulePredictionFile()) - ert_keywords.addKeyword(self.addFixedLengthScheduleKw()) - ert_keywords.addKeyword(self.addStaticKw()) - - - - def addFixedLengthScheduleKw(self): - fixed_length_sched_kw = ConfigurationLineDefinition(keyword=KeywordDefinition("ADD_FIXED_LENGTH_SCHEDULE_KW"), - arguments=[StringArgument(), - StringArgument()], - documentation_link="keywords/add_fixed_length_schedule_kw", - required=False, - group=self.group) - return fixed_length_sched_kw - - - def addStaticKw(self): - add_static_kw = ConfigurationLineDefinition(keyword=KeywordDefinition("ADD_STATIC_KW"), - arguments=[StringArgument(), - StringArgument()], - documentation_link="keywords/add_static_kw", - required=False, - group=self.group) - return add_static_kw - - - - def addDefine(self): - define = ConfigurationLineDefinition(keyword=KeywordDefinition("DEFINE"), - arguments=[ProperNameArgument(), - StringArgument(rest_of_line=True,allow_space=True)], - documentation_link="keywords/define", - required=False, - group=self.group) - return define - - - - def addSchedulePredictionFile(self): - schedule_prediction_file = ConfigurationLineDefinition(keyword=KeywordDefinition("SCHEDULE_PREDICTION_FILE"), - arguments=[PathArgument()], - documentation_link="keywords/schedule_prediction_file", - required=False, - group=self.group) - return schedule_prediction_file - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/analysis_module_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/analysis_module_keywords.py deleted file mode 100644 index 604e59801a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/analysis_module_keywords.py +++ /dev/null @@ -1,106 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, KeywordDefinition, ConfigurationLineDefinition, PathArgument, StringArgument, FloatArgument, BoolArgument -from ert_gui.ide.keywords.definitions.proper_name_format_argument import ProperNameFormatArgument - - -class AnalysisModuleKeywords(object): - def __init__(self, ert_keywords): - super(AnalysisModuleKeywords, self).__init__() - self.group = "Analysis Module" - - ert_keywords.addKeyword(self.addAnalysisLoad()) - ert_keywords.addKeyword(self.addAnalysisSelect()) - ert_keywords.addKeyword(self.addAnalysisCopy()) - ert_keywords.addKeyword(self.addAnalysisSetVar()) - ert_keywords.addKeyword(self.addIterCase()) - ert_keywords.addKeyword(self.addIterCount()) - ert_keywords.addKeyword(self.addStdCutoff()) - ert_keywords.addKeyword(self.addSingleNodeUpdate()) - ert_keywords.addKeyword(self.addIterRetryCount()) - - - - def addAnalysisLoad(self): - analysis_load = ConfigurationLineDefinition(keyword=KeywordDefinition("ANALYSIS_LOAD"), - arguments=[StringArgument(),StringArgument()], - documentation_link="keywords/analysis_load", - required=False, - group=self.group) - return analysis_load - - - - def addAnalysisSelect(self): - analysis_select = ConfigurationLineDefinition(keyword=KeywordDefinition("ANALYSIS_SELECT"), - arguments=[StringArgument()], - documentation_link="keywords/analysis_select", - required=False, - group=self.group) - return analysis_select - - - def addAnalysisSetVar(self): - analysis_set_var = ConfigurationLineDefinition(keyword=KeywordDefinition("ANALYSIS_SET_VAR"), - arguments=[StringArgument(), - StringArgument(), - StringArgument(rest_of_line=True,allow_space=True)], - documentation_link="keywords/analysis_set_var", - required=False, - group=self.group) - return analysis_set_var - - - - def addAnalysisCopy(self): - analysis_copy = ConfigurationLineDefinition(keyword=KeywordDefinition("ANALYSIS_COPY"), - arguments=[StringArgument(), StringArgument()], - documentation_link="keywords/analysis_copy", - required=False, - group=self.group) - return analysis_copy - - - - - def addIterCase(self): - iter_case = ConfigurationLineDefinition(keyword=KeywordDefinition("ITER_CASE"), - arguments=[ProperNameFormatArgument()], - documentation_link="keywords/iter_case", - required=False, - group=self.group) - return iter_case - - - def addIterCount(self): - iter_count = ConfigurationLineDefinition(keyword=KeywordDefinition("ITER_COUNT"), - arguments=[IntegerArgument()], - documentation_link="keywords/iter_count", - required=False, - group=self.group) - return iter_count - - - def addIterRetryCount(self): - retry_count = ConfigurationLineDefinition(keyword=KeywordDefinition("ITER_RETRY_COUNT"), - arguments=[IntegerArgument()], - documentation_link="keywords/iter_retry_count", - required=False, - group=self.group) - return retry_count - - - def addStdCutoff(self): - std_cutoff = ConfigurationLineDefinition(keyword=KeywordDefinition("STD_CUTOFF"), - arguments=[FloatArgument()], - documentation_link="keywords/std_cutoff", - required=False, - group=self.group) - return std_cutoff - - - def addSingleNodeUpdate(self): - single_node_update = ConfigurationLineDefinition(keyword=KeywordDefinition("SINGLE_NODE_UPDATE"), - arguments=[BoolArgument()], - documentation_link="keywords/single_node_update", - required=False, - group=self.group) - return single_node_update \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/configuration_line_builder.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/configuration_line_builder.py deleted file mode 100644 index cc2766463c..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/configuration_line_builder.py +++ /dev/null @@ -1,110 +0,0 @@ -from ert_gui.ide.keywords import ErtKeywords -from ert_gui.ide.keywords.configuration_line_parser import ConfigurationLineParser -from ert_gui.ide.keywords.data import ConfigurationLine, Argument, Keyword - - -class ConfigurationLineBuilder(object): - DEFAULT_GROUP = "Unknown keyword" - DEFAULT_DOCUMENTATION_LINK = "unknown_keyword" - - def __init__(self, keywords): - super(ConfigurationLineBuilder, self).__init__() - - assert isinstance(keywords, ErtKeywords) - self.__keywords = keywords - self.__configuration_line_parser = ConfigurationLineParser() - self.__configuration_line = None - - - def processLine(self, line): - self.__configuration_line_parser.parseLine(line) - self.__configuration_line = None - - if self.__configuration_line_parser.hasKeyword(): - keyword = self.__configuration_line_parser.keyword() - arguments = self.__configuration_line_parser.arguments() - - documentation_link = ConfigurationLineBuilder.DEFAULT_DOCUMENTATION_LINK - group = ConfigurationLineBuilder.DEFAULT_GROUP - required = False - - if keyword.value() in self.__keywords: - configuration_line_definition = self.__keywords[keyword.value()] - - documentation_link = configuration_line_definition.documentationLink() - group = configuration_line_definition.group() - required = configuration_line_definition.isRequired() - - keyword.setKeywordDefinition(configuration_line_definition.keywordDefinition()) - - arguments = self.__matchArguments(keyword, configuration_line_definition.argumentDefinitions(), arguments) - - - self.__configuration_line = ConfigurationLine(keyword, arguments, documentation_link, group, required) - - def configurationLine(self): - """ @rtype: ConfigurationLine """ - return self.__configuration_line - - def hasConfigurationLine(self): - """ @rtype: bool """ - return self.__configuration_line is not None - - def hasComment(self): - """ @rtype: bool """ - return self.__configuration_line_parser.hasComment() - - def commentIndex(self): - return self.__configuration_line_parser.commentIndex() - - - def __matchArguments(self, keyword, arg_defs, args): - """ - @type keyword: Keyword - @type arg_defs: list of ArgumentDefinition - @type args: list of Argument - @rtype: list of Argument - """ - arg_def_count = len(arg_defs) - arg_count = len(args) - - if arg_count > arg_def_count: - # merge last input arguments - - last_arg_def = arg_defs[len(arg_defs) - 1] - - if last_arg_def.consumeRestOfLine(): - from_arg = args[arg_def_count - 1] - to_arg = args[arg_count - 1] - - last_argument = Argument(from_arg.fromIndex(), to_arg.toIndex(), keyword.line()) - args = args[0:arg_def_count] - args[len(args) - 1] = last_argument - - else: - from_arg = args[arg_def_count] - to_arg = args[arg_count - 1] - - last_argument = Argument(from_arg.fromIndex(), to_arg.toIndex(), keyword.line()) - args = args[0:arg_def_count] - args.append(last_argument) - - if arg_count < arg_def_count: - # pad with empty arguments - line = keyword.line() - - for index in range(arg_def_count - arg_count): - empty_argument = Argument(len(line), len(line), line) - args.append(empty_argument) - - - for index in range(len(args)): - if index < len(arg_defs): - args[index].setArgumentDefinition(arg_defs[index]) - - - return args - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/configuration_line_parser.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/configuration_line_parser.py deleted file mode 100644 index abcc270e20..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/configuration_line_parser.py +++ /dev/null @@ -1,80 +0,0 @@ -import re -from ert_gui.ide.keywords.data import Argument, Keyword - - -class ConfigurationLineParser(object): - COMMENT_PATTERN = re.compile(".*?(--.*)") - KEYWORD_PATTERN = re.compile("^\s*([A-Z_]+)(\s|--)?") - ARGUMENT_PATTERN = re.compile('\s+?(\S+)\s*?') - - def __init__(self): - super(ConfigurationLineParser, self).__init__() - - self.__comment_index = -1 - self.__keyword = None - self.__text = None - self.__arguments_index = -1 - self.__arguments = [] - - - def parseLine(self, line): - self.__keyword = None - self.__comment_index = -1 - self.__text = line - self.__arguments_index = -1 - self.__arguments = [] - - comment_match = re.match(ConfigurationLineParser.COMMENT_PATTERN, line) - if comment_match is not None: - self.__comment_index = comment_match.start(1) - line = line[0:comment_match.start(1)] - - keyword_match = re.match(ConfigurationLineParser.KEYWORD_PATTERN, line) - if keyword_match is not None: - self.__keyword = Keyword(keyword_match.start(1), keyword_match.end(1), line) - self.__arguments_index = keyword_match.end(1) - - if self.hasKeyword(): - argument_match = ConfigurationLineParser.ARGUMENT_PATTERN.finditer(line) - - for match in argument_match: - self.__arguments.append(Argument(match.start(1), match.end(1), line)) - - - def hasComment(self): - """ @rtype: bool """ - return self.__comment_index >= 0 - - def commentIndex(self): - """ @rtype: str """ - return self.__comment_index - - def hasKeyword(self): - """ @rtype: bool """ - return self.__keyword is not None - - def keyword(self): - """ @rtype: Keyword """ - return self.__keyword - - def text(self): - """ @rtype: str """ - return self.__text - - def uncommentedText(self): - """ @rtype: str """ - if self.hasComment(): - return self.__text[0:self.commentIndex()] - return self.text() - - def argumentsText(self): - """ @rtype: str """ - if self.hasKeyword(): - return self.uncommentedText()[self.__arguments_index:] - return "" - - def arguments(self): - """ @rtype: list of Argument """ - return self.__arguments - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/CMakeLists.txt deleted file mode 100644 index 2e90451487..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - argument.py - configuration_line.py - keyword.py - token.py - validation_status.py -) - -add_python_package("python.ert_gui.ide.keywords.data" ${PYTHON_INSTALL_PREFIX}/ert_gui/ide/keywords/data "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/__init__.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/__init__.py deleted file mode 100644 index 9421556f0a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from .validation_status import ValidationStatus - -from .token import Token -from .argument import Argument -from .keyword import Keyword - -from .configuration_line import ConfigurationLine diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/argument.py deleted file mode 100644 index 74b18a0231..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/argument.py +++ /dev/null @@ -1,27 +0,0 @@ -from ert_gui.ide.keywords.data import Token - - -class Argument(Token): - def __init__(self, from_index, to_index, line): - super(Argument, self).__init__(from_index, to_index, line) - self.__argument_definition = None - - - def setArgumentDefinition(self, argument_definition): - self.__argument_definition = argument_definition - - def argumentDefinition(self): - """ @rtype: ArgumentDefinition """ - return self.__argument_definition - - def hasArgumentDefinition(self): - """ @rtype: bool """ - return self.__argument_definition is not None - - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/configuration_line.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/configuration_line.py deleted file mode 100644 index bd77df285b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/configuration_line.py +++ /dev/null @@ -1,89 +0,0 @@ -from ert_gui.ide.keywords.data import Argument, Keyword, ValidationStatus -from ert_gui.ide.keywords.definitions import ArgumentDefinition, KeywordDefinition - - -class ConfigurationLine(object): - ARGUMENT_NOT_EXPECTED = "Argument not expected!" - ARGUMENT_ERROR = "Keyword has an argument error!" - UNKNOWN_KEYWORD = "Unknown keyword!" - - def __init__(self, keyword, arguments, documentation_link, group, required=False): - """ - @type keyword: Keyword - @type arguments: list of Argument - @type documentation_link: str - @type group: str - @type required: bool - """ - super(ConfigurationLine, self).__init__() - - self.__keyword = keyword - self.__arguments = arguments - self.__documentation_link = documentation_link - self.__required = required - self.__group = group - self.__validation_status = {} - - self.__validateTokens() - - - def __validateTokens(self): - keyword_validation_status = ValidationStatus() - - if not self.__keyword.hasKeywordDefinition(): - keyword_validation_status.setFailed() - keyword_validation_status.addToMessage(ConfigurationLine.UNKNOWN_KEYWORD) - - self.__validation_status[self.__keyword] = keyword_validation_status - - argument_error = False - for argument in self.__arguments: - argument_validation_status = ValidationStatus() - - if not argument.hasArgumentDefinition(): - argument_validation_status.setFailed() - argument_validation_status.addToMessage(ConfigurationLine.ARGUMENT_NOT_EXPECTED) - - argument_error = True - else: - arg_def = argument.argumentDefinition() - argument_validation_status = arg_def.validate(argument.value()) - - if not argument_validation_status: - argument_error = True - - self.__validation_status[argument] = argument_validation_status - - if argument_error: - keyword_validation_status.setFailed() - keyword_validation_status.addToMessage(ConfigurationLine.ARGUMENT_ERROR) - - for argument in self.__arguments: - argument_validation_status = self.validationStatusForToken(argument) - if not argument_validation_status: - keyword_validation_status.addToMessage(argument_validation_status.message()) - - - def keyword(self): - """ @rtype: Keyword""" - return self.__keyword - - def arguments(self): - """ @rtype: list of Argument """ - return self.__arguments - - def isRequired(self): - """ @rtype: bool """ - return self.__required - - def documentationLink(self): - """ @rtype: str """ - return self.__documentation_link - - def group(self): - """ @rtype: str """ - return self.__group - - def validationStatusForToken(self, token): - """ @rtype: ValidationStatus """ - return self.__validation_status[token] diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/keyword.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/keyword.py deleted file mode 100644 index 00ff0c79c2..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/keyword.py +++ /dev/null @@ -1,19 +0,0 @@ -from ert_gui.ide.keywords.data import Token -from ert_gui.ide.keywords.definitions import KeywordDefinition - - -class Keyword(Token): - def __init__(self, from_index, to_index, line): - super(Keyword, self).__init__(from_index, to_index, line) - - self.__keyword_definition = None - - def keywordDefinition(self): - """ @rtype: KeywordDefinition """ - return self.__keyword_definition - - def setKeywordDefinition(self, keyword_definition): - self.__keyword_definition = keyword_definition - - def hasKeywordDefinition(self): - return self.__keyword_definition is not None \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/token.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/token.py deleted file mode 100644 index a762100101..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/token.py +++ /dev/null @@ -1,36 +0,0 @@ -class Token(object): - - def __init__(self, from_index, to_index, line): - super(Token, self).__init__() - - self.__from_index = from_index - self.__to_index = to_index - self.__line = line - - def value(self): - """ @rtype: str """ - return self.__line[self.__from_index:self.__to_index] - - def fromIndex(self): - """ @rtype: int """ - return self.__from_index - - def toIndex(self): - """ @rtype: int """ - return self.__to_index - - def line(self): - """ @rtype: str """ - return self.__line - - def count(self): - """ @rtype: int """ - return self.toIndex() - self.fromIndex() - - def __contains__(self, item): - assert isinstance(item, int) - - return self.__from_index <= item < self.__to_index - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/validation_status.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/validation_status.py deleted file mode 100644 index ee949edc56..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/data/validation_status.py +++ /dev/null @@ -1,35 +0,0 @@ -class ValidationStatus(object): - def __init__(self): - super(ValidationStatus, self).__init__() - self.reset() - - def reset(self): - self.__fail = False - self.__message = "" - self.__value = None - - def setFailed(self): - self.__fail = True - - def failed(self): - return self.__fail - - def addToMessage(self, message): - self.__message += message + "\n" - - def message(self): - return self.__message.strip() - - def setValue(self, value): - self.__value = value - - def value(self): - return self.__value - - def __nonzero__(self): - return not self.__fail - - def __str__(self): - return self.__message - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/CMakeLists.txt deleted file mode 100644 index e95326ab5b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - argument_definition.py - bool_argument.py - configuration_line_definition.py - float_argument.py - integer_argument.py - keyword_definition.py - number_list_string_argument.py - path_argument.py - percent_argument.py - proper_name_argument.py - proper_name_format_argument.py - proper_name_format_string_argument.py - range_string_argument.py - string_argument.py -) - -add_python_package("python.ert_gui.ide.keywords.definitions" ${PYTHON_INSTALL_PREFIX}/ert_gui/ide/keywords/definitions "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/__init__.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/__init__.py deleted file mode 100644 index aac0683937..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -from .argument_definition import ArgumentDefinition -from .integer_argument import IntegerArgument -from .percent_argument import PercentArgument -from .string_argument import StringArgument -from .bool_argument import BoolArgument -from .float_argument import FloatArgument -from .path_argument import PathArgument -from .proper_name_argument import ProperNameArgument -from .proper_name_format_argument import ProperNameFormatArgument -from .proper_name_format_string_argument import ProperNameFormatStringArgument -from .range_string_argument import RangeStringArgument -from .number_list_string_argument import NumberListStringArgument - -from .argument_definition import ArgumentDefinition -from .keyword_definition import KeywordDefinition -from .configuration_line_definition import ConfigurationLineDefinition diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/argument_definition.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/argument_definition.py deleted file mode 100644 index 6d10bb5a09..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/argument_definition.py +++ /dev/null @@ -1,30 +0,0 @@ -from ert_gui.ide.keywords.data import ValidationStatus - -class ArgumentDefinition(object): - MISSING_ARGUMENT = "Missing argument!" - - def __init__(self, optional=False, built_in=False, rest_of_line=False): - super(ArgumentDefinition, self).__init__() - self.__optional = optional - self.__built_in = built_in - self.__rest_of_line = rest_of_line - - def isOptional(self): - return self.__optional - - def isBuiltIn(self): - return self.__built_in - - def consumeRestOfLine(self): - return self.__rest_of_line - - - def validate(self, token): - vs = ValidationStatus() - - if not self.isOptional() and token.strip() == "": - vs.setFailed() - vs.addToMessage(ArgumentDefinition.MISSING_ARGUMENT) - - return vs - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/bool_argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/bool_argument.py deleted file mode 100644 index 85c736295a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/bool_argument.py +++ /dev/null @@ -1,36 +0,0 @@ - -import re -from ert_gui.ide.keywords.definitions import ArgumentDefinition - - -class BoolArgument(ArgumentDefinition): - - NOT_BOOL = "The argument must be TRUE or FALSE." - - true_pattern = re.compile("^(1|T|[Tt][Rr][Uu][Ee])$") - false_pattern = re.compile("^(0|F|[Ff][Aa][Ll][Ss][Ee])$") - - def __init__(self, **kwargs): - super(BoolArgument, self).__init__(**kwargs) - - - def validate(self, token): - validation_status = super(BoolArgument, self).validate(token) - - true_match = BoolArgument.true_pattern.match(token) - false_match = BoolArgument.false_pattern.match(token) - - if true_match is None and false_match is None: - validation_status.setFailed() - validation_status.addToMessage(BoolArgument.NOT_BOOL) - else: - validation_status.setValue(true_match is not None) - - return validation_status - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/configuration_line_definition.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/configuration_line_definition.py deleted file mode 100644 index d1837c58e5..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/configuration_line_definition.py +++ /dev/null @@ -1,32 +0,0 @@ -from ert_gui.ide.keywords.definitions import KeywordDefinition, ArgumentDefinition - - -class ConfigurationLineDefinition(object): - def __init__(self, keyword, arguments, documentation_link, group, required=False): - super(ConfigurationLineDefinition, self).__init__() - - self.__keyword_definition = keyword - self.__argument_definitions = arguments - self.__documentation_link = documentation_link - self.__required = required - self.__group = group - - def isRequired(self): - """ @rtype: bool """ - return self.__required - - def keywordDefinition(self): - """ @rtype: KeywordDefinition """ - return self.__keyword_definition - - def argumentDefinitions(self): - """ @rtype: list of ArgumentDefinition """ - return self.__argument_definitions - - def documentationLink(self): - """ @rtype: str """ - return self.__documentation_link - - def group(self): - """ @rtype: str """ - return self.__group \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/float_argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/float_argument.py deleted file mode 100644 index d289dbb9c2..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/float_argument.py +++ /dev/null @@ -1,59 +0,0 @@ -import re -from ert_gui.ide.keywords.definitions import ArgumentDefinition - - -class FloatArgument(ArgumentDefinition): - - NOT_FLOAT = "The argument must be a float." - NOT_IN_RANGE = "The argument is not in range: %s" - - pattern = re.compile("^[\S]+$") - - def __init__(self, from_value=None, to_value=None, **kwargs): - super(FloatArgument, self).__init__(**kwargs) - self.from_value = from_value - self.to_value = to_value - - - def validate(self, token): - validation_status = super(FloatArgument, self).validate(token) - - match = FloatArgument.pattern.match(token) - - if match is None: - validation_status.setFailed() - validation_status.addToMessage(FloatArgument.NOT_FLOAT) - else: - try: - value = float(token) - - if self.from_value is not None and self.to_value is not None and not self.from_value <= value <= self.to_value: - validation_status.setFailed() - range_string = "%f <= %f <= %f" % (self.from_value, value, self.to_value) - validation_status.addToMessage(FloatArgument.NOT_IN_RANGE % range_string) - - elif self.from_value is not None and self.from_value > value: - validation_status.setFailed() - range_string = "%f <= %f" % (self.from_value, value) - validation_status.addToMessage(FloatArgument.NOT_IN_RANGE % range_string) - - elif self.to_value is not None and self.to_value < value: - validation_status.setFailed() - range_string = "%f <= %f" % (value, self.to_value) - validation_status.addToMessage(FloatArgument.NOT_IN_RANGE % range_string) - - if not validation_status.failed(): - validation_status.setValue(value) - - except ValueError: - validation_status.setFailed() - validation_status.addToMessage(FloatArgument.NOT_FLOAT) - - return validation_status - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/integer_argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/integer_argument.py deleted file mode 100644 index e6b57531f6..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/integer_argument.py +++ /dev/null @@ -1,56 +0,0 @@ -import re -from ert_gui.ide.keywords.definitions import ArgumentDefinition - - -class IntegerArgument(ArgumentDefinition): - - NOT_INTEGER = "The argument must be an integer." - NOT_IN_RANGE = "The argument is not in range: %s" - - pattern = re.compile("^-?[0-9]+$") - - def __init__(self, from_value=None, to_value=None, **kwargs): - super(IntegerArgument, self).__init__(**kwargs) - self.from_value = from_value - self.to_value = to_value - - - def validate(self, token): - validation_status = super(IntegerArgument, self).validate(token) - - match = IntegerArgument.pattern.match(token) - - if match is None: - validation_status.setFailed() - validation_status.addToMessage(IntegerArgument.NOT_INTEGER) - else: - value = int(token) - - if self.from_value is not None and self.to_value is not None and not self.from_value <= value <= self.to_value: - validation_status.setFailed() - range_string = "%d <= %d <= %d" % (self.from_value, value, self.to_value) - validation_status.addToMessage(IntegerArgument.NOT_IN_RANGE % range_string) - - elif self.from_value is not None and self.from_value > value: - validation_status.setFailed() - range_string = "%d <= %d" % (self.from_value, value) - validation_status.addToMessage(IntegerArgument.NOT_IN_RANGE % range_string) - - elif self.to_value is not None and self.to_value < value: - validation_status.setFailed() - range_string = "%d <= %d" % (value, self.to_value) - validation_status.addToMessage(IntegerArgument.NOT_IN_RANGE % range_string) - - - if not validation_status.failed(): - validation_status.setValue(value) - - - return validation_status - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/keyword_definition.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/keyword_definition.py deleted file mode 100644 index 24456505e6..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/keyword_definition.py +++ /dev/null @@ -1,9 +0,0 @@ -class KeywordDefinition(object): - - def __init__(self, name): - super(KeywordDefinition, self).__init__() - self.__name = name - - def name(self): - return self.__name - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/number_list_string_argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/number_list_string_argument.py deleted file mode 100644 index 6f5d245fda..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/number_list_string_argument.py +++ /dev/null @@ -1,43 +0,0 @@ -import re -from ert_gui.ide.keywords.definitions import ArgumentDefinition - - -class NumberListStringArgument(ArgumentDefinition): - - NOT_A_VALID_NUMBER_LIST_STRING = "The input should be of the type:
\n\t23,5.5,11,1.01,3\n
i.e. numeric values separated by commas." - VALUE_NOT_A_NUMBER = "The value: '%s' is not a number." - - PATTERN = re.compile("^[0-9\.\-+, \t]+$") - - def __init__(self, **kwargs): - super(NumberListStringArgument, self).__init__(**kwargs) - - def validate(self, token): - validation_status = super(NumberListStringArgument, self).validate(token) - - if not validation_status: - return validation_status - else: - match = NumberListStringArgument.PATTERN.match(token) - - if match is None: - validation_status.setFailed() - validation_status.addToMessage(NumberListStringArgument.NOT_A_VALID_NUMBER_LIST_STRING) - else: - - groups = token.split(",") - - for group in groups: - group = group.strip() - - if len(group) > 0: - try: - num = float(group.strip()) - except ValueError: - validation_status.setFailed() - validation_status.addToMessage(NumberListStringArgument.VALUE_NOT_A_NUMBER % group) - - - validation_status.setValue(token) - - return validation_status diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/path_argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/path_argument.py deleted file mode 100644 index b604fd42ef..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/path_argument.py +++ /dev/null @@ -1,50 +0,0 @@ -import os -import re -from ert_gui.ide.keywords.definitions import ArgumentDefinition - - -class PathArgument(ArgumentDefinition): - - NOT_A_VALID_PATH = "The argument must be a valid path." - PATH_DOES_NOT_EXIST = "The argument must be a valid path that exists." - - PATTERN = re.compile("^[\S]+$") - PATTERN_WITH_SPACE = re.compile("^[\S| ]+$") - - DEFINES = {} - - def __init__(self, must_exist=True, **kwargs): - super(PathArgument, self).__init__(**kwargs) - self.__must_exist = must_exist - - if not "" in PathArgument.DEFINES: - PathArgument.DEFINES[""] = "." - - - def validate(self, token): - validation_status = super(PathArgument, self).validate(token) - - token = PathArgument.substituteDefines(token) - - if self.__must_exist and not os.path.exists(token): - validation_status.setFailed() - validation_status.addToMessage(PathArgument.PATH_DOES_NOT_EXIST) - - return validation_status - - @staticmethod - def substituteDefines(token): - result = token - for key in PathArgument.DEFINES: - if result.find(key) != -1: - value = PathArgument.DEFINES[key] - result = result.replace(key, value) - return result - - @staticmethod - def addDefine(key, value): - value = PathArgument.substituteDefines(value) - PathArgument.DEFINES[key] = value - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/percent_argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/percent_argument.py deleted file mode 100644 index 9f329971cb..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/percent_argument.py +++ /dev/null @@ -1,56 +0,0 @@ -import re -from ert_gui.ide.keywords.definitions import ArgumentDefinition - - -class PercentArgument(ArgumentDefinition): - - NOT_PERCENT = "The argument must be a number followed by % - no space allowed." - NOT_IN_RANGE = "The argument is not in range: %s" - - pattern = re.compile("^-?[0-9]+(\.[0-9]+)?\%$") - - def __init__(self, from_value=None, to_value=None, **kwargs): - super(PercentArgument, self).__init__(**kwargs) - self.from_value = from_value * 0.01 - self.to_value = to_value * 0.01 - - - def validate(self, token): - validation_status = super(PercentArgument, self).validate(token) - - match = PercentArgument.pattern.match(token) - - if match is None: - validation_status.setFailed() - validation_status.addToMessage(PercentArgument.NOT_PERCENT) - else: - value = float(token[:-1]) * 0.01 - - if self.from_value is not None and self.to_value is not None and not self.from_value <= value <= self.to_value: - validation_status.setFailed() - range_string = "%d <= %d <= %d" % (self.from_value, value, self.to_value) - validation_status.addToMessage(IntegerArgument.NOT_IN_RANGE % range_string) - - elif self.from_value is not None and self.from_value > value: - validation_status.setFailed() - range_string = "%d <= %d" % (self.from_value, value) - validation_status.addToMessage(IntegerArgument.NOT_IN_RANGE % range_string) - - elif self.to_value is not None and self.to_value < value: - validation_status.setFailed() - range_string = "%d <= %d" % (value, self.to_value) - validation_status.addToMessage(IntegerArgument.NOT_IN_RANGE % range_string) - - - if not validation_status.failed(): - validation_status.setValue(value) - - - return validation_status - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_argument.py deleted file mode 100644 index 2eed9cc809..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_argument.py +++ /dev/null @@ -1,48 +0,0 @@ -import re -from ert_gui.ide.keywords.definitions import ArgumentDefinition - - -class ProperNameArgument(ArgumentDefinition): - - NOT_A_VALID_NAME = "The argument must be a valid string containing only characters of these types:" \ - "
    " \ - "
  • Letters: A-Z and a-z
  • " \ - "
  • Numbers: 0-9
  • " \ - "
  • Underscore: _
  • " \ - "
  • Dash:
  • " \ - "
  • Period: .
  • " \ - "
  • Brackets: <>
  • " \ - "
" - - - PATTERN = re.compile("^[A-Za-z0-9_\-.<>]+$") - - - def __init__(self, **kwargs): - super(ProperNameArgument, self).__init__(**kwargs) - - - def validate(self, token): - validation_status = super(ProperNameArgument, self).validate(token) - - if not validation_status: - return validation_status - else: - match = ProperNameArgument.PATTERN.match(token) - - if match is None: - validation_status.setFailed() - validation_status.addToMessage(ProperNameArgument.NOT_A_VALID_NAME) - else: - - if not validation_status.failed(): - validation_status.setValue(token) - - return validation_status - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_format_argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_format_argument.py deleted file mode 100644 index ec5f59b721..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_format_argument.py +++ /dev/null @@ -1,48 +0,0 @@ -import re -from ert_gui.ide.keywords.definitions import ArgumentDefinition - - -class ProperNameFormatArgument(ArgumentDefinition): - - NOT_A_VALID_NAME_FORMAT = "The argument must be a valid string containing a %d and only characters of these types:" \ - "
    " \ - "
  • Letters: A-Z and a-z
  • " \ - "
  • Numbers: 0-9
  • " \ - "
  • Underscore: _
  • " \ - "
  • Dash:
  • " \ - "
  • Period: .
  • " \ - "
  • Brackets: <>
  • " \ - "
" - - - PATTERN = re.compile("^[A-Za-z0-9_\-.<>]*(%d)[A-Za-z0-9_\-.<>]*$") - - - def __init__(self, **kwargs): - super(ProperNameFormatArgument, self).__init__(**kwargs) - - - def validate(self, token): - validation_status = super(ProperNameFormatArgument, self).validate(token) - - if not validation_status: - return validation_status - else: - match = ProperNameFormatArgument.PATTERN.match(token) - - if match is None: - validation_status.setFailed() - validation_status.addToMessage(ProperNameFormatArgument.NOT_A_VALID_NAME_FORMAT) - else: - - if not validation_status.failed(): - validation_status.setValue(token) - - return validation_status - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_format_string_argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_format_string_argument.py deleted file mode 100644 index 4eabbcd971..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/proper_name_format_string_argument.py +++ /dev/null @@ -1,45 +0,0 @@ -import re -from ert_gui.ide.keywords.definitions import ArgumentDefinition - - -''' -Keyword definition for proper names containing a string argument. -''' -class ProperNameFormatStringArgument(ArgumentDefinition): - - NOT_A_VALID_NAME_FORMAT = "The argument must be a valid string containing a %s and only characters of these types:" \ - "
    " \ - "
  • Letters: A-Z and a-z
  • " \ - "
  • Numbers: 0-9
  • " \ - "
  • Underscore: _
  • " \ - "
  • Dash:
  • " \ - "
  • Period: .
  • " \ - "
  • Brackets: <>
  • " \ - "
" - - - PATTERN = re.compile("^[A-Za-z0-9_\-.<>]*(%s)[A-Za-z0-9_\-.<>]*$") - - - def __init__(self, **kwargs): - super(ProperNameFormatStringArgument, self).__init__(**kwargs) - - - def validate(self, token): - validation_status = super(ProperNameFormatStringArgument, self).validate(token) - - if not validation_status: - return validation_status - else: - match = ProperNameFormatStringArgument.PATTERN.match(token) - - if match is None: - validation_status.setFailed() - validation_status.addToMessage(ProperNameFormatStringArgument.NOT_A_VALID_NAME_FORMAT) - else: - - if not validation_status.failed(): - validation_status.setValue(token) - - return validation_status - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/range_string_argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/range_string_argument.py deleted file mode 100644 index 8fca2fde08..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/range_string_argument.py +++ /dev/null @@ -1,71 +0,0 @@ -import re -from ert_gui.ide.keywords.definitions import ArgumentDefinition - - -class RangeStringArgument(ArgumentDefinition): - - NOT_A_VALID_RANGE_STRING = "The input should be of the type:
\n\t1,3-5,9,17\n
i.e. integer values separated by commas, and dashes to represent ranges." - VALUE_NOT_IN_RANGE = "A value must be in the range from 0 to %d." - - - PATTERN = re.compile("^[0-9\-, \t]+$") - RANGE_PATTERN = re.compile("^[ \t]*([0-9]+)[ \t]*-[ \t]*([0-9]+)[ \t]*$") - NUMBER_PATTERN = re.compile("^[ \t]*([0-9]+)[ \t]*$") - - - def __init__(self, max_value=None, **kwargs): - super(RangeStringArgument, self).__init__(**kwargs) - self.__max_value = max_value - - def validate(self, token): - validation_status = super(RangeStringArgument, self).validate(token) - - if not validation_status: - return validation_status - else: - match = RangeStringArgument.PATTERN.match(token) - - if match is None: - validation_status.setFailed() - validation_status.addToMessage(RangeStringArgument.NOT_A_VALID_RANGE_STRING) - else: - - groups = token.split(",") - - for group in groups: - range_match = RangeStringArgument.RANGE_PATTERN.match(group) - number_match = RangeStringArgument.NUMBER_PATTERN.match(group) - - - if range_match is None and number_match is None: - validation_status.setFailed() - validation_status.addToMessage(RangeStringArgument.NOT_A_VALID_RANGE_STRING) - break - - if range_match: - num_1 = int(range_match.group(1)) - num_2 = int(range_match.group(2)) - - if not num_2 > num_1: - validation_status.setFailed() - validation_status.addToMessage(RangeStringArgument.NOT_A_VALID_RANGE_STRING) - break - - if self.__max_value is not None and (num_1 >= self.__max_value or num_2 >= self.__max_value): - validation_status.setFailed() - validation_status.addToMessage(RangeStringArgument.VALUE_NOT_IN_RANGE % (self.__max_value - 1)) - break - - if number_match and self.__max_value is not None: - num = int(number_match.group(1)) - - if num >= self.__max_value: - validation_status.setFailed() - validation_status.addToMessage(RangeStringArgument.VALUE_NOT_IN_RANGE % (self.__max_value - 1)) - break - - - - validation_status.setValue(token) - - return validation_status diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/string_argument.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/string_argument.py deleted file mode 100644 index 760d26f018..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/definitions/string_argument.py +++ /dev/null @@ -1,47 +0,0 @@ -import re -from ert_gui.ide.keywords.definitions import ArgumentDefinition - - -class StringArgument(ArgumentDefinition): - - NOT_A_VALID_STRING = "The argument must be a valid string." - - PATTERN = re.compile("^[\S]+$") - PATTERN_WITH_SPACE = re.compile("^[\S| ]+$") - - - def __init__(self, allow_space=False, **kwargs): - super(StringArgument, self).__init__(**kwargs) - self.__allow_space = allow_space - - - def validate(self, token): - validation_status = super(StringArgument, self).validate(token) - - if not validation_status: - return validation_status - elif self.isOptional() and token.strip() == "": - return validation_status - else: - if self.__allow_space: - match = StringArgument.PATTERN_WITH_SPACE.match(token) - else: - match = StringArgument.PATTERN.match(token) - - if match is None: - validation_status.setFailed() - validation_status.addToMessage(StringArgument.NOT_A_VALID_STRING) - else: - - if not validation_status.failed(): - validation_status.setValue(token) - - - return validation_status - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/eclipse_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/eclipse_keywords.py deleted file mode 100644 index 2386e78271..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/eclipse_keywords.py +++ /dev/null @@ -1,101 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, KeywordDefinition, ConfigurationLineDefinition, StringArgument, BoolArgument -from ert_gui.ide.keywords.definitions.path_argument import PathArgument - - -class EclipseKeywords(object): - def __init__(self, ert_keywords): - super(EclipseKeywords, self).__init__() - self.group = "Eclipse" - - - ert_keywords.addKeyword(self.addDataFile()) - ert_keywords.addKeyword(self.addEclBase()) - ert_keywords.addKeyword(self.addJobName()) - ert_keywords.addKeyword(self.addGrid()) - ert_keywords.addKeyword(self.addInitSection()) - ert_keywords.addKeyword(self.addScheduleFile()) - ert_keywords.addKeyword(self.addDataKw()) - ert_keywords.addKeyword(self.addEquilInitFile()) - ert_keywords.addKeyword(self.addIgnoreSchedule()) - - - - def addDataFile(self): - data_file = ConfigurationLineDefinition(keyword=KeywordDefinition("DATA_FILE"), - arguments=[PathArgument()], - documentation_link="keywords/data_file", - required=True, - group=self.group) - return data_file - - - def addEquilInitFile(self): - equil_init_file = ConfigurationLineDefinition(keyword=KeywordDefinition("EQUIL_INIT_FILE"), - arguments=[PathArgument()], - documentation_link="keywords/equil_init_file", - group=self.group) - return equil_init_file - - - - def addEclBase(self): - ecl_base = ConfigurationLineDefinition(keyword=KeywordDefinition("ECLBASE"), - arguments=[StringArgument()], - documentation_link="keywords/eclbase", - required=True, - group=self.group) - return ecl_base - - - def addJobName(self): - job_name = ConfigurationLineDefinition(keyword=KeywordDefinition("JOBNAME"), - arguments=[StringArgument()], - documentation_link="keywords/job_name", - required=True, - group=self.group) - return job_name - - - def addGrid(self): - grid = ConfigurationLineDefinition(keyword=KeywordDefinition("GRID"), - arguments=[PathArgument()], - documentation_link="keywords/grid", - required=True, - group=self.group) - return grid - - def addInitSection(self): - init_section = ConfigurationLineDefinition(keyword=KeywordDefinition("INIT_SECTION"), - arguments=[PathArgument()], - documentation_link="keywords/init_section", - required=True, - group=self.group) - return init_section - - - def addScheduleFile(self): - schedule_file = ConfigurationLineDefinition(keyword=KeywordDefinition("SCHEDULE_FILE"), - arguments=[PathArgument()], - documentation_link="keywords/schedule_file", - required=True, - group=self.group) - return schedule_file - - - def addIgnoreSchedule(self): - ignore_schedule = ConfigurationLineDefinition(keyword=KeywordDefinition("IGNORE_SCHEDULE"), - arguments=[BoolArgument()], - documentation_link="keywords/ignore_schedule", - required=False, - group=self.group) - return ignore_schedule - - - def addDataKw(self): - data_kw = ConfigurationLineDefinition(keyword=KeywordDefinition("DATA_KW"), - arguments=[StringArgument(), - StringArgument(rest_of_line=True, allow_space=True)], - documentation_link="keywords/data_kw", - required=False, - group=self.group) - return data_kw \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/enkf_control_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/enkf_control_keywords.py deleted file mode 100644 index efad1a52e2..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/enkf_control_keywords.py +++ /dev/null @@ -1,240 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, KeywordDefinition, ConfigurationLineDefinition, PathArgument, StringArgument, FloatArgument, BoolArgument - - -class EnkfControlKeywords(object): - def __init__(self, ert_keywords): - super(EnkfControlKeywords, self).__init__() - self.group = "Enkf Control" - - ert_keywords.addKeyword(self.addEnkfAlpha()) - ert_keywords.addKeyword(self.addEnkfBootstrap()) - ert_keywords.addKeyword(self.addEnkfCvFolds()) - ert_keywords.addKeyword(self.addEnkfForceNComp()) - ert_keywords.addKeyword(self.addEnkfLocalCv()) - ert_keywords.addKeyword(self.addEnkfPenPress()) - ert_keywords.addKeyword(self.addEnkfMode()) - ert_keywords.addKeyword(self.addMergeObservations()) - ert_keywords.addKeyword(self.addEnkfNComp()) - ert_keywords.addKeyword(self.addEnkfRerun()) - ert_keywords.addKeyword(self.addEnkfScaling()) - ert_keywords.addKeyword(self.addEnkfTruncation()) - ert_keywords.addKeyword(self.addUpdateLogPath()) - ert_keywords.addKeyword(self.addRerunStart()) - ert_keywords.addKeyword(self.addUpdateResults()) - ert_keywords.addKeyword(self.addEnkfCrossValidation()) - ert_keywords.addKeyword(self.addEnkfKernelRegression()) - ert_keywords.addKeyword(self.addEnkfKernelFunction()) - ert_keywords.addKeyword(self.addEnkfKernelParam()) - ert_keywords.addKeyword(self.addEnkfSchedFile()) - ert_keywords.addKeyword(self.addCaseTable()) - ert_keywords.addKeyword(self.addContainer()) - - - - def addEnkfAlpha(self): - enkf_alpha = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_ALPHA"), - arguments=[FloatArgument()], - documentation_link="keywords/enkf_alpha", - required=False, - group=self.group) - return enkf_alpha - - - - def addEnkfBootstrap(self): - enkf_bootstrap = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_BOOTSTRAP"), - arguments=[BoolArgument()], - documentation_link="keywords/enkf_bootstrap", - required=False, - group=self.group) - return enkf_bootstrap - - - - def addEnkfCvFolds(self): - enkf_cv_folds = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_CV_FOLDS"), - arguments=[IntegerArgument()], - documentation_link="keywords/enkf_cv_folds", - required=False, - group=self.group) - return enkf_cv_folds - - - - def addEnkfForceNComp(self): - enkf_force_ncomp = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_FORCE_NCOMP"), - arguments=[BoolArgument()], - documentation_link="keywords/enkf_force_ncomp", - required=False, - group=self.group) - return enkf_force_ncomp - - - def addEnkfLocalCv(self): - enkf_local_cv = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_LOCAL_CV"), - arguments=[BoolArgument()], - documentation_link="keywords/enkf_local_cv", - required=False, - group=self.group) - return enkf_local_cv - - - def addEnkfPenPress(self): - enkf_pen_press = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_PEN_PRESS"), - arguments=[BoolArgument()], - documentation_link="keywords/enkf_pen_press", - required=False, - group=self.group) - return enkf_pen_press - - - - def addEnkfMode(self): - enkf_mode = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_MODE"), - arguments=[StringArgument(built_in=True)], - documentation_link="keywords/enkf_mode", - required=False, - group=self.group) - return enkf_mode - - - - def addMergeObservations(self): - enkf_merge_observations = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_MERGE_OBSERVATIONS"), - arguments=[BoolArgument()], - documentation_link="keywords/enkf_merge_observations", - required=False, - group=self.group) - return enkf_merge_observations - - - - def addEnkfNComp(self): - enkf_ncomp = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_NCOMP"), - arguments=[IntegerArgument()], - documentation_link="keywords/enkf_ncomp", - required=False, - group=self.group) - return enkf_ncomp - - - def addEnkfRerun(self): - enkf_rerun = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_RERUN"), - arguments=[BoolArgument()], - documentation_link="keywords/enkf_rerun", - required=False, - group=self.group) - return enkf_rerun - - - def addRerunStart(self): - rerun_start = ConfigurationLineDefinition(keyword=KeywordDefinition("RERUN_START"), - arguments=[IntegerArgument()], - documentation_link="keywords/rerun_start", - required=False, - group=self.group) - return rerun_start - - - - def addEnkfScaling(self): - enkf_scaling = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_SCALING"), - arguments=[BoolArgument()], - documentation_link="keywords/enkf_scaling", - required=False, - group=self.group) - return enkf_scaling - - - - def addEnkfTruncation(self): - enkf_truncation = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_TRUNCATION"), - arguments=[FloatArgument()], - documentation_link="keywords/enkf_truncation", - required=False, - group=self.group) - return enkf_truncation - - - - def addUpdateLogPath(self): - update_log_path = ConfigurationLineDefinition(keyword=KeywordDefinition("UPDATE_LOG_PATH"), - arguments=[PathArgument()], - documentation_link="keywords/update_log_path", - required=False, - group=self.group) - return update_log_path - - - def addUpdateResults(self): - update_results = ConfigurationLineDefinition(keyword=KeywordDefinition("UPDATE_RESULTS"), - arguments=[BoolArgument()], - documentation_link="keywords/update_results", - required=False, - group=self.group) - return update_results - - - def addEnkfCrossValidation(self): - cross_validation = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_CROSS_VALIDATION"), - arguments=[StringArgument()], - documentation_link="keywords/enkf_cross_validation", - required=False, - group=self.group) - return cross_validation - - - def addEnkfKernelRegression(self): - kernel_regression = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_KERNEL_REGRESSION"), - arguments=[StringArgument()], - documentation_link="keywords/enkf_kernel_regression", - required=False, - group=self.group) - return kernel_regression - - - def addEnkfKernelFunction(self): - kernel_function = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_KERNEL_FUNCTION"), - arguments=[StringArgument()], - documentation_link="keywords/enkf_kernel_function", - required=False, - group=self.group) - return kernel_function - - - def addEnkfKernelParam(self): - kernel_param = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_KERNEL_PARAM"), - arguments=[StringArgument()], - documentation_link="keywords/enkf_kernel_param", - required=False, - group=self.group) - return kernel_param - - - def addEnkfSchedFile(self): - sched_file = ConfigurationLineDefinition(keyword=KeywordDefinition("ENKF_SCHED_FILE"), - arguments=[PathArgument()], - documentation_link="keywords/enkf_sched_file", - required=False, - group=self.group) - return sched_file - - - - def addCaseTable(self): - case_table = ConfigurationLineDefinition(keyword=KeywordDefinition("CASE_TABLE"), - arguments=[StringArgument()], - documentation_link="keywords/case_table", - required=False, - group=self.group) - return case_table - - - def addContainer(self): - container = ConfigurationLineDefinition(keyword=KeywordDefinition("CONTAINER"), - arguments=[StringArgument(rest_of_line=True,allow_space=True)], - documentation_link="keywords/container", - required=False, - group=self.group) - return container - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/ensemble_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/ensemble_keywords.py deleted file mode 100644 index f85e3dbfa2..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/ensemble_keywords.py +++ /dev/null @@ -1,135 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, KeywordDefinition, ConfigurationLineDefinition, PathArgument, StringArgument - - -class EnsembleKeywords(object): - def __init__(self, ert_keywords): - super(EnsembleKeywords, self).__init__() - self.group = "Ensemble" - - ert_keywords.addKeyword(self.addNumRealizations()) - ert_keywords.addKeyword(self.addEnsPath()) - ert_keywords.addKeyword(self.addSelectCase()) - ert_keywords.addKeyword(self.addEndDate()) - ert_keywords.addKeyword(self.addHistorySource()) - ert_keywords.addKeyword(self.addRefCase()) - ert_keywords.addKeyword(self.addInclude()) - ert_keywords.addKeyword(self.addObsConfig()) - ert_keywords.addKeyword(self.addResultPath()) - ert_keywords.addKeyword(self.addLicensePath()) - ert_keywords.addKeyword(self.addLocalConfig()) - ert_keywords.addKeyword(self.addRefcaseList()) - - - - - - def addNumRealizations(self): - num_realizations = ConfigurationLineDefinition(keyword=KeywordDefinition("NUM_REALIZATIONS"), - arguments=[IntegerArgument(from_value=1)], - documentation_link="keywords/num_realizations", - required=True, - group=self.group) - return num_realizations - - - def addEndDate(self): - end_date = ConfigurationLineDefinition(keyword=KeywordDefinition("END_DATE"), - arguments=[StringArgument()], - documentation_link="keywords/end_date", - required=False, - group=self.group) - return end_date - - - def addEnsPath(self): - ens_path = ConfigurationLineDefinition(keyword=KeywordDefinition("ENSPATH"), - arguments=[PathArgument()], - documentation_link="keywords/enspath", - required=False, - group=self.group) - return ens_path - - - - def addSelectCase(self): - select_case = ConfigurationLineDefinition(keyword=KeywordDefinition("SELECT_CASE"), - arguments=[StringArgument()], - documentation_link="keywords/select_case", - required=False, - group=self.group) - return select_case - - - def addHistorySource(self): - history_source = ConfigurationLineDefinition(keyword=KeywordDefinition("HISTORY_SOURCE"), - arguments=[StringArgument(built_in=True)], - documentation_link="keywords/history_source", - required=False, - group=self.group) - return history_source - - - def addRefCase(self): - refcase = ConfigurationLineDefinition(keyword=KeywordDefinition("REFCASE"), - arguments=[PathArgument()], - documentation_link="keywords/refcase", - required=False, - group=self.group) - return refcase - - - def addRefcaseList(self): - refcase_list = ConfigurationLineDefinition(keyword=KeywordDefinition("REFCASE_LIST"), - arguments=[StringArgument(rest_of_line=True,allow_space=True)], - documentation_link="keywords/refcase_list", - required=False, - group=self.group) - return refcase_list - - - - def addInclude(self): - include = ConfigurationLineDefinition(keyword=KeywordDefinition("INCLUDE"), - arguments=[PathArgument()], - documentation_link="keywords/include", - required=False, - group=self.group) - return include - - - - def addObsConfig(self): - obs_config = ConfigurationLineDefinition(keyword=KeywordDefinition("OBS_CONFIG"), - arguments=[PathArgument()], - documentation_link="keywords/obs_config", - required=False, - group=self.group) - return obs_config - - - def addResultPath(self): - result_path = ConfigurationLineDefinition(keyword=KeywordDefinition("RESULT_PATH"), - arguments=[PathArgument()], - documentation_link="keywords/result_path", - required=False, - group=self.group) - return result_path - - - def addLicensePath(self): - license_path = ConfigurationLineDefinition(keyword=KeywordDefinition("LICENSE_PATH"), - arguments=[PathArgument()], - documentation_link="keywords/license_path", - required=False, - group=self.group) - return license_path - - - def addLocalConfig(self): - local_config = ConfigurationLineDefinition(keyword=KeywordDefinition("LOCAL_CONFIG"), - arguments=[StringArgument(rest_of_line=True,allow_space=True)], - documentation_link="keywords/local_config", - required=False, - group=self.group) - return local_config - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/ert_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/ert_keywords.py deleted file mode 100644 index 572604add8..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/ert_keywords.py +++ /dev/null @@ -1,73 +0,0 @@ -from ert_gui.ide.keywords.advanced_keywords import AdvancedKeywords -from ert_gui.ide.keywords.analysis_module_keywords import AnalysisModuleKeywords -from ert_gui.ide.keywords.definitions import ConfigurationLineDefinition -from ert_gui.ide.keywords.eclipse_keywords import EclipseKeywords -from ert_gui.ide.keywords.enkf_control_keywords import EnkfControlKeywords -from ert_gui.ide.keywords.ensemble_keywords import EnsembleKeywords -from ert_gui.ide.keywords.parametrization_keywords import ParametrizationKeywords -from ert_gui.ide.keywords.plot_keywords import PlotKeywords -from ert_gui.ide.keywords.qc_keywords import QCKeywords -from ert_gui.ide.keywords.queue_system_keywords import QueueSystemKeywords -from ert_gui.ide.keywords.run_keywords import RunKeywords -from ert_gui.ide.keywords.simulation_control_keywords import SimulationControlKeywords -from ert_gui.ide.keywords.unix_environment_keywords import UnixEnvironmentKeywords -from ert_gui.ide.keywords.workflow_keywords import WorkflowKeywords - - -class ErtKeywords(object): - def __init__(self): - super(ErtKeywords, self).__init__() - - self.keywords = {} - self.groups = {} - - EnsembleKeywords(self) - RunKeywords(self) - EclipseKeywords(self) - QueueSystemKeywords(self) - SimulationControlKeywords(self) - ParametrizationKeywords(self) - EnkfControlKeywords(self) - AnalysisModuleKeywords(self) - PlotKeywords(self) - WorkflowKeywords(self) - AdvancedKeywords(self) - QCKeywords(self) - UnixEnvironmentKeywords(self) - - - # group_names = sorted(self.groups.keys()) - # - # for group in group_names: - # print(group) - # keywords = self.groups[group] - # for keyword in keywords: - # print(" %s" % keyword.keywordDefinition().name()) - - - - - - def addKeyword(self, keyword): - assert isinstance(keyword, ConfigurationLineDefinition) - - name = keyword.keywordDefinition().name() - if name in self.keywords: - raise ValueError("Keyword %s already in Ert keyword list!" % name) - - self.keywords[name] = keyword - - group = keyword.group() - - if not group in self.groups: - self.groups[group] = [] - - self.groups[group].append(keyword) - - def __contains__(self, item): - return item in self.keywords - - def __getitem__(self, item): - """ @rtype: ConfigurationLineDefinition """ - return self.keywords[item] - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/parametrization_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/parametrization_keywords.py deleted file mode 100644 index baac76ee3c..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/parametrization_keywords.py +++ /dev/null @@ -1,128 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, KeywordDefinition, ConfigurationLineDefinition, PathArgument, StringArgument - - -class ParametrizationKeywords(object): - def __init__(self, ert_keywords): - super(ParametrizationKeywords, self).__init__() - self.group = "Parametrization" - - ert_keywords.addKeyword(self.addField()) - ert_keywords.addKeyword(self.addGenData()) - ert_keywords.addKeyword(self.addGenKw()) - ert_keywords.addKeyword(self.addSummary()) - ert_keywords.addKeyword(self.addGenParam()) - ert_keywords.addKeyword(self.addDBaseType()) - ert_keywords.addKeyword(self.addStoreSeed()) - ert_keywords.addKeyword(self.addLoadSeed()) - ert_keywords.addKeyword(self.addGenKwTagFormat()) - ert_keywords.addKeyword(self.addSurface()) - ert_keywords.addKeyword(self.addGenKwExportFile()) - - - - - def addField(self): - field = ConfigurationLineDefinition(keyword=KeywordDefinition("FIELD"), - arguments=[StringArgument(), - StringArgument(), - StringArgument(rest_of_line=True, allow_space=True)], - documentation_link="keywords/field", - required=False, - group=self.group) - return field - - - - def addGenData(self): - gen_data = ConfigurationLineDefinition(keyword=KeywordDefinition("GEN_DATA"), - arguments=[StringArgument(), - StringArgument(), - StringArgument(rest_of_line=True, allow_space=True)], - documentation_link="keywords/gen_data", - required=False, - group=self.group) - return gen_data - - - def addGenKw(self): - gen_kw = ConfigurationLineDefinition(keyword=KeywordDefinition("GEN_KW"), - arguments=[StringArgument(), - StringArgument(), - StringArgument(rest_of_line=True,allow_space=True)], - documentation_link="keywords/gen_kw", - required=False, - group=self.group) - return gen_kw - - - def addGenKwExportFile(self): - gen_kw_export_file = ConfigurationLineDefinition(keyword=KeywordDefinition("GEN_KW_EXPORT_FILE"), - arguments=[StringArgument()], - documentation_link="keywords/gen_kw_export_file", - required=False, - group=self.group) - return gen_kw_export_file - - - def addGenKwTagFormat(self): - gen_kw_tag_format = ConfigurationLineDefinition(keyword=KeywordDefinition("GEN_KW_TAG_FORMAT"), - arguments=[StringArgument(built_in=True,allow_space=True)], - documentation_link="keywords/gen_kw_tag_format", - required=False, - group=self.group) - return gen_kw_tag_format - - - def addGenParam(self): - gen_param = ConfigurationLineDefinition(keyword=KeywordDefinition("GEN_PARAM"), - arguments=[StringArgument(), - StringArgument(), - StringArgument(built_in=True,allow_space=True)], - documentation_link="keywords/gen_param", - required=False, - group=self.group) - return gen_param - - - def addSummary(self): - summary = ConfigurationLineDefinition(keyword=KeywordDefinition("SUMMARY"), - arguments=[StringArgument(rest_of_line=True,allow_space=True)], - documentation_link="keywords/summary", - required=False, - group=self.group) - return summary - - def addDBaseType(self): - dbase_type = ConfigurationLineDefinition(keyword=KeywordDefinition("DBASE_TYPE"), - arguments=[StringArgument()], - documentation_link="keywords/dbase_type", - required=False, - group=self.group) - return dbase_type - - - def addStoreSeed(self): - store_seed = ConfigurationLineDefinition(keyword=KeywordDefinition("STORE_SEED"), - arguments=[StringArgument(built_in=True)], - documentation_link="keywords/store_seed", - required=False, - group=self.group) - return store_seed - - - def addLoadSeed(self): - load_seed = ConfigurationLineDefinition(keyword=KeywordDefinition("LOAD_SEED"), - arguments=[StringArgument(built_in=True)], - documentation_link="keywords/load_seed", - required=False, - group=self.group) - return load_seed - - - def addSurface(self): - surface = ConfigurationLineDefinition(keyword=KeywordDefinition("SURFACE"), - arguments=[StringArgument(rest_of_line=True,allow_space=True)], - documentation_link="keywords/surface", - required=False, - group=self.group) - return surface \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/plot_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/plot_keywords.py deleted file mode 100644 index b4a70291db..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/plot_keywords.py +++ /dev/null @@ -1,135 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, KeywordDefinition, ConfigurationLineDefinition, PathArgument, StringArgument, BoolArgument - - -class PlotKeywords(object): - def __init__(self, ert_keywords): - super(PlotKeywords, self).__init__() - self.group = "Plot" - - ert_keywords.addKeyword(self.addImageViewer()) - ert_keywords.addKeyword(self.addImageType()) - ert_keywords.addKeyword(self.addPlotDriver()) - ert_keywords.addKeyword(self.addPlotErrorbar()) - ert_keywords.addKeyword(self.addPlotErrorbarMax()) - ert_keywords.addKeyword(self.addPlotWidth()) - ert_keywords.addKeyword(self.addPlotHeight()) - ert_keywords.addKeyword(self.addPlotRefcase()) - ert_keywords.addKeyword(self.addPlotRefcaseList()) - ert_keywords.addKeyword(self.addPlotPath()) - ert_keywords.addKeyword(self.addRftConfig()) - ert_keywords.addKeyword(self.addRftPath()) - - - - def addImageViewer(self): - image_viewer = ConfigurationLineDefinition(keyword=KeywordDefinition("IMAGE_VIEWER"), - arguments=[PathArgument()], - documentation_link="keywords/image_viewer", - required=False, - group=self.group) - return image_viewer - - - def addImageType(self): - image_type = ConfigurationLineDefinition(keyword=KeywordDefinition("IMAGE_TYPE"), - arguments=[StringArgument(built_in=True)], - documentation_link="keywords/image_type", - required=False, - group=self.group) - return image_type - - - def addPlotDriver(self): - plot_driver = ConfigurationLineDefinition(keyword=KeywordDefinition("PLOT_DRIVER"), - arguments=[StringArgument(built_in=True)], - documentation_link="keywords/plot_driver", - required=False, - group=self.group) - return plot_driver - - - def addPlotErrorbar(self): - plot_errorbar = ConfigurationLineDefinition(keyword=KeywordDefinition("PLOT_ERRORBAR"), - arguments=[BoolArgument()], - documentation_link="keywords/plot_errorbar", - required=False, - group=self.group) - return plot_errorbar - - - - def addPlotErrorbarMax(self): - plot_errorbar_max = ConfigurationLineDefinition(keyword=KeywordDefinition("PLOT_ERRORBAR_MAX"), - arguments=[IntegerArgument()], - documentation_link="keywords/plot_errorbar_max", - required=False, - group=self.group) - return plot_errorbar_max - - - - def addPlotWidth(self): - plot_width = ConfigurationLineDefinition(keyword=KeywordDefinition("PLOT_WIDTH"), - arguments=[IntegerArgument()], - documentation_link="keywords/plot_width", - required=False, - group=self.group) - return plot_width - - - def addPlotHeight(self): - plot_height = ConfigurationLineDefinition(keyword=KeywordDefinition("PLOT_HEIGHT"), - arguments=[IntegerArgument()], - documentation_link="keywords/plot_height", - required=False, - group=self.group) - return plot_height - - - - def addPlotRefcase(self): - plot_refcase = ConfigurationLineDefinition(keyword=KeywordDefinition("PLOT_REFCASE"), - arguments=[BoolArgument()], - documentation_link="keywords/plot_refcase", - required=False, - group=self.group) - return plot_refcase - - - - def addPlotRefcaseList(self): - plot_refcase_list = ConfigurationLineDefinition(keyword=KeywordDefinition("PLOT_REFCASE_LIST"), - arguments=[StringArgument(rest_of_line=True,allow_space=True)], - documentation_link="keywords/plot_refcase_list", - required=False, - group=self.group) - return plot_refcase_list - - - def addPlotPath(self): - plot_path = ConfigurationLineDefinition(keyword=KeywordDefinition("PLOT_PATH"), - arguments=[PathArgument(must_exist=False)], - documentation_link="keywords/plot_path", - required=False, - group=self.group) - return plot_path - - - - def addRftConfig(self): - rft_config = ConfigurationLineDefinition(keyword=KeywordDefinition("RFT_CONFIG"), - arguments=[PathArgument()], - documentation_link="keywords/rft_config", - required=False, - group=self.group) - return rft_config - - - def addRftPath(self): - rft_path = ConfigurationLineDefinition(keyword=KeywordDefinition("RFTPATH"), - arguments=[PathArgument()], - documentation_link="keywords/rftpath", - required=False, - group=self.group) - return rft_path - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/qc_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/qc_keywords.py deleted file mode 100644 index 8838c35185..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/qc_keywords.py +++ /dev/null @@ -1,31 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, KeywordDefinition, ConfigurationLineDefinition, PathArgument, StringArgument - - -class QCKeywords(object): - def __init__(self, ert_keywords): - super(QCKeywords, self).__init__() - self.group = "Quality Check" - - ert_keywords.addKeyword(self.addQCWorkflow()) - ert_keywords.addKeyword(self.addQCPath()) - - - - - def addQCWorkflow(self): - qc_workflow = ConfigurationLineDefinition(keyword=KeywordDefinition("QC_WORKFLOW"), - arguments=[StringArgument()], - documentation_link="keywords/qc_workflow", - required=False, - group=self.group) - return qc_workflow - - - - def addQCPath(self): - qc_path = ConfigurationLineDefinition(keyword=KeywordDefinition("QC_PATH"), - arguments=[PathArgument()], - documentation_link="keywords/qc_path", - required=False, - group=self.group) - return qc_path \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/queue_system_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/queue_system_keywords.py deleted file mode 100644 index 7158b12127..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/queue_system_keywords.py +++ /dev/null @@ -1,128 +0,0 @@ -from ert_gui.ide.keywords.definitions import StringArgument, KeywordDefinition, IntegerArgument, PathArgument -from ert_gui.ide.keywords.definitions.configuration_line_definition import ConfigurationLineDefinition - - -class QueueSystemKeywords(object): - - - def __init__(self, ert_keywords): - super(QueueSystemKeywords, self).__init__() - self.group = "Queue System" - - ert_keywords.addKeyword(self.addQueueOption()) - ert_keywords.addKeyword(self.addQueueSystem()) - ert_keywords.addKeyword(self.addLsfServer()) - ert_keywords.addKeyword(self.addLsfQueue()) - ert_keywords.addKeyword(self.addMaxRunningLsf()) - ert_keywords.addKeyword(self.addTorqueQueue()) - ert_keywords.addKeyword(self.addMaxRunningLocal()) - ert_keywords.addKeyword(self.addRshHost()) - ert_keywords.addKeyword(self.addRshCommand()) - ert_keywords.addKeyword(self.addMaxRunningRsh()) - ert_keywords.addKeyword(self.addHostType()) - ert_keywords.addKeyword(self.addLsfResources()) - - - - def addQueueOption(self): - queue_option = ConfigurationLineDefinition(keyword = KeywordDefinition("QUEUE_OPTION"), - arguments=[ - StringArgument(built_in=True), - StringArgument(built_in=True), - StringArgument(allow_space=True, rest_of_line=True) - ], - documentation_link="keywords/queue_option", - group=self.group) - - return queue_option - - - - def addQueueSystem(self): - queue_system = ConfigurationLineDefinition(keyword = KeywordDefinition("QUEUE_SYSTEM"), - arguments=[StringArgument(built_in=True)], - documentation_link="keywords/queue_system", - group=self.group) - return queue_system - - - def addLsfServer(self): - lsf_server = ConfigurationLineDefinition(keyword = KeywordDefinition("LSF_SERVER"), - arguments=[StringArgument(built_in=True)], - documentation_link="keywords/lsf_server", - group=self.group) - return lsf_server - - - - def addLsfQueue(self): - lsf_queue = ConfigurationLineDefinition(keyword = KeywordDefinition("LSF_QUEUE"), - arguments=[StringArgument()], - documentation_link="keywords/lsf_queue", - group=self.group) - return lsf_queue - - - def addMaxRunningLsf(self): - max_running_lsf = ConfigurationLineDefinition(keyword = KeywordDefinition("MAX_RUNNING_LSF"), - arguments=[IntegerArgument(from_value=1)], - documentation_link="keywords/max_running_lsf", - group=self.group) - return max_running_lsf - - - def addLsfResources(self): - lsf_resources = ConfigurationLineDefinition(keyword = KeywordDefinition("LSF_RESOURCES"), - arguments=[StringArgument(rest_of_line=True,allow_space=True)], - documentation_link="keywords/lsf_resources", - group=self.group) - return lsf_resources - - - def addTorqueQueue(self): - torque_queue = ConfigurationLineDefinition(keyword = KeywordDefinition("TORQUE_QUEUE"), - arguments=[StringArgument()], - documentation_link="keywords/torque_queue", - group=self.group) - return torque_queue - - - def addMaxRunningLocal(self): - max_running_local = ConfigurationLineDefinition(keyword = KeywordDefinition("MAX_RUNNING_LOCAL"), - arguments=[IntegerArgument(from_value=1)], - documentation_link="keywords/max_running_local", - group=self.group) - return max_running_local - - - def addRshHost(self): - rsh_host = ConfigurationLineDefinition(keyword = KeywordDefinition("RSH_HOST"), - arguments=[StringArgument(), StringArgument(rest_of_line=True, allow_space=True)], - documentation_link="keywords/rsh_host", - group=self.group) - return rsh_host - - - def addRshCommand(self): - rsh_command = ConfigurationLineDefinition(keyword = KeywordDefinition("RSH_COMMAND"), - arguments=[PathArgument()], - documentation_link="keywords/rsh_command", - group=self.group) - return rsh_command - - - def addMaxRunningRsh(self): - max_running_rsh = ConfigurationLineDefinition(keyword = KeywordDefinition("MAX_RUNNING_RSH"), - arguments=[IntegerArgument()], - documentation_link="keywords/max_running_rsh", - group=self.group) - return max_running_rsh - - - - def addHostType(self): - host_type = ConfigurationLineDefinition(keyword = KeywordDefinition("HOST_TYPE"), - arguments=[StringArgument(rest_of_line=True, allow_space=True)], - documentation_link="keywords/host_type", - group=self.group) - return host_type diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/run_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/run_keywords.py deleted file mode 100644 index 7043da7eb6..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/run_keywords.py +++ /dev/null @@ -1,144 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, KeywordDefinition, ConfigurationLineDefinition, PathArgument, StringArgument, BoolArgument - - -class RunKeywords(object): - def __init__(self, ert_keywords): - super(RunKeywords, self).__init__() - self.group = "Run" - - ert_keywords.addKeyword(self.addDeleteRunpath()) - ert_keywords.addKeyword(self.addKeepRunpath()) - ert_keywords.addKeyword(self.addInstallJob()) - ert_keywords.addKeyword(self.addRunpath()) - ert_keywords.addKeyword(self.addRunpathFile()) - ert_keywords.addKeyword(self.addForwardModel()) - ert_keywords.addKeyword(self.addJobScript()) - ert_keywords.addKeyword(self.addRunTemplate()) - ert_keywords.addKeyword(self.addLogLevel()) - ert_keywords.addKeyword(self.addLogFile()) - ert_keywords.addKeyword(self.addMaxSubmit()) - ert_keywords.addKeyword(self.addMaxResample()) - ert_keywords.addKeyword(self.addPreClearRunpath()) - - - - - - def addInstallJob(self): - install_job = ConfigurationLineDefinition(keyword=KeywordDefinition("INSTALL_JOB"), - arguments=[StringArgument(),PathArgument()], - documentation_link="keywords/install_job", - required=False, - group=self.group) - return install_job - - - - def addDeleteRunpath(self): - delete_runpath = ConfigurationLineDefinition(keyword=KeywordDefinition("DELETE_RUNPATH"), - arguments=[StringArgument()], - documentation_link="keywords/delete_runpath", - required=False, - group=self.group) - return delete_runpath - - - def addKeepRunpath(self): - keep_runpath = ConfigurationLineDefinition(keyword=KeywordDefinition("KEEP_RUNPATH"), - arguments=[StringArgument()], - documentation_link="keywords/keep_runpath", - required=False, - group=self.group) - return keep_runpath - - - - - - def addRunpath(self): - runpath = ConfigurationLineDefinition(keyword=KeywordDefinition("RUNPATH"), - arguments=[PathArgument(must_exist=False)], - documentation_link="keywords/runpath", - required=False, - group=self.group) - return runpath - - - - def addRunpathFile(self): - runpath_file = ConfigurationLineDefinition(keyword=KeywordDefinition("RUNPATH_FILE"), - arguments=[PathArgument()], - documentation_link="keywords/runpath_file", - required=False, - group=self.group) - return runpath_file - - - def addForwardModel(self): - forward_model = ConfigurationLineDefinition(keyword=KeywordDefinition("FORWARD_MODEL"), - arguments=[StringArgument(rest_of_line=True, allow_space=True)], - documentation_link="keywords/forward_model", - required=False, - group=self.group) - return forward_model - - def addJobScript(self): - job_script = ConfigurationLineDefinition(keyword=KeywordDefinition("JOB_SCRIPT"), - arguments=[PathArgument()], - documentation_link="keywords/job_script", - required=False, - group=self.group) - return job_script - - def addRunTemplate(self): - run_template = ConfigurationLineDefinition(keyword=KeywordDefinition("RUN_TEMPLATE"), - arguments=[PathArgument(),StringArgument()], - documentation_link="keywords/run_template", - required=False, - group=self.group) - return run_template - - - def addLogLevel(self): - log_level = ConfigurationLineDefinition(keyword=KeywordDefinition("LOG_LEVEL"), - arguments=[IntegerArgument()], - documentation_link="keywords/log_level", - required=False, - group=self.group) - return log_level - - - def addLogFile(self): - log_file = ConfigurationLineDefinition(keyword=KeywordDefinition("LOG_FILE"), - arguments=[PathArgument()], - documentation_link="keywords/log_file", - required=False, - group=self.group) - return log_file - - - - def addMaxSubmit(self): - max_submit = ConfigurationLineDefinition(keyword = KeywordDefinition("MAX_SUBMIT"), - arguments=[IntegerArgument()], - documentation_link="keywords/max_submit", - group=self.group) - return max_submit - - - def addMaxResample(self): - max_resample = ConfigurationLineDefinition(keyword=KeywordDefinition("MAX_RESAMPLE"), - arguments=[IntegerArgument()], - documentation_link="keywords/max_resample", - required=False, - group=self.group) - return max_resample - - - def addPreClearRunpath(self): - pre_clear_runpath = ConfigurationLineDefinition(keyword=KeywordDefinition("PRE_CLEAR_RUNPATH"), - arguments=[BoolArgument()], - documentation_link="keywords/pre_clear_runpath", - required=False, - group=self.group) - return pre_clear_runpath \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/simulation_control_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/simulation_control_keywords.py deleted file mode 100644 index 35fb78a419..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/simulation_control_keywords.py +++ /dev/null @@ -1,43 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, BoolArgument, StringArgument, ConfigurationLineDefinition, KeywordDefinition , PercentArgument - - -class SimulationControlKeywords(object): - def __init__(self, ert_keywords): - super(SimulationControlKeywords, self).__init__() - self.group = "Simulation Control" - - - - ert_keywords.addKeyword(self.addMaxRuntime()) - ert_keywords.addKeyword(self.addMinRealizations()) - ert_keywords.addKeyword(self.addStopLongRunning()) - - - def addMaxRuntime(self): - max_runtime = ConfigurationLineDefinition(keyword=KeywordDefinition("MAX_RUNTIME"), - arguments=[IntegerArgument(from_value=0)], - documentation_link="keywords/max_runtime", - required=False, - group=self.group) - return max_runtime - - - - - def addMinRealizations(self): - min_realizations = ConfigurationLineDefinition(keyword=KeywordDefinition("MIN_REALIZATIONS"), - arguments=[IntegerArgument(from_value = 0) , - PercentArgument(from_value = 0 , to_value = 100)], - documentation_link="keywords/min_realizations", - required=False, - group=self.group) - return min_realizations - - - def addStopLongRunning(self): - stop_long_running = ConfigurationLineDefinition(keyword=KeywordDefinition("STOP_LONG_RUNNING"), - arguments=[BoolArgument()], - documentation_link="keywords/stop_long_running", - required=False, - group=self.group) - return stop_long_running diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/unix_environment_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/unix_environment_keywords.py deleted file mode 100644 index 835a3b3b55..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/unix_environment_keywords.py +++ /dev/null @@ -1,40 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, KeywordDefinition, ConfigurationLineDefinition, PathArgument, StringArgument, BoolArgument - - -class UnixEnvironmentKeywords(object): - def __init__(self, ert_keywords): - super(UnixEnvironmentKeywords, self).__init__() - self.group = "Unix" - - ert_keywords.addKeyword(self.addSetEnv()) - ert_keywords.addKeyword(self.addUMask()) - ert_keywords.addKeyword(self.addUpdatePath()) - - - - - def addSetEnv(self): - setenv = ConfigurationLineDefinition(keyword=KeywordDefinition("SETENV"), - arguments=[StringArgument(), StringArgument(rest_of_line=True,allow_space=True)], - documentation_link="keywords/setenv", - required=False, - group=self.group) - return setenv - - - def addUMask(self): - umask = ConfigurationLineDefinition(keyword=KeywordDefinition("UMASK"), - arguments=[IntegerArgument()], - documentation_link="keywords/umask", - required=False, - group=self.group) - return umask - - - def addUpdatePath(self): - update_path = ConfigurationLineDefinition(keyword=KeywordDefinition("UPDATE_PATH"), - arguments=[StringArgument(built_in=True), PathArgument()], - documentation_link="keywords/update_path", - required=False, - group=self.group) - return update_path diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/workflow_keywords.py b/ThirdParty/Ert/python/python/ert_gui/ide/keywords/workflow_keywords.py deleted file mode 100644 index 0566d20a5f..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/keywords/workflow_keywords.py +++ /dev/null @@ -1,115 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, KeywordDefinition, ConfigurationLineDefinition, PathArgument, StringArgument, BoolArgument - - -class WorkflowKeywords(object): - def __init__(self, ert_keywords): - super(WorkflowKeywords, self).__init__() - self.group = "Workflow Jobs" - - ert_keywords.addKeyword(self.addLoadWorkflowJob()) - ert_keywords.addKeyword(self.addWorkflowJobDirectory()) - ert_keywords.addKeyword(self.addLoadWorkflow()) - ert_keywords.addKeyword(self.addInternal()) - ert_keywords.addKeyword(self.addFunction()) - ert_keywords.addKeyword(self.addModule()) - ert_keywords.addKeyword(self.addExecutable()) - ert_keywords.addKeyword(self.addMinArg()) - ert_keywords.addKeyword(self.addMaxArg()) - ert_keywords.addKeyword(self.addArgType()) - - - - def addInternal(self): - internal = ConfigurationLineDefinition(keyword=KeywordDefinition("INTERNAL"), - arguments=[BoolArgument()], - documentation_link="keywords/internal", - required=False, - group=self.group) - return internal - - - def addFunction(self): - function = ConfigurationLineDefinition(keyword=KeywordDefinition("FUNCTION"), - arguments=[StringArgument()], - documentation_link="keywords/function", - required=False, - group=self.group) - return function - - - def addModule(self): - module = ConfigurationLineDefinition(keyword=KeywordDefinition("MODULE"), - arguments=[PathArgument()], - documentation_link="keywords/module", - required=False, - group=self.group) - return module - - - def addExecutable(self): - executable = ConfigurationLineDefinition(keyword=KeywordDefinition("EXECUTABLE"), - arguments=[PathArgument()], - documentation_link="keywords/executable", - required=False, - group=self.group) - return executable - - - - - def addMinArg(self): - min_arg = ConfigurationLineDefinition(keyword=KeywordDefinition("MIN_ARG"), - arguments=[IntegerArgument()], - documentation_link="keywords/min_arg", - required=False, - group=self.group) - return min_arg - - - - - def addMaxArg(self): - max_arg = ConfigurationLineDefinition(keyword=KeywordDefinition("MAX_ARG"), - arguments=[IntegerArgument()], - documentation_link="keywords/max_arg", - required=False, - group=self.group) - return max_arg - - - - def addArgType(self): - arg_type = ConfigurationLineDefinition(keyword=KeywordDefinition("ARG_TYPE"), - arguments=[StringArgument(built_in=True)], - documentation_link="keywords/arg_type", - required=False, - group=self.group) - return arg_type - - - def addLoadWorkflowJob(self): - load_workflow_job = ConfigurationLineDefinition(keyword=KeywordDefinition("LOAD_WORKFLOW_JOB"), - arguments=[StringArgument()], - documentation_link="keywords/load_workflow_job", - required=False, - group=self.group) - return load_workflow_job - - - - def addWorkflowJobDirectory(self): - workflow_job_directory = ConfigurationLineDefinition(keyword=KeywordDefinition("WORKFLOW_JOB_DIRECTORY"), - arguments=[PathArgument()], - documentation_link="keywords/workflow_job_directory", - required=False, - group=self.group) - return workflow_job_directory - - - def addLoadWorkflow(self): - load_workflow = ConfigurationLineDefinition(keyword=KeywordDefinition("LOAD_WORKFLOW"), - arguments=[PathArgument(), StringArgument(optional=True)], - documentation_link="keywords/load_workflow", - required=False, - group=self.group) - return load_workflow \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/parameter.py b/ThirdParty/Ert/python/python/ert_gui/ide/parameter.py deleted file mode 100644 index b7a0371ee3..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/parameter.py +++ /dev/null @@ -1,19 +0,0 @@ -class Parameter(object): - def __init__(self, value, start, end): - super(Parameter, self).__init__() - #: :type: str - self.value = value - #: :type: int - self.start = start - #: :type: int - self.end = end - - #: :type: bool - self.error = False - #: :type: str - self.error_message = "" - - @property - def length(self): - """ @rtype: int """ - return self.end - self.start \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/wizards/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/ide/wizards/CMakeLists.txt deleted file mode 100644 index c2450868b9..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/wizards/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - tree_item.py - tree_model.py - wizard_view.py -) - -add_python_package("python.ert_gui.ide.wizards" ${PYTHON_INSTALL_PREFIX}/ert_gui/ide/wizards "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/wizards/__init__.py b/ThirdParty/Ert/python/python/ert_gui/ide/wizards/__init__.py deleted file mode 100644 index e8b9ef3cce..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/wizards/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .tree_item import TreeItem -from .tree_model import TreeModel -from .wizard_view import WizardView \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/wizards/tree_item.py b/ThirdParty/Ert/python/python/ert_gui/ide/wizards/tree_item.py deleted file mode 100644 index e7793dd842..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/wizards/tree_item.py +++ /dev/null @@ -1,38 +0,0 @@ -class TreeItem(object): - def __init__(self, name, data=None): - super(TreeItem, self).__init__() - self.__name = name - self.__parent = None - - self.__children = [] - self.__data = data - - def child(self, row): - return self.__children[row] - - def __len__(self): - return len(self.__children) - - def data(self): - return self.__data - - def name(self): - return self.__name - - def addChild(self, child): - assert isinstance(child, TreeItem) - child.setParent(self) - self.__children.append(child) - return child - - def parent(self): - return self.__parent - - def setParent(self, parent): - self.__parent = parent - - def row(self): - if self.__parent is not None: - return self.__parent.__children.index(self) - - return 0 \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/wizards/tree_model.py b/ThirdParty/Ert/python/python/ert_gui/ide/wizards/tree_model.py deleted file mode 100644 index 1cef6708b7..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/wizards/tree_model.py +++ /dev/null @@ -1,97 +0,0 @@ -from PyQt4.QtCore import QAbstractItemModel, QModelIndex, QVariant, Qt -from ert_gui.ide.wizards import TreeItem - - -class TreeModel(QAbstractItemModel): - - def __init__(self, tree_root, parent=None): - QAbstractItemModel.__init__(self, parent) - - self.__root = tree_root - - def data(self, q_model_index, role=Qt.DisplayRole): - - item = self.item(q_model_index) - - if item is not None: - if role == Qt.DisplayRole: - return item.name() - - return QVariant() - - def item(self, q_model_index): - if not q_model_index.isValid(): - return None - - return q_model_index.internalPointer() - - - def flags(self, q_model_index): - if not q_model_index.isValid(): - return 0 - - item = self.item(q_model_index) - - if item.data() is None: - return Qt.ItemIsEnabled - else: - return Qt.ItemIsEnabled | Qt.ItemIsSelectable - - - def headerData(self, section, orientation, role=Qt.DisplayRole): - if orientation == Qt.Horizontal and role == Qt.DisplayRole: - return self.__root.name() - - return QVariant() - - - def index(self, row, column, parent=None): - if parent is None: - parent = QModelIndex() - - if not self.hasIndex(row, column, parent): - return QModelIndex() - - if not parent.isValid(): - parent_item = self.__root - else: - parent_item = parent.internalPointer() - - child_item = parent_item.child(row) - - return self.createIndex(row, column, child_item) - - - def parent(self, q_model_index): - if not q_model_index.isValid(): - return QModelIndex() - - child_item = q_model_index.internalPointer() - parent_item = child_item.parent() - - if parent_item == self.__root: - return QModelIndex() - - return self.createIndex(parent_item.row(), 0, parent_item) - - def rowCount(self, parent): - if parent is None: - parent = QModelIndex() - - if parent.column() > 0: - return 0 - - if not parent.isValid(): - return len(self.__root) - else: - return len(parent.internalPointer()) - - - - def columnCount(self, parent): - return 1 - - - def emitChange(self): - self.modelReset.emit() - diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/wizards/wizard_view.py b/ThirdParty/Ert/python/python/ert_gui/ide/wizards/wizard_view.py deleted file mode 100644 index b5ce7fe05e..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/ide/wizards/wizard_view.py +++ /dev/null @@ -1,42 +0,0 @@ -from PyQt4.QtGui import QTreeView -from ert_gui.ide.wizards import TreeItem -from ert_gui.ide.wizards.tree_model import TreeModel - - -class WizardView(QTreeView): - def __init__(self, parent=None): - QTreeView.__init__(self, parent) - - self.__root = TreeItem("ERT") - - self.__tree_model = TreeModel(self.__root) - - self.setModel(self.__tree_model) - - #: :type: dict of (str, TreeItem) - self.__groups = {} - - self.header().hide() - - - def addGroup(self, group_name): - if group_name in self.__groups: - raise ValueError("A group with name: %s already exists!" % group_name) - - group = TreeItem(group_name) - - self.__groups[group_name] = group - self.__root.addChild(group) - - self.__tree_model.emitChange() - - - def addItemToGroup(self, group, item): - group_item = self.__groups[group] - - child_item = TreeItem(item) - group_item.addChild(child_item) - - self.__tree_model.emitChange() - - diff --git a/ThirdParty/Ert/python/python/ert_gui/main_window.py b/ThirdParty/Ert/python/python/ert_gui/main_window.py deleted file mode 100644 index ccecd82500..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/main_window.py +++ /dev/null @@ -1,128 +0,0 @@ -from PyQt4.QtCore import QSettings, Qt -from PyQt4.QtGui import QMainWindow, qApp, QWidget, QVBoxLayout, QDockWidget, QAction, QToolButton -from ert_gui.about_dialog import AboutDialog - - -class GertMainWindow(QMainWindow): - def __init__(self): - QMainWindow.__init__(self) - - self.tools = {} - - self.resize(300, 700) - self.setWindowTitle('ERT') - - self.__main_widget = None - - self.central_widget = QWidget() - self.central_layout = QVBoxLayout() - self.central_widget.setLayout(self.central_layout) - - self.setCentralWidget(self.central_widget) - - self.toolbar = self.addToolBar("Tools") - self.toolbar.setObjectName("Toolbar") - self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) - - self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea) - self.setCorner(Qt.BottomLeftCorner, Qt.BottomDockWidgetArea) - - self.setCorner(Qt.TopRightCorner, Qt.RightDockWidgetArea) - self.setCorner(Qt.BottomRightCorner, Qt.BottomDockWidgetArea) - self.__view_menu = None - self.__help_menu = None - - self.__createMenu() - self.__fetchSettings() - - def addDock(self, name, widget, area=Qt.RightDockWidgetArea, allowed_areas=Qt.AllDockWidgetAreas): - dock_widget = QDockWidget(name) - dock_widget.setObjectName("%sDock" % name) - dock_widget.setWidget(widget) - dock_widget.setAllowedAreas(allowed_areas) - - self.addDockWidget(area, dock_widget) - - self.__view_menu.addAction(dock_widget.toggleViewAction()) - return dock_widget - - def addTool(self, tool): - tool.setParent(self) - self.tools[tool.getName()] = tool - self.toolbar.addAction(tool.getAction()) - - if tool.isPopupMenu(): - tool_button = self.toolbar.widgetForAction(tool.getAction()) - tool_button.setPopupMode(QToolButton.InstantPopup) - - - def __createMenu(self): - file_menu = self.menuBar().addMenu("&File") - file_menu.addAction("Close", self.__quit) - self.__view_menu = self.menuBar().addMenu("&View") - self.__help_menu = self.menuBar().addMenu("&Help") - """:type: QMenu""" - - """ @rtype: list of QAction """ - advanced_toggle_action = QAction("Show Advanced Options", self) - advanced_toggle_action.setObjectName("AdvancedSimulationOptions") - advanced_toggle_action.setCheckable(True) - advanced_toggle_action.setChecked(False) - advanced_toggle_action.toggled.connect(self.toggleAdvancedMode) - - self.__view_menu.addAction(advanced_toggle_action) - - """ @rtype: list of QAction """ - show_about = self.__help_menu.addAction("About") - show_about.setMenuRole(QAction.ApplicationSpecificRole) - show_about.triggered.connect(self.__showAboutMessage) - - - def __quit(self): - self.__saveSettings() - qApp.quit() - - - def __saveSettings(self): - settings = QSettings("Statoil", "Ert-Gui") - settings.setValue("geometry", self.saveGeometry()) - settings.setValue("windowState", self.saveState()) - - - def closeEvent(self, event): - #Use QT settings saving mechanism - #settings stored in ~/.config/Statoil/ErtGui.conf - self.__saveSettings() - QMainWindow.closeEvent(self, event) - - - def __fetchSettings(self): - settings = QSettings("Statoil", "Ert-Gui") - self.restoreGeometry(settings.value("geometry").toByteArray()) - self.restoreState(settings.value("windowState").toByteArray()) - - def toggleAdvancedMode(self, advanced_mode): - if hasattr(self.__main_widget, "toggleAdvancedMode"): - self.__main_widget.toggleAdvancedMode(advanced_mode) - - for tool in self.tools.values(): - if hasattr(tool, "toggleAdvancedMode"): - tool.toggleAdvancedMode(advanced_mode) - - - def setWidget(self, widget): - self.__main_widget = widget - actions = widget.getActions() - for action in actions: - self.__view_menu.addAction(action) - - self.central_layout.addWidget(widget) - - def __showAboutMessage(self): - diag = AboutDialog(self) - diag.show() - pass - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/newconfig.py b/ThirdParty/Ert/python/python/ert_gui/newconfig.py deleted file mode 100644 index 419df4f53c..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/newconfig.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'newconfig.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -import os - -from PyQt4.QtCore import Qt, SIGNAL, QSize -from PyQt4.QtGui import QDialog, QFormLayout, QLabel, QDialogButtonBox, QComboBox, QSpinBox, QLineEdit, QWidget - - -def createSpace(size=5): - """Creates a widget that can be used as spacing on a panel.""" - qw = QWidget() - qw.setMinimumSize(QSize(size, size)) - - return qw - - -class NewConfigurationDialog(QDialog): - """A dialog for selecting defaults for a new configuration.""" - - def __init__(self, configuration_path, parent=None): - QDialog.__init__(self, parent) - - self.setModal(True) - self.setWindowTitle("New configuration file") - self.setMinimumWidth(250) - self.setMinimumHeight(150) - - layout = QFormLayout() - - directory, filename = os.path.split(configuration_path) - - if directory.strip() == "": - directory = os.path.abspath(os.curdir) - self.configuration_path = "%s/%s" % (directory, filename) - else: - self.configuration_path = configuration_path - - configuration_location = QLabel() - configuration_location.setText(directory) - - configuration_name = QLabel() - configuration_name.setText(filename) - - self.db_type = QComboBox() - self.db_type.addItem("BLOCK_FS") - self.db_type.addItem("PLAIN") - - self.num_realizations = QSpinBox() - self.num_realizations.setMinimum(1) - self.num_realizations.setMaximum(1000) - self.num_realizations.setValue(10) - - self.storage_path = QLineEdit() - self.storage_path.setText("Storage") - self.connect(self.storage_path, SIGNAL('textChanged(QString)'), self._validateName) - - layout.addRow(createSpace(10)) - layout.addRow("Configuration name:", configuration_name) - layout.addRow("Configuration location:", configuration_location) - layout.addRow("Path to store DBase:", self.storage_path) - layout.addRow("DBase type:", self.db_type) - layout.addRow("Number of realizations", self.num_realizations) - layout.addRow(createSpace(10)) - - buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) - self.ok_button = buttons.button(QDialogButtonBox.Ok) - - layout.addRow(buttons) - - self.connect(buttons, SIGNAL('accepted()'), self.accept) - self.connect(buttons, SIGNAL('rejected()'), self.reject) - - self.setLayout(layout) - - def getNumberOfRealizations(self): - return self.num_realizations.value() - - def getConfigurationPath(self): - return self.configuration_path - - def getDBaseType(self): - """Return the DBase type""" - return str(self.db_type.currentText()) - - def getStoragePath(self): - """Return the DBase storage path""" - return str(self.storage_path.text()).strip() - - def _validateName(self, name): - name = str(name) - enabled = len(name) > 0 and name.find(" ") == -1 - self.ok_button.setEnabled(enabled) diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/plottery/CMakeLists.txt deleted file mode 100644 index 4a9f42d59c..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - plot_config.py - plot_config_history.py - plot_config_factory.py - plot_context.py - plot_data_gatherer.py - plot_limits.py - plot_style.py -) - -add_python_package("python.ert_gui.plottery" ${PYTHON_INSTALL_PREFIX}/ert_gui/plottery "${PYTHON_SOURCES}" True) - -add_subdirectory(plots) diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/__init__.py b/ThirdParty/Ert/python/python/ert_gui/plottery/__init__.py deleted file mode 100644 index 30332e1857..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from .plot_data_gatherer import PlotDataGatherer -from .plot_style import PlotStyle -from .plot_limits import PlotLimits -from .plot_config import PlotConfig -from .plot_context import PlotContext -from .plot_config_history import PlotConfigHistory -from .plot_config_factory import PlotConfigFactory diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_config.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plot_config.py deleted file mode 100644 index 0ac1a5cbde..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_config.py +++ /dev/null @@ -1,305 +0,0 @@ -import itertools -from ert_gui.plottery import PlotStyle, PlotLimits - - -class PlotConfig(object): - - # The plot_settings input argument is an internalisation of the (quite few) plot - # policy settings which can be set in the configuration file. - - def __init__(self, plot_settings, title="Unnamed", x_label=None, y_label=None): - self._title = title - self._plot_settings = plot_settings - if self._plot_settings is None: - raise ValueError('PlotConfig needs a non-None plot settings.') - self._line_color_cycle_colors = ["#000000"] - self._line_color_cycle = itertools.cycle(self._line_color_cycle_colors) #Black - # Blueish, Greenlike, Beigeoid, Pinkness, Orangy-Brown - self.setLineColorCycle(["#386CB0", "#7FC97F", "#FDC086", "#F0027F", "#BF5B17"]) - # alternative color cycle: - # ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33", - # "#a65628", "#f781bf" ,"#386CB0", "#7FC97F", "#FDC086", "#F0027F", "#BF5B17"] - - self._legend_items = [] - self._legend_labels = [] - - self._x_label = x_label - self._y_label = y_label - - self._limits = PlotLimits() - - self._default_style = PlotStyle(name="Default", color=None, alpha=0.8) - - self._refcase_style = PlotStyle(name="Refcase", alpha=0.8, line_style="--", marker="", width=2.0, - enabled=self._plot_settings["SHOW_REFCASE"]) - - self._history_style = PlotStyle(name="History", alpha=0.8, marker=".", width=2.0, - enabled=self._plot_settings["SHOW_HISTORY"]) - - self._observs_style = PlotStyle(name="Observations", line_style="-", alpha=0.8, - marker=".", width=1.0, color="#000000") - - self._histogram_style = PlotStyle(name="Histogram", width=2.0) - self._distribution_style = PlotStyle(name="Distribution", line_style="", marker="o", alpha=0.5, size=10.0) - self._distribution_line_style = PlotStyle(name="Distribution Lines", line_style="-", alpha=0.25, width=1.0) - self._distribution_line_style.setEnabled(False) - self._current_color = None - - self._legend_enabled = True - self._grid_enabled = True - - - self._statistics_style = { - "mean": PlotStyle("Mean", line_style=""), - "p50": PlotStyle("P50", line_style=""), - "min-max": PlotStyle("Min/Max", line_style=""), - "p10-p90": PlotStyle("P10-P90", line_style=""), - "p33-p67": PlotStyle("P33-P67", line_style=""), - "std": PlotStyle("Std dev", line_style="") - } - - self._std_dev_factor = 1 # sigma 1 is default std dev - - def currentColor(self): - if self._current_color is None: - self.nextColor() - - return self._current_color - - def nextColor(self): - self._current_color = self._line_color_cycle.next() - return self._current_color - - def setLineColorCycle(self, color_list): - self._line_color_cycle_colors = color_list - self._line_color_cycle = itertools.cycle(color_list) - - def lineColorCycle(self): - return list(self._line_color_cycle_colors) - - def addLegendItem(self, label, item): - self._legend_items.append(item) - self._legend_labels.append(label) - - def title(self): - """ :rtype: str """ - return self._title if self._title is not None else "Unnamed" - - def setTitle(self, title): - self._title = title - - def isUnnamed(self): - return self._title is None - - def defaultStyle(self): - style = PlotStyle("Default Style") - style.copyStyleFrom(self._default_style) - style.color = self.currentColor() - return style - - def observationsColor(self): - return self._observs_style.color - - def observationsStyle(self): - """ @rtype: PlotStyle """ - style = PlotStyle("Observations Style") - style.copyStyleFrom(self._observs_style) - return style - - def refcaseStyle(self): - """ @rtype: PlotStyle """ - style = PlotStyle("Refcase Style") - style.copyStyleFrom(self._refcase_style) - return style - - def historyStyle(self): - """ @rtype: PlotStyle """ - style = PlotStyle("History Style") - style.copyStyleFrom(self._history_style) - return style - - def histogramStyle(self): - """ @rtype: PlotStyle """ - style = PlotStyle("Histogram Style") - style.copyStyleFrom(self._histogram_style) - style.color = self.currentColor() - return style - - def distributionStyle(self): - """ @rtype: PlotStyle """ - style = PlotStyle("Distribution Style") - style.copyStyleFrom(self._distribution_style) - style.color = self.currentColor() - return style - - def distributionLineStyle(self): - """ @rtype: ert_gui.plottery.PlotStyle """ - style = PlotStyle("Distribution Line Style") - style.copyStyleFrom(self._distribution_line_style) - return style - - def xLabel(self): - return self._x_label - - def yLabel(self): - return self._y_label - - def legendItems(self): - return self._legend_items - - def legendLabels(self): - return self._legend_labels - - def setXLabel(self, label): - self._x_label = label - - def setYLabel(self, label): - self._y_label = label - - def setObservationsEnabled(self, enabled): - self._observs_style.setEnabled(enabled) - - def isObservationsEnabled(self): - return self._observs_style.isEnabled() - - def setRefcaseEnabled(self, enabled): - self._refcase_style.setEnabled(enabled) - - def isRefcaseEnabled(self): - return self._refcase_style.isEnabled() - - def setHistoryEnabled(self, enabled): - self._history_style.setEnabled(enabled) - - def isHistoryEnabled(self): - return self._history_style.isEnabled() - - def isLegendEnabled(self): - return self._legend_enabled - - def isDistributionLineEnabled(self): - return self._distribution_line_style.isEnabled() - - def setDistributionLineEnabled(self, enabled): - self._distribution_line_style.setEnabled(enabled) - - def setStandardDeviationFactor(self, value): - self._std_dev_factor = value - - def getStandardDeviationFactor(self): - return self._std_dev_factor - - def setLegendEnabled(self, enabled): - self._legend_enabled = enabled - - def isGridEnabled(self): - return self._grid_enabled - - def setGridEnabled(self, enabled): - self._grid_enabled = enabled - - def setStatisticsStyle(self, statistic, style): - """ - @type statistic: str - @type style: PlotStyle - """ - - statistics_style = self._statistics_style[statistic] - statistics_style.line_style = style.line_style - statistics_style.marker = style.marker - statistics_style.width = style.width - statistics_style.size = style.size - - def getStatisticsStyle(self, statistic): - style = self._statistics_style[statistic] - copy_style = PlotStyle(style.name) - copy_style.copyStyleFrom(style) - copy_style.color = self.currentColor() - return copy_style - - def setRefcaseStyle(self, style): - """ @type style: PlotStyle """ - self._refcase_style.line_style = style.line_style - self._refcase_style.marker = style.marker - self._refcase_style.width = style.width - self._refcase_style.size = style.size - - def setHistoryStyle(self, style): - """ @type style: PlotStyle """ - self._history_style.line_style = style.line_style - self._history_style.marker = style.marker - self._history_style.width = style.width - self._history_style.size = style.size - - def setObservationsColor(self, color): - self._observs_style.color = color - - def setObservationsStyle(self, style): - """ @type style: PlotStyle """ - self._observs_style.line_style = style.line_style - self._observs_style.marker = style.marker - self._observs_style.width = style.width - self._observs_style.size = style.size - - def setDefaultStyle(self, style): - """ @type style: PlotStyle """ - self._default_style.line_style = style.line_style - self._default_style.marker = style.marker - self._default_style.width = style.width - self._default_style.size = style.size - - - @property - def limits(self): - """ @rtype: PlotLimits """ - limits = PlotLimits() - limits.copyLimitsFrom(self._limits) - return limits - - @limits.setter - def limits(self, value): - """ @type value: PlotLimits """ - self._limits.copyLimitsFrom(value) - - - def copyConfigFrom(self, other): - """ - :type other: PlotConfig - """ - self._default_style.copyStyleFrom(other._default_style, copy_enabled_state=True) - self._refcase_style.copyStyleFrom(other._refcase_style, copy_enabled_state=True) - self._history_style.copyStyleFrom(other._history_style, copy_enabled_state=True) - self._histogram_style.copyStyleFrom(other._histogram_style, copy_enabled_state=True) - self._observs_style.copyStyleFrom(other._observs_style, copy_enabled_state=True) - self._distribution_style.copyStyleFrom(other._distribution_style, copy_enabled_state=True) - self._distribution_line_style.copyStyleFrom(other._distribution_line_style, copy_enabled_state=True) - - self._statistics_style["mean"].copyStyleFrom(other._statistics_style["mean"], copy_enabled_state=True) - self._statistics_style["p50"].copyStyleFrom(other._statistics_style["p50"], copy_enabled_state=True) - self._statistics_style["min-max"].copyStyleFrom(other._statistics_style["min-max"], copy_enabled_state=True) - self._statistics_style["p10-p90"].copyStyleFrom(other._statistics_style["p10-p90"], copy_enabled_state=True) - self._statistics_style["p33-p67"].copyStyleFrom(other._statistics_style["p33-p67"], copy_enabled_state=True) - self._statistics_style["std"].copyStyleFrom(other._statistics_style["std"], copy_enabled_state=True) - - self._std_dev_factor = other._std_dev_factor - self._legend_enabled = other._legend_enabled - self._grid_enabled = other._grid_enabled - - self.setLineColorCycle(other._line_color_cycle_colors) - - self._legend_items = other._legend_items[:] - self._legend_labels = other._legend_labels[:] - - self._x_label = other._x_label - self._y_label = other._y_label - - self._limits.copyLimitsFrom(other._limits) - - if other._title is not None: - self._title = other._title - - @classmethod - def createCopy(cls, other): - copy = PlotConfig(other._plot_settings ) - copy.copyConfigFrom(other) - return copy diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_config_factory.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plot_config_factory.py deleted file mode 100644 index 793d240407..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_config_factory.py +++ /dev/null @@ -1,45 +0,0 @@ -from ert_gui.plottery import PlotConfig - - -class PlotConfigFactory(object): - - @classmethod - def createPlotConfigForKey(cls, ert, key): - """ - @type ert: ert.enkf.enkf_main.EnKFMain - @param key: str - @return: PlotConfig - """ - plot_config = PlotConfig(ert.plotConfig() , title = key) - return PlotConfigFactory.updatePlotConfigForKey(ert, key, plot_config) - - - @classmethod - def updatePlotConfigForKey(cls, ert, key, plot_config): - """ - @type ert: ert.enkf.enkf_main.EnKFMain - @param key: str - @return: PlotConfig - """ - key_manager = ert.getKeyManager() - # The styling of statistics changes based on the nature of the data - if key_manager.isSummaryKey(key) or key_manager.isGenDataKey(key): - mean_style = plot_config.getStatisticsStyle("mean") - mean_style.line_style = "-" - plot_config.setStatisticsStyle("mean", mean_style) - - p10p90_style = plot_config.getStatisticsStyle("p10-p90") - p10p90_style.line_style = "--" - plot_config.setStatisticsStyle("p10-p90", p10p90_style) - else: - mean_style = plot_config.getStatisticsStyle("mean") - mean_style.line_style = "-" - mean_style.marker = "o" - plot_config.setStatisticsStyle("mean", mean_style) - - std_style = plot_config.getStatisticsStyle("std") - std_style.line_style = "--" - std_style.marker = "D" - plot_config.setStatisticsStyle("std", std_style) - - return plot_config diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_config_history.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plot_config_history.py deleted file mode 100644 index b21699267e..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_config_history.py +++ /dev/null @@ -1,46 +0,0 @@ -from ert_gui.plottery import PlotConfig - - -class PlotConfigHistory(object): - """ A Class for tracking changes to a PlotConfig class (supports undo, redo and reset)""" - - def __init__(self, name, initial): - super(PlotConfigHistory, self).__init__() - self._name = name - self._initial = PlotConfig.createCopy(initial) - self._undo_history = [] - self._redo_history = [] - self._current = PlotConfig.createCopy(self._initial) - - def isUndoPossible(self): - """ @rtype: bool """ - return len(self._undo_history) > 0 - - def isRedoPossible(self): - """ @rtype: bool """ - return len(self._redo_history) > 0 - - def applyChanges(self, plot_config): - """ @type plot_config: PlotConfig """ - self._undo_history.append(self._current) - copy = PlotConfig.createCopy(self._current) - copy.copyConfigFrom(plot_config) - self._current = copy - del self._redo_history[:] - - def resetChanges(self): - self.applyChanges(self._initial) - - def undoChanges(self): - if self.isUndoPossible(): - self._redo_history.append(self._current) - self._current = self._undo_history.pop() - - def redoChanges(self): - if self.isRedoPossible(): - self._undo_history.append(self._current) - self._current = self._redo_history.pop() - - def getPlotConfig(self): - """ @rtype: PlotConfig """ - return PlotConfig.createCopy(self._current) diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_context.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plot_context.py deleted file mode 100644 index 8afeaf74d4..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_context.py +++ /dev/null @@ -1,80 +0,0 @@ -from .plot_config import PlotConfig -from .plot_data_gatherer import PlotDataGatherer - -class PlotContext(object): - UNKNOWN_AXIS = None - VALUE_AXIS = "VALUE" - DATE_AXIS = "DATE" - INDEX_AXIS = "INDEX" - COUNT_AXIS = "COUNT" - DENSITY_AXIS = "DENSITY" - DEPTH_AXIS = "DEPTH" - AXIS_TYPES = [UNKNOWN_AXIS, COUNT_AXIS, DATE_AXIS, DENSITY_AXIS, DEPTH_AXIS, INDEX_AXIS, VALUE_AXIS] - - def __init__(self, ert, figure, plot_config, cases, key, data_gatherer): - super(PlotContext, self).__init__() - self._data_gatherer = data_gatherer - self._key = key - self._cases = cases - self._figure = figure - self._ert = ert - self._plot_config = plot_config - - self._date_support_active = True - self._x_axis = None - self._y_axis = None - - def figure(self): - """ :rtype: matplotlib.figure.Figure""" - return self._figure - - def plotConfig(self): - """ :rtype: PlotConfig """ - return self._plot_config - - def ert(self): - """ :rtype: ert.enkf.EnKFMain""" - return self._ert - - def cases(self): - """ :rtype: list of str """ - return self._cases - - def key(self): - """ :rtype: str """ - return self._key - - def dataGatherer(self): - """ :rtype: PlotDataGatherer """ - return self._data_gatherer - - def deactivateDateSupport(self): - self._date_support_active = False - - def isDateSupportActive(self): - """ @rtype: bool """ - return self._date_support_active - - @property - def x_axis(self): - """ @rtype: str """ - return self._x_axis - - @x_axis.setter - def x_axis(self, value): - """ @type value: str """ - if not value in PlotContext.AXIS_TYPES: - raise UserWarning("Axis: '%s' is not one of: %s" % (value, PlotContext.AXIS_TYPES)) - self._x_axis = value - - @property - def y_axis(self): - """ @rtype: str """ - return self._y_axis - - @y_axis.setter - def y_axis(self, value): - """ @type value: str """ - if not value in PlotContext.AXIS_TYPES: - raise UserWarning("Axis: '%s' is not one of: %s" % (value, PlotContext.AXIS_TYPES)) - self._y_axis = value \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_data_gatherer.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plot_data_gatherer.py deleted file mode 100644 index 11fa2a3c94..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_data_gatherer.py +++ /dev/null @@ -1,159 +0,0 @@ -from pandas import DataFrame -from ert.enkf.export import GenKwCollector, SummaryCollector, GenDataCollector, SummaryObservationCollector, \ - GenDataObservationCollector, CustomKWCollector - - -class PlotDataGatherer(object): - - def __init__(self, dataGatherFunc, conditionFunc, refcaseGatherFunc=None, observationGatherFunc=None, historyGatherFunc=None): - super(PlotDataGatherer, self).__init__() - - self._dataGatherFunction = dataGatherFunc - self._conditionFunction = conditionFunc - self._refcaseGatherFunction = refcaseGatherFunc - self._observationGatherFunction = observationGatherFunc - self._historyGatherFunc = historyGatherFunc - - def hasHistoryGatherFunction(self): - """ :rtype: bool """ - return self._historyGatherFunc is not None - - def hasRefcaseGatherFunction(self): - """ :rtype: bool """ - return self._refcaseGatherFunction is not None - - def hasObservationGatherFunction(self): - """ :rtype: bool """ - return self._observationGatherFunction is not None - - def canGatherDataForKey(self, key): - """ :rtype: bool """ - return self._conditionFunction(key) - - def gatherData(self, ert, case, key): - """ :rtype: pandas.DataFrame """ - if not self.canGatherDataForKey(key): - raise UserWarning("Unable to gather data for key: %s" % key) - - return self._dataGatherFunction(ert, case, key) - - def gatherRefcaseData(self, ert, key): - """ :rtype: pandas.DataFrame """ - if not self.canGatherDataForKey(key) or not self.hasRefcaseGatherFunction(): - raise UserWarning("Unable to gather refcase data for key: %s" % key) - - return self._refcaseGatherFunction(ert, key) - - def gatherObservationData(self, ert, case, key): - """ :rtype: pandas.DataFrame """ - if not self.canGatherDataForKey(key) or not self.hasObservationGatherFunction(): - raise UserWarning("Unable to gather observation data for key: %s" % key) - - return self._observationGatherFunction(ert, case, key) - - def gatherHistoryData(self, ert, case, key): - """ :rtype: pandas.DataFrame """ - if not self.canGatherDataForKey(key) or not self.hasHistoryGatherFunction(): - raise UserWarning("Unable to gather history data for key: %s" % key) - - return self._historyGatherFunc(ert, case, key) - - - @staticmethod - def gatherGenKwData(ert, case, key): - """ :rtype: pandas.DataFrame """ - data = GenKwCollector.loadAllGenKwData(ert, case, [key]) - return data[key].dropna() - - @staticmethod - def gatherSummaryData(ert, case, key): - """ :rtype: pandas.DataFrame """ - data = SummaryCollector.loadAllSummaryData(ert, case, [key]) - if not data.empty: - data = data.reset_index() - data = data.pivot(index="Date", columns="Realization", values=key) - - return data #.dropna() - - @staticmethod - def gatherSummaryRefcaseData(ert, key): - refcase = ert.eclConfig().getRefcase() - - if refcase is None or not key in refcase: - return DataFrame() - - vector = refcase.get_vector(key, report_only=False) - - rows = [] - for index in range(1, len(vector)): - node = vector[index] - row = { - "Date": node.date, - key: node.value - } - rows.append(row) - - data = DataFrame(rows) - data = data.set_index("Date") - - return data - - @staticmethod - def gatherSummaryHistoryData(ert, case, key): - # create history key - if ":" in key: - head, tail = key.split(":", 2) - key = "%sH:%s" % (head, tail) - else: - key = "%sH" % key - - data = PlotDataGatherer.gatherSummaryRefcaseData(ert, key) - if data.empty and case is not None: - data = PlotDataGatherer.gatherSummaryData(ert, case, key) - - return data - - @staticmethod - def gatherSummaryObservationData(ert, case, key): - if ert.getKeyManager().isKeyWithObservations(key): - return SummaryObservationCollector.loadObservationData(ert, case, [key]).dropna() - else: - return DataFrame() - - - @staticmethod - def gatherGenDataData(ert, case, key): - """ :rtype: pandas.DataFrame """ - key, report_step = key.split("@", 1) - report_step = int(report_step) - try: - data = GenDataCollector.loadGenData(ert, case, key, report_step) - except ValueError: - data = DataFrame() - - return data.dropna() # removes all rows that has a NaN - - - @staticmethod - def gatherGenDataObservationData(ert, case, key_with_report_step): - """ :rtype: pandas.DataFrame """ - key, report_step = key_with_report_step.split("@", 1) - report_step = int(report_step) - - obs_key = GenDataObservationCollector.getObservationKeyForDataKey(ert, key, report_step) - - if obs_key is not None: - obs_data = GenDataObservationCollector.loadGenDataObservations(ert, case, obs_key) - columns = {obs_key: key_with_report_step, "STD_%s" % obs_key: "STD_%s" % key_with_report_step} - obs_data = obs_data.rename(columns=columns) - else: - obs_data = DataFrame() - - return obs_data.dropna() - - @staticmethod - def gatherCustomKwData(ert, case, key): - """ :rtype: pandas.DataFrame """ - data = CustomKWCollector.loadAllCustomKWData(ert, case, [key])[key] - - return data diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_limits.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plot_limits.py deleted file mode 100644 index bac7f42dd5..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_limits.py +++ /dev/null @@ -1,105 +0,0 @@ -import datetime - -class limit_property(object): - def __init__(self, attribute_name, types, minimum=None, maximum=None): - super(limit_property, self).__init__() - self._types = types - self._maximum = maximum - self._minimum = minimum - self._attribute_name = attribute_name - - def __get__(self, instance, owner): - if not hasattr(instance, "_%s" % self._attribute_name): - setattr(instance, "_%s" % self._attribute_name, None) - return getattr(instance, "_%s" % self._attribute_name) - - def __set__(self, instance, value): - if value is not None: - if not isinstance(value, self._types): - raise TypeError("Value not (one) of type(s): %s: %s" % (self._types, repr(value))) - if self._minimum is not None and value < self._minimum: - raise ValueError("Value can not be less than %f: %f < %f" % (self._minimum, value, self._minimum)) - if self._maximum is not None and value > self._maximum: - raise ValueError("Value can not be larger than %f: %f > %f" % (self._maximum, value, self._maximum)) - - setattr(instance, "_%s" % self._attribute_name, value) - - -class limits_property(object): - def __init__(self, minimum_attribute_name, maximum_attribute_name): - super(limits_property, self).__init__() - self._minimum_attribute_name = minimum_attribute_name - self._maximum_attribute_name = maximum_attribute_name - - def __get__(self, instance, owner): - return getattr(instance, "%s" % self._minimum_attribute_name), getattr(instance, "%s" % self._maximum_attribute_name) - - def __set__(self, instance, value): - setattr(instance, "_%s" % self._minimum_attribute_name, value[0]) - setattr(instance, "_%s" % self._maximum_attribute_name, value[1]) - - -class PlotLimits(object): - value_minimum = limit_property("value_minimum", (float, int)) - """ :type: float """ - value_maximum = limit_property("value_maximum", (float, int)) - """ :type: float """ - value_limits = limits_property("value_minimum", "value_maximum") - """ :type: (float, float) """ - - index_minimum = limit_property("index_minimum", int, minimum=0) - """ :type: int """ - index_maximum = limit_property("index_maximum", int, minimum=0) - """ :type: int """ - index_limits = limits_property("index_minimum", "index_maximum") - """ :type: (int, int) """ - - count_minimum = limit_property("count_minimum", int, minimum=0) - """ :type: int """ - count_maximum = limit_property("count_maximum", int, minimum=0) - """ :type: int """ - count_limits = limits_property("count_minimum", "count_maximum") - """ :type: (int, int) """ - - density_minimum = limit_property("density_minimum", (float, int), minimum=0.0) - """ :type: float """ - density_maximum = limit_property("density_maximum", (float, int), minimum=0.0) - """ :type: float """ - density_limits = limits_property("density_minimum", "density_maximum") - """ :type: (float, float) """ - - depth_minimum = limit_property("depth_minimum", (float, int), minimum=0.0) - """ :type: float """ - depth_maximum = limit_property("depth_maximum", (float, int), minimum=0.0) - """ :type: float """ - depth_limits = limits_property("depth_minimum", "depth_maximum") - """ :type: tuple[float, float] """ - - date_minimum = limit_property("date_minimum", (datetime.date, datetime.datetime)) - """ :type: datetime.datetime or datetime.date """ - date_maximum = limit_property("date_maximum", (datetime.date, datetime.datetime)) - """ :type: datetime.datetime or datetime.date """ - date_limits = limits_property("date_minimum", "date_maximum") - """ :type: tuple[datetime.datetime|datetime.date, datetime.datetime|datetime.date] """ - - - def __eq__(self, other): - """ @type other: PlotLimits """ - equality = self.value_limits == other.value_limits - equality = equality and self.index_limits == other.index_limits - equality = equality and self.count_limits == other.count_limits - equality = equality and self.depth_limits == other.depth_limits - equality = equality and self.date_limits == other.date_limits - equality = equality and self.density_limits == other.density_limits - - return equality - - - def copyLimitsFrom(self, other): - """ @type other: PlotLimits """ - self.value_limits = other.value_limits - self.density_limits = other.density_limits - self.depth_limits = other.depth_limits - self.index_limits = other.index_limits - self.date_limits = other.date_limits - self.count_limits = other.count_limits \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_style.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plot_style.py deleted file mode 100644 index a7b1357d9b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plot_style.py +++ /dev/null @@ -1,112 +0,0 @@ -class PlotStyle(object): - def __init__(self, name, color="#000000", alpha=1.0, line_style="-", marker="", width=1.0, size=7.5, enabled = True): - super(PlotStyle, self).__init__() - self.name = name - self.color = color - self.alpha = alpha - self.line_style = line_style - self.marker = marker - self.width = width - self.size = size - self._enabled = enabled - self._is_copy = False - - def copyStyleFrom(self, other, copy_enabled_state=False): - self.color = other.color - self.alpha = other.alpha - self.line_style = other._line_style - self.marker = other._marker - self.width = other.width - self.size = other.size - self._is_copy = True - - if copy_enabled_state: - self.setEnabled(other.isEnabled()) - - def isEnabled(self): - return self._enabled - - def setEnabled(self, enabled): - self._enabled = enabled - - def isVisible(self): - return self.line_style != "" or self.marker != "" - - @property - def name(self): - return self._name - - @name.setter - def name(self, name): - self._name = name - - @property - def color(self): - return self._color - - @color.setter - def color(self, color): - self._color = color - - @property - def alpha(self): - return self._alpha - - @alpha.setter - def alpha(self, alpha): - if alpha > 1.0: - alpha = 1.0 - if alpha < 0.0: - alpha = 0.0 - self._alpha = alpha - - @property - def marker(self): - return self._marker if self._marker is not None else "" - - @marker.setter - def marker(self, marker): - self._marker = marker - - @property - def line_style(self): - return self._line_style if self._line_style is not None else "" - - @line_style.setter - def line_style(self, line_style): - self._line_style = line_style - - @property - def width(self): - return self._width - - @width.setter - def width(self, width): - if width < 0.0: - width = 0.0 - self._width = width - - @property - def size(self): - return self._size - - @size.setter - def size(self, size): - if size < 0.0: - size = 0.0 - self._size = size - - - def __str__(self): - return "%s c:%s a:%f ls:%s m:%s w:%f s:%f enabled:%s copy:%s" % (self.name, self.color, self.alpha, self.line_style, self.marker, self.width, self.size, self.isEnabled(), self._is_copy) - - def __eq__(self, other): - equalness = self.alpha == other.alpha - equalness = equalness and self.marker == other.marker - equalness = equalness and self.line_style == other.line_style - equalness = equalness and self.width == other.width - equalness = equalness and self.color == other.color - equalness = equalness and self.size == other.size - equalness = equalness and self.isEnabled() == other.isEnabled() - - return equalness diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/CMakeLists.txt deleted file mode 100644 index 24aa63b774..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - ccsp.py - distribution.py - ensemble.py - gaussian_kde.py - histogram.py - history.py - observations.py - plot_tools.py - refcase.py - statistics.py -) - -add_python_package("python.ert_gui.plottery.plots" ${PYTHON_INSTALL_PREFIX}/ert_gui/plottery/plots "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/__init__.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/__init__.py deleted file mode 100644 index 64f84b1e9a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -import os -import matplotlib - -from .histogram import plotHistogram -from .gaussian_kde import plotGaussianKDE - -from .refcase import plotRefcase -from .history import plotHistory -from .observations import plotObservations - -from .ensemble import plotEnsemble -from .statistics import plotStatistics -from .distribution import plotDistribution -from .ccsp import plotCrossCaseStatistics diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/ccsp.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/ccsp.py deleted file mode 100644 index 52679222d7..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/ccsp.py +++ /dev/null @@ -1,221 +0,0 @@ -from matplotlib.patches import Rectangle -from matplotlib.lines import Line2D -from .plot_tools import PlotTools -import pandas as pd - -def plotCrossCaseStatistics(plot_context): - """ @type plot_context: ert_gui.plottery.PlotContext """ - ert = plot_context.ert() - key = plot_context.key() - config = plot_context.plotConfig() - axes = plot_context.figure().add_subplot(111) - """:type: matplotlib.axes.Axes """ - - plot_context.deactivateDateSupport() - - plot_context.y_axis = plot_context.VALUE_AXIS - - if key.startswith("LOG10_"): - key = key[6:] - axes.set_yscale("log") - - case_list = plot_context.cases() - case_indexes = [] - ccs = { - "index": [], - "mean": {}, - "min": {}, - "max": {}, - "std": {}, - "p10": {}, - "p33": {}, - "p50": {}, - "p67": {}, - "p90": {} - } - for case_index, case in enumerate(case_list): - case_indexes.append(case_index) - data = plot_context.dataGatherer().gatherData(ert, case, key) - std_dev_factor = config.getStandardDeviationFactor() - - if not data.empty: - data = _assertNumeric(data) - if not data is None: - ccs["index"].append(case_index) - ccs["mean"][case_index] = data.mean() - ccs["min"][case_index] = data.min() - ccs["max"][case_index] = data.max() - ccs["std"][case_index] = data.std() * std_dev_factor - ccs["p10"][case_index] = data.quantile(0.1) - ccs["p33"][case_index] = data.quantile(0.33) - ccs["p50"][case_index] = data.quantile(0.5) - ccs["p67"][case_index] = data.quantile(0.67) - ccs["p90"][case_index] = data.quantile(0.9) - - _plotCrossCaseStatistics(axes, config, ccs, case_index) - config.nextColor() - - if config.isDistributionLineEnabled() and len(ccs["index"]) > 1: - _plotConnectionLines(axes, config, ccs) - - _addStatisticsLegends(config) - - axes.set_xticks([-1] + case_indexes + [len(case_indexes)]) - - rotation = 0 - if len(case_list) > 3: - rotation = 30 - - axes.set_xticklabels([""] + case_list + [""], rotation=rotation) - - PlotTools.finalizePlot(plot_context, axes, default_x_label="Case", default_y_label="Value") - - -def _addStatisticsLegends(plot_config): - _addStatisticsLegend(plot_config, "mean") - _addStatisticsLegend(plot_config, "p50") - _addStatisticsLegend(plot_config, "min-max", 0.2) - _addStatisticsLegend(plot_config, "p10-p90", 0.4) - _addStatisticsLegend(plot_config, "std", 0.4) - _addStatisticsLegend(plot_config, "p33-p67", 0.6) - - -def _addStatisticsLegend(plot_config, style_name, alpha_multiplier=1.0): - style = plot_config.getStatisticsStyle(style_name) - if style.isVisible(): - if style.line_style == "#": - rectangle = Rectangle((0, 0), 1, 1, color='black', alpha=style.alpha * alpha_multiplier) # creates rectangle patch for legend use. - plot_config.addLegendItem(style.name, rectangle) - else: - line = Line2D([], [], color='black', marker=style.marker, linestyle=style.line_style, linewidth=style.width, alpha=style.alpha) - plot_config.addLegendItem(style.name, line) - - -def _assertNumeric(data): - if data.dtype == "object": - try: - data = pd.to_numeric(data, errors='coerce') - except AttributeError: - data = data.convert_objects(convert_numeric=True) - - if data.dtype == "object": - data = None - return data - - -def _plotCrossCaseStatistics(axes, plot_config, data, index): - """ - @type axes: matplotlib.axes.Axes - @type plot_config: PlotConfig - @type data: DataFrame - @type index: int - """ - - axes.set_xlabel(plot_config.xLabel()) - axes.set_ylabel(plot_config.yLabel()) - - style = plot_config.getStatisticsStyle("mean") - if style.isVisible(): - axes.plot([index], data["mean"][index], alpha=style.alpha, linestyle="", color=style.color, marker=style.marker, markersize=style.size) - - style = plot_config.getStatisticsStyle("p50") - if style.isVisible(): - axes.plot([index], data["p50"][index], alpha=style.alpha, linestyle="", color=style.color, marker=style.marker, markersize=style.size) - - style = plot_config.getStatisticsStyle("std") - if style.isVisible(): - axes.plot([index], data["mean"][index] + data["std"][index], alpha=style.alpha, linestyle="", color=style.color, marker=style.marker, markersize=style.size) - axes.plot([index], data["mean"][index] - data["std"][index], alpha=style.alpha, linestyle="", color=style.color, marker=style.marker, markersize=style.size) - - style = plot_config.getStatisticsStyle("min-max") - if style.isVisible(): - axes.plot([index], data["min"][index], alpha=style.alpha, linestyle="", color=style.color, marker=style.marker, markersize=style.size) - axes.plot([index], data["max"][index], alpha=style.alpha, linestyle="", color=style.color, marker=style.marker, markersize=style.size) - - style = plot_config.getStatisticsStyle("p10-p90") - if style.isVisible(): - axes.plot([index], data["p10"][index], alpha=style.alpha, linestyle="", color=style.color, marker=style.marker, markersize=style.size) - axes.plot([index], data["p90"][index], alpha=style.alpha, linestyle="", color=style.color, marker=style.marker, markersize=style.size) - - style = plot_config.getStatisticsStyle("p33-p67") - if style.isVisible(): - axes.plot([index], data["p33"][index], alpha=style.alpha, linestyle="", color=style.color, marker=style.marker, markersize=style.size) - axes.plot([index], data["p67"][index], alpha=style.alpha, linestyle="", color=style.color, marker=style.marker, markersize=style.size) - - -def _plotConnectionLines(axes, plot_config, ccs): - """ - @type axes: matplotlib.axes.Axes - @type plot_config: PlotConfig - @type ccs: dict[str, dict[int, float]] - """ - line_style = plot_config.distributionLineStyle() - index_list = ccs["index"] - """ :type: list[int] """ - for index in range(len(index_list) - 1): - from_index = index_list[index] - to_index = index_list[index + 1] - - x = [from_index, to_index] - - style = plot_config.getStatisticsStyle("mean") - if style.isVisible(): - y = [ccs["mean"][from_index], ccs["mean"][to_index]] - axes.plot(x, y, alpha=line_style.alpha, linestyle=style.line_style, color=line_style.color, linewidth=style.width) - - style = plot_config.getStatisticsStyle("p50") - if style.isVisible(): - y = [ccs["p50"][from_index], ccs["p50"][to_index]] - axes.plot(x, y, alpha=line_style.alpha, linestyle=style.line_style, color=line_style.color, linewidth=style.width) - - style = plot_config.getStatisticsStyle("std") - if style.isVisible(): - mean = [ccs["mean"][from_index], ccs["mean"][to_index]] - std = [ccs["std"][from_index], ccs["std"][to_index]] - - y_1 = [mean[0] + std[0], mean[1] + std[1]] - y_2 = [mean[0] - std[0], mean[1] - std[1]] - - linestyle = style.line_style - if linestyle == "#": - linestyle = "" - - axes.plot(x, y_1, alpha=style.alpha, linestyle=linestyle, color=line_style.color, linewidth=style.width) - axes.plot(x, y_2, alpha=style.alpha, linestyle=linestyle, color=line_style.color, linewidth=style.width) - - style = plot_config.getStatisticsStyle("min-max") - if style.isVisible(): - y_1 = [ccs["min"][from_index], ccs["min"][to_index]] - y_2 = [ccs["max"][from_index], ccs["max"][to_index]] - - linestyle = style.line_style - if linestyle == "#": - linestyle = "" - - axes.plot(x, y_1, alpha=style.alpha, linestyle=linestyle, color=line_style.color, linewidth=style.width) - axes.plot(x, y_2, alpha=style.alpha, linestyle=linestyle, color=line_style.color, linewidth=style.width) - - style = plot_config.getStatisticsStyle("p10-p90") - if style.isVisible(): - y_1 = [ccs["p10"][from_index], ccs["p10"][to_index]] - y_2 = [ccs["p90"][from_index], ccs["p90"][to_index]] - - linestyle = style.line_style - if linestyle == "#": - linestyle = "" - - axes.plot(x, y_1, alpha=style.alpha, linestyle=linestyle, color=line_style.color, linewidth=style.width) - axes.plot(x, y_2, alpha=style.alpha, linestyle=linestyle, color=line_style.color, linewidth=style.width) - - style = plot_config.getStatisticsStyle("p33-p67") - if style.isVisible(): - y_1 = [ccs["p33"][from_index], ccs["p33"][to_index]] - y_2 = [ccs["p67"][from_index], ccs["p67"][to_index]] - - linestyle = style.line_style - if linestyle == "#": - linestyle = "" - - axes.plot(x, y_1, alpha=style.alpha, linestyle=linestyle, color=line_style.color, linewidth=style.width) - axes.plot(x, y_2, alpha=style.alpha, linestyle=linestyle, color=line_style.color, linewidth=style.width) - diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/distribution.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/distribution.py deleted file mode 100644 index af0b546a1d..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/distribution.py +++ /dev/null @@ -1,77 +0,0 @@ -from .plot_tools import PlotTools -import pandas as pd - -def plotDistribution(plot_context): - """ @type plot_context: ert_gui.plottery.PlotContext """ - ert = plot_context.ert() - key = plot_context.key() - config = plot_context.plotConfig() - axes = plot_context.figure().add_subplot(111) - """:type: matplotlib.axes.Axes """ - - plot_context.deactivateDateSupport() - - plot_context.y_axis = plot_context.VALUE_AXIS - - if key.startswith("LOG10_"): - key = key[6:] - axes.set_yscale("log") - - case_list = plot_context.cases() - case_indexes = [] - previous_data = None - for case_index, case in enumerate(case_list): - case_indexes.append(case_index) - data = plot_context.dataGatherer().gatherData(ert, case, key) - - if not data.empty: - _plotDistribution(axes, config, data, case, case_index, previous_data) - config.nextColor() - - previous_data = data - - axes.set_xticks([-1] + case_indexes + [len(case_indexes)]) - - rotation = 0 - if len(case_list) > 3: - rotation = 30 - - axes.set_xticklabels([""] + case_list + [""], rotation=rotation) - - config.setLegendEnabled(False) - - PlotTools.finalizePlot(plot_context, axes, default_x_label="Case", default_y_label="Value") - - -def _plotDistribution(axes, plot_config, data, label, index, previous_data): - """ - @type axes: matplotlib.axes.Axes - @type plot_config: PlotConfig - @type data: DataFrame - @type label: Str - """ - - axes.set_xlabel(plot_config.xLabel()) - axes.set_ylabel(plot_config.yLabel()) - - style = plot_config.distributionStyle() - - if data.dtype == "object": - try: - data = pd.to_numeric(data, errors='coerce') - except AttributeError: - data = data.convert_objects(convert_numeric=True) - - if data.dtype == "object": - dots = [] - else: - dots = axes.plot([index] * len(data), data, color=style.color, alpha=style.alpha, marker=style.marker, linestyle=style.line_style, markersize=style.size) - - if plot_config.isDistributionLineEnabled() and previous_data is not None: - line_style = plot_config.distributionLineStyle() - x = [index - 1, index] - y = [previous_data, data] - lines = axes.plot(x, y, color=line_style.color, alpha=line_style.alpha, linestyle=line_style.line_style, linewidth=line_style.width) - - if len(dots) > 0: - plot_config.addLegendItem(label, dots[0]) diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/ensemble.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/ensemble.py deleted file mode 100644 index 333a3a2434..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/ensemble.py +++ /dev/null @@ -1,56 +0,0 @@ -from .refcase import plotRefcase -from .history import plotHistory -from .observations import plotObservations -from .plot_tools import PlotTools - -def plotEnsemble(plot_context): - """ - @type plot_context: ert_gui.plottery.PlotContext - """ - ert = plot_context.ert() - key = plot_context.key() - config = plot_context.plotConfig() - """:type: ert_gui.plottery.PlotConfig """ - axes = plot_context.figure().add_subplot(111) - """:type: matplotlib.axes.Axes """ - - case_list = plot_context.cases() - - plot_context.y_axis = plot_context.VALUE_AXIS - plot_context.x_axis = plot_context.DATE_AXIS - - for case in case_list: - data = plot_context.dataGatherer().gatherData(ert, case, key) - if not data.empty: - if not data.index.is_all_dates: - plot_context.deactivateDateSupport() - plot_context.x_axis = plot_context.INDEX_AXIS - - _plotLines(axes, config, data, case, plot_context.isDateSupportActive()) - config.nextColor() - - plotRefcase(plot_context, axes) - plotObservations(plot_context, axes) - plotHistory(plot_context, axes) - - default_x_label = "Date" if plot_context.isDateSupportActive() else "Index" - PlotTools.finalizePlot(plot_context, axes, default_x_label=default_x_label, default_y_label="Value") - - -def _plotLines(axes, plot_config, data, ensemble_label, is_date_supported): - """ - @type axes: matplotlib.axes.Axes - @type plot_config: ert_gui.plottery.PlotConfig - @type data: pandas.DataFrame - @type ensemble_label: Str - """ - - style = plot_config.defaultStyle() - - if is_date_supported: - lines = axes.plot_date(x=data.index.values, y=data, color=style.color, alpha=style.alpha, marker=style.marker, linestyle=style.line_style, linewidth=style.width, markersize=style.size) - else: - lines = axes.plot(data.index.values, data, color=style.color, alpha=style.alpha, marker=style.marker, linestyle=style.line_style, linewidth=style.width, markersize=style.size) - - if len(lines) > 0: - plot_config.addLegendItem(ensemble_label, lines[0]) diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/gaussian_kde.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/gaussian_kde.py deleted file mode 100644 index 5e6c6b7124..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/gaussian_kde.py +++ /dev/null @@ -1,63 +0,0 @@ -import numpy -from scipy.stats import gaussian_kde -from .plot_tools import PlotTools -import pandas as pd - - -def plotGaussianKDE(plot_context): - """ - @type plot_context: ert_gui.plottery.PlotContext - """ - ert = plot_context.ert() - key = plot_context.key() - config = plot_context.plotConfig() - axes = plot_context.figure().add_subplot(111) - """:type: matplotlib.axes.Axes """ - - plot_context.deactivateDateSupport() - plot_context.x_axis = plot_context.VALUE_AXIS - plot_context.y_axis = plot_context.DENSITY_AXIS - - if key.startswith("LOG10_"): - key = key[6:] - axes.set_xscale("log") - - case_list = plot_context.cases() - for case in case_list: - data = plot_context.dataGatherer().gatherData(ert, case, key) - - if not data.empty and data.nunique() > 1: - _plotGaussianKDE(axes, config, data, case) - config.nextColor() - - PlotTools.finalizePlot(plot_context, axes, default_x_label="Value", default_y_label="Density") - - -def _plotGaussianKDE(axes, plot_config, data, label): - """ - @type axes: matplotlib.axes.Axes - @type plot_config: PlotConfig - @type data: DataFrame - @type label: Str - """ - - style = plot_config.histogramStyle() - - if data.dtype == "object": - try: - data = pd.to_numeric(data, errors='coerce') - except AttributeError: - data = data.convert_objects(convert_numeric=True) - - if data.dtype == "object": - pass - else: - sample_range = data.max() - data.min() - indexes = numpy.linspace(data.min() - 0.5 * sample_range, data.max() + 0.5 * sample_range, 1000) - gkde = gaussian_kde(data.values) - evaluated_gkde = gkde.evaluate(indexes) - - lines = axes.plot(indexes, evaluated_gkde, linewidth=style.width, color=style.color, alpha=style.alpha) - - if len(lines) > 0: - plot_config.addLegendItem(label, lines[0]) \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/histogram.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/histogram.py deleted file mode 100644 index eeb308c10a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/histogram.py +++ /dev/null @@ -1,183 +0,0 @@ -from math import sqrt, ceil, floor, log10 -from matplotlib.patches import Rectangle -import numpy -from .plot_tools import PlotTools -import pandas as pd - -def plotHistogram(plot_context): - """ @type plot_context: ert_gui.plottery.PlotContext """ - ert = plot_context.ert() - key = plot_context.key() - config = plot_context.plotConfig() - - case_list = plot_context.cases() - case_count = len(case_list) - - plot_context.x_axis = plot_context.VALUE_AXIS - plot_context.Y_axis = plot_context.COUNT_AXIS - - if config.xLabel() is None: - config.setXLabel("Value") - - if config.yLabel() is None: - config.setYLabel("Count") - - use_log_scale = False - if key.startswith("LOG10_"): - key = key[6:] - use_log_scale = True - - data = {} - minimum = None - maximum = None - categories = set() - max_element_count = 0 - categorical = False - for case in case_list: - data[case] = plot_context.dataGatherer().gatherData(ert, case, key) - - if data[case].dtype == "object": - try: - data[case] = pd.to_numeric(data[case], errors='ignore') - except AttributeError: - data[case] = data[case].convert_objects(convert_numeric=True) - - if data[case].dtype == "object": - categorical = True - - if categorical: - categories = categories.union(set(data[case].unique())) - else: - if minimum is None: - minimum = data[case].min() - else: - minimum = min(minimum, data[case].min()) - - if maximum is None: - maximum = data[case].max() - else: - maximum = max(maximum, data[case].max()) - - max_element_count = max(max_element_count, len(data[case].index)) - - categories = sorted(categories) - bin_count = int(ceil(sqrt(max_element_count))) - - axes = {} - """:type: dict of (str, matplotlib.axes.Axes) """ - for index, case in enumerate(case_list): - axes[case] = plot_context.figure().add_subplot(case_count, 1, index + 1) - - axes[case].set_title("%s (%s)" % (config.title(), case)) - - if use_log_scale: - axes[case].set_xscale("log") - - if not data[case].empty: - if categorical: - _plotCategoricalHistogram(axes[case], config, data[case], case, categories) - else: - _plotHistogram(axes[case], config, data[case], case, bin_count, use_log_scale, minimum, maximum) - - config.nextColor() - PlotTools.showGrid(axes[case], plot_context) - - min_count = 0 - max_count = max([subplot.get_ylim()[1] for subplot in axes.values()]) - - custom_limits = plot_context.plotConfig().limits - - if custom_limits.count_maximum is not None: - max_count = custom_limits.count_maximum - - if custom_limits.count_minimum is not None: - min_count = custom_limits.count_minimum - - for subplot in axes.values(): - subplot.set_ylim(min_count, max_count) - subplot.set_xlim(custom_limits.value_minimum, custom_limits.value_maximum) - - -def _plotCategoricalHistogram(axes, plot_config, data, label, categories): - """ - @type axes: matplotlib.axes.Axes - @type plot_config: PlotConfig - @type data: DataFrame - @type label: str - @type categories: list of str - """ - - axes.set_xlabel(plot_config.xLabel()) - axes.set_ylabel(plot_config.yLabel()) - - style = plot_config.histogramStyle() - - counts = data.value_counts() - freq = [counts[category] if category in counts else 0 for category in categories] - pos = numpy.arange(len(categories)) - width = 1.0 - axes.set_xticks(pos + (width / 2.0)) - axes.set_xticklabels(categories) - - axes.bar(pos, freq, alpha=style.alpha, color=style.color, width=width) - - rectangle = Rectangle((0, 0), 1, 1, color=style.color) # creates rectangle patch for legend use. - plot_config.addLegendItem(label, rectangle) - - -def _plotHistogram(axes, plot_config, data, label, bin_count, use_log_scale=False, minimum=None, maximum=None): - """ - @type axes: matplotlib.axes.Axes - @type plot_config: PlotConfig - @type data: DataFrame - @type label: str - """ - - axes.set_xlabel(plot_config.xLabel()) - axes.set_ylabel(plot_config.yLabel()) - - style = plot_config.histogramStyle() - - if minimum is not None and maximum is not None: - if use_log_scale: - bins = _histogramLogBins(bin_count, minimum, maximum) - else: - bins = numpy.linspace(minimum, maximum, bin_count) - else: - bins = bin_count - - axes.hist(data.values, alpha=style.alpha, bins=bins, color=style.color) - - if minimum == maximum: - minimum -= 0.5 - maximum += 0.5 - - axes.set_xlim(minimum, maximum) - - rectangle = Rectangle((0, 0), 1, 1, color=style.color) # creates rectangle patch for legend use.' - plot_config.addLegendItem(label, rectangle) - - - -def _histogramLogBins(bin_count, minimum=None, maximum=None): - """ - @type data: pandas.DataFrame - @rtype: int - """ - minimum = log10(float(minimum)) - maximum = log10(float(maximum)) - - min_value = int(floor(minimum)) - max_value = int(ceil(maximum)) - - log_bin_count = max_value - min_value - - if log_bin_count < bin_count: - next_bin_count = log_bin_count * 2 - - if bin_count - log_bin_count > next_bin_count - bin_count: - log_bin_count = next_bin_count - else: - log_bin_count = bin_count - - return 10 ** numpy.linspace(minimum, maximum, log_bin_count) diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/history.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/history.py deleted file mode 100644 index dd1d8d7768..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/history.py +++ /dev/null @@ -1,33 +0,0 @@ -def plotHistory(plot_context, axes): - ert = plot_context.ert() - key = plot_context.key() - - if len(plot_context.cases()) == 0: - case = None - else: - case = plot_context.cases()[0] - - config = plot_context.plotConfig() - data_gatherer = plot_context.dataGatherer() - - if config.isHistoryEnabled() and data_gatherer.hasHistoryGatherFunction(): - history_data = data_gatherer.gatherHistoryData(ert, case, key) - - if not history_data.empty: - _plotHistory(axes, config, history_data) - - -def _plotHistory(axes, plot_config, data): - """ - @type axes: matplotlib.axes.Axes - @type plot_config: PlotConfig - @type data: DataFrame - """ - - style = plot_config.historyStyle() - - lines = axes.plot_date(x=data.index.values, y=data, color=style.color, alpha=style.alpha, marker=style.marker, linestyle=style.line_style, - linewidth=style.width, markersize=style.size) - - if len(lines) > 0 and style.isVisible(): - plot_config.addLegendItem("History", lines[0]) diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/observations.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/observations.py deleted file mode 100644 index 68d050b68a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/observations.py +++ /dev/null @@ -1,54 +0,0 @@ -import math - -def plotObservations(plot_context, axes): - ert = plot_context.ert() - key = plot_context.key() - config = plot_context.plotConfig() - case_list = plot_context.cases() - data_gatherer = plot_context.dataGatherer() - - if config.isObservationsEnabled() and data_gatherer.hasObservationGatherFunction(): - if len(case_list) > 0: - observation_data = data_gatherer.gatherObservationData(ert, case_list[0], key) - - if not observation_data.empty: - _plotObservations(axes, config, observation_data, value_column=key) - - - -def _plotObservations(axes, plot_config, data, value_column): - """ - Observations are always plotted on top. z-order set to 1000 - - Since it is not possible to apply different linestyles to the errorbar, the line_style / fmt is used to toggle - visibility of the solid errorbar, by using the elinewidth parameter. - - @type axes: matplotlib.axes.Axes - @type plot_config: PlotConfig - @type data: DataFrame - @type value_column: Str - """ - - style = plot_config.observationsStyle() - - # adjusting the top and bottom bar, according to the line width/thickness - def cap_size(line_with): - return 0 if line_with == 0 else math.log(line_with, 1.2)+3 - - # line style set to 'off' toggles errorbar visibility - if style.line_style == '': - style.width = 0 - - errorbars = axes.errorbar(x=data.index.values, y=data[value_column].values, - yerr=data["STD_%s" % value_column].values, - fmt=style.line_style, ecolor=style.color, color=style.color, - capsize=cap_size(style.width), - capthick=style.width, #same as width/thickness on error line - alpha=style.alpha, - linewidth=0, - marker=style.marker, - ms=style.size, - elinewidth=style.width, zorder=1000) - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/plot_tools.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/plot_tools.py deleted file mode 100644 index 7e2a3b93a2..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/plot_tools.py +++ /dev/null @@ -1,109 +0,0 @@ -class PlotTools(object): - @staticmethod - def showGrid(axes, plot_context): - config = plot_context.plotConfig() - if config.isGridEnabled(): - axes.grid() - - - @staticmethod - def showLegend(axes, plot_context): - config = plot_context.plotConfig() - if config.isLegendEnabled() and len(config.legendItems()) > 0: - axes.legend(config.legendItems(), config.legendLabels(), numpoints=1) - - - @staticmethod - def _getXAxisLimits(plot_context): - """ @type plot_context: ert_gui.plottery.PlotContext """ - limits = plot_context.plotConfig().limits - axis_name = plot_context.x_axis - - if axis_name == plot_context.VALUE_AXIS: - return limits.value_limits - elif axis_name == plot_context.COUNT_AXIS: - # return limits.count_limits - return None # Histogram takes care of itself - elif axis_name == plot_context.DATE_AXIS: - return limits.date_limits - elif axis_name == plot_context.DENSITY_AXIS: - return limits.density_limits - elif axis_name == plot_context.DEPTH_AXIS: - return limits.depth_limits - elif axis_name == plot_context.INDEX_AXIS: - return limits.index_limits - - return None # No limits set - - @staticmethod - def _getYAxisLimits(plot_context): - """ @type plot_context: ert_gui.plottery.PlotContext """ - limits = plot_context.plotConfig().limits - axis_name = plot_context.y_axis - - if axis_name == plot_context.VALUE_AXIS: - return limits.value_limits - elif axis_name == plot_context.COUNT_AXIS: - # return limits.count_limits - return None # Histogram takes care of itself - elif axis_name == plot_context.DATE_AXIS: - return limits.date_limits - elif axis_name == plot_context.DENSITY_AXIS: - return limits.density_limits - elif axis_name == plot_context.DEPTH_AXIS: - return limits.depth_limits - elif axis_name == plot_context.INDEX_AXIS: - return limits.index_limits - - return None # No limits set - - - - @staticmethod - def finalizePlot(plot_context, axes, default_x_label="Unnamed", default_y_label="Unnamed"): - """ - @type plot_context: ert_gui.plottery.PlotContext - @type axes: - @type default_x_label: - @type default_y_label: - """ - - PlotTools.showLegend(axes, plot_context) - PlotTools.showGrid(axes, plot_context) - - PlotTools.__setupLabels(plot_context, default_x_label, default_y_label) - - plot_config = plot_context.plotConfig() - axes.set_xlabel(plot_config.xLabel()) - axes.set_ylabel(plot_config.yLabel()) - - x_axis_limits = PlotTools._getXAxisLimits(plot_context) - if x_axis_limits is not None: - axes.set_xlim(*x_axis_limits) - - y_axis_limits = PlotTools._getYAxisLimits(plot_context) - if y_axis_limits is not None: - axes.set_ylim(*y_axis_limits) - - axes.set_title(plot_config.title()) - - if plot_context.isDateSupportActive(): - plot_context.figure().autofmt_xdate() - - - @staticmethod - def __setupLabels(plot_context, default_x_label, default_y_label): - ert = plot_context.ert() - key = plot_context.key() - config = plot_context.plotConfig() - - if config.xLabel() is None: - config.setXLabel(default_x_label) - - if config.yLabel() is None: - config.setYLabel(default_y_label) - - if ert.eclConfig().hasRefcase() and key in ert.eclConfig().getRefcase(): - unit = ert.eclConfig().getRefcase().unit(key) - if unit != "": - config.setYLabel(unit) \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/refcase.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/refcase.py deleted file mode 100644 index 4a0836bf1b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/refcase.py +++ /dev/null @@ -1,26 +0,0 @@ -def plotRefcase(plot_context, axes): - ert = plot_context.ert() - key = plot_context.key() - config = plot_context.plotConfig() - data_gatherer = plot_context.dataGatherer() - - if config.isRefcaseEnabled() and data_gatherer.hasRefcaseGatherFunction(): - refcase_data = data_gatherer.gatherRefcaseData(ert, key) - - if not refcase_data.empty: - _plotRefcase(axes, config, refcase_data) - - -def _plotRefcase(axes, plot_config, data): - """ - @type axes: matplotlib.axes.Axes - @type plot_config: PlotConfig - @type data: DataFrame - """ - - style = plot_config.refcaseStyle() - - lines = axes.plot_date(x=data.index.values, y=data, color=style.color, alpha=style.alpha, marker=style.marker, linestyle=style.line_style, linewidth=style.width, markersize=style.size) - - if len(lines) > 0 and style.isVisible(): - plot_config.addLegendItem("Refcase", lines[0]) \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/statistics.py b/ThirdParty/Ert/python/python/ert_gui/plottery/plots/statistics.py deleted file mode 100644 index 79b6f99067..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/plottery/plots/statistics.py +++ /dev/null @@ -1,117 +0,0 @@ -from matplotlib.patches import Rectangle -from matplotlib.lines import Line2D -from pandas import DataFrame -from .refcase import plotRefcase -from .observations import plotObservations -from .plot_tools import PlotTools - - -def plotStatistics(plot_context): - """ @type plot_context: ert_gui.plottery.PlotContext """ - ert = plot_context.ert() - key = plot_context.key() - config = plot_context.plotConfig() - """:type: ert_gui.plotter.PlotConfig """ - axes = plot_context.figure().add_subplot(111) - """:type: matplotlib.axes.Axes """ - - plot_context.y_axis = plot_context.VALUE_AXIS - plot_context.x_axis = plot_context.DATE_AXIS - - case_list = plot_context.cases() - for case in case_list: - data = plot_context.dataGatherer().gatherData(ert, case, key) - - if not data.empty: - if not data.index.is_all_dates: - plot_context.deactivateDateSupport() - plot_context.x_axis = plot_context.INDEX_AXIS - - style = config.getStatisticsStyle("mean") - rectangle = Rectangle((0, 0), 1, 1, color=style.color, alpha=0.8) # creates rectangle patch for legend use. - config.addLegendItem(case, rectangle) - - statistics_data = DataFrame() - std_dev_factor = config.getStandardDeviationFactor() - - statistics_data["Minimum"] = data.min(axis=1) - statistics_data["Maximum"] = data.max(axis=1) - statistics_data["Mean"] = data.mean(axis=1) - statistics_data["p10"] = data.quantile(0.1, axis=1) - statistics_data["p33"] = data.quantile(0.33, axis=1) - statistics_data["p50"] = data.quantile(0.50, axis=1) - statistics_data["p67"] = data.quantile(0.67, axis=1) - statistics_data["p90"] = data.quantile(0.90, axis=1) - std = data.std(axis=1) * std_dev_factor - statistics_data["std+"] = statistics_data["Mean"] + std - statistics_data["std-"] = statistics_data["Mean"] - std - - _plotPercentiles(axes, config, statistics_data, case) - config.nextColor() - - _addStatisticsLegends(plot_config=config) - - plotRefcase(plot_context, axes) - plotObservations(plot_context, axes) - - default_x_label = "Date" if plot_context.isDateSupportActive() else "Index" - PlotTools.finalizePlot(plot_context, axes, default_x_label=default_x_label, default_y_label="Value") - -def _addStatisticsLegends(plot_config): - _addStatisticsLegend(plot_config, "mean") - _addStatisticsLegend(plot_config, "p50") - _addStatisticsLegend(plot_config, "min-max", 0.2) - _addStatisticsLegend(plot_config, "p10-p90", 0.4) - _addStatisticsLegend(plot_config, "std", 0.4) - _addStatisticsLegend(plot_config, "p33-p67", 0.6) - -def _addStatisticsLegend(plot_config, style_name, alpha_multiplier=1.0): - style = plot_config.getStatisticsStyle(style_name) - if style.isVisible(): - if style.line_style == "#": - rectangle = Rectangle((0, 0), 1, 1, color='black', alpha=style.alpha * alpha_multiplier) # creates rectangle patch for legend use. - plot_config.addLegendItem(style.name, rectangle) - else: - line = Line2D([], [], color='black', marker=style.marker, linestyle=style.line_style, linewidth=style.width, alpha=style.alpha, markersize=style.size) - plot_config.addLegendItem(style.name, line) - - -def _plotPercentiles(axes, plot_config, data, ensemble_label): - """ - @type axes: matplotlib.axes.Axes - @type plot_config: ert_gui.plottery.PlotConfig - @type data: DataFrame - @type ensemble_label: Str - """ - style = plot_config.getStatisticsStyle("mean") - if style.isVisible(): - axes.plot(data.index.values, data["Mean"].values, alpha=style.alpha, linestyle=style.line_style, color=style.color, marker=style.marker, linewidth=style.width, markersize=style.size) - - style = plot_config.getStatisticsStyle("p50") - if style.isVisible(): - axes.plot(data.index.values, data["p50"].values, alpha=style.alpha, linestyle=style.line_style, color=style.color, marker=style.marker, linewidth=style.width, markersize=style.size) - - style = plot_config.getStatisticsStyle("std") - _plotPercentile(axes, style, data.index.values, data["std+"].values, data["std-"].values, 0.5) - - style = plot_config.getStatisticsStyle("min-max") - _plotPercentile(axes, style, data.index.values, data["Maximum"].values, data["Minimum"].values, 0.5) - - style = plot_config.getStatisticsStyle("p10-p90") - _plotPercentile(axes, style, data.index.values, data["p90"].values, data["p10"].values, 0.5) - - style = plot_config.getStatisticsStyle("p33-p67") - _plotPercentile(axes, style, data.index.values, data["p67"].values, data["p33"].values, 0.5) - - -def _plotPercentile(axes, style, index_values, top_line_data, bottom_line_data, alpha_multiplier): - alpha = style.alpha - line_style = style.line_style - color = style.color - marker = style.marker - - if line_style == "#": - axes.fill_between(index_values, bottom_line_data, top_line_data, alpha=alpha * alpha_multiplier, color=color) - elif style.isVisible(): - axes.plot(index_values, bottom_line_data, alpha=alpha, linestyle=line_style, color=color, marker=marker, linewidth=style.width, markersize=style.size) - axes.plot(index_values, top_line_data, alpha=alpha, linestyle=line_style, color=color, marker=marker, linewidth=style.width, markersize=style.size) diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/shell/CMakeLists.txt deleted file mode 100644 index c825821338..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - analysis_module.py - cases.py - custom_kw_keys.py - debug.py - export.py - ertshell.py - ert_shell_collection.py - gen_data_keys.py - gen_kw_keys.py - observations.py - plot_settings.py - plugins.py - results.py - ert_shell_context.py - server.py - shell_plot.py - simulations.py - smoother.py - storage.py - summary_keys.py - workflows.py -) - -add_python_package("python.ert_gui.shell" ${PYTHON_INSTALL_PREFIX}/ert_gui/shell "${PYTHON_SOURCES}" True) - -add_subdirectory(libshell) diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/__init__.py b/ThirdParty/Ert/python/python/ert_gui/shell/__init__.py deleted file mode 100644 index 52fb97e60b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -from .ert_shell_context import ErtShellContext - -def isConfigLoaded(shell_context, verbose=True): - """ @rtype: bool """ - if shell_context.ert() is None: - if verbose: - print("Error: A config file has not been loaded!") - return False - return True - -def assertConfigLoaded(func): - def wrapper(self, *args, **kwargs): - # prefixes should be either do_ or complete_ - if func.__name__.startswith("complete_"): - result = [] - verbose = False - else: - result = False - verbose = True - - if isConfigLoaded(self.shellContext(), verbose=verbose): - result = func(self, *args, **kwargs) - - return result - - wrapper.__doc__ = func.__doc__ - wrapper.__name__ = func.__name__ - - return wrapper - -from .ert_shell_collection import ErtShellCollection -from .plot_settings import PlotSettings -from .shell_plot import ShellPlot -from .ertshell import ErtShell diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/analysis_module.py b/ThirdParty/Ert/python/python/ert_gui/shell/analysis_module.py deleted file mode 100644 index 26b839c28b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/analysis_module.py +++ /dev/null @@ -1,119 +0,0 @@ -from ert_gui.shell import assertConfigLoaded, ErtShellCollection -from ert_gui.shell.libshell import extractFullArgument, autoCompleteListWithSeparator, matchItems, splitArguments - - -class AnalysisModule(ErtShellCollection): - def __init__(self, parent): - super(AnalysisModule, self).__init__("analysis_module", parent) - - self.addShellProperty(name="active_module", - getter=AnalysisModule.getAnalysisModule, - setter=AnalysisModule.setAnalysisModule, - validator=AnalysisModule.validateAnalysisModule, - completer=AnalysisModule.completeAnalysisModule, - help_arguments="[analysis_module]", - help_message="Show or set the current analysis module.", - pretty_attribute="Active Module") - - self.addShellFunction(name="list", - function=AnalysisModule.list, - help_message="Shows a list of the available analysis modules.") - - self.addShellFunction(name="variables", - function=AnalysisModule.variables, - help_message="Shows a list of the available options for the current analysis module.") - - self.addShellFunction(name="set", - function=AnalysisModule.set, - completer=AnalysisModule.completeSet, - help_arguments=" ", - help_message="Set a variable value.") - - - @assertConfigLoaded - def getAnalysisModule(self): - return self.ert().analysisConfig().activeModuleName() - - - @assertConfigLoaded - def setAnalysisModule(self, analysis_module_name): - self.ert().analysisConfig().selectModule(analysis_module_name) - - - @assertConfigLoaded - def validateAnalysisModule(self, line): - keys = matchItems(line, self.getAnalysisModules()) - - if len(keys) == 0 or len(keys) > 1: - raise ValueError("Must enter a single valid Analysis Module") - - return list(keys)[0] - - - def completeAnalysisModule(self, text, line, begidx, endidx): - key = extractFullArgument(line, endidx) - return autoCompleteListWithSeparator(key, self.getAnalysisModules()) - - - @assertConfigLoaded - def getAnalysisModules(self): - analysis_modules = self.ert().analysisConfig().getModuleList() - items = [analysis_module for analysis_module in analysis_modules] - return items - - - @assertConfigLoaded - def list(self, args): - items = self.getAnalysisModules() - self.columnize(items) - - - @assertConfigLoaded - def variables(self, args): - active_module = self.ert().analysisConfig().getActiveModule() - variables = active_module.getVariableNames() - - format = " %-20s %-6s %-20s %s" - print(format % ("Name", "Type", "Value", "Description")) - - for variable_name in variables: - variable_type = active_module.getVariableType(variable_name).__name__ - variable_value = active_module.getVariableValue(variable_name) - variable_description = active_module.getVariableDescription(variable_name) - print(format % (variable_name, variable_type, variable_value, variable_description)) - - - @assertConfigLoaded - def set(self, line): - arguments = splitArguments(line) - - if len(arguments) > 1: - active_module = self.ert().analysisConfig().getActiveModule() - variables = active_module.getVariableNames() - variable, argument = line.split(" ", 1) - - if not variable in variables: - self.lastCommandFailed("Variable with name: %s, not available in analysis module!" % variable) - else: - variable_type = active_module.getVariableType(variable) - try: - value = variable_type(argument) - active_module.setVar(variable, argument) - except ValueError: - self.lastCommandFailed("Unable to convert '%s' into to a: %s" % (argument, variable_type.__name__)) - - else: - self.lastCommandFailed("This keyword requires a variable name and a value.") - - - - @assertConfigLoaded - def completeSet(self, text, line, begidx, endidx): - arguments = splitArguments(line) - - if len(arguments) > 2 or len(arguments) == 2 and not text: - return [] - - active_module = self.ert().analysisConfig().getActiveModule() - variables = active_module.getVariableNames() - return autoCompleteListWithSeparator(text, variables) \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/cases.py b/ThirdParty/Ert/python/python/ert_gui/shell/cases.py deleted file mode 100644 index 4e334c3ddc..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/cases.py +++ /dev/null @@ -1,174 +0,0 @@ -from ert.enkf import EnkfVarType - -from ert_gui.shell import assertConfigLoaded, ErtShellCollection -from ert_gui.shell.libshell import autoCompleteList, splitArguments -from ert_gui.shell.libshell.shell_tools import boolValidator - - -class Cases(ErtShellCollection): - def __init__(self, parent): - super(Cases, self).__init__("case", parent) - self._show_hidden = False - - self.addShellFunction(name="list", - function=Cases.list, - help_message="Shows a list of all available cases.") - - self.addShellFunction(name="select", - function=Cases.select, - completer=Cases.completeSelect, - help_arguments="", - help_message="Change the current file system to the named case.") - - self.addShellFunction(name="create", - function=Cases.create, - help_arguments="", - help_message="Create a new case with the specified named.") - - self.addShellFunction(name="summary_key_set", - function=Cases.summaryKeySet, - help_message="Shows a list of the stored summary keys.") - - self.addShellFunction(name="state", - function=Cases.state, - completer=Cases.completeFilesystem, - help_arguments="[case_name]", - help_message="Shows a list of the states of the individual realizations. " - "Uses the current case if no case name is provided.") - - self.addShellFunction(name="time_map", - function=Cases.timemap, - completer=Cases.completeFilesystem, - help_arguments="[case_name]", - help_message="Shows a list of the time/report steps of the case. " - "Uses the current case if no case name is provided.") - - self.addShellFunction(name="initialize", - function=Cases.initialize, - completer=Cases.completeFilesystem, - help_arguments="[case_name]", - help_message="Initialize the selected case from scratch. " - "Uses the current if no case name is provided") - - self.addShellProperty(name="show_hidden", - getter=Cases.showHidden, - setter=Cases.setShowHidden, - validator=boolValidator, - completer=["true", "false"], - help_arguments="[true|false]", - help_message="Show or set the visibility of hidden cases", - pretty_attribute="Hidden case visibility") - - - def showHidden(self): - return self._show_hidden - - def setShowHidden(self, show_hidden): - self._show_hidden = show_hidden - - @assertConfigLoaded - def list(self, line): - fs_list = self.getFileSystemNames() - current_fs = self.ert().getEnkfFsManager().getCurrentFileSystem().getCaseName() - max_length = max([len(fs) for fs in fs_list]) - case_format = "%1s %-" + str(max_length) + "s %s" - for fs in fs_list: - current = "" - if fs == current_fs: - current = "*" - - state = "No Data" - if self.ert().getEnkfFsManager().caseHasData(fs): - state = "Data" - - print(case_format % (current, fs, state)) - - def getFileSystemNames(self): - fsm = self.ert().getEnkfFsManager() - if self._show_hidden: - return [case for case in fsm.getCaseList()] - else: - return [case for case in fsm.getCaseList() if not fsm.isCaseHidden(case)] - - @assertConfigLoaded - def select(self, case_name): - case_name = case_name.strip() - if case_name in self.getFileSystemNames(): - fs = self.ert().getEnkfFsManager().getFileSystem(case_name) - self.ert().getEnkfFsManager().switchFileSystem(fs) - else: - self.lastCommandFailed("Unknown case '%s'" % case_name) - - @assertConfigLoaded - def completeSelect(self, text, line, begidx, endidx): - return autoCompleteList(text, self.getFileSystemNames()) - - @assertConfigLoaded - def create(self, line): - arguments = splitArguments(line) - - if len(arguments) == 1: - case_name = arguments[0] - if case_name not in self.getFileSystemNames(): - fs = self.ert().getEnkfFsManager().getFileSystem(case_name) - self.ert().getEnkfFsManager().switchFileSystem(fs) - else: - self.lastCommandFailed("Case '%s' already exists!" % case_name) - else: - self.lastCommandFailed("Expected one argument: received: '%s'" % line) - - @assertConfigLoaded - def summaryKeySet(self, line): - fs = self.ert().getEnkfFsManager().getCurrentFileSystem() - key_set = sorted([key for key in fs.getSummaryKeySet().keys()]) - self.columnize(key_set) - - @assertConfigLoaded - def state(self, case_name): - case_name = case_name.strip() - if not case_name: - case_name = self.ert().getEnkfFsManager().getCurrentFileSystem().getCaseName() - elif not case_name in self.getFileSystemNames(): - self.lastCommandFailed("Unknown case name '%s'" % case_name) - return False - - state_map = self.ert().getEnkfFsManager().getStateMapForCase(case_name) - states = ["%d: %s" % (index, state) for index, state in enumerate(state_map)] - - self.columnize(states) - - @assertConfigLoaded - def completeFilesystem(self, text, line, begidx, endidx): - return autoCompleteList(text, self.getFileSystemNames()) - - @assertConfigLoaded - def timemap(self, case_name): - case_name = case_name.strip() - if not case_name: - case_name = self.ert().getEnkfFsManager().getCurrentFileSystem().getCaseName() - elif not case_name in self.getFileSystemNames(): - self.lastCommandFailed("Unknown case name '%s'" % case_name) - return False - - time_map = self.ert().getEnkfFsManager().getTimeMapForCase(case_name) - report_steps = ["%d: %s" % (index, report_step_time) for index, report_step_time in enumerate(time_map)] - - self.columnize(report_steps) - - - @assertConfigLoaded - def initialize(self, case_name): - case_name = case_name.strip() - if not case_name: - case_name = self.ert().getEnkfFsManager().getCurrentFileSystem().getCaseName() - elif not case_name in self.getFileSystemNames(): - self.lastCommandFailed("Unknown case name '%s'" % case_name) - return False - - ert = self.ert() - fs = ert.getEnkfFsManager().getFileSystem(case_name) - size = self.ert().getEnsembleSize() - parameters = ert.ensembleConfig().getKeylistFromVarType(EnkfVarType.PARAMETER) - ert.getEnkfFsManager().initializeCaseFromScratch(fs , parameters, 0, size - 1) - - print("Case: '%s' initialized") diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/custom_kw_keys.py b/ThirdParty/Ert/python/python/ert_gui/shell/custom_kw_keys.py deleted file mode 100644 index d1360fe27d..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/custom_kw_keys.py +++ /dev/null @@ -1,37 +0,0 @@ -from ert_gui.shell import assertConfigLoaded, ShellPlot, ErtShellCollection -from ert_gui.plottery import PlotDataGatherer as PDG - - -class CustomKWKeys(ErtShellCollection): - def __init__(self, parent): - super(CustomKWKeys, self).__init__("custom_kw", parent) - - self.addShellFunction(**{"name": "list", - "function": CustomKWKeys.list, - "help_message": "List all CustomKW keys."}) - - self.__plot_data_gatherer = None - - ShellPlot.addPrintSupport(self, "CustomKW") - ShellPlot.addHistogramPlotSupport(self, "CustomKW") - ShellPlot.addGaussianKDEPlotSupport(self, "CustomKW") - ShellPlot.addDistributionPlotSupport(self, "CustomKW") - ShellPlot.addCrossCaseStatisticsPlotSupport(self, "CustomKW") - - - def fetchSupportedKeys(self): - return self.ert().getKeyManager().customKwKeys() - - - def plotDataGatherer(self): - if self.__plot_data_gatherer is None: - custom_kw_pdg = PDG.gatherCustomKwData - custom_kw_key_manager = self.ert().getKeyManager().isCustomKwKey - self.__plot_data_gatherer = PDG(custom_kw_pdg, custom_kw_key_manager) - - return self.__plot_data_gatherer - - - @assertConfigLoaded - def list(self, line): - self.columnize(self.fetchSupportedKeys()) diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/debug.py b/ThirdParty/Ert/python/python/ert_gui/shell/debug.py deleted file mode 100644 index bdc8a035e8..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/debug.py +++ /dev/null @@ -1,59 +0,0 @@ -from ert import Version -from ert_gui.shell import assertConfigLoaded, ErtShellCollection - - -class Debug(ErtShellCollection): - def __init__(self, parent): - super(Debug, self).__init__("debug", parent) - - self.addShellFunction(name="site_config", function=Debug.siteConfig, help_message="Show the path to the current site_config") - self.addShellFunction(name="version", function=Debug.version, help_message="Show the internalized ert version number") - self.addShellFunction(name="timestamp", function=Debug.timestamp, help_message="Show the build timestamp") - self.addShellFunction(name="git_commit", function=Debug.gitCommit, help_message="Show the git commit") - self.addShellFunction(name="info", function=Debug.info, help_message="Shows site_config, version, timestamp and Git Commit") - self.addShellFunction(name="last_plugin_result", function=Debug.lastPluginResult, help_message="Shows the last plugin result.") - self.addShellFunction(name="eval", function=Debug.eval, help_arguments="", help_message="Evaluate a Python expression. The last plugin result is defined as: x") - - self.shellContext()["debug"] = self - self.__last_plugin_result = None - self.__local_variables = {} - - def setLastPluginResult(self, result): - self.__last_plugin_result = result - - @assertConfigLoaded - def siteConfig(self, line): - print("Site Config: %s" % self.ert().siteConfig().getLocation()) - - def version(self, line): - print("Version: %s" % Version.getVersion()) - - def timestamp(self, line): - print("Timestamp: %s" % Version.getBuildTime()) - - def gitCommit(self, line): - print("Git Commit: %s" % Version.getGitCommit(True)) - - @assertConfigLoaded - def info(self, line): - print("Site Config: %s" % self.ert().siteConfig().getLocation()) - print("Version: %s" % Version.getVersion()) - print("Timestamp: %s" % Version.getBuildTime()) - print("Git Commit: %s" % Version.getGitCommit(True)) - - def lastPluginResult(self, line): - print("Last plugin result: %s" % self.__last_plugin_result) - - def eval(self, line): - line = line.strip() - - if len(line) > 0: - self.__local_variables["x"] = self.__last_plugin_result - try: - exec(line, self.__local_variables) - except Exception as e: - print("Error: The expression caused an exception!") - print(e) - else: - print("Error: A python expression is required!") - diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/ert_shell_collection.py b/ThirdParty/Ert/python/python/ert_gui/shell/ert_shell_collection.py deleted file mode 100644 index b003be1be6..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/ert_shell_collection.py +++ /dev/null @@ -1,19 +0,0 @@ -from ert_gui.shell import assertConfigLoaded -from ert_gui.shell.libshell import ShellCollection - - -class ErtShellCollection(ShellCollection): - def __init__(self, name, parent=None, description="No description available"): - super(ErtShellCollection, self).__init__(name, parent, description) - - def shellContext(self): - """ @rtype: ert_gui.shell.ErtShellContext """ - return super(ErtShellCollection, self).shellContext() - - @assertConfigLoaded - def ert(self): - """ @rtype: ert.enkf.enkf_main.EnKFMain """ - return self.shellContext().ert() - - def columnize(self, items, displaywidth=80): - self.shellContext().shell().columnize(items, displaywidth=displaywidth) \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/ert_shell_context.py b/ThirdParty/Ert/python/python/ert_gui/shell/ert_shell_context.py deleted file mode 100644 index 2cece5ef68..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/ert_shell_context.py +++ /dev/null @@ -1,20 +0,0 @@ -from ert_gui.shell.libshell import ShellContext - - -class ErtShellContext(ShellContext): - def __init__(self, shell): - super(ErtShellContext, self).__init__(shell) - self.__ert = None - """ :type: EnKFMain """ - - def ert(self): - """ @rtype: ert.enkf.enkf_main.EnKFMain """ - return self.__ert - - def setErt(self, ert): - """ @type ert: ert.enkf.enkf_main.EnKFMain """ - if self.__ert is not None and self.__ert != ert: - self.__ert.free() - self.__ert = None - - self.__ert = ert \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/ertshell.py b/ThirdParty/Ert/python/python/ert_gui/shell/ertshell.py deleted file mode 100644 index b061b86b19..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/ertshell.py +++ /dev/null @@ -1,192 +0,0 @@ -import atexit -from cmd import Cmd -import readline -import os - -from ert.enkf import EnKFMain -import ert_gui -from ert_gui.shell import PlotSettings - -from ert_gui.shell.analysis_module import AnalysisModule -from ert_gui.shell.custom_kw_keys import CustomKWKeys -from ert_gui.shell.debug import Debug -from ert_gui.shell.cases import Cases -from ert_gui.shell.export import Export -from ert_gui.shell.gen_data_keys import GenDataKeys -from ert_gui.shell.gen_kw_keys import GenKWKeys -from ert_gui.shell.results import Results -from ert_gui.shell.plugins import Plugins -from ert_gui.shell.simulations import Simulations -from ert_gui.shell.smoother import Smoother -from ert_gui.shell.storage import Storage -from ert_gui.shell.summary_keys import SummaryKeys -from ert_gui.shell.workflows import Workflows -from ert_gui.shell.observations import Observations -from ert_gui.shell.server import Server -from ert_gui.shell.libshell import extractFullArgument, getPossibleFilenameCompletions -from ert_gui.shell import ErtShellContext - -import matplotlib - -class ErtShell(Cmd): - prompt = "--> " - intro = " :::::::::::::::::::::::::::::::::::::\n" \ - " :: ::\n" \ - " :: ______ ______ _______ ::\n" \ - " :: | ____| | __ \ |__ __| ::\n" \ - " :: | |__ | |__) | | | ::\n" \ - " :: | __| | _ / | | ::\n" \ - " :: | |____ | | \ \ | | ::\n" \ - " :: |______| |_| \_\ |_| ::\n" \ - " :: ::\n" \ - " :: Ensemble based Reservoir Tool ::\n" \ - " :::::::::::::::::::::::::::::::::::::\n" \ - "\n" \ - "Interactive shell for working with ERT.\n" \ - "\n" \ - "-- Type help for a list of supported commands.\n" \ - "-- Type exit or press Ctrl+D to end the shell session.\n" \ - "-- Press Tab for auto completion.\n" \ - "-- Arrow up/down for history.\n" - - - def __init__(self, forget_history=False): - Cmd.__init__(self) - - self._children = [] - - self._shell_context = ErtShellContext(self) - - if not forget_history: - self._history_file = os.path.join(os.path.expanduser("~/.ertshell/ertshell.history")) - self._init_history() - else: - self._history_file = None - - matplotlib.rcParams["interactive"] = True - matplotlib.rcParams["mathtext.default"] = "regular" - matplotlib.rcParams["verbose.level"] = "helpful" - matplotlib.rcParams["verbose.fileo"] = "sys.stderr" - - try: - matplotlib.style.use("ggplot") # available from version 1.4 - except AttributeError: - pass - - Debug(self) - PlotSettings(self) - Cases(self) - Workflows(self) - Plugins(self) - SummaryKeys(self) - GenDataKeys(self) - GenKWKeys(self) - Results(self) - Simulations(self) - CustomKWKeys(self) - AnalysisModule(self) - Smoother(self) - Observations(self) - Export(self) - Storage(self) - Server(self) - - self._last_command_failed = False - - atexit.register(self._cleanup) - - def _init_history(self): - try: - readline.set_history_length(100) - readline.read_history_file(self._history_file) - except IOError: - pass - atexit.register(self._save_history) - - def _save_history(self): - if self._history_file is not None: - if not os.path.exists(os.path.dirname(self._history_file)): - os.makedirs(os.path.dirname(self._history_file)) - - readline.write_history_file(self._history_file) - - def _cleanup(self): - print("Performing cleanup...") - - for child in self._children: - child.cleanup() - - if self.shellContext().ert() is not None: - self.shellContext().setErt(None) - - - def addChild(self, child): - self._children.append(child) - - def emptyline(self): - pass - - def do_load_config(self, config_file): - if os.path.exists(config_file) and os.path.isfile(config_file): - self.shellContext().setErt(EnKFMain(config_file)) - ert_gui.configureErtNotifier(self.shellContext().ert(), config_file) - else: - self.lastCommandFailed("Config file '%s' not found!\n" % config_file) - - def complete_load_config(self, text, line, begidx, endidx): - argument = extractFullArgument(line, endidx) - return getPossibleFilenameCompletions(argument) - - - def help_load_config(self): - print("\n".join(("load_config config_file", - " Loads a config file."))) - - def do_cwd(self, line): - cwd = os.getcwd() - print("Current directory: %s" % cwd) - - def help_cwd(self): - print("Show the current directory.") - - def do_exit(self, line): - return True - - def help_exit(self): - return "\n".join(("exit", - " End the shell session.")), - - do_EOF = do_exit - - def help_EOF(self): - return "\n".join(("EOF", - " The same as exit. (Ctrl+D)")), - - def shellContext(self): - return self._shell_context - - def default(self, line): - Cmd.default(self, line) - self._last_command_failed = True - - def precmd(self, line): - self._last_command_failed = False - return Cmd.precmd(self, line) - - def invokeCommand(self, line): - self._last_command_failed = False - self.onecmd(line) - return not self._last_command_failed - - def lastCommandFailed(self, message): - print("Error: %s" % message) - self._last_command_failed = True - - def get_names(self): - return dir(self) - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/export.py b/ThirdParty/Ert/python/python/ert_gui/shell/export.py deleted file mode 100644 index e08d4915ba..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/export.py +++ /dev/null @@ -1,68 +0,0 @@ -from __future__ import print_function -from ert.util import IntVector -from ert.enkf.enums import ErtImplType -from ert.enkf.data import EnkfNode -from ert_gui.shell import assertConfigLoaded, ErtShellCollection -from ert_gui.shell.libshell import autoCompleteList, splitArguments - - -class Export(ErtShellCollection): - DEFAULT_EXPORT_PATH = "export/%s/%s_%%d" - - def __init__(self, parent): - super(Export, self).__init__("export", parent) - default_path = Export.DEFAULT_EXPORT_PATH % ("{KEY}", "{KEY}") - - self.addShellFunction(name="FIELD", - function=Export.exportFIELD, - completer=Export.completeFIELD, - help_arguments=" [%s] [1,4,7-10]" % default_path, - help_message="Export parameters; path and realisations in [...] are optional.") - - def supportedFIELDKeys(self): - ens_config = self.ert().ensembleConfig() - key_list = ens_config.getKeylistFromImplType(ErtImplType.FIELD) - return key_list - - @assertConfigLoaded - def completeFIELD(self, text, line, begidx, endidx): - arguments = splitArguments(line) - - if len(arguments) > 2 or len(arguments) == 2 and not text: - return [] - - return autoCompleteList(text, self.supportedFIELDKeys()) - - @assertConfigLoaded - def exportFIELD(self, line): - arguments = splitArguments(line) - - if len(arguments) >= 1: - ens_config = self.ert().ensembleConfig() - key = arguments[0] - if key in self.supportedFIELDKeys(): - config_node = ens_config[key] - if len(arguments) >= 2: - path_fmt = arguments[1] - else: - path_fmt = Export.DEFAULT_EXPORT_PATH % (key, key) + ".grdecl" - - if len(arguments) >= 3: - range_string = "".join(arguments[2:]) - iens_list = IntVector.active_list(range_string) - else: - ens_size = self.ert().getEnsembleSize() - iens_list = IntVector.createRange(0, ens_size, 1) - - fs_manager = self.ert().getEnkfFsManager() - fs = fs_manager.getCurrentFileSystem() - mc = self.ert().getModelConfig() - init_file = config_node.getInitFile(mc.getRunpathFormat()) - if init_file: - print('Using init file: %s' % init_file) - - EnkfNode.exportMany(config_node, path_fmt, fs, iens_list, arg=init_file) - else: - self.lastCommandFailed("No such FIELD node: %s" % key) - else: - self.lastCommandFailed("Expected at least one argument: received: '%s'" % line) diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/gen_data_keys.py b/ThirdParty/Ert/python/python/ert_gui/shell/gen_data_keys.py deleted file mode 100644 index cf6f7b67b9..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/gen_data_keys.py +++ /dev/null @@ -1,32 +0,0 @@ -from ert_gui.plottery import PlotDataGatherer as PDG -from ert_gui.shell import ShellPlot, assertConfigLoaded, ErtShellCollection - - -class GenDataKeys(ErtShellCollection): - def __init__(self, parent): - super(GenDataKeys, self).__init__("gen_data", parent) - self.addShellFunction(name="list", function=GenDataKeys.list, help_message="Shows a list of all available GenData keys.") - - self.__plot_data_gatherer = None - - ShellPlot.addPrintSupport(self, "GenData") - ShellPlot.addEnsemblePlotSupport(self, "GenData") - ShellPlot.addQuantilesPlotSupport(self, "GenData") - - - def fetchSupportedKeys(self): - return self.ert().getKeyManager().genDataKeys() - - def plotDataGatherer(self): - if self.__plot_data_gatherer is None: - gen_data_pdg = PDG.gatherGenDataData - gen_data_key_manager = self.ert().getKeyManager().isGenDataKey - gen_data_observation_pdg = PDG.gatherGenDataObservationData - pdg = PDG(gen_data_pdg, gen_data_key_manager, observationGatherFunc=gen_data_observation_pdg) - self.__plot_data_gatherer = pdg - - return self.__plot_data_gatherer - - @assertConfigLoaded - def list(self, line): - self.columnize(self.fetchSupportedKeys()) diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/gen_kw_keys.py b/ThirdParty/Ert/python/python/ert_gui/shell/gen_kw_keys.py deleted file mode 100644 index 104f006185..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/gen_kw_keys.py +++ /dev/null @@ -1,31 +0,0 @@ -from ert_gui.shell import ShellPlot, assertConfigLoaded, ErtShellCollection -from ert_gui.plottery import PlotDataGatherer as PDG - - -class GenKWKeys(ErtShellCollection): - def __init__(self, parent): - super(GenKWKeys, self).__init__("gen_kw", parent) - self.addShellFunction(name="list", function=GenKWKeys.list, help_message="Shows a list of all available GenKW keys.") - - self.__plot_data_gatherer = None - - ShellPlot.addPrintSupport(self, "GenKW") - ShellPlot.addHistogramPlotSupport(self, "GenKW") - ShellPlot.addGaussianKDEPlotSupport(self, "GenKW") - ShellPlot.addDistributionPlotSupport(self, "GenKW") - ShellPlot.addCrossCaseStatisticsPlotSupport(self, "GenKW") - - def fetchSupportedKeys(self): - return self.ert().getKeyManager().genKwKeys() - - def plotDataGatherer(self): - if self.__plot_data_gatherer is None: - gen_kw_pdg = PDG.gatherGenKwData - gen_kw_key_manager = self.ert().getKeyManager().isGenKwKey - self.__plot_data_gatherer = PDG(gen_kw_pdg, gen_kw_key_manager) - - return self.__plot_data_gatherer - - @assertConfigLoaded - def list(self, line): - self.columnize(self.fetchSupportedKeys()) diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/shell/libshell/CMakeLists.txt deleted file mode 100644 index 11b4cb7ad0..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - shell_collection.py - shell_context.py - shell_function.py - shell_path_tools.py - shell_property.py - shell_tools.py -) - -add_python_package("python.ert_gui.shell.libshell" ${PYTHON_INSTALL_PREFIX}/ert_gui/shell/libshell "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/__init__.py b/ThirdParty/Ert/python/python/ert_gui/shell/libshell/__init__.py deleted file mode 100644 index cf18bdc417..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from .shell_context import ShellContext -from .shell_tools import autoCompleteList, extractFullArgument, autoCompleteListWithSeparator, matchItems, containsAny, findRightMostSeparator, boolValidator, createListValidator, createFloatValidator, widthAsPercentageOfConsoleWidth, getTerminalSize, splitArguments -from .shell_path_tools import getPossibleFilenameCompletions, pathCompleter, pathify -from .shell_property import ShellProperty -from .shell_function import ShellFunction -from .shell_collection import ShellCollection \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_collection.py b/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_collection.py deleted file mode 100644 index db5a2adc9d..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_collection.py +++ /dev/null @@ -1,171 +0,0 @@ -import shlex -import textwrap -from ert_gui.shell.libshell import autoCompleteList, ShellFunction, ShellProperty, widthAsPercentageOfConsoleWidth, getTerminalSize - - -class ShellCollection(object): - command_help_message = "The command: '%s' supports the following keywords:" - - def __init__(self, name, parent=None, description="No description available"): - super(ShellCollection, self).__init__() - self.__name = name - self.__parent = None - self.__description = description - - if parent is not None: - self.setParent(parent) - parent.addChild(self) - - self.__collection = {} - self.__model_tracker = {} - self.__children = [] - - def setParent(self, parent): - if not hasattr(parent, "shellContext"): - raise ValueError("Parent is missing function: shellContext()") - - if not hasattr(parent, "lastCommandFailed"): - raise ValueError("Parent is missing function: lastCommandFailed()") - - setattr(parent, "do_%s" % self.name, self.doKeywords) - setattr(parent, "complete_%s" % self.name, self.completeKeywords) - setattr(parent, "help_%s" % self.name, self.helpKeywords) - self.__parent = parent - - - def addChild(self, child): - self.__children.append(child) - - def cleanup(self): - for child in self.__children: - child.cleanup() - - def addCollection(self, collection): - """ - :type collection: ShellCollection - """ - self.__collection[collection.name] = collection - collection.setParent(self) - - - def addProperty(self, property): - """ - :type property: ShellProperty - """ - self.__collection[property.name] = property - property.setParent(self) - - def addFunction(self, function): - """ - :type function: ShellFunction - """ - self.__collection[function.name] = function - function.setParent(self) - - - def addShellProperty(self, name, getter, setter=None, validator=None, completer=None, help_arguments=None, help_message=None, pretty_attribute=None, model=None): - """ @rtype: ShellProperty """ - shell_property = ShellProperty(name, getter, setter, validator, completer, help_arguments, help_message, pretty_attribute) - self.addProperty(shell_property) - - if model is None: - model = self - - self.__model_tracker[name] = model - return shell_property - - - def getModelForProperty(self, property_name): - return self.__model_tracker[property_name] - - - def addShellFunction(self, name, function, completer=None, help_arguments=None, help_message=None, model=None): - """ @rtype: ShellFunction """ - func = ShellFunction(name, function, completer, help_arguments, help_message) - self.addFunction(func) - - if model is None: - model = self - - self.__model_tracker[name] = model - - return func - - - def getModelForFunction(self, name): - return self.__model_tracker[name] - - @property - def name(self): - return self.__name - - def shellContext(self): - """ :rtype: ert_gui.shell.libshell.ShellContext """ - return self.__parent.shellContext() - - def lastCommandFailed(self, message): - self.__parent.lastCommandFailed(message) - - def findKeywords(self): - return self.__collection.keys() - - def completeKeywords(self, text, line, begidx, endidx): - arguments = shlex.split(line) - assert arguments[0] == self.name - - line = line[len(self.name) + 1:] - begidx = begidx - len(self.name) + 1 - endidx = endidx - len(self.name) + 1 - keyword, sep, arguments = line.partition(' ') - - if begidx >= len(keyword) and keyword in self.findKeywords(): - if hasattr(self, "complete_%s" % keyword): - func = getattr(self, "complete_%s" % keyword) - return func(text, line, begidx, endidx) - else: - return [] - else: - return autoCompleteList(text, self.findKeywords()) - - def doKeywords(self, line): - keyword, sep, arguments = line.partition(' ') - - if keyword.strip() == "": - self.printGuidance() - elif keyword in self.__collection: - func = getattr(self, "do_%s" % keyword) - return func(arguments) - else: - self.lastCommandFailed("Unknown keyword: '%s'" % keyword) - self.printGuidance() - - - def printGuidance(self): - print(self.command_help_message % self.name) - self.shellContext().shell().columnize(self.findKeywords(), getTerminalSize()[0]) - - - def helpKeywords(self): - print(self.command_help_message % self.name) - keywords = self.findKeywords() - - keyword_column_width = widthAsPercentageOfConsoleWidth(20) - parameter_column_width = widthAsPercentageOfConsoleWidth(30) - help_column_width = widthAsPercentageOfConsoleWidth(48) - help_format = " %-" + str(keyword_column_width) + "s %-" + str(parameter_column_width) + "s %-" + str(help_column_width) + "s" - - print(help_format % ("Keyword", "Parameter(s)", "Help")) - - for keyword in keywords: - message = "No help available!" - parameters = None - if hasattr(self, "help_tuple_%s" % keyword): - func = getattr(self, "help_tuple_%s" % keyword) - _, parameters, message = func() - - message = textwrap.wrap(message, help_column_width) - print(help_format % (keyword, parameters, message[0])) - - if len(message) > 1: - for line in message[1:]: - print(help_format % ("", "", line)) \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_context.py b/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_context.py deleted file mode 100644 index 7e52e46ed0..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_context.py +++ /dev/null @@ -1,23 +0,0 @@ - -class ShellContext(object): - def __init__(self, shell): - super(ShellContext, self).__init__() - - self.__shell = shell - """ :type: Cmd """ - - self.__settings = {} - - - def shell(self): - """ @rtype: ert_gui.shell.ErtShell """ - return self.__shell - - def __setitem__(self, key, value): - self.__settings[key] = value - - def __getitem__(self, key): - return self.__settings[key] - - def __contains__(self, key): - return key in self.__settings \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_function.py b/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_function.py deleted file mode 100644 index 48c3b144ed..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_function.py +++ /dev/null @@ -1,62 +0,0 @@ -from ert_gui.shell.libshell import extractFullArgument, autoCompleteListWithSeparator - - -class ShellFunction(object): - - def __init__(self, name, function, completer=None, help_arguments=None, help_message=None): - super(ShellFunction, self).__init__() - self.__parent = None - self.__name = name - - if function is None: - raise ValueError("Function can not be None for shell function '%s'" % name) - - self.__function = function - self.__completer = completer - - self.__help_arguments = help_arguments - self.__help_message = help_message if help_message is not None else "No help available!" - - - def setParent(self, parent): - if parent is None: - raise ValueError("Function target can not be None for shell function '%s'" % self.name) - - if not hasattr(parent, "getModelForFunction"): - raise ValueError("function target is missing method 'getModelForFunction(name)' for shell function '%s'" % self.name) - - if hasattr(parent, "do_%s" % self.name) or hasattr(parent, "complete_%s" % self.name) or hasattr(parent, "help_%s" % self.name) : - raise ValueError("function with name '%s' already exists for object '%s'" % (self.name, parent)) - - setattr(parent, "do_%s" % self.name, self.doFunction) - setattr(parent, "complete_%s" % self.name, self.completeFunction) - setattr(parent, "help_tuple_%s" % self.name, self.helpFunction) - - self.__parent = parent - - - def doFunction(self, line): - model = self.getModelForFunction() - self.__function(model, line.strip()) - - def completeFunction(self, text, line, begidx, endidx): - if self.__completer is not None: - if callable(self.__completer): - model = self.getModelForFunction() - return self.__completer(model, text, line, begidx, endidx) - else: - key = extractFullArgument(line, endidx) - return autoCompleteListWithSeparator(key, self.__completer) - - return [] - - def helpFunction(self): - return self.name, self.__help_arguments, self.__help_message - - def getModelForFunction(self): - return self.__parent.getModelForFunction(self.name) - - @property - def name(self): - return self.__name - diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_path_tools.py b/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_path_tools.py deleted file mode 100644 index d9322fb8cc..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_path_tools.py +++ /dev/null @@ -1,26 +0,0 @@ -import os -from ert_gui.shell.libshell import containsAny, extractFullArgument, findRightMostSeparator - - -def pathify(head, tail): - path = os.path.join(head, tail) - if os.path.isdir(path): - return "%s/" % tail - return tail - -def getPossibleFilenameCompletions(text, separators="-"): - head, tail = os.path.split(text.strip()) - if head == "": # no head - head = "." - files = os.listdir(head) - - separator_pos = 0 - if containsAny(tail, separators): - separator_pos = findRightMostSeparator(tail, separators) + 1 - - return [pathify(head, f)[separator_pos:] for f in files if f.startswith(tail)] - - -def pathCompleter(model, text, line, begidx, endidx): - argument = extractFullArgument(line, endidx) - return getPossibleFilenameCompletions(argument) \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_property.py b/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_property.py deleted file mode 100644 index 6a8b8d2e3c..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_property.py +++ /dev/null @@ -1,90 +0,0 @@ -from ert_gui.shell.libshell import extractFullArgument, autoCompleteListWithSeparator - -class ShellProperty(object): - def __init__(self, name, getter, setter=None, validator=None, completer=None, help_arguments=None, help_message=None, pretty_attribute=None): - super(ShellProperty, self).__init__() - self.__parent = None - - if getter is None: - raise ValueError("Getter function/property can not be None for shell property '%s'" % name) - - self.__setter = setter - self.__getter = getter - - self.__name = name - self.__pretty_attribute = name if pretty_attribute is None else pretty_attribute - - self.__help_arguments = help_arguments - self.__help_message = help_message if help_message is not None else "No help available!" - - self.__completer = completer - self.__validator = validator - - - - def setParent(self, parent): - if parent is None: - raise ValueError("Property target can not be None for shell property '%s'" % self.name) - - if not hasattr(parent, "getModelForProperty"): - raise ValueError("Property target is missing method 'getModelForProperty(name)' for shell property '%s'" % self.name) - - if hasattr(parent, "do_%s" % self.name) or hasattr(parent, "complete_%s" % self.name) or hasattr(parent, "help_%s" % self.name) : - raise ValueError("Property with name '%s' already exists for object '%s'" % (self.name, parent)) - - setattr(parent, "do_%s" % self.name, self.doFunction) - setattr(parent, "complete_%s" % self.name, self.completeFunction) - setattr(parent, "help_tuple_%s" % self.name, self.helpFunction) - - self.__parent = parent - - - def doFunction(self, line): - value = line.strip() - model = self.getModelForProperty() - if value == "": - if isinstance(self.__getter, property): - result = self.__getter.__get__(model) - else: - result = self.__getter(model) - print("%s = %s" % (self.__pretty_attribute, result)) - else: - try: - if self.__validator is not None: - value = self.__validator(model, value) - - if self.__setter is not None: - if isinstance(self.__setter, property): - self.__setter.__set__(model, value) - else: - self.__setter(model, value) - print("%s set to: %s" % (self.__pretty_attribute, value)) - else: - self.lastCommandFailed("Property '%s' is set to read only" % self.__pretty_attribute) - except ValueError as e: - self.lastCommandFailed(e.message) - - - def completeFunction(self, text, line, begidx, endidx): - if self.__completer is not None: - if callable(self.__completer): - model = self.getModelForProperty() - return self.__completer(model, text, line, begidx, endidx) - else: - key = extractFullArgument(line, endidx) - return autoCompleteListWithSeparator(key, self.__completer) - - return [] - - def helpFunction(self): - return self.name, self.__help_arguments, self.__help_message - - def getModelForProperty(self): - return self.__parent.getModelForProperty(self.name) - - def lastCommandFailed(self, message): - self.__parent.lastCommandFailed(message) - - @property - def name(self): - return self.__name diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_tools.py b/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_tools.py deleted file mode 100644 index 800cffc9ee..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/libshell/shell_tools.py +++ /dev/null @@ -1,136 +0,0 @@ -import fnmatch -from math import floor -import shlex - - -def autoCompleteList(text, items): - if not text: - completions = items - else: - completions = [item for item in items if str(item).lower().startswith(text.lower())] - return completions - -def containsAny(string, chars): - return True in [char in string for char in chars] - -def findRightMostSeparator(text, separators): - max_pos = 0 - - for separator in separators: - pos = text.rfind(separator) - max_pos = max(pos, max_pos) - - return max_pos - -def autoCompleteListWithSeparator(text, items, separators=":,@"): - if containsAny(text, separators): - auto_complete_list = autoCompleteList(text, items) - separator_pos = findRightMostSeparator(text, separators) - auto_complete_list = [item[separator_pos + 1:] for item in auto_complete_list] - else: - auto_complete_list = autoCompleteList(text, items) - - return auto_complete_list - - -def extractFullArgument(line, endidx): - last_space_index = line.rfind(" ", 0, endidx) - newstart = 0 if last_space_index == -1 else last_space_index - return line[newstart:endidx].strip() - - -def matchItems(line, items): - patterns = shlex.split(line) - - result_items = set() - - for pattern in patterns: - pattern_matches = set() - for item in items: - if fnmatch.fnmatch(item.lower(), pattern.lower()): # case-insensitive matching - pattern_matches.add(item) - - if len(pattern_matches) == 0: - print("Error: Name/Pattern '%s' does not match anything." % pattern) - else: - result_items = result_items | pattern_matches - - return result_items - - -def boolValidator(model, value): - trueness = value.lower() in ("yes", "true", "t", "1") - falseness = value.lower() in ("no", "false", "f", "0") - - if not (trueness or falseness): - raise ValueError("Unable to convert '%s' into a boolean expression true|false" % value) - - return trueness - - -def createFloatValidator(minimum=None, maximum=None): - def validate(model, value): - value = float(value) - if minimum is not None: - value = max(value, minimum) - - if maximum is not None: - value = min(value, maximum) - - return value - return validate - - -def createListValidator(items): - def validate(model, value): - value = value.lower() - for item in items: - if value == str(item).lower(): - return item - - raise ValueError("Value '%s' not in collection: %s" % (value, items)) - - return validate - -def splitArguments(line): - """ @rtype: list of str """ - return shlex.split(line) - -def widthAsPercentageOfConsoleWidth(percentage): - width, height = getTerminalSize() - if width == 0: - width = 80 - - return int(floor(percentage * width / 100.0)) - - -def getTerminalSize(): - """ - @rtype: tuple of (int,int) - @return: Console dimensions as: width, height - """ - import os - env = os.environ - - def ioctl_GWINSZ(fd): - try: - import fcntl, termios, struct, os - cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) - except: - return - return cr - - cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) - - if not cr: - try: - fd = os.open(os.ctermid(), os.O_RDONLY) - cr = ioctl_GWINSZ(fd) - os.close(fd) - except: - pass - - if not cr: - cr = (env.get('LINES', 25), env.get('COLUMNS', 80)) - return int(cr[1]), int(cr[0]) - diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/observations.py b/ThirdParty/Ert/python/python/ert_gui/shell/observations.py deleted file mode 100644 index c05a86d3b1..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/observations.py +++ /dev/null @@ -1,67 +0,0 @@ -import os - -from ert_gui.shell import assertConfigLoaded, ErtShellCollection -from ert_gui.shell.libshell import extractFullArgument, getPossibleFilenameCompletions - - -class Observations(ErtShellCollection): - def __init__(self, parent): - super(Observations, self).__init__("observations", parent) - - self.addShellFunction(name="list", - function=Observations.list, - help_message="List all observation keys.") - - self.addShellFunction(name="clear", - function=Observations.clear, - help_message="Remove all observations.") - - self.addShellFunction(name="load", - function=Observations.load, - completer=Observations.completeLoad, - help_arguments="", - help_message="Add observations from the specified file.") - - self.addShellFunction(name="reload", - function=Observations.reload, - completer=Observations.completeReload, - help_arguments="", - help_message="Perform a clear before adding observations from the specified file.") - - - @assertConfigLoaded - def list(self, line): - keys = [obs_vector.getObservationKey() for obs_vector in self.ert().getObservations()] - print("Observation keys:") - self.columnize(keys) - - @assertConfigLoaded - def clear(self, line): - self.ert().getObservations().clear() - - @assertConfigLoaded - def load(self, config_file): - if os.path.exists(config_file) and os.path.isfile(config_file): - # This will append observations; alternatively reload() - # can be used to clear the current observations first. - self.ert().loadObservations( config_file , clear = False ) - else: - self.lastCommandFailed("Observations file '%s' not found!\n" % config_file) - - @assertConfigLoaded - def reload(self, config_file): - if os.path.exists(config_file) and os.path.isfile(config_file): - # If clear is False the new observations will be added to the existing. - self.ert().loadObservations( config_file , clear = True ) - else: - self.lastCommandFailed("Observations file '%s' not found!\n" % config_file) - - @assertConfigLoaded - def completeLoad(self, text, line, begidx, endidx): - argument = extractFullArgument(line, endidx) - return getPossibleFilenameCompletions(argument) - - @assertConfigLoaded - def completeReload(self, text, line, begidx, endidx): - argument = extractFullArgument(line, endidx) - return getPossibleFilenameCompletions(argument) diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/plot_settings.py b/ThirdParty/Ert/python/python/ert_gui/shell/plot_settings.py deleted file mode 100644 index d34c4c6452..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/plot_settings.py +++ /dev/null @@ -1,178 +0,0 @@ -from ert.enkf.enkf_fs_manager import naturalSortKey -from ert.enkf import PlotSettings as ErtPlotSettings -from ert_gui.plottery.plot_config import PlotConfig -from ert_gui.shell import assertConfigLoaded, ErtShellCollection -from ert_gui.shell.libshell import autoCompleteList, boolValidator, pathCompleter, splitArguments -from ert_gui.shell.libshell.shell_tools import matchItems - - -def plotPathValidator(model, line): - arguments = splitArguments(line) - - if len(arguments) == 1: - return arguments[0] # todo: check if exists and is file or directory for example - else: - raise ValueError("Can only set one path. If you require spaces in your path, " - "surround it with quotes: \"path with space\".") - - -class PlotSettings(ErtShellCollection): - def __init__(self, parent): - super(PlotSettings, self).__init__("plot_settings", parent) - - self.__cases = None - if self.ert(): - ert_ps = self.ert().plotConfig( ) - else: - ert_ps = ErtPlotSettings( ) - - self.__plot_config = PlotConfig( ert_ps ) - self.shellContext()["plot_settings"] = self - - self.addShellFunction(name="current", - function=PlotSettings.current, - help_message="Shows the selected plot source case(s).") - - self.addShellFunction(name="reset_title", - function=PlotSettings.resetTitle, - help_message="Reset plot title back to default.") - - self.addShellFunction(name="select", - function=PlotSettings.select, - completer=PlotSettings.completeSelect, - help_arguments="[case_1..case_n]", - help_message="Select one or more cases as default plot sources. Empty resets to current case.") - - self.addShellProperty(name="path", - getter=PlotSettings.getPath, - setter=PlotSettings.setPath, - validator=plotPathValidator, - completer=pathCompleter, - help_arguments="[path]", - help_message="Show or set the plot output path", - pretty_attribute="Plot output path") - - self.addShellProperty(name="title", - getter=PlotConfig.title, - setter=PlotConfig.setTitle, - help_arguments="[new_title]", - help_message="Show or set the title of the plot", - pretty_attribute="Title", - model=self.__plot_config) - - self.addShellProperty(name="x_label", - getter=PlotConfig.xLabel, - setter=PlotConfig.setXLabel, - help_arguments="[new_label]", - help_message="Show or set the X label of the plot", - pretty_attribute="X label", - model=self.__plot_config) - - self.addShellProperty(name="y_label", - getter=PlotConfig.yLabel, - setter=PlotConfig.setYLabel, - help_arguments="[new_label]", - help_message="Show or set the Y label of the plot", - pretty_attribute="Y label", - model=self.__plot_config) - - self.addShellProperty(name="grid", - getter=PlotConfig.isGridEnabled, - setter=PlotConfig.setGridEnabled, - validator=boolValidator, - completer=["true", "false"], - help_arguments="[true|false]", - help_message="Show or set the grid visibility", - pretty_attribute="Grid visibility", - model=self.__plot_config) - - self.addShellProperty(name="legend", - getter=PlotConfig.isLegendEnabled, - setter=PlotConfig.setLegendEnabled, - validator=boolValidator, - completer=["true", "false"], - help_arguments="[true|false]", - help_message="Show or set the legend visibility", - pretty_attribute="Legend visibility", - model=self.__plot_config) - - self.addShellProperty(name="connection_lines", - getter=PlotConfig.isDistributionLineEnabled, - setter=PlotConfig.setDistributionLineEnabled, - validator=boolValidator, - completer=["true", "false"], - help_arguments="[true|false]", - help_message="Show or set the connection lines visibility", - pretty_attribute="Connection Line visibility", - model=self.__plot_config) - - self.addShellProperty(name="refcase", - getter=PlotConfig.isRefcaseEnabled, - setter=PlotConfig.setRefcaseEnabled, - validator=boolValidator, - completer=["true", "false"], - help_arguments="[true|false]", - help_message="Show or set the refcase visibility", - pretty_attribute="Refcase visibility", - model=self.__plot_config) - - self.addShellProperty(name="observations", - getter=PlotConfig.isObservationsEnabled, - setter=PlotConfig.setObservationsEnabled, - validator=boolValidator, - completer=["true", "false"], - help_arguments="[true|false]", - help_message="Show or set the observations visibility", - pretty_attribute="Observations visibility", - model=self.__plot_config) - - - def getCurrentPlotCases(self): - """ @rtype: list of str """ - - if self.__cases is None: - case_name = self.ert().getEnkfFsManager().getCurrentFileSystem().getCaseName() - return [case_name] - - return self.__cases - - def plotConfig(self): - return self.__plot_config - - @assertConfigLoaded - def current(self, line): - keys = self.getCurrentPlotCases() - self.columnize(keys) - - @assertConfigLoaded - def select(self, line): - matched_cases = matchItems(line, self.getAllCaseList()) - - if len(matched_cases) > 0: - self.__cases = sorted(list(matched_cases), key=naturalSortKey) - else: - if len(line) > 0: - self.lastCommandFailed("No valid case names provided: %s" % line) - print("Case reset to default: %s" % self.ert().getEnkfFsManager().getCurrentFileSystem().getCaseName()) - self.__cases = None - - @assertConfigLoaded - def completeSelect(self, text, line, begidx, endidx): - return autoCompleteList(text, self.getAllCaseList()) - - def getAllCaseList(self): - fs_manager = self.ert().getEnkfFsManager() - all_case_list = fs_manager.getCaseList() - all_case_list = [case for case in all_case_list if not case.startswith(".")] - return all_case_list - - @assertConfigLoaded - def getPath(self): - return self.ert().plotConfig().getPath() - - @assertConfigLoaded - def setPath(self, path): - self.ert().plotConfig().setPath(path) - - def resetTitle(self, line): - self.plotConfig().setTitle(None) diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/plugins.py b/ThirdParty/Ert/python/python/ert_gui/shell/plugins.py deleted file mode 100644 index 275eaface6..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/plugins.py +++ /dev/null @@ -1,190 +0,0 @@ -import inspect -import time -from ert.job_queue import ErtScript, CancelPluginException -from ert_gui.shell import assertConfigLoaded, ErtShellCollection -from ert_gui.shell.libshell import splitArguments, autoCompleteList - - -class Plugins(ErtShellCollection): - def __init__(self, parent): - super(Plugins, self).__init__("plugins", parent) - - self.addShellFunction(name="list", - function=Plugins.list, - help_message="Shows a list of all available plugins.") - - self.addShellFunction(name="help", - function=Plugins.help, - completer=Plugins.completeHelp, - help_arguments="", - help_message="Shows help for the specified plugin if available.") - - self.addShellFunction(name="run", - function=Plugins.run, - completer=Plugins.completeRun, - help_arguments=" [args]", - help_message="Run a named plugin with either arguments or default input GUI.") - - self.addShellFunction(name="arguments", - function=Plugins.arguments, - completer=Plugins.completeArguments, - help_arguments="", - help_message="Shows a list of expected arguments for a specified plugin.") - - - @assertConfigLoaded - def list(self, line): - plugins = self.getPluginNames() - if len(plugins) > 0: - self.columnize(plugins) - else: - print("No plugins available.") - - - @assertConfigLoaded - def run(self, line): - arguments = splitArguments(line) - - if len(arguments) < 1: - print("Error: This keyword requires a name of a plugin to run.") - else: - plugin_name = arguments[0] - plugin_job = self.getWorkflowJob(plugin_name) - - if plugin_job is not None: - try: - script = self.getScript(plugin_job) - if len(arguments) > 1: - arguments = arguments[1:] - else: - arguments = script.getArguments(None) - - now = time.time() - result = plugin_job.run(self.ert(), arguments) - - self.shellContext()["debug"].setLastPluginResult(result) - - diff = time.time() - now - print("Plugin running time: %d seconds" % int(diff)) - - print(result) - except CancelPluginException: - print("Plugin cancelled before execution!") - else: - self.lastCommandFailed("Unknown plugin: '%s'" % plugin_name) - - - @assertConfigLoaded - def completeRun(self, text, line, begidx, endidx): - arguments = splitArguments(line) - - if len(arguments) > 2 or len(arguments) == 2 and not text: - return [] - return autoCompleteList(text, self.getPluginNames()) - - - @assertConfigLoaded - def arguments(self, plugin_name): - plugin_job = self.getWorkflowJob(plugin_name) - - if plugin_job is not None: - script, arguments = self.getScriptAndArguments(plugin_job) - - if len(arguments) > 1: - print("The plugin: '%s' takes the following required <...> and/or optional [...] arguments:\n" % plugin_name) - arguments_format = " %-25s %-35s %-20s" - print(arguments_format % ("Arguments", "Default Value", "Type")) - - for argument in arguments: - - if not argument["optional"]: - argument_format = "<%s>" - else: - argument_format = "[%s]" - - print(arguments_format % (argument_format % argument["name"], argument["default"], argument["type"].__name__)) - else: - print("Plugin has no arguments.") - else: - self.lastCommandFailed("Unknown plugin: '%s'" % plugin_name) - - @assertConfigLoaded - def completeArguments(self, text, line, begidx, endidx): - arguments = splitArguments(line) - - if len(arguments) > 2 or len(arguments) == 2 and not text: - return [] - return autoCompleteList(text, self.getPluginNames()) - - - @assertConfigLoaded - def help(self, line): - arguments = splitArguments(line) - - if len(arguments) < 1: - self.lastCommandFailed("This keyword requires a name of a plugin to run.") - else: - plugin_name = arguments[0] - plugin_job = self.getWorkflowJob(plugin_name) - - if plugin_job is not None: - script = self.getScript(plugin_job) - - print(script.__doc__) - else: - self.lastCommandFailed("Unknown plugin: '%s'" % plugin_name) - - - @assertConfigLoaded - def completeHelp(self, text, line, begidx, endidx): - arguments = splitArguments(line) - - if len(arguments) > 2 or len(arguments) == 2 and not text: - return [] - return autoCompleteList(text, self.getPluginNames()) - - def getPluginNames(self): - plugin_jobs = self.ert().getWorkflowList().getPluginJobs() - return [plugin.name() for plugin in plugin_jobs] - - - def getWorkflowJob(self, plugin_name): - """ @rtype: WorkflowJob """ - plugin_name = plugin_name.strip() - plugin_jobs = self.ert().getWorkflowList().getPluginJobs() - plugin_job = next((job for job in plugin_jobs if job.name() == plugin_name), None) - return plugin_job - - - def getScript(self, plugin_job): - script_obj = ErtScript.loadScriptFromFile(plugin_job.getInternalScriptPath()) - script = script_obj(self.ert()) - return script - - def getScriptAndArguments(self, plugin_job): - script = self.getScript(plugin_job) - arg_spec = inspect.getargspec(script.run) - - arguments = [] - - if len(arg_spec.args) > 1: - - for argument_name, argument_type in zip(arg_spec.args[1:], plugin_job.argumentTypes()): - arguments.append({ - "name": argument_name, - "type": argument_type, - "default": "", - "optional": False - }) - - if arg_spec.defaults is not None: - for index, value in enumerate(reversed(arg_spec.defaults)): - arguments[len(arguments) - 1 - index]["default"] = value - - min_arg_count = plugin_job.minimumArgumentCount() - - for index, argument in enumerate(arguments): - if index >= min_arg_count: - argument["optional"] = True - - return script, arguments diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/results.py b/ThirdParty/Ert/python/python/ert_gui/shell/results.py deleted file mode 100644 index 9b6a5c34c7..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/results.py +++ /dev/null @@ -1,50 +0,0 @@ -from ert.util import BoolVector -from ert_gui.shell import assertConfigLoaded, ErtShellCollection -from ert_gui.shell.libshell import splitArguments - - -class Results(ErtShellCollection): - def __init__(self, parent): - super(Results, self).__init__("results", parent) - - self.addShellFunction(name="runpath", function=Results.runpath, help_message="Shows the current runpath.") - self.addShellFunction(name="load", function=Results.load, completer=Results.completeLoad, help_arguments="", help_message="Load results from the specified realizations.") #todo iterations - - @assertConfigLoaded - def runpath(self, args): - runpath = self.ert().getModelConfig().getRunpathAsString() - print("Runpath set to: %s" % runpath) - - - @assertConfigLoaded - def load(self, args): - arguments = splitArguments(args) - - if len(arguments) < 1: - self.lastCommandFailed("Loading requires a realization mask.") - return False - - realization_count = self.ert().getEnsembleSize() - - mask = BoolVector(False, realization_count) - mask_success = mask.updateActiveMask(arguments[0]) - - if not mask_success: - self.lastCommandFailed("The realization mask: '%s' is not valid." % arguments[0]) - return False - - fs = self.ert().getEnkfFsManager().getCurrentFileSystem() - self.ert().loadFromForwardModel(mask, 0, fs) - - - @assertConfigLoaded - def completeLoad(self, text, line, begidx, endidx): - arguments = splitArguments(line) - - if len(arguments) > 2 or len(arguments) == 2 and not text: - return [] - - if not text: - return ["0-%d" % self.ert().getEnsembleSize()] # todo should generate based on realization directories. - - return [] diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/server.py b/ThirdParty/Ert/python/python/ert_gui/shell/server.py deleted file mode 100644 index 693b6271c7..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/server.py +++ /dev/null @@ -1,105 +0,0 @@ -import socket -from threading import Thread - -from ert.server import ErtRPCServer -from ert_gui.shell import assertConfigLoaded, ErtShellCollection - - -class Server(ErtShellCollection): - def __init__(self, parent): - super(Server, self).__init__("server", parent) - self.shellContext()["server_settings"] = self - - self.addShellFunction(name="start", - function=Server.startServer, - help_message="Start the ERT RPC Server") - - self.addShellFunction(name="stop", - function=Server.stopServer, - help_message="Stop the ERT RPC Server") - - self.addShellFunction(name="inspect", - function=Server.inspect, - help_message="Shows information about the current job queue") - - self.addShellProperty(name="hostname", - getter=Server.getHost, - setter=Server.setHost, - help_arguments="[hostname]", - help_message="Show or set the server hostname", - pretty_attribute="Hostname") - - self.addShellProperty(name="port", - getter=Server.getPort, - setter=Server.setPort, - help_arguments="[port]", - help_message="Show or set the server port number (0 = automatic)", - pretty_attribute="Port") - - self._server = None - """ :type: ErtRPCServer """ - - self._hostname = "localhost" - self._port = 0 - - def getHost(self): - return self._hostname - - def setHost(self, hostname): - self._hostname = hostname - - def getPort(self): - return self._port - - def setPort(self, port): - self._port = int(port) - - @assertConfigLoaded - def startServer(self, line): - port = self._port - host = self._hostname - - if self._server is None: - try: - self._server = ErtRPCServer(self.ert(), host=host, port=port) - except socket.error as e: - print("Unable to start the server on port: %d" % port) - else: - thread = Thread(name="Shell Server Thread") - thread.daemon = True - thread.run = self._server.start - thread.start() - print("Server running on host: '%s' and port: %d" % (self._server.host, self._server.port)) - else: - print("A server is already running at host: '%s' and port: %d" % (self._server.host, self._server.port)) - - def _stopServer(self): - if self._server is not None: - self._server.stop() - self._server = None - print("Server stopped") - - def stopServer(self, line): - if self._server is not None: - self._stopServer() - else: - print("No server to stop") - - def cleanup(self): - self._stopServer() - ErtShellCollection.cleanup(self) - - def inspect(self, line): - if self._server is not None: - if self._server.isRunning(): - print("Waiting..: %d" % self._server.getWaitingCount()) - print("Running..: %d" % self._server.getRunningCount()) - print("Failed...: %d" % self._server.getFailedCount()) - print("Succeeded: %d" % self._server.getSuccessCount()) - print("Batch#...: %d" % self._server.getBatchNumber()) - else: - print("Server is not running any simulations") - else: - print("No server is not available") - - diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/shell_plot.py b/ThirdParty/Ert/python/python/ert_gui/shell/shell_plot.py deleted file mode 100644 index 293b9daf3d..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/shell_plot.py +++ /dev/null @@ -1,236 +0,0 @@ -import ert_gui.plottery.plots as plots - -import matplotlib.pyplot as plt - -from ert_gui.plottery.plot_config_factory import PlotConfigFactory -from ert_gui.shell import assertConfigLoaded -from ert_gui.plottery import PlotConfig, PlotContext -from ert_gui.shell.libshell import matchItems, extractFullArgument, autoCompleteListWithSeparator - - -class ShellPlot(object): - @classmethod - def _createPlotContext(cls, shell_context, data_gatherer, key): - """ - :type shell_context: ShellContext - :param data_gatherer: PlotDataGatherer - :param key: str - """ - figure = plt.figure() - figure.set_tight_layout(True) - cases = shell_context["plot_settings"].getCurrentPlotCases() - - plot_config = PlotConfig(key) - #plot settings should keep of track of single attributes and only apply the changed ones... - plot_config.copyConfigFrom(shell_context["plot_settings"].plotConfig()) - - if plot_config.isUnnamed(): - plot_config.setTitle(key) - - #Apply data type specific changes for statistics... - PlotConfigFactory.updatePlotConfigForKey(shell_context.ert(), key, plot_config) - - plot_context = PlotContext(shell_context.ert(), figure, plot_config, cases, key, data_gatherer) - return plot_context - - @classmethod - def plotEnsemble(cls, shell_context, data_gatherer, key): - """ - :type shell_context: ShellContext - :param data_gatherer: PlotDataGatherer - :param key: str - """ - plot_context = cls._createPlotContext(shell_context, data_gatherer, key) - plots.plotEnsemble(plot_context) - - @classmethod - def plotQuantiles(cls, shell_context, data_gatherer, key): - """ - :type shell_context: ShellContext - :param data_gatherer: PlotDataGatherer - :param key: str - """ - plot_context = cls._createPlotContext(shell_context, data_gatherer, key) - plots.plotStatistics(plot_context) - - @classmethod - def plotHistogram(cls, shell_context, data_gatherer, key): - """ - :type shell_context: ShellContext - :param data_gatherer: PlotDataGatherer - :param key: str - """ - plot_context = cls._createPlotContext(shell_context, data_gatherer, key) - plots.plotHistogram(plot_context) - - @classmethod - def plotDistribution(cls, shell_context, data_gatherer, key): - """ - :type shell_context: ShellContext - :param data_gatherer: PlotDataGatherer - :param key: str - """ - plot_context = cls._createPlotContext(shell_context, data_gatherer, key) - plots.plotDistribution(plot_context) - - @classmethod - def plotGaussianKDE(cls, shell_context, data_gatherer, key): - """ - :type shell_context: ShellContext - :param data_gatherer: PlotDataGatherer - :param key: str - """ - plot_context = cls._createPlotContext(shell_context, data_gatherer, key) - plots.plotGaussianKDE(plot_context) - - @classmethod - def plotCrossCaseStatistics(cls, shell_context, data_gatherer, key): - """ - :type shell_context: ShellContext - :param data_gatherer: PlotDataGatherer - :param key: str - """ - plot_context = cls._createPlotContext(shell_context, data_gatherer, key) - plots.plotCrossCaseStatistics(plot_context) - - @classmethod - def _checkForRequiredMethods(cls, instance): - if not hasattr(instance, "fetchSupportedKeys"): - raise NotImplementedError("Class must implement: fetchSupportedKeys()") - - if not hasattr(instance, "plotDataGatherer"): - raise NotImplementedError("Class must implement: plotDataGatherer()") - - @classmethod - def _createDoFunction(cls, plot_function, name): - def do_function(self, line): - keys = matchItems(line, self.fetchSupportedKeys()) - - if len(keys) == 0: - self.lastCommandFailed("Must have at least one %s key" % name) - return False - - for key in keys: - pdg = self.plotDataGatherer() - plot_function(self.shellContext(), pdg, key) - - return assertConfigLoaded(do_function) - - @classmethod - def _createCompleteFunction(cls): - def complete_function(self, text, line, begidx, endidx): - key = extractFullArgument(line, endidx) - return autoCompleteListWithSeparator(key, self.fetchSupportedKeys()) - - complete_function = assertConfigLoaded(complete_function) - return complete_function - - @classmethod - def addHistogramPlotSupport(cls, instance, name): - """ - :type instance: ert_gui.shell.libshell.ShellCollection - """ - cls._checkForRequiredMethods(instance) - - instance.addShellFunction(name="histogram", - function=cls._createDoFunction(ShellPlot.plotHistogram, name), - completer=cls._createCompleteFunction(), - help_arguments=" [key_2..key_n]", - help_message="Plot a histogram for the specified %s key(s)." % name) - - @classmethod - def addGaussianKDEPlotSupport(cls, instance, name): - """ - :type instance: ert_gui.shell.ShellFunction - """ - cls._checkForRequiredMethods(instance) - - instance.addShellFunction(name="density", - function=cls._createDoFunction(ShellPlot.plotGaussianKDE, name), - completer=cls._createCompleteFunction(), - help_arguments=" [key_2..key_n]", - help_message="Plot a GaussianKDE plot for the specified %s key(s)." % name) - - @classmethod - def addEnsemblePlotSupport(cls, instance, name): - """ - :type instance: ert_gui.shell.ShellFunction - """ - cls._checkForRequiredMethods(instance) - - instance.addShellFunction(name="plot", - function=cls._createDoFunction(ShellPlot.plotEnsemble, name), - completer=cls._createCompleteFunction(), - help_arguments=" [key_2..key_n]", - help_message="Plot an ensemble plot for the specified %s key(s)." % name) - - @classmethod - def addQuantilesPlotSupport(cls, instance, name): - """ - :type instance: ert_gui.shell.ShellFunction - """ - cls._checkForRequiredMethods(instance) - - instance.addShellFunction(name="plot_quantile", - function=cls._createDoFunction(ShellPlot.plotQuantiles, name), - completer=cls._createCompleteFunction(), - help_arguments=" [key_2..key_n]", - help_message="Plot a different statistics for the specified %s key(s)." % name) - - @classmethod - def addDistributionPlotSupport(cls, instance, name): - """ - :type instance: ert_gui.shell.ShellFunction - """ - cls._checkForRequiredMethods(instance) - instance.addShellFunction(name="distribution", - function=cls._createDoFunction(ShellPlot.plotDistribution, name), - completer=cls._createCompleteFunction(), - help_arguments=" [key_2..key_n]", - help_message="Plot the distribution plot for the specified %s key(s)." % name) - - @classmethod - def addCrossCaseStatisticsPlotSupport(cls, instance, name): - """ - :type instance: ert_gui.shell.ShellFunction - """ - cls._checkForRequiredMethods(instance) - instance.addShellFunction(name="cross_case_statistics", - function=cls._createDoFunction(ShellPlot.plotCrossCaseStatistics, name), - completer=cls._createCompleteFunction(), - help_arguments=" [key_2..key_n]", - help_message="Plot the cross case statistics plot for the specified %s key(s)." % name) - - @classmethod - def _createDoPrintFunction(cls, name): - def do_function(self, line): - keys = matchItems(line, self.fetchSupportedKeys()) - - if len(keys) == 0: - self.lastCommandFailed("Must have at least one %s key" % name) - return False - - case_name = self.shellContext().ert().getEnkfFsManager().getCurrentFileSystem().getCaseName() - - for key in keys: - pdg = self.plotDataGatherer() - if pdg.canGatherDataForKey(key): - data = pdg.gatherData(self.shellContext().ert(), case_name, key) - print(data) - else: - self.lastCommandFailed("Unable to print data for key: %s" % key) - - return assertConfigLoaded(do_function) - - @classmethod - def addPrintSupport(cls, instance, name): - """ - :type instance: ert_gui.shell.ShellFunction - """ - cls._checkForRequiredMethods(instance) - - instance.addShellFunction(name="print", - function=cls._createDoPrintFunction(name), - completer=cls._createCompleteFunction(), - help_arguments=" [key_2..key_n]", - help_message="Print the values for the specified %s key(s)." % name) diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/simulations.py b/ThirdParty/Ert/python/python/ert_gui/shell/simulations.py deleted file mode 100644 index b8ca252347..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/simulations.py +++ /dev/null @@ -1,58 +0,0 @@ -import time -from datetime import datetime - -from ert.enkf import EnkfSimulationRunner -from ert.enkf.enums import HookRuntime -from ert_gui.shell import assertConfigLoaded, ErtShellCollection - - -class Simulations(ErtShellCollection): - def __init__(self, parent): - super(Simulations, self).__init__("simulations", parent) - self.addShellFunction(name="settings", - function=Simulations.settings, - help_message="Show simulations settings.") - - self.addShellFunction(name="ensemble_experiment", - function=Simulations.ensembleExperiment, - help_message="Run Ensemble Experiment.") - - @assertConfigLoaded - def settings(self, line): - runpath = self.ert().getModelConfig().getRunpathAsString() - - iteration_count = self.ert().analysisConfig().getAnalysisIterConfig().getNumIterations() - realizations = self.ert().getEnsembleSize() - - print("Runpath: %s" % runpath) - print("Iteration count: %d" % iteration_count) - print("Realization count: %d" % realizations) - - @assertConfigLoaded - def ensembleExperiment(self, line): - simulation_runner = EnkfSimulationRunner(self.ert()) - - now = time.time() - print("Ensemble Experiment started at: %s" % datetime.now().isoformat(sep=" ")) - - iteration_count = 0 - active_realization_mask = BoolVector(default_value = True, initial_size = self.ert().getEnsembleSize()) - simulation_runner.createRunPath(active_realization_mask, iteration_count) - - simulation_runner.runWorkflows(HookRuntime.PRE_SIMULATION) - - print("Start simulations!") - num_successful_realizations = simulation_runner.runEnsembleExperiment() - - success = self.ert().analysisConfig().haveEnoughRealisations(num_successful_realizations, self.ert().getEnsembleSize()) - if not success: - print("Error: Number of successful realizations is too low.\nYou can allow more failed realizations by setting / changing the MIN_REALIZATIONS configuration element!") - return - - print("Ensemble Experiment post processing!") - simulation_runner.runWorkflows(HookRuntime.POST_SIMULATION) - - print("Ensemble Experiment completed at: %s" % datetime.now().isoformat(sep=" ")) - - diff = time.time() - now - print("Running time: %d seconds" % int(diff)) diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/smoother.py b/ThirdParty/Ert/python/python/ert_gui/shell/smoother.py deleted file mode 100644 index 72eeb68a90..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/smoother.py +++ /dev/null @@ -1,88 +0,0 @@ -from ert.enkf import ESUpdate -from ert_gui.shell import assertConfigLoaded, ErtShellCollection -from ert_gui.shell.libshell import splitArguments, createFloatValidator -from ert.enkf.enums import HookRuntime - -class Smoother(ErtShellCollection): - def __init__(self, parent): - super(Smoother, self).__init__("smoother", parent) - - self.addShellProperty(name="overlap_alpha", - getter=Smoother.getOverlapAlpha, - setter=Smoother.setOverlapAlpha, - validator=createFloatValidator(), - completer=None, - help_arguments="[alpha_value]", - help_message="Show or set the overlap alpha.", - pretty_attribute="Overlap Alpha") - - self.addShellProperty(name="std_cutoff", - getter=Smoother.getStdCutOff, - setter=Smoother.setStdCutOff, - validator=createFloatValidator(minimum=0), - completer=None, - help_arguments="[cutoff_value]", - help_message="Show or set the standard deviation cutoff value (>0).", - pretty_attribute="Standard Deviation Cutoff") - - self.addShellProperty(name="global_std_scaling", - getter=Smoother.getGlobalStdScaling, - setter=Smoother.setGlobalStdScaling, - validator=createFloatValidator(minimum=0), - completer=None, - help_arguments="[std_scaling]", - help_message="Show or set the global standard deviation scaling value (>0) applied to updates.", - pretty_attribute="Global Standard Deviation Scaling") - - self.addShellFunction(name="update", - function=Smoother.update, - help_arguments=" ", - help_message="Set a variable value.") - - - @assertConfigLoaded - def analysisConfig(self): - """ @rtype: ert.analysis.AnalysisConfig """ - return self.ert().analysisConfig() - - def setOverlapAlpha(self, value): - self.analysisConfig().setEnkfAlpha(value) - - def getOverlapAlpha(self): - return self.analysisConfig().getEnkfAlpha() - - def setStdCutOff(self, value): - self.analysisConfig().setStdCutoff(value) - - def getStdCutOff(self): - return self.analysisConfig().getStdCutoff() - - def setGlobalStdScaling(self, value): - self.analysisConfig().setGlobalStdScaling(value) - - def getGlobalStdScaling(self): - return self.analysisConfig().getGlobalStdScaling() - - @assertConfigLoaded - def update(self, line): - arguments = splitArguments(line) - - if len(arguments) == 1: - case_name = arguments[0] - ert = self.ert() - fs_manager = ert.getEnkfFsManager() - - ert.getEnkfSimulationRunner().runWorkflows(HookRuntime.PRE_UPDATE) - - es_update = ESUpdate( ert ) - target_fs = fs_manager.getFileSystem(case_name) - source_fs = fs_manager.getCurrentFileSystem( ) - success = es_update.smootherUpdate( source_fs , target_fs ) - - if not success: - self.lastCommandFailed("Unable to perform update") - - ert.getEnkfSimulationRunner().runWorkflows(HookRuntime.POST_UPDATE) - - else: - self.lastCommandFailed("Expected one argument: received: '%s'" % line) diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/storage.py b/ThirdParty/Ert/python/python/ert_gui/shell/storage.py deleted file mode 100644 index ef08aeeb32..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/storage.py +++ /dev/null @@ -1,90 +0,0 @@ -import ert -from ert_gui.shell import ErtShellCollection -from ert_gui.shell.libshell import splitArguments, getPossibleFilenameCompletions, extractFullArgument - - -import ctypes -import os - -NO_SORT = 0 -STRING_SORT = 1 -OFFSET_SORT = 2 - -import cwrap.clib as clib -UTIL_LIB = ert.load("libert_util") - -UTIL_LIB.block_fs_is_mount.restype = ctypes.c_bool -UTIL_LIB.block_fs_mount.restype = ctypes.c_void_p -UTIL_LIB.block_fs_alloc_filelist.restype = ctypes.c_void_p -UTIL_LIB.block_fs_close.restype = ctypes.c_void_p - -UTIL_LIB.vector_get_size.restype = ctypes.c_int -UTIL_LIB.vector_iget_const.restype = ctypes.c_void_p -UTIL_LIB.vector_free.restype = ctypes.c_void_p - -UTIL_LIB.user_file_node_get_filename.restype = ctypes.c_char_p -UTIL_LIB.user_file_node_get_data_size.restype = ctypes.c_int -UTIL_LIB.user_file_node_get_node_offset.restype = ctypes.c_long - -class Storage(ErtShellCollection): - def __init__(self, parent): - super(Storage, self).__init__("storage", parent) - - self.addShellFunction(name="ls", - function=Storage.ls, - completer=Storage.completeLs, - help_arguments=" [wildcard_pattern]", - help_message="Will list all elements in 'block_file' matching optional 'wildcard_pattern'") - - def ls(self, line): - arguments = splitArguments(line) - - if len(arguments) == 0: - self.lastCommandFailed("A 'block file' is required.") - else: - block_file = arguments[0] - pattern = None if len(arguments) == 1 else arguments[1] - - if not os.path.isfile(block_file): - self.lastCommandFailed("The path: '%s' is not a file." % block_file) - else: - if not UTIL_LIB.block_fs_is_mount(block_file): - _, filename = os.path.split(block_file) - self.lastCommandFailed("The file: '%s' is not a block mount file." % filename) - else: - block_fs = UTIL_LIB.block_fs_mount(block_file, 1, 0, 1, 0, False, True, False) - files = UTIL_LIB.block_fs_alloc_filelist(block_fs, pattern, OFFSET_SORT, False) - - file_count = UTIL_LIB.vector_get_size(files) - - if file_count > 0: - fmt = " %-40s %10d %10d" - print(" %-40s %10s %10s" % ("Keyword", "Size", "Offset")) - - for index in range(file_count): - node = UTIL_LIB.vector_iget_const(files, index) - node_filename = UTIL_LIB.user_file_node_get_filename(node) - node_size = UTIL_LIB.user_file_node_get_data_size(node) - node_offset = UTIL_LIB.user_file_node_get_node_offset(node) - print(fmt % (node_filename, node_size, node_offset)) - - UTIL_LIB.vector_free(files) - UTIL_LIB.block_fs_close(block_fs) - - - def completeLs(self, text, line, begidx, endidx): - arguments = splitArguments(line) - last_argument = extractFullArgument(line, endidx) - - if len(arguments) == 1 and len(text) == 0: - ert = self.ert() - if ert is not None: - return [ert.getModelConfig().getEnspath() + os.path.sep] - else: - return getPossibleFilenameCompletions("") - elif len(arguments) == 2 and len(last_argument) > 0: - return getPossibleFilenameCompletions(last_argument) - elif len(arguments) == 3 and len(text) > 0: - return [] # pattern completion... - else: - return [] diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/summary_keys.py b/ThirdParty/Ert/python/python/ert_gui/shell/summary_keys.py deleted file mode 100644 index 1d915bd505..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/summary_keys.py +++ /dev/null @@ -1,95 +0,0 @@ -from ert_gui.plottery import PlotDataGatherer as PDG -from ert_gui.shell import assertConfigLoaded, ShellPlot, ErtShellCollection -from ert_gui.shell.libshell import splitArguments - - -class SummaryKeys(ErtShellCollection): - def __init__(self, parent): - super(SummaryKeys, self).__init__("summary", parent) - - self.addShellFunction(name="list", - function=SummaryKeys.list, - help_message="Shows a list of all available Summary keys. (* = with observations)") - - self.addShellFunction(name="observations", - function=SummaryKeys.observations, - help_message= "Shows a list of all available Summary key observations.") - - self.addShellFunction(name="matchers", - function=SummaryKeys.matchers, - help_message="Shows a list of all Summary keys that the ensemble will match " - "against during simulations and manual load.") - - self.addShellFunction(name="add_matcher", - function=SummaryKeys.add_matcher, - help_arguments="", - help_message="Add a matcher to the Summary key matcher set.") - - self.__plot_data_gatherer = None - - ShellPlot.addPrintSupport(self, "Summary") - ShellPlot.addEnsemblePlotSupport(self, "Summary") - ShellPlot.addQuantilesPlotSupport(self, "Summary") - - - @assertConfigLoaded - def list(self, line): - keys = self.summaryKeys() - observation_keys = self.summaryObservationKeys() - - result = ["*%s" % key if key in observation_keys else " %s" % key for key in keys] - - self.columnize(result) - - @assertConfigLoaded - def observations(self, line): - keys = self.summaryKeys() - - observation_keys = [] - for key in keys: - obs_keys = self.ert().ensembleConfig().getNode(key).getObservationKeys() - observation_keys.extend(obs_keys) - - self.columnize(observation_keys) - - @assertConfigLoaded - def matchers(self, line): - ensemble_config = self.ert().ensembleConfig() - summary_key_matcher = ensemble_config.getSummaryKeyMatcher() - keys = sorted(["!%s" % key if summary_key_matcher.isRequired(key) else " %s" % key for key in summary_key_matcher.keys()]) - - self.columnize(keys) - - @assertConfigLoaded - def add_matcher(self, line): - args = splitArguments(line) - - if len(args) < 1: - self.lastCommandFailed("A Summary key is required.") - return False - - self.ert().ensembleConfig().getSummaryKeyMatcher().addSummaryKey(args[0].strip()) - - - def summaryKeys(self): - return self.ert().getKeyManager().summaryKeys() - - - def summaryObservationKeys(self): - return self.ert().getKeyManager().summaryKeysWithObservations() - - - def fetchSupportedKeys(self): - return self.summaryKeys() - - - def plotDataGatherer(self): - if self.__plot_data_gatherer is None: - summary_pdg = PDG.gatherSummaryData - summary_key_manager = self.ert().getKeyManager().isSummaryKey - refcase_pdg = PDG.gatherSummaryRefcaseData - observation_pdg = PDG.gatherSummaryObservationData - pdg = PDG(summary_pdg, summary_key_manager, refcaseGatherFunc=refcase_pdg, observationGatherFunc=observation_pdg) - self.__plot_data_gatherer = pdg - - return self.__plot_data_gatherer diff --git a/ThirdParty/Ert/python/python/ert_gui/shell/workflows.py b/ThirdParty/Ert/python/python/ert_gui/shell/workflows.py deleted file mode 100644 index c2c65c43cb..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/shell/workflows.py +++ /dev/null @@ -1,48 +0,0 @@ -from ert.job_queue import WorkflowRunner -from ert_gui.shell import assertConfigLoaded, ErtShellCollection -from ert_gui.shell.libshell import autoCompleteList - - -class Workflows(ErtShellCollection): - def __init__(self, parent): - super(Workflows, self).__init__("workflows", parent) - - self.addShellFunction(name="list", - function=Workflows.list, - help_message="Shows a list of all available workflows.") - - self.addShellFunction(name="run", - function=Workflows.run, - completer=Workflows.completeRun, - help_arguments="", - help_message="Run a named workflow.") - - def getWorkflowNames(self): - return [workflow for workflow in self.ert().getWorkflowList().getWorkflowNames()] - - @assertConfigLoaded - def list(self, line): - workflows = self.getWorkflowNames() - if len(workflows) > 0: - self.columnize(workflows) - else: - print("No workflows available.") - - @assertConfigLoaded - def run(self, workflow): - workflow = workflow.strip() - if workflow in self.getWorkflowNames(): - workflow_list = self.ert().getWorkflowList() - workflow = workflow_list[workflow] - context = workflow_list.getContext() - - runner = WorkflowRunner(workflow, self.ert(), context) - runner.run() - runner.wait() - else: - self.lastCommandFailed("Unknown workflow: '%s'" % workflow) - - @assertConfigLoaded - def completeRun(self, text, line, begidx, endidx): - return autoCompleteList(text, self.getWorkflowNames()) - diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/simulation/CMakeLists.txt deleted file mode 100644 index 76c0e02957..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - ensemble_experiment_panel.py - ensemble_smoother_panel.py - iterated_ensemble_smoother_panel.py - multiple_data_assimilation_panel.py - progress.py - run_dialog.py - simple_progress.py - simulation_config_panel.py - simulation_panel.py -) - -add_python_package("python.ert_gui.simulation" ${PYTHON_INSTALL_PREFIX}/ert_gui/simulation "${PYTHON_SOURCES}" True) - -add_subdirectory(models) diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/__init__.py b/ThirdParty/Ert/python/python/ert_gui/simulation/__init__.py deleted file mode 100644 index 4c029f1732..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from .progress import Progress -from .simple_progress import SimpleProgress -from .run_dialog import RunDialog -from .simulation_config_panel import SimulationConfigPanel -from .ensemble_experiment_panel import EnsembleExperimentPanel -from .ensemble_smoother_panel import EnsembleSmootherPanel -from .iterated_ensemble_smoother_panel import IteratedEnsembleSmootherPanel -from .multiple_data_assimilation_panel import MultipleDataAssimilationPanel - diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/ensemble_experiment_panel.py b/ThirdParty/Ert/python/python/ert_gui/simulation/ensemble_experiment_panel.py deleted file mode 100644 index ca62e11a36..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/ensemble_experiment_panel.py +++ /dev/null @@ -1,52 +0,0 @@ -from PyQt4.QtGui import QFormLayout, QLabel - -from ert_gui.ertwidgets import addHelpToWidget -from ert_gui.ertwidgets.caseselector import CaseSelector -from ert_gui.ertwidgets.models.activerealizationsmodel import ActiveRealizationsModel -from ert_gui.ertwidgets.models.ertmodel import getRealizationCount, getRunPath -from ert_gui.ertwidgets.stringbox import StringBox -from ert_gui.ide.keywords.definitions import RangeStringArgument -from ert_gui.simulation.models import EnsembleExperiment -from ert_gui.simulation.simulation_config_panel import SimulationConfigPanel - - -class EnsembleExperimentPanel(SimulationConfigPanel): - - def __init__(self): - SimulationConfigPanel.__init__(self, EnsembleExperiment()) - - layout = QFormLayout() - - case_selector = CaseSelector() - layout.addRow("Current case:", case_selector) - - run_path_label = QLabel("%s" % getRunPath()) - addHelpToWidget(run_path_label, "config/simulation/runpath") - layout.addRow("Runpath:", run_path_label) - - number_of_realizations_label = QLabel("%d" % getRealizationCount()) - addHelpToWidget(number_of_realizations_label, "config/ensemble/num_realizations") - layout.addRow(QLabel("Number of realizations:"), number_of_realizations_label) - - self._active_realizations_model = ActiveRealizationsModel() - self._active_realizations_field = StringBox(self._active_realizations_model, "config/simulation/active_realizations") - self._active_realizations_field.setValidator(RangeStringArgument(getRealizationCount())) - layout.addRow("Active realizations", self._active_realizations_field) - - self._active_realizations_field.getValidationSupport().validationChanged.connect(self.simulationConfigurationChanged) - - self.setLayout(layout) - - - def isConfigurationValid(self): - return self._active_realizations_field.isValid() - - def toggleAdvancedOptions(self, show_advanced): - self._active_realizations_field.setVisible(show_advanced) - self.layout().labelForField(self._active_realizations_field).setVisible(show_advanced) - - def getSimulationArguments(self): - active_realizations_mask = self._active_realizations_model.getActiveRealizationsMask() - return {"active_realizations": active_realizations_mask} - - diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/ensemble_smoother_panel.py b/ThirdParty/Ert/python/python/ert_gui/simulation/ensemble_smoother_panel.py deleted file mode 100644 index def973caf9..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/ensemble_smoother_panel.py +++ /dev/null @@ -1,64 +0,0 @@ -from PyQt4.QtGui import QFormLayout, QLabel - -from ert_gui.ertwidgets import addHelpToWidget, AnalysisModuleSelector -from ert_gui.ertwidgets.caseselector import CaseSelector -from ert_gui.ertwidgets.models.activerealizationsmodel import ActiveRealizationsModel -from ert_gui.ertwidgets.models.ertmodel import getRealizationCount, getRunPath -from ert_gui.ertwidgets.models.targetcasemodel import TargetCaseModel -from ert_gui.ertwidgets.stringbox import StringBox -from ert_gui.ide.keywords.definitions import RangeStringArgument, ProperNameArgument -from ert_gui.simulation import SimulationConfigPanel -from ert_gui.simulation.models import EnsembleSmoother - - -class EnsembleSmootherPanel(SimulationConfigPanel): - def __init__(self): - SimulationConfigPanel.__init__(self, EnsembleSmoother()) - - layout = QFormLayout() - - case_selector = CaseSelector() - layout.addRow("Current case:", case_selector) - - run_path_label = QLabel("%s" % getRunPath()) - addHelpToWidget(run_path_label, "config/simulation/runpath") - layout.addRow("Runpath:", run_path_label) - - number_of_realizations_label = QLabel("%d" % getRealizationCount()) - addHelpToWidget(number_of_realizations_label, "config/ensemble/num_realizations") - layout.addRow(QLabel("Number of realizations:"), number_of_realizations_label) - - self._target_case_model = TargetCaseModel() - self._target_case_field = StringBox(self._target_case_model, "config/simulation/target_case") - self._target_case_field.setValidator(ProperNameArgument()) - layout.addRow("Target case:", self._target_case_field) - - self._analysis_module_selector = AnalysisModuleSelector(iterable=False, help_link="config/analysis/analysis_module") - layout.addRow("Analysis Module:", self._analysis_module_selector) - - self._active_realizations_model = ActiveRealizationsModel() - self._active_realizations_field = StringBox(self._active_realizations_model, "config/simulation/active_realizations") - self._active_realizations_field.setValidator(RangeStringArgument(getRealizationCount())) - layout.addRow("Active realizations", self._active_realizations_field) - - self._target_case_field.getValidationSupport().validationChanged.connect(self.simulationConfigurationChanged) - self._active_realizations_field.getValidationSupport().validationChanged.connect(self.simulationConfigurationChanged) - - self.setLayout(layout) - - def isConfigurationValid(self): - return self._target_case_field.isValid() and self._active_realizations_field.isValid() - - def toggleAdvancedOptions(self, show_advanced): - self._active_realizations_field.setVisible(show_advanced) - self.layout().labelForField(self._active_realizations_field).setVisible(show_advanced) - - self._analysis_module_selector.setVisible(show_advanced) - self.layout().labelForField(self._analysis_module_selector).setVisible(show_advanced) - - def getSimulationArguments(self): - arguments = {"active_realizations": self._active_realizations_model.getActiveRealizationsMask(), - "target_case": self._target_case_model.getValue(), - "analysis_module": self._analysis_module_selector.getSelectedAnalysisModuleName() - } - return arguments diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/iterated_ensemble_smoother_panel.py b/ThirdParty/Ert/python/python/ert_gui/simulation/iterated_ensemble_smoother_panel.py deleted file mode 100644 index ff4bb79457..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/iterated_ensemble_smoother_panel.py +++ /dev/null @@ -1,78 +0,0 @@ -from PyQt4.QtGui import QFormLayout, QLabel, QSpinBox - -from ert_gui.ertwidgets import addHelpToWidget, AnalysisModuleSelector, CaseSelector -from ert_gui.ertwidgets.models.activerealizationsmodel import ActiveRealizationsModel -from ert_gui.ertwidgets.models.ertmodel import getRealizationCount, getRunPath, setNumberOfIterations, getNumberOfIterations -from ert_gui.ertwidgets.models.targetcasemodel import TargetCaseModel -from ert_gui.ertwidgets.stringbox import StringBox -from ert_gui.ide.keywords.definitions import RangeStringArgument, ProperNameFormatArgument -from ert_gui.simulation import SimulationConfigPanel -from ert_gui.simulation.models import IteratedEnsembleSmoother - - -class IteratedEnsembleSmootherPanel(SimulationConfigPanel): - def __init__(self, advanced_option=False): - SimulationConfigPanel.__init__(self, IteratedEnsembleSmoother(), advanced_option) - - layout = QFormLayout() - - case_selector = CaseSelector() - layout.addRow("Current case:", case_selector) - - run_path_label = QLabel("%s" % getRunPath()) - addHelpToWidget(run_path_label, "config/simulation/runpath") - layout.addRow("Runpath:", run_path_label) - - number_of_realizations_label = QLabel("%d" % getRealizationCount()) - addHelpToWidget(number_of_realizations_label, "config/ensemble/num_realizations") - layout.addRow(QLabel("Number of realizations:"), number_of_realizations_label) - - # The num_iterations_spinner does not track any external changes (will that ever happen?) - num_iterations_spinner = QSpinBox() - num_iterations_spinner.setMinimum(1) - num_iterations_spinner.setMaximum(100) - num_iterations_spinner.setValue(getNumberOfIterations()) - addHelpToWidget(num_iterations_spinner, "config/simulation/number_of_iterations") - num_iterations_spinner.valueChanged[int].connect(setNumberOfIterations) - - layout.addRow("Number of iterations:", num_iterations_spinner) - - self._iterated_target_case_format_model = TargetCaseModel(format_mode=True) - self._iterated_target_case_format_field = StringBox(self._iterated_target_case_format_model, "config/simulation/iterated_target_case_format") - self._iterated_target_case_format_field.setValidator(ProperNameFormatArgument()) - layout.addRow("Target case format:", self._iterated_target_case_format_field) - - - self._analysis_module_selector = AnalysisModuleSelector(iterable=True, help_link="config/analysis/analysis_module") - layout.addRow("Analysis Module:", self._analysis_module_selector) - - self._active_realizations_model = ActiveRealizationsModel() - self._active_realizations_field = StringBox(self._active_realizations_model, "config/simulation/active_realizations") - self._active_realizations_field.setValidator(RangeStringArgument(getRealizationCount())) - layout.addRow("Active realizations", self._active_realizations_field) - - - self._iterated_target_case_format_field.getValidationSupport().validationChanged.connect(self.simulationConfigurationChanged) - self._active_realizations_field.getValidationSupport().validationChanged.connect(self.simulationConfigurationChanged) - - self.setLayout(layout) - - def isConfigurationValid(self): - analysis_module = self._analysis_module_selector.getSelectedAnalysisModuleName() - return self._iterated_target_case_format_field.isValid() and self._active_realizations_field.isValid() and analysis_module is not None - - - def toggleAdvancedOptions(self, show_advanced): - self._active_realizations_field.setVisible(show_advanced) - self.layout().labelForField(self._active_realizations_field).setVisible(show_advanced) - - self._analysis_module_selector.setVisible(show_advanced) - self.layout().labelForField(self._analysis_module_selector).setVisible(show_advanced) - - - def getSimulationArguments(self): - arguments = {"active_realizations": self._active_realizations_model.getActiveRealizationsMask(), - "target_case": self._iterated_target_case_format_model.getValue(), - "analysis_module": self._analysis_module_selector.getSelectedAnalysisModuleName() - } - return arguments diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/models/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/simulation/models/CMakeLists.txt deleted file mode 100644 index 630b7ae43a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/models/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - base_run_model.py - ensemble_experiment.py - ensemble_smoother.py - iterated_ensemble_smoother.py - multiple_data_assimilation.py - simulations_tracker.py -) - -add_python_package("python.ert_gui.simulation.models" ${PYTHON_INSTALL_PREFIX}/ert_gui/simulation/models "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/models/__init__.py b/ThirdParty/Ert/python/python/ert_gui/simulation/models/__init__.py deleted file mode 100644 index 8f0b2301a3..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/models/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from .base_run_model import BaseRunModel, ErtRunError -from .ensemble_experiment import EnsembleExperiment -from .ensemble_smoother import EnsembleSmoother -from .iterated_ensemble_smoother import IteratedEnsembleSmoother -from .multiple_data_assimilation import MultipleDataAssimilation -from .simulations_tracker import SimulationsTracker \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/models/base_run_model.py b/ThirdParty/Ert/python/python/ert_gui/simulation/models/base_run_model.py deleted file mode 100644 index 1297174fe6..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/models/base_run_model.py +++ /dev/null @@ -1,206 +0,0 @@ -import time -from ert.job_queue import JobStatusType -from ert_gui import ERT -from ert.enkf import ErtLog - - -class ErtRunError(Exception): - pass - -class BaseRunModel(object): - - def __init__(self, name, phase_count=1): - super(BaseRunModel, self).__init__() - self._name = name - self._phase = 0 - self._phase_count = phase_count - self._phase_update_count = 0 - self._phase_name = "Not defined" - - self._job_start_time = 0 - self._job_stop_time = 0 - self._indeterminate = False - self._fail_message = "" - self._failed = False - self.reset( ) - - - def ert(self): - """ @rtype: ert.enkf.EnKFMain""" - return ERT.ert - - def reset(self): - self._failed = False - - - def startSimulations(self, run_arguments): - try: - self.runSimulations(run_arguments) - except ErtRunError as e: - self._failed = True - self._fail_message = str(e) - self._simulationEnded() - - - def runSimulations(self, run_arguments): - raise NotImplementedError("Method must be implemented by inheritors!") - - - def killAllSimulations(self): - job_queue = self.ert().siteConfig().getJobQueue() - job_queue.killAllJobs() - - - def userExitCalled(self): - """ @rtype: bool """ - job_queue = self.ert().siteConfig().getJobQueue() - return job_queue.getUserExit( ) - - - def phaseCount(self): - """ @rtype: int """ - return self._phase_count - - - def setPhaseCount(self, phase_count): - self._phase_count = phase_count - self.setPhase(0, "") - - - def currentPhase(self): - """ @rtype: int """ - return self._phase - - - def setPhaseName(self, phase_name, indeterminate=None): - self._phase_name = phase_name - self.setIndeterminate(indeterminate) - - - def getPhaseName(self): - """ @rtype: str """ - return self._phase_name - - - def setIndeterminate(self, indeterminate): - if indeterminate is not None: - self._indeterminate = indeterminate - - - def isFinished(self): - """ @rtype: bool """ - return self._phase == self._phase_count or self.hasRunFailed() - - - def hasRunFailed(self): - """ @rtype: bool """ - return self._failed - - - def getFailMessage(self): - """ @rtype: str """ - return self._fail_message - - - def _simulationEnded(self): - self._job_stop_time = int(time.time()) - - - def setPhase(self, phase, phase_name, indeterminate=None): - self.setPhaseName(phase_name) - if not 0 <= phase <= self._phase_count: - raise ValueError("Phase must be an integer from 0 to less than %d." % self._phase_count) - - self.setIndeterminate(indeterminate) - - if phase == 0: - self._job_start_time = int(time.time()) - - if phase == self._phase_count: - self._simulationEnded() - - self._phase = phase - self._phase_update_count = 0 - - - def getRunningTime(self): - """ @rtype: float """ - if self._job_stop_time < self._job_start_time: - return time.time() - self._job_start_time - else: - return self._job_stop_time - self._job_start_time - - - def getQueueSize(self): - """ @rtype: int """ - queue_size = len(self.ert().siteConfig().getJobQueue()) - - if queue_size == 0: - queue_size = 1 - - return queue_size - - - def getQueueStatus(self): - """ @rtype: dict of (JobStatusType, int) """ - job_queue = self.ert().siteConfig().getJobQueue() - - queue_status = {} - - if job_queue.isRunning(): - for job_number in range(len(job_queue)): - status = job_queue.getJobStatus(job_number) - - if not status in queue_status: - queue_status[status] = 0 - - queue_status[status] += 1 - - return queue_status - - def isQueueRunning(self): - """ @rtype: bool """ - return self.ert().siteConfig().getJobQueue().isRunning() - - - def getProgress(self): - """ @rtype: float """ - if self.isFinished(): - current_progress = 1.0 - elif not self.isQueueRunning() and self._phase_update_count > 0: - current_progress = (self._phase + 1.0) / self._phase_count - else: - self._phase_update_count += 1 - queue_status = self.getQueueStatus() - queue_size = self.getQueueSize() - - done_state = JobStatusType.JOB_QUEUE_SUCCESS | JobStatusType.JOB_QUEUE_DONE - done_count = 0 - - for state in queue_status: - if state in done_state: - done_count += queue_status[state] - - phase_progress = float(done_count) / queue_size - current_progress = (self._phase + phase_progress) / self._phase_count - - return current_progress - - - def isIndeterminate(self): - """ @rtype: bool """ - return not self.isFinished() and self._indeterminate - - - def checkHaveSufficientRealizations(self, num_successful_realizations): - if num_successful_realizations == 0: - raise ErtRunError("Simulation failed! All realizations failed!") - elif not self.ert().analysisConfig().haveEnoughRealisations(num_successful_realizations, self.ert().getEnsembleSize()): - raise ErtRunError("Too many simulations have failed! You can add/adjust MIN_REALIZATIONS to allow failures in your simulations.\n\n" - "Check ERT log file '%s' or simulation folder for details." % ErtLog.getFilename()) - - - def __str__(self): - return self._name - - diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/models/ensemble_experiment.py b/ThirdParty/Ert/python/python/ert_gui/simulation/models/ensemble_experiment.py deleted file mode 100644 index 26bc7947c9..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/models/ensemble_experiment.py +++ /dev/null @@ -1,30 +0,0 @@ -from ert.enkf.enums import HookRuntime -from ert_gui.simulation.models import BaseRunModel, ErtRunError - - -class EnsembleExperiment(BaseRunModel): - - def __init__(self): - super(EnsembleExperiment, self).__init__("Ensemble Experiment") - - def runSimulations(self, arguments): - self.setPhase(0, "Running simulations...", indeterminate=False) - active_realization_mask = arguments["active_realizations"] - - self.setPhaseName("Pre processing...", indeterminate=True) - self.ert().getEnkfSimulationRunner().createRunPath(active_realization_mask, 0) - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.PRE_SIMULATION ) - - self.setPhaseName("Running ensemble experiment...", indeterminate=False) - - num_successful_realizations = self.ert().getEnkfSimulationRunner().runEnsembleExperiment(active_realization_mask) - - self.checkHaveSufficientRealizations(num_successful_realizations) - - self.setPhaseName("Post processing...", indeterminate=True) - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.POST_SIMULATION ) - - self.setPhase(1, "Simulations completed.") # done... - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/models/ensemble_smoother.py b/ThirdParty/Ert/python/python/ert_gui/simulation/models/ensemble_smoother.py deleted file mode 100644 index 0b2d3001b6..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/models/ensemble_smoother.py +++ /dev/null @@ -1,65 +0,0 @@ -from ert.enkf.enums import EnkfInitModeEnum -from ert.enkf.enums import HookRuntime -from ert_gui.simulation.models import BaseRunModel, ErtRunError - - -class EnsembleSmoother(BaseRunModel): - - def __init__(self): - super(EnsembleSmoother, self).__init__(name="Ensemble Smoother", phase_count=2) - - def setAnalysisModule(self, module_name): - module_load_success = self.ert().analysisConfig().selectModule(module_name) - - if not module_load_success: - raise ErtRunError("Unable to load analysis module '%s'!" % module_name) - - - def runSimulations(self, arguments): - self.setPhase(0, "Running simulations...", indeterminate=False) - - self.setAnalysisModule(arguments["analysis_module"]) - active_realization_mask = arguments["active_realizations"] - - self.setPhaseName("Pre processing...", indeterminate=True) - self.ert().getEnkfSimulationRunner().createRunPath(active_realization_mask, 0) - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.PRE_SIMULATION ) - - self.setPhaseName("Running forecast...", indeterminate=False) - num_successful_realizations = self.ert().getEnkfSimulationRunner().runSimpleStep(active_realization_mask, EnkfInitModeEnum.INIT_CONDITIONAL , 0) - - self.checkHaveSufficientRealizations(num_successful_realizations) - - self.setPhaseName("Post processing...", indeterminate=True) - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.POST_SIMULATION ) - - self.setPhaseName("Analyzing...") - - target_case_name = arguments["target_case"] - target_fs = self.ert().getEnkfFsManager().getFileSystem(target_case_name) - source_fs = self.ert().getEnkfFsManager().getCurrentFileSystem() - - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.PRE_UPDATE ) - es_update = self.ert().getESUpdate( ) - success = es_update.smootherUpdate(source_fs, target_fs) - if not success: - raise ErtRunError("Analysis of simulation failed!") - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.POST_UPDATE ) - - self.setPhase(1, "Running simulations...") - self.ert().getEnkfFsManager().switchFileSystem(target_fs) - - self.setPhaseName("Pre processing...") - self.ert().getEnkfSimulationRunner().createRunPath(active_realization_mask, 1) - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.PRE_SIMULATION ) - - self.setPhaseName("Running forecast...", indeterminate=False) - - num_successful_realizations = self.ert().getEnkfSimulationRunner().runSimpleStep(active_realization_mask, EnkfInitModeEnum.INIT_NONE, 1) - - self.checkHaveSufficientRealizations(num_successful_realizations) - - self.setPhaseName("Post processing...", indeterminate=True) - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.POST_SIMULATION ) - - self.setPhase(2, "Simulations completed.") diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/models/iterated_ensemble_smoother.py b/ThirdParty/Ert/python/python/ert_gui/simulation/models/iterated_ensemble_smoother.py deleted file mode 100644 index aa7907821d..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/models/iterated_ensemble_smoother.py +++ /dev/null @@ -1,109 +0,0 @@ -from ert.enkf.enums import EnkfInitModeEnum, HookRuntime -from ert_gui.ertwidgets.models.ertmodel import getNumberOfIterations -from ert_gui.simulation.models import BaseRunModel, ErtRunError - - -class IteratedEnsembleSmoother(BaseRunModel): - - def __init__(self): - super(IteratedEnsembleSmoother, self).__init__(name="Iterated Ensemble Smoother", phase_count=2) - - def setAnalysisModule(self, module_name): - module_load_success = self.ert().analysisConfig().selectModule(module_name) - - if not module_load_success: - raise ErtRunError("Unable to load analysis module '%s'!" % module_name) - - return self.ert().analysisConfig().getModule(module_name) - - - def runAndPostProcess(self, active_realization_mask, phase, phase_count, mode): - self.setPhase(phase, "Running iteration %d of %d simulation iterations..." % (phase, phase_count - 1), indeterminate=False) - - self.setPhaseName("Pre processing...", indeterminate=True) - self.ert().getEnkfSimulationRunner().createRunPath(active_realization_mask, phase) - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.PRE_SIMULATION ) - - self.setPhaseName("Running forecast...", indeterminate=False) - num_successful_realizations = self.ert().getEnkfSimulationRunner().runSimpleStep(active_realization_mask, mode, phase) - - self.checkHaveSufficientRealizations(num_successful_realizations) - - self.setPhaseName("Post processing...", indeterminate=True) - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.POST_SIMULATION ) - - - def createTargetCaseFileSystem(self, phase, target_case_format): - target_fs = self.ert().getEnkfFsManager().getFileSystem(target_case_format % phase) - return target_fs - - - def analyzeStep(self, target_fs): - self.setPhaseName("Analyzing...", indeterminate=True) - source_fs = self.ert().getEnkfFsManager().getCurrentFileSystem() - - self.setPhaseName("Pre processing update...", indeterminate=True) - EnkfSimulationRunner(ert).runWorkflows(HookRuntime.PRE_UPDATE) - es_update = self.ert().getESUpdate() - - success = es_update.smootherUpdate(source_fs, target_fs) - if not success: - raise ErtRunError("Analysis of simulation failed!") - - self.setPhaseName("Post processing update...", indeterminate=True) - EnkfSimulationRunner(ert).runWorkflows(HookRuntime.POST_UPDATE) - - def runSimulations(self, arguments): - phase_count = getNumberOfIterations() + 1 - self.setPhaseCount(phase_count) - - analysis_module = self.setAnalysisModule(arguments["analysis_module"]) - active_realization_mask = arguments["active_realizations"] - target_case_format = arguments["target_case"] - - source_fs = self.ert().getEnkfFsManager().getCurrentFileSystem() - initial_fs = self.createTargetCaseFileSystem(0, target_case_format) - - if not source_fs == initial_fs: - self.ert().getEnkfFsManager().switchFileSystem(initial_fs) - self.ert().getEnkfFsManager().initializeCurrentCaseFromExisting(source_fs, 0) - - self.runAndPostProcess(active_realization_mask, 0, phase_count, EnkfInitModeEnum.INIT_CONDITIONAL) - - self.ert().analysisConfig().getAnalysisIterConfig().setCaseFormat( target_case_format ) - - analysis_config = self.ert().analysisConfig() - analysis_iter_config = analysis_config.getAnalysisIterConfig() - num_retries_per_iteration = analysis_iter_config.getNumRetries() - num_tries = 0 - current_iteration = 1 - - while current_iteration <= getNumberOfIterations() and num_tries < num_retries_per_iteration: - target_fs = self.createTargetCaseFileSystem(current_iteration, target_case_format) - - pre_analysis_iter_num = analysis_module.getInt("ITER") - self.analyzeStep(target_fs) - post_analysis_iter_num = analysis_module.getInt("ITER") - - analysis_success = False - if post_analysis_iter_num > pre_analysis_iter_num: - analysis_success = True - - if analysis_success: - self.ert().getEnkfFsManager().switchFileSystem(target_fs) - self.runAndPostProcess(active_realization_mask, current_iteration, phase_count, EnkfInitModeEnum.INIT_NONE) - num_tries = 0 - current_iteration += 1 - else: - self.ert().getEnkfFsManager().initializeCurrentCaseFromExisting(target_fs, 0) - self.runAndPostProcess(active_realization_mask, current_iteration - 1 , phase_count, EnkfInitModeEnum.INIT_NONE) - num_tries += 1 - - - - if current_iteration == phase_count: - self.setPhase(phase_count, "Simulations completed.") - else: - raise ErtRunError("Iterated Ensemble Smoother stopped: maximum number of iteration retries (%d retries) reached for iteration %d" % (num_retries_per_iteration, current_iteration)) - - diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/models/multiple_data_assimilation.py b/ThirdParty/Ert/python/python/ert_gui/simulation/models/multiple_data_assimilation.py deleted file mode 100644 index 8dac4bb2d1..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/models/multiple_data_assimilation.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# This file is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from ert.enkf.enums import EnkfInitModeEnum -from ert.enkf.enums import HookRuntime - -from ert_gui.simulation.models import BaseRunModel, ErtRunError - - -class MultipleDataAssimilation(BaseRunModel): - """ - Run Multiple Data Assimilation (MDA) Ensemble Smoother with custom weights. - """ - - def __init__(self): - super(MultipleDataAssimilation, self).__init__(name="Multiple Data Assimilation (ES MDA)", phase_count=2) - self.weights = "3, 2, 1" # default value - - def getWeights(self): - return self.weights - - def setWeights(self, weights): - str_weights = str(weights) - print("Weights changed: %s" % str_weights) - self.weights = str_weights - - def setAnalysisModule(self, module_name): - module_load_success = self.ert().analysisConfig().selectModule(module_name) - - if not module_load_success: - raise ErtRunError("Unable to load analysis module '%s'!" % module_name) - - - def runSimulations(self, arguments): - weights = self.parseWeights(self.weights) - iteration_count = len(weights) - - self.setAnalysisModule(arguments["analysis_module"]) - - print("Running MDA ES for %s iterations\t%s" % (iteration_count, ", ".join(str(weight) for weight in weights))) - weights = self.normalizeWeights(weights) - - weight_string = ", ".join(str(round(weight,3)) for weight in weights) - print("Running MDA ES on (weights normalized)\t%s" % weight_string) - - - self.setPhaseCount(iteration_count+2) # pre + post + weights - - target_case_format = arguments["target_case"] - - source_fs = self.ert().getEnkfFsManager().getCurrentFileSystem() - target_case_name = target_case_format % 0 - target_fs = self.ert().getEnkfFsManager().getFileSystem(target_case_name) - - if not source_fs == target_fs: - self.ert().getEnkfFsManager().switchFileSystem(target_fs) - self.ert().getEnkfFsManager().initializeCurrentCaseFromExisting(source_fs, 0) - - active_realization_mask = arguments["active_realizations"] - - - phase_string = "Running MDA ES %d iteration%s." % (iteration_count, ('s' if (iteration_count != 1) else '')) - self.setPhaseName(phase_string, indeterminate=True) - - self.ert().getEnkfSimulationRunner().createRunPath(active_realization_mask, 1) - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.PRE_SIMULATION ) - - - for iteration, weight in enumerate(weights): - num_successful_realizations = self.simulateAndPostProcess(target_case_format, active_realization_mask, iteration) - - # We exit because the user has pressed 'Kill all simulations'. - if self.userExitCalled( ): - self.setPhase(iteration_count + 2, "Simulations stopped") - return - - # We exit if there are too few realisations left for updating. - self.checkHaveSufficientRealizations(num_successful_realizations) - - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.PRE_UPDATE ) - self.update(target_case_format, iteration, weights[iteration]) - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.POST_UPDATE ) - - self.setPhaseName("Post processing...", indeterminate=True) - self.simulateAndPostProcess(target_case_format, active_realization_mask, iteration_count) - - self.setPhase(iteration_count + 2, "Simulations completed.") - - - def update(self, target_case_format, iteration, weight): - source_fs = self.ert().getEnkfFsManager().getCurrentFileSystem() - next_iteration = (iteration + 1) - next_target_case_name = target_case_format % next_iteration - target_fs = self.ert().getEnkfFsManager().getFileSystem(next_target_case_name) - - phase_string = "Analyzing iteration: %d with weight %f" % (next_iteration, weight) - self.setPhase(self.currentPhase() + 1, phase_string, indeterminate=True) - - es_update = self.ert().getESUpdate( ) - es_update.setGlobalStdScaling(weight) - success = es_update.smootherUpdate(source_fs, target_fs) - - if not success: - raise UserWarning("Analysis of simulation failed for iteration: %d!" % next_iteration) - - - def simulateAndPostProcess(self, target_case_format, active_realization_mask, iteration): - target_case_name = target_case_format % iteration - - target_fs = self.ert().getEnkfFsManager().getFileSystem(target_case_name) - self.ert().getEnkfFsManager().switchFileSystem(target_fs) - - phase_string = "Running simulation for iteration: %d" % iteration - self.setPhaseName(phase_string, indeterminate=True) - self.ert().getEnkfSimulationRunner().createRunPath(active_realization_mask, iteration) - - phase_string = "Pre processing for iteration: %d" % iteration - self.setPhaseName(phase_string) - self.ert().getEnkfSimulationRunner().runWorkflows( HookRuntime.PRE_SIMULATION ) - - phase_string = "Running forecast for iteration: %d" % iteration - self.setPhaseName(phase_string, indeterminate=False) - num_successful_realizations = self.ert().getEnkfSimulationRunner().runSimpleStep(active_realization_mask, EnkfInitModeEnum.INIT_CONDITIONAL, iteration) - - phase_string = "Post processing for iteration: %d" % iteration - self.setPhaseName(phase_string, indeterminate=True) - self.ert().getEnkfSimulationRunner().runWorkflows(HookRuntime.POST_SIMULATION) - - return num_successful_realizations - - - @staticmethod - def normalizeWeights(weights): - """ :rtype: list of float """ - if not weights: - return [] - weights = [weight for weight in weights if abs(weight) != 0.0] - from math import sqrt - length = sqrt(sum((1.0 / x) * (1.0 / x) for x in weights)) - return [x * length for x in weights] - - - @staticmethod - def parseWeights(weights): - if not weights: - return [] - - elements = weights.split(",") - elements = [element.strip() for element in elements if not element.strip() == ""] - - result = [] - for element in elements: - try: - f = float(element) - if f == 0: - print('Warning: 0 weight, will ignore') - else: - result.append(f) - except ValueError: - raise ValueError('Warning: cannot parse weight %s' % element) - - return result diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/models/simulations_tracker.py b/ThirdParty/Ert/python/python/ert_gui/simulation/models/simulations_tracker.py deleted file mode 100644 index 0e684bb112..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/models/simulations_tracker.py +++ /dev/null @@ -1,87 +0,0 @@ -from ert.job_queue import JobStatusType - -class SimulationStateStatus(object): - COLOR_WAITING = (164, 164, 255) - COLOR_PENDING = (164, 200, 255) - COLOR_RUNNING = (200, 255, 200) - COLOR_FAILED = (255, 200, 200) - - COLOR_FINISHED = (200, 200, 200) - COLOR_NOT_ACTIVE = (255, 255, 255) - - def __init__(self, name, state, color): - self.__name = name - self.__state = state - self.__color = color - - self.__count = 0 - self.__total_count = 1 - - @property - def name(self): - return self.__name - - @property - def state(self): - return self.__state - - @property - def color(self): - return self.__color - - @property - def count(self): - return self.__count - - @count.setter - def count(self, value): - self.__count = value - - @property - def total_count(self): - return self.__total_count - - @total_count.setter - def total_count(self, value): - self.__total_count = value - - -class SimulationsTracker(object): - def __init__(self): - super(SimulationsTracker, self).__init__() - - waiting_flag = JobStatusType.JOB_QUEUE_NOT_ACTIVE | JobStatusType.JOB_QUEUE_WAITING | JobStatusType.JOB_QUEUE_SUBMITTED - waiting_state = SimulationStateStatus("Waiting", waiting_flag, SimulationStateStatus.COLOR_WAITING) - - pending_flag = JobStatusType.JOB_QUEUE_PENDING - pending_state = SimulationStateStatus("Pending", pending_flag, SimulationStateStatus.COLOR_PENDING) - - running_flag = JobStatusType.JOB_QUEUE_RUNNING | JobStatusType.JOB_QUEUE_EXIT | JobStatusType.JOB_QUEUE_RUNNING_CALLBACK - running_state = SimulationStateStatus("Running", running_flag, SimulationStateStatus.COLOR_RUNNING) - - # Failed also includes simulations which have been killed by the MAX_RUNTIME system. - failed_flag = JobStatusType.JOB_QUEUE_IS_KILLED | JobStatusType.JOB_QUEUE_DO_KILL - failed_flag |= JobStatusType.JOB_QUEUE_FAILED | JobStatusType.JOB_QUEUE_DO_KILL_NODE_FAILURE - failed_state = SimulationStateStatus("Failed", failed_flag, SimulationStateStatus.COLOR_FAILED) - - done_flag = JobStatusType.JOB_QUEUE_DONE | JobStatusType.JOB_QUEUE_SUCCESS - done_state = SimulationStateStatus("Finished", done_flag, SimulationStateStatus.COLOR_FINISHED) - - self.states = [waiting_state, pending_state, running_state, failed_state, done_state] - self.custom_states = [waiting_state, pending_state, running_state, failed_state, done_state] - - self.__checkForUnusedEnums() - - def getStates(self): - """ @rtype: list[SimulationStateStatus] """ - return list(self.custom_states) - - def __checkForUnusedEnums(self): - for enum in JobStatusType.enums(): - used = False - for state in self.states: - if enum in state.state: - used = True - - if not used: - raise AssertionError("Enum identifier '%s' not used!" % enum) diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/multiple_data_assimilation_panel.py b/ThirdParty/Ert/python/python/ert_gui/simulation/multiple_data_assimilation_panel.py deleted file mode 100644 index 724160656e..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/multiple_data_assimilation_panel.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# This file is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from PyQt4.QtGui import QFormLayout, QLabel - -from ert_gui.ertwidgets import addHelpToWidget, CaseSelector, ActiveLabel, AnalysisModuleSelector -from ert_gui.ertwidgets.models.activerealizationsmodel import ActiveRealizationsModel -from ert_gui.ertwidgets.models.ertmodel import getRealizationCount, getRunPath -from ert_gui.ertwidgets.models.targetcasemodel import TargetCaseModel -from ert_gui.ertwidgets.models.valuemodel import ValueModel -from ert_gui.ertwidgets.stringbox import StringBox -from ert_gui.ide.keywords.definitions import NumberListStringArgument, RangeStringArgument, ProperNameFormatArgument -from ert_gui.simulation import SimulationConfigPanel -from ert_gui.simulation.models import MultipleDataAssimilation - - -class MultipleDataAssimilationPanel(SimulationConfigPanel): - def __init__(self): - SimulationConfigPanel.__init__(self, MultipleDataAssimilation()) - - layout = QFormLayout() - - case_selector = CaseSelector() - layout.addRow("Current case:", case_selector) - - run_path_label = QLabel("%s" % getRunPath()) - addHelpToWidget(run_path_label, "config/simulation/runpath") - layout.addRow("Runpath:", run_path_label) - - number_of_realizations_label = QLabel("%d" % getRealizationCount()) - addHelpToWidget(number_of_realizations_label, "config/ensemble/num_realizations") - layout.addRow(QLabel("Number of realizations:"), number_of_realizations_label) - - self._target_case_format_model = TargetCaseModel(format_mode=True) - self._target_case_format_field = StringBox(self._target_case_format_model, "config/simulation/target_case_format") - self._target_case_format_field.setValidator(ProperNameFormatArgument()) - layout.addRow("Target case format:", self._target_case_format_field) - - self._createInputForWeights(layout) - - self._analysis_module_selector = AnalysisModuleSelector(iterable=False, help_link="config/analysis/analysis_module") - layout.addRow("Analysis Module:", self._analysis_module_selector) - - - self._active_realizations_model = ActiveRealizationsModel() - self._active_realizations_field = StringBox(self._active_realizations_model, "config/simulation/active_realizations") - self._active_realizations_field.setValidator(RangeStringArgument(getRealizationCount())) - layout.addRow("Active realizations", self._active_realizations_field) - - - self._target_case_format_field.getValidationSupport().validationChanged.connect(self.simulationConfigurationChanged) - self._active_realizations_field.getValidationSupport().validationChanged.connect(self.simulationConfigurationChanged) - self._relative_iteration_weights_box.getValidationSupport().validationChanged.connect(self.simulationConfigurationChanged) - - self.setLayout(layout) - - def _createInputForWeights(self, layout): - relative_iteration_weights_model = ValueModel(self.getSimulationModel().getWeights()) - self._relative_iteration_weights_box = StringBox(relative_iteration_weights_model, help_link="config/simulation/iteration_weights", continuous_update=True) - self._relative_iteration_weights_box.setValidator(NumberListStringArgument()) - layout.addRow("Relative Weights:", self._relative_iteration_weights_box) - - relative_iteration_weights_model.valueChanged.connect(self.getSimulationModel().setWeights) - - normalized_weights_model = ValueModel() - normalized_weights_widget = ActiveLabel(normalized_weights_model, help_link="config/simulation/iteration_weights") - layout.addRow('Normalized weights:', normalized_weights_widget) - - def updateVisualizationOfNormalizedWeights(): - if self._relative_iteration_weights_box.isValid(): - weights = MultipleDataAssimilation.parseWeights(relative_iteration_weights_model.getValue()) - normalized_weights = MultipleDataAssimilation.normalizeWeights(weights) - normalized_weights_model.setValue(", ".join("%.2f" % x for x in normalized_weights)) - else: - normalized_weights_model.setValue("The weights are invalid!") - - self._relative_iteration_weights_box.getValidationSupport().validationChanged.connect(updateVisualizationOfNormalizedWeights) - - updateVisualizationOfNormalizedWeights() # To normalize the default weights - - def isConfigurationValid(self): - return self._target_case_format_field.isValid() and self._active_realizations_field.isValid() and self._relative_iteration_weights_box.isValid() - - def toggleAdvancedOptions(self, show_advanced): - self._active_realizations_field.setVisible(show_advanced) - self.layout().labelForField(self._active_realizations_field).setVisible(show_advanced) - - self._analysis_module_selector.setVisible(show_advanced) - self.layout().labelForField(self._analysis_module_selector).setVisible(show_advanced) - - def getSimulationArguments(self): - arguments = {"active_realizations": self._active_realizations_model.getActiveRealizationsMask(), - "target_case": self._target_case_format_model.getValue(), - "analysis_module": self._analysis_module_selector.getSelectedAnalysisModuleName() - } - return arguments - diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/progress.py b/ThirdParty/Ert/python/python/ert_gui/simulation/progress.py deleted file mode 100644 index a6fb3aed16..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/progress.py +++ /dev/null @@ -1,123 +0,0 @@ -from math import floor -from PyQt4.QtCore import QTimer -from PyQt4.QtGui import QWidget, QPainter, QColor, QFrame, QLinearGradient - - -class StateTracker(object): - def __init__(self, state_reference, color, progress=0.0): - super(StateTracker, self).__init__() - self.name = state_reference - self.color = color - self.progress = progress - - def setProgress(self, progress): - self.progress = progress - - -class Progress(QFrame): - def __init__(self): - QFrame.__init__(self) - self.setLineWidth(1) - self.setFrameStyle(QFrame.Panel | QFrame.Plain) - - self.__color = QColor(255, 255, 255) - - self.setMinimumHeight(30) - self.__state_order = [] - """@type: list of State""" - - self.__states = {} - """@type: dict of (object, State)""" - - self.__shiny = False - self.__count = 0 - - self.__indeterminate = False - self.__indeterminate_color = QColor(128, 128, 128) - self.__indeterminate_state = 0.5 - self.__indeterminate_step_size = 0.05 - self.__timer = QTimer(self) - self.__timer.setInterval(100) - self.__timer.timeout.connect(self.update) - - def addState(self, state, state_color, progress=0.0): - state_tracker = StateTracker(state, state_color, progress) - self.__state_order.append(state_tracker) - self.__states[state] = state_tracker - - - def updateState(self, state, progress): - self.__count += 1 - self.__states[state].setProgress(progress) - self.update() - - - def setIndeterminate(self, indeterminate): - self.__indeterminate = indeterminate - if indeterminate: - self.__timer.start() - else: - self.__timer.stop() - - def setIndeterminateColor(self, color): - self.__indeterminate_color = color - - - def paintEvent(self, paint_event): - QFrame.paintEvent(self, paint_event) - painter = QPainter(self) - painter.setRenderHint(QPainter.Antialiasing, True) - painter.setRenderHint(QPainter.SmoothPixmapTransform, True) - - rect = self.contentsRect() - """@type: QRect""" - - painter.fillRect(rect, self.__color) - - x = rect.x() - y = rect.y() - width = rect.width() - height = rect.height() - - if not self.__indeterminate: - count = len(self.__state_order) - for index in range(count): - state = self.__state_order[index] - state_width = floor(width * (state.progress / 100.0)) - - if index == count - 1: - state_width = width - x + 1 - - painter.fillRect(x, y, state_width, height, state.color) - - x += state_width - else: - painter.fillRect(rect, self.__indeterminate_color) - - p = self.__indeterminate_state - s = self.__indeterminate_step_size - - gradient = QLinearGradient(0, rect.height() / 2, rect.width(), rect.height() / 2) - gradient.setColorAt(p - s, QColor(255, 255, 255, 0)) - gradient.setColorAt(p, QColor(255, 255, 255, 200)) - gradient.setColorAt(p + s, QColor(255, 255, 255, 0)) - painter.fillRect(rect, gradient) - - self.__indeterminate_state += s - - if self.__indeterminate_state + s >= 1.0 or self.__indeterminate_state + s <= 0.0: - self.__indeterminate_step_size *= -1 - self.__indeterminate_state = round(self.__indeterminate_state) + self.__indeterminate_step_size - - - - if self.__shiny: - #Shiny overlay! - gradient = QLinearGradient(rect.width() / 2, 0, rect.width() / 2, rect.height()) - gradient.setColorAt(0, QColor(255, 255, 255, 0)) - gradient.setColorAt(0.2, QColor(255, 255, 255, 200)) - gradient.setColorAt(0.4, QColor(255, 255, 255, 0)) - gradient.setColorAt(0.85, QColor(255, 255, 255, 0)) - gradient.setColorAt(0.85, QColor(0, 0, 0, 0)) - gradient.setColorAt(1, QColor(0, 0, 0, 127)) - painter.fillRect(rect, gradient) diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/run_dialog.py b/ThirdParty/Ert/python/python/ert_gui/simulation/run_dialog.py deleted file mode 100644 index e6ef13e211..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/run_dialog.py +++ /dev/null @@ -1,208 +0,0 @@ -from threading import Thread - -from PyQt4.QtCore import Qt, QTimer, QSize -from PyQt4.QtGui import QDialog, QVBoxLayout, QLayout, QMessageBox, QPushButton, QHBoxLayout, QColor, QLabel - -from ert_gui.ertwidgets import resourceMovie, Legend -from ert_gui.simulation import Progress, SimpleProgress -from ert_gui.simulation.models import BaseRunModel, SimulationsTracker -from ert_gui.tools.plot.plot_tool import PlotTool - - -class RunDialog(QDialog): - - def __init__(self, run_model, run_arguments, parent): - QDialog.__init__(self, parent) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint) - self.setModal(True) - self.setWindowModality(Qt.WindowModal) - self.setWindowTitle("Simulations") - - assert isinstance(run_model, BaseRunModel) - self._run_model = run_model - self._run_arguments = run_arguments - - layout = QVBoxLayout() - layout.setSizeConstraint(QLayout.SetFixedSize) - - self.simulations_tracker = SimulationsTracker() - states = self.simulations_tracker.getStates() - - self.total_progress = SimpleProgress() - layout.addWidget(self.total_progress) - - - status_layout = QHBoxLayout() - status_layout.addStretch() - self.__status_label = QLabel() - status_layout.addWidget(self.__status_label) - status_layout.addStretch() - layout.addLayout(status_layout) - - self.progress = Progress() - self.progress.setIndeterminateColor(self.total_progress.color) - for state in states: - self.progress.addState(state.state, QColor(*state.color), 100.0 * state.count / state.total_count) - - layout.addWidget(self.progress) - - legend_layout = QHBoxLayout() - self.legends = {} - for state in states: - self.legends[state] = Legend("%s (%d/%d)", QColor(*state.color)) - self.legends[state].updateLegend(state.name, 0, 0) - legend_layout.addWidget(self.legends[state]) - - layout.addLayout(legend_layout) - - self.running_time = QLabel("") - - ert = None - if isinstance(run_model, BaseRunModel): - ert = run_model.ert() - - self.plot_tool = PlotTool() - self.plot_tool.setParent(None) - self.plot_button = QPushButton(self.plot_tool.getName()) - self.plot_button.clicked.connect(self.plot_tool.trigger) - self.plot_button.setEnabled(ert is not None) - - self.kill_button = QPushButton("Kill simulations") - self.done_button = QPushButton("Done") - self.done_button.setHidden(True) - - button_layout = QHBoxLayout() - - size = 20 - spin_movie = resourceMovie("ide/loading.gif") - spin_movie.setSpeed(60) - spin_movie.setScaledSize(QSize(size, size)) - spin_movie.start() - - self.processing_animation = QLabel() - self.processing_animation.setMaximumSize(QSize(size, size)) - self.processing_animation.setMinimumSize(QSize(size, size)) - self.processing_animation.setMovie(spin_movie) - - button_layout.addWidget(self.processing_animation) - button_layout.addWidget(self.running_time) - button_layout.addStretch() - button_layout.addWidget(self.plot_button) - button_layout.addWidget(self.kill_button) - button_layout.addWidget(self.done_button) - - layout.addStretch() - layout.addLayout(button_layout) - - self.setLayout(layout) - - self.kill_button.clicked.connect(self.killJobs) - self.done_button.clicked.connect(self.accept) - - self.__updating = False - self.__update_queued = False - self.__simulation_started = False - - self.__update_timer = QTimer(self) - self.__update_timer.setInterval(500) - self.__update_timer.timeout.connect(self.updateRunStatus) - - - def startSimulation(self): - self._run_model.reset() - - def run(): - self._run_model.startSimulations(self._run_arguments) - - simulation_thread = Thread(name="ert_gui_simulation_thread") - simulation_thread.setDaemon(True) - simulation_thread.run = run - simulation_thread.start() - - self.__update_timer.start() - - - def checkIfRunFinished(self): - if self._run_model.isFinished(): - self.hideKillAndShowDone() - - if self._run_model.hasRunFailed(): - error = self._run_model.getFailMessage() - QMessageBox.critical(self, "Simulations failed!", "The simulation failed with the following error:\n\n%s" % error) - self.reject() - - - def updateRunStatus(self): - self.checkIfRunFinished() - - self.total_progress.setProgress(self._run_model.getProgress()) - - self.__status_label.setText(self._run_model.getPhaseName()) - - states = self.simulations_tracker.getStates() - - if self._run_model.isIndeterminate(): - self.progress.setIndeterminate(True) - - for state in states: - self.legends[state].updateLegend(state.name, 0, 0) - - else: - self.progress.setIndeterminate(False) - total_count = self._run_model.getQueueSize() - queue_status = self._run_model.getQueueStatus() - - for state in states: - state.count = 0 - state.total_count = total_count - - for state in states: - for queue_state in queue_status: - if queue_state in state.state: - state.count += queue_status[queue_state] - - self.progress.updateState(state.state, 100.0 * state.count / state.total_count) - self.legends[state].updateLegend(state.name, state.count, state.total_count) - - self.setRunningTime() - - - def setRunningTime(self): - days = 0 - hours = 0 - minutes = 0 - seconds = self._run_model.getRunningTime() - - if seconds >= 60: - minutes, seconds = divmod(seconds, 60) - - if minutes >= 60: - hours, minutes = divmod(minutes, 60) - - if hours >= 24: - days, hours = divmod(hours, 24) - - if days > 0: - self.running_time.setText("Running time: %d days %d hours %d minutes %d seconds" % (days, hours, minutes, seconds)) - elif hours > 0: - self.running_time.setText("Running time: %d hours %d minutes %d seconds" % (hours, minutes, seconds)) - elif minutes > 0: - self.running_time.setText("Running time: %d minutes %d seconds" % (minutes, seconds)) - else: - self.running_time.setText("Running time: %d seconds" % seconds) - - - def killJobs(self): - kill_job = QMessageBox.question(self, "Kill simulations?", "Are you sure you want to kill the currently running simulations?", QMessageBox.Yes | QMessageBox.No ) - - if kill_job == QMessageBox.Yes: - if self._run_model.killAllSimulations(): - self.reject() - - - def hideKillAndShowDone(self): - self.__update_timer.stop() - self.processing_animation.hide() - self.kill_button.setHidden(True) - self.done_button.setHidden(False) diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/simple_progress.py b/ThirdParty/Ert/python/python/ert_gui/simulation/simple_progress.py deleted file mode 100644 index c8b2afaa99..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/simple_progress.py +++ /dev/null @@ -1,55 +0,0 @@ -from math import floor -from PyQt4.QtGui import QPainter, QColor, QFrame, QLinearGradient - - -class SimpleProgress(QFrame): - def __init__(self): - QFrame.__init__(self) - self.setLineWidth(1) - self.setFrameStyle(QFrame.Panel | QFrame.Plain) - - self.background_color = QColor(255, 255, 255) - # self.color = QColor(0, 128, 255) - self.color = QColor(255, 200, 128) - - self.setMinimumHeight(15) - self.setMaximumHeight(15) - - self.__progress = 0 - - self.__shiny = False - - def setProgress(self, progress): - self.__progress = progress - self.update() - - def paintEvent(self, paint_event): - QFrame.paintEvent(self, paint_event) - painter = QPainter(self) - painter.setRenderHint(QPainter.Antialiasing, True) - painter.setRenderHint(QPainter.SmoothPixmapTransform, True) - - rect = self.contentsRect() - """@type: QRect""" - - painter.fillRect(rect, self.background_color) - - x = rect.x() - y = rect.y() - height = rect.height() - width = floor(rect.width() * self.__progress) - - painter.fillRect(x, y, width, height, self.color) - - if self.__shiny: - #Shiny overlay! - gradient = QLinearGradient(rect.width() / 2, 0, rect.width() / 2, rect.height()) - gradient.setColorAt(0, QColor(255, 255, 255, 0)) - gradient.setColorAt(0.2, QColor(255, 255, 255, 200)) - gradient.setColorAt(0.4, QColor(255, 255, 255, 0)) - gradient.setColorAt(0.85, QColor(255, 255, 255, 0)) - gradient.setColorAt(0.85, QColor(0, 0, 0, 0)) - gradient.setColorAt(1, QColor(0, 0, 0, 127)) - painter.fillRect(rect, gradient) - - diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/simulation_config_panel.py b/ThirdParty/Ert/python/python/ert_gui/simulation/simulation_config_panel.py deleted file mode 100644 index 9a946f336a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/simulation_config_panel.py +++ /dev/null @@ -1,30 +0,0 @@ -from PyQt4.QtCore import pyqtSignal -from PyQt4.QtGui import QWidget - - -class SimulationConfigPanel(QWidget): - - simulationConfigurationChanged = pyqtSignal() - - def __init__(self, simulation_model, advanced_option=False): - QWidget.__init__(self) - self.setContentsMargins(10, 10, 10, 10) - self.__simulation_model = simulation_model - self._advanced_option = advanced_option - - @property - def is_advanced_option(self): - return self._advanced_option - - def getSimulationModel(self): - return self.__simulation_model - - def isConfigurationValid(self): - return True - - def toggleAdvancedOptions(self, show_advanced): - raise NotImplementedError("toggleAdvancedOptions must be implemented!") - - def getSimulationArguments(self): - """" @rtype: dict[str, object]""" - return {} diff --git a/ThirdParty/Ert/python/python/ert_gui/simulation/simulation_panel.py b/ThirdParty/Ert/python/python/ert_gui/simulation/simulation_panel.py deleted file mode 100644 index 070cf11b2a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/simulation/simulation_panel.py +++ /dev/null @@ -1,135 +0,0 @@ -from PyQt4.QtCore import Qt, QSize -from PyQt4.QtGui import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QStackedWidget, QFrame, QToolButton, QMessageBox, QComboBox - -from ert_gui import ERT -from ert_gui.ertwidgets import addHelpToWidget, resourceIcon -from ert_gui.ertwidgets.models.ertmodel import getCurrentCaseName -from ert_gui.simulation import EnsembleExperimentPanel, EnsembleSmootherPanel -from ert_gui.simulation import IteratedEnsembleSmootherPanel, MultipleDataAssimilationPanel, SimulationConfigPanel -from ert_gui.simulation import RunDialog -from collections import OrderedDict - -class SimulationPanel(QWidget): - - def __init__(self): - QWidget.__init__(self) - - layout = QVBoxLayout() - - self._simulation_mode_combo = QComboBox() - addHelpToWidget(self._simulation_mode_combo, "run/simulation_mode") - - self._simulation_mode_combo.currentIndexChanged.connect(self.toggleSimulationMode) - - simulation_mode_layout = QHBoxLayout() - simulation_mode_layout.addSpacing(10) - simulation_mode_layout.addWidget(QLabel("Simulation mode:"), 0, Qt.AlignVCenter) - simulation_mode_layout.addWidget(self._simulation_mode_combo, 0, Qt.AlignVCenter) - - simulation_mode_layout.addSpacing(20) - - self.run_button = QToolButton() - self.run_button.setIconSize(QSize(32, 32)) - self.run_button.setText("Start Simulation") - self.run_button.setIcon(resourceIcon("ide/gear_in_play")) - self.run_button.clicked.connect(self.runSimulation) - self.run_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) - addHelpToWidget(self.run_button, "run/start_simulation") - - simulation_mode_layout.addWidget(self.run_button) - simulation_mode_layout.addStretch(1) - - layout.addSpacing(5) - layout.addLayout(simulation_mode_layout) - layout.addSpacing(10) - - self._simulation_stack = QStackedWidget() - self._simulation_stack.setLineWidth(1) - self._simulation_stack.setFrameStyle(QFrame.StyledPanel) - - layout.addWidget(self._simulation_stack) - - self._simulation_widgets = OrderedDict() - """ :type: OrderedDict[BaseRunModel,SimulationConfigPanel]""" - - self.addSimulationConfigPanel(EnsembleExperimentPanel()) - self.addSimulationConfigPanel(EnsembleSmootherPanel()) - self.addSimulationConfigPanel(IteratedEnsembleSmootherPanel(advanced_option=True)) - self.addSimulationConfigPanel(MultipleDataAssimilationPanel()) - - self.setLayout(layout) - - - def addSimulationConfigPanel(self, panel): - assert isinstance(panel, SimulationConfigPanel) - - panel.toggleAdvancedOptions(False) - self._simulation_stack.addWidget(panel) - - simulation_model = panel.getSimulationModel() - - self._simulation_widgets[simulation_model] = panel - - if not panel.is_advanced_option: - self._simulation_mode_combo.addItem(str(simulation_model), simulation_model) - - panel.simulationConfigurationChanged.connect(self.validationStatusChanged) - - - def getActions(self): - return [] - - def toggleAdvancedOptions(self, show_advanced): - current_model = self.getCurrentSimulationModel() - - self._simulation_mode_combo.clear() - - for model, panel in self._simulation_widgets.iteritems(): - if show_advanced or not panel.is_advanced_option: - self._simulation_mode_combo.addItem(str(model), model) - - old_index = self._simulation_mode_combo.findText(str(current_model)) - self._simulation_mode_combo.setCurrentIndex(old_index if old_index > -1 else 0) - - def toggleAdvancedMode(self, show_advanced): - for panel in self._simulation_widgets.values(): - panel.toggleAdvancedOptions(show_advanced) - - self.toggleAdvancedOptions(show_advanced) - - def getCurrentSimulationModel(self): - data = self._simulation_mode_combo.itemData(self._simulation_mode_combo.currentIndex(), Qt.UserRole) - return data.toPyObject() - - def getSimulationArguments(self): - """ @rtype: dict[str,object]""" - simulation_widget = self._simulation_widgets[self.getCurrentSimulationModel()] - return simulation_widget.getSimulationArguments() - - - def runSimulation(self): - case_name = getCurrentCaseName() - message = "Are you sure you want to use case '%s' for initialization of the initial ensemble when running the simulations?" % case_name - start_simulations = QMessageBox.question(self, "Start simulations?", message, QMessageBox.Yes | QMessageBox.No ) - - if start_simulations == QMessageBox.Yes: - run_model = self.getCurrentSimulationModel() - arguments = self.getSimulationArguments() - dialog = RunDialog(run_model, arguments, self) - dialog.startSimulation() - dialog.exec_() - - ERT.emitErtChange() # simulations may have added new cases. - - - def toggleSimulationMode(self): - current_model = self.getCurrentSimulationModel() - if current_model is not None: - widget = self._simulation_widgets[self.getCurrentSimulationModel()] - self._simulation_stack.setCurrentWidget(widget) - self.validationStatusChanged() - - - def validationStatusChanged(self): - widget = self._simulation_widgets[self.getCurrentSimulationModel()] - self.run_button.setEnabled(widget.isConfigurationValid()) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/CMakeLists.txt deleted file mode 100644 index 7e3ebd3e78..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - help_center.py - tool.py -) - -add_python_package("python.ert_gui.tools" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools "${PYTHON_SOURCES}" True) - -add_subdirectory(export) -add_subdirectory(help) -add_subdirectory(ide) -add_subdirectory(load_results) -add_subdirectory(manage_cases) -add_subdirectory(plot) -add_subdirectory(plugins) -add_subdirectory(run_analysis) -add_subdirectory(workflows) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/__init__.py deleted file mode 100644 index 17af514901..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .help_center import HelpCenter -from .tool import Tool \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/export/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/export/CMakeLists.txt deleted file mode 100644 index 3ff565a6d8..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/export/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - export_panel.py - export_tool.py - exporter.py - export_keyword_model.py - export_model.py -) - -add_python_package("python.ert_gui.tools.export" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/export "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/export/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/export/__init__.py deleted file mode 100644 index 4a34ca171a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/export/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .export_model import ExportModel -from .export_keyword_model import ExportKeywordModel -from .export_panel import ExportPanel -from .exporter import Exporter -from .export_tool import ExportTool diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/export/export_keyword_model.py b/ThirdParty/Ert/python/python/ert_gui/tools/export/export_keyword_model.py deleted file mode 100644 index 66ca48f76b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/export/export_keyword_model.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'export_keyword_model.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from ert.enkf import EnkfVarType, ErtImplType -from ert_gui import ERT - - -class ExportKeywordModel(object): - def __init__(self): - super(ExportKeywordModel, self).__init__() - self.__gen_kw = None - self.__field_kw = None - self.__gen_data = None - self.__gen_param = None - - def getKeylistFromImplType(self, ert_impl_type): - return sorted(ERT.ert.ensembleConfig().getKeylistFromImplType(ert_impl_type)) - - def isDynamicPlot(self, key): - vtype = self.getVarType(key) - return vtype in [EnkfVarType.DYNAMIC_STATE, EnkfVarType.DYNAMIC_RESULT] - - def isDynamicField(self, key): - return self.getVarType(key) == EnkfVarType.DYNAMIC_STATE - - def getVarType(self, key): - config_node = ERT.ert.ensembleConfig().getNode(key) - variable_type = config_node.getVariableType() - return variable_type - - def getImplementationType(self, key): - config_node = ERT.ert.ensembleConfig().getNode(key) - return config_node.getImplementationType() - - def getGenKwKeyWords(self): - if self.__gen_kw is None: - self.__gen_kw = [key for key in ERT.ert.ensembleConfig().getKeylistFromImplType(ErtImplType.GEN_KW)] - - return self.__gen_kw - - def getGenDataKeyWords(self): - if self.__gen_data is None: - gen_data_list = [] - gen_param_list = [] - for key in ERT.ert.ensembleConfig().getKeylistFromImplType(ErtImplType.GEN_DATA): - if self.getVarType(key) == EnkfVarType.PARAMETER: - gen_param_list.append(key) - continue - if ERT.ert.ensembleConfig().getNode(key).getDataModelConfig().getOutputFormat() is not None: - gen_data_list.append(key) - elif ERT.ert.ensembleConfig().getNode(key).getDataModelConfig().getInputFormat() is not None: - gen_data_list.append(key) - self.__gen_data = gen_data_list - self.__gen_param = gen_param_list - return self.__gen_data + self.__gen_param - - def getFieldKeyWords(self): - if self.__field_kw is None: - self.__field_kw = self.getKeylistFromImplType(ErtImplType.FIELD) - - return self.__field_kw - - def getKeyWords(self): - return sorted(self.getFieldKeyWords() + self.getGenKwKeyWords() + self.getGenDataKeyWords()) - - def hasKeywords(self): - return self.getKeyWords().count > 0 - - def isGenKw(self, key): - if self.__gen_kw is None: - self.getGenKwKeyWords() - - return key in self.__gen_kw - - def isFieldKw(self, key): - if self.__field_kw is None: - self.getFieldKeyWords() - - return key in self.__field_kw - - def isGenDataKw(self, key): - if self.__gen_data is None: - self.getGenDataKeyWords() - - return key in self.__gen_data - - def isGenParamKw(self, key): - if self.__gen_param is None: - self.getGenDataKeyWords() - - return key in self.__gen_param - - def getGenDataReportSteps(self, key): - gen_data_list = [] - obs_keys = ERT.ert.ensembleConfig().getNode(key).getObservationKeys() - for obs_key in obs_keys: - obs_vector = ERT.ert.getObservations()[obs_key] - for report_step in obs_vector.getStepList(): - gen_data_list.append(str(report_step)) - - return gen_data_list diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/export/export_model.py b/ThirdParty/Ert/python/python/ert_gui/tools/export/export_model.py deleted file mode 100644 index 59f466d82a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/export/export_model.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'export_model.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from __future__ import print_function -import os.path -from ert.enkf import EnkfConfigNode, EnkfNode, EnkfFieldFileFormatEnum, ErtImplType -from ert.enkf import GenKw, GenDataFileType, GenData, NodeId -from ert_gui import ERT - - -class ExportModel(object): - def __init__(self): - super(ExportModel, self).__init__() - - def exportField(self, keyword, path, iactive, file_type, report_step, selected_case): - """ - @type keyword: str - @type path: str - @type iactive: BoolVector - @type file_type: EnkfFieldFileFormatEnum - @type report_step: int - @type selected_case: str - """ - - fs = ERT.ert.getEnkfFsManager().getFileSystem(selected_case) - if file_type == EnkfFieldFileFormatEnum.ECL_GRDECL_FILE: - extension = ".grdecl" - elif file_type == EnkfFieldFileFormatEnum.RMS_ROFF_FILE: - extension = ".roff" - - iens_list = iactive.createActiveList() - path_fmt = os.path.join(path, keyword + "_%d" + extension) - config_node = ERT.ert.ensembleConfig()[keyword] - mc = ERT.ert.getModelConfig() - init_file = config_node.getInitFile(mc.getRunpathFormat()) - if init_file: - print('Using init file:%s' % init_file) - EnkfNode.exportMany(config_node, path_fmt, fs, iens_list, file_type=file_type, arg=init_file) - return True - - def exportGenKw(self, keyword, path, iactive, file_type, report_step, selected_case): - """ - @type keyword: str - @type path: str - @type iactive: BoolVector - @type file_type: EnkfFieldFileFormatEnum - @type report_step: int - @type selected_case: str - """ - enkf_config_node = ERT.ert.ensembleConfig().getNode(keyword) - assert isinstance(enkf_config_node, EnkfConfigNode) - node = EnkfNode(enkf_config_node) - fs = ERT.ert.getEnkfFsManager().getFileSystem(selected_case) - - for index, value in enumerate(iactive): - if value: - if node.tryLoad(fs, NodeId(report_step, index)): - gen_kw = GenKw.createCReference(node.valuePointer()) - filename = str(path + "/" + keyword + "_{0}").format(index) - if file_type == "Parameter list": - filename += ".txt" - gen_kw.exportParameters(filename) - else: - filename += ".inc" - gen_kw.exportTemplate(filename) - - def exportGenData(self, keyword, path, iactive, file_type, report_step, selected_case): - """ - @type keyword: str - @type path: str - @type iactive: BoolVector - @type file_type: EnkfFieldFileFormatEnum - @type report_step: int - @type selected_case: str - """ - fs = ERT.ert.getEnkfFsManager().getFileSystem(selected_case) - config_node = ERT.ert.ensembleConfig().getNode(keyword) - gen_data_config_node = config_node.getDataModelConfig() - - export_type = gen_data_config_node.getOutputFormat() - if export_type == GenDataFileType.GEN_DATA_UNDEFINED: - export_type = gen_data_config_node.getInputFormat() - - node = EnkfNode(config_node) - - for index, active in enumerate(iactive): - if active: - node_id = NodeId(int(report_step), index) - - if node.tryLoad(fs, node_id): - gen_data = node.asGenData() - - filename = str(path + "/" + keyword + "_{0}").format(index) + ".txt" - gen_data.export(filename, export_type, None) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/export/export_panel.py b/ThirdParty/Ert/python/python/ert_gui/tools/export/export_panel.py deleted file mode 100644 index 81c600f3e7..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/export/export_panel.py +++ /dev/null @@ -1,186 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'export_panel.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from PyQt4.QtCore import QDir, pyqtSignal -from PyQt4.QtGui import QFormLayout, QWidget, QLineEdit, QToolButton, QHBoxLayout, QFileDialog, QComboBox - -from ert_gui.ertwidgets.models.activerealizationsmodel import ActiveRealizationsModel -from ert_gui.ertwidgets.models.all_cases_model import AllCasesModel -from ert_gui.ertwidgets.models.ertmodel import getCurrentCaseName -from ert_gui.ertwidgets.stringbox import StringBox -from ert_gui.ide.keywords.definitions import RangeStringArgument -from ert_gui.tools.export import ExportKeywordModel - - -class ExportPanel(QWidget): - updateExportButton = pyqtSignal(str, bool) - runExport = pyqtSignal(dict) - - def __init__(self, parent=None): - QWidget.__init__(self, parent) - self.setMinimumWidth(500) - self.setMinimumHeight(200) - self._dynamic = False - - self.setWindowTitle("Export data") - self.activateWindow() - - layout = QFormLayout() - current_case = getCurrentCaseName() - - self._case_model = AllCasesModel() - self._case_combo = QComboBox() - self._case_combo.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength) - self._case_combo.setMinimumContentsLength(20) - self._case_combo.setModel(self._case_model) - self._case_combo.setCurrentIndex(self._case_model.indexOf(current_case)) - layout.addRow("Select case:", self._case_combo) - - self._export_keyword_model = ExportKeywordModel() - - self._kw_model = self._export_keyword_model.getKeyWords() - self._keywords = QComboBox() - self._keywords.addItems(self._kw_model) - layout.addRow("Select keyword:", self._keywords) - - self._active_realizations_model = ActiveRealizationsModel() - self._active_realizations_field = StringBox(self._active_realizations_model, "config/simulation/active_realizations") - self._active_realizations_field.setValidator(RangeStringArgument()) - self._active_realizations_field.getValidationSupport().validationChanged.connect(self.validateExportDialog) - layout.addRow("Active realizations:", self._active_realizations_field) - - file_name_button = QToolButton() - file_name_button.setText("Browse") - file_name_button.clicked.connect(self.selectFileDirectory) - - self._defaultPath = QDir.currentPath() + "/export" - self._file_name = QLineEdit() - self._file_name.setEnabled(False) - self._file_name.setText(self._defaultPath) - self._file_name.textChanged.connect(self.validateExportDialog) - self._file_name.setMinimumWidth(250) - - file_name_layout = QHBoxLayout() - file_name_layout.addWidget(self._file_name) - file_name_layout.addWidget(file_name_button) - layout.addRow("Select directory to save files to:", file_name_layout) - - self._gen_kw_file_types = ["Parameter list", "Template based"] - self._field_kw_file_types = ["Eclipse GRDECL", "RMS roff"] - self._gen_data_file_types = ["Gen data"] - - self._file_type_model = self._field_kw_file_types - self._file_type_combo = QComboBox() - self._file_type_combo.setSizeAdjustPolicy(QComboBox.AdjustToContents) - self._file_type_combo.addItems(self._file_type_model) - layout.addRow("Select file format:", self._file_type_combo) - - self._report_step = QLineEdit() - layout.addRow("Report step:", self._report_step) - - self._gen_data_report_step_model = [] - self._gen_data_report_step = QComboBox() - layout.addRow("Report step:", self._gen_data_report_step) - - self.setLayout(layout) - self._keywords.currentIndexChanged.connect(self.keywordSelected) - self.keywordSelected() - - def selectFileDirectory(self): - directory = QFileDialog().getExistingDirectory(self, "Directory", self._file_name.text(), QFileDialog.ShowDirsOnly) - if str(directory).__len__() > 0: - self._file_name.setText(str(directory)) - - def updateFileExportType(self, keyword): - self._file_type_combo.clear() - if self._export_keyword_model.isGenKw(keyword): - self._file_type_model = self._gen_kw_file_types - elif self._export_keyword_model.isGenParamKw(keyword): - self._file_type_model = self._gen_data_file_types - elif self._export_keyword_model.isGenDataKw(keyword): - self._file_type_model = self._gen_data_file_types - else: - self._file_type_model = self._field_kw_file_types - - self._file_type_combo.addItems(self._file_type_model) - - def export(self): - keyword = self._kw_model[self._keywords.currentIndex()] - report_step = self.getReportStep(keyword) - all_cases = self._case_model.getAllItems() - selected_case = all_cases[self._case_combo.currentIndex()] - path = self._file_name.text() - iactive = self._active_realizations_model.getActiveRealizationsMask() - file_type_key = self._file_type_model[self._file_type_combo.currentIndex()] - values = {"keyword": keyword, - "report_step": report_step, - "iactive": iactive, - "file_type_key": file_type_key, - "path": path, - "selected_case": selected_case} - self.runExport.emit(values) - - def getReportStep(self, key): - report_step = 0 - if self._dynamic: - report_step = self._report_step.text() - - if self._export_keyword_model.isGenParamKw(key): - return report_step - - if self._export_keyword_model.isGenDataKw(key): - lst = self._gen_data_report_step_model - idx = self._gen_data_report_step.currentIndex() - if lst and len(lst) > idx: - report_step = lst[idx] - else: - raise IndexError('No such model step: %d. Valid range: [0, %d)' % (idx, len(lst))) - - return report_step - - def keywordSelected(self): - key = self._kw_model[self._keywords.currentIndex()] - self.updateFileExportType(key) - self._dynamic = False - if self._export_keyword_model.isFieldKw(key): - self._dynamic = self._export_keyword_model.isDynamicField(key) - - self._report_step.setVisible(self._dynamic) - self.layout().labelForField(self._report_step).setVisible(self._dynamic) - - self._gen_data_report_step.setVisible(self._export_keyword_model.isGenDataKw(key)) - self.layout().labelForField(self._gen_data_report_step).setVisible(self._export_keyword_model.isGenDataKw(key)) - - if self._export_keyword_model.isGenDataKw(key): - data = self._export_keyword_model.getGenDataReportSteps(key) - self._gen_data_report_step_model = data - self._gen_data_report_step.clear() - self._gen_data_report_step.addItems(self._gen_data_report_step_model) - - def setSelectedCase(self, selected_case): - self._case_combo.setCurrentIndex(self._case_model.indexOf(selected_case)) - - def validateExportDialog(self): - validRealizations = False - if self._active_realizations_field.isValid(): - validRealizations = True - - path = str(self._file_name.text()) - validPath = len(path) > 0 - - if validRealizations and validPath: - self.updateExportButton.emit("export", True) - else: - self.updateExportButton.emit("export", False) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/export/export_tool.py b/ThirdParty/Ert/python/python/ert_gui/tools/export/export_tool.py deleted file mode 100644 index ffecb55406..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/export/export_tool.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'export_tool.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from weakref import ref - -from ert_gui.ertwidgets import resourceIcon -from ert_gui.ertwidgets.closabledialog import ClosableDialog -from ert_gui.ertwidgets.models.ertmodel import getCurrentCaseName -from ert_gui.tools import Tool -from ert_gui.tools.export import ExportPanel, Exporter, ExportKeywordModel - - -class ExportTool(Tool): - def __init__(self): - super(ExportTool, self).__init__("Export Data", "tools/export", resourceIcon("ide/table_export")) - self.__export_widget = None - self.__dialog = None - self.__exporter = None - self.setEnabled(ExportKeywordModel().hasKeywords()) - - def trigger(self): - if self.__export_widget is None: - self.__export_widget = ref(ExportPanel(self.parent())) - self.__exporter = Exporter() - self.__export_widget().runExport.connect(self.__exporter.runExport) - - self.__export_widget().setSelectedCase(getCurrentCaseName()) - self.__dialog = ref(ClosableDialog("Export", self.__export_widget(), self.parent())) - self.__export_widget().updateExportButton.connect(self.__dialog().toggleButton) - self.__dialog().addButton("Export", self.export) - self.__dialog().show() - - def export(self): - self.__export_widget().export() - self.__dialog().accept() diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/export/exporter.py b/ThirdParty/Ert/python/python/ert_gui/tools/export/exporter.py deleted file mode 100644 index 9a1225f3e2..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/export/exporter.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'export_tool.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import os -import sys -from PyQt4.QtCore import QDir -from PyQt4.QtGui import QMessageBox -from ert.enkf import EnkfFieldFileFormatEnum -from ert_gui.tools.export import ExportModel, ExportKeywordModel - - -class Exporter(): - def __init__(self): - self.__export_keyword_model = ExportKeywordModel() - - def runExport(self, values): - keyword = values["keyword"] - file_name = self.createExportFileNameMask(keyword, values["selected_case"], values["report_step"], values["path"]) - - if self.__export_keyword_model.isFieldKw(keyword): - self.exportField(keyword, file_name, values["iactive"], values["file_type_key"], values["report_step"], values["selected_case"]) - elif self.__export_keyword_model.isGenKw(keyword): - self.exportGenKw(keyword, file_name, values["iactive"], values["file_type_key"], values["report_step"], values["selected_case"]) - elif self.__export_keyword_model.isGenParamKw(keyword) or self.__export_keyword_model.isGenDataKw(keyword): - self.exportGenData(keyword, file_name, values["iactive"], values["file_type_key"], values["report_step"], values["selected_case"]) - else: - sys.stderr.write('** WARNING: Cannot export unknown keyword type "%s".\n' % keyword) - - def exportField(self, keyword, file_name, iactive, file_type_key, report_step, selected_case): - if file_type_key == "Eclipse GRDECL": - file_type = EnkfFieldFileFormatEnum.ECL_GRDECL_FILE - else: - file_type = EnkfFieldFileFormatEnum.RMS_ROFF_FILE - - result = ExportModel().exportField(keyword, file_name, iactive, file_type, report_step, selected_case) - if not result: - QMessageBox.warning(self, "Warning", '''Something did not work!''', QMessageBox.Ok) - - def exportGenData(self, keyword, file_name, iactive, file_type_key, report_step, selected_case): - ExportModel().exportGenData(keyword, file_name, iactive, file_type_key, report_step, selected_case) - - def exportGenKw(self, keyword, file_name, iactive, file_type_key, report_step, selected_case): - ExportModel().exportGenKw(keyword, file_name, iactive, file_type_key, report_step, selected_case) - - def createExportFileNameMask(self, keyword, current_case, report_step, path): - impl_type = None - - if self.__export_keyword_model.isFieldKw(keyword): - impl_type = self.__export_keyword_model.getImplementationType(keyword) - elif self.__export_keyword_model.isGenDataKw(keyword): - impl_type = "Gen_Data" - elif self.__export_keyword_model.isGenKw(keyword): - impl_type = "Gen_Kw" - elif self.__export_keyword_model.isGenParamKw(keyword): - impl_type = "Gen_Param" - - path = os.path.join(str(path), str(current_case), str(impl_type), str(keyword)) - - if self.__export_keyword_model.isGenDataKw(keyword): - path = path + "_" + str(report_step) - - if not QDir(path).exists(): - os.makedirs(path) - - return path diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/help/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/help/CMakeLists.txt deleted file mode 100644 index d8698f25ce..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/help/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - help_tool.py - help_window.py -) - -add_python_package("python.ert_gui.tools.help" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/help "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/help/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/help/__init__.py deleted file mode 100644 index bf58faee13..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/help/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .help_window import HelpWindow -from .help_tool import HelpTool diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/help/help_tool.py b/ThirdParty/Ert/python/python/ert_gui/tools/help/help_tool.py deleted file mode 100644 index 165cd42704..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/help/help_tool.py +++ /dev/null @@ -1,26 +0,0 @@ -from ert_gui.ertwidgets import resourceIcon -from ert_gui.tools import Tool -from ert_gui.tools.help import HelpWindow - - -class HelpTool(Tool): - __help_window_instance = None - - def __init__(self, help_center_name, parent): - super(HelpTool, self).__init__("Help", "tools/help", resourceIcon("ide/help"), enabled=True, checkable=True) - self.setParent(parent) - - self.help_center_name = help_center_name - - if HelpTool.__help_window_instance is None: - HelpTool.__help_window_instance = HelpWindow(self.help_center_name, parent=self.parent()) - self.__help_window_instance.visibilityChanged.connect(self.getAction().setChecked) - - - def trigger(self): - checked = self.getAction().isChecked() - if checked: - HelpTool.__help_window_instance.show() - else: - HelpTool.__help_window_instance.hide() - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/help/help_window.py b/ThirdParty/Ert/python/python/ert_gui/tools/help/help_window.py deleted file mode 100644 index 3d4b27cdcf..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/help/help_window.py +++ /dev/null @@ -1,86 +0,0 @@ -from PyQt4.QtCore import Qt, QUrl, pyqtSignal, QSettings -from PyQt4.QtGui import QLabel, QVBoxLayout, QColor, QDesktopServices, QDialog, QMainWindow, QWidget - -from ert_gui.tools import HelpCenter - - -class HelpWindow(QMainWindow): - help_prefix = None - default_help_string = "No help available!" - validation_template = ("" - "" - "" - "" - "
Notice:
%s
" - "") - - visibilityChanged = pyqtSignal(bool) - - def __init__(self, help_center_name, parent=None): - QMainWindow.__init__(self, parent, Qt.WindowStaysOnTopHint) - palette = self.palette() - palette.setColor(self.backgroundRole(), QColor(255, 255, 224)) - self.setPalette(palette) - self.setAutoFillBackground(True) - self.setMinimumWidth(300) - self.setMinimumHeight(250) - self.setWindowTitle("Help") - self.setObjectName("ert-gui-help") - - central_widget = QWidget() - - layout = QVBoxLayout() - central_widget.setLayout(layout) - - self.link_widget = QLabel() - self.link_widget.setStyleSheet("font-weight: bold") - self.link_widget.setMinimumHeight(20) - - self.help_widget = QLabel(HelpWindow.default_help_string) - self.help_widget.setWordWrap(True) - self.help_widget.setTextFormat(Qt.RichText) - self.help_widget.linkActivated.connect(self.openHelpURL) - - layout.addWidget(self.link_widget) - layout.addWidget(self.help_widget) - layout.addStretch(1) - - HelpCenter.getHelpCenter(help_center_name).addListener(self) - - self.__position = None - self.__geometry = None - self.setCentralWidget(central_widget) - - # settings = QSettings("Statoil", "Ert-Gui") - # self.restoreGeometry(settings.value("ert-gui-help/geometry").toByteArray()) - - - def openHelpURL(self, q_string): - url = QUrl(q_string) - QDesktopServices.openUrl(url) - - - def setHelpMessage(self, help_link, message): - self.link_widget.setText(help_link) - self.help_widget.setText(message) - - def showEvent(self, q_show_event): - if self.__geometry is not None and self.__position is not None: - self.setGeometry(self.__geometry) - self.move(self.__position) - self.visibilityChanged.emit(True) - - def hideEvent(self, q_hide_event): - self.__position = self.pos() - self.__geometry = self.geometry() - self.visibilityChanged.emit(False) - - - def keyPressEvent(self, event): - if event.key() != Qt.Key_Escape: - QMainWindow.keyPressEvent(self, event) - - def closeEvent(self, event): - self.hide() - event.ignore() - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/help_center.py b/ThirdParty/Ert/python/python/ert_gui/tools/help_center.py deleted file mode 100644 index 0be497a559..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/help_center.py +++ /dev/null @@ -1,107 +0,0 @@ -import os - - -class HelpCenter(object): - __default_help_string = "No help available!" - __help_centers = {} - - def __init__(self, name): - if name in HelpCenter.__help_centers: - raise UserWarning("HelpCenter '%s' already exists!") - - super(HelpCenter, self).__init__() - self.__name = name - self.__listeners = [] - self.__help_prefix = "" - self.__current_help_link = "" - self.__help_messages = {} - - HelpCenter.__help_centers[name] = self - - - def setHelpMessageLink(self, help_link): - self.__current_help_link = help_link - - help_message = self.resolveHelpLink(help_link) - - if help_message is not None: - self.__help_messages[help_link] = help_message - else: - self.__help_messages[help_link] = self.__default_help_string - - # if not help_link in self.__help_messages: - # help_message = self.resolveHelpLink(help_link) - # if help_message is not None: - # self.__help_messages[help_link] = help_message - # else: - # self.__help_messages[help_link] = self.__default_help_string - - for listener in self.__listeners: - listener.setHelpMessage(help_link, self.__help_messages[help_link]) - - def addListener(self, listener): - self.__listeners.append(listener) - help_link = self.__current_help_link - listener.setHelpMessage(help_link, self.__help_messages[help_link]) - - - # The setHelpLinkPrefix should be set to point to a directory - # containing (directories) with html help files. In the current - # implementation this variable is set from the gert_main.py script. - def setHelpLinkPrefix(self, prefix): - self.__help_prefix = prefix - - def getTemplate(self): - path = self.__help_prefix + "template.html" - if os.path.exists(path) and os.path.isfile(path): - f = open(path, 'r') - template = f.read() - f.close() - return template - else: - return "%s" - - def resolveHelpLink(self, help_link): - """ - Reads a HTML file from the help directory. - The HTML must follow the specification allowed by QT here: http://doc.trolltech.com/4.6/richtext-html-subset.html - """ - - # This code can be used to find widgets with empty help labels - # if label.strip() == "": - # raise AssertionError("NOOOOOOOOOOOOOOOOOOOOO!!!!!!!!!!!!") - - path = self.__help_prefix + help_link + ".html" - if os.path.exists(path) and os.path.isfile(path): - f = open(path, 'r') - help = f.read() - f.close() - return self.getTemplate() % help - else: - # This code automatically creates empty help files - # sys.stderr.write("Missing help file: '%s'\n" % label) - # if not label == "" and not label.find("/") == -1: - # sys.stderr.write("Creating help file: '%s'\n" % label) - # directory, filename = os.path.split(path) - # - # if not os.path.exists(directory): - # os.makedirs(directory) - # - # file_object = open(path, "w") - # file_object.write(label) - # file_object.close() - return None - - - @classmethod - def getHelpCenter(cls, name): - """ @rtype: HelpCenter """ - return HelpCenter.__help_centers.get(name) - - - @staticmethod - def addHelpToAction(action, link, help_center_name="ERT"): - def showHelp(): - HelpCenter.getHelpCenter(help_center_name).setHelpMessageLink(link) - - action.hovered.connect(showHelp) \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/ide/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/ide/CMakeLists.txt deleted file mode 100644 index 83e6cfc49b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/ide/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - configuration_panel.py - ide_panel.py - ide_tool.py - ide_window.py -) - -add_python_package("python.ert_gui.tools.ide" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/ide "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/ide/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/ide/__init__.py deleted file mode 100644 index b76ae2cfc5..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/ide/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .ide_panel import IdePanel -from .configuration_panel import ConfigurationPanel -from .ide_window import IdeWindow -from .ide_tool import IdeTool diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/ide/configuration_panel.py b/ThirdParty/Ert/python/python/ert_gui/tools/ide/configuration_panel.py deleted file mode 100644 index 64c87e844b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/ide/configuration_panel.py +++ /dev/null @@ -1,124 +0,0 @@ -import re -import shutil - -from PyQt4.QtCore import pyqtSignal -from PyQt4.QtGui import QWidget, QVBoxLayout, QToolBar, QMessageBox, QSizePolicy, QFileDialog - -from ert_gui.ertwidgets import SearchBox, resourceIcon -from ert_gui.ide.highlighter import KeywordHighlighter -from ert_gui.ide.keywords.definitions.path_argument import PathArgument -from ert_gui.tools.ide import IdePanel - - -class ConfigurationPanel(QWidget): - - reloadApplication = pyqtSignal(str) - - def __init__(self, config_file_path, help_tool): - QWidget.__init__(self) - - layout = QVBoxLayout() - - toolbar = QToolBar("toolbar") - - - save_action = toolbar.addAction(resourceIcon("ide/disk"), "Save") - save_action.triggered.connect(self.save) - - save_as_action = toolbar.addAction(resourceIcon("ide/save_as"), "Save As") - save_as_action.triggered.connect(self.saveAs) - - # reload_icon = toolbar.style().standardIcon(QStyle.SP_BrowserReload) - # reload_action = toolbar.addAction(reload_icon, "Reload") - # reload_action.triggered.connect(self.reload) - - toolbar.addSeparator() - - toolbar.addAction(help_tool.getAction()) - - - stretchy_separator = QWidget() - stretchy_separator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - toolbar.addWidget(stretchy_separator) - - - search = SearchBox() - search.setMaximumWidth(200) - search.setContentsMargins(5, 2, 5, 2) - - toolbar.addWidget(search) - - layout.addWidget(toolbar) - - self.ide_panel = IdePanel() - layout.addWidget(self.ide_panel, 1) - - self.config_file_path = config_file_path - - with open(config_file_path) as f: - config_file_text = f.read() - - self.highlighter = KeywordHighlighter(self.ide_panel.document()) - - search.filterChanged.connect(self.highlighter.setSearchString) - - self.parseDefines(config_file_text) - self.ide_panel.document().setPlainText(config_file_text) - - cursor = self.ide_panel.textCursor() - cursor.setPosition(0) - self.ide_panel.setTextCursor(cursor) - self.ide_panel.setFocus() - - - self.setLayout(layout) - - - - def getName(self): - return "Configuration" - - - def save(self): - backup_path = "%s.backup" % self.config_file_path - shutil.copyfile(self.config_file_path, backup_path) - - with open(self.config_file_path, "w") as f: - f.write(self.ide_panel.getText()) - - message = "To make your changes current, a reload of the configuration file is required. Would you like to reload now?" - result = QMessageBox.information(self, "Reload required!", message, QMessageBox.Yes | QMessageBox.No) - - if result == QMessageBox.Yes: - self.reload(self.config_file_path) - - - def saveAs(self): - config_file = QFileDialog.getSaveFileName(self, "Save Configuration File As") - - config_file = str(config_file) - - if len(config_file) > 0: - with open(config_file, "w") as f: - f.write(self.ide_panel.getText()) - - message = "The current configuration file has been saved to a new file. Do you want to restart Ert using the new configuration file?" - result = QMessageBox.information(self, "Restart Ert?", message, QMessageBox.Yes | QMessageBox.No) - - if result == QMessageBox.Yes: - self.reload(config_file) - - - def reload(self, path): - self.reloadApplication.emit(path) - - def start(self): - print("Start!") - - def parseDefines(self, text): - pattern = re.compile("[ \t]*DEFINE[ \t]*(\S+)[ \t]*(\S+)") - - match = re.findall(pattern, text) - - for m in match: - PathArgument.addDefine(m[0], m[1]) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_panel.py b/ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_panel.py deleted file mode 100644 index 280dde1774..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_panel.py +++ /dev/null @@ -1,211 +0,0 @@ -import re -from PyQt4.QtCore import Qt, QEvent, QDir, QRegExp, QChar -from PyQt4.QtGui import QPlainTextEdit, QTextOption, QCompleter, QStringListModel, QFont, QColor, QShortcut, QKeySequence, QTextCursor, QFileSystemModel, QTextDocument -from ert_gui.tools import HelpCenter - - -class IdePanel(QPlainTextEdit): - def __init__(self): - QPlainTextEdit.__init__(self) - self.setWordWrapMode(QTextOption.NoWrap) - self.setFont(QFont("monospace", 10)) - self.setCursorWidth(2) - self.installEventFilter(self) - - self.cursorPositionChanged.connect(self.showHelp) - - self.completer = QCompleter(self) - self.completer.setWidget(self) - self.completer.setCaseSensitivity(Qt.CaseInsensitive) - self.completer.activated.connect(self.insertCompletion) - - - auto_complete = QShortcut(QKeySequence("Ctrl+Space"), self) - auto_complete.activated.connect(self.activateCompleter) - - copy_line = QShortcut(QKeySequence("Ctrl+D"), self) - copy_line.activated.connect(self.duplicateLine) - - select_fragment = QShortcut(QKeySequence("Ctrl+J"), self) - select_fragment.activated.connect(self.selectFragment) - - def showHelp(self): - text_cursor = self.textCursor() - user_data = text_cursor.block().userData() - - if user_data is not None: - configuration_line = user_data.configuration_line - - if configuration_line.keyword().hasKeywordDefinition(): - HelpCenter.getHelpCenter("ERT").setHelpMessageLink("config/" + configuration_line.documentationLink()) - - - def getText(self): - return self.document().toPlainText() - - - def eventFilter(self, qobject, qevent): - if qobject == self and qevent.type() == QEvent.ToolTip: - text_cursor = self.cursorForPosition(qevent.pos()) - pos = text_cursor.positionInBlock() - - user_data = text_cursor.block().userData() - if user_data is not None: - #: :type: ConfigurationLine - configuration_line = user_data.configuration_line - # if configuration_line.keyword().hasKeywordDefinition(): - # print(configuration_line.keyword().keywordDefinition().documentation) - - if pos in configuration_line.keyword(): - self.setToolTip(configuration_line.validationStatusForToken(configuration_line.keyword()).message()) - else: - for argument in configuration_line.arguments(): - if pos in argument: - self.setToolTip(configuration_line.validationStatusForToken(argument).message()) - - else: - self.setToolTip("") - - - return QPlainTextEdit.eventFilter(self, qobject, qevent) - - - def activateCompleter(self): - text_cursor = self.textCursor() - block = self.document().findBlock(text_cursor.position()) - position_in_block = text_cursor.positionInBlock() - - - - self.selectWordUnderCursor(text_cursor) - word = unicode(text_cursor.selectedText()) - - user_data = block.userData() - - self.completer.setCompletionPrefix(word) - - show_completer = False - if user_data is None: - self.completer.setModel(QStringListModel(self.handler_names)) - show_completer = True - - else: - keyword = user_data.keyword - options = keyword.handler.parameterOptions(keyword, word, position_in_block) - - if len(options) == 1: - self.insertCompletion(options[0]) - elif len(options) > 1: - self.completer.setModel(QStringListModel(options)) - if self.completer.completionCount() == 1: - self.insertCompletion(self.completer.currentCompletion()) - else: - show_completer = True - - - if show_completer: - rect = self.cursorRect(text_cursor) - rect.setWidth(self.completer.popup().sizeHintForColumn(0) + self.completer.popup().verticalScrollBar().sizeHint().width()) - self.completer.complete(rect) - - def keyPressEvent(self, qkeyevent): - if self.completer.popup().isVisible(): - dead_keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab] - if qkeyevent.key() in dead_keys: - qkeyevent.ignore() - return - - if qkeyevent.modifiers() == Qt.ShiftModifier: - if qkeyevent.key() & Qt.Key_Delete == Qt.Key_Delete: - self.deleteLine() - - QPlainTextEdit.keyPressEvent(self, qkeyevent) - - - def insertCompletion(self, string): - text_cursor = self.textCursor() - self.selectWordUnderCursor(text_cursor) - text_cursor.insertText(string) - - def isCursorInSpace(self): - text_cursor = self.textCursor() - if text_cursor.positionInBlock() > 0: - text_cursor.movePosition(QTextCursor.Left, QTextCursor.MoveAnchor) - text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) - - if text_cursor.positionInBlock() < text_cursor.block().length() - 1: - text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) - - if unicode(text_cursor.selectedText()).strip() == "": - return True - - return False - - def selectWordUnderCursor(self, text_cursor): - if not self.isCursorInSpace(): - # text_cursor.select(QTextCursor.WordUnderCursor) - - # pattern = "[\s|\v|\f|\n|\r|\t|\xe2\x80\xa8|\xe2\x80\xa9]" - # pattern = "[\\s|\\xe2\\x80\\xa9|\\xe2\\x80\\xa8]" - - block_start = 0 - block_end = text_cursor.block().length() - - cursor_pos = text_cursor.positionInBlock() - pos = cursor_pos - pattern = u"[\s\u2029\u2028]" - while pos >= block_start: - text_cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor) - text = text_cursor.selectedText() - if re.search(pattern, text): - break - pos -= 1 - - text_cursor.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor) - - while pos < block_end: - text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) - text = text_cursor.selectedText() - if re.search(pattern, text): - break - pos += 1 - - text_cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor) - - # pattern = "[\\s]" - # start = self.document().find(QRegExp(pattern), text_cursor, QTextDocument.FindBackward | QTextDocument.FindCaseSensitively) - # end = self.document().find(QRegExp(pattern), text_cursor, QTextDocument.FindCaseSensitively) - # block_end_pos = text_cursor.block().position() + text_cursor.block().length() - # - # text_cursor.setPosition(start.position(), QTextCursor.MoveAnchor) - # # text_cursor.setPosition(min(block_end_pos, end.position() - 1), QTextCursor.KeepAnchor) - # text_cursor.setPosition(end.position() - 1, QTextCursor.KeepAnchor) - - - def deleteLine(self): - text_cursor = self.textCursor() - text_cursor.beginEditBlock() - text_cursor.select(QTextCursor.LineUnderCursor) - text_cursor.removeSelectedText() - text_cursor.deletePreviousChar() - - text_cursor.movePosition(QTextCursor.NextBlock) - text_cursor.movePosition(QTextCursor.StartOfLine) - self.setTextCursor(text_cursor) - text_cursor.endEditBlock() - - def duplicateLine(self): - text_cursor = self.textCursor() - text_cursor.beginEditBlock() - text_cursor.select(QTextCursor.LineUnderCursor) - text = text_cursor.selectedText() - text_cursor.movePosition(QTextCursor.EndOfLine) - text_cursor.insertBlock() - text_cursor.insertText(text) - text_cursor.endEditBlock() - - - def selectFragment(self): - text_cursor = self.textCursor() - self.selectWordUnderCursor(text_cursor) - self.setTextCursor(text_cursor) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_tool.py b/ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_tool.py deleted file mode 100644 index 9c9ca5b4c7..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_tool.py +++ /dev/null @@ -1,24 +0,0 @@ -from weakref import ref - -from ert_gui import ERT -from ert_gui.ertwidgets import resourceIcon -from ert_gui.tools import Tool -from ert_gui.tools.ide import IdeWindow - - -class IdeTool(Tool): - def __init__(self, path, help_tool): - super(IdeTool, self).__init__("Configure", "tools/ide", resourceIcon("ide/widgets")) - - self.ide_window = None - self.path = path - self.help_tool = help_tool - - def trigger(self): - if self.ide_window is None: - self.ide_window = ref(IdeWindow(self.path, self.parent(), self.help_tool)) - self.ide_window().reloadTriggered.connect(ERT.reloadERT) - - self.ide_window().show() - self.ide_window().raise_() - self.ide_window().activateWindow() \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_window.py b/ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_window.py deleted file mode 100644 index b123c7171b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/ide/ide_window.py +++ /dev/null @@ -1,59 +0,0 @@ -from PyQt4.QtCore import pyqtSignal -from PyQt4.QtGui import QMainWindow - -from ert_gui.tools.ide.configuration_panel import ConfigurationPanel - - -class IdeWindow(QMainWindow): - reloadTriggered = pyqtSignal(str) - - def __init__(self, path, parent, help_tool): - QMainWindow.__init__(self, parent) - - self.resize(900, 900) - - self.__position = None - self.__geometry = None - - self.__configuration_panel = ConfigurationPanel(path, help_tool) - self.__configuration_panel.reloadApplication.connect(self.reloadTriggered) - self.setCentralWidget(self.__configuration_panel) - self.setWindowTitle("Configuration") - self.activateWindow() - - - # wizard_panel = WizardView() - # wizard_panel.addGroup("Parameters") - # wizard_panel.addItemToGroup("Parameters", "Add Summary key") - # wizard_panel.addItemToGroup("Parameters", "Add Field parameter") - # wizard_panel.addItemToGroup("Parameters", "Add Data Keyword") - # wizard_panel.addGroup("Eclipse") - # wizard_panel.addItemToGroup("Eclipse", "Setup Eclipse parameters") - # wizard_panel.addGroup("Observations") - # wizard_panel.addItemToGroup("Observations", "Add Observations") - # wizard_panel.expandAll() - # self.addDock("Wizards", wizard_panel) - - - def closeEvent(self, q_close_event): - self.__position = self.pos() - self.__geometry = self.geometry() - self.hide() - q_close_event.ignore() - - def show(self): - if self.__geometry is not None and self.__position is not None: - self.setGeometry(self.__geometry) - self.move(self.__position) - QMainWindow.show(self) - - # def addDock(self, name, widget, area=Qt.RightDockWidgetArea, allowed_areas=Qt.AllDockWidgetAreas): - # dock_widget = QDockWidget(name) - # dock_widget.setObjectName("%sDock" % name) - # dock_widget.setWidget(widget) - # dock_widget.setAllowedAreas(allowed_areas) - # - # self.addDockWidget(area, dock_widget) - # - # self.__view_menu.addAction(dock_widget.toggleViewAction()) - # return dock_widget diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/load_results/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/load_results/CMakeLists.txt deleted file mode 100644 index ea92b4461c..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/load_results/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - load_results_panel.py - load_results_tool.py - load_results_model.py - -) - -add_python_package("python.ert_gui.tools.load_results" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/load_results "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/load_results/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/load_results/__init__.py deleted file mode 100644 index 783c414edc..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/load_results/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .load_results_model import LoadResultsModel -from .load_results_panel import LoadResultsPanel -from .load_results_tool import LoadResultsTool diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_model.py b/ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_model.py deleted file mode 100644 index f60bc6d991..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_model.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'load_results_model.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import os - -from ert_gui import ERT - - -class LoadResultsModel(object): - - @staticmethod - def loadResults(selected_case, realisations, iteration): - """ - @type selected_case: str - @type realisations: BoolVector - @type iteration: int - @rtype int: number of loaded realisations - """ - fs = ERT.ert.getEnkfFsManager().getFileSystem(selected_case) - return ERT.ert.loadFromForwardModel(realisations, iteration, fs) - - @staticmethod - def isValidRunPath(): - """ @rtype: bool """ - run_path = ERT.ert.getModelConfig().getRunpathAsString() - try: - result = run_path % (0, 0) - return True - except TypeError: - pass - - try: - result = run_path % 0 - return True - except TypeError: - pass - - return False - - @staticmethod - def getCurrentRunPath(): - """ @rtype: str """ - return ERT.ert.getModelConfig().getRunpathAsString() - - - @staticmethod - def getIterationCount(): - """ @rtype: int """ - run_path = ERT.ert.getModelConfig().getRunpathAsString() - try: - results = run_path % (0, 0) - except TypeError: - return 0 - - iteration = 0 - valid_directory = True - while valid_directory: - formatted = run_path % (0, iteration) - valid_directory = os.path.exists(formatted) - if valid_directory: - iteration += 1 - - return iteration - - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_panel.py b/ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_panel.py deleted file mode 100644 index 3b7bff6013..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_panel.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'load_results_panel.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from PyQt4.QtGui import QWidget, QFormLayout, QComboBox, QTextEdit - -from ert_gui.ertwidgets.models.activerealizationsmodel import ActiveRealizationsModel -from ert_gui.ertwidgets.models.all_cases_model import AllCasesModel -from ert_gui.ertwidgets.models.ertmodel import getCurrentCaseName -from ert_gui.ertwidgets.models.valuemodel import ValueModel -from ert_gui.ertwidgets.stringbox import StringBox -from ert_gui.ide.keywords.definitions import RangeStringArgument, IntegerArgument -from ert_gui.tools.load_results import LoadResultsModel - - -class LoadResultsPanel(QWidget): - - def __init__(self): - QWidget.__init__(self) - - self.setMinimumWidth(500) - self.setMinimumHeight(200) - self._dynamic = False - - self.setWindowTitle("Load results manually") - self.activateWindow() - - layout = QFormLayout() - current_case = getCurrentCaseName() - - run_path_text = QTextEdit() - run_path_text.setText(self.readCurrentRunPath()) - run_path_text.setDisabled(True) - run_path_text.setFixedHeight(80) - - layout.addRow("Load data from current run path: ",run_path_text) - - self._case_model = AllCasesModel() - self._case_combo = QComboBox() - self._case_combo.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength) - self._case_combo.setMinimumContentsLength(20) - self._case_combo.setModel(self._case_model) - self._case_combo.setCurrentIndex(self._case_model.indexOf(current_case)) - layout.addRow("Load into case:", self._case_combo) - - - self._active_realizations_model = ActiveRealizationsModel() - self._active_realizations_field = StringBox(self._active_realizations_model, "load_results_manually/Realizations") - self._active_realizations_field.setValidator(RangeStringArgument()) - layout.addRow("Realizations to load:", self._active_realizations_field) - - iterations_count = LoadResultsModel.getIterationCount() - - self._iterations_model = ValueModel(iterations_count) - self._iterations_field = StringBox(self._iterations_model, "load_results_manually/iterations") - self._iterations_field.setValidator(IntegerArgument()) - layout.addRow("Iteration to load:", self._iterations_field) - - self.setLayout(layout) - - def readCurrentRunPath(self): - current_case = getCurrentCaseName() - run_path = LoadResultsModel.getCurrentRunPath() - run_path = run_path.replace("",current_case) - run_path = run_path.replace("",current_case) - return run_path - - - def load(self): - all_cases = self._case_model.getAllItems() - selected_case = all_cases[self._case_combo.currentIndex()] - realizations = self._active_realizations_model.getActiveRealizationsMask() - iteration = self._iterations_model.getValue() - try: - if iteration is None: - iteration = '' - iteration = int(iteration) - except ValueError as e: - print('Expected a (whole) number in iteration field, got "%s". Error message: %s.' % (iteration, e)) - return False - loaded = LoadResultsModel.loadResults(selected_case, realizations, iteration) - if loaded > 0: - print('Successfully loaded %d realisations.' % loaded) - else: - print('No realisations loaded.') - return loaded - - def setCurrectCase(self): - current_case = getCurrentCaseName() - self._case_combo.setCurrentIndex(self._case_model.indexOf(current_case)) \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_tool.py b/ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_tool.py deleted file mode 100644 index 88825bb0dc..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/load_results/load_results_tool.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'load_results_tool.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from ert_gui.ertwidgets import resourceIcon -from ert_gui.ertwidgets.closabledialog import ClosableDialog -from ert_gui.tools import Tool -from ert_gui.tools.load_results import LoadResultsModel -from ert_gui.tools.load_results import LoadResultsPanel - - -class LoadResultsTool(Tool): - def __init__(self): - super(LoadResultsTool, self).__init__("Load results manually", "tools/load_manually", resourceIcon("ide/table_import")) - self.__import_widget = None - self.__dialog = None - self.setVisible(False) - - - - - def trigger(self): - if self.__import_widget is None: - self.__import_widget = LoadResultsPanel() - self.__dialog = ClosableDialog("Load results manually", self.__import_widget, self.parent()) - self.__import_widget.setCurrectCase() - self.__dialog.addButton("Load", self.load) - self.__dialog.exec_() - - def load(self): - self.__import_widget.load() - self.__dialog.accept() - - def toggleAdvancedMode(self, advanced_mode): - self.setVisible(advanced_mode) - if not LoadResultsModel.isValidRunPath(): - self.setEnabled(False) - - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/CMakeLists.txt deleted file mode 100644 index 3f599f743f..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - case_init_configuration.py - manage_cases_tool.py -) - -add_python_package("python.ert_gui.tools.manage_cases" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/manage_cases "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/__init__.py deleted file mode 100644 index 29c33e538e..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .manage_cases_tool import ManageCasesTool diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/case_init_configuration.py b/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/case_init_configuration.py deleted file mode 100644 index c2173dc3fd..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/case_init_configuration.py +++ /dev/null @@ -1,206 +0,0 @@ -from PyQt4.QtGui import QToolButton, QTextEdit, QTabWidget, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QSpinBox -from PyQt4.QtCore import Qt - -from ert_gui import ERT -from ert_gui.ertwidgets import addHelpToWidget, showWaitCursorWhileWaiting -from ert_gui.ertwidgets.caselist import CaseList -from ert_gui.ertwidgets.caseselector import CaseSelector -from ert_gui.ertwidgets.checklist import CheckList -from ert_gui.ertwidgets.models.ertmodel import getRealizationCount, initializeCurrentCaseFromScratch, getCaseRealizationStates, getParameterList, getHistoryLength, \ - initializeCurrentCaseFromExisting, getCurrentCaseName -from ert_gui.ertwidgets.models.selectable_list_model import SelectableListModel - - -def createCheckLists(): - parameter_model = SelectableListModel([]) - - parameter_model.getList = getParameterList - parameter_check_list = CheckList(parameter_model, "Parameters", "init/select_parameters") - parameter_check_list.setMaximumWidth(300) - - members_model = SelectableListModel([]) - - def getMemberList(): - return [str(member) for member in range(getRealizationCount())] - - members_model.getList = getMemberList - member_check_list = CheckList(members_model, "Members", "init/select_members") - member_check_list.setMaximumWidth(150) - return createRow(parameter_check_list, member_check_list), parameter_model, members_model - - -def createRow(*widgets): - row = QHBoxLayout() - - for widget in widgets: - row.addWidget(widget) - - row.addStretch() - return row - - -class CaseInitializationConfigurationPanel(QTabWidget): - @showWaitCursorWhileWaiting - def __init__(self): - QTabWidget.__init__(self) - self.setWindowTitle("Case Management") - self.setMinimumWidth(600) - - self.addCreateNewCaseTab() - self.addInitializeFromScratchTab() - self.addInitializeFromExistingTab() - self.addShowCaseInfo() - - def addCreateNewCaseTab(self): - panel = QWidget() - layout = QVBoxLayout() - case_list = CaseList() - case_list.setMaximumWidth(250) - - layout.addWidget(case_list) - layout.addStretch() - - panel.setLayout(layout) - - self.addTab(panel, "Create new case") - - def addInitializeFromScratchTab(self): - panel = QWidget() - layout = QVBoxLayout() - - row1 = createRow(QLabel("Target case:"), CaseSelector()) - layout.addLayout(row1) - - check_list_layout, parameter_model, members_model = createCheckLists() - layout.addLayout(check_list_layout) - - layout.addSpacing(10) - - initialize_button = QPushButton("Initialize") - addHelpToWidget(initialize_button, "init/initialize_from_scratch") - initialize_button.setMinimumWidth(75) - initialize_button.setMaximumWidth(150) - - def initializeFromScratch(): - parameters = parameter_model.getSelectedItems() - members = members_model.getSelectedItems() - initializeCurrentCaseFromScratch(parameters, members) - - initialize_button.clicked.connect(initializeFromScratch) - layout.addWidget(initialize_button, 0, Qt.AlignCenter) - - layout.addSpacing(10) - - panel.setLayout(layout) - self.addTab(panel, "Initialize from scratch") - - def addInitializeFromExistingTab(self): - widget = QWidget() - layout = QVBoxLayout() - - target_case = CaseSelector() - row = createRow(QLabel("Target case:"), target_case) - layout.addLayout(row) - - source_case = CaseSelector(update_ert=False, show_only_initialized=True, ignore_current=True) - row = createRow(QLabel("Source case:"), source_case) - layout.addLayout(row) - - row, history_length_spinner = self.createTimeStepRow() - layout.addLayout(row) - - layout.addSpacing(10) - check_list_layout, parameter_model, members_model = createCheckLists() - layout.addLayout(check_list_layout) - layout.addSpacing(10) - - initialize_button = QPushButton("Initialize") - addHelpToWidget(initialize_button, "init/initialize_from_existing") - initialize_button.setMinimumWidth(75) - initialize_button.setMaximumWidth(150) - - def initializeFromExisting(): - source_case_name = str(source_case.currentText()) - target_case_name = str(target_case.currentText()) - report_step = history_length_spinner.value() - parameters = parameter_model.getSelectedItems() - members = members_model.getSelectedItems() - initializeCurrentCaseFromExisting(source_case_name, target_case_name, report_step, parameters, members) - - initialize_button.clicked.connect(initializeFromExisting) - layout.addWidget(initialize_button, 0, Qt.AlignCenter) - - - layout.addSpacing(10) - - layout.addStretch() - widget.setLayout(layout) - self.addTab(widget, "Initialize from existing") - - def createTimeStepRow(self): - history_length_spinner = QSpinBox() - addHelpToWidget(history_length_spinner, "config/init/history_length") - history_length_spinner.setMinimum(0) - history_length_spinner.setMaximum(getHistoryLength()) - - initial = QToolButton() - initial.setText("Initial") - addHelpToWidget(initial, "config/init/history_length") - - def setToMin(): - history_length_spinner.setValue(0) - - initial.clicked.connect(setToMin) - - end_of_time = QToolButton() - end_of_time.setText("End of time") - addHelpToWidget(end_of_time, "config/init/history_length") - - def setToMax(): - history_length_spinner.setValue(getHistoryLength()) - - end_of_time.clicked.connect(setToMax) - - row = createRow(QLabel("Timestep:"), history_length_spinner, initial, end_of_time) - - return row, history_length_spinner - - def addShowCaseInfo(self): - case_widget = QWidget() - layout = QVBoxLayout() - - case_selector = CaseSelector(update_ert=False, help_link="init/selected_case_info") - row1 = createRow(QLabel("Select case:"), case_selector) - - layout.addLayout(row1) - - self._case_info_area = QTextEdit() - self._case_info_area.setReadOnly(True) - self._case_info_area.setMinimumHeight(300) - - row2 = createRow(QLabel("Case info:"), self._case_info_area) - - layout.addLayout(row2) - - case_widget.setLayout(layout) - - case_selector.currentIndexChanged[str].connect(self._showInfoForCase) - ERT.ertChanged.connect(self._showInfoForCase) - - self.addTab(case_widget, "Case Info") - - self._showInfoForCase() - - def _showInfoForCase(self, case_name=None): - if case_name is None: - case_name = getCurrentCaseName() - - states = getCaseRealizationStates(str(case_name)) - - html = "" - for index in range(len(states)): - html += "" % (index, str(states[index])) - - html += "
%d.%s
" - - self._case_info_area.setHtml(html) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/manage_cases_tool.py b/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/manage_cases_tool.py deleted file mode 100644 index d593a138a4..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/manage_cases/manage_cases_tool.py +++ /dev/null @@ -1,20 +0,0 @@ -from ert_gui.ertwidgets import resourceIcon -from ert_gui.ertwidgets.closabledialog import ClosableDialog -from ert_gui.tools import Tool -from ert_gui.tools.manage_cases.case_init_configuration import CaseInitializationConfigurationPanel - - -class ManageCasesTool(Tool): - def __init__(self): - super(ManageCasesTool, self).__init__("Manage Cases", "tools/manage_cases", resourceIcon("ide/database_gear")) - - - def trigger(self): - case_management_widget = CaseInitializationConfigurationPanel() - - dialog = ClosableDialog("Manage Cases", case_management_widget, self.parent()) - dialog.exec_() - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/plot/CMakeLists.txt deleted file mode 100644 index d42c0775fd..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - color_chooser.py - data_type_keys_list_model.py - data_type_keys_widget.py - data_type_proxy_model.py - filter_popup.py - plot_case_model.py - plot_case_selection_widget.py - plot_tool.py - plot_widget.py - plot_window.py - style_chooser.py - filterable_kw_list_model.py -) - -add_python_package("python.ert_gui.tools.plot" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/plot "${PYTHON_SOURCES}" True) - -add_subdirectory(customize) -add_subdirectory(widgets) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/__init__.py deleted file mode 100644 index 533609e104..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -from .plot_widget import PlotWidget - -from .filter_popup import FilterPopup - -from .filterable_kw_list_model import FilterableKwListModel -from .data_type_keys_list_model import DataTypeKeysListModel -from .data_type_proxy_model import DataTypeProxyModel -from .data_type_keys_widget import DataTypeKeysWidget - -from .plot_case_model import PlotCaseModel -from .plot_case_selection_widget import CaseSelectionWidget - -from .color_chooser import ColorBox -from .style_chooser import StyleChooser - -from .plot_window import PlotWindow -from .plot_tool import PlotTool - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/color_chooser.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/color_chooser.py deleted file mode 100644 index 834389736f..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/color_chooser.py +++ /dev/null @@ -1,54 +0,0 @@ -from PyQt4.QtCore import QSize, QRect, pyqtSignal -from PyQt4.QtGui import QWidget, QPainter, QHBoxLayout, QLabel, QFrame, QColor, QColorDialog - - -class ColorBox(QFrame): - colorChanged = pyqtSignal(QColor) - - """A widget that shows a colored box""" - def __init__(self, color, size=15): - QFrame.__init__(self) - self.setFrameStyle(QFrame.Panel | QFrame.Sunken) - self.setMaximumSize(QSize(size, size)) - self.setMinimumSize(QSize(size, size)) - - self._tile_colors = [QColor(255, 255, 255), QColor(200, 200, 255)] - self._color = color - - def paintEvent(self, paint_event): - """Paints the box""" - painter = QPainter(self) - rect = self.contentsRect() - tile_count = 3 - tile_size = rect.width() / tile_count - painter.save() - painter.translate(rect.x(), rect.y()) - - for y in range(tile_count): - for x in range(tile_count): - color_index = (y * tile_count + x) % 2 - tile_rect = QRect(x * tile_size, y * tile_size, tile_size, tile_size) - painter.fillRect(tile_rect, self._tile_colors[color_index]) - - painter.restore() - painter.fillRect(rect, self._color) - - QFrame.paintEvent(self, paint_event) - - def mouseReleaseEvent(self, QMouseEvent): - color = QColorDialog.getColor(self._color, self, "Select color", QColorDialog.ShowAlphaChannel) - - if color.isValid(): - self._color = color - self.update() - self.colorChanged.emit(self._color) - - @property - def color(self): - """ @rtype: QColor """ - return self._color - - @color.setter - def color(self, color): - self._color = QColor(color) - self.update() diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/CMakeLists.txt deleted file mode 100644 index 291759bac9..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - customization_view.py - customize_plot_dialog.py - default_customization_view.py - limits_customization_view.py - statistics_customization_view.py - style_customization_view.py -) - -add_python_package("python.ert_gui.tools.plot.customize" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/plot/customize "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/__init__.py deleted file mode 100644 index 99e83000c2..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from ert_gui.tools.plot.customize.customization_view import CustomizationView, WidgetProperty -from ert_gui.tools.plot.customize.default_customization_view import DefaultCustomizationView -from ert_gui.tools.plot.customize.style_customization_view import StyleCustomizationView -from ert_gui.tools.plot.customize.limits_customization_view import LimitsCustomizationView -from ert_gui.tools.plot.customize.statistics_customization_view import StatisticsCustomizationView -from ert_gui.tools.plot.customize.customize_plot_dialog import PlotCustomizer diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/customization_view.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/customization_view.py deleted file mode 100644 index 53eb78f1b5..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/customization_view.py +++ /dev/null @@ -1,144 +0,0 @@ -from PyQt4.QtGui import QWidget, QFormLayout, QSpacerItem, QCheckBox, QHBoxLayout, QSpinBox - -from ert_gui.plottery import PlotConfig -from ert_gui.tools.plot import StyleChooser -from ert_gui.tools.plot.widgets.clearable_line_edit import ClearableLineEdit - -from ert_gui.tools.plot import style_chooser as sc - -class CustomizationView(QWidget): - def __init__(self): - QWidget.__init__(self) - - self._layout = QFormLayout() - self.setLayout(self._layout) - self._widgets = {} - - - def addRow(self, title, widget): - self._layout.addRow(title, widget) - - def addLineEdit(self, attribute_name, title, tool_tip=None, placeholder=""): - self[attribute_name] = ClearableLineEdit(placeholder=placeholder) - self.addRow(title, self[attribute_name]) - - if tool_tip is not None: - self[attribute_name].setToolTip(tool_tip) - - def getter(self): - value = str(self[attribute_name].text()) - if value == "": - value = None - return value - - def setter(self, value): - if value is None: - value = "" - self[attribute_name].setText(str(value)) - - self.updateProperty(attribute_name, getter, setter) - - def addCheckBox(self, attribute_name, title, tool_tip=None): - self[attribute_name] = QCheckBox() - self.addRow(title, self[attribute_name]) - - if tool_tip is not None: - self[attribute_name].setToolTip(tool_tip) - - def getter(self): - return self[attribute_name].isChecked() - - def setter(self, value): - self[attribute_name].setChecked(value) - - self.updateProperty(attribute_name, getter, setter) - - def addSpinBox(self, attribute_name, title, tool_tip=None, min_value=1, max_value=10, single_step=1): - sb = QSpinBox() - self[attribute_name] = sb - sb.setMaximumHeight(25) - sb_layout = QHBoxLayout() - sb_layout.addWidget(sb) - sb_layout.addStretch() - self.addRow(title, sb_layout) - - if tool_tip is not None: - sb.setToolTip(tool_tip) - - sb.setMinimum(min_value) - sb.setMaximum(max_value) - sb.setSingleStep(single_step) - - def getter(self): - return self[attribute_name].value() - - def setter(self, value): - self[attribute_name].setValue(value) - - self.updateProperty(attribute_name, getter, setter) - return sb - - def addStyleChooser(self, attribute_name, title, tool_tip=None, line_style_set=sc.STYLESET_DEFAULT): - style_chooser = StyleChooser(line_style_set=line_style_set) - self[attribute_name] = style_chooser - self.addRow(title, self[attribute_name]) - - if tool_tip is not None: - self[attribute_name].setToolTip(tool_tip) - - def getter(self): - return self[attribute_name].getStyle() - - def setter(self, style): - self[attribute_name].setStyle(style) - - self.updateProperty(attribute_name, getter, setter) - - def updateProperty(self, attribute_name, getter, setter): - setattr(self.__class__, attribute_name, property(getter, setter)) - - def setWidgetEnabled(self, attribute_name, enabled): - widget = self[attribute_name] - widget.setEnabled(enabled) - widget.setHidden(enabled) - label = self._layout.labelForField(widget) - label.setEnabled(enabled) - label.setHidden(enabled) - - def addSpacing(self, pixels=10): - self._layout.addItem(QSpacerItem(1, pixels)) - - def addHeading(self, title): - self.addSpacing(10) - self._layout.addRow(title, None) - self.addSpacing(1) - - def __getitem__(self, item): - """ - @rtype: QWidget - """ - return self._widgets[item] - - def __setitem__(self, key, value): - self._widgets[key] = value - - def applyCustomization(self, plot_config): - """ - @type plot_config: PlotConfig - """ - raise NotImplementedError("Class '%s' has not implemented the applyCustomization() function!" % self.__class__.__name__) - - def revertCustomization(self, plot_config): - """ - @type plot_config: PlotConfig - """ - raise NotImplementedError("Class '%s' has not implemented the revertCustomization() function!" % self.__class__.__name__) - - - -class WidgetProperty(object): - def __get__(self, instance, owner): - raise UserWarning("Property is invalid!") - - def __set__(self, instance, value): - raise UserWarning("Property is invalid!") diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/customize_plot_dialog.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/customize_plot_dialog.py deleted file mode 100644 index 8b92559fbc..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/customize_plot_dialog.py +++ /dev/null @@ -1,292 +0,0 @@ -from PyQt4.QtCore import Qt, pyqtSignal, QObject -from PyQt4.QtGui import QDialog, QVBoxLayout, QLayout, QTabWidget, QHBoxLayout, QPushButton, QToolButton, QMenu, \ - QWidgetAction, QListWidget - -from ert_gui import ERT -from ert_gui.tools.plot.widgets import CopyStyleToDialog -from ert_gui.ertwidgets import resourceIcon -from ert_gui.plottery import PlotConfig, PlotConfigHistory -from ert_gui.tools.plot.customize import DefaultCustomizationView, StyleCustomizationView, \ - StatisticsCustomizationView, LimitsCustomizationView - - -class PlotCustomizer(QObject): - - settingsChanged = pyqtSignal() - - def __init__(self, parent, default_plot_settings): - super(PlotCustomizer, self).__init__() - - self._plot_config_key = None - self._previous_key = None - self.default_plot_settings = default_plot_settings - self._plot_configs = {None: PlotConfigHistory("No_Key_Selected", PlotConfig(default_plot_settings, title=None))} - - self._plotConfigCreator = self._defaultPlotConfigCreator - - self._customization_dialog = CustomizePlotDialog("Customize", parent, key=self._plot_config_key) - - self._customization_dialog.addTab("general", "General", DefaultCustomizationView()) - self._customization_dialog.addTab("style", "Style", StyleCustomizationView()) - self._customization_dialog.addTab("statistics", "Statistics", StatisticsCustomizationView()) - - self._customize_limits = LimitsCustomizationView() - self._customization_dialog.addTab("limits", "Limits", self._customize_limits) - - self._customization_dialog.applySettings.connect(self.applyCustomization) - self._customization_dialog.undoSettings.connect(self.undoCustomization) - self._customization_dialog.redoSettings.connect(self.redoCustomization) - self._customization_dialog.resetSettings.connect(self.resetCustomization) - self._customization_dialog.copySettings.connect(self.copyCustomization) - self._customization_dialog.copySettingsToOthers.connect(self.copyCustomizationTo) - self._revertCustomization(self.getPlotConfig()) - - - def _getPlotConfigHistory(self): - """ @rtype: PlotConfigHistory """ - return self._plot_configs[self._plot_config_key] - - def undoCustomization(self): - history = self._getPlotConfigHistory() - history.undoChanges() - self._revertCustomization(history.getPlotConfig()) - - def redoCustomization(self): - history = self._getPlotConfigHistory() - history.redoChanges() - self._revertCustomization(history.getPlotConfig()) - - def resetCustomization(self): - history = self._getPlotConfigHistory() - history.resetChanges() - self._revertCustomization(history.getPlotConfig()) - - - def applyCustomization(self): - history = self._getPlotConfigHistory() - plot_config = history.getPlotConfig() - if self._customization_dialog is not None: - for customization_view in self._customization_dialog: - customization_view.applyCustomization(plot_config) - - history.applyChanges(plot_config) - - self._emitChangedSignal() - - - def _revertCustomization(self, plot_config, emit=True): - if self._customization_dialog is not None: - for customization_view in self._customization_dialog: - customization_view.revertCustomization(plot_config) - - self._emitChangedSignal(emit) - - def _emitChangedSignal(self, emit=True): - history = self._getPlotConfigHistory() - self._customization_dialog.setUndoRedoCopyState(history.isUndoPossible(), history.isRedoPossible(), self.isCopyPossible()) - - if emit: - self.settingsChanged.emit() - - def isCopyPossible(self): - """ @rtype: bool """ - return len(self._plot_configs) > 2 - - def copyCustomizationTo(self, keys): - """ copies the plotconfig of the current key, to a set of other keys""" - history = self._getPlotConfigHistory() - - for key in keys: - if key not in self._plot_configs: - self._plot_configs[key] = PlotConfigHistory("No_Key_Selected", - PlotConfig(self.default_plot_settings, title=None)) - source_config = history.getPlotConfig() - source_config.setTitle(key) - - self._plot_configs[key].applyChanges(source_config) - - self._customization_dialog.addCopyableKey(key) - - self._emitChangedSignal(emit=True) - - - def copyCustomization(self, key): - key = str(key) - if self.isCopyPossible(): - source_config = self._plot_configs[key].getPlotConfig() - source_config.setTitle(None) - - history = self._getPlotConfigHistory() - history.applyChanges(source_config) - - self._revertCustomization(history.getPlotConfig()) - - def toggleCustomizationDialog(self): - if self._customization_dialog.isVisible(): - self._customization_dialog.hide() - else: - self._customization_dialog.show() - - def _defaultPlotConfigCreator(self, title): - return PlotConfig(title) - - def _selectiveCopyOfCurrentPlotConfig(self, title): - return self._plotConfigCreator(title) - - def switchPlotConfigHistory(self, key): - if key != self._plot_config_key: - if not key in self._plot_configs: - self._plot_configs[key] = PlotConfigHistory(key, self._selectiveCopyOfCurrentPlotConfig(key)) - self._customization_dialog.addCopyableKey(key) - self._customization_dialog.currentPlotKeyChanged(key) - self._previous_key = self._plot_config_key - self._plot_config_key = key - self._revertCustomization(self.getPlotConfig(), emit=False) - - def getPlotConfig(self): - """ @rtype: PlotConfig """ - return self._getPlotConfigHistory().getPlotConfig() - - def setAxisTypes(self, x_axis_type, y_axis_type): - self._customize_limits.setAxisTypes(x_axis_type, y_axis_type) - - def setPlotConfigCreator(self, func): - self._plotConfigCreator = func - - -class CustomizePlotDialog(QDialog): - applySettings = pyqtSignal() - undoSettings = pyqtSignal() - redoSettings = pyqtSignal() - resetSettings = pyqtSignal() - copySettings = pyqtSignal(str) - copySettingsToOthers = pyqtSignal(list) - - def __init__(self, title, parent=None, key=''): - QDialog.__init__(self, parent) - self.setWindowTitle(title) - - self._ert = ERT.ert - - """:type: ert.enkf.enkf_main.EnKFMain""" - - self.key_manager = self._ert.getKeyManager() - """:type: ert.enkf.key_manager.KeyManager """ - - self.current_key = key - - self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowCancelButtonHint) - - self._tab_map = {} - self._tab_order = [] - - layout = QVBoxLayout() - - self._tabs = QTabWidget() - layout.addWidget(self._tabs) - layout.setSizeConstraint(QLayout.SetFixedSize) # not resizable!!! - - self._button_layout = QHBoxLayout() - - self._reset_button = QToolButton() - self._reset_button.setIcon(resourceIcon("update.png")) - self._reset_button.setToolTip("Reset all settings back to default") - self._reset_button.clicked.connect(self.resetSettings) - - self._undo_button = QToolButton() - self._undo_button.setIcon(resourceIcon("undo.png")) - self._undo_button.setToolTip("Undo") - self._undo_button.clicked.connect(self.undoSettings) - - self._redo_button = QToolButton() - self._redo_button.setIcon(resourceIcon("redo.png")) - self._redo_button.setToolTip("Redo") - self._redo_button.clicked.connect(self.redoSettings) - self._redo_button.setEnabled(False) - - self._copy_from_button = QToolButton() - self._copy_from_button.setIcon(resourceIcon("copy_from.png")) - self._copy_from_button.setToolTip("Copy settings from another key") - self._copy_from_button.setPopupMode(QToolButton.InstantPopup) - self._copy_from_button.setEnabled(False) - - self._copy_to_button = QToolButton() - self._copy_to_button.setIcon(resourceIcon("copy_to.png")) - self._copy_to_button.setToolTip("Copy current plot settings to other keys") - self._copy_to_button.setPopupMode(QToolButton.InstantPopup) - self._copy_to_button.clicked.connect(self.initiateCopyStyleToDialog) - self._copy_to_button.setEnabled(True) - - tool_menu = QMenu(self._copy_from_button) - self._popup_list = QListWidget(tool_menu) - self._popup_list.setSortingEnabled(True) - self._popup_list.itemClicked.connect(self.keySelected) - action = QWidgetAction(tool_menu) - action.setDefaultWidget(self._popup_list) - tool_menu.addAction(action) - self._copy_from_button.setMenu(tool_menu) - - self._apply_button = QPushButton("Apply") - self._apply_button.setToolTip("Apply the new settings") - self._apply_button.clicked.connect(self.applySettings) - self._apply_button.setDefault(True) - - self._close_button = QPushButton("Close") - self._close_button.setToolTip("Hide this dialog") - self._close_button.clicked.connect(self.hide) - - self._button_layout.addWidget(self._reset_button) - self._button_layout.addStretch() - self._button_layout.addWidget(self._undo_button) - self._button_layout.addWidget(self._redo_button) - self._button_layout.addWidget(self._copy_from_button) - self._button_layout.addWidget(self._copy_to_button) - self._button_layout.addStretch() - self._button_layout.addWidget(self._apply_button) - self._button_layout.addWidget(self._close_button) - - layout.addStretch() - layout.addLayout(self._button_layout) - - self.setLayout(layout) - - def initiateCopyStyleToDialog(self): - all_other_keys = [k for k in self.key_manager.allDataTypeKeys() if k != self.current_key] - dialog = CopyStyleToDialog(self, self.current_key, all_other_keys) - if dialog.exec_(): - self.copySettingsToOthers.emit(dialog.getSelectedKeys()) - - def addCopyableKey(self, key): - self._popup_list.addItem(key) - - def keySelected(self, list_widget_item): - self.copySettings.emit(str(list_widget_item.text())) - - def currentPlotKeyChanged(self, new_key): - self.current_key = new_key - - def keyPressEvent(self, q_key_event): - if q_key_event.key() == Qt.Key_Escape: - self.hide() - else: - QDialog.keyPressEvent(self, q_key_event) - - def addTab(self, attribute_name, title, widget): - self._tabs.addTab(widget, title) - self._tab_map[attribute_name] = widget - self._tab_order.append(attribute_name) - - def __getitem__(self, item): - """ @rtype: ert_gui.tools.plot.customize.customization_view.CustomizationView """ - return self._tab_map[item] - - def __iter__(self): - for attribute_name in self._tab_order: - yield self._tab_map[attribute_name] - - def setUndoRedoCopyState(self, undo, redo, copy=False): - self._undo_button.setEnabled(undo) - self._redo_button.setEnabled(redo) - self._copy_from_button.setEnabled(copy) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/default_customization_view.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/default_customization_view.py deleted file mode 100644 index 5cd8e1f764..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/default_customization_view.py +++ /dev/null @@ -1,69 +0,0 @@ -from ert_gui.tools.plot.customize import CustomizationView, WidgetProperty - - -class DefaultCustomizationView(CustomizationView): - - title = WidgetProperty() - x_label = WidgetProperty() - y_label = WidgetProperty() - legend = WidgetProperty() - grid = WidgetProperty() - refcase = WidgetProperty() - history = WidgetProperty() - observations = WidgetProperty() - - - def __init__(self): - CustomizationView.__init__(self) - label_msg = "Set to empty to use the default %s.\n" \ - "It is also possible to use LaTeX. Enclose expression with $...$ for example: \n" \ - "$\\alpha > \\beta$\n" \ - "$r^3$\n" \ - "$\\frac{1}{x}$\n" \ - "$\\sqrt{2}$" - - self.addLineEdit("title", "Title", "The title of the plot. %s" % (label_msg % "title"), placeholder="Title") - self.addSpacing() - self.addLineEdit("x_label", "X Label", "The label of the X axis. %s" % (label_msg % "label"), placeholder="X Label") - self.addLineEdit("y_label", "Y Label", "The label of the Y axis. %s" % (label_msg % "label"), placeholder="Y Label") - self.addSpacing() - self.addCheckBox("legend", "Legend", "Toggle Legend visibility.") - self.addCheckBox("grid", "Grid", "Toggle Grid visibility.") - self.addCheckBox("refcase", "Refcase", "Toggle Refcase visibility.") - self.addCheckBox("history", "History", "Toggle History visibility.") - self.addCheckBox("observations", "Observations", "Toggle Observations visibility.") - - - def applyCustomization(self, plot_config): - """ - @type plot_config: ert_gui.plottery.PlotConfig - """ - plot_config.setTitle(self.title) - - plot_config.setXLabel(self.x_label) - plot_config.setYLabel(self.y_label) - - plot_config.setLegendEnabled(self.legend) - plot_config.setGridEnabled(self.grid) - plot_config.setRefcaseEnabled(self.refcase) - plot_config.setHistoryEnabled(self.history) - plot_config.setObservationsEnabled(self.observations) - - - def revertCustomization(self, plot_config): - """ - @type plot_config: ert_gui.plottery.PlotConfig - """ - if not plot_config.isUnnamed(): - self.title = plot_config.title() - else: - self.title = "" - - self.x_label = plot_config.xLabel() - self.y_label = plot_config.yLabel() - - self.legend = plot_config.isLegendEnabled() - self.grid = plot_config.isGridEnabled() - self.refcase = plot_config.isRefcaseEnabled() - self.history = plot_config.isHistoryEnabled() - self.observations = plot_config.isObservationsEnabled() diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/limits_customization_view.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/limits_customization_view.py deleted file mode 100644 index 90b4dadfb7..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/limits_customization_view.py +++ /dev/null @@ -1,251 +0,0 @@ -from PyQt4.QtGui import QDoubleValidator, QStackedWidget, QIntValidator, QLabel -from ert_gui.tools.plot.widgets.custom_date_edit import CustomDateEdit - -from ert_gui.plottery import PlotContext -from ert_gui.plottery.plot_limits import PlotLimits -from ert_gui.tools.plot.customize import CustomizationView -from ert_gui.tools.plot.widgets.clearable_line_edit import ClearableLineEdit - - -class StackedInput(QStackedWidget): - def __init__(self): - QStackedWidget.__init__(self) - self._inputs = {} - self._index_map = {} - self.addInput(PlotContext.UNKNOWN_AXIS, QLabel("Fixed")) - self._current_name = PlotContext.UNKNOWN_AXIS - - def addInput(self, name, widget): - index = self.addWidget(widget) - self._inputs[name] = widget - self._index_map[name] = index - - def switchToInput(self, name): - index_for_name = self._index_map[name] - self.setCurrentIndex(index_for_name) - self._current_name = name - - def getCurrentInputName(self): - return self._current_name - - -class LimitsStack(StackedInput): - FLOAT_AXIS = [PlotContext.VALUE_AXIS, PlotContext.DENSITY_AXIS, PlotContext.DEPTH_AXIS] - INT_AXIS = [PlotContext.INDEX_AXIS, PlotContext.COUNT_AXIS] - NUMBER_AXIS = FLOAT_AXIS + INT_AXIS - - def __init__(self): - StackedInput.__init__(self) - self.addInput(PlotContext.COUNT_AXIS, self.createIntegerLineEdit(minimum=0, placeholder="Default value")) - self.addInput(PlotContext.DATE_AXIS, CustomDateEdit()) - self.addInput(PlotContext.DENSITY_AXIS, self.createDoubleLineEdit(minimum=0, placeholder="Default value")) - self.addInput(PlotContext.DEPTH_AXIS, self.createDoubleLineEdit(minimum=0, placeholder="Default value")) - self.addInput(PlotContext.INDEX_AXIS, self.createIntegerLineEdit(minimum=0, placeholder="Default value")) - self.addInput(PlotContext.VALUE_AXIS, self.createDoubleLineEdit(placeholder="Default value")) - - def createDoubleLineEdit(self, minimum=None, maximum=None, placeholder=""): - line_edit = ClearableLineEdit(placeholder=placeholder) - validator = QDoubleValidator() - - if minimum is not None: - validator.setBottom(minimum) - - if maximum is not None: - validator.setTop(maximum) - - line_edit.setValidator(validator) - return line_edit - - def createIntegerLineEdit(self, minimum=None, maximum=None, placeholder=""): - line_edit = ClearableLineEdit(placeholder=placeholder) - validator = QIntValidator() - - if minimum is not None: - validator.setBottom(minimum) - - if maximum is not None: - validator.setTop(maximum) - - line_edit.setValidator(validator) - return line_edit - - def setValue(self, axis_name, value): - input = self._inputs[axis_name] - - if axis_name in LimitsStack.NUMBER_AXIS: - if value is None: - input.setText("") - else: - input.setText(str(value)) - elif axis_name == PlotContext.DATE_AXIS: - input.setDate(value) - - def getValue(self, axis_name): - input = self._inputs[axis_name] - result = None - if axis_name in LimitsStack.FLOAT_AXIS: - try: - result = float(input.text()) - except ValueError: - result = None - elif axis_name in LimitsStack.INT_AXIS: - try: - result = int(input.text()) - except ValueError: - result = None - elif axis_name == PlotContext.DATE_AXIS: - result = input.date() - - return result - - -class LimitsWidget(object): - def __init__(self): - self._limits = PlotLimits() - self._x_minimum_stack = LimitsStack() - self._x_maximum_stack = LimitsStack() - self._x_current_input_name = PlotContext.UNKNOWN_AXIS - - self._y_minimum_stack = LimitsStack() - self._y_maximum_stack = LimitsStack() - self._y_current_input_name = PlotContext.UNKNOWN_AXIS - - - @property - def x_minimum_stack(self): - """ @rtype: LimitsStack """ - return self._x_minimum_stack - - @property - def x_maximum_stack(self): - """ @rtype: LimitsStack """ - return self._x_maximum_stack - - @property - def y_minimum_stack(self): - """ @rtype: LimitsStack """ - return self._y_minimum_stack - - @property - def y_maximum_stack(self): - """ @rtype: LimitsStack """ - return self._y_maximum_stack - - @property - def limits(self): - """ @rtype: PlotLimits """ - self._updateLimits() - limits = PlotLimits() - limits.copyLimitsFrom(self._limits) - return limits - - @limits.setter - def limits(self, value): - """ @type value: PlotLimits """ - self._limits.copyLimitsFrom(value) - self._updateWidgets() - - def _updateWidgets(self): - limits = self._limits - self._x_minimum_stack.setValue(PlotContext.DATE_AXIS, limits.date_minimum) - self._x_maximum_stack.setValue(PlotContext.DATE_AXIS, limits.date_maximum) - self._y_minimum_stack.setValue(PlotContext.DATE_AXIS, limits.date_minimum) - self._y_maximum_stack.setValue(PlotContext.DATE_AXIS, limits.date_maximum) - - self._x_minimum_stack.setValue(PlotContext.DEPTH_AXIS, limits.depth_minimum) - self._x_maximum_stack.setValue(PlotContext.DEPTH_AXIS, limits.depth_maximum) - self._y_minimum_stack.setValue(PlotContext.DEPTH_AXIS, limits.depth_minimum) - self._y_maximum_stack.setValue(PlotContext.DEPTH_AXIS, limits.depth_maximum) - - self._x_minimum_stack.setValue(PlotContext.DENSITY_AXIS, limits.density_minimum) - self._x_maximum_stack.setValue(PlotContext.DENSITY_AXIS, limits.density_maximum) - self._y_minimum_stack.setValue(PlotContext.DENSITY_AXIS, limits.density_minimum) - self._y_maximum_stack.setValue(PlotContext.DENSITY_AXIS, limits.density_maximum) - - self._x_minimum_stack.setValue(PlotContext.COUNT_AXIS, limits.count_minimum) - self._x_maximum_stack.setValue(PlotContext.COUNT_AXIS, limits.count_maximum) - self._y_minimum_stack.setValue(PlotContext.COUNT_AXIS, limits.count_minimum) - self._y_maximum_stack.setValue(PlotContext.COUNT_AXIS, limits.count_maximum) - - self._x_minimum_stack.setValue(PlotContext.INDEX_AXIS, limits.index_minimum) - self._x_maximum_stack.setValue(PlotContext.INDEX_AXIS, limits.index_maximum) - self._y_minimum_stack.setValue(PlotContext.INDEX_AXIS, limits.index_minimum) - self._y_maximum_stack.setValue(PlotContext.INDEX_AXIS, limits.index_maximum) - - self._x_minimum_stack.setValue(PlotContext.VALUE_AXIS, limits.value_minimum) - self._x_maximum_stack.setValue(PlotContext.VALUE_AXIS, limits.value_maximum) - self._y_minimum_stack.setValue(PlotContext.VALUE_AXIS, limits.value_minimum) - self._y_maximum_stack.setValue(PlotContext.VALUE_AXIS, limits.value_maximum) - - - def _updateLimits(self): - if self._x_current_input_name is not PlotContext.UNKNOWN_AXIS: - minimum = self._x_minimum_stack.getValue(self._x_current_input_name) - maximum = self._x_maximum_stack.getValue(self._x_current_input_name) - self._updateLimit(self._x_current_input_name, minimum, maximum) - - if self._y_current_input_name is not PlotContext.UNKNOWN_AXIS: - minimum = self._y_minimum_stack.getValue(self._y_current_input_name) - maximum = self._y_maximum_stack.getValue(self._y_current_input_name) - self._updateLimit(self._y_current_input_name, minimum, maximum) - - - def _updateLimit(self, axis_name, minimum, maximum): - if axis_name == PlotContext.COUNT_AXIS: - self._limits.count_limits = minimum, maximum - elif axis_name == PlotContext.DENSITY_AXIS: - self._limits.density_limits = minimum, maximum - elif axis_name == PlotContext.DEPTH_AXIS: - self._limits.depth_limits = minimum, maximum - elif axis_name == PlotContext.DATE_AXIS: - self._limits.date_limits = minimum, maximum - elif axis_name == PlotContext.INDEX_AXIS: - self._limits.index_limits = minimum, maximum - elif axis_name == PlotContext.VALUE_AXIS: - self._limits.value_limits = minimum, maximum - - - def switchInputOnX(self, axis_type): - self._x_current_input_name = axis_type - self._updateWidgets() - self._x_minimum_stack.switchToInput(axis_type) - self._x_maximum_stack.switchToInput(axis_type) - - - def switchInputOnY(self, axis_type): - self._y_current_input_name = axis_type - self._updateWidgets() - self._y_minimum_stack.switchToInput(axis_type) - self._y_maximum_stack.switchToInput(axis_type) - - - -class LimitsCustomizationView(CustomizationView): - - def __init__(self): - CustomizationView.__init__(self) - - limits_widget = LimitsWidget() - self._limits_widget = limits_widget - - self.addHeading("X Axis") - self.addRow("Minimum", limits_widget.x_minimum_stack) - self.addRow("Maximum", limits_widget.x_maximum_stack) - - self.addHeading("Y Axis") - self.addRow("Minimum", limits_widget.y_minimum_stack) - self.addRow("Maximum", limits_widget.y_maximum_stack) - - - def setAxisTypes(self, x_axis_type, y_axis_type): - self._limits_widget.switchInputOnX(x_axis_type) - self._limits_widget.switchInputOnY(y_axis_type) - - def revertCustomization(self, plot_config): - """ @type plot_config: ert_gui.plottery.PlotConfig """ - self._limits_widget.limits = plot_config.limits - - - def applyCustomization(self, plot_config): - """ @type plot_config: ert_gui.plottery.PlotConfig """ - plot_config.limits = self._limits_widget.limits diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/statistics_customization_view.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/statistics_customization_view.py deleted file mode 100644 index 8ce2f0d9cc..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/statistics_customization_view.py +++ /dev/null @@ -1,125 +0,0 @@ -from PyQt4.QtGui import QHBoxLayout, QLabel, QComboBox - -from ert_gui.tools.plot.customize import CustomizationView, WidgetProperty -from ert_gui.tools.plot import style_chooser as sc - -class StatisticsCustomizationView(CustomizationView): - mean_style = WidgetProperty() - p50_style = WidgetProperty() - std_style = WidgetProperty() - min_max_style = WidgetProperty() - p10_p90_style = WidgetProperty() - p33_p67_style = WidgetProperty() - std_dev_factor = WidgetProperty() - distribution_lines = WidgetProperty() - - - def __init__(self): - CustomizationView.__init__(self) - - self._presets = ["Statistics Default", "Cross Case Statistics Default", "Overview", "All statistics"] - - self.addRow("Presets", self.createPresets()) - self.addSpacing(10) - layout = QHBoxLayout() - self.addRow("", layout) - self.addStyleChooser("mean_style", "Mean", "Line and marker style for the mean line.") - self.addStyleChooser("p50_style", "P50", "Line and marker style for the P50 line.") - self.addStyleChooser("std_style", "Std dev", - "Line and marker style for the unbiased standard deviation lines.", - line_style_set=sc.STYLESET_AREA) - self.addStyleChooser("min_max_style", "Min/Max", - "Line and marker style for the min/max lines.", - line_style_set=sc.STYLESET_AREA) - self.addStyleChooser("p10_p90_style", "P10-P90", - "Line and marker style for the P10-P90 lines.", - line_style_set=sc.STYLESET_AREA) - self.addStyleChooser("p33_p67_style", "P33-P67", - "Line and marker style for the P33-P67 lines.", - line_style_set=sc.STYLESET_AREA) - self.addSpacing() - - std_box = self.addSpinBox("std_dev_factor", "Std dev multiplier", - "Choose which standard deviation to plot", max_value=3) - - self.addCheckBox("distribution_lines", "Connection Lines", "Toggle distribution connection lines visibility.") - - self["mean_style"].createLabelLayout(layout) - - - - def createPresets(self): - preset_combo = QComboBox() - for preset in self._presets: - preset_combo.addItem(preset) - - preset_combo.currentIndexChanged.connect(self.presetSelected) - return preset_combo - - - def presetSelected(self, index): - if index == 0: # Default - self.updateStyle("mean_style", "-", None) - self.updateStyle("p50_style", None, None) - self.updateStyle("std_style", None, None) - self.updateStyle("min_max_style", None, None) - self.updateStyle("p10_p90_style", "--", None) - self.updateStyle("p33_p67_style", None, None) - elif index == 1: # CCS Default - self.updateStyle("mean_style", "-", "o") - self.updateStyle("p50_style", None, None) - self.updateStyle("std_style", "--", "D") - self.updateStyle("min_max_style", None, None) - self.updateStyle("p10_p90_style", None, None) - self.updateStyle("p33_p67_style", None, None) - elif index == 2: # Overview - self.updateStyle("mean_style", None, None) - self.updateStyle("p50_style", None, None) - self.updateStyle("std_style", None, None) - self.updateStyle("min_max_style", "#", None) - self.updateStyle("p10_p90_style", None, None) - self.updateStyle("p33_p67_style", None, None) - elif index == 3: # All statistics - self.updateStyle("mean_style", "-", None) - self.updateStyle("p50_style", "--", "x") - self.updateStyle("std_style", ":", None) - self.updateStyle("min_max_style", "--", None) - self.updateStyle("p10_p90_style", "#", None) - self.updateStyle("p33_p67_style", "#", None) - - - def updateStyle(self, attribute_name, line_style, marker_style): - style = getattr(self, attribute_name) - style.line_style = line_style - style.marker = marker_style - setattr(self, attribute_name, style) - - - def applyCustomization(self, plot_config): - """ - @type plot_config: ert_gui.plottery.PlotConfig - """ - plot_config.setStatisticsStyle("mean", self.mean_style) - plot_config.setStatisticsStyle("p50", self.p50_style) - plot_config.setStatisticsStyle("std", self.std_style) - plot_config.setStatisticsStyle("min-max", self.min_max_style) - plot_config.setStatisticsStyle("p10-p90", self.p10_p90_style) - plot_config.setStatisticsStyle("p33-p67", self.p33_p67_style) - - plot_config.setStandardDeviationFactor(self.std_dev_factor) - plot_config.setDistributionLineEnabled(self.distribution_lines) - - - def revertCustomization(self, plot_config): - """ - @type plot_config: ert_gui.plottery.PlotConfig - """ - self.mean_style = plot_config.getStatisticsStyle("mean") - self.p50_style = plot_config.getStatisticsStyle("p50") - self.std_style = plot_config.getStatisticsStyle("std") - self.min_max_style = plot_config.getStatisticsStyle("min-max") - self.p10_p90_style = plot_config.getStatisticsStyle("p10-p90") - self.p33_p67_style = plot_config.getStatisticsStyle("p33-p67") - - self.std_dev_factor = plot_config.getStandardDeviationFactor() - self.distribution_lines = plot_config.isDistributionLineEnabled() diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/style_customization_view.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/style_customization_view.py deleted file mode 100644 index 96b2eb25ef..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/customize/style_customization_view.py +++ /dev/null @@ -1,94 +0,0 @@ -from PyQt4.QtGui import QHBoxLayout, QLabel, QColor - -from ert_gui.tools.plot import ColorBox -from ert_gui.tools.plot.customize import CustomizationView, WidgetProperty - -from ert_gui.tools.plot import style_chooser as sc - -class StyleCustomizationView(CustomizationView): - default_style = WidgetProperty() - refcase_style = WidgetProperty() - history_style = WidgetProperty() - observs_style = WidgetProperty() - color_cycle = WidgetProperty() - observs_color = WidgetProperty() - - def __init__(self): - CustomizationView.__init__(self) - - layout = QHBoxLayout() - - self.addRow("", layout) - self.addStyleChooser("default_style", "Default", "Line and marker style for default lines.") - self.addStyleChooser("refcase_style", "Refcase", "Line and marker style for the refcase line.") - self.addStyleChooser("history_style", "History", "Line and marker style for the history line.") - self.addStyleChooser("observs_style", "Observation", "Line and marker style for the observation line.", - line_style_set=sc.STYLESET_TOGGLE) - - self["default_style"].createLabelLayout(layout) - - self.addSpacing(10) - - color_layout = QHBoxLayout() - - self._color_boxes = [] - for name in ["#1", "#2", "#3", "#4", "#5"]: - color_box = self.createColorBox(name) - self._color_boxes.append(color_box) - color_layout.addWidget(color_box) - - self.addRow("Color Cycle", color_layout) - self.updateProperty("color_cycle", StyleCustomizationView.getColorCycle, StyleCustomizationView.setColorCycle) - - self._observs_color_box = self.createColorBox("observations_color") - self.addRow('Observations Color', self._observs_color_box) - self.updateProperty("observs_color", - StyleCustomizationView.getObservationsColor, - StyleCustomizationView.setObservationsColor) - - def getObservationsColor(self): - return str(self._observs_color_box.color.name()) - - def setObservationsColor(self, name): - self._observs_color_box.color = name - - def createColorBox(self, name): - color_box = ColorBox(QColor(255, 255, 255), 20) - color_box.setToolTip(name) - return color_box - - def getColorCycle(self): - colors = [] - for color_box in self._color_boxes: - colors.append(str(color_box.color.name())) - - return colors - - def setColorCycle(self, color_cycle): - for index, color in enumerate(color_cycle): - if 0 <= index < len(self._color_boxes): - color_box = self._color_boxes[index] - color_box.color = color - - def applyCustomization(self, plot_config): - """ - @type plot_config: ert_gui.plottery.PlotConfig - """ - plot_config.setDefaultStyle(self.default_style) - plot_config.setRefcaseStyle(self.refcase_style) - plot_config.setHistoryStyle(self.history_style) - plot_config.setObservationsStyle(self.observs_style) - plot_config.setObservationsColor(self.observs_color) - plot_config.setLineColorCycle(self.color_cycle) - - def revertCustomization(self, plot_config): - """ - @type plot_config: ert_gui.plottery.PlotConfig - """ - self.default_style = plot_config.defaultStyle() - self.refcase_style = plot_config.refcaseStyle() - self.history_style = plot_config.historyStyle() - self.observs_style = plot_config.observationsStyle() - self.observs_color = plot_config.observationsColor() - self.color_cycle = plot_config.lineColorCycle() - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_keys_list_model.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_keys_list_model.py deleted file mode 100644 index 4c4a509ba6..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_keys_list_model.py +++ /dev/null @@ -1,77 +0,0 @@ -from PyQt4.QtCore import QAbstractItemModel, QModelIndex, Qt, QVariant -from PyQt4.QtGui import QColor - -from ert_gui.ertwidgets import resourceIcon - - -class DataTypeKeysListModel(QAbstractItemModel): - DEFAULT_DATA_TYPE = QColor(255, 255, 255) - HAS_OBSERVATIONS = QColor(237, 218, 116) - GROUP_ITEM = QColor(64, 64, 64) - - def __init__(self, ert): - """ - @type ert: ert.enkf.EnKFMain - """ - QAbstractItemModel.__init__(self) - self.__ert = ert - self.__icon = resourceIcon("ide/small/bullet_star") - - def keyManager(self): - return self.__ert.getKeyManager() - - def index(self, row, column, parent=None, *args, **kwargs): - return self.createIndex(row, column, parent) - - def parent(self, index=None): - return QModelIndex() - - def rowCount(self, parent=None, *args, **kwargs): - return len(self.keyManager().allDataTypeKeys()) - - def columnCount(self, QModelIndex_parent=None, *args, **kwargs): - return 1 - - def data(self, index, role=None): - assert isinstance(index, QModelIndex) - - if index.isValid(): - items = self.keyManager().allDataTypeKeys() - row = index.row() - item = items[row] - - if role == Qt.DisplayRole: - return item - elif role == Qt.BackgroundRole: - if self.keyManager().isKeyWithObservations(item): - return self.HAS_OBSERVATIONS - - return QVariant() - - def itemAt(self, index): - assert isinstance(index, QModelIndex) - - if index.isValid(): - row = index.row() - return self.keyManager().allDataTypeKeys()[row] - - return None - - - def isSummaryKey(self, key): - return self.keyManager().isSummaryKey(key) - - def isBlockKey(self, key): - return False - - def isGenKWKey(self, key): - return self.keyManager().isGenKwKey(key) - - def isGenDataKey(self, key): - return self.keyManager().isGenDataKey(key) - - def isCustomKwKey(self, key): - return self.keyManager().isCustomKwKey(key) - - def isCustomPcaKey(self, key): - return False diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_keys_widget.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_keys_widget.py deleted file mode 100644 index 13914f2744..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_keys_widget.py +++ /dev/null @@ -1,78 +0,0 @@ -from PyQt4.QtCore import pyqtSignal -from PyQt4.QtGui import QWidget, QVBoxLayout, QListView, QHBoxLayout, QToolButton - -from ert_gui.ertwidgets import SearchBox, resourceIcon, Legend -from ert_gui.tools.plot import DataTypeKeysListModel, DataTypeProxyModel, FilterPopup - - -class DataTypeKeysWidget(QWidget): - dataTypeKeySelected = pyqtSignal() - - def __init__(self, model): - QWidget.__init__(self) - - self.__filter_popup = FilterPopup(self) - self.__filter_popup.filterSettingsChanged.connect(self.onItemChanged) - - layout = QVBoxLayout() - - self.model = model - self.filter_model = DataTypeProxyModel(self.model) - - filter_layout = QHBoxLayout() - - self.search_box = SearchBox() - self.search_box.filterChanged.connect(self.setSearchString) - filter_layout.addWidget(self.search_box) - - filter_popup_button = QToolButton() - filter_popup_button.setIcon(resourceIcon("ide/cog_edit.png")) - filter_popup_button.clicked.connect(self.showFilterPopup) - filter_layout.addWidget(filter_popup_button) - layout.addLayout(filter_layout) - - self.data_type_keys_widget = QListView() - self.data_type_keys_widget.setModel(self.filter_model) - self.data_type_keys_widget.selectionModel().selectionChanged.connect(self.itemSelected) - - layout.addSpacing(15) - layout.addWidget(self.data_type_keys_widget, 2) - layout.addStretch() - - # layout.addWidget(Legend("Default types", DataTypeKeysListModel.DEFAULT_DATA_TYPE)) - layout.addWidget(Legend("Observations available", DataTypeKeysListModel.HAS_OBSERVATIONS)) - - self.setLayout(layout) - - def onItemChanged(self, item): - # self.filter_model.setShowBlockKeys(item["block"]) - self.filter_model.setShowSummaryKeys(item["summary"]) - self.filter_model.setShowGenKWKeys(item["gen_kw"]) - self.filter_model.setShowGenDataKeys(item["gen_data"]) - self.filter_model.setShowCustomKwKeys(item["custom_kw"]) - # self.filter_model.setShowCustomPcaKeys(item["custom_pca"]) - - - def itemSelected(self): - selected_item = self.getSelectedItem() - if selected_item is not None: - self.dataTypeKeySelected.emit() - - - def getSelectedItem(self): - """ @rtype: str """ - index = self.data_type_keys_widget.currentIndex() - source_index = self.filter_model.mapToSource(index) - item = self.model.itemAt(source_index) - return item - - def selectDefault(self): - self.data_type_keys_widget.setCurrentIndex(self.filter_model.index(0, 0)) - - - def setSearchString(self, filter): - self.filter_model.setFilterFixedString(filter) - - def showFilterPopup(self): - self.__filter_popup.show() - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_proxy_model.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_proxy_model.py deleted file mode 100644 index 059762f9ef..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/data_type_proxy_model.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'data_type_proxy_model.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from PyQt4.QtCore import Qt -from PyQt4.QtGui import QSortFilterProxyModel -from ert_gui.tools.plot import DataTypeKeysListModel - - -class DataTypeProxyModel(QSortFilterProxyModel): - - def __init__(self, model , parent=None): - QSortFilterProxyModel.__init__(self, parent) - self.__show_summary_keys = True - self.__show_block_keys = True - self.__show_gen_kw_keys = True - self.__show_gen_data_keys = True - self.__show_custom_kw_keys = True - self.__show_custom_pca_keys = True - - self.setFilterCaseSensitivity(Qt.CaseInsensitive) - self.setSourceModel(model) - - def filterAcceptsRow(self, index, q_model_index): - show = QSortFilterProxyModel.filterAcceptsRow(self, index, q_model_index) - - if show: - source_model = self.sourceModel() - source_index = source_model.index(index, 0, q_model_index) - key = source_model.itemAt(source_index) - - if not self.__show_summary_keys and source_model.isSummaryKey(key): - show = False - - elif not self.__show_block_keys and source_model.isBlockKey(key): - show = False - - elif not self.__show_gen_kw_keys and source_model.isGenKWKey(key): - show = False - - elif not self.__show_gen_data_keys and source_model.isGenDataKey(key): - show = False - - elif not self.__show_custom_kw_keys and source_model.isCustomKwKey(key): - show = False - - elif not self.__show_custom_pca_keys and source_model.isCustomPcaKey(key): - show = False - - - return show - - def sourceModel(self): - """ @rtype: DataTypeKeysListModel """ - return QSortFilterProxyModel.sourceModel(self) - - def setShowSummaryKeys(self, visible): - self.__show_summary_keys = visible - self.invalidateFilter() - - def setShowBlockKeys(self, visible): - self.__show_block_keys = visible - self.invalidateFilter() - - def setShowGenKWKeys(self, visible): - self.__show_gen_kw_keys = visible - self.invalidateFilter() - - def setShowGenDataKeys(self, visible): - self.__show_gen_data_keys = visible - self.invalidateFilter() - - def setShowCustomKwKeys(self, visible): - self.__show_custom_kw_keys = visible - self.invalidateFilter() - - def setShowCustomPcaKeys(self, visible): - self.__show_custom_pca_keys = visible - self.invalidateFilter() - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/filter_popup.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/filter_popup.py deleted file mode 100644 index cfb286533a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/filter_popup.py +++ /dev/null @@ -1,58 +0,0 @@ -from PyQt4.QtCore import Qt, pyqtSignal -from PyQt4.QtGui import QWidget, QFrame, QDialog, QVBoxLayout, QCheckBox, QLabel, QLayout, QCursor - - -class FilterPopup(QDialog): - filterSettingsChanged = pyqtSignal(dict) - - def __init__(self, parent=None): - QDialog.__init__(self, parent, Qt.WindowStaysOnTopHint | Qt.X11BypassWindowManagerHint | Qt.FramelessWindowHint) - self.setVisible(False) - - self.filter_items = {} - - layout = QVBoxLayout() - layout.setMargin(0) - frame = QFrame() - frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) - layout.addWidget(frame) - - self.__layout = QVBoxLayout() - self.__layout.setSizeConstraint(QLayout.SetFixedSize) - self.__layout.addWidget(QLabel("Filter by data type:")) - - self.addFilterItem("Summary", "summary") - # self.addFilterItem("Block", "block") - self.addFilterItem("Gen KW", "gen_kw") - self.addFilterItem("Gen Data", "gen_data") - self.addFilterItem("Custom KW", "custom_kw") - # self.addFilterItem("Custom PCA", "custom_pca") - - frame.setLayout(self.__layout) - - self.setLayout(layout) - self.adjustSize() - - - def addFilterItem(self, name, id, value=True): - self.filter_items[id] = value - - check_box = QCheckBox(name) - check_box.setChecked(value) - - def toggleItem(checked): - self.filter_items[id] = checked - self.filterSettingsChanged.emit(self.filter_items) - - check_box.toggled.connect(toggleItem) - - self.__layout.addWidget(check_box) - - def leaveEvent(self, QEvent): - QWidget.leaveEvent(self, QEvent) - self.hide() - - def show(self): - QWidget.show(self) - p = QCursor().pos() - self.move(p.x(), p.y()) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/filterable_kw_list_model.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/filterable_kw_list_model.py deleted file mode 100644 index 0d0f83f3ab..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/filterable_kw_list_model.py +++ /dev/null @@ -1,55 +0,0 @@ -from ert_gui.ertwidgets.models.selectable_list_model import SelectableListModel - - -class FilterableKwListModel(SelectableListModel): - """ - Adds ERT - plotting keyword specific filtering functionality to the general SelectableListModel - """ - def __init__(self, ert, selectable_keys): - SelectableListModel.__init__(self, selectable_keys) - self._ert = ert - self._show_summary_keys = True - self._show_gen_kw_keys = True - self._show_gen_data_keys = True - self._show_custom_kw_keys = True - - def getList(self): - filtered_list = [] - for item in self._items: - if self._show_summary_keys and self.isSummaryKey(item): - filtered_list.append(item) - elif self._show_gen_kw_keys and self.isGenKWKey(item): - filtered_list.append(item) - elif self._show_gen_data_keys and self.isGenDataKey(item): - filtered_list.append(item) - elif self._show_custom_kw_keys and self.isCustomKwKey(item): - filtered_list.append(item) - - return filtered_list - - def keyManager(self): - return self._ert.getKeyManager() - - def isSummaryKey(self, key): - return self.keyManager().isSummaryKey(key) - - def isGenKWKey(self, key): - return self.keyManager().isGenKwKey(key) - - def isGenDataKey(self, key): - return self.keyManager().isGenDataKey(key) - - def isCustomKwKey(self, key): - return self.keyManager().isCustomKwKey(key) - - def setShowSummaryKeys(self, visible): - self._show_summary_keys = visible - - def setShowGenKWKeys(self, visible): - self._show_gen_kw_keys = visible - - def setShowGenDataKeys(self, visible): - self._show_gen_data_keys = visible - - def setShowCustomKwKeys(self, visible): - self._show_custom_kw_keys = visible diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_case_model.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_case_model.py deleted file mode 100644 index bc1029cfc1..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_case_model.py +++ /dev/null @@ -1,69 +0,0 @@ -from PyQt4.QtCore import QAbstractItemModel, QModelIndex, Qt, QVariant - -from ert_gui.ertwidgets.models.ertmodel import getAllCasesNotRunning - - -class PlotCaseModel(QAbstractItemModel): - - def __init__(self): - QAbstractItemModel.__init__(self) - self.__data = None - - def index(self, row, column, parent=None, *args, **kwargs): - return self.createIndex(row, column, parent) - - def parent(self, index=None): - return QModelIndex() - - def rowCount(self, parent=None, *args, **kwargs): - items = self.getAllItems() - return len(items) - - def columnCount(self, QModelIndex_parent=None, *args, **kwargs): - return 1 - - - def data(self, index, role=None): - assert isinstance(index, QModelIndex) - - if index.isValid(): - items = self.getAllItems() - row = index.row() - item = items[row] - - if role == Qt.DisplayRole: - return item - - return QVariant() - - def itemAt(self, index): - assert isinstance(index, QModelIndex) - - if index.isValid(): - row = index.row() - return self.getAllItems()[row] - - return None - - - def getAllItems(self): - if self.__data is None: - self.__data = getAllCasesNotRunning() - - return self.__data - - def __iter__(self): - cur = 0 - while cur < self.rowCount(): - yield self.itemAt(self.index(cur, 0)) - cur += 1 - - - - - - - - - - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_case_selection_widget.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_case_selection_widget.py deleted file mode 100644 index 6942795949..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_case_selection_widget.py +++ /dev/null @@ -1,119 +0,0 @@ -from PyQt4.QtCore import pyqtSignal, QSignalMapper, Qt -from PyQt4.QtGui import QWidget, QVBoxLayout, QHBoxLayout, QToolButton, QComboBox - -from ert_gui.ertwidgets import resourceIcon -from ert_gui.tools.plot import PlotCaseModel - - -class CaseSelectionWidget(QWidget): - - caseSelectionChanged = pyqtSignal() - - def __init__(self, current_case): - QWidget.__init__(self) - - self.__model = PlotCaseModel() - - self.__signal_mapper = QSignalMapper(self) - self.__case_selectors = {} - self.__case_selectors_order = [] - - layout = QVBoxLayout() - - add_button_layout = QHBoxLayout() - self.__add_case_button = QToolButton() - self.__add_case_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) - self.__add_case_button.setText("Add case to plot") - self.__add_case_button.setIcon(resourceIcon("ide/small/add")) - self.__add_case_button.clicked.connect(self.addCaseSelector) - - add_button_layout.addStretch() - add_button_layout.addWidget(self.__add_case_button) - add_button_layout.addStretch() - - layout.addLayout(add_button_layout) - - self.__case_layout = QVBoxLayout() - self.__case_layout.setMargin(0) - layout.addLayout(self.__case_layout) - - self.addCaseSelector(disabled=True, current_case=current_case) - layout.addStretch() - - self.setLayout(layout) - - self.__signal_mapper.mapped[QWidget].connect(self.removeWidget) - - - def __caseName(self, widget): - """ @rtype: str """ - return str(self.__case_selectors[widget].currentText()) - - def getPlotCaseNames(self): - if self.__model.rowCount() == 0: - return [] - - return [self.__caseName(widget) for widget in self.__case_selectors_order] - - def checkCaseCount(self): - state = True - if len(self.__case_selectors_order) == 5: - state = False - - self.__add_case_button.setEnabled(state) - - - def addCaseSelector(self, disabled=False, current_case=None): - widget = QWidget() - - layout = QHBoxLayout() - layout.setMargin(0) - widget.setLayout(layout) - - combo = QComboBox() - combo.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLengthWithIcon) - combo.setMinimumContentsLength(20) - combo.setModel(self.__model) - - if current_case is not None: - index = 0 - for item in self.__model: - if item == current_case: - combo.setCurrentIndex(index) - break - index += 1 - - combo.currentIndexChanged.connect(self.caseSelectionChanged.emit) - - - - layout.addWidget(combo, 1) - - button = QToolButton() - button.setAutoRaise(True) - button.setDisabled(disabled) - button.setIcon(resourceIcon("ide/small/delete")) - button.clicked.connect(self.__signal_mapper.map) - - layout.addWidget(button) - - self.__case_selectors[widget] = combo - self.__case_selectors_order.append(widget) - self.__signal_mapper.setMapping(button, widget) - - self.__case_layout.addWidget(widget) - - self.checkCaseCount() - self.caseSelectionChanged.emit() - - - - def removeWidget(self, widget): - self.__case_layout.removeWidget(widget) - del self.__case_selectors[widget] - self.__case_selectors_order.remove(widget) - widget.setParent(None) - self.caseSelectionChanged.emit() - - self.checkCaseCount() - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_tool.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_tool.py deleted file mode 100644 index 6433919831..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_tool.py +++ /dev/null @@ -1,14 +0,0 @@ -from ert_gui.ertwidgets import resourceIcon -from ert_gui.tools import Tool -from ert_gui.tools.plot import PlotWindow - - -class PlotTool(Tool): - def __init__(self): - super(PlotTool, self).__init__("Create Plot", "tools/plot", resourceIcon("ide/chart_curve_add")) - - def trigger(self): - plot_window = PlotWindow(self.parent()) - plot_window.show() - - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_widget.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_widget.py deleted file mode 100644 index b250eed2a0..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_widget.py +++ /dev/null @@ -1,112 +0,0 @@ -import sys -import traceback - -from PyQt4.QtCore import Qt, pyqtSignal -from PyQt4.QtGui import QWidget, QVBoxLayout, QAction - -from matplotlib.figure import Figure -from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas, NavigationToolbar2QT - -from ert_gui.ertwidgets import resourceIcon - - -class CustomNavigationToolbar(NavigationToolbar2QT): - customizationTriggered = pyqtSignal() - - def __init__(self, canvas, parent, coordinates=True): - super(CustomNavigationToolbar, self).__init__(canvas, parent, coordinates) - - gear = resourceIcon("ide/cog_edit.png") - customize_action = QAction(gear, "Customize", self) - customize_action.setToolTip("Customize plot settings") - customize_action.triggered.connect(self.customizationTriggered) - - for action in self.actions(): - if str(action.text()).lower() == "subplots": - self.removeAction(action) - - if str(action.text()).lower() == "customize": - self.insertAction(action, customize_action) - self.removeAction(action) - break - - - -class PlotWidget(QWidget): - customizationTriggered = pyqtSignal() - - def __init__(self, name, plotFunction, plot_condition_function_list, plotContextFunction, parent=None): - QWidget.__init__(self, parent) - - self._name = name - self._plotFunction = plotFunction - self._plotContextFunction = plotContextFunction - self._plot_conditions = plot_condition_function_list - """:type: list of functions """ - - self._figure = Figure() - self._figure.set_tight_layout(True) - self._canvas = FigureCanvas(self._figure) - self._canvas.setParent(self) - self._canvas.setFocusPolicy(Qt.StrongFocus) - self._canvas.setFocus() - - vbox = QVBoxLayout() - vbox.addWidget(self._canvas) - self._toolbar = CustomNavigationToolbar(self._canvas, self) - self._toolbar.customizationTriggered.connect(self.customizationTriggered) - vbox.addWidget(self._toolbar) - self.setLayout(vbox) - - self._dirty = True - self._active = False - self.resetPlot() - - - def getFigure(self): - """ :rtype: matplotlib.figure.Figure""" - return self._figure - - - def resetPlot(self): - self._figure.clear() - - @property - def name(self): - """ @rtype: str """ - return self._name - - def updatePlot(self): - if self.isDirty() and self.isActive(): - # print("Drawing: %s" % self._name) - self.resetPlot() - plot_context = self._plotContextFunction(self.getFigure()) - try: - self._plotFunction(plot_context) - self._canvas.draw() - except StandardError as e: - exc_type, exc_value, exc_tb = sys.exc_info() - sys.stderr.write("%s\n" % ("-" * 80)) - traceback.print_tb(exc_tb) - sys.stderr.write("Exception type: %s\n" % exc_type.__name__) - sys.stderr.write("%s\n" % e.message) - sys.stderr.write("%s\n" % ("-" * 80)) - sys.stderr.write("An error occurred during plotting. This stack trace is helpful for diagnosing the problem.") - - self.setDirty(False) - - - def setDirty(self, dirty=True): - self._dirty = dirty - - def isDirty(self): - return self._dirty - - def setActive(self, active=True): - self._active = active - - def isActive(self): - return self._active - - def canPlotKey(self, key): - return any([plotConditionFunction(key) for plotConditionFunction in self._plot_conditions]) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_window.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_window.py deleted file mode 100644 index 66a4da77a1..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/plot_window.py +++ /dev/null @@ -1,199 +0,0 @@ -from PyQt4.QtCore import Qt -from PyQt4.QtGui import QMainWindow, QDockWidget, QTabWidget, QWidget, QVBoxLayout - -from ert_gui import ERT -from ert_gui.ertwidgets import showWaitCursorWhileWaiting -from ert_gui.ertwidgets.models.ertmodel import getCurrentCaseName -from ert_gui.plottery import PlotContext, PlotDataGatherer as PDG, PlotConfig, plots, PlotConfigFactory - -from ert_gui.tools.plot import DataTypeKeysWidget, CaseSelectionWidget, PlotWidget, DataTypeKeysListModel -from ert_gui.tools.plot.customize import PlotCustomizer - -CROSS_CASE_STATISTICS = "Cross Case Statistics" -DISTRIBUTION = "Distribution" -GAUSSIAN_KDE = "Gaussian KDE" -ENSEMBLE = "Ensemble" -HISTOGRAM = "Histogram" -STATISTICS = "Statistics" - -class PlotWindow(QMainWindow): - - - def __init__(self, parent): - QMainWindow.__init__(self, parent) - - self._ert = ERT.ert - """:type: ert.enkf.enkf_main.EnKFMain""" - - key_manager = self._ert.getKeyManager() - """:type: ert.enkf.key_manager.KeyManager """ - - self.setMinimumWidth(850) - self.setMinimumHeight(650) - - self.setWindowTitle("Plotting") - self.activateWindow() - - self._plot_customizer = PlotCustomizer(self, self._ert.plotConfig()) - - def plotConfigCreator(key): - return PlotConfigFactory.createPlotConfigForKey(self._ert, key) - - self._plot_customizer.setPlotConfigCreator(plotConfigCreator) - self._plot_customizer.settingsChanged.connect(self.keySelected) - - self._central_tab = QTabWidget() - self._central_tab.currentChanged.connect(self.currentPlotChanged) - - central_widget = QWidget() - central_layout = QVBoxLayout() - central_layout.setContentsMargins(0, 0, 0, 0) - central_widget.setLayout(central_layout) - - central_layout.addWidget(self._central_tab) - - self.setCentralWidget(central_widget) - - self._plot_widgets = [] - """:type: list of PlotWidget""" - - self._data_gatherers = [] - """:type: list of PlotDataGatherer """ - - summary_gatherer = self.createDataGatherer(PDG.gatherSummaryData, key_manager.isSummaryKey, refcaseGatherFunc=PDG.gatherSummaryRefcaseData, observationGatherFunc=PDG.gatherSummaryObservationData, historyGatherFunc=PDG.gatherSummaryHistoryData) - gen_data_gatherer = self.createDataGatherer(PDG.gatherGenDataData, key_manager.isGenDataKey, observationGatherFunc=PDG.gatherGenDataObservationData) - gen_kw_gatherer = self.createDataGatherer(PDG.gatherGenKwData, key_manager.isGenKwKey) - custom_kw_gatherer = self.createDataGatherer(PDG.gatherCustomKwData, key_manager.isCustomKwKey) - - - self.addPlotWidget(ENSEMBLE, plots.plotEnsemble, [summary_gatherer, gen_data_gatherer]) - self.addPlotWidget(STATISTICS, plots.plotStatistics, [summary_gatherer, gen_data_gatherer]) - self.addPlotWidget(HISTOGRAM, plots.plotHistogram, [gen_kw_gatherer, custom_kw_gatherer]) - self.addPlotWidget(GAUSSIAN_KDE, plots.plotGaussianKDE, [gen_kw_gatherer, custom_kw_gatherer]) - self.addPlotWidget(DISTRIBUTION, plots.plotDistribution, [gen_kw_gatherer, custom_kw_gatherer]) - self.addPlotWidget(CROSS_CASE_STATISTICS, plots.plotCrossCaseStatistics, [gen_kw_gatherer, custom_kw_gatherer]) - - - data_types_key_model = DataTypeKeysListModel(self._ert) - - self._data_type_keys_widget = DataTypeKeysWidget(data_types_key_model) - self._data_type_keys_widget.dataTypeKeySelected.connect(self.keySelected) - self.addDock("Data types", self._data_type_keys_widget) - - current_case = getCurrentCaseName() - self._case_selection_widget = CaseSelectionWidget(current_case) - self._case_selection_widget.caseSelectionChanged.connect(self.keySelected) - self.addDock("Plot case", self._case_selection_widget) - - current_plot_widget = self._plot_widgets[self._central_tab.currentIndex()] - current_plot_widget.setActive() - self._data_type_keys_widget.selectDefault() - self._updateCustomizer(current_plot_widget) - - - - - def createDataGatherer(self, dataGatherFunc, gatherConditionFunc, refcaseGatherFunc=None, observationGatherFunc=None, historyGatherFunc=None): - data_gatherer = PDG(dataGatherFunc, gatherConditionFunc, refcaseGatherFunc=refcaseGatherFunc, observationGatherFunc=observationGatherFunc, historyGatherFunc=historyGatherFunc) - self._data_gatherers.append(data_gatherer) - return data_gatherer - - - def currentPlotChanged(self): - for plot_widget in self._plot_widgets: - plot_widget.setActive(False) - index = self._central_tab.indexOf(plot_widget) - - if index == self._central_tab.currentIndex() and plot_widget.canPlotKey(self.getSelectedKey()): - plot_widget.setActive() - self._updateCustomizer(plot_widget) - plot_widget.updatePlot() - - def _updateCustomizer(self, plot_widget): - """ @type plot_widget: PlotWidget """ - key = self.getSelectedKey() - key_manager = self._ert.getKeyManager() - - index_type = PlotContext.UNKNOWN_AXIS - - if key_manager.isGenDataKey(key): - index_type = PlotContext.INDEX_AXIS - elif key_manager.isSummaryKey(key): - index_type = PlotContext.DATE_AXIS - - x_axis_type = PlotContext.UNKNOWN_AXIS - y_axis_type = PlotContext.UNKNOWN_AXIS - - if plot_widget.name == ENSEMBLE: - x_axis_type = index_type - y_axis_type = PlotContext.VALUE_AXIS - elif plot_widget.name == STATISTICS: - x_axis_type = index_type - y_axis_type = PlotContext.VALUE_AXIS - elif plot_widget.name == DISTRIBUTION: - y_axis_type = PlotContext.VALUE_AXIS - elif plot_widget.name == CROSS_CASE_STATISTICS: - y_axis_type = PlotContext.VALUE_AXIS - elif plot_widget.name == HISTOGRAM: - x_axis_type = PlotContext.VALUE_AXIS - y_axis_type = PlotContext.COUNT_AXIS - elif plot_widget.name == GAUSSIAN_KDE: - x_axis_type = PlotContext.VALUE_AXIS - y_axis_type = PlotContext.DENSITY_AXIS - - self._plot_customizer.setAxisTypes(x_axis_type, y_axis_type) - - - def createPlotContext(self, figure): - key = self.getSelectedKey() - cases = self._case_selection_widget.getPlotCaseNames() - data_gatherer = self.getDataGathererForKey(key) - plot_config = PlotConfig.createCopy(self._plot_customizer.getPlotConfig()) - plot_config.setTitle(key) - return PlotContext(self._ert, figure, plot_config, cases, key, data_gatherer) - - def getDataGathererForKey(self, key): - """ @rtype: PlotDataGatherer """ - return next((data_gatherer for data_gatherer in self._data_gatherers if data_gatherer.canGatherDataForKey(key)), None) - - def getSelectedKey(self): - return str(self._data_type_keys_widget.getSelectedItem()) - - def addPlotWidget(self, name, plotFunction, data_gatherers, enabled=True): - plot_condition_function_list = [data_gatherer.canGatherDataForKey for data_gatherer in data_gatherers] - plot_widget = PlotWidget(name, plotFunction, plot_condition_function_list, self.createPlotContext) - plot_widget.customizationTriggered.connect(self.toggleCustomizeDialog) - - index = self._central_tab.addTab(plot_widget, name) - self._plot_widgets.append(plot_widget) - self._central_tab.setTabEnabled(index, enabled) - - - def addDock(self, name, widget, area=Qt.LeftDockWidgetArea, allowed_areas=Qt.AllDockWidgetAreas): - dock_widget = QDockWidget(name) - dock_widget.setObjectName("%sDock" % name) - dock_widget.setWidget(widget) - dock_widget.setAllowedAreas(allowed_areas) - dock_widget.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) - - self.addDockWidget(area, dock_widget) - return dock_widget - - - @showWaitCursorWhileWaiting - def keySelected(self): - key = self.getSelectedKey() - self._plot_customizer.switchPlotConfigHistory(key) - - for plot_widget in self._plot_widgets: - plot_widget.setDirty() - index = self._central_tab.indexOf(plot_widget) - self._central_tab.setTabEnabled(index, plot_widget.canPlotKey(key)) - - for plot_widget in self._plot_widgets: - if plot_widget.canPlotKey(key): - plot_widget.updatePlot() - - - def toggleCustomizeDialog(self): - self._plot_customizer.toggleCustomizationDialog() diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/style_chooser.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/style_chooser.py deleted file mode 100644 index ae8743cbfa..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/style_chooser.py +++ /dev/null @@ -1,161 +0,0 @@ -from PyQt4.QtGui import QWidget, QHBoxLayout, QComboBox, QDoubleSpinBox, QLabel, QHBoxLayout - -from ert_gui.plottery import PlotStyle - - -STYLE_OFF = ("Off", None) -STYLE_AREA = ("Area", "#") -STYLE_SOLID = ("Solid", "-") -STYLE_DASHED = ("Dashed", "--") -STYLE_DOTTED = ("Dotted", ":") -STYLE_DASH_DOTTED = ("Dash Dotted", "-.") - -STYLESET_DEFAULT = 'default' -STYLESET_AREA = 'area' -STYLESET_TOGGLE = 'toggle_only' - -STYLES = { - STYLESET_DEFAULT: [STYLE_OFF, STYLE_SOLID, STYLE_DASHED, STYLE_DOTTED, STYLE_DASH_DOTTED], - STYLESET_AREA: [STYLE_OFF, STYLE_AREA, STYLE_SOLID, STYLE_DASHED, STYLE_DOTTED, STYLE_DASH_DOTTED], - STYLESET_TOGGLE: [STYLE_OFF, STYLE_SOLID] -} - -MARKER_OFF = ("Off", None) -MARKER_X = ("X", "x") -MARKER_CIRCLE = ("Circle", "o") -MARKER_POINT = ("Point", ".") -MARKER_PIXEL = ("Pixel", ",") -MARKER_PLUS = ("Plus", "+") -MARKER_STAR = ("Star", "*") -MARKER_DIAMOND = ("Diamond", "D") -MARKER_PENTAGON = ("Pentagon", "p") -MARKER_SQUARE = ("Square", "s") -MARKER_HLINE = ("H Line", "_") -MARKER_VLINE = ("V Line", "|") -MARKER_OCTAGON = ("Octagon", "8") -MARKER_HEXAGON1 = ("Hexagon 1", "h") -MARKER_HEXAGON2 = ("Hexagon 2", "H") - -MARKERS = [MARKER_OFF, MARKER_X, MARKER_CIRCLE, MARKER_POINT, MARKER_STAR, MARKER_DIAMOND, MARKER_PLUS, MARKER_PENTAGON, MARKER_SQUARE, MARKER_OCTAGON, MARKER_HEXAGON1, MARKER_HEXAGON2] - - -class StyleChooser(QWidget): - - def __init__(self, line_style_set=STYLESET_DEFAULT): - QWidget.__init__(self) - self._style = PlotStyle("StyleChooser Internal Style") - - self._styles = STYLES['default'] if not line_style_set in STYLES else STYLES[line_style_set] - - self.setMinimumWidth(140) - self.setMaximumHeight(25) - - layout = QHBoxLayout() - layout.setMargin(0) - layout.setSpacing(2) - - self.line_chooser = QComboBox() - self.line_chooser.setToolTip("Select line style.") - for style in self._styles: - self.line_chooser.addItem(*style) - - self.marker_chooser = QComboBox() - self.marker_chooser.setToolTip("Select marker style.") - for marker in MARKERS: - self.marker_chooser.addItem(*marker) - - self.thickness_spinner = QDoubleSpinBox() - self.thickness_spinner.setToolTip("Line thickness") - self.thickness_spinner.setMinimum(0.1) - self.thickness_spinner.setDecimals(1) - self.thickness_spinner.setSingleStep(0.1) - - self.size_spinner = QDoubleSpinBox() - self.size_spinner.setToolTip("Marker Size") - self.size_spinner.setMinimum(0.1) - self.size_spinner.setDecimals(1) - self.size_spinner.setSingleStep(0.1) - - # the text content of the spinner varies, but shouldn't push the control out of boundaries - self.line_chooser.setMinimumWidth(110) - layout.addWidget(self.line_chooser) - layout.addWidget(self.thickness_spinner) - layout.addWidget(self.marker_chooser) - layout.addWidget(self.size_spinner) - - self.setLayout(layout) - - self.line_chooser.currentIndexChanged.connect(self._updateStyle) - self.marker_chooser.currentIndexChanged.connect(self._updateStyle) - self.thickness_spinner.valueChanged.connect(self._updateStyle) - self.size_spinner.valueChanged.connect(self._updateStyle) - - self._updateLineStyleAndMarker(self._style.line_style, self._style.marker, self._style.width, self._style.size) - self._layout = layout - - def getItemSizes(self): - line_style_combo_width = self._layout.itemAt(0).sizeHint().width() - thickness_spinner_width = self._layout.itemAt(1).sizeHint().width() - marker_combo_width = self._layout.itemAt(2).sizeHint().width() - size_spinner_width = self._layout.itemAt(3).sizeHint().width() - return line_style_combo_width, thickness_spinner_width, marker_combo_width, size_spinner_width - - def _findLineStyleIndex(self, line_style): - for index, style in enumerate(self._styles): - if style[1] == line_style: - return index - elif style[1] is None and line_style == "": - return index - return -1 - - def _findMarkerStyleIndex(self, marker): - for index, style in enumerate(MARKERS): - if style[1] == marker: - return index - elif style[1] is None and marker == "": - return index - return -1 - - def _updateLineStyleAndMarker(self, line_style, marker, thickness, size): - self.line_chooser.setCurrentIndex(self._findLineStyleIndex(line_style)) - self.marker_chooser.setCurrentIndex(self._findMarkerStyleIndex(marker)) - self.thickness_spinner.setValue(thickness) - self.size_spinner.setValue(size) - - def _updateStyle(self): - self.marker_chooser.setEnabled(self.line_chooser.currentText() != "Area") - - line_style = self.line_chooser.itemData(self.line_chooser.currentIndex()) - marker_style = self.marker_chooser.itemData(self.marker_chooser.currentIndex()) - thickness = float(self.thickness_spinner.value()) - size = float(self.size_spinner.value()) - - self._style.line_style = str(line_style.toString()) - self._style.marker = str(marker_style.toString()) - self._style.width = thickness - self._style.size = size - - def setStyle(self, style): - """ @type style: PlotStyle """ - self._style.copyStyleFrom(style) - self._updateLineStyleAndMarker(style.line_style, style.marker, style.width, style.size) - - def getStyle(self): - """ @rtype: PlotStyle """ - style = PlotStyle("Generated Style from StyleChooser") - style.copyStyleFrom(self._style) - return style - - def createLabelLayout(self, layout=None): - if layout is None: - layout = QHBoxLayout() - - titles = ["Line Style", "Width", "Marker Style", "Size"] - sizes = self.getItemSizes() - for title, size in zip(titles, sizes): - label = QLabel(title) - label.setFixedWidth(size) - layout.addWidget(label) - - return layout - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/CMakeLists.txt deleted file mode 100644 index 7f823aff44..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - clearable_line_edit.py - custom_date_edit.py - copy_style_to_dialog.py -) - -add_python_package("python.ert_gui.tools.plot.widgets" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/plot/widgets "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/__init__.py deleted file mode 100644 index e00b98554a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from ert_gui.tools.plot.widgets.copy_style_to_dialog import CopyStyleToDialog diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/clearable_line_edit.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/clearable_line_edit.py deleted file mode 100644 index 81d24eec9b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/clearable_line_edit.py +++ /dev/null @@ -1,97 +0,0 @@ -from PyQt4.QtCore import QString, QSize, Qt -from PyQt4.QtGui import QPushButton, QColor, QLineEdit, QStyle - -from ert_gui.ertwidgets import resourceIcon - - -class ClearableLineEdit(QLineEdit): - passive_color = QColor(194, 194, 194) - - def __init__(self, placeholder="yyyy-mm-dd"): - QLineEdit.__init__(self) - - self._placeholder_text = placeholder - self._active_color = self.palette().color(self.foregroundRole()) - self._placeholder_active = False - - self._clear_button = QPushButton(self) - self._clear_button.setIcon(resourceIcon("remove_favorite.png")) - self._clear_button.setFlat(True) - self._clear_button.setFocusPolicy(Qt.NoFocus) - self._clear_button.setFixedSize(17, 17) - self._clear_button.setCursor(Qt.ArrowCursor) - - self._clear_button.clicked.connect(self.clearButtonClicked) - self._clear_button.setVisible(False) - - self.textChanged.connect(self.toggleClearButtonVisibility) - - self.showPlaceholder() - - - def toggleClearButtonVisibility(self): - self._clear_button.setVisible(len(str(self.text())) > 0 and not self._placeholder_active) - - def sizeHint(self): - size = QLineEdit.sizeHint(self) - return QSize(size.width() + self._clear_button.width() + 3, size.height()) - - def minimumSizeHint(self): - size = QLineEdit.minimumSizeHint(self) - return QSize(size.width() + self._clear_button.width() + 3, size.height()) - - def resizeEvent(self, event): - right = self.rect().right() - frame_width = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) - self._clear_button.move(right - frame_width - self._clear_button.width(), (self.height() - self._clear_button.height()) / 2) - QLineEdit.resizeEvent(self, event) - - def clearButtonClicked(self): - self.setText("") - - def showPlaceholder(self): - if not self._placeholder_active: - self._placeholder_active = True - QLineEdit.setText(self, self._placeholder_text) - palette = self.palette() - palette.setColor(self.foregroundRole(), self.passive_color) - self.setPalette(palette) - - def hidePlaceHolder(self): - if self._placeholder_active: - self._placeholder_active = False - QLineEdit.setText(self, "") - palette = self.palette() - palette.setColor(self.foregroundRole(), self._active_color) - self.setPalette(palette) - - def focusInEvent(self, focus_event): - QLineEdit.focusInEvent(self, focus_event) - self.hidePlaceHolder() - - def focusOutEvent(self, focus_event): - QLineEdit.focusOutEvent(self, focus_event) - if str(QLineEdit.text(self)) == "": - self.showPlaceholder() - - def keyPressEvent(self, key_event): - if key_event.key() == Qt.Key_Escape: - self.clear() - self.clearFocus() - key_event.accept() - - QLineEdit.keyPressEvent(self, key_event) - - def setText(self, string): - self.hidePlaceHolder() - - QLineEdit.setText(self, string) - - if len(str(string)) == 0 and not self.hasFocus(): - self.showPlaceholder() - - def text(self): - if self._placeholder_active: - return QString("") - else: - return QLineEdit.text(self) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/copy_style_to_dialog.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/copy_style_to_dialog.py deleted file mode 100644 index 5a37c53a33..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/copy_style_to_dialog.py +++ /dev/null @@ -1,62 +0,0 @@ -from PyQt4.QtGui import QFormLayout, QWidget, QDialog, QPushButton, QHBoxLayout, QToolButton -from ert_gui.ertwidgets import CheckList, resourceIcon -from ert_gui.tools.plot import FilterPopup, FilterableKwListModel -from ert_gui import ERT - - -class CopyStyleToDialog(QDialog): - - def __init__(self, parent=None, current_key='', selectable_keys=[]): - QWidget.__init__(self, parent) - self.setMinimumWidth(450) - self.setMinimumHeight(200) - self._dynamic = False - self.setWindowTitle("Copy the style of {0} to other keys".format(current_key)) - self.activateWindow() - - layout = QFormLayout(self) - - self._ert = ERT.ert - """:type: ert.enkf.enkf_main.EnKFMain""" - - self.model = self._ert - - self._filter_popup = FilterPopup(self) - self._filter_popup.filterSettingsChanged.connect(self.filterSettingsChanged) - - filter_popup_button = QToolButton() - filter_popup_button.setIcon(resourceIcon("ide/cog_edit.png")) - filter_popup_button.clicked.connect(self._filter_popup.show) - - self._list_model = FilterableKwListModel(self._ert, selectable_keys) - self._list_model.unselectAll() - - self._cl = CheckList(self._list_model, custom_filter_button=filter_popup_button) - - layout.addWidget(self._cl) - - apply_button = QPushButton("Apply") - apply_button.clicked.connect(self.accept) - apply_button.setDefault(True) - - close_button = QPushButton("Close") - close_button.setToolTip("Hide this dialog") - close_button.clicked.connect(self.reject) - - button_layout = QHBoxLayout() - button_layout.addStretch() - button_layout.addWidget(apply_button) - button_layout.addWidget(close_button) - - layout.addRow(button_layout) - - - def getSelectedKeys(self): - return self._list_model.getSelectedItems() - - def filterSettingsChanged(self, item): - self._list_model.setShowSummaryKeys(item["summary"]) - self._list_model.setShowGenKWKeys(item["gen_kw"]) - self._list_model.setShowGenDataKeys(item["gen_data"]) - self._list_model.setShowCustomKwKeys(item["custom_kw"]) - self._cl.modelChanged() diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/custom_date_edit.py b/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/custom_date_edit.py deleted file mode 100644 index 882a97ee36..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plot/widgets/custom_date_edit.py +++ /dev/null @@ -1,53 +0,0 @@ -import datetime - -from PyQt4.QtCore import QDate -from PyQt4.QtGui import QWidget, QHBoxLayout, QCalendarWidget, QToolButton, QMenu, QWidgetAction - -from ert_gui.ertwidgets import resourceIcon -from ert_gui.tools.plot.widgets.clearable_line_edit import ClearableLineEdit - -class CustomDateEdit(QWidget): - def __init__(self): - QWidget.__init__(self) - self._line_edit = ClearableLineEdit() - - self._calendar_button = QToolButton() - self._calendar_button.setPopupMode(QToolButton.InstantPopup) - self._calendar_button.setFixedSize(26, 26) - self._calendar_button.setAutoRaise(True) - self._calendar_button.setIcon(resourceIcon("calendar.png")) - self._calendar_button.setStyleSheet("QToolButton::menu-indicator { image: none; }") - - tool_menu = QMenu(self._calendar_button) - self._calendar_widget = QCalendarWidget(tool_menu) - action = QWidgetAction(tool_menu) - action.setDefaultWidget(self._calendar_widget) - tool_menu.addAction(action) - self._calendar_button.setMenu(tool_menu) - - layout = QHBoxLayout() - layout.setMargin(0) - layout.addWidget(self._line_edit) - layout.addWidget(self._calendar_button) - self.setLayout(layout) - - self._calendar_widget.activated.connect(self.setDate) - - def setDate(self, date): - if isinstance(date, datetime.date): - date = QDate(date.year, date.month, date.day) - - if date is not None and date.isValid(): - self._line_edit.setText(str(date.toString("yyyy-MM-dd"))) - else: - self._line_edit.setText("") - - - def date(self): - date_string = self._line_edit.text() - if len(str(date_string).strip()) > 0: - date = QDate.fromString(date_string, "yyyy-MM-dd") - if date.isValid(): - return datetime.date(date.year(), date.month(), date.day()) - - return None diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/plugins/CMakeLists.txt deleted file mode 100644 index 26ba15fee6..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - plugin.py - plugin_handler.py - plugin_runner.py - plugins_tool.py - process_job_dialog.py -) - -add_python_package("python.ert_gui.tools.plugins" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/plugins "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/plugins/__init__.py deleted file mode 100644 index d3509c4f5d..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .process_job_dialog import ProcessJobDialog -from .plugin import Plugin -from .plugin_runner import PluginRunner -from .plugin_handler import PluginHandler -from .plugins_tool import PluginsTool diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin.py b/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin.py deleted file mode 100644 index 1a4ee460b3..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin.py +++ /dev/null @@ -1,54 +0,0 @@ -from ert.job_queue import ErtScript, ErtPlugin, WorkflowJob - -class Plugin(object): - def __init__(self, ert, workflow_job): - """ - @type ert: ert.enkf.EnKFMain - @type workflow_job: WorkflowJob - """ - self.__ert = ert - self.__workflow_job = workflow_job - self.__parent_window = None - - script = self.__loadPlugin() - self.__name = script.getName() - self.__description = script.getDescription() - - - def __loadPlugin(self): - """ @rtype: ErtPlugin """ - script_obj = ErtScript.loadScriptFromFile(self.__workflow_job.getInternalScriptPath()) - script = script_obj(self.__ert) - return script - - def getName(self): - """ @rtype: str """ - return self.__name - - def getDescription(self): - """ @rtype: str """ - return self.__description - - def getArguments(self): - """ - Returns a list of arguments. Either from GUI or from arbitrary code. - If the user for example cancels in the GUI a CancelPluginException is raised. - @rtype: list """ - script = self.__loadPlugin() - return script.getArguments(self.__parent_window) - - - def setParentWindow(self, parent_window): - self.__parent_window = parent_window - - def getParentWindow(self): - """ @rtype: QWidget """ - return self.__parent_window - - def ert(self): - """ @rtype: ert.enkf.enkf_main.EnKFMain """ - return self.__ert - - def getWorkflowJob(self): - """ @rtype: WorkflowJob """ - return self.__workflow_job diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin_handler.py b/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin_handler.py deleted file mode 100644 index 6622bfc79e..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin_handler.py +++ /dev/null @@ -1,37 +0,0 @@ -from ert.job_queue import WorkflowJob -from .plugin import Plugin - - -class PluginHandler(object): - - def __init__(self, ert, plugin_jobs, parent_window): - """ @type plugin_jobs: list of WorkflowJob """ - self.__ert = ert - self.__plugins = [] - - for job in plugin_jobs: - plugin = Plugin(self.__ert, job) - self.__plugins.append(plugin) - plugin.setParentWindow(parent_window) - - self.__plugins = sorted(self.__plugins, key=Plugin.getName) - - - def ert(self): - """ @rtype: ert.enkf.enkf_main.EnKFMain """ - return self.__ert - - def __iter__(self): - """ @rtype: Plugin """ - index = 0 - while index < len(self.__plugins): - yield self.__plugins[index] - index += 1 - - def __getitem__(self, index): - """ @rtype: Plugin """ - return self.__plugins[index] - - - def __len__(self): - return len(self.__plugins) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin_runner.py b/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin_runner.py deleted file mode 100644 index 44978a8999..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugin_runner.py +++ /dev/null @@ -1,91 +0,0 @@ -from functools import partial -from threading import Thread -import time -from ert.job_queue.ert_plugin import CancelPluginException -from ert_gui.tools.plugins import Plugin, ProcessJobDialog -from ert.job_queue import WorkflowJob - -class PluginRunner(object): - def __init__(self, plugin): - """ - @type plugin: Plugin - """ - super(PluginRunner, self).__init__() - - self.__plugin = plugin - - self.__plugin_finished_callback = lambda : None - - self.__result = None - - def run(self): - try: - plugin = self.__plugin - - arguments = plugin.getArguments() - dialog = ProcessJobDialog(plugin.getName(), plugin.getParentWindow()) - - dialog.cancelConfirmed.connect(self.cancel) - - run_function = partial(self.__runWorkflowJob, plugin, arguments) - - workflow_job_thread = Thread(name="ert_gui_workflow_job_thread") - workflow_job_thread.setDaemon(True) - workflow_job_thread.run = run_function - workflow_job_thread.start() - - - poll_function = partial(self.__pollRunner, plugin, dialog) - - poll_thread = Thread(name="ert_gui_workflow_job_poll_thread") - poll_thread.setDaemon(True) - poll_thread.run = poll_function - poll_thread.start() - - dialog.show() - except CancelPluginException: - print("Plugin cancelled before execution!") - - def __runWorkflowJob(self, plugin, arguments): - workflow_job = plugin.getWorkflowJob() - self.__result = workflow_job.run(plugin.ert(), arguments) - - - def __pollRunner(self, plugin, dialog): - self.wait() - - details = "" - if self.__result is not None: - details = str(self.__result) - - if plugin.getWorkflowJob().hasFailed(): - dialog.presentError.emit("Job Failed!", "The job '%s' has failed while running!" % plugin.getName(), details) - dialog.disposeDialog.emit() - elif plugin.getWorkflowJob().isCancelled(): - dialog.presentInformation.emit("Job Cancelled!", "The job '%s' was cancelled successfully!" % plugin.getName(), details) - dialog.disposeDialog.emit() - else: - dialog.presentInformation.emit("Job Completed!", "The job '%s' was completed successfully!" % plugin.getName(), details) - dialog.disposeDialog.emit() - - self.__plugin_finished_callback() - - - def isRunning(self): - """ @rtype: bool """ - return self.__plugin.getWorkflowJob().isRunning() - - def isCancelled(self): - """ @rtype: bool """ - return self.__plugin.getWorkflowJob().isCancelled() - - def cancel(self): - if self.isRunning(): - self.__plugin.getWorkflowJob().cancel() - - def wait(self): - while self.isRunning(): - time.sleep(1) - - def setPluginFinishedCallback(self, callback): - self.__plugin_finished_callback = callback \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugins_tool.py b/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugins_tool.py deleted file mode 100644 index 6f8ba2fa1d..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/plugins_tool.py +++ /dev/null @@ -1,34 +0,0 @@ -from PyQt4.QtGui import QMenu - -from ert_gui import ERT -from ert_gui.ertwidgets import resourceIcon -from ert_gui.tools import Tool -from ert_gui.tools.plugins import PluginHandler, PluginRunner - - -class PluginsTool(Tool): - def __init__(self, plugin_handler): - """ - @type plugin_handler: PluginHandler - """ - enabled = len(plugin_handler) > 0 - super(PluginsTool, self).__init__("Plugins", "tools/plugins", resourceIcon("ide/plugin"), enabled, popup_menu=True) - - self.__plugins = {} - - menu = QMenu() - for plugin in plugin_handler: - plugin_runner = PluginRunner(plugin) - plugin_runner.setPluginFinishedCallback(self.trigger) - - self.__plugins[plugin] = plugin_runner - plugin_action = menu.addAction(plugin.getName()) - plugin_action.setToolTip(plugin.getDescription()) - plugin_action.triggered.connect(plugin_runner.run) - - self.getAction().setMenu(menu) - - - def trigger(self): - ERT.emitErtChange() # plugin may have added new cases. - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/process_job_dialog.py b/ThirdParty/Ert/python/python/ert_gui/tools/plugins/process_job_dialog.py deleted file mode 100644 index 1a80bdc62a..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/plugins/process_job_dialog.py +++ /dev/null @@ -1,121 +0,0 @@ -from PyQt4.QtCore import Qt, pyqtSignal, QSize -from PyQt4.QtGui import QDialog, QVBoxLayout, QLayout, QPushButton, QHBoxLayout, QWidget, QLabel, QMessageBox, QSizePolicy, QSpacerItem - -from ert_gui.ertwidgets import resourceMovie - - -class ProcessJobDialog(QDialog): - - disposeDialog = pyqtSignal() - presentInformation = pyqtSignal(str, str, str) - presentError = pyqtSignal(str, str, str) - - closeButtonPressed = pyqtSignal() - cancelConfirmed = pyqtSignal() - - def __init__(self, title, parent=None): - QDialog.__init__(self, parent) - - self.__parent = parent - self.setWindowTitle(title) - self.setModal(True) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowCancelButtonHint) - - layout = QVBoxLayout() - layout.setSizeConstraint(QLayout.SetFixedSize) - - widget = QWidget() - widget_layout = QHBoxLayout() - - size = 64 - spin_movie = resourceMovie("ide/loading.gif") - spin_movie.setSpeed(60) - spin_movie.setScaledSize(QSize(size, size)) - spin_movie.start() - - processing_animation = QLabel() - processing_animation.setMaximumSize(QSize(size, size)) - processing_animation.setMinimumSize(QSize(size, size)) - processing_animation.setMovie(spin_movie) - widget_layout.addWidget(processing_animation) - - self.processing_label = QLabel("Processing job: '%s'" % title) - widget_layout.addWidget(self.processing_label, Qt.AlignBottom) - - widget.setLayout(widget_layout) - - layout.addWidget(widget) - - button_layout = QHBoxLayout() - self.close_button = QPushButton("Close") - self.close_button.clicked.connect(self.closeButtonPressed.emit) - button_layout.addStretch() - button_layout.addWidget(self.close_button) - - layout.addStretch() - layout.addLayout(button_layout) - - self.setLayout(layout) - - self.disposeDialog.connect(self.reject) - self.presentInformation.connect(self.__presentInformation) - self.presentError.connect(self.__presentError) - self.closeButtonPressed.connect(self.__confirmCancel) - - - def disableCloseButton(self): - self.close_button.setEnabled(False) - - def enableCloseButton(self): - self.close_button.setEnabled(True) - - def keyPressEvent(self, q_key_event): - if not self.close_button.isEnabled() and q_key_event.key() == Qt.Key_Escape: - pass - else: - QDialog.keyPressEvent(self, q_key_event) - - def closeEvent(self, close_event): - close_event.ignore() - self.closeButtonPressed.emit() - - def __createMsgBox(self, title, message, details): - msg_box = QMessageBox(self.parent()) - msg_box.setText(title) - msg_box.setInformativeText(message) - - if len(details) > 0: - msg_box.setDetailedText(details) - - horizontal_spacer = QSpacerItem(500, 0, QSizePolicy.MinimumExpanding, QSizePolicy.Expanding) - layout = msg_box.layout() - layout.addItem(horizontal_spacer, layout.rowCount(), 0, 1, layout.columnCount()) - - return msg_box - - - def __presentInformation(self, title, message, details): - msg_box = self.__createMsgBox(title, message, details) - msg_box.setIcon(QMessageBox.Information) - - msg_box.exec_() - - def __presentError(self, title, message, details): - msg_box = self.__createMsgBox(title, message, details) - msg_box.setIcon(QMessageBox.Critical) - - msg_box.exec_() - - - def __confirmCancel(self): - cancel_box = self.__createMsgBox("Confirm Cancel", "Are you sure you want to cancel the running job?", "") - cancel_box.setIcon(QMessageBox.Question) - cancel_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) - cancel_box.exec_() - - cancel = cancel_box.result() - - if cancel == QMessageBox.Yes: - self.cancelConfirmed.emit() diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/CMakeLists.txt deleted file mode 100644 index d1472f71cf..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - run_analysis_panel.py - run_analysis_tool.py -) - -add_python_package("python.ert_gui.tools.run_analysis" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/run_analysis "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/__init__.py deleted file mode 100644 index c4c65f4e2b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .run_analysis_panel import RunAnalysisPanel -from .run_analysis_tool import RunAnalysisTool diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/run_analysis_panel.py b/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/run_analysis_panel.py deleted file mode 100644 index d4adc7f990..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/run_analysis_panel.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# The file 'run_analysis_panel.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from PyQt4.QtGui import QWidget, QFormLayout, QLineEdit - -from ert_gui.ertwidgets.analysismoduleselector import AnalysisModuleSelector -from ert_gui.ertwidgets.caseselector import CaseSelector - - -class RunAnalysisPanel(QWidget): - - def __init__(self): - QWidget.__init__(self) - - self.setWindowTitle("Run Analysis") - self.activateWindow() - - self.analysis_module = AnalysisModuleSelector(load_all = True, help_link = "config/analysis/analysis_module") - self.target_case_text = QLineEdit() - self.source_case_selector = CaseSelector(update_ert = False) - - layout = QFormLayout() - layout.addRow("Analysis", self.analysis_module) - layout.addRow("Target case", self.target_case_text) - layout.addRow("Source case", self.source_case_selector) - self.setLayout(layout) - - def target_case(self): - return str(self.target_case_text.text()) - - def source_case(self): - return str(self.source_case_selector.currentText()) - - def module(self): - return self.analysis_module.getSelectedAnalysisModuleName() diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/run_analysis_tool.py b/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/run_analysis_tool.py deleted file mode 100644 index 52c89c0f5b..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/run_analysis/run_analysis_tool.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# The file 'run_analysis_tool.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from PyQt4.QtGui import QMessageBox - -from ert_gui import ERT -from ert.enkf import ESUpdate -from ert_gui.ertwidgets import resourceIcon -from ert_gui.ertwidgets.closabledialog import ClosableDialog -from ert_gui.tools import Tool -from ert_gui.tools.run_analysis import RunAnalysisPanel - - -class RunAnalysisTool(Tool): - def __init__(self): - super(RunAnalysisTool, self).__init__("Run Analysis", "tools/run_analysis", resourceIcon("ide/table_import")) - self._run_widget = None - self._dialog = None - self._selected_case_name = None - self.setVisible(False) - - - def trigger(self): - if self._run_widget is None: - self._run_widget = RunAnalysisPanel() - self._dialog = ClosableDialog("Run Analysis", self._run_widget, self.parent()) - self._dialog.addButton("Run", self.run) - self._dialog.exec_() - - def run(self): - target = self._run_widget.target_case() - source = self._run_widget.source_case() - - ert = ERT.ert - fs_manager = ert.getEnkfFsManager() - es_update = ESUpdate(ert) - - target_fs = fs_manager.getFileSystem(target) - source_fs = fs_manager.getFileSystem(source) - success = es_update.smootherUpdate( source_fs , target_fs ) - - if not success: - msg = QMessageBox() - msg.setIcon(QMessageBox.Warning) - msg.setWindowTitle("Run Analysis") - msg.setText("Unable to run analysis for case '%s'." % source) - msg.setStandardButtons(QMessageBox.Ok) - msg.exec_() - return - - ERT.ertChanged.emit() - self._dialog.accept() - - def toggleAdvancedMode(self, advanced_mode): - self.setVisible(advanced_mode) diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/tool.py b/ThirdParty/Ert/python/python/ert_gui/tools/tool.py deleted file mode 100644 index 67034a0efb..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/tool.py +++ /dev/null @@ -1,57 +0,0 @@ -from PyQt4.QtGui import QAction -from ert_gui.tools import HelpCenter - - -class Tool(object): - def __init__(self, name, help_link="", icon=None, enabled=True, checkable=False, popup_menu=False): - super(Tool, self).__init__() - self.__icon = icon - self.__name = name - self.__parent = None - self.__enabled = enabled - self.__checkable = checkable - self.__help_link = help_link - self.__is_popup_menu = popup_menu - - self.__action = QAction(self.getIcon(), self.getName(), None) - self.__action.setIconText(self.getName()) - self.__action.setEnabled(self.isEnabled()) - self.__action.setCheckable(checkable) - self.__action.triggered.connect(self.trigger) - - HelpCenter.addHelpToAction(self.__action, self.getHelpLink()) - - def getIcon(self): - return self.__icon - - def getName(self): - return self.__name - - def trigger(self): - raise NotImplementedError() - - def setParent(self, parent): - self.__parent = parent - self.__action.setParent(parent) - - def parent(self): - return self.__parent - - def isEnabled(self): - return self.__enabled - - def getHelpLink(self): - return self.__help_link - - - def getAction(self): - return self.__action - - def setVisible(self, visible): - self.__action.setVisible(visible) - - def setEnabled(self, enabled): - self.__action.setEnabled(enabled) - - def isPopupMenu(self): - return self.__is_popup_menu diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/workflows/CMakeLists.txt b/ThirdParty/Ert/python/python/ert_gui/tools/workflows/CMakeLists.txt deleted file mode 100644 index a042788db3..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/workflows/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - run_workflow_widget.py - workflow_dialog.py - workflows_tool.py -) - -add_python_package("python.ert_gui.tools.workflows" ${PYTHON_INSTALL_PREFIX}/ert_gui/tools/workflows "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/workflows/__init__.py b/ThirdParty/Ert/python/python/ert_gui/tools/workflows/__init__.py deleted file mode 100644 index 5dd024d585..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/workflows/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .run_workflow_widget import RunWorkflowWidget -from .workflows_tool import WorkflowsTool \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/workflows/run_workflow_widget.py b/ThirdParty/Ert/python/python/ert_gui/tools/workflows/run_workflow_widget.py deleted file mode 100644 index 05f81ddccf..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/workflows/run_workflow_widget.py +++ /dev/null @@ -1,146 +0,0 @@ -import time -from threading import Thread - -from PyQt4.QtCore import QSize, Qt, pyqtSignal -from PyQt4.QtGui import QWidget, QHBoxLayout, QLabel, QToolButton, QMessageBox, QComboBox - -from ert_gui.ertwidgets import addHelpToWidget, resourceMovie, resourceIcon -from ert_gui.ertwidgets.models.ertmodel import getWorkflowNames, createWorkflowRunner -from ert_gui.tools.workflows.workflow_dialog import WorkflowDialog - - -class RunWorkflowWidget(QWidget): - - workflowSucceeded = pyqtSignal() - workflowFailed = pyqtSignal() - workflowKilled = pyqtSignal() - - def __init__(self): - QWidget.__init__(self) - - layout = QHBoxLayout() - layout.addSpacing(10) - - - self._workflow_combo = QComboBox() - addHelpToWidget(self._workflow_combo, "run/workflow") - - self._workflow_combo.addItems(getWorkflowNames()) - - layout.addWidget(QLabel("Select Workflow:"), 0, Qt.AlignVCenter) - layout.addWidget(self._workflow_combo, 0, Qt.AlignVCenter) - - # simulation_mode_layout.addStretch() - layout.addSpacing(20) - - self.run_button = QToolButton() - self.run_button.setIconSize(QSize(32, 32)) - self.run_button.setText("Start Workflow") - self.run_button.setIcon(resourceIcon("ide/gear_in_play")) - self.run_button.clicked.connect(self.startWorkflow) - self.run_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) - - layout.addWidget(self.run_button) - layout.addStretch(1) - - self.setLayout(layout) - - self._running_workflow_dialog = None - - self.workflowSucceeded.connect(self.workflowFinished) - self.workflowFailed.connect(self.workflowFinishedWithFail) - self.workflowKilled.connect(self.workflowStoppedByUser) - - self._workflow_runner = None - """:type: WorkflowRunner""" - - - def createSpinWidget(self): - widget = QWidget() - layout = QHBoxLayout() - - size = 64 - spin_movie = resourceMovie("ide/loading.gif") - spin_movie.setSpeed(60) - spin_movie.setScaledSize(QSize(size, size)) - spin_movie.start() - - processing_animation = QLabel() - processing_animation.setMaximumSize(QSize(size, size)) - processing_animation.setMinimumSize(QSize(size, size)) - processing_animation.setMovie(spin_movie) - layout.addWidget(processing_animation) - - processing_label = QLabel("Processing workflow '%s'" % self.getCurrentWorkflowName()) - layout.addWidget(processing_label, Qt.AlignBottom) - - widget.setLayout(layout) - - return widget - - - def cancelWorkflow(self): - if self._workflow_runner.isRunning(): - cancel = QMessageBox.question(self, "Confirm Cancel", "Are you sure you want to cancel the running workflow?", QMessageBox.Yes | QMessageBox.No) - - if cancel == QMessageBox.Yes: - self._workflow_runner.cancel() - self._running_workflow_dialog.disableCloseButton() - - def getCurrentWorkflowName(self): - index = self._workflow_combo.currentIndex() - return getWorkflowNames()[index] - - - def startWorkflow(self): - self._running_workflow_dialog = WorkflowDialog("Running Workflow", self.createSpinWidget(), self) - self._running_workflow_dialog.closeButtonPressed.connect(self.cancelWorkflow) - - workflow_thread = Thread(name="ert_gui_workflow_thread") - workflow_thread.setDaemon(True) - workflow_thread.run = self.runWorkflow - - self._workflow_runner = createWorkflowRunner(self.getCurrentWorkflowName()) - self._workflow_runner.run() - - workflow_thread.start() - - self._running_workflow_dialog.show() - - def runWorkflow(self): - while self._workflow_runner.isRunning(): - time.sleep(2) - - cancelled = self._workflow_runner.isCancelled() - - if cancelled: - self.workflowKilled.emit() - else: - success = self._workflow_runner.workflowResult() - - if not success: - self.workflowFailed.emit() - else: - self.workflowSucceeded.emit() - - def workflowFinished(self): - workflow_name = self.getCurrentWorkflowName() - QMessageBox.information(self, "Workflow completed!", "The workflow '%s' completed successfully!" % workflow_name) - self._running_workflow_dialog.accept() - self._running_workflow_dialog = None - - def workflowFinishedWithFail(self): - workflow_name = self.getCurrentWorkflowName() - - error = self._workflow_runner.workflowError() - - QMessageBox.critical(self, "Workflow failed!", "The workflow '%s' failed!\n\n%s" % (workflow_name, error)) - self._running_workflow_dialog.reject() - self._running_workflow_dialog = None - - def workflowStoppedByUser(self): - workflow_name = self.getCurrentWorkflowName() - QMessageBox.information(self, "Workflow killed!", "The workflow '%s' was killed successfully!" % workflow_name) - self._running_workflow_dialog.reject() - self._running_workflow_dialog = None - \ No newline at end of file diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/workflows/workflow_dialog.py b/ThirdParty/Ert/python/python/ert_gui/tools/workflows/workflow_dialog.py deleted file mode 100644 index 320eb8a9be..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/workflows/workflow_dialog.py +++ /dev/null @@ -1,46 +0,0 @@ -from PyQt4.QtCore import Qt, pyqtSignal -from PyQt4.QtGui import QDialog, QVBoxLayout, QLayout, QPushButton, QHBoxLayout - - -class WorkflowDialog(QDialog): - - closeButtonPressed = pyqtSignal() - - def __init__(self, title, widget, parent=None): - QDialog.__init__(self, parent) - - self.setWindowTitle(title) - self.setModal(True) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowCancelButtonHint) - - - layout = QVBoxLayout() - layout.setSizeConstraint(QLayout.SetFixedSize) # not resizable!!! - layout.addWidget(widget) - - button_layout = QHBoxLayout() - self.close_button = QPushButton("Close") - self.close_button.clicked.connect(self.closeButtonPressed.emit) - button_layout.addStretch() - button_layout.addWidget(self.close_button) - - layout.addStretch() - layout.addLayout(button_layout) - - self.setLayout(layout) - - - def disableCloseButton(self): - self.close_button.setEnabled(False) - - def enableCloseButton(self): - self.close_button.setEnabled(True) - - def keyPressEvent(self, q_key_event): - if not self.close_button.isEnabled() and q_key_event.key() == Qt.Key_Escape: - pass - else: - QDialog.keyPressEvent(self, q_key_event) - diff --git a/ThirdParty/Ert/python/python/ert_gui/tools/workflows/workflows_tool.py b/ThirdParty/Ert/python/python/ert_gui/tools/workflows/workflows_tool.py deleted file mode 100644 index 223d52584d..0000000000 --- a/ThirdParty/Ert/python/python/ert_gui/tools/workflows/workflows_tool.py +++ /dev/null @@ -1,20 +0,0 @@ -from ert_gui import ERT -from ert_gui.ertwidgets import resourceIcon -from ert_gui.ertwidgets.closabledialog import ClosableDialog -from ert_gui.ertwidgets.models.ertmodel import getWorkflowNames -from ert_gui.tools import Tool -from ert_gui.tools.workflows import RunWorkflowWidget - - -class WorkflowsTool(Tool): - def __init__(self): - enabled = len(getWorkflowNames()) > 0 - super(WorkflowsTool, self).__init__("Run Workflow", "tools/workflows", resourceIcon("ide/to_do_list_checked_1"), enabled) - - - def trigger(self): - run_workflow_widget = RunWorkflowWidget() - dialog = ClosableDialog("Run workflow", run_workflow_widget, self.parent()) - dialog.exec_() - ERT.emitErtChange() # workflow may have added new cases. - diff --git a/ThirdParty/Ert/python/python/test_env.py.in b/ThirdParty/Ert/python/python/test_env.py.in new file mode 100644 index 0000000000..9fd11ea156 --- /dev/null +++ b/ThirdParty/Ert/python/python/test_env.py.in @@ -0,0 +1,6 @@ +import os + +TESTDATA_ROOT = os.getenv("ERT_TEST_ROOT_PATH") or "${PROJECT_SOURCE_DIR}/test-data" +SOURCE_ROOT = "${PROJECT_SOURCE_DIR}" +BUILD_ROOT = "${PROJECT_BINARY_DIR}" + diff --git a/ThirdParty/Ert/python/tests/CMakeLists.txt b/ThirdParty/Ert/python/tests/CMakeLists.txt index c2e0f176a7..5ebbfa3c82 100644 --- a/ThirdParty/Ert/python/tests/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/CMakeLists.txt @@ -3,6 +3,7 @@ set(TEST_SOURCES ctest_import.py ctest_run.py import_tester.py + test_pylint.py ) set(TEST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) @@ -31,25 +32,9 @@ function (addPythonTest TEST_NAME TEST_CLASS) endfunction(addPythonTest) -add_subdirectory(core) +add_subdirectory(geometry) +add_subdirectory(util) +add_subdirectory(ecl) +add_subdirectory(well) add_subdirectory(cwrap) -add_subdirectory(share) - -if(BUILD_ERT) - add_subdirectory(ert) - - add_test( NAME python.tests.ert.import - WORKING_DIRECTORY ${INSTALL_DIRECTORY} - COMMAND tests/ctest_import.py ${INSTALL_DIRECTORY} "ert") - - if (ERT_BUILD_GUI) - add_subdirectory(gui) - - add_test( NAME python.tests.ert_gui.import - WORKING_DIRECTORY ${INSTALL_DIRECTORY} - COMMAND tests/ctest_import.py ${INSTALL_DIRECTORY} "ert_gui") - endif() - - -endif() - +addPythonTest(lint test_pylint.LintErt) diff --git a/ThirdParty/Ert/python/tests/core/CMakeLists.txt b/ThirdParty/Ert/python/tests/core/CMakeLists.txt deleted file mode 100644 index 79d2b16ce6..0000000000 --- a/ThirdParty/Ert/python/tests/core/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set(TEST_SOURCES - __init__.py -) - -add_python_package("python.tests.core" ${PYTHON_INSTALL_PREFIX}/tests/core "${TEST_SOURCES}" False) - -add_subdirectory(geometry) -add_subdirectory(util) -add_subdirectory(ecl) -add_subdirectory(well) diff --git a/ThirdParty/Ert/python/tests/core/ecl/__init__.py b/ThirdParty/Ert/python/tests/core/ecl/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_deprecation.py b/ThirdParty/Ert/python/tests/core/ecl/test_deprecation.py deleted file mode 100644 index 712eab67be..0000000000 --- a/ThirdParty/Ert/python/tests/core/ecl/test_deprecation.py +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'test_deprecation.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import warnings -import time -import datetime - -from ert.test import ExtendedTestCase, TestAreaContext -from ert.ecl import EclFile,EclGrid,EclKW,EclTypeEnum,EclGrid,EclRegion,FortIO, openFortIO,EclRFT -from ert.ecl.ecl_case import EclCase -from ert.test.ecl_mock import createEclSum -from ert.util import BoolVector - -# The class Deprecation_1_9_Test contains methods which will be marked -# as deprecated in the 1.9.x versions. - -warnings.simplefilter("error" , DeprecationWarning) - - -class Deprecation_2_1_Test(ExtendedTestCase): - def test_ecl_kw_classprop(self): - with self.assertRaises(DeprecationWarning): - int_kw = EclKW.int_kw - - def test_ecl_kw_numpy_property(self): - kw = EclKW("TEST" , 10 , EclTypeEnum.ECL_INT_TYPE) - with self.assertRaises(DeprecationWarning): - n = kw.numpy_array - - def test_smspec_node_properties(self): - case = createEclSum("CSV" , [("FOPT", None , 0) , ("FOPR" , None , 0)]) - node = case.smspec_node( "FOPT" ) - - with self.assertRaises(DeprecationWarning): - node.is_total - - with self.assertRaises(DeprecationWarning): - node.is_rate - - with self.assertRaises(DeprecationWarning): - node.is_historical - - - -class Deprecation_2_0_Test(ExtendedTestCase): - def test_EclGrid_dims_property(self): - with self.assertRaises(DeprecationWarning): - grid = EclGrid.create_rectangular( (10,20,30) , (1,1,1) ) - - def test_EclFile_name_property(self): - with TestAreaContext("name") as t: - kw = EclKW("TEST", 3, EclTypeEnum.ECL_INT_TYPE) - with openFortIO("TEST" , mode = FortIO.WRITE_MODE) as f: - kw.fwrite( f ) - - t.sync() - - f = EclFile( "TEST" ) - with self.assertRaises(DeprecationWarning): - name = f.name - - def test_EclGrid_get_corner_xyz(self): - grid = EclGrid.createRectangular( (10,20,30) , (1,1,1) ) - with self.assertRaises(DeprecationWarning): - grid.get_corner_xyz(0 , global_index = 10) - - - def test_ecl_ecl_ecl(self): - with self.assertRaises(DeprecationWarning): - import ert.ecl.ecl as ecl - - - def test_ecl_kw_fortio_size_property(self): - kw = EclKW("KW" , 1000 , EclTypeEnum.ECL_INT_TYPE) - with self.assertRaises(DeprecationWarning): - kw.fortio_size - - - def test_ecl_kw_size_property(self): - kw = EclKW("KW" , 1000 , EclTypeEnum.ECL_INT_TYPE) - with self.assertRaises(DeprecationWarning): - kw.size - - - def test_ecl_kw_set_name(self): - kw = EclKW("KW" , 1000 , EclTypeEnum.ECL_INT_TYPE) - with self.assertRaises(DeprecationWarning): - kw.set_name("HEI") - - def test_ecl_kw_get_name(self): - kw = EclKW("KW" , 1000 , EclTypeEnum.ECL_INT_TYPE) - with self.assertRaises(DeprecationWarning): - kw.get_name( ) - - - def test_ecl_kw_create(self): - with self.assertRaises(DeprecationWarning): - kw = EclKW.create("KW" , 1000 , EclTypeEnum.ECL_INT_TYPE) - - - def test_ecl_kw_iget(self): - kw = EclKW("PORO" , 1000 , EclTypeEnum.ECL_FLOAT_TYPE) - with self.assertRaises(DeprecationWarning): - value = kw.iget( 100 ) - - - def test_ecl_kw_numeric_property(self): - kw = EclKW("PORO" , 1000 , EclTypeEnum.ECL_FLOAT_TYPE) - with self.assertRaises(DeprecationWarning): - kw.numeric - - - def test_ecl_kw_grdecl_load(self): - with TestAreaContext("ecl_kw/deprecate/grdecl_load"): - kw = EclKW("PORO" , 1000 , EclTypeEnum.ECL_FLOAT_TYPE) - with open("PORO.grdecl" , "w") as poro_file: - kw.write_grdecl( poro_file ) - - with open("PORO.grdecl") as poro_file: - with self.assertRaises(DeprecationWarning): - kw = EclKW.grdecl_load( poro_file , "PORO") - - - def test_ecl_grid_dual_property(self): - grid = EclGrid.createRectangular((10,20,30) , (1,1,1) ) - with self.assertRaises(DeprecationWarning): - grid.dual_grid - - - def test_ecl_grid_name(self): - grid = EclGrid.createRectangular((10,20,30) , (1,1,1) ) - with self.assertRaises(DeprecationWarning): - grid.name - - - def test_ecl_grid_dims_property(self): - grid = EclGrid.createRectangular((10,20,30) , (1,1,1) ) - with self.assertRaises(DeprecationWarning): - grid.nx - - with self.assertRaises(DeprecationWarning): - grid.ny - - with self.assertRaises(DeprecationWarning): - grid.nz - - with self.assertRaises(DeprecationWarning): - grid.size - - with self.assertRaises(DeprecationWarning): - grid.nactive - - def test_ecl_grid_num_lgr(self): - grid = EclGrid.createRectangular((10,20,30) , (1,1,1) ) - with self.assertRaises(DeprecationWarning): - grid.num_lgr - - - - def test_ecl_region_name(self): - grid = EclGrid.createRectangular((10,20,30) , (1,1,1) ) - region = EclRegion( grid , False ) - - with self.assertRaises(DeprecationWarning): - region.name = "NAME" - - with self.assertRaises(DeprecationWarning): - region.get_name( ) - - - def test_ecl_case( self ): - with self.assertRaises(DeprecationWarning): - case = EclCase( "CASE" ) - - - def test_rft(self): - rft = EclRFT("WELL" , "RFT" , datetime.date.today() , 100 ) - - # Property: type - with self.assertRaises(DeprecationWarning): - t = rft.type - - # Property: date - with self.assertRaises(DeprecationWarning): - d = rft.date - - # Property: well - with self.assertRaises(DeprecationWarning): - d = rft.date - - # Property: size - with self.assertRaises(DeprecationWarning): - d = rft.size - - def test_rft_file(self): - # These deprecations are not tested - but just recorded here. - # Property: num_wells - # Property: headers - pass - - - - -class Deprecation_1_9_Test(ExtendedTestCase): - - def test_EclGrid_dims_property(self): - grid = EclGrid.createRectangular( (10,20,30) , (1,1,1) ) - with self.assertRaises(DeprecationWarning): - d = grid.dims - - - def test_EclKW_min_max(self): - kw = EclKW("TEST", 3, EclTypeEnum.ECL_INT_TYPE) - with self.assertRaises(DeprecationWarning): - kw.min - - with self.assertRaises(DeprecationWarning): - kw.max - - with self.assertRaises(DeprecationWarning): - kw.min_max - - def test_EclRegion_properties(self): - grid = EclGrid.createRectangular( (10,10,10) , (1,1,1)) - region = EclRegion( grid , False ) - - with self.assertRaises(DeprecationWarning): - region.active_size - - with self.assertRaises(DeprecationWarning): - region.global_size - - with self.assertRaises(DeprecationWarning): - region.global_list - - with self.assertRaises(DeprecationWarning): - region.active_list - - - def test_BoolVector_active_mask(self): - with self.assertRaises(DeprecationWarning): - active_vector = BoolVector.active_mask("1,1,1,1,1,1") - - - diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_grid.py b/ThirdParty/Ert/python/tests/core/ecl/test_grid.py deleted file mode 100644 index d41c1bbaa1..0000000000 --- a/ThirdParty/Ert/python/tests/core/ecl/test_grid.py +++ /dev/null @@ -1,245 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'test_grid.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import os.path -from unittest import skipIf -import time - -from ert.util import IntVector -from ert.ecl import EclGrid,EclKW,EclTypeEnum, EclUnitTypeEnum, EclFile -from ert.ecl.faults import Layer , FaultCollection -from ert.test import ExtendedTestCase , TestAreaContext - - -# This test class should only have test cases which do not require -# external test data. Tests involving Statoil test data are in the -# test_grid_statoil module. - -class GridTest(ExtendedTestCase): - - def test_oom_grid(self): - nx = 2000 - ny = 2000 - nz = 2000 - - with self.assertRaises(MemoryError): - grid = EclGrid.createRectangular( (nx,ny,nz), (1,1,1)) - - - - def test_posXYEdge(self): - nx = 10 - ny = 11 - grid = EclGrid.createRectangular( (nx,ny,1) , (1,1,1) ) - self.assertEqual( grid.findCellCornerXY(0,0,0) , 0 ) - self.assertEqual( grid.findCellCornerXY(nx,0,0) , nx) - self.assertEqual( grid.findCellCornerXY(0 , ny , 0) , (nx + 1 ) * ny ) - self.assertEqual( grid.findCellCornerXY(nx,ny,0) , (nx + 1 ) * (ny + 1) - 1) - - self.assertEqual( grid.findCellCornerXY(0.25,0,0) , 0 ) - self.assertEqual( grid.findCellCornerXY(0,0.25,0) , 0 ) - - self.assertEqual( grid.findCellCornerXY(nx - 0.25,0,0) , nx ) - self.assertEqual( grid.findCellCornerXY(nx , 0.25,0) , nx ) - - self.assertEqual( grid.findCellCornerXY(0 , ny - 0.25, 0) , (nx + 1 ) * ny ) - self.assertEqual( grid.findCellCornerXY(0.25 , ny , 0) , (nx + 1 ) * ny ) - - self.assertEqual( grid.findCellCornerXY(nx -0.25 ,ny,0) , (nx + 1 ) * (ny + 1) - 1) - self.assertEqual( grid.findCellCornerXY(nx , ny - 0.25,0) , (nx + 1 ) * (ny + 1) - 1) - - - def test_dims(self): - grid = EclGrid.createRectangular( (10,20,30) , (1,1,1) ) - self.assertEqual( grid.getNX() , 10 ) - self.assertEqual( grid.getNY() , 20 ) - self.assertEqual( grid.getNZ() , 30 ) - self.assertEqual( grid.getGlobalSize() , 30*10*20 ) - - self.assertEqual( grid.getDims() , (10,20,30,6000) ) - - - - def test_create(self): - with self.assertRaises(ValueError): - grid = EclGrid.createRectangular( (10,20,30) , (1,1,1) , actnum = [0,1,1,2]) - - with self.assertRaises(ValueError): - grid = EclGrid.createRectangular( (10,20,30) , (1,1,1) , actnum = IntVector(initial_size = 10)) - - actnum = IntVector(default_value = 1 , initial_size = 6000) - actnum[0] = 0 - actnum[1] = 0 - grid = EclGrid.createRectangular( (10,20,30) , (1,1,1) , actnum = actnum) - self.assertEqual( grid.getNumActive( ) , 30*20*10 - 2) - - - - - def test_node_pos(self): - grid = EclGrid.createRectangular( (10,20,30) , (1,1,1) ) - with self.assertRaises(IndexError): - grid.getNodePos(-1,0,0) - - with self.assertRaises(IndexError): - grid.getNodePos(11,0,0) - - p0 = grid.getNodePos(0,0,0) - self.assertEqual( p0 , (0,0,0)) - - p7 = grid.getNodePos(10,20,30) - self.assertEqual( p7 , (10,20,30)) - - - def test_truncated_file(self): - grid = EclGrid.createRectangular( (10,20,30) , (1,1,1) ) - with TestAreaContext("python/ecl_grid/truncated"): - grid.save_EGRID( "TEST.EGRID") - - size = os.path.getsize( "TEST.EGRID") - with open("TEST.EGRID" , "r+") as f: - f.truncate( size / 2 ) - - with self.assertRaises(IOError): - EclGrid("TEST.EGRID") - - def test_posXY1(self): - nx = 4 - ny = 1 - nz = 1 - grid = EclGrid.createRectangular( (nx,ny,nz) , (1,1,1) ) - (i,j) = grid.findCellXY( 0.5 , 0.5, 0 ) - self.assertEqual(i , 0) - self.assertEqual(j , 0) - - (i,j) = grid.findCellXY( 3.5 , 0.5, 0 ) - self.assertEqual(i , 3) - self.assertEqual(j , 0) - - - def test_init_ACTNUM(self): - nx = 10 - ny = 23 - nz = 7 - grid = EclGrid.createRectangular( (nx,ny,nz) , (1,1,1) ) - actnum = grid.exportACTNUM() - - self.assertEqual( len(actnum) , nx*ny*nz ) - self.assertEqual( actnum[0] , 1 ) - self.assertEqual( actnum[nx*ny*nz - 1] , 1 ) - - actnum_kw = grid.exportACTNUMKw( ) - self.assertEqual(len(actnum_kw) , len(actnum)) - for a1,a2 in zip(actnum, actnum_kw): - self.assertEqual(a1, a2) - - - def test_posXY(self): - nx = 10 - ny = 23 - nz = 7 - grid = EclGrid.createRectangular( (nx,ny,nz) , (1,1,1) ) - with self.assertRaises(IndexError): - grid.findCellXY( 1 , 1, -1 ) - - with self.assertRaises(IndexError): - grid.findCellXY( 1 , 1, nz + 1 ) - - with self.assertRaises(ValueError): - grid.findCellXY(15 , 78 , 2) - - - i,j = grid.findCellXY( 1.5 , 1.5 , 2 ) - self.assertEqual(i , 1) - self.assertEqual(j , 1) - - - for i in range(nx): - for j in range(ny): - p = grid.findCellXY(i + 0.5 , j+ 0.5 , 0) - self.assertEqual( p[0] , i ) - self.assertEqual( p[1] , j ) - - c = grid.findCellCornerXY( 0.10 , 0.10 , 0 ) - self.assertEqual(c , 0) - - c = grid.findCellCornerXY( 0.90 , 0.90 , 0 ) - self.assertEqual( c , (nx + 1) + 1 ) - - c = grid.findCellCornerXY( 0.10 , 0.90 , 0 ) - self.assertEqual( c , (nx + 1) ) - - c = grid.findCellCornerXY( 0.90 , 0.90 , 0 ) - self.assertEqual( c , (nx + 1) + 1 ) - - c = grid.findCellCornerXY( 0.90 , 0.10 , 0 ) - self.assertEqual( c , 1 ) - - def test_compressed_copy(self): - nx = 10 - ny = 10 - nz = 10 - grid = EclGrid.createRectangular( (nx,ny,nz) , (1,1,1) ) - kw1 = EclKW.create("KW" , 1001 , EclTypeEnum.ECL_INT_TYPE ) - with self.assertRaises(ValueError): - cp = grid.compressedKWCopy( kw1 ) - - - def test_dxdydz(self): - nx = 10 - ny = 10 - nz = 10 - grid = EclGrid.createRectangular( (nx,ny,nz) , (2,3,4) ) - - (dx,dy,dz) = grid.getCellDims( active_index = 0 ) - self.assertEqual( dx , 2 ) - self.assertEqual( dy , 3 ) - self.assertEqual( dz , 4 ) - - def test_numpy3D(self): - nx = 10 - ny = 7 - nz = 5 - grid = EclGrid.createRectangular((nx,ny,nz) , (1,1,1)) - kw = EclKW( "SWAT" , nx*ny*nz , EclTypeEnum.ECL_FLOAT_TYPE ) - numpy_3d = grid.create3D( kw ) - - - def test_output_units(self): - n = 10 - a = 1 - grid = EclGrid.createRectangular( (n,n,n), (a,a,a)) - - with TestAreaContext("python/ecl_grid/units"): - grid.save_EGRID( "CASE.EGRID" , output_unit = EclUnitTypeEnum.ECL_FIELD_UNITS ) - f = EclFile("CASE.EGRID") - g = f["GRIDUNIT"][0] - self.assertEqual( g[0].strip( ) , "FEET" ) - g2 = EclGrid("CASE.EGRID") - self.assertFloatEqual( g2.cell_volume( global_index = 0 ) , 3.28084*3.28084*3.28084) - - - grid.save_EGRID( "CASE.EGRID" ) - f = EclFile("CASE.EGRID") - g = f["GRIDUNIT"][0] - self.assertEqual( g[0].strip( ) , "METRES" ) - - grid.save_EGRID( "CASE.EGRID" , output_unit = EclUnitTypeEnum.ECL_LAB_UNITS) - f = EclFile("CASE.EGRID") - g = f["GRIDUNIT"][0] - self.assertEqual( g[0].strip() , "CM" ) - g2 = EclGrid("CASE.EGRID") - self.assertFloatEqual( g2.cell_volume( global_index = 0 ) , 100*100*100 ) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_legacy_ecl.py b/ThirdParty/Ert/python/tests/core/ecl/test_legacy_ecl.py deleted file mode 100644 index 1c9ffd6b8f..0000000000 --- a/ThirdParty/Ert/python/tests/core/ecl/test_legacy_ecl.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2013 Statoil ASA, Norway. -# -# This file is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -try: - from unittest2 import TestCase -except ImportError: - from unittest import TestCase - -from ert.ecl import EclTypeEnum, EclFileFlagEnum, EclPhaseEnum - -import ert.ecl.ecl as ecl -import ert.ecl as new_ecl - -class LegacyEclTest(TestCase): - - def test_classes(self): - self.assertEqual(ecl.EclSum, new_ecl.EclSum) - - self.assertEqual(ecl.EclRFTFile, new_ecl.EclRFTFile) - self.assertEqual(ecl.EclRFTCell, new_ecl.EclRFTCell) - self.assertEqual(ecl.EclPLTCell, new_ecl.EclPLTCell) - - self.assertEqual(ecl.EclKW, new_ecl.EclKW) - self.assertEqual(ecl.EclFile, new_ecl.EclFile) - - self.assertEqual(ecl.FortIO, new_ecl.FortIO) - - self.assertEqual(ecl.EclGrid, new_ecl.EclGrid) - - self.assertEqual(ecl.EclRegion, new_ecl.EclRegion) diff --git a/ThirdParty/Ert/python/tests/core/geometry/CMakeLists.txt b/ThirdParty/Ert/python/tests/core/geometry/CMakeLists.txt deleted file mode 100644 index 6fc11295d9..0000000000 --- a/ThirdParty/Ert/python/tests/core/geometry/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_convex_hull.py - test_cpolyline.py - test_cpolyline_collection.py - test_geometry_tools.py - test_intersection.py - test_point_in_polygon.py - test_polygon_slicing.py - test_polyline.py - test_surface.py -) - -add_python_package("python.tests.core.geometry" ${PYTHON_INSTALL_PREFIX}/tests/core/geometry "${TEST_SOURCES}" False) - -addPythonTest(core.geometry.surface tests.core.geometry.test_surface.SurfaceTest) -addPythonTest(core.geometry.polyline tests.core.geometry.test_polyline.PolylineTest) -addPythonTest(core.geometry.intersection tests.core.geometry.test_intersection.IntersectionTest) -addPythonTest(core.geometry.convex_hull tests.core.geometry.test_convex_hull.ConvexHullTest) -addPythonTest(core.geometry.point_in_polygon tests.core.geometry.test_point_in_polygon.PointInPolygonTest) -addPythonTest(core.geometry.polygon_slicing tests.core.geometry.test_polygon_slicing.PolygonSlicingTest) -addPythonTest(core.geometry.cpolyline tests.core.geometry.test_cpolyline.CPolylineTest) -addPythonTest(core.geometry.cpolyline_collection tests.core.geometry.test_cpolyline_collection.CPolylineCollectionTest) -addPythonTest(core.geometry.geometry_tools tests.core.geometry.test_geometry_tools.GeometryToolsTest ) diff --git a/ThirdParty/Ert/python/tests/core/geometry/__init__.py b/ThirdParty/Ert/python/tests/core/geometry/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/core/util/CMakeLists.txt b/ThirdParty/Ert/python/tests/core/util/CMakeLists.txt deleted file mode 100644 index e90b279076..0000000000 --- a/ThirdParty/Ert/python/tests/core/util/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_ctime.py - test_cstring.py - test_hash.py - test_lookup_table.py - test_matrix.py - test_rng.py - test_stat.py - test_string_list.py - test_substitution_list.py - test_thread_pool.py - test_cthread_pool.py - test_ui_return.py - test_vectors.py - test_version.py - test_work_area.py - test_path_context.py - test_arg_pack.py - test_spawn.py -) - -add_python_package("python.tests.core.util" ${PYTHON_INSTALL_PREFIX}/tests/core/util "${TEST_SOURCES}" False) - -addPythonTest(core.util.ctime core.util.test_ctime.CTimeTest) -addPythonTest(core.util.cstring core.util.test_cstring.CStringTest) -addPythonTest(core.util.hash core.util.test_hash.HashTest) -addPythonTest(core.util.lookup_table core.util.test_lookup_table.LookupTableTest ) -addPythonTest(core.util.matrix core.util.test_matrix.MatrixTest ) -addPythonTest(core.util.rng core.util.test_rng.RngTest ) -addPythonTest(core.util.stat core.util.test_stat.StatTest ) -addPythonTest(core.util.stringlist core.util.test_string_list.StringListTest) -addPythonTest(core.util.tvector core.util.test_vectors.UtilTest) -addPythonTest(core.util.ui_return core.util.test_ui_return.UIReturnTest) -addPythonTest(core.util.work_area core.util.test_work_area.WorkAreaTest) -addPythonTest(core.util.version core.util.test_version.VersionTest) -addPythonTest(core.util.path_context core.util.test_path_context.PathContextTest) -addPythonTest(core.util.thread_pool core.util.test_thread_pool.ThreadPoolTest) -addPythonTest(core.util.cthread_pool core.util.test_cthread_pool.CThreadPoolTest) -addPythonTest(core.util.arg_pack core.util.test_arg_pack.ArgPackTest) -addPythonTest(core.util.spawn core.util.test_spawn.SpawnTest) diff --git a/ThirdParty/Ert/python/tests/core/util/__init__.py b/ThirdParty/Ert/python/tests/core/util/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/core/well/CMakeLists.txt b/ThirdParty/Ert/python/tests/core/well/CMakeLists.txt deleted file mode 100644 index 381665920d..0000000000 --- a/ThirdParty/Ert/python/tests/core/well/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_ecl_well.py - test_ecl_well2.py - test_ecl_well3.py -) - -add_python_package("python.tests.core.well" ${PYTHON_INSTALL_PREFIX}/tests/core/well "${TEST_SOURCES}" False) - -if (STATOIL_TESTDATA_ROOT) - addPythonTest(core.well.ecl_well core.well.test_ecl_well.EclWellTest LABELS StatoilData) - addPythonTest(core.well.ecl_well2 core.well.test_ecl_well2.EclWellTest2 LABELS StatoilData) - addPythonTest(core.well.ecl_well3 core.well.test_ecl_well3.EclWellTest3 LABELS StatoilData) -endif() diff --git a/ThirdParty/Ert/python/tests/core/well/__init__.py b/ThirdParty/Ert/python/tests/core/well/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/cwrap/CMakeLists.txt b/ThirdParty/Ert/python/tests/cwrap/CMakeLists.txt index 0f9355a5c4..5ae758b143 100644 --- a/ThirdParty/Ert/python/tests/cwrap/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/cwrap/CMakeLists.txt @@ -7,11 +7,11 @@ set(TEST_SOURCES test_cfile.py ) -add_python_package("python.tests.core.cwrap" ${PYTHON_INSTALL_PREFIX}/tests/core/cwrap "${TEST_SOURCES}" False) +add_python_package("python.tests.cwrap" ${PYTHON_INSTALL_PREFIX}/tests/cwrap "${TEST_SOURCES}" False) -addPythonTest(core.cwrap.basecclass tests.core.cwrap.test_basecclass.BaseCClassTest) -addPythonTest(core.cwrap.basecenum tests.core.cwrap.test_basecenum.BaseCEnumTest) -addPythonTest(core.cwrap.basecvalue tests.core.cwrap.test_basecvalue.BaseCValueTest) -addPythonTest(core.cwrap.metacwrap tests.core.cwrap.test_metawrap.MetaWrapTest) -addPythonTest(core.cwrap.cfile tests.core.cwrap.test_cfile.CFILETest) +addPythonTest(cwrap.basecclass tests.cwrap.test_basecclass.BaseCClassTest) +addPythonTest(cwrap.basecenum tests.cwrap.test_basecenum.BaseCEnumTest) +addPythonTest(cwrap.basecvalue tests.cwrap.test_basecvalue.BaseCValueTest) +addPythonTest(cwrap.metacwrap tests.cwrap.test_metawrap.MetaWrapTest) +addPythonTest(cwrap.cfile tests.cwrap.test_cfile.CFILETest) diff --git a/ThirdParty/Ert/python/tests/cwrap/test_metawrap.py b/ThirdParty/Ert/python/tests/cwrap/test_metawrap.py index d58f5a4a7e..afbc5bd5af 100644 --- a/ThirdParty/Ert/python/tests/cwrap/test_metawrap.py +++ b/ThirdParty/Ert/python/tests/cwrap/test_metawrap.py @@ -1,5 +1,6 @@ +from __future__ import absolute_import, division, print_function, unicode_literals +from six import string_types import ctypes -from types import StringType, IntType import ert from cwrap import BaseCClass, Prototype, PrototypeError @@ -33,13 +34,15 @@ class StringList(BaseCClass): if initial: for s in initial: - if isinstance(s, StringType): + if isinstance(s, bytes): + s.decode('ascii') + if isinstance(s, string_types): self.append(s) else: raise TypeError("Item: %s not a string" % s) def __getitem__(self, index): - if isinstance(index, IntType): + if isinstance(index, int): length = len(self) if index < 0: index += length @@ -51,7 +54,9 @@ class StringList(BaseCClass): raise TypeError("Index should be integer type") def append(self, string): - if isinstance(string, StringType): + if isinstance(string, bytes): + s.decode('ascii') + if isinstance(string, string_types): self._append(self, string) else: self._append(self, str(string)) @@ -109,10 +114,10 @@ class MetaWrapTest(ExtendedTestCase): char_ptr = ctypes.c_char_p(c_ptr) python_string = char_ptr.value TestUtilPrototype.lib.free(c_ptr) - return python_string + return python_string.decode('ascii') Prototype.registerType("string_obj", stringObj) dateStamp = TestUtilPrototype("string_obj util_alloc_date_stamp_utc()") date_stamp = dateStamp() - self.assertIsInstance(date_stamp, str) + self.assertIsInstance(date_stamp, string_types) diff --git a/ThirdParty/Ert/python/tests/core/ecl/CMakeLists.txt b/ThirdParty/Ert/python/tests/ecl/CMakeLists.txt similarity index 93% rename from ThirdParty/Ert/python/tests/core/ecl/CMakeLists.txt rename to ThirdParty/Ert/python/tests/ecl/CMakeLists.txt index 3067197906..e2cdb6551d 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/ecl/CMakeLists.txt @@ -24,9 +24,9 @@ set(TEST_SOURCES test_ecl_kw.py test_kw_function.py test_layer.py - test_legacy_ecl.py test_npv.py test_region.py + test_region_statoil.py test_restart.py test_rft.py test_rft_statoil.py @@ -38,6 +38,7 @@ set(TEST_SOURCES test_sum.py test_grav.py test_geertsma.py + test_ecl_type.py ) add_python_package("python.tests.ecl" ${PYTHON_INSTALL_PREFIX}/tests/ecl "${TEST_SOURCES}" False) @@ -46,7 +47,6 @@ addPythonTest(ecl.ecl_grid ecl.test_grid.GridTest ) addPythonTest(ecl.ecl_kw ecl.test_ecl_kw.KWTest) addPythonTest(ecl.ecl_kw_function ecl.test_kw_function.KWFunctionTest) addPythonTest(ecl.ecl_3dkw ecl.test_ecl_3dkw.Ecl3DKWTest ) -addPythonTest(ecl.legacy_ecl ecl.test_legacy_ecl.LegacyEclTest) addPythonTest(ecl.ecl_rft ecl.test_rft.RFTTest) addPythonTest(ecl.ecl_rft_cell ecl.test_rft_cell.RFTCellTest) addPythonTest(ecl.ecl_sum2 ecl.test_sum.SumTest) @@ -62,6 +62,8 @@ addPythonTest(ecl.fortio ecl.test_fortio.FortIOTest) addPythonTest(ecl.ecl_file ecl.test_ecl_file.EclFileTest) addPythonTest(ecl.ecl_grav ecl.test_grav.EclGravTest) addPythonTest(ecl.ecl_geertsma ecl.test_geertsma.GeertsmaTest) +addPythonTest(ecl.ecl_type ecl.test_ecl_type.EclDataTypeTest) +addPythonTest(ecl.ecl_region ecl.test_region.RegionTest) if (STATOIL_TESTDATA_ROOT) @@ -72,7 +74,7 @@ if (STATOIL_TESTDATA_ROOT) addPythonTest(ecl.ecl_init_file ecl.test_ecl_init_file.InitFileTest LABELS StatoilData) addPythonTest(ecl.ecl_restart_file ecl.test_ecl_restart_file.RestartFileTest LABELS StatoilData) addPythonTest(ecl.ecl_restart ecl.test_restart.RestartTest LABELS StatoilData ) - addPythonTest(ecl.ecl_region ecl.test_region.RegionTest LABELS StatoilData) + addPythonTest(ecl.ecl_region_statoil ecl.test_region_statoil.RegionTest LABELS StatoilData) addPythonTest(ecl.ecl_rft_statoil ecl.test_rft_statoil.RFTTest LABELS StatoilData) addPythonTest(ecl.ecl_sum1 ecl.test_sum_statoil.SumTest LABELS StatoilData) addPythonTest(ecl.ecl_sum_vector ecl.test_ecl_sum_vector.EclSumVectorTest LABELS StatoilData) diff --git a/ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/__init__.py b/ThirdParty/Ert/python/tests/ecl/__init__.py similarity index 100% rename from ThirdParty/Ert/python/python/ert_gui/ertwidgets/models/__init__.py rename to ThirdParty/Ert/python/tests/ecl/__init__.py diff --git a/ThirdParty/Ert/python/tests/ecl/test_deprecation.py b/ThirdParty/Ert/python/tests/ecl/test_deprecation.py new file mode 100644 index 0000000000..87b08dc51a --- /dev/null +++ b/ThirdParty/Ert/python/tests/ecl/test_deprecation.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# Copyright (C) 2011 Statoil ASA, Norway. +# +# The file 'test_deprecation.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. +import warnings +import time +import datetime + +from ert.test import ExtendedTestCase, TestAreaContext +from ert.ecl import EclFile, EclGrid, EclKW, EclDataType, EclGrid, EclRegion +from ert.ecl import FortIO, openFortIO, EclRFT, EclGridGenerator +from ert.test.ecl_mock import createEclSum +from ert.util import BoolVector + +# The class Deprecation_1_9_Test contains methods which will be marked +# as deprecated in the 1.9.x versions. + +warnings.simplefilter("error" , DeprecationWarning) + +class Deprecation_2_1_Test(ExtendedTestCase): + pass + +class Deprecation_2_0_Test(ExtendedTestCase): + + def test_EclFile_name_property(self): + with TestAreaContext("name") as t: + kw = EclKW("TEST", 3, EclDataType.ECL_INT) + with openFortIO("TEST" , mode = FortIO.WRITE_MODE) as f: + kw.fwrite( f ) + + t.sync() + f = EclFile( "TEST" ) + +class Deprecation_1_9_Test(ExtendedTestCase): + + def test_EclRegion_properties(self): + grid = EclGridGenerator.createRectangular( (10,10,10) , (1,1,1)) + region = EclRegion( grid , False ) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_3dkw.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_3dkw.py similarity index 84% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_3dkw.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_3dkw.py index 5135dc5315..8e586b57db 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_3dkw.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_3dkw.py @@ -18,7 +18,7 @@ import os import random from ert.util import IntVector -from ert.ecl import Ecl3DKW , EclKW, EclTypeEnum, EclFile, FortIO, EclFileFlagEnum , EclGrid +from ert.ecl import Ecl3DKW , EclKW, EclDataType, EclFile, FortIO, EclFileFlagEnum , EclGrid from ert.test import ExtendedTestCase , TestAreaContext @@ -31,7 +31,7 @@ class Ecl3DKWTest(ExtendedTestCase): actnum[i] = 0 grid = EclGrid.createRectangular( (10,10,10) , (1,1,1) , actnum = actnum) - kw = Ecl3DKW.create( "KW" , grid , EclTypeEnum.ECL_FLOAT_TYPE ) + kw = Ecl3DKW( "KW" , grid , EclDataType.ECL_FLOAT ) self.assertEqual( len(kw) , grid.getNumActive()) self.assertEqual( (10,10,10) , kw.dims() ) @@ -43,7 +43,7 @@ class Ecl3DKWTest(ExtendedTestCase): actnum[i] = 0 grid = EclGrid.createRectangular( (10,10,10) , (1,1,1) , actnum = actnum) - kw = Ecl3DKW.create( "KW" , grid , EclTypeEnum.ECL_FLOAT_TYPE , global_active = True) + kw = Ecl3DKW( "KW" , grid , EclDataType.ECL_FLOAT , global_active = True) self.assertEqual( len(kw) , grid.getGlobalSize()) kw.assign(50) @@ -58,7 +58,7 @@ class Ecl3DKWTest(ExtendedTestCase): ny = 11 nz = 12 grid = EclGrid.createRectangular( (nx,ny,nz) , (1,1,1) ) - kw = Ecl3DKW.create("REGIONS" , grid , EclTypeEnum.ECL_INT_TYPE , global_active = True) + kw = Ecl3DKW("REGIONS" , grid , EclDataType.ECL_INT , global_active = True) kw.assign(3) self.assertEqual( 3 * nx*ny*nz , sum(kw)) @@ -78,7 +78,7 @@ class Ecl3DKWTest(ExtendedTestCase): actnum[i] = 0 grid = EclGrid.createRectangular( (10,10,10) , (1,1,1) , actnum = actnum) - kw = Ecl3DKW.create( "KW" , grid , EclTypeEnum.ECL_FLOAT_TYPE , default_value = 77) + kw = Ecl3DKW( "KW" , grid , EclDataType.ECL_FLOAT , default_value = 77) with self.assertRaises(IndexError): kw[1000] @@ -105,7 +105,7 @@ class Ecl3DKWTest(ExtendedTestCase): actnum[i] = 0 grid = EclGrid.createRectangular( (10,10,10) , (1,1,1) , actnum = actnum) - kw = Ecl3DKW.create( "KW" , grid , EclTypeEnum.ECL_FLOAT_TYPE , default_value = 77) + kw = Ecl3DKW( "KW" , grid , EclDataType.ECL_FLOAT , default_value = 77) with self.assertRaises(IndexError): kw[1000] @@ -138,9 +138,9 @@ class Ecl3DKWTest(ExtendedTestCase): actnum[i] = 0 grid = EclGrid.createRectangular( (10,10,10) , (1,1,1) , actnum = actnum) - kw_wrong_size = EclKW.create( "KW" , 27 , EclTypeEnum.ECL_FLOAT_TYPE ) - kw_global_size = EclKW.create( "KW" , grid.getGlobalSize() , EclTypeEnum.ECL_FLOAT_TYPE ) - kw_active_size = EclKW.create( "KW" , grid.getNumActive() , EclTypeEnum.ECL_FLOAT_TYPE ) + kw_wrong_size = EclKW( "KW" , 27 , EclDataType.ECL_FLOAT ) + kw_global_size = EclKW( "KW" , grid.getGlobalSize() , EclDataType.ECL_FLOAT ) + kw_active_size = EclKW( "KW" , grid.getNumActive() , EclDataType.ECL_FLOAT ) with self.assertRaises(ValueError): Ecl3DKW.castFromKW(kw_wrong_size , grid) @@ -158,7 +158,7 @@ class Ecl3DKWTest(ExtendedTestCase): def test_default(self): grid = EclGrid.createRectangular( (10,10,10) , (1,1,1)) - kw = Ecl3DKW.create( "KW" , grid , EclTypeEnum.ECL_FLOAT_TYPE ) + kw = Ecl3DKW( "KW" , grid , EclDataType.ECL_FLOAT ) kw.setDefault(55) self.assertTrue( 55 , kw.getDefault()) @@ -169,7 +169,7 @@ class Ecl3DKWTest(ExtendedTestCase): actnum[2*i + 1] = 0 grid = EclGrid.createRectangular( (10,10,10) , (1,1,1) , actnum = actnum) - kw = Ecl3DKW.create( "KW" , grid , EclTypeEnum.ECL_INT_TYPE , global_active = True) + kw = Ecl3DKW( "KW" , grid , EclDataType.ECL_INT , global_active = True) for i in range(len(kw)): kw[i] = i @@ -188,7 +188,7 @@ class Ecl3DKWTest(ExtendedTestCase): actnum[2*i + 1] = 0 grid = EclGrid.createRectangular( (10,10,10) , (1,1,1) , actnum = actnum) - kw = Ecl3DKW.create( "KW" , grid , EclTypeEnum.ECL_INT_TYPE , global_active = False) + kw = Ecl3DKW( "KW" , grid , EclDataType.ECL_INT , global_active = False) for i in range(len(kw)): kw[i] = i diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_cmp.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_cmp.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_cmp.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_cmp.py diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_file.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_file.py similarity index 80% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_file.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_file.py index 2872cd52d1..71bf8bfe1c 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_file.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_file.py @@ -1,18 +1,18 @@ #!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'sum_test.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at +# Copyright (C) 2011 Statoil ASA, Norway. +# +# The file 'sum_test.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at # for more details. import datetime import os.path @@ -21,7 +21,7 @@ from unittest import skipIf from ert.ecl import EclFile, FortIO, EclKW , openFortIO , openEclFile -from ert.ecl import EclFileFlagEnum, EclTypeEnum, EclFileEnum +from ert.ecl import EclFileFlagEnum, EclDataType, EclFileEnum from ert.test import ExtendedTestCase , TestAreaContext @@ -40,7 +40,7 @@ def loadKeywords( name ): return kw_list - + class EclFileTest(ExtendedTestCase): @@ -50,7 +50,7 @@ class EclFileTest(ExtendedTestCase): self.assertEqual( fmt_file , expected[1] ) self.assertEqual( step , expected[2] ) - + def test_file_type(self): self.assertFileType( "ECLIPSE.UNRST" , (EclFileEnum.ECL_UNIFIED_RESTART_FILE , False , None)) self.assertFileType( "ECLIPSE.X0030" , (EclFileEnum.ECL_RESTART_FILE , False , 30 )) @@ -59,7 +59,7 @@ class EclFileTest(ExtendedTestCase): self.assertFileType( "ECLIPSE.A0010" , (EclFileEnum.ECL_SUMMARY_FILE , True , 10 )) self.assertFileType( "ECLIPSE.EGRID" , (EclFileEnum.ECL_EGRID_FILE , False , None )) - + def test_IOError(self): with self.assertRaises(IOError): EclFile("No/Does/not/exist") @@ -67,8 +67,8 @@ class EclFileTest(ExtendedTestCase): def test_context( self ): with TestAreaContext("python/ecl_file/context"): - kw1 = EclKW.create( "KW1" , 100 , EclTypeEnum.ECL_INT_TYPE) - kw2 = EclKW.create( "KW2" , 100 , EclTypeEnum.ECL_INT_TYPE) + kw1 = EclKW( "KW1" , 100 , EclDataType.ECL_INT) + kw2 = EclKW( "KW2" , 100 , EclDataType.ECL_INT) with openFortIO("TEST" , mode = FortIO.WRITE_MODE) as f: kw1.fwrite( f ) kw2.fwrite( f ) @@ -77,13 +77,14 @@ class EclFileTest(ExtendedTestCase): self.assertEqual( len(ecl_file) , 2 ) self.assertTrue( ecl_file.has_kw("KW1")) self.assertTrue( ecl_file.has_kw("KW2")) + self.assertEqual(ecl_file[1], ecl_file[-1]) + + - - def test_gc(self): - kw1 = EclKW("KW1" , 100 , EclTypeEnum.ECL_INT_TYPE) - kw2 = EclKW("KW2" , 100 , EclTypeEnum.ECL_INT_TYPE) - kw3 = EclKW("KW3" , 100 , EclTypeEnum.ECL_INT_TYPE) + kw1 = EclKW("KW1" , 100 , EclDataType.ECL_INT) + kw2 = EclKW("KW2" , 100 , EclDataType.ECL_INT) + kw3 = EclKW("KW3" , 100 , EclDataType.ECL_INT) for i in range(len(kw1)): kw1[i] = i @@ -91,50 +92,58 @@ class EclFileTest(ExtendedTestCase): kw3[i] = 3*i kw_list = [kw1 , kw2 , kw2] - + with TestAreaContext("context") as ta: createFile("TEST" , kw_list ) - gc.collect() + gc.collect() kw_list2 = loadKeywords( "TEST" ) for kw1,kw2 in zip(kw_list,kw_list2): self.assertEqual( kw1, kw2 ) - + def test_block_view(self): with TestAreaContext("python/ecl_file/view"): with openFortIO("TEST" , mode = FortIO.WRITE_MODE) as f: for i in range(5): - header = EclKW("HEADER" , 1 , EclTypeEnum.ECL_INT_TYPE ) + header = EclKW("HEADER" , 1 , EclDataType.ECL_INT ) header[0] = i - - data1 = EclKW("DATA1" , 100 , EclTypeEnum.ECL_INT_TYPE ) + + data1 = EclKW("DATA1" , 100 , EclDataType.ECL_INT ) data1.assign( i ) - data2 = EclKW("DATA2" , 100 , EclTypeEnum.ECL_INT_TYPE ) + data2 = EclKW("DATA2" , 100 , EclDataType.ECL_INT ) data2.assign( i*10 ) header.fwrite( f ) data1.fwrite( f ) data2.fwrite( f ) - + ecl_file = EclFile("TEST") + pfx = 'EclFile(' + self.assertEqual(pfx, repr(ecl_file)[:len(pfx)]) with self.assertRaises(KeyError): ecl_file.blockView("NO" , 1) with self.assertRaises(IndexError): ecl_file.blockView("HEADER" , 100) + with self.assertRaises(IndexError): + ecl_file.blockView("HEADER" , 1000) + + bv = ecl_file.blockView("HEADER" , -1) + + for i in range(5): view = ecl_file.blockView("HEADER" , i) self.assertEqual( len(view) , 3) header = view["HEADER"][0] data1 = view["DATA1"][0] data2 = view["DATA2"][0] - + self.assertEqual( header[0] , i ) self.assertEqual( data1[99] , i ) self.assertEqual( data2[99] , i*10 ) @@ -145,7 +154,7 @@ class EclFileTest(ExtendedTestCase): self.assertEqual( len(view) , 2) header = view["HEADER"][0] data1 = view["DATA1"][0] - + self.assertEqual( header[0] , i ) self.assertEqual( data1[99] , i ) @@ -159,4 +168,3 @@ class EclFileTest(ExtendedTestCase): #self.assertTrue( "HEADER" in view ) #self.assertTrue( "DATA1" in view ) #self.assertFalse( "DATA2" in view ) - diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_file_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_file_statoil.py similarity index 98% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_file_statoil.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_file_statoil.py index 49d426f173..234882e854 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_file_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_file_statoil.py @@ -19,7 +19,7 @@ import os.path from unittest import skipIf from ert.ecl import EclFile, FortIO, EclKW , openFortIO , openEclFile -from ert.ecl import EclFileFlagEnum, EclTypeEnum, EclFileEnum +from ert.ecl import EclFileFlagEnum, EclFileEnum from ert.test import ExtendedTestCase , TestAreaContext diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_init_file.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_init_file.py similarity index 93% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_init_file.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_init_file.py index 0e34c180a7..6ba97937b5 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_init_file.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_init_file.py @@ -16,7 +16,7 @@ from ert.test import ExtendedTestCase -from ert.ecl import Ecl3DKW , EclKW, EclTypeEnum, EclInitFile , EclFile, FortIO, EclFileFlagEnum , EclGrid +from ert.ecl import Ecl3DKW , EclKW, EclInitFile , EclFile, FortIO, EclFileFlagEnum , EclGrid class InitFileTest(ExtendedTestCase): def setUp(self): diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_kw.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_kw.py similarity index 72% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_kw.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_kw.py index 3841ca3822..4634bf78e4 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_kw.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_kw.py @@ -17,25 +17,27 @@ import os import random import numpy -from ert.ecl import EclKW, EclTypeEnum, EclFile, FortIO, EclFileFlagEnum , openFortIO +import warnings + +from ert.ecl import EclKW, EclDataType, EclTypeEnum, EclFile, FortIO, EclFileFlagEnum , openFortIO from ert.test import ExtendedTestCase , TestAreaContext def copy_long(): - src = EclKW.create("NAME", 100, EclTypeEnum.ECL_FLOAT_TYPE) + src = EclKW("NAME", 100, EclDataType.ECL_FLOAT) copy = src.sub_copy(0, 2000) def copy_offset(): - src = EclKW.create("NAME", 100, EclTypeEnum.ECL_FLOAT_TYPE) + src = EclKW("NAME", 100, EclDataType.ECL_FLOAT) copy = src.sub_copy(200, 100) class KWTest(ExtendedTestCase): def test_min_max(self): - kw = EclKW("TEST", 3, EclTypeEnum.ECL_INT_TYPE) + kw = EclKW("TEST", 3, EclDataType.ECL_INT) kw[0] = 10 kw[1] = 5 kw[2] = 0 @@ -45,8 +47,22 @@ class KWTest(ExtendedTestCase): self.assertEqual( (0,10) , kw.getMinMax()) + def test_deprecated_datatypes(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + kw = EclKW("Test", 10, EclTypeEnum.ECL_INT_TYPE) + self.assertTrue(len(w) > 0) + self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + kw = EclKW("Test", 10, EclDataType.ECL_INT) + self.assertTrue(len(w) == 0) + self.assertEqual(EclTypeEnum.ECL_INT_TYPE, kw.type) + + self.assertTrue(len(w) > 0) + self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) def kw_test( self, data_type, data, fmt ): name1 = "file1.txt" @@ -66,42 +82,42 @@ class KWTest(ExtendedTestCase): file2.write(fmt % d) file2.close() self.assertFilesAreEqual(name1, name2) - self.assertEqual( kw.getEclType() , data_type ) + self.assertEqual( kw.data_type , data_type ) def test_create(self): with self.assertRaises(ValueError): - EclKW.create( "ToGodDamnLong" , 100 , EclTypeEnum.ECL_CHAR_TYPE ) + EclKW( "ToGodDamnLong" , 100 , EclDataType.ECL_CHAR ) def test_sum( self ): - kw_string = EclKW.create( "STRING" , 100 , EclTypeEnum.ECL_CHAR_TYPE ) + kw_string = EclKW( "STRING" , 100 , EclDataType.ECL_CHAR ) with self.assertRaises(ValueError): kw_string.sum() - kw_int = EclKW.create( "INT" , 4 , EclTypeEnum.ECL_INT_TYPE ) + kw_int = EclKW( "INT" , 4 , EclDataType.ECL_INT ) kw_int[0] = 1 kw_int[1] = 2 kw_int[2] = 3 kw_int[3] = 4 self.assertEqual( kw_int.sum() , 10 ) - kw_d = EclKW.create( "D" , 4 , EclTypeEnum.ECL_DOUBLE_TYPE ) + kw_d = EclKW( "D" , 4 , EclDataType.ECL_DOUBLE ) kw_d[0] = 1 kw_d[1] = 2 kw_d[2] = 3 kw_d[3] = 4 self.assertEqual( kw_d.sum() , 10 ) - kw_f = EclKW.create( "F" , 4 , EclTypeEnum.ECL_FLOAT_TYPE ) + kw_f = EclKW( "F" , 4 , EclDataType.ECL_FLOAT ) kw_f[0] = 1 kw_f[1] = 2 kw_f[2] = 3 kw_f[3] = 4 self.assertEqual( kw_f.sum() , 10 ) - kw_b = EclKW.create( "F" , 4 , EclTypeEnum.ECL_BOOL_TYPE ) + kw_b = EclKW( "F" , 4 , EclDataType.ECL_BOOL ) kw_b[0] = False kw_b[1] = True kw_b[2] = False @@ -112,23 +128,26 @@ class KWTest(ExtendedTestCase): def test_fprintf( self ): with TestAreaContext("python.ecl_kw"): - self.kw_test(EclTypeEnum.ECL_INT_TYPE, [0, 1, 2, 3, 4, 5], "%4d\n") - self.kw_test(EclTypeEnum.ECL_FLOAT_TYPE, [0.0, 1.1, 2.2, 3.3, 4.4, 5.5], "%12.6f\n") - self.kw_test(EclTypeEnum.ECL_DOUBLE_TYPE, [0.0, 1.1, 2.2, 3.3, 4.4, 5.5], "%12.6f\n") - self.kw_test(EclTypeEnum.ECL_BOOL_TYPE, [True, True, True, False, True], "%4d\n") - self.kw_test(EclTypeEnum.ECL_CHAR_TYPE, ["1", "22", "4444", "666666", "88888888"], "%-8s\n") + self.kw_test(EclDataType.ECL_INT, [0, 1, 2, 3, 4, 5], "%4d\n") + self.kw_test(EclDataType.ECL_FLOAT, [0.0, 1.1, 2.2, 3.3, 4.4, 5.5], "%12.6f\n") + self.kw_test(EclDataType.ECL_DOUBLE, [0.0, 1.1, 2.2, 3.3, 4.4, 5.5], "%12.6f\n") + self.kw_test(EclDataType.ECL_BOOL, [True, True, True, False, True], "%4d\n") + self.kw_test(EclDataType.ECL_CHAR, ["1", "22", "4444", "666666", "88888888"], "%-8s\n") def test_kw_write(self): with TestAreaContext("python/ecl_kw/writing"): data = [random.random() for i in range(10000)] - kw = EclKW("TEST", len(data), EclTypeEnum.ECL_DOUBLE_TYPE) + kw = EclKW("TEST", len(data), EclDataType.ECL_DOUBLE) i = 0 for d in data: kw[i] = d i += 1 + pfx = 'EclKW(' + self.assertEqual(pfx, repr(kw)[:len(pfx)]) + fortio = FortIO("ECL_KW_TEST", FortIO.WRITE_MODE) kw.fwrite(fortio) fortio.close() @@ -160,7 +179,7 @@ class KWTest(ExtendedTestCase): def test_fprintf_data(self): with TestAreaContext("kw_no_header"): - kw = EclKW.create("REGIONS" , 10 , EclTypeEnum.ECL_INT_TYPE) + kw = EclKW("REGIONS" , 10 , EclDataType.ECL_INT) for i in range(len(kw)): kw[i] = i @@ -180,7 +199,7 @@ class KWTest(ExtendedTestCase): def test_sliced_set(self): - kw = EclKW.create("REGIONS" , 10 , EclTypeEnum.ECL_INT_TYPE) + kw = EclKW("REGIONS" , 10 , EclDataType.ECL_INT) kw.assign(99) kw[0:5] = 66 self.assertEqual(kw[0] , 66) @@ -190,23 +209,23 @@ class KWTest(ExtendedTestCase): def test_long_name(self): with self.assertRaises(ValueError): - EclKW.create("LONGLONGNAME" , 10 , EclTypeEnum.ECL_INT_TYPE) + EclKW("LONGLONGNAME" , 10 , EclDataType.ECL_INT) - kw = EclKW.create("REGIONS" , 10 , EclTypeEnum.ECL_INT_TYPE) + kw = EclKW("REGIONS" , 10 , EclDataType.ECL_INT) with self.assertRaises(ValueError): - kw.set_name("LONGLONGNAME") + kw.setName("LONGLONGNAME") def test_abs(self): - kw = EclKW("NAME" , 10 , EclTypeEnum.ECL_CHAR_TYPE) + kw = EclKW("NAME" , 10 , EclDataType.ECL_CHAR) with self.assertRaises(TypeError): abs_kw = abs(kw) - kw = EclKW("NAME" , 10 , EclTypeEnum.ECL_BOOL_TYPE) + kw = EclKW("NAME" , 10 , EclDataType.ECL_BOOL) with self.assertRaises(TypeError): abs_kw = abs(kw) - kw = EclKW("NAME" , 10 , EclTypeEnum.ECL_INT_TYPE) + kw = EclKW("NAME" , 10 , EclDataType.ECL_INT) for i in range(len(kw)): kw[i] = -i @@ -217,8 +236,8 @@ class KWTest(ExtendedTestCase): def test_fmt(self): - kw1 = EclKW( "NAME1" , 100 , EclTypeEnum.ECL_INT_TYPE) - kw2 = EclKW( "NAME2" , 100 , EclTypeEnum.ECL_INT_TYPE) + kw1 = EclKW( "NAME1" , 100 , EclDataType.ECL_INT) + kw2 = EclKW( "NAME2" , 100 , EclDataType.ECL_INT) for i in range(len(kw1)): kw1[i] = i + 1 @@ -242,11 +261,11 @@ class KWTest(ExtendedTestCase): def test_first_different(self): - kw1 = EclKW( "NAME1" , 100 , EclTypeEnum.ECL_INT_TYPE) - kw2 = EclKW( "NAME2" , 100 , EclTypeEnum.ECL_INT_TYPE) - kw3 = EclKW( "NAME2" , 200 , EclTypeEnum.ECL_INT_TYPE) - kw4 = EclKW( "NAME2" , 100 , EclTypeEnum.ECL_FLOAT_TYPE) - kw5 = EclKW( "NAME2" , 100 , EclTypeEnum.ECL_FLOAT_TYPE) + kw1 = EclKW( "NAME1" , 100 , EclDataType.ECL_INT) + kw2 = EclKW( "NAME2" , 100 , EclDataType.ECL_INT) + kw3 = EclKW( "NAME2" , 200 , EclDataType.ECL_INT) + kw4 = EclKW( "NAME2" , 100 , EclDataType.ECL_FLOAT) + kw5 = EclKW( "NAME2" , 100 , EclDataType.ECL_FLOAT) with self.assertRaises( IndexError ): @@ -293,8 +312,8 @@ class KWTest(ExtendedTestCase): def test_numeric_equal(self): - kw1 = EclKW("Name1" , 10 , EclTypeEnum.ECL_DOUBLE_TYPE ) - kw2 = EclKW("Name1" , 10 , EclTypeEnum.ECL_DOUBLE_TYPE ) + kw1 = EclKW("Name1" , 10 , EclDataType.ECL_DOUBLE ) + kw2 = EclKW("Name1" , 10 , EclDataType.ECL_DOUBLE ) shift = 0.0001 @@ -313,10 +332,10 @@ class KWTest(ExtendedTestCase): self.assertTrue( kw1.equal_numeric( kw2 , abs_epsilon = abs_diff * 1.1 , rel_epsilon = 0)) def test_mul(self): - kw1 = EclKW("Name1" , 10 , EclTypeEnum.ECL_INT_TYPE ) + kw1 = EclKW("Name1" , 10 , EclDataType.ECL_INT ) kw1.assign( 10 ) - kw2 = EclKW("Name1" , 10 , EclTypeEnum.ECL_INT_TYPE ) + kw2 = EclKW("Name1" , 10 , EclDataType.ECL_INT ) kw2.assign( 2 ) kw3 = kw1 * kw2 @@ -331,7 +350,7 @@ class KWTest(ExtendedTestCase): def test_numpy(self): - kw1 = EclKW("DOUBLE", 10, EclTypeEnum.ECL_DOUBLE_TYPE ) + kw1 = EclKW("DOUBLE", 10, EclDataType.ECL_DOUBLE ) view = kw1.numpyView( ) copy = kw1.numpyCopy( ) @@ -344,17 +363,17 @@ class KWTest(ExtendedTestCase): self.assertTrue( copy[ 0 ] == kw1[ 0 ] - 1) - kw2 = EclKW("CHAR", 10, EclTypeEnum.ECL_CHAR_TYPE ) + kw2 = EclKW("CHAR", 10, EclDataType.ECL_CHAR ) with self.assertRaises(ValueError): kw2.numpyView( ) - kw3 = EclKW("BOOL", 10, EclTypeEnum.ECL_BOOL_TYPE ) + kw3 = EclKW("BOOL", 10, EclDataType.ECL_BOOL ) with self.assertRaises(ValueError): kw3.numpyView( ) def test_slice(self): N = 100 - kw = EclKW("KW" , N , EclTypeEnum.ECL_INT_TYPE) + kw = EclKW("KW" , N , EclDataType.ECL_INT) for i in range(len(kw)): kw[i] = i @@ -371,7 +390,7 @@ class KWTest(ExtendedTestCase): def test_resize(self): N = 4 - kw = EclKW("KW" , N , EclTypeEnum.ECL_INT_TYPE) + kw = EclKW("KW" , N , EclDataType.ECL_INT) for i in range(N): kw[i] = i @@ -385,3 +404,8 @@ class KWTest(ExtendedTestCase): for i in range(N/2): self.assertEqual( kw[i] , i ) + + def test_typename(self): + kw = EclKW("KW" , 100 , EclDataType.ECL_INT) + + self.assertEqual( kw.typeName( ) , "INTE") diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_kw_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_kw_statoil.py similarity index 85% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_kw_statoil.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_kw_statoil.py index 2ddb0f600c..a96827fbf7 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_kw_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_kw_statoil.py @@ -16,18 +16,18 @@ # for more details. import os import random -from ert.ecl import EclKW, EclTypeEnum, EclFile, FortIO, EclFileFlagEnum +from ert.ecl import EclKW, EclDataType, EclFile, FortIO, EclFileFlagEnum from ert.test import ExtendedTestCase , TestAreaContext def copy_long(): - src = EclKW.create("NAME", 100, EclTypeEnum.ECL_FLOAT_TYPE) + src = EclKW("NAME", 100, EclDataType.ECL_FLOAT) copy = src.sub_copy(0, 2000) def copy_offset(): - src = EclKW.create("NAME", 100, EclTypeEnum.ECL_FLOAT_TYPE) + src = EclKW("NAME", 100, EclDataType.ECL_FLOAT) copy = src.sub_copy(200, 100) @@ -37,7 +37,7 @@ class KWTest(ExtendedTestCase): unrst_file = EclFile(unrst_file_path) size = 0 for kw in unrst_file: - size += kw.fortio_size + size += kw.fortIOSize() stat = os.stat(unrst_file_path) self.assertTrue(size == stat.st_size) @@ -51,16 +51,16 @@ class KWTest(ExtendedTestCase): swat = unrst_file["SWAT"][0] swat1 = swat.sub_copy(0, -1) - swat2 = swat.sub_copy(0, swat.size) + swat2 = swat.sub_copy(0, len(swat)) self.assertTrue(swat.equal(swat1)) self.assertTrue(swat.equal(swat2)) swat3 = swat.sub_copy(20000, 100, new_header="swat") - self.assertTrue(swat3.name == "swat") - self.assertTrue(swat3.size == 100) + self.assertTrue(swat3.getName() == "swat") + self.assertTrue(len(swat3) == 100) equal = True - for i in range(swat3.size): + for i in range(len(swat3)): if swat3[i] != swat[i + 20000]: equal = False self.assertTrue(equal) @@ -70,12 +70,12 @@ class KWTest(ExtendedTestCase): def test_equal(self): - kw1 = EclKW("TEST", 3, EclTypeEnum.ECL_CHAR_TYPE) + kw1 = EclKW("TEST", 3, EclDataType.ECL_CHAR) kw1[0] = "Test1" kw1[1] = "Test13" kw1[2] = "Test15" - kw2 = EclKW("TEST", 3, EclTypeEnum.ECL_CHAR_TYPE) + kw2 = EclKW("TEST", 3, EclDataType.ECL_CHAR) kw2[0] = "Test1" kw2[1] = "Test13" kw2[2] = "Test15" diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_restart_file.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_restart_file.py similarity index 95% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_restart_file.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_restart_file.py index 18095d2535..a46681b383 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_restart_file.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_restart_file.py @@ -16,7 +16,7 @@ import datetime from ert.test import ExtendedTestCase -from ert.ecl import Ecl3DKW , EclKW, EclTypeEnum, EclRestartFile , EclFile, FortIO, EclFileFlagEnum , EclGrid +from ert.ecl import Ecl3DKW , EclKW, EclRestartFile , EclFile, FortIO, EclFileFlagEnum , EclGrid class RestartFileTest(ExtendedTestCase): def setUp(self): diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_sum.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_sum.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_sum.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_sum.py diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_sum_tstep.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_sum_tstep.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_sum_tstep.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_sum_tstep.py diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_sum_vector.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_sum_vector.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_sum_vector.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_sum_vector.py diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_type.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_type.py new file mode 100644 index 0000000000..c700801874 --- /dev/null +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_type.py @@ -0,0 +1,93 @@ +from ert.test import TestAreaContext, ExtendedTestCase + +from ert.ecl import EclDataType, EclTypeEnum + +class EclDataTypeTest(ExtendedTestCase): + + # All of the below should list their elements in the same order as + # EclTypeEnum! + # [char, float, double, int, bool, mess] + + ELEMENT_SIZE = [9, 4, 8, 4, 4, 0] + + VERIFIERS = [ + EclDataType.is_char, + EclDataType.is_float, + EclDataType.is_double, + EclDataType.is_int, + EclDataType.is_bool, + EclDataType.is_mess + ] + + TYPE_NAMES = ["CHAR", "REAL", "DOUB", "INTE", "LOGI", "MESS"] + + def test_alloc_from_type(self): + for (ecl_type, element_size) in zip(EclTypeEnum.enums(), self.ELEMENT_SIZE): + data_type = EclDataType(ecl_type) + self.assertEqual(ecl_type, data_type.type) + self.assertEqual(element_size, data_type.element_size) + + def test_alloc(self): + for (ecl_type, element_size) in zip(EclTypeEnum.enums(), self.ELEMENT_SIZE): + data_type = EclDataType(ecl_type, element_size) + self.assertEqual(ecl_type, data_type.type) + self.assertEqual(element_size, data_type.element_size) + + def test_type_verifiers(self): + for (ecl_type, verifier) in zip(EclTypeEnum.enums(), self.VERIFIERS): + ecl_type = EclDataType(ecl_type) + self.assertTrue(verifier(ecl_type)) + + def test_get_type_name(self): + for (ecl_type, type_name) in zip(EclTypeEnum.enums(), self.TYPE_NAMES): + self.assertEqual(type_name, EclDataType(ecl_type).type_name) + + def test_initialization_validation(self): + invalid_args = [ + (None, 0, self.TYPE_NAMES[0]), + (1, None, self.TYPE_NAMES[0]), + (1, 0, self.TYPE_NAMES[0]), + (None, None, None), + (None, 12, None) + ] + + for inv_arg in invalid_args: + with self.assertRaises(ValueError): + EclDataType(inv_arg[0], inv_arg[1], inv_arg[2]) + + def test_create_from_type_name(self): + for (ecl_type, type_name) in zip(EclTypeEnum.enums(), self.TYPE_NAMES): + self.assertEqual(ecl_type, EclDataType.create_from_type_name(type_name).type) + + def test_is_numeric(self): + numeric_types = [ + EclTypeEnum.ECL_INT_TYPE, + EclTypeEnum.ECL_FLOAT_TYPE, + EclTypeEnum.ECL_DOUBLE_TYPE + ] + + for ecl_type in numeric_types: + self.assertTrue(EclDataType(ecl_type).is_numeric()) + + for ecl_type in set(EclTypeEnum.enums())-set(numeric_types): + self.assertFalse(EclDataType(ecl_type).is_numeric()) + + def test_equals(self): + for ecl_type in EclTypeEnum.enums(): + self.assertTrue( EclDataType(ecl_type).is_equal(EclDataType(ecl_type)) ) + self.assertEqual( EclDataType(ecl_type), EclDataType(ecl_type) ) + + for other in set(EclTypeEnum.enums())-set([ecl_type]): + self.assertFalse( EclDataType(ecl_type).is_equal(EclDataType(other)) ) + self.assertNotEqual( EclDataType(ecl_type), EclDataType(other) ) + + def test_hash(self): + all_types = set() + + for index, ecl_type in enumerate(EclTypeEnum.enums()): + all_types.add(EclDataType(ecl_type)) + self.assertEqual(index+1, len(all_types)) + + for index, ecl_type in enumerate(EclTypeEnum.enums()): + all_types.add(EclDataType(ecl_type)) + self.assertEqual(len(EclTypeEnum.enums()), len(all_types)) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_ecl_util.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_util.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/ecl/test_ecl_util.py rename to ThirdParty/Ert/python/tests/ecl/test_ecl_util.py diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_fault_blocks.py b/ThirdParty/Ert/python/tests/ecl/test_fault_blocks.py similarity index 91% rename from ThirdParty/Ert/python/tests/core/ecl/test_fault_blocks.py rename to ThirdParty/Ert/python/tests/ecl/test_fault_blocks.py index 192369f6b0..1f46ca524f 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_fault_blocks.py +++ b/ThirdParty/Ert/python/tests/ecl/test_fault_blocks.py @@ -16,8 +16,9 @@ # for more details. from __future__ import print_function from unittest import skipIf +import warnings -from ert.ecl import EclGrid, EclTypeEnum , EclKW , EclRegion +from ert.ecl import EclGrid, EclKW , EclRegion, EclDataType from ert.ecl.faults import FaultBlock, FaultBlockLayer, FaultBlockCell,FaultCollection from ert.geo import Polyline , CPolylineCollection from ert.test import ExtendedTestCase , TestAreaContext @@ -25,8 +26,8 @@ from ert.test import ExtendedTestCase , TestAreaContext class FaultBlockTest(ExtendedTestCase): def setUp(self): - self.grid = EclGrid.create_rectangular( (10,10,10) , (1,1,1) ) - self.kw = EclKW.create( "FAULTBLK" , self.grid.size , EclTypeEnum.ECL_INT_TYPE ) + self.grid = EclGrid.createRectangular( (10,10,10) , (1,1,1) ) + self.kw = EclKW( "FAULTBLK" , self.grid.getGlobalSize() , EclDataType.ECL_INT ) self.kw.assign( 1 ) reg = EclRegion( self.grid , False ) @@ -40,8 +41,8 @@ class FaultBlockTest(ExtendedTestCase): def test_fault_block(self): - grid = EclGrid.create_rectangular( (5,5,1) , (1,1,1) ) - kw = EclKW.create( "FAULTBLK" , grid.size , EclTypeEnum.ECL_INT_TYPE ) + grid = EclGrid.createRectangular( (5,5,1) , (1,1,1) ) + kw = EclKW( "FAULTBLK" , grid.getGlobalSize() , EclDataType.ECL_INT ) kw.assign( 0 ) for j in range(1,4): for i in range(1,4): @@ -56,7 +57,6 @@ class FaultBlockTest(ExtendedTestCase): self.assertEqual( len(block) , 9) self.assertEqual( layer , block.getParentLayer() ) - def test_get_ijk(self): with TestAreaContext("python/fault_block_layer/neighbour") as work_area: with open("kw.grdecl","w") as fileH: @@ -68,9 +68,9 @@ class FaultBlockTest(ExtendedTestCase): fileH.write("4 4 4 0 5\n") fileH.write("/\n") - kw = EclKW.read_grdecl(open("kw.grdecl") , "FAULTBLK" , ecl_type = EclTypeEnum.ECL_INT_TYPE) + kw = EclKW.read_grdecl(open("kw.grdecl") , "FAULTBLK" , ecl_type = EclDataType.ECL_INT) - grid = EclGrid.create_rectangular( (5,5,1) , (1,1,1) ) + grid = EclGrid.createRectangular( (5,5,1) , (1,1,1) ) layer = FaultBlockLayer( grid , 0 ) layer.loadKeyword( kw ) @@ -100,9 +100,9 @@ class FaultBlockTest(ExtendedTestCase): fileH.write("4 4 4 0 5\n") fileH.write("/\n") - kw = EclKW.read_grdecl(open("kw.grdecl") , "FAULTBLK" , ecl_type = EclTypeEnum.ECL_INT_TYPE) + kw = EclKW.read_grdecl(open("kw.grdecl") , "FAULTBLK" , ecl_type = EclDataType.ECL_INT) - grid = EclGrid.create_rectangular( (5,5,1) , (1,1,1) ) + grid = EclGrid.createRectangular( (5,5,1) , (1,1,1) ) layer = FaultBlockLayer( grid , 0 ) layer.loadKeyword( kw ) @@ -160,7 +160,7 @@ class FaultBlockTest(ExtendedTestCase): fileH.write("3 3 3 3 2 2 2 2 \n") fileH.write("/\n") - kw = EclKW.read_grdecl(open("faultblock.grdecl") , "FAULTBLK" , ecl_type = EclTypeEnum.ECL_INT_TYPE) + kw = EclKW.read_grdecl(open("faultblock.grdecl") , "FAULTBLK" , ecl_type = EclDataType.ECL_INT) with open("faults.grdecl" , "w") as f: f.write("FAULTS\n") f.write("\'FY\' 1 4 4 4 1 1 'Y' /\n") @@ -226,7 +226,7 @@ class FaultBlockTest(ExtendedTestCase): fileH.write("1 1 1 1 1 2 2 2 \n") fileH.write("/\n") - kw = EclKW.read_grdecl(open("faultblock.grdecl") , "FAULTBLK" , ecl_type = EclTypeEnum.ECL_INT_TYPE) + kw = EclKW.read_grdecl(open("faultblock.grdecl") , "FAULTBLK" , ecl_type = EclDataType.ECL_INT) with open("faults.grdecl" , "w") as f: f.write("FAULTS\n") f.write("\'FX\' 4 4 1 4 1 1 'X' /\n") @@ -252,8 +252,8 @@ class FaultBlockTest(ExtendedTestCase): def test_fault_block_edge(self): - grid = EclGrid.create_rectangular( (5,5,1) , (1,1,1) ) - kw = EclKW.create( "FAULTBLK" , grid.size , EclTypeEnum.ECL_INT_TYPE ) + grid = EclGrid.createRectangular( (5,5,1) , (1,1,1) ) + kw = EclKW( "FAULTBLK" , grid.getGlobalSize() , EclDataType.ECL_INT ) kw.assign( 0 ) for j in range(1,4): for i in range(1,4): @@ -271,12 +271,12 @@ class FaultBlockTest(ExtendedTestCase): layer = FaultBlockLayer( self.grid , -1 ) with self.assertRaises(ValueError): - layer = FaultBlockLayer( self.grid , self.grid.size ) + layer = FaultBlockLayer( self.grid , self.grid.getGlobalSize() ) layer = FaultBlockLayer( self.grid , 1 ) self.assertEqual( 1 , layer.getK() ) - kw = EclKW.create( "FAULTBLK" , self.grid.size , EclTypeEnum.ECL_FLOAT_TYPE ) + kw = EclKW( "FAULTBLK" , self.grid.getGlobalSize() , EclDataType.ECL_FLOAT ) with self.assertRaises(ValueError): layer.scanKeyword( kw ) @@ -358,7 +358,7 @@ class FaultBlockTest(ExtendedTestCase): def test_add_polyline_barrier1(self): - grid = EclGrid.create_rectangular( (4,1,1) , (1,1,1) ) + grid = EclGrid.createRectangular( (4,1,1) , (1,1,1) ) layer = FaultBlockLayer( self.grid , 0 ) polyline = Polyline( init_points = [ (1.99 , 0.001) , (2.01 , 0.99)]) @@ -376,7 +376,7 @@ class FaultBlockTest(ExtendedTestCase): def test_add_polyline_barrier2(self): - grid = EclGrid.create_rectangular( (10,10,1) , (1,1,1) ) + grid = EclGrid.createRectangular( (10,10,1) , (1,1,1) ) layer = FaultBlockLayer( self.grid , 0 ) polyline = Polyline( init_points = [ (0.1 , 0.9) , (8.9,0.9) , (8.9,8.9) ]) @@ -407,11 +407,11 @@ class FaultBlockTest(ExtendedTestCase): def test_fault_block_layer_export(self): layer = FaultBlockLayer( self.grid , 1 ) - kw1 = EclKW.create( "FAULTBLK" , self.grid.size + 1 , EclTypeEnum.ECL_INT_TYPE ) + kw1 = EclKW( "FAULTBLK" , self.grid.getGlobalSize() + 1 , EclDataType.ECL_INT ) with self.assertRaises(ValueError): layer.exportKeyword( kw1 ) - kw2 = EclKW.create( "FAULTBLK" , self.grid.size , EclTypeEnum.ECL_FLOAT_TYPE ) + kw2 = EclKW( "FAULTBLK" , self.grid.getGlobalSize() , EclDataType.ECL_FLOAT ) with self.assertRaises(TypeError): layer.exportKeyword(kw2) @@ -436,7 +436,7 @@ class FaultBlockTest(ExtendedTestCase): fileH.write("/\n") - kw = EclKW.read_grdecl(open("faultblock.grdecl") , "FAULTBLK" , ecl_type = EclTypeEnum.ECL_INT_TYPE) + kw = EclKW.read_grdecl(open("faultblock.grdecl") , "FAULTBLK" , ecl_type = EclDataType.ECL_INT) with open("faults.grdecl" , "w") as f: f.write("FAULTS\n") f.write("\'FX\' 4 4 1 4 1 1 'X' /\n") diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_fault_blocks_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_fault_blocks_statoil.py similarity index 94% rename from ThirdParty/Ert/python/tests/core/ecl/test_fault_blocks_statoil.py rename to ThirdParty/Ert/python/tests/ecl/test_fault_blocks_statoil.py index 0225105108..9c7d88f7f8 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_fault_blocks_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_fault_blocks_statoil.py @@ -19,7 +19,7 @@ try: except ImportError: from unittest import skipIf -from ert.ecl import EclGrid, EclTypeEnum , EclKW +from ert.ecl import EclGrid, EclDataType , EclKW from ert.test import ExtendedTestCase from ert.ecl.faults import FaultBlock, FaultBlockLayer @@ -27,7 +27,7 @@ class FaultBlockTest(ExtendedTestCase): def setUp(self): self.grid = EclGrid( self.createTestPath("Statoil/ECLIPSE/Mariner/MARINER.EGRID")) fileH = open( self.createTestPath("Statoil/ECLIPSE/Mariner/faultblock.grdecl") ) - self.kw = EclKW.read_grdecl( fileH , "FAULTBLK" , ecl_type = EclTypeEnum.ECL_INT_TYPE ) + self.kw = EclKW.read_grdecl( fileH , "FAULTBLK" , ecl_type = EclDataType.ECL_INT ) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_faults.py b/ThirdParty/Ert/python/tests/ecl/test_faults.py similarity index 95% rename from ThirdParty/Ert/python/tests/core/ecl/test_faults.py rename to ThirdParty/Ert/python/tests/ecl/test_faults.py index 0407f4a65b..0a2f1873a7 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_faults.py +++ b/ThirdParty/Ert/python/tests/ecl/test_faults.py @@ -20,7 +20,7 @@ import time from ert import util from ert.ecl.faults import FaultCollection, Fault, FaultLine, FaultSegment,FaultBlockLayer -from ert.ecl import EclGrid, EclKW, EclTypeEnum +from ert.ecl import EclGrid, EclKW, EclDataType from ert.test import ExtendedTestCase, TestAreaContext from ert.geo import Polyline , CPolyline @@ -28,8 +28,8 @@ from ert.geo import Polyline , CPolyline class FaultTest(ExtendedTestCase): @classmethod def setUpClass(cls): - cls.grid = EclGrid.create_rectangular( (151,100,50) , (1,1,1)) - + cls.grid = EclGrid.createRectangular( (151,100,50) , (1,1,1)) + def setUp(self): self.faults1 = self.createTestPath("local/ECLIPSE/FAULTS/fault1.grdecl") self.faults2 = self.createTestPath("local/ECLIPSE/FAULTS/fault2.grdecl") @@ -39,7 +39,7 @@ class FaultTest(ExtendedTestCase): nx = 10 ny = 10 nz = 10 - grid = EclGrid.create_rectangular( (nx,ny,nz) , (0.1,0.1,0.1)) + grid = EclGrid.createRectangular( (nx,ny,nz) , (0.1,0.1,0.1)) f = Fault(grid , "F") f.addRecord(0 , 1 , 0 , 0 , 0,0 , "Y-") f.addRecord(2 , 2 , 0 , 1 , 0,0 , "X-") @@ -119,7 +119,7 @@ class FaultTest(ExtendedTestCase): nx = 10 ny = 10 nz = 2 - grid = EclGrid.create_rectangular( (nx,ny,nz) , (0.1,0.1,0.1)) + grid = EclGrid.createRectangular( (nx,ny,nz) , (0.1,0.1,0.1)) fl = FaultLine(grid , 0) C1 = (nx + 1) * 5 + 3 C2 = C1 + 2 @@ -204,7 +204,7 @@ class FaultTest(ExtendedTestCase): def test_connect_faults(self): - grid = EclGrid.create_rectangular( (100,100,10) , (1,1,1)) + grid = EclGrid.createRectangular( (100,100,10) , (1,1,1)) # Fault1 Fault4 # | | @@ -359,7 +359,7 @@ class FaultTest(ExtendedTestCase): def test_join_faults(self): - grid = EclGrid.create_rectangular( (100,100,10) , (1,1,1)) + grid = EclGrid.createRectangular( (100,100,10) , (1,1,1)) # Fault1 Fault4 # | | @@ -391,7 +391,7 @@ class FaultTest(ExtendedTestCase): def test_contact(self): - grid = EclGrid.create_rectangular( (100,100,10) , (1,1,1)) + grid = EclGrid.createRectangular( (100,100,10) , (1,1,1)) # Fault1 Fault4 # | | @@ -500,7 +500,7 @@ class FaultTest(ExtendedTestCase): nx = 120 ny = 60 nz = 43 - grid = EclGrid.create_rectangular( (nx , ny , nz) , (1,1,1) ) + grid = EclGrid.createRectangular( (nx , ny , nz) , (1,1,1) ) with TestAreaContext("python/faults/line_order"): with open("faults.grdecl" , "w") as f: f.write("""FAULTS @@ -540,7 +540,7 @@ class FaultTest(ExtendedTestCase): nx = 10 ny = 8 nz = 7 - grid = EclGrid.create_rectangular( (nx , ny , nz) , (1,1,1) ) + grid = EclGrid.createRectangular( (nx , ny , nz) , (1,1,1) ) faults_file = self.createTestPath("local/ECLIPSE/FAULTS/faults_nb.grdecl") faults = FaultCollection( grid , faults_file ) @@ -601,7 +601,7 @@ class FaultTest(ExtendedTestCase): def test_polyline_intersection(self): - grid = EclGrid.create_rectangular( (100,100,10) , (0.25 , 0.25 , 1)) + grid = EclGrid.createRectangular( (100,100,10) , (0.25 , 0.25 , 1)) # Fault1 Fault4 # | | @@ -642,7 +642,7 @@ class FaultTest(ExtendedTestCase): nx = 10 ny = 10 nz = 1 - grid = EclGrid.create_rectangular( (nx , ny , nz) , (1,1,1) ) + grid = EclGrid.createRectangular( (nx , ny , nz) , (1,1,1) ) with TestAreaContext("python/faults/line_order"): with open("faults.grdecl" , "w") as f: f.write("""FAULTS @@ -660,7 +660,7 @@ class FaultTest(ExtendedTestCase): def test_extend_to_polyline(self): - grid = EclGrid.create_rectangular( (3,3,1) , (1 , 1 , 1)) + grid = EclGrid.createRectangular( (3,3,1) , (1 , 1 , 1)) # o o o o # @@ -688,7 +688,7 @@ class FaultTest(ExtendedTestCase): def test_extend_polyline_on(self): - grid = EclGrid.create_rectangular( (3,3,1) , (1 , 1 , 1)) + grid = EclGrid.createRectangular( (3,3,1) , (1 , 1 , 1)) # o o o o # @@ -720,13 +720,13 @@ class FaultTest(ExtendedTestCase): def test_stepped(self): - grid = EclGrid.create_rectangular( (6,1,4) , (1,1,1)) + grid = EclGrid.createRectangular( (6,1,4) , (1,1,1)) f = Fault(grid , "F") f.addRecord(4,4,0,0,0,1,"X") f.addRecord(2,2,0,0,1,1,"Z") f.addRecord(1,1,0,0,2,3,"X") - block_kw = EclKW.create("FAULTBLK" , grid.getGlobalSize() , EclTypeEnum.ECL_INT_TYPE) + block_kw = EclKW("FAULTBLK" , grid.getGlobalSize() , EclDataType.ECL_INT) block_kw.assign(1) block_kw[5] = 2 block_kw[11] = 2 @@ -761,7 +761,7 @@ class FaultTest(ExtendedTestCase): def test_connectWithPolyline(self): - grid = EclGrid.create_rectangular( (4,4,1) , (1 , 1 , 1)) + grid = EclGrid.createRectangular( (4,4,1) , (1 , 1 , 1)) # o o o o o diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_fortio.py b/ThirdParty/Ert/python/tests/ecl/test_fortio.py similarity index 89% rename from ThirdParty/Ert/python/tests/core/ecl/test_fortio.py rename to ThirdParty/Ert/python/tests/ecl/test_fortio.py index 36a635e8fb..9ef02be191 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_fortio.py +++ b/ThirdParty/Ert/python/tests/ecl/test_fortio.py @@ -16,7 +16,7 @@ # for more details. import os from random import randint -from ert.ecl import FortIO, EclTypeEnum, EclKW , openFortIO, EclFile +from ert.ecl import FortIO, EclDataType, EclKW , openFortIO, EclFile from ert.test import ExtendedTestCase, TestAreaContext @@ -37,8 +37,8 @@ class FortIOTest(ExtendedTestCase): f = FortIO("odes_not_exist", FortIO.READ_MODE) def test_kw(self): - kw1 = EclKW.create("KW1", 2, EclTypeEnum.ECL_INT_TYPE) - kw2 = EclKW.create("KW2", 2, EclTypeEnum.ECL_INT_TYPE) + kw1 = EclKW("KW1", 2, EclDataType.ECL_INT) + kw2 = EclKW("KW2", 2, EclDataType.ECL_INT) kw1[0] = 99 kw1[1] = 77 @@ -61,8 +61,8 @@ class FortIOTest(ExtendedTestCase): def test_truncate(self): - kw1 = EclKW.create("KW1", 2, EclTypeEnum.ECL_INT_TYPE) - kw2 = EclKW.create("KW2", 2, EclTypeEnum.ECL_INT_TYPE) + kw1 = EclKW("KW1", 2, EclDataType.ECL_INT) + kw2 = EclKW("KW2", 2, EclDataType.ECL_INT) kw1[0] = 99 kw1[1] = 77 @@ -110,7 +110,7 @@ class FortIOTest(ExtendedTestCase): def test_context(self): with TestAreaContext("python/fortio/context") as t: - kw1 = EclKW.create("KW" , 2456 , EclTypeEnum.ECL_FLOAT_TYPE) + kw1 = EclKW("KW" , 2456 , EclDataType.ECL_FLOAT) for i in range(len(kw1)): kw1[i] = randint(0,1000) @@ -128,7 +128,7 @@ class FortIOTest(ExtendedTestCase): def test_is_fortran_file(self): with TestAreaContext("python/fortio/guess"): - kw1 = EclKW.create("KW" , 12345 , EclTypeEnum.ECL_FLOAT_TYPE) + kw1 = EclKW("KW" , 12345 , EclDataType.ECL_FLOAT) with openFortIO("fortran_file" , mode = FortIO.WRITE_MODE) as f: kw1.fwrite( f ) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_geertsma.py b/ThirdParty/Ert/python/tests/ecl/test_geertsma.py similarity index 83% rename from ThirdParty/Ert/python/tests/core/ecl/test_geertsma.py rename to ThirdParty/Ert/python/tests/ecl/test_geertsma.py index f7665196e9..1b85f97e9a 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_geertsma.py +++ b/ThirdParty/Ert/python/tests/ecl/test_geertsma.py @@ -1,5 +1,5 @@ import datetime -from ert.ecl import EclGrid, EclKW, EclTypeEnum, openFortIO, FortIO, EclFile, EclSubsidence +from ert.ecl import EclGrid, EclKW, EclDataType, openFortIO, FortIO, EclFile, EclSubsidence from ert.test import ExtendedTestCase , TestAreaContext @@ -7,7 +7,7 @@ import numpy as np def create_init(grid, case): - poro = EclKW("PORO", grid.getNumActive(), EclTypeEnum.ECL_FLOAT_TYPE) + poro = EclKW("PORO", grid.getNumActive(), EclDataType.ECL_FLOAT) porv = poro.copy() porv.setName("PORV") for g in range(grid.getGlobalSize()): @@ -20,13 +20,13 @@ def create_init(grid, case): def create_restart(grid, case, p1, p2=None): with openFortIO("%s.UNRST" % case, mode=FortIO.WRITE_MODE) as f: - seq_hdr = EclKW("SEQNUM", 1, EclTypeEnum.ECL_FLOAT_TYPE) + seq_hdr = EclKW("SEQNUM", 1, EclDataType.ECL_FLOAT) seq_hdr[0] = 10 - p = EclKW("PRESSURE", grid.getNumActive(), EclTypeEnum.ECL_FLOAT_TYPE) + p = EclKW("PRESSURE", grid.getNumActive(), EclDataType.ECL_FLOAT) for i in range(len(p1)): p[i] = p1[i] - header = EclKW("INTEHEAD", 67, EclTypeEnum.ECL_INT_TYPE) + header = EclKW("INTEHEAD", 67, EclDataType.ECL_INT) header[64] = 1 header[65] = 1 header[66] = 2000 @@ -72,12 +72,12 @@ class GeertsmaTest(ExtendedTestCase): receiver = (1000, 1000, 0) dz = subsidence.evalGeertsma("S1", None, receiver, youngs_modulus, poisson_ratio, seabed) - np.testing.assert_almost_equal(dz, -3.944214576168326e-09) + np.testing.assert_almost_equal(dz, 3.944214576168326e-09) receiver = (1000, 1000, topres - seabed - above) dz = subsidence.evalGeertsma("S1", None, receiver, youngs_modulus, poisson_ratio, seabed) - np.testing.assert_almost_equal(dz, -5.8160298201497136e-08) + np.testing.assert_almost_equal(dz, 5.8160298201497136e-08) @staticmethod def test_geertsma_kernel_2_source_points_2_vintages(): @@ -105,15 +105,15 @@ class GeertsmaTest(ExtendedTestCase): receiver = (1000, 1000, 0) dz1 = subsidence.evalGeertsma("S1", None, receiver, youngs_modulus, poisson_ratio, seabed) - np.testing.assert_almost_equal(dz1, -8.65322541521704e-07) + np.testing.assert_almost_equal(dz1, 8.65322541521704e-07) dz2 = subsidence.evalGeertsma("S2", None, receiver, youngs_modulus, poisson_ratio, seabed) - np.testing.assert_almost_equal(dz2, -2.275556615015282e-06) + np.testing.assert_almost_equal(dz2, 2.275556615015282e-06) - np.testing.assert_almost_equal(dz2-dz1, -1.4102340734935779e-06) + np.testing.assert_almost_equal(dz1-dz2, -1.4102340734935779e-06) dz = subsidence.evalGeertsma("S1", "S2", receiver, youngs_modulus, poisson_ratio, seabed) - np.testing.assert_almost_equal(dz, -1.4102340734935779e-06) + np.testing.assert_almost_equal(dz, dz1-dz2) @staticmethod def test_geertsma_kernel_seabed(): @@ -139,6 +139,6 @@ class GeertsmaTest(ExtendedTestCase): receiver = (1000, 1000, topres - seabed - above) dz = subsidence.evalGeertsma("S1", None, receiver, youngs_modulus, poisson_ratio, seabed) - np.testing.assert_almost_equal(dz, -5.819790154474284e-08) + np.testing.assert_almost_equal(dz, 5.819790154474284e-08) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_grav.py b/ThirdParty/Ert/python/tests/ecl/test_grav.py similarity index 79% rename from ThirdParty/Ert/python/tests/core/ecl/test_grav.py rename to ThirdParty/Ert/python/tests/ecl/test_grav.py index 816b059cfc..8cc10d13fa 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_grav.py +++ b/ThirdParty/Ert/python/tests/ecl/test_grav.py @@ -1,5 +1,5 @@ import time -from ert.ecl import EclGrav, EclKW, EclGrid, EclFile, EclTypeEnum, openFortIO, FortIO +from ert.ecl import EclGrav, EclKW, EclGrid, EclFile, EclDataType, openFortIO, FortIO from ert.test import ExtendedTestCase , TestAreaContext @@ -14,7 +14,7 @@ class EclGravTest(ExtendedTestCase): # The init file created here only contains a PORO field. More # properties must be added to this before it can be used for # any usefull gravity calculations. - poro = EclKW( "PORO" , self.grid.getGlobalSize() , EclTypeEnum.ECL_FLOAT_TYPE ) + poro = EclKW( "PORO" , self.grid.getGlobalSize() , EclDataType.ECL_FLOAT ) with TestAreaContext("grav_init"): with openFortIO( "TEST.INIT" , mode = FortIO.WRITE_MODE ) as f: poro.fwrite( f ) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_grdecl.py b/ThirdParty/Ert/python/tests/ecl/test_grdecl.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/ecl/test_grdecl.py rename to ThirdParty/Ert/python/tests/ecl/test_grdecl.py diff --git a/ThirdParty/Ert/python/tests/ecl/test_grid.py b/ThirdParty/Ert/python/tests/ecl/test_grid.py new file mode 100644 index 0000000000..e7ce0ebdb9 --- /dev/null +++ b/ThirdParty/Ert/python/tests/ecl/test_grid.py @@ -0,0 +1,553 @@ +#!/usr/bin/env python +# Copyright (C) 2014 Statoil ASA, Norway. +# +# The file 'test_grid.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. +import os.path +from unittest import skipIf +import time +import itertools +from numpy import linspace + +from ert.util import IntVector +from ert.ecl import EclGrid, EclKW, EclDataType, EclUnitTypeEnum, EclFile +from ert.ecl import EclGridGenerator as GridGen +from ert.ecl.faults import Layer , FaultCollection +from ert.test import ExtendedTestCase , TestAreaContext + +# This dict is used to verify that corners are mapped to the correct +# cell with respect to containment. +CORNER_HOME = { + (0, 0, 0) : 0, (0, 0, 1) : 9, (0, 0, 2) : 18, (0, 0, 3) : 18, + (0, 1, 0) : 3, (0, 1, 1) : 12, (0, 1, 2) : 21, (0, 1, 3) : 21, + (0, 2, 0) : 6, (0, 2, 1) : 15, (0, 2, 2) : 24, (0, 2, 3) : 24, + (0, 3, 0) : 6, (0, 3, 1) : 15, (0, 3, 2) : 24, (0, 3, 3) : 24, + (1, 0, 0) : 1, (1, 0, 1) : 10, (1, 0, 2) : 19, (1, 0, 3) : 19, + (1, 1, 0) : 4, (1, 1, 1) : 13, (1, 1, 2) : 22, (1, 1, 3) : 22, + (1, 2, 0) : 7, (1, 2, 1) : 16, (1, 2, 2) : 25, (1, 2, 3) : 25, + (1, 3, 0) : 7, (1, 3, 1) : 16, (1, 3, 2) : 25, (1, 3, 3) : 25, + (2, 0, 0) : 2, (2, 0, 1) : 11, (2, 0, 2) : 20, (2, 0, 3) : 20, + (2, 1, 0) : 5, (2, 1, 1) : 14, (2, 1, 2) : 23, (2, 1, 3) : 23, + (2, 2, 0) : 8, (2, 2, 1) : 17, (2, 2, 2) : 26, (2, 2, 3) : 26, + (2, 3, 0) : 8, (2, 3, 1) : 17, (2, 3, 2) : 26, (2, 3, 3) : 26, + (3, 0, 0) : 2, (3, 0, 1) : 11, (3, 0, 2) : 20, (3, 0, 3) : 20, + (3, 1, 0) : 5, (3, 1, 1) : 14, (3, 1, 2) : 23, (3, 1, 3) : 23, + (3, 2, 0) : 8, (3, 2, 1) : 17, (3, 2, 2) : 26, (3, 2, 3) : 26, + (3, 3, 0) : 8, (3, 3, 1) : 17, (3, 3, 2) : 26, (3, 3, 3) : 26 +} + +def createVolumeTestGridBase(dim, dV, offset=1): + return [ + GridGen.createGrid(dim, dV, offset=0), + GridGen.createGrid(dim, dV, offset=offset), + GridGen.createGrid(dim, dV, offset=offset, irregular_offset=True), + GridGen.createGrid(dim, dV, offset=offset, concave=True), + GridGen.createGrid(dim, dV, offset=offset, irregular=True), + GridGen.createGrid(dim, dV, offset=offset, concave=True, irregular=True), + GridGen.createGrid(dim, dV, offset=offset, irregular_offset=True, concave=True), + GridGen.createGrid(dim, dV, offset=0, faults=True), + GridGen.createGrid(dim, dV, offset=offset, faults=True), + GridGen.createGrid(dim, dV, escape_origo_shift=(100, 100, 0), scale=2), + GridGen.createGrid(dim, dV, escape_origo_shift=(100, 100, 0), scale=0.5), + GridGen.createGrid(dim, dV, escape_origo_shift=(100, 100, 0), translation=(50,50,0)), + GridGen.createGrid(dim, dV, escape_origo_shift=(100, 100, 0), rotate=True), + GridGen.createGrid(dim, dV, escape_origo_shift=(100, 100, 0), misalign=True), + GridGen.createGrid(dim, dV, offset=offset, escape_origo_shift=(100, 100, 0), + irregular_offset=True, concave=True, irregular=True, + scale=1.5, translation=(5,5,0), rotate=True, + misalign=True) + ] + +def createContainmentTestBase(): + return [ + (3, GridGen.createGrid((6,6,6), (1,1,1), offset=1)), + (10, GridGen.createGrid((3,3,3), (1,1,1), offset=1, concave=True)), + (4, GridGen.createGrid((10,10,1), (1,1,1), offset=0., misalign=True)), + (3, + GridGen.createGrid((6,6,6), (1,1,1), offset=0., + escape_origo_shift=(100, 100, 0), + irregular_offset=True, concave=True, irregular=True, + scale=1.5, translation=(5,5,0), + misalign=True + ) + ) + ] + +def getMinMaxValue(grid): + corners = [ + grid.getCellCorner(i, cell) + for i in range(8) + for cell in range(grid.getGlobalSize()) + ] + + return [(min(values), max(values)) for values in zip(*corners)] + +def createWrapperGrid(grid): + """ + Creates a grid that occupies the same space as the given grid, + but that consists of a single cell. + """ + + x, y, z = grid.getNX()-1, grid.getNY()-1, grid.getNZ()-1 + corner_pos = [ + (0, 0, 0), (x, 0, 0), (0, y, 0), (x, y, 0), + (0, 0, z), (x, 0, z), (0, y, z), (x, y, z) + ] + + corners = [ + grid.getCellCorner(i, ijk=pos) + for i, pos in enumerate(corner_pos) + ] + + return GridGen.createSingleCellGrid(corners) + +def average(points): + p = reduce(lambda a,b: (a[0]+b[0], a[1]+b[1], a[2]+b[2]), points) + return [elem/float(len(points)) for elem in p] + +# This test class should only have test cases which do not require +# external test data. Tests involving Statoil test data are in the +# test_grid_statoil module. +class GridTest(ExtendedTestCase): + + def test_oom_grid(self): + nx = 2000 + ny = 2000 + nz = 2000 + + with self.assertRaises(MemoryError): + grid = GridGen.createRectangular( (nx,ny,nz), (1,1,1)) + + + + def test_posXYEdge(self): + nx = 10 + ny = 11 + grid = GridGen.createRectangular( (nx,ny,1) , (1,1,1) ) + self.assertEqual( grid.findCellCornerXY(0,0,0) , 0 ) + self.assertEqual( grid.findCellCornerXY(nx,0,0) , nx) + self.assertEqual( grid.findCellCornerXY(0 , ny , 0) , (nx + 1 ) * ny ) + self.assertEqual( grid.findCellCornerXY(nx,ny,0) , (nx + 1 ) * (ny + 1) - 1) + + self.assertEqual( grid.findCellCornerXY(0.25,0,0) , 0 ) + self.assertEqual( grid.findCellCornerXY(0,0.25,0) , 0 ) + + self.assertEqual( grid.findCellCornerXY(nx - 0.25,0,0) , nx ) + self.assertEqual( grid.findCellCornerXY(nx , 0.25,0) , nx ) + + self.assertEqual( grid.findCellCornerXY(0 , ny - 0.25, 0) , (nx + 1 ) * ny ) + self.assertEqual( grid.findCellCornerXY(0.25 , ny , 0) , (nx + 1 ) * ny ) + + self.assertEqual( grid.findCellCornerXY(nx -0.25 ,ny,0) , (nx + 1 ) * (ny + 1) - 1) + self.assertEqual( grid.findCellCornerXY(nx , ny - 0.25,0) , (nx + 1 ) * (ny + 1) - 1) + + + def test_dims(self): + grid = GridGen.createRectangular( (10,20,30) , (1,1,1) ) + self.assertEqual( grid.getNX() , 10 ) + self.assertEqual( grid.getNY() , 20 ) + self.assertEqual( grid.getNZ() , 30 ) + self.assertEqual( grid.getGlobalSize() , 30*10*20 ) + + self.assertEqual( grid.getDims() , (10,20,30,6000) ) + + + + def test_create(self): + with self.assertRaises(ValueError): + grid = GridGen.createRectangular( (10,20,30) , (1,1,1) , actnum = [0,1,1,2]) + + with self.assertRaises(ValueError): + grid = GridGen.createRectangular( (10,20,30) , (1,1,1) , actnum = IntVector(initial_size = 10)) + + actnum = IntVector(default_value = 1 , initial_size = 6000) + actnum[0] = 0 + actnum[1] = 0 + grid = GridGen.createRectangular( (10,20,30) , (1,1,1) , actnum = actnum) + self.assertEqual( grid.getNumActive( ) , 30*20*10 - 2) + + def test_repr_and_name(self): + grid = GridGen.createRectangular((2,2,2), (10,10,10), actnum=[0,0,0,0,1,1,1,1]) + pfx = 'EclGrid(' + rep = repr(grid) + self.assertEqual(pfx, rep[:len(pfx)]) + self.assertEqual(type(rep), type('')) + self.assertEqual(type(grid.getName()), type('')) + with TestAreaContext("python/ecl_grid/repr"): + grid.save_EGRID("CASE.EGRID") + g2 = EclGrid("CASE.EGRID") + r2 = repr(g2) + self.assertEqual(pfx, r2[:len(pfx)]) + self.assertEqual(type(r2), type('')) + self.assertEqual(type(g2.getName()), type('')) + + def test_node_pos(self): + grid = GridGen.createRectangular( (10,20,30) , (1,1,1) ) + with self.assertRaises(IndexError): + grid.getNodePos(-1,0,0) + + with self.assertRaises(IndexError): + grid.getNodePos(11,0,0) + + p0 = grid.getNodePos(0,0,0) + self.assertEqual( p0 , (0,0,0)) + + p7 = grid.getNodePos(10,20,30) + self.assertEqual( p7 , (10,20,30)) + + + def test_truncated_file(self): + grid = GridGen.createRectangular( (10,20,30) , (1,1,1) ) + with TestAreaContext("python/ecl_grid/truncated"): + grid.save_EGRID( "TEST.EGRID") + + size = os.path.getsize( "TEST.EGRID") + with open("TEST.EGRID" , "r+") as f: + f.truncate( size / 2 ) + + with self.assertRaises(IOError): + EclGrid("TEST.EGRID") + + def test_posXY1(self): + nx = 4 + ny = 1 + nz = 1 + grid = GridGen.createRectangular( (nx,ny,nz) , (1,1,1) ) + (i,j) = grid.findCellXY( 0.5 , 0.5, 0 ) + self.assertEqual(i , 0) + self.assertEqual(j , 0) + + (i,j) = grid.findCellXY( 3.5 , 0.5, 0 ) + self.assertEqual(i , 3) + self.assertEqual(j , 0) + + + def test_init_ACTNUM(self): + nx = 10 + ny = 23 + nz = 7 + grid = GridGen.createRectangular( (nx,ny,nz) , (1,1,1) ) + actnum = grid.exportACTNUM() + + self.assertEqual( len(actnum) , nx*ny*nz ) + self.assertEqual( actnum[0] , 1 ) + self.assertEqual( actnum[nx*ny*nz - 1] , 1 ) + + actnum_kw = grid.exportACTNUMKw( ) + self.assertEqual(len(actnum_kw) , len(actnum)) + for a1,a2 in zip(actnum, actnum_kw): + self.assertEqual(a1, a2) + + + def test_posXY(self): + nx = 10 + ny = 23 + nz = 7 + grid = GridGen.createRectangular( (nx,ny,nz) , (1,1,1) ) + with self.assertRaises(IndexError): + grid.findCellXY( 1 , 1, -1 ) + + with self.assertRaises(IndexError): + grid.findCellXY( 1 , 1, nz + 1 ) + + with self.assertRaises(ValueError): + grid.findCellXY(15 , 78 , 2) + + + i,j = grid.findCellXY( 1.5 , 1.5 , 2 ) + self.assertEqual(i , 1) + self.assertEqual(j , 1) + + + for i in range(nx): + for j in range(ny): + p = grid.findCellXY(i + 0.5 , j+ 0.5 , 0) + self.assertEqual( p[0] , i ) + self.assertEqual( p[1] , j ) + + c = grid.findCellCornerXY( 0.10 , 0.10 , 0 ) + self.assertEqual(c , 0) + + c = grid.findCellCornerXY( 0.90 , 0.90 , 0 ) + self.assertEqual( c , (nx + 1) + 1 ) + + c = grid.findCellCornerXY( 0.10 , 0.90 , 0 ) + self.assertEqual( c , (nx + 1) ) + + c = grid.findCellCornerXY( 0.90 , 0.90 , 0 ) + self.assertEqual( c , (nx + 1) + 1 ) + + c = grid.findCellCornerXY( 0.90 , 0.10 , 0 ) + self.assertEqual( c , 1 ) + + def test_compressed_copy(self): + nx = 10 + ny = 10 + nz = 10 + grid = GridGen.createRectangular( (nx,ny,nz) , (1,1,1) ) + kw1 = EclKW("KW" , 1001 , EclDataType.ECL_INT ) + with self.assertRaises(ValueError): + cp = grid.compressedKWCopy( kw1 ) + + + def test_dxdydz(self): + nx = 10 + ny = 10 + nz = 10 + grid = GridGen.createRectangular( (nx,ny,nz) , (2,3,4) ) + + (dx,dy,dz) = grid.getCellDims( active_index = 0 ) + self.assertEqual( dx , 2 ) + self.assertEqual( dy , 3 ) + self.assertEqual( dz , 4 ) + + def test_numpy3D(self): + nx = 10 + ny = 7 + nz = 5 + grid = GridGen.createRectangular((nx,ny,nz) , (1,1,1)) + kw = EclKW( "SWAT" , nx*ny*nz , EclDataType.ECL_FLOAT ) + numpy_3d = grid.create3D( kw ) + + def test_len(self): + nx = 10 + ny = 11 + nz = 12 + actnum = EclKW( "ACTNUM" , nx*ny*nz , EclDataType.ECL_INT ) + actnum[0] = 1 + actnum[1] = 1 + actnum[2] = 1 + actnum[3] = 1 + + grid = GridGen.createRectangular( (nx,ny,nz) , (1,1,1), actnum = actnum) + self.assertEqual( len(grid) , nx*ny*nz ) + self.assertEqual( grid.getNumActive( ) , 4 ) + + + def test_output_units(self): + n = 10 + a = 1 + grid = GridGen.createRectangular( (n,n,n), (a,a,a)) + + with TestAreaContext("python/ecl_grid/units"): + grid.save_EGRID( "CASE.EGRID" , output_unit = EclUnitTypeEnum.ECL_FIELD_UNITS ) + f = EclFile("CASE.EGRID") + g = f["GRIDUNIT"][0] + self.assertEqual( g[0].strip( ) , "FEET" ) + g2 = EclGrid("CASE.EGRID") + self.assertFloatEqual( g2.cell_volume( global_index = 0 ) , 3.28084*3.28084*3.28084) + + + grid.save_EGRID( "CASE.EGRID" ) + f = EclFile("CASE.EGRID") + g = f["GRIDUNIT"][0] + self.assertEqual( g[0].strip( ) , "METRES" ) + + grid.save_EGRID( "CASE.EGRID" , output_unit = EclUnitTypeEnum.ECL_LAB_UNITS) + f = EclFile("CASE.EGRID") + g = f["GRIDUNIT"][0] + self.assertEqual( g[0].strip() , "CM" ) + g2 = EclGrid("CASE.EGRID") + self.assertFloatEqual( g2.cell_volume( global_index = 0 ) , 100*100*100 ) + + def test_volume(self): + dim = (10,10,10) + dV = (2,2,2) + + grids = createVolumeTestGridBase(dim, dV) + for grid in grids: + tot_vol = createWrapperGrid(grid).cell_volume(0) + cell_volumes = [grid.cell_volume(i) for i in range(grid.getGlobalSize())] + self.assertTrue(min(cell_volumes) >= 0) + self.assertFloatEqual(sum(cell_volumes), tot_vol) + + def test_unique_containment(self): + test_base = createContainmentTestBase() + + for steps_per_unit, grid in test_base: + wgrid = createWrapperGrid(grid) + + (xmin, xmax), (ymin, ymax), (zmin, zmax) = getMinMaxValue(wgrid) + x_space = linspace(xmin-1, xmax+1, (xmax-xmin+2)*steps_per_unit+1) + y_space = linspace(ymin-1, ymax+1, (ymax-ymin+2)*steps_per_unit+1) + z_space = linspace(zmin-1, zmax+1, (zmax-zmin+2)*steps_per_unit+1) + + for x, y, z in itertools.product(x_space, y_space, z_space): + hits = [ + grid.cell_contains(x, y, z, i) + for i in range(grid.getGlobalSize()) + ].count(True) + + self.assertTrue(hits in [0, 1]) + + self.assertEqual( + 1 if wgrid.cell_contains(x, y, z, 0) else 0, + hits + ) + + def test_cell_corner_containment(self): + n = 4 + d = 10 + grid = GridGen.createRectangular( (n, n, n), (d, d, d)) + + for x, y, z in itertools.product(range(0, n*d+1, d), repeat=3): + self.assertEqual( + 1, + [grid.cell_contains(x, y, z, i) for i in range(n**3)].count(True) + ) + + def test_cell_corner_containment_compatability(self): + grid = GridGen.createRectangular( (3,3,3), (1,1,1) ) + + for x, y, z in itertools.product(range(4), repeat=3): + for i in range(27): + if grid.cell_contains(x, y, z, i): + self.assertEqual( + CORNER_HOME[(x,y,z)], + i + ) + + def test_cell_face_containment(self): + n = 4 + d = 10 + grid = GridGen.createRectangular( (n, n, n), (d, d, d)) + + for x, y, z in itertools.product(range(d/2, n*d, d), repeat=3): + for axis, direction in itertools.product(range(3), [-1, 1]): + p = [x, y, z] + p[axis] = p[axis] + direction*d/2 + self.assertEqual( + 1, + [grid.cell_contains(p[0], p[1], p[2], i) for i in range(n**3)].count(True) + ) + + # This test generates a cell that is concave on ALL 6 sides + def test_concave_cell_containment(self): + points = [ + (5, 5, 5), + (20, 10, 10), + (10, 20, 10), + (25, 25, 5), + (10, 10, 20), + (25, 5, 25), + (5, 25, 25), + (20, 20, 20) + ] + + grid = GridGen.createSingleCellGrid(points) + + assertPoint = lambda p : self.assertTrue( + grid.cell_contains(p[0], p[1], p[2], 0) + ) + + assertNotPoint = lambda p : self.assertFalse( + grid.cell_contains(p[0], p[1], p[2], 0) + ) + + # Cell center + assertPoint(average(points)); + + # "Side" center + assertNotPoint(average(points[0:4:])) + assertNotPoint(average(points[4:8:])) + assertNotPoint(average(points[1:8:2])) + assertNotPoint(average(points[0:8:2])) + assertNotPoint(average(points[0:8:4] + points[1:8:4])) + assertNotPoint(average(points[2:8:4] + points[3:8:4])) + + # Corners + for p in points: + assertPoint(p) + + # Edges + edges = ([(i, i+1) for i in range(0, 8, 2)] + + [(i, i+2) for i in [0, 1, 4, 5]] + + [(i, i+4) for i in range(4)] + + [(1,2), (2,7), (1,7), (4,7), (2,4), (4,1)]) + for a,b in edges: + assertPoint(average([points[a], points[b]])) + + # Epsilon inside from corners + middle_point = average(points) + for p in points: + assertPoint(average(20*[p] + [middle_point])) + + # Espilon outside + middle_point[2] = 0 + for p in points[0:4:]: + assertNotPoint(average(20*[p] + [middle_point])) + + middle_point[2] = 30 + for p in points[4:8:]: + assertNotPoint(average(20*[p] + [middle_point])) + + # This test generates a cell that is strictly convex on ALL 6 sides + def test_concvex_cell_containment(self): + points = [ + (10, 10, 10), + (25, 5, 5), + (5, 25, 5), + (20, 20, 10), + (5, 5, 25), + (20, 10, 20), + (10, 20, 20), + (25, 25, 25) + ] + + grid = GridGen.createSingleCellGrid(points) + + assertPoint = lambda p : self.assertTrue( + grid.cell_contains(p[0], p[1], p[2], 0) + ) + + assertNotPoint = lambda p : self.assertFalse( + grid.cell_contains(p[0], p[1], p[2], 0) + ) + + # Cell center + assertPoint(average(points)); + + # "Side" center + assertPoint(average(points[0:4:])) + assertPoint(average(points[4:8:])) + assertPoint(average(points[1:8:2])) + assertPoint(average(points[0:8:2])) + assertPoint(average(points[0:8:4] + points[1:8:4])) + assertPoint(average(points[2:8:4] + points[3:8:4])) + + # Corners + for p in points: + assertPoint(p) + + # Edges + edges = ([(i, i+1) for i in range(0, 8, 2)] + + [(i, i+2) for i in [0, 1, 4, 5]] + + [(i, i+4) for i in range(4)] + + [(1,2), (2,7), (1,7), (4,7), (2,4), (4,1)]) + for a,b in edges: + assertPoint(average([points[a], points[b]])) + + # Epsilon inside from corners + middle_point = average(points) + for p in points: + assertPoint(average(20*[p] + [middle_point])) + + # Espilon outside + middle_point[2] = 0 + for p in points[0:4:]: + assertNotPoint(average(20*[p] + [middle_point])) + + middle_point[2] = 30 + for p in points[4:8:]: + assertNotPoint(average(20*[p] + [middle_point])) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_grid_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_grid_statoil.py similarity index 93% rename from ThirdParty/Ert/python/tests/core/ecl/test_grid_statoil.py rename to ThirdParty/Ert/python/tests/ecl/test_grid_statoil.py index 96f4a2c011..920cdaa95b 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_grid_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_grid_statoil.py @@ -22,7 +22,7 @@ except ImportError: from unittest import skipIf import time -from ert.ecl import EclTypeEnum, EclKW, EclGrid, EclFile, openEclFile +from ert.ecl import EclDataType, EclKW, EclGrid, EclFile, openEclFile from ert.util import DoubleVector, IntVector from ert.test import ExtendedTestCase , TestAreaContext @@ -107,7 +107,7 @@ class GridTest(ExtendedTestCase): def test_EGRID( self ): grid = EclGrid(self.egrid_file()) self.assertTrue(grid) - dims = grid.dims + dims = grid.getDims() self.assertEqual(dims[0] , grid.getNX()) self.assertEqual(dims[1] , grid.getNY()) self.assertEqual(dims[2] , grid.getNZ()) @@ -116,11 +116,11 @@ class GridTest(ExtendedTestCase): def create(self, filename, load_actnum=True): fileH = open(filename, "r") - specgrid = EclKW.read_grdecl(fileH, "SPECGRID", ecl_type=EclTypeEnum.ECL_INT_TYPE, strict=False) + specgrid = EclKW.read_grdecl(fileH, "SPECGRID", ecl_type=EclDataType.ECL_INT, strict=False) zcorn = EclKW.read_grdecl(fileH, "ZCORN") coord = EclKW.read_grdecl(fileH, "COORD") if load_actnum: - actnum = EclKW.read_grdecl(fileH, "ACTNUM", ecl_type=EclTypeEnum.ECL_INT_TYPE) + actnum = EclKW.read_grdecl(fileH, "ACTNUM", ecl_type=EclDataType.ECL_INT) else: actnum = None @@ -291,20 +291,20 @@ class GridTest(ExtendedTestCase): def test_dual(self): with TestAreaContext("python/grid-test/testDual"): grid = EclGrid(self.egrid_file()) - self.assertFalse(grid.dual_grid) - self.assertTrue(grid.nactive_fracture == 0) + self.assertFalse(grid.dualGrid()) + self.assertTrue(grid.getNumActiveFracture() == 0) grid2 = EclGrid(self.grid_file()) - self.assertFalse(grid.dual_grid) - self.assertTrue(grid.nactive_fracture == 0) + self.assertFalse(grid.dualGrid()) + self.assertTrue(grid.getNumActiveFracture() == 0) dgrid = EclGrid(self.createTestPath("Statoil/ECLIPSE/DualPoro/DUALPOR_MSW.EGRID")) - self.assertTrue(dgrid.nactive == dgrid.nactive_fracture) - self.assertTrue(dgrid.nactive == 46118) + self.assertTrue(dgrid.getNumActive() == dgrid.getNumActiveFracture()) + self.assertTrue(dgrid.getNumActive() == 46118) dgrid2 = EclGrid(self.createTestPath("Statoil/ECLIPSE/DualPoro/DUALPOR_MSW.GRID")) - self.assertTrue(dgrid.nactive == dgrid.nactive_fracture) - self.assertTrue(dgrid.nactive == 46118) + self.assertTrue(dgrid.getNumActive() == dgrid.getNumActiveFracture()) + self.assertTrue(dgrid.getNumActive() == 46118) self.assertTrue(dgrid.equal(dgrid2)) @@ -312,8 +312,8 @@ class GridTest(ExtendedTestCase): # situation where some cells are only matrix active, and some # cells are only fracture active. dgrid = EclGrid(self.createTestPath("Statoil/ECLIPSE/DualPoro/DUAL_DIFF.EGRID")) - self.assertTrue(dgrid.nactive == 106) - self.assertTrue(dgrid.nactive_fracture == 105) + self.assertTrue(dgrid.getNumActive() == 106) + self.assertTrue(dgrid.getNumActiveFracture() == 105) self.assertTrue(dgrid.get_active_fracture_index(global_index=0) == -1) self.assertTrue(dgrid.get_active_fracture_index(global_index=2) == -1) @@ -330,8 +330,8 @@ class GridTest(ExtendedTestCase): self.assertTrue(dgrid.equal(dgrid2 , verbose = True)) - @skipIf(ExtendedTestCase.slowTestShouldNotRun(), "Slow test of nactive large memory skipped!") - def test_nactive_large_memory(self): + @skipIf(ExtendedTestCase.slowTestShouldNotRun(), "Slow test of numActive large memory skipped!") + def test_num_active_large_memory(self): case = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE") vecList = [] for i in range(12500): @@ -341,8 +341,8 @@ class GridTest(ExtendedTestCase): grid1 = EclGrid(case) grid2 = EclGrid(case) - self.assertEqual(grid1.nactive, grid2.nactive) - self.assertEqual(grid1.nactive, 34770) + self.assertEqual(grid1.getNumActive(), grid2.getNumActive()) + self.assertEqual(grid1.getNumActive(), 34770) def test_no_mapaxes_check_for_nan(self): diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_indexed_read.py b/ThirdParty/Ert/python/tests/ecl/test_indexed_read.py similarity index 87% rename from ThirdParty/Ert/python/tests/core/ecl/test_indexed_read.py rename to ThirdParty/Ert/python/tests/ecl/test_indexed_read.py index edbb7221fb..0e26f31df4 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_indexed_read.py +++ b/ThirdParty/Ert/python/tests/ecl/test_indexed_read.py @@ -2,12 +2,12 @@ import ctypes import ert from ert.ecl import EclPrototype -from ert.ecl import EclKW, EclFile, EclTypeEnum, FortIO +from ert.ecl import EclKW, EclFile, EclDataType, FortIO from ert.test import ExtendedTestCase, TestAreaContext from ert.util import IntVector class EclIndexedReadTest(ExtendedTestCase): - _freadIndexedData = EclPrototype("void ecl_kw_fread_indexed_data(fortio, int, int, int, int_vector, char*)", bind = False) # fortio, offset, type, count, index_map, buffer + _freadIndexedData = EclPrototype("void ecl_kw_fread_indexed_data_python(fortio, int, ecl_data_type, int, int_vector, char*)", bind = False) # fortio, offset, type, count, index_map, buffer _eclFileIndexedRead = EclPrototype("void ecl_file_indexed_read(ecl_file, char*, int, int_vector, char*)", bind = False) # ecl_file, kw, index, index_map, buffer def test_ecl_kw_indexed_read(self): @@ -15,7 +15,7 @@ class EclIndexedReadTest(ExtendedTestCase): fortio = FortIO("index_test", mode=FortIO.WRITE_MODE) element_count = 100000 - ecl_kw = EclKW.create("TEST", element_count, EclTypeEnum.ECL_INT_TYPE) + ecl_kw = EclKW("TEST", element_count, EclDataType.ECL_INT) for index in range(element_count): ecl_kw[index] = index @@ -54,7 +54,7 @@ class EclIndexedReadTest(ExtendedTestCase): char_buffer = ctypes.create_string_buffer(len(index_map) * ctypes.sizeof(ctypes.c_int)) - self._freadIndexedData(fortio, 24, EclTypeEnum.ECL_INT_TYPE, element_count, index_map, char_buffer) + self._freadIndexedData(fortio, 24, EclDataType.ECL_INT, element_count, index_map, char_buffer) int_buffer = ctypes.cast(char_buffer, ctypes.POINTER(ctypes.c_int)) @@ -68,8 +68,8 @@ class EclIndexedReadTest(ExtendedTestCase): fortio = FortIO("ecl_file_index_test", mode=FortIO.WRITE_MODE) element_count = 100000 - ecl_kw_1 = EclKW.create("TEST1", element_count, EclTypeEnum.ECL_INT_TYPE) - ecl_kw_2 = EclKW.create("TEST2", element_count, EclTypeEnum.ECL_INT_TYPE) + ecl_kw_1 = EclKW("TEST1", element_count, EclDataType.ECL_INT) + ecl_kw_2 = EclKW("TEST2", element_count, EclDataType.ECL_INT) for index in range(element_count): ecl_kw_1[index] = index diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_kw_function.py b/ThirdParty/Ert/python/tests/ecl/test_kw_function.py similarity index 92% rename from ThirdParty/Ert/python/tests/core/ecl/test_kw_function.py rename to ThirdParty/Ert/python/tests/ecl/test_kw_function.py index cd60c14f60..a492f4b096 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_kw_function.py +++ b/ThirdParty/Ert/python/tests/ecl/test_kw_function.py @@ -16,7 +16,7 @@ # for more details. import os import random -from ert.ecl import EclKW, EclTypeEnum, EclGrid , Ecl3DKW +from ert.ecl import EclKW, EclDataType, EclGrid , Ecl3DKW from ert.util import IntVector from ert.test import ExtendedTestCase @@ -32,7 +32,7 @@ class KWFunctionTest(ExtendedTestCase): grid = EclGrid.createRectangular( (nx,ny,nz) , (1,1,1) , actnum = actnum) self.assertEqual( grid.getNumActive() , nx*ny*nz - 1 ) - kw = Ecl3DKW.create( "REGIONS" , grid , EclTypeEnum.ECL_INT_TYPE , global_active = True ) + kw = Ecl3DKW.create( "REGIONS" , grid , EclDataType.ECL_INT , global_active = True ) kw.assign( 0 ) kw[0:nx*ny/2] = 1 kw[5,2,0] = 0 diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_layer.py b/ThirdParty/Ert/python/tests/ecl/test_layer.py similarity index 99% rename from ThirdParty/Ert/python/tests/core/ecl/test_layer.py rename to ThirdParty/Ert/python/tests/ecl/test_layer.py index 26a176288f..2791b0179f 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_layer.py +++ b/ThirdParty/Ert/python/tests/ecl/test_layer.py @@ -112,7 +112,7 @@ class LayerTest(ExtendedTestCase): nx = 120 ny = 60 nz = 43 - grid = EclGrid.create_rectangular( (nx , ny , nz) , (1,1,1) ) + grid = EclGrid.createRectangular( (nx , ny , nz) , (1,1,1) ) with TestAreaContext("python/faults/line_order"): with open("faults.grdecl" , "w") as f: f.write("""FAULTS diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_npv.py b/ThirdParty/Ert/python/tests/ecl/test_npv.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/ecl/test_npv.py rename to ThirdParty/Ert/python/tests/ecl/test_npv.py diff --git a/ThirdParty/Ert/python/tests/ecl/test_region.py b/ThirdParty/Ert/python/tests/ecl/test_region.py new file mode 100644 index 0000000000..921ef1457a --- /dev/null +++ b/ThirdParty/Ert/python/tests/ecl/test_region.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# Copyright (C) 2017 Statoil ASA, Norway. +# +# The file 'test_region.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. +from ert.ecl import EclGrid, EclKW, EclRegion, EclDataType +from ert.ecl.faults import Layer +from ert.test import ExtendedTestCase + + +class RegionTest(ExtendedTestCase): + + def test_equal(self): + grid = EclGrid.createRectangular( (10,10,1) , (1,1,1)) + kw_int = EclKW( "INT" , grid.getGlobalSize( ) , EclDataType.ECL_INT ) + kw_float = EclKW( "FLOAT" , grid.getGlobalSize( ) , EclDataType.ECL_FLOAT ) + + kw_int[0:49] = 1 + region = EclRegion(grid, False) + region.select_equal( kw_int , 1 ) + glist = region.getGlobalList() + for g in glist: + self.assertEqual( kw_int[g] , 1 ) + + with self.assertRaises(ValueError): + region.select_equal( kw_float , 1 ) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_region.py b/ThirdParty/Ert/python/tests/ecl/test_region_statoil.py similarity index 91% rename from ThirdParty/Ert/python/tests/core/ecl/test_region.py rename to ThirdParty/Ert/python/tests/ecl/test_region_statoil.py index caf9616b6e..46ebe821a7 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_region.py +++ b/ThirdParty/Ert/python/tests/ecl/test_region_statoil.py @@ -103,7 +103,7 @@ class RegionTest(ExtendedTestCase): reg.select_islice(0, 5) OK = True - global_list = reg.global_list + global_list = reg.getGlobalList() self.assertEqual(global_list.parent(), reg) for gi in global_list: @@ -111,11 +111,11 @@ class RegionTest(ExtendedTestCase): if i > 5: OK = False self.assertTrue(OK) - self.assertTrue(self.grid.ny * self.grid.nz * 6 == len(reg.global_list)) + self.assertTrue(self.grid.getNY() * self.grid.getNZ() * 6 == len(reg.getGlobalList())) reg.select_jslice(7, 8, intersect=True) OK = True - for gi in reg.global_list: + for gi in reg.getGlobalList(): (i, j, k) = self.grid.get_ijk(global_index=gi) if i > 5: OK = False @@ -124,13 +124,13 @@ class RegionTest(ExtendedTestCase): OK = False self.assertTrue(OK) - self.assertTrue(2 * self.grid.nz * 6 == len(reg.global_list)) + self.assertTrue(2 * self.grid.getNZ() * 6 == len(reg.getGlobalList())) reg2 = EclRegion(self.grid, False) reg2.select_kslice(3, 5) reg &= reg2 OK = True - for gi in reg.global_list: + for gi in reg.getGlobalList(): (i, j, k) = self.grid.get_ijk(global_index=gi) if i > 5: OK = False @@ -149,8 +149,8 @@ class RegionTest(ExtendedTestCase): def test_index_list(self): reg = EclRegion(self.grid, False) reg.select_islice(0, 5) - active_list = reg.active_list - global_list = reg.global_list + active_list = reg.getActiveList() + global_list = reg.getGlobalList() @@ -160,7 +160,7 @@ class RegionTest(ExtendedTestCase): dx = 0.1 dy = 0.1 reg.select_inside_polygon( [(x-dx,y-dy) , (x-dx,y+dy) , (x+dx,y+dy) , (x+dx,y-dy)] ) - self.assertTrue( self.grid.nz == len(reg.getGlobalList())) + self.assertTrue( self.grid.getNZ() == len(reg.getGlobalList())) def test_heidrun(self): @@ -176,7 +176,7 @@ class RegionTest(ExtendedTestCase): reg = EclRegion( grid , False ) reg.select_inside_polygon( polygon ) - self.assertEqual( 0 , len(reg.global_list) % grid.nz) + self.assertEqual( 0 , len(reg.getGlobalList()) % grid.getNZ()) def test_layer(self): diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_removed.py b/ThirdParty/Ert/python/tests/ecl/test_removed.py similarity index 87% rename from ThirdParty/Ert/python/tests/core/ecl/test_removed.py rename to ThirdParty/Ert/python/tests/ecl/test_removed.py index 54f26f45a8..3596802101 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_removed.py +++ b/ThirdParty/Ert/python/tests/ecl/test_removed.py @@ -1,9 +1,8 @@ -import warnings import time import datetime from ert.test import ExtendedTestCase, TestAreaContext -from ert.ecl import EclFile,EclKW,EclTypeEnum,openFortIO, FortIO +from ert.ecl import EclFile,EclKW,EclDataType,openFortIO, FortIO @@ -11,7 +10,7 @@ class Removed_2_1_Test(ExtendedTestCase): def test_ecl_file_block(self): with TestAreaContext("name") as t: - kw = EclKW("TEST", 3, EclTypeEnum.ECL_INT_TYPE) + kw = EclKW("TEST", 3, EclDataType.ECL_INT) with openFortIO("TEST" , mode = FortIO.WRITE_MODE) as f: kw.fwrite( f ) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_restart.py b/ThirdParty/Ert/python/tests/ecl/test_restart.py similarity index 97% rename from ThirdParty/Ert/python/tests/core/ecl/test_restart.py rename to ThirdParty/Ert/python/tests/ecl/test_restart.py index 391b07ba20..7ce8773361 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_restart.py +++ b/ThirdParty/Ert/python/tests/ecl/test_restart.py @@ -109,10 +109,10 @@ class RestartTest(ExtendedTestCase): def test_name(self): f = EclFile(self.u_file) - self.assertTrue(f.name == self.u_file) + self.assertTrue(f.getFilename() == self.u_file) f = EclFile(self.xfile0) - self.assertTrue(f.name == self.xfile0) + self.assertTrue(f.getFilename() == self.xfile0) def test_kw( self ): diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_rft.py b/ThirdParty/Ert/python/tests/ecl/test_rft.py similarity index 83% rename from ThirdParty/Ert/python/tests/core/ecl/test_rft.py rename to ThirdParty/Ert/python/tests/ecl/test_rft.py index fe0215facf..109b5296ee 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_rft.py +++ b/ThirdParty/Ert/python/tests/ecl/test_rft.py @@ -31,6 +31,8 @@ class RFTTest(ExtendedTestCase): with self.assertRaises(IndexError): cell = rft[5] - - + def test_repr(self): + rft = EclRFT( "WELL" , "RFT" , datetime.date(2015 , 10 , 1 ) , 100 ) + pfx = 'EclRFT(completed_cells = 0, date = 2015-10-01, RFT, MSW)' + self.assertEqual(pfx, repr(rft)[:len(pfx)]) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_rft_cell.py b/ThirdParty/Ert/python/tests/ecl/test_rft_cell.py similarity index 91% rename from ThirdParty/Ert/python/tests/core/ecl/test_rft_cell.py rename to ThirdParty/Ert/python/tests/ecl/test_rft_cell.py index 11f720c85b..ea134d4a3f 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_rft_cell.py +++ b/ThirdParty/Ert/python/tests/ecl/test_rft_cell.py @@ -16,7 +16,6 @@ # for more details. -import warnings from ert.ecl import EclRFTCell, EclPLTCell from ert.test import ExtendedTestCase @@ -76,12 +75,6 @@ class RFTCellTest(ExtendedTestCase): self.assertEqual(j, cell.get_j()) self.assertEqual(k, cell.get_k()) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - self.assertTrue(cell.get_i() + 1 == cell.i) - self.assertTrue(cell.get_j() + 1 == cell.j) - self.assertTrue(cell.get_k() + 1 == cell.k) - self.assertFloatEqual(pressure, cell.pressure) self.assertFloatEqual(depth, cell.depth) self.assertFloatEqual(orat, cell.orat) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_rft_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_rft_statoil.py similarity index 99% rename from ThirdParty/Ert/python/tests/core/ecl/test_rft_statoil.py rename to ThirdParty/Ert/python/tests/ecl/test_rft_statoil.py index 147ee80cbb..e1e9b07bfb 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_rft_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_rft_statoil.py @@ -57,7 +57,7 @@ class RFTTest(ExtendedTestCase): self.assertIsInstance(cell, EclRFTCell) rft.sort() - for h in rftFile.headers: + for h in rftFile.getHeaders(): print(h) self.assertIsInstance( h[1] , datetime.date ) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_statoil_faults.py b/ThirdParty/Ert/python/tests/ecl/test_statoil_faults.py similarity index 97% rename from ThirdParty/Ert/python/tests/core/ecl/test_statoil_faults.py rename to ThirdParty/Ert/python/tests/ecl/test_statoil_faults.py index e436985e18..0804a9e41a 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_statoil_faults.py +++ b/ThirdParty/Ert/python/tests/ecl/test_statoil_faults.py @@ -21,7 +21,7 @@ except ImportError: import time from ert.ecl.faults import FaultCollection, Fault, FaultLine, FaultSegment -from ert.ecl import EclGrid,EclKW,EclTypeEnum +from ert.ecl import EclGrid, EclKW, EclDataType from ert.test import ExtendedTestCase @@ -30,10 +30,10 @@ class StatoilFaultTest(ExtendedTestCase): def loadGrid(self): grid_file = self.createTestPath("Statoil/ECLIPSE/Faults/grid.grdecl") fileH = open(grid_file, "r") - specgrid = EclKW.read_grdecl(fileH, "SPECGRID", ecl_type=EclTypeEnum.ECL_INT_TYPE, strict=False) + specgrid = EclKW.read_grdecl(fileH, "SPECGRID", ecl_type=EclDataType.ECL_INT, strict=False) zcorn = EclKW.read_grdecl(fileH, "ZCORN") coord = EclKW.read_grdecl(fileH, "COORD") - actnum = EclKW.read_grdecl(fileH, "ACTNUM", ecl_type=EclTypeEnum.ECL_INT_TYPE) + actnum = EclKW.read_grdecl(fileH, "ACTNUM", ecl_type=EclDataType.ECL_INT) return EclGrid.create(specgrid, zcorn, coord, actnum) diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_sum.py b/ThirdParty/Ert/python/tests/ecl/test_sum.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/ecl/test_sum.py rename to ThirdParty/Ert/python/tests/ecl/test_sum.py diff --git a/ThirdParty/Ert/python/tests/core/ecl/test_sum_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_sum_statoil.py similarity index 96% rename from ThirdParty/Ert/python/tests/core/ecl/test_sum_statoil.py rename to ThirdParty/Ert/python/tests/ecl/test_sum_statoil.py index 37f4781473..b31b83b7e7 100644 --- a/ThirdParty/Ert/python/tests/core/ecl/test_sum_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_sum_statoil.py @@ -248,28 +248,28 @@ class SumTest(ExtendedTestCase): self.assertRaises(KeyError, sum.smspec_node, "BJARNE") node = sum.smspec_node("FOPT") - self.assertTrue(node.is_total) - self.assertFalse(node.is_historical) + self.assertTrue(node.isTotal()) + self.assertFalse(node.isHistorical()) node = sum.smspec_node("FOPR") - self.assertFalse(node.is_total) - self.assertFalse(node.is_historical) + self.assertFalse(node.isTotal()) + self.assertFalse(node.isHistorical()) self.assertTrue(node.keyword == "FOPR") node = sum.smspec_node("FOPRH") - self.assertFalse(node.is_total) - self.assertTrue(node.is_historical) - self.assertTrue(node.is_rate) + self.assertFalse(node.isTotal()) + self.assertTrue(node.isHistorical()) + self.assertTrue(node.isRate()) self.assertTrue(node.keyword == "FOPRH") node = sum.smspec_node("WOPR:OP_1") - self.assertFalse(node.is_total) - self.assertTrue(node.is_rate) + self.assertFalse(node.isTotal()) + self.assertTrue(node.isRate()) self.assertTrue(node.keyword == "WOPR") node = sum.smspec_node("WOPT:OP_1") - self.assertTrue(node.is_total) - self.assertFalse(node.is_rate) + self.assertTrue(node.isTotal()) + self.assertFalse(node.isRate()) self.assertTrue(node.unit == "SM3") self.assertTrue(node.wgname == "OP_1") self.assertTrue(node.keyword == "WOPT") @@ -277,8 +277,8 @@ class SumTest(ExtendedTestCase): self.assertTrue(sum.unit("FOPR") == "SM3/DAY") node = sum.smspec_node("FOPTH") - self.assertTrue(node.is_total) - self.assertFalse(node.is_rate) + self.assertTrue(node.isTotal()) + self.assertFalse(node.isRate()) self.assertIsNone(node.wgname) node = sum.smspec_node("FOPTH") diff --git a/ThirdParty/Ert/python/tests/ert/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/CMakeLists.txt deleted file mode 100644 index 892b16a645..0000000000 --- a/ThirdParty/Ert/python/tests/ert/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(TEST_SOURCES - __init__.py -) - -add_python_package("python.tests.ert" ${PYTHON_INSTALL_PREFIX}/tests/ert "${TEST_SOURCES}" False) - -add_subdirectory(analysis) -add_subdirectory(config) -add_subdirectory(enkf) -add_subdirectory(job_queue) -add_subdirectory(run) -add_subdirectory(sched) -add_subdirectory(server) -add_subdirectory(testcase) diff --git a/ThirdParty/Ert/python/tests/ert/__init__.py b/ThirdParty/Ert/python/tests/ert/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/ert/analysis/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/analysis/CMakeLists.txt deleted file mode 100644 index 64512c7ede..0000000000 --- a/ThirdParty/Ert/python/tests/ert/analysis/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_analysis_module.py - test_linalg.py - test_options_enum.py - test_rml.py - test_std_enkf.py - test_std_enkf_debug.py -) - -add_python_package("python.tests.ert.analysis" ${PYTHON_INSTALL_PREFIX}/tests/ert/analysis "${TEST_SOURCES}" False) - -addPythonTest(ert.analysis.analysis_module tests.ert.analysis.test_analysis_module.AnalysisModuleTest) -addPythonTest(ert.analysis.enums tests.ert.analysis.test_options_enum.AnalysisOptionsEnumTest) -addPythonTest(ert.analysis.linalg tests.ert.analysis.test_linalg.LinalgTest) -addPythonTest(ert.analysis.rml tests.ert.analysis.test_rml.RMLTest) -addPythonTest(ert.analysis.std_enkf tests.ert.analysis.test_std_enkf.StdEnKFTest) -addPythonTest(ert.analysis.std_enkf_debug tests.ert.analysis.test_std_enkf_debug.StdEnKFDebugTest) - diff --git a/ThirdParty/Ert/python/tests/ert/analysis/__init__.py b/ThirdParty/Ert/python/tests/ert/analysis/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/ert/analysis/test_analysis_module.py b/ThirdParty/Ert/python/tests/ert/analysis/test_analysis_module.py deleted file mode 100644 index 6190619276..0000000000 --- a/ThirdParty/Ert/python/tests/ert/analysis/test_analysis_module.py +++ /dev/null @@ -1,153 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'test_analysis_module.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import ert -from ert.test import ExtendedTestCase -from ert.analysis import AnalysisModule, AnalysisModuleLoadStatusEnum, AnalysisModuleOptionsEnum - -from ert.util.enums import RngAlgTypeEnum, RngInitModeEnum -from ert.util.rng import RandomNumberGenerator - -from ert.util import Matrix - -class AnalysisModuleTest(ExtendedTestCase): - def setUp(self): - self.libname = ert.ert_lib_path + "/rml_enkf.so" - self.rng = RandomNumberGenerator(RngAlgTypeEnum.MZRAN, RngInitModeEnum.INIT_DEFAULT) - - def createAnalysisModule(self): - return AnalysisModule(self.rng, lib_name = self.libname) - - def test_load_status_enum(self): - source_file_path = "libanalysis/include/ert/analysis/analysis_module.h" - self.assertEnumIsFullyDefined(AnalysisModuleLoadStatusEnum, "analysis_module_load_status_enum", source_file_path) - - def test_analysis_module(self): - am = self.createAnalysisModule() - - self.assertEqual(am.getLibName(), self.libname) - - self.assertFalse(am.getInternal()) - - self.assertTrue(am.setVar("ITER", "1")) - - self.assertEqual(am.getTableName(), "analysis_table") - - self.assertTrue(am.checkOption(AnalysisModuleOptionsEnum.ANALYSIS_ITERABLE)) - - self.assertTrue(am.hasVar("ITER")) - - self.assertIsInstance(am.getDouble("ENKF_TRUNCATION"), float) - - self.assertIsInstance(am.getInt("ITER"), int) - - def test_set_get_var(self): - mod = AnalysisModule( self.rng , name = "STD_ENKF" ) - with self.assertRaises(KeyError): - mod.setVar("NO-NOT_THIS_KEY" , 100) - - - with self.assertRaises(KeyError): - mod.getInt("NO-NOT_THIS_KEY") - - - - - - def test_create_internal(self): - with self.assertRaises( KeyError ): - mod = AnalysisModule( self.rng , name = "STD_ENKFXXX" ) - - mod = AnalysisModule( self.rng , name = "STD_ENKF" ) - - - def test_initX_enkf_linalg_lowrankCinv(self): - """Test AnalysisModule.initX with EE=False and GE=False""" - mod = AnalysisModule( self.rng , name = "STD_ENKF" ) - A, S, R, dObs, E, D = self._n_identity_mcs() - self.assertFalse(mod.getBool('USE_EE')) - self.assertFalse(mod.getBool('USE_GE')) - - elt_a, elt_b = 1.222, -0.111 - vals = (elt_a, elt_b, elt_b, - elt_b, elt_a, elt_b, - elt_b, elt_b, elt_a) - expected = self.construct_matrix(3, vals) - - X = mod.initX(A, S, R, dObs, E, D) - self._matrix_close(X, expected) - - def test_initX_enkf_linalg_lowrank_EE(self): - """Test AnalysisModule.initX with EE=True and GE=False""" - mod = AnalysisModule( self.rng , name = "STD_ENKF" ) - A, S, R, dObs, E, D = self._n_identity_mcs() - mod.setVar('USE_EE', True) - self.assertTrue(mod.getBool('USE_EE')) - self.assertFalse(mod.getBool('USE_GE')) - - elt_a, elt_b = 1.33, -0.167 - vals = (elt_a, elt_b, elt_b, - elt_b, elt_a, elt_b, - elt_b, elt_b, elt_a) - expected = self.construct_matrix(3, vals) - X = mod.initX(A, S, R, dObs, E, D) - self._matrix_close(X, expected) - - def test_initX_subspace_inversion_algorithm(self): - """Test AnalysisModule.initX with EE=True and GE=True, the subspace inversion algorithm""" - mod = AnalysisModule( self.rng , name = "STD_ENKF" ) - A, S, R, dObs, E, D = self._n_identity_mcs() - - mod.setVar('USE_EE', True) - mod.setVar('USE_GE', True) - self.assertTrue(mod.getBool('USE_EE')) - self.assertTrue(mod.getBool('USE_GE')) - - vals = ( 1.39, -0.111, -0.278, - -0.111, 1.39, -0.278, - -0.278, -0.278, 1.56 ) - expected = self.construct_matrix(3, vals) - X = mod.initX(A, S, R, dObs, E, D) - self._matrix_close(X, expected) - - def construct_matrix(self, n, vals): - """Constructs n*n matrix with vals as entries""" - self.assertEqual(n*n, len(vals)) - m = Matrix(n,n) - idx = 0 - for i in range(n): - for j in range(n): - m[(i,j)] = vals[idx] - idx += 1 - return m - - def _n_identity_mcs(self, n=6,s=3): - """return n copies of the identity matrix on s*s elts""" - return tuple([Matrix.identity(s) for i in range(n)]) - - def _matrix_close(self, m1, m2, epsilon=0.01): - """Check that matrices m1 and m2 are of same dimension and that they are - pointwise within epsilon difference.""" - - c = m1.columns() - r = m1.rows() - self.assertEqual(c, m2.columns(), 'Number of columns for m1 differ from m2') - self.assertEqual(r, m2.rows(), 'Number of rows for m1 differ from m2') - for i in range(0, c): - for j in range(0,r): - pos = (i,j) - diff = abs(m1[pos] - m2[pos]) - self.assertTrue(diff <= epsilon, 'Matrices differ at (i,j) = (%d,%d). %f != %f' % (i, j, m1[pos], m2[pos])) diff --git a/ThirdParty/Ert/python/tests/ert/analysis/test_linalg.py b/ThirdParty/Ert/python/tests/ert/analysis/test_linalg.py deleted file mode 100644 index 8ccef6e91c..0000000000 --- a/ThirdParty/Ert/python/tests/ert/analysis/test_linalg.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'test_labscale.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -from ert.enkf import ObsVector -from ert.util import Matrix -from ert.analysis import Linalg -from ert.test import ExtendedTestCase - -class LinalgTest(ExtendedTestCase): - - def test_num_PC(self): - S = Matrix(3,3) - S[0,0] = 1 - S[1,1] = 1 - S[2,2] = 1 - - with self.assertRaises(ValueError): - num_pc = Linalg.numPC( S , 0 ) - - with self.assertRaises(ValueError): - num_pc = Linalg.numPC( S , 1.5 ) - - num_pc = Linalg.numPC( S , 0.20 ) - self.assertEqual( num_pc , 1 ) - - num_pc = Linalg.numPC( S , 0.50 ) - self.assertEqual( num_pc , 2 ) - - num_pc = Linalg.numPC( S , 0.80 ) - self.assertEqual( num_pc , 3 ) - - diff --git a/ThirdParty/Ert/python/tests/ert/analysis/test_options_enum.py b/ThirdParty/Ert/python/tests/ert/analysis/test_options_enum.py deleted file mode 100644 index 9013f1954e..0000000000 --- a/ThirdParty/Ert/python/tests/ert/analysis/test_options_enum.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'test_options_enum.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from ert.test import ExtendedTestCase -from ert.analysis import AnalysisModuleOptionsEnum - - -class AnalysisOptionsEnumTest(ExtendedTestCase): - def test_items(self): - source_file_path = "libanalysis/include/ert/analysis/analysis_module.h" - self.assertEnumIsFullyDefined(AnalysisModuleOptionsEnum, "analysis_module_flag_enum", source_file_path) diff --git a/ThirdParty/Ert/python/tests/ert/analysis/test_rml.py b/ThirdParty/Ert/python/tests/ert/analysis/test_rml.py deleted file mode 100644 index 1440f73596..0000000000 --- a/ThirdParty/Ert/python/tests/ert/analysis/test_rml.py +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'test_analysis_module.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import random - -from ert.test import ExtendedTestCase -from ert.util.enums import RngAlgTypeEnum, RngInitModeEnum -from ert.util import Matrix, BoolVector , RandomNumberGenerator -from ert.analysis import AnalysisModule, AnalysisModuleLoadStatusEnum, AnalysisModuleOptionsEnum -from ert.enkf import MeasData , ObsData - -import ert - - -def forward_model(params , model_error = False): - # Y = A*p[0] + B*p[1] - A = 2 - B = -1 - C = 1 - D = 0.1 - state = [A*params[0] + B*params[1] , C*params[0] - D*params[1]*params[0]] - return state - - -def measure(state): - return 0.25*state[0] - 0.1*state[1]*state[1] - - -def init_matrices(ens , mask , obs , rng): - state_size = 2 - report_step = 5 - meas_data = MeasData( mask ) - meas_block = meas_data.addBlock("OBS" , report_step , len(obs) ) - - A = Matrix( state_size , mask.countEqual( True )) - active_iens = 0 - for iens,params in enumerate( ens ): - if mask[iens]: - state = forward_model( params ) - meas_block[0,iens] = measure( state ) - - A[0 , active_iens] = params[0] - A[1 , active_iens] = params[1] - - active_iens += 1 - - - S = meas_data.createS() - - obs_data = ObsData() - obs_block = obs_data.addBlock("OBS" , 1) - for iobs,obs_value in enumerate(obs): - obs_block[iobs] = obs_value - - - R = obs_data.createR() - dObs = obs_data.createDObs() - E = obs_data.createE( rng , meas_data.getActiveEnsSize() ) - D = obs_data.createD(E , S) - - obs_data.scale(S , E = E , D = D , R = R , D_obs = dObs) - return (A , S , E , D , R , dObs) - - - -class RMLTest(ExtendedTestCase): - def setUp(self): - self.libname = ert.ert_lib_path + "/rml_enkf.so" - self.user = "TEST" - - def createAnalysisModule(self): - rng = RandomNumberGenerator(RngAlgTypeEnum.MZRAN, RngInitModeEnum.INIT_DEFAULT) - return AnalysisModule(rng, lib_name = self.libname) - - def test_load_status_enum(self): - source_file_path = "libanalysis/include/ert/analysis/analysis_module.h" - self.assertEnumIsFullyDefined(AnalysisModuleLoadStatusEnum, "analysis_module_load_status_enum", source_file_path) - - - - - def test_analysis_module(self): - rng = RandomNumberGenerator( ) - module = self.createAnalysisModule() - ens_size = 12 - obs_size = 1 - state_size = 2 - - true_params = [1.25 , 0.75] - true_state = forward_model( true_params ) - obs = [(measure( true_state ) , 0.75)] - A = Matrix( state_size , ens_size ) - - ens = [] - for iens in range(ens_size): - param = [ random.gauss( 1.00 , 1.00 ) , random.gauss(1.00 , 1.00)] - ens.append( param ) - - mask = BoolVector(default_value = True , initial_size = ens_size) - mask[2] = False - (A , S , E , D , R , dObs) = init_matrices( ens , mask , obs , rng ) - - module.initUpdate( mask , S , R , dObs , E , D ) - module.updateA( A , S , R , dObs , E , D ) - - - mask[10] = False - mask[5] = False - (A , S , E , D , R , dObs) = init_matrices( ens , mask , obs , rng ) - self.assertEqual( S.dims() , (obs_size , mask.countEqual( True ))) - self.assertEqual( E.dims() , (obs_size , mask.countEqual( True ))) - self.assertEqual( D.dims() , (obs_size , mask.countEqual( True ))) - - module.initUpdate( mask , S , R , dObs , E , D ) - module.updateA( A , S , R , dObs , E , D ) - diff --git a/ThirdParty/Ert/python/tests/ert/analysis/test_std_enkf.py b/ThirdParty/Ert/python/tests/ert/analysis/test_std_enkf.py deleted file mode 100644 index cf62215da9..0000000000 --- a/ThirdParty/Ert/python/tests/ert/analysis/test_std_enkf.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# The file 'test_analysis_module.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from ert.test import ExtendedTestCase -from ert.analysis import AnalysisModule, AnalysisModuleLoadStatusEnum, AnalysisModuleOptionsEnum - -from ert.util.enums import RngAlgTypeEnum, RngInitModeEnum -from ert.util.rng import RandomNumberGenerator - - -class StdEnKFTest(ExtendedTestCase): - - def setUp(self): - self.rng = RandomNumberGenerator(RngAlgTypeEnum.MZRAN, RngInitModeEnum.INIT_DEFAULT) - self.module = AnalysisModule( self.rng , name = "STD_ENKF" ) - - def toggleKey(self, key): - self.assertTrue( self.module.hasVar( key )) - - # check it is true - self.assertTrue( self.module.setVar( key , True ) ) - self.assertTrue( self.module.getBool(key) ) - - # set it to false - self.assertTrue( self.module.setVar( key , False ) ) - self.assertFalse( self.module.getBool(key) ) - - def test_EE_option(self): - self.toggleKey( 'USE_EE' ) - - def test_GE_option(self): - self.toggleKey( 'USE_GE' ) - - - def test_scaledata_option(self): - self.toggleKey( 'ANALYSIS_SCALE_DATA' ) - - - diff --git a/ThirdParty/Ert/python/tests/ert/analysis/test_std_enkf_debug.py b/ThirdParty/Ert/python/tests/ert/analysis/test_std_enkf_debug.py deleted file mode 100644 index 80637c9cab..0000000000 --- a/ThirdParty/Ert/python/tests/ert/analysis/test_std_enkf_debug.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (C) 2016 Statoil ASA, Norway. -# -# The file 'test_analysis_module.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import ert -from ert.test import ExtendedTestCase -from ert.analysis import AnalysisModule, AnalysisModuleLoadStatusEnum, AnalysisModuleOptionsEnum -from ert.analysis import AnalysisPrototype -from ert.util.enums import RngAlgTypeEnum, RngInitModeEnum -from ert.util.rng import RandomNumberGenerator - - -class StdEnKFDebugTest(ExtendedTestCase): - - def setUp(self): - self.rng = RandomNumberGenerator(RngAlgTypeEnum.MZRAN, RngInitModeEnum.INIT_DEFAULT) - self.libname = ert.ert_lib_path + "/std_enkf_debug.so" - self.module = AnalysisModule( self.rng , lib_name = self.libname ) - - - def toggleKey(self, key): - self.assertTrue( self.module.hasVar( key )) - - # check it is true - self.assertTrue( self.module.setVar( key , True ) ) - self.assertTrue( self.module.getBool(key) ) - - # set it to false - self.assertTrue( self.module.setVar( key , False ) ) - self.assertFalse( self.module.getBool(key) ) - - def test_EE_option(self): - self.toggleKey( 'USE_EE' ) - - - def test_scaledata_option(self): - self.toggleKey( 'ANALYSIS_SCALE_DATA' ) - - def test_prefix(self): - self.assertTrue( self.module.hasVar("PREFIX")) - self.assertTrue( self.module.setVar( "PREFIX" , "Path") ) diff --git a/ThirdParty/Ert/python/tests/ert/config/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/config/CMakeLists.txt deleted file mode 100644 index 06443963eb..0000000000 --- a/ThirdParty/Ert/python/tests/ert/config/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_config.py -) - -add_python_package("python.tests.ert.config" ${PYTHON_INSTALL_PREFIX}/tests/ert/config "${TEST_SOURCES}" True) - -addPythonTest(ert.config tests.ert.config.test_config.ConfigTest) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/config/__init__.py b/ThirdParty/Ert/python/tests/ert/config/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/ert/config/test_config.py b/ThirdParty/Ert/python/tests/ert/config/test_config.py deleted file mode 100644 index a58507cd34..0000000000 --- a/ThirdParty/Ert/python/tests/ert/config/test_config.py +++ /dev/null @@ -1,366 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'test_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import os - -import ert -from ert.config import ContentTypeEnum, UnrecognizedEnum, SchemaItem, ContentItem, ContentNode, ConfigParser, ConfigContent,ConfigSettings -from cwrap import Prototype, clib -from ert.test import ExtendedTestCase, TestAreaContext - - -class TestConfigPrototype(Prototype): - lib = ert.load("libconfig") - - def __init__(self, prototype, bind=False): - super(TestConfigPrototype, self).__init__(TestConfigPrototype.lib, prototype, bind=bind) - -# Adding extra functions to the ConfigContent object for the ability -# to test low level C functions which are not exposed in Python. -_safe_iget = TestConfigPrototype("char* config_content_safe_iget( config_content , char* , int , int)") -_iget = TestConfigPrototype("char* config_content_iget( config_content , char* , int , int)") -_iget_as_int = TestConfigPrototype("int config_content_iget_as_int( config_content , char* , int , int)") -_iget_as_bool = TestConfigPrototype("bool config_content_iget_as_bool( config_content , char* , int , int)") -_iget_as_double = TestConfigPrototype("double config_content_iget_as_double( config_content , char* , int , int)") -_get_occurences = TestConfigPrototype("int config_content_get_occurences( config_content , char* )") - - -class ConfigTest(ExtendedTestCase): - def setUp( self ): - self.file_list = [] - - - def test_enums(self): - source_file_path = "libconfig/include/ert/config/config_schema_item.h" - self.assertEnumIsFullyDefined(ContentTypeEnum, "config_item_types", source_file_path) - self.assertEnumIsFullyDefined(UnrecognizedEnum, "config_schema_unrecognized_enum", source_file_path) - - - def test_item_types(self): - with TestAreaContext("config/types") as test_area: - with open("config" , "w") as f: - f.write("TYPE_ITEM 10 3.14 TruE String file\n") - - conf = ConfigParser() - schema_item = conf.add("TYPE_ITEM", False) - schema_item.iset_type(0 , ContentTypeEnum.CONFIG_INT ) - schema_item.iset_type(1 , ContentTypeEnum.CONFIG_FLOAT ) - schema_item.iset_type(2 , ContentTypeEnum.CONFIG_BOOL ) - schema_item.iset_type(3 , ContentTypeEnum.CONFIG_STRING ) - schema_item.iset_type(4 , ContentTypeEnum.CONFIG_PATH ) - self.assertFalse( "TYPE_XX" in conf ) - self.assertTrue( "TYPE_ITEM" in conf ) - - content = conf.parse("config") - type_item = content["TYPE_ITEM"][0] - int_value = type_item[0] - self.assertEqual( int_value , 10 ) - self.assertEqual( type_item.igetString(0) , "10") - - float_value = type_item[1] - self.assertEqual( float_value , 3.14 ) - self.assertEqual( type_item.igetString(1) , "3.14") - - bool_value = type_item[2] - self.assertEqual( bool_value , True) - self.assertEqual( type_item.igetString(2) , "TruE") - - string_value = type_item[3] - self.assertEqual( string_value , "String") - self.assertEqual( type_item.igetString(3) , "String") - - path_value = type_item[4] - self.assertEqual( path_value , "file") - self.assertEqual( type_item.igetString(4) , "file") - - - - - - def test_parse(self): - conf = ConfigParser() - conf.add("FIELD", False) - schema_item = conf.add("RSH_HOST", False) - self.assertIsInstance(schema_item, SchemaItem) - test_path = self.createTestPath("local/config/simple_config") - content = conf.parse(test_path, unrecognized=UnrecognizedEnum.CONFIG_UNRECOGNIZED_IGNORE) - self.assertTrue( content.isValid() ) - - - content_item = content["RSH_HOST"] - self.assertIsInstance(content_item, ContentItem) - self.assertEqual(len(content_item), 1) - with self.assertRaises(TypeError): - content_item["BJARNE"] - - with self.assertRaises(IndexError): - content_item[10] - - content_node = content_item[0] - self.assertIsInstance(content_node, ContentNode) - self.assertEqual(len(content_node), 2) - self.assertEqual(content_node[1], "be-lx633214:2") - self.assertEqual(content_node.content(sep=","), "be-lx655082:2,be-lx633214:2") - self.assertEqual(content_node.content(), "be-lx655082:2 be-lx633214:2") - - - content_item = content["FIELD"] - self.assertEqual(len(content_item), 5) - with self.assertRaises(IOError): - conf.parse("DoesNotExits") - - - def test_parse_invalid(self): - conf = ConfigParser() - conf.add("INT", value_type = ContentTypeEnum.CONFIG_INT ) - with TestAreaContext("config/parse2"): - with open("config","w") as fileH: - fileH.write("INT xx\n") - - with self.assertRaises(ValueError): - conf.parse("config") - - content = conf.parse("config" , validate = False ) - self.assertFalse( content.isValid() ) - self.assertEqual( len(content.getErrors()) , 1 ) - - - def test_parse_deprecated(self): - conf = ConfigParser() - item = conf.add("INT", value_type = ContentTypeEnum.CONFIG_INT ) - msg = "ITEM INT IS DEPRECATED" - item.setDeprecated( msg ) - with TestAreaContext("config/parse2"): - with open("config","w") as fileH: - fileH.write("INT 100\n") - - content = conf.parse("config" ) - self.assertTrue( content.isValid() ) - - warnings = content.getWarnings() - self.assertEqual( len(warnings) , 1 ) - self.assertEqual( warnings[0] , msg ) - - - def test_parse_dotdot_relative(self): - conf = ConfigParser() - schema_item = conf.add("EXECUTABLE", False) - schema_item.iset_type(0 , ContentTypeEnum.CONFIG_PATH ) - - - with TestAreaContext("config/parse_dotdot"): - os.makedirs("cwd/jobs") - os.makedirs("eclipse/bin") - script_path = os.path.join( os.getcwd() , "eclipse/bin/script.sh") - with open(script_path,"w") as f: - f.write("This is a test script") - - with open("cwd/jobs/JOB","w") as fileH: - fileH.write("EXECUTABLE ../../eclipse/bin/script.sh\n") - - os.makedirs("cwd/ert") - os.chdir("cwd/ert") - content = conf.parse("../jobs/JOB") - item = content["EXECUTABLE"] - node = item[0] - self.assertEqual( script_path , node.getPath( )) - - - - - - def test_parser_content(self): - conf = ConfigParser() - conf.add("KEY2", False) - schema_item = conf.add("KEY", False) - schema_item.iset_type(2 , ContentTypeEnum.CONFIG_INT ) - schema_item.iset_type(3 , ContentTypeEnum.CONFIG_BOOL ) - schema_item.iset_type(4 , ContentTypeEnum.CONFIG_FLOAT ) - schema_item.iset_type(5 , ContentTypeEnum.CONFIG_PATH ) - schema_item = conf.add("NOT_IN_CONTENT", False) - - - with TestAreaContext("config/parse2"): - with open("config","w") as fileH: - fileH.write("KEY VALUE1 VALUE2 100 True 3.14 path/file.txt\n") - - cwd0 = os.getcwd( ) - os.makedirs("tmp") - os.chdir("tmp") - content = conf.parse("../config") - self.assertTrue( content.isValid() ) - self.assertTrue( "KEY" in content ) - self.assertFalse( "NOKEY" in content ) - - self.assertFalse( "NOT_IN_CONTENT" in content ) - item = content["NOT_IN_CONTENT"] - self.assertEqual( len(item) , 0 ) - - with self.assertRaises(KeyError): - content["Nokey"] - - item = content["KEY"] - self.assertEqual(len(item) , 1) - - line = item[0] - with self.assertRaises(TypeError): - line.getPath(4) - - with self.assertRaises(TypeError): - line.getPath() - - - rel_path = line.getPath(index = 5, absolute = False) - self.assertEqual( rel_path , "../path/file.txt" ) - get = line[5] - self.assertEqual( get , "../path/file.txt") - abs_path = line.getPath(index = 5) - self.assertEqual( abs_path , os.path.join(cwd0 , "path/file.txt")) - - rel_path = line.getPath(index = 5, absolute = False , relative_start = "../") - self.assertEqual( rel_path , "path/file.txt" ) - - - with self.assertRaises(IndexError): - item[10] - - node = item[0] - self.assertEqual(len(node) , 6) - with self.assertRaises(IndexError): - node[6] - - self.assertEqual( node[0] , "VALUE1" ) - self.assertEqual( node[1] , "VALUE2" ) - self.assertEqual( node[2] , 100 ) - self.assertEqual( node[3] , True ) - self.assertEqual( node[4] , 3.14) - - self.assertEqual( content.getValue( "KEY" , 0 , 1 ) , "VALUE2" ) - self.assertEqual( _iget( content , "KEY" , 0 , 1) , "VALUE2") - - self.assertEqual( content.getValue( "KEY" , 0 , 2 ) , 100 ) - self.assertEqual( _iget_as_int( content , "KEY" , 0 , 2) , 100) - - self.assertEqual( content.getValue( "KEY" , 0 , 3 ) , True ) - self.assertEqual( _iget_as_bool( content , "KEY" , 0 , 3) , True) - - self.assertEqual( content.getValue( "KEY" , 0 , 4 ) , 3.14 ) - self.assertEqual( _iget_as_double( content , "KEY" , 0 , 4) , 3.14) - - self.assertIsNone( _safe_iget( content , "KEY2" , 0 , 0)) - - self.assertEqual( _get_occurences( content , "KEY2" ) , 0) - self.assertEqual( _get_occurences( content , "KEY" ) , 1) - self.assertEqual( _get_occurences( content , "MISSING-KEY" ) , 0) - - - - def test_schema(self): - schema_item = SchemaItem("TestItem") - self.assertIsInstance(schema_item, SchemaItem) - self.assertEqual(schema_item.iget_type(6), ContentTypeEnum.CONFIG_STRING) - schema_item.iset_type(0, ContentTypeEnum.CONFIG_INT) - self.assertEqual(schema_item.iget_type(0), ContentTypeEnum.CONFIG_INT) - schema_item.set_argc_minmax(3, 6) - - self.assertTrue( SchemaItem.validString( ContentTypeEnum.CONFIG_INT , "100") ) - self.assertFalse( SchemaItem.validString( ContentTypeEnum.CONFIG_INT , "100.99") ) - self.assertTrue( SchemaItem.validString( ContentTypeEnum.CONFIG_FLOAT , "100.99") ) - self.assertFalse( SchemaItem.validString( ContentTypeEnum.CONFIG_FLOAT , "100.99X") ) - self.assertTrue( SchemaItem.validString( ContentTypeEnum.CONFIG_STRING , "100.99XX") ) - self.assertTrue( SchemaItem.validString( ContentTypeEnum.CONFIG_PATH , "100.99XX") ) - - - del schema_item - - - - - def test_settings(self): - cs = ConfigSettings("SETTINGS") - - with self.assertRaises(TypeError): - cs.addSetting("SETTING1" , ContentTypeEnum.CONFIG_INT , 100.67) - - self.assertFalse( "SETTING1" in cs ) - cs.addSetting("SETTING2" , ContentTypeEnum.CONFIG_INT , 100) - self.assertTrue( "SETTING2" in cs ) - - with self.assertRaises(KeyError): - value = cs["NO_SUCH_KEY"] - - self.assertEqual( cs["SETTING2"] , 100 ) - - with self.assertRaises(KeyError): - cs["NO_SUCH_KEY"] = 100 - - - parser = ConfigParser() - cs = ConfigSettings("SETTINGS") - cs.addSetting("A" , ContentTypeEnum.CONFIG_INT , 1) - cs.addSetting("B" , ContentTypeEnum.CONFIG_INT , 1) - cs.addSetting("C" , ContentTypeEnum.CONFIG_INT , 1) - cs.initParser( parser ) - - - with TestAreaContext("config/parse3"): - with open("config","w") as fileH: - fileH.write("SETTINGS A 100\n") - fileH.write("SETTINGS B 200\n") - fileH.write("SETTINGS C 300\n") - - content = parser.parse( "config" ) - cs.apply( content ) - self.assertEqual( cs["A"] , 100) - self.assertEqual( cs["B"] , 200) - self.assertEqual( cs["C"] , 300) - - keys = cs.keys() - self.assertTrue("A" in keys ) - self.assertTrue("B" in keys ) - self.assertTrue("C" in keys ) - self.assertEqual( len(keys) , 3 ) - - cs = ConfigSettings("SETTINGS") - cs.addDoubleSetting("A" , 1.0) - self.assertEqual( ContentTypeEnum.CONFIG_FLOAT , cs.getType("A")) - - cs = ConfigSettings("SETTINGS") - cs.addDoubleSetting("A" , 1.0) - cs.addIntSetting("B" , 1) - cs.addStringSetting("C" , "1") - cs.addBoolSetting("D" , True) - cs.initParser( parser ) - - with TestAreaContext("config/parse4"): - with open("config","w") as fileH: - fileH.write("SETTINGS A 100.1\n") - fileH.write("SETTINGS B 200\n") - fileH.write("SETTINGS C 300\n") - fileH.write("SETTINGS D False\n") - - content = parser.parse( "config" ) - - cs.apply( content ) - self.assertEqual( cs["A"] , 100.1) - self.assertEqual( cs["B"] , 200) - self.assertEqual( cs["C"] , "300") - self.assertEqual( cs["D"] , False) - - with self.assertRaises(Exception): - cs["A"] = "Hei" - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/enkf/CMakeLists.txt deleted file mode 100644 index 4b3640bff4..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/CMakeLists.txt +++ /dev/null @@ -1,87 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_active_list.py - test_analysis_config.py - test_analysis_iter_config.py - test_block_obs.py - test_custom_kw_config_set.py - test_ecl_config.py - test_es_update.py - test_enkf.py - test_enkf_fs.py - test_enkf_fs_manager1.py - test_enkf_fs_manager2.py - test_enkf_library.py - test_enkf_load_results_manually.py - test_enkf_obs.py - test_ert_context.py - test_ert_log.py - test_gen_obs.py - test_labscale.py - test_linalg.py - test_local_obsdata_node.py - test_local_config.py - test_meas_block.py - test_meas_data.py - test_obs_block.py - test_obs_data.py - test_state_map.py - test_summary_key_matcher.py - test_summary_key_set.py - test_summary_obs.py - test_time_map.py - test_update.py - test_ensemble_config.py - test_deprecation.py - test_field_config.py - test_field_export.py - test_hook_workflow.py - test_forward_load_context.py - test_runpath_list.py -) - -add_python_package("python.tests.ert.enkf" ${PYTHON_INSTALL_PREFIX}/tests/ert/enkf "${TEST_SOURCES}" False) -addPythonTest(ert.enkf.es_update tests.ert.enkf.test_es_update.ESUpdateTest) -addPythonTest(ert.enkf.forward_load_context tests.ert.enkf.test_forward_load_context.ForwardLoadContextTest) -addPythonTest(ert.enkf.deprecation tests.ert.enkf.test_deprecation.DeprecationTest) -addPythonTest(ert.enkf.meas_block tests.ert.enkf.test_meas_block.MeasBlockTest) -addPythonTest(ert.enkf.meas_data tests.ert.enkf.test_meas_data.MeasDataTest) -addPythonTest(ert.enkf.obs_data tests.ert.enkf.test_obs_data.ObsDataTest) -addPythonTest(ert.enkf.gen_obs tests.ert.enkf.test_gen_obs.GenObsTest) -addPythonTest(ert.enkf.summary_obs tests.ert.enkf.test_summary_obs.SummaryObsTest) -addPythonTest(ert.enkf.block_obs tests.ert.enkf.test_block_obs.BlockObsTest) -addPythonTest(ert.enkf.obs_block tests.ert.enkf.test_obs_block.ObsBlockTest) -addPythonTest(ert.enkf.ert_log tests.ert.enkf.test_ert_log.ErtLogTest) -addPythonTest(ert.enkf.analysis_config tests.ert.enkf.test_analysis_config.AnalysisConfigTest) -addPythonTest(ert.enkf.analysis_iter_config tests.ert.enkf.test_analysis_iter_config.AnalysisIterConfigTest) -addPythonTest(ert.enkf.state_map tests.ert.enkf.test_state_map.StateMapTest) -addPythonTest(ert.enkf.custom_kw_config_set tests.ert.enkf.test_custom_kw_config_set.CustomKWConfigSetTest) -addPythonTest(ert.enkf.summary_key_matcher tests.ert.enkf.test_summary_key_matcher.SummaryKeyMatcherTest) -addPythonTest(ert.enkf.time_map tests.ert.enkf.test_time_map.TimeMapTest) -addPythonTest(ert.enkf.active_list tests.ert.enkf.test_active_list.ActiveListTest) -addPythonTest(ert.enkf.local_obsdata_node tests.ert.enkf.test_local_obsdata_node.LocalObsdataNodeTest) -addPythonTest(ert.enkf.local_config tests.ert.enkf.test_local_config.LocalConfigTest) -addPythonTest(ert.enkf.ensemble_config tests.ert.enkf.test_ensemble_config.EnsembleConfigTest) -addPythonTest(ert.enkf.hook_workflow tests.ert.enkf.test_hook_workflow.HookWorkFlowTest) -addPythonTest(ert.enkf.runpath_list tests.ert.enkf.test_runpath_list.RunpathListTest) -addPythonTest(ert.enkf.field_config tests.ert.enkf.test_field_config.FieldConfigTest) - -if (STATOIL_TESTDATA_ROOT) - addPythonTest(ert.enkf.enkf tests.ert.enkf.test_enkf.EnKFTest LABELS StatoilData) - addPythonTest(ert.enkf.enkf_obs tests.ert.enkf.test_enkf_obs.EnKFObsTest LABELS StatoilData) - addPythonTest(ert.enkf.enkf_load_results_manually tests.ert.enkf.test_enkf_load_results_manually.LoadResultsManuallyTest LABELS StatoilData) - addPythonTest(ert.enkf.enkf_fs tests.ert.enkf.test_enkf_fs.EnKFFSTest LABELS StatoilData) - addPythonTest(ert.enkf.enkf_fs_manager1 tests.ert.enkf.test_enkf_fs_manager1.EnKFFSManagerTest1 LABELS StatoilData) - addPythonTest(ert.enkf.enkf_fs_manager2 tests.ert.enkf.test_enkf_fs_manager2.EnKFFSManagerTest2 LABELS StatoilData) - addPythonTest(ert.enkf.enkf_library tests.ert.enkf.test_enkf_library.EnKFLibraryTest) - addPythonTest(ert.enkf.summary_key_set tests.ert.enkf.test_summary_key_set.SummaryKeySetTest LABELS StatoilData) - addPythonTest(ert.enkf.ecl_config tests.ert.enkf.test_ecl_config.EclConfigTest LABELS StatoilData) - addPythonTest(ert.enkf.ert_test_context tests.ert.enkf.test_ert_context.ErtTestContextTest LABELS StatoilData) - addPythonTest(ert.enkf.update tests.ert.enkf.test_update.UpdateTest LABELS StatoilData) - addPythonTest(ert.enkf.labscale tests.ert.enkf.test_labscale.LabScaleTest LABELS StatoilData) - addPythonTest(ert.enkf.field_export tests.ert.enkf.test_field_export.FieldExportTest LABELS StatoilData) -endif() - -add_subdirectory(data) -add_subdirectory(export) -add_subdirectory(plot) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/__init__.py b/ThirdParty/Ert/python/tests/ert/enkf/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/ert/enkf/data/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/enkf/data/CMakeLists.txt deleted file mode 100644 index 2f2d27be53..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/data/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_custom_kw.py - test_custom_kw_config.py - test_field_config.py - test_gen_data.py - test_gen_data_config.py - test_gen_kw.py - test_gen_kw_config.py -) - -add_python_package("python.tests.ert.enkf.data" ${PYTHON_INSTALL_PREFIX}/tests/ert/enkf/data "${TEST_SOURCES}" False) - -addPythonTest(ert.enkf.data.custom_kw tests.ert.enkf.data.test_custom_kw.CustomKWTest) -addPythonTest(ert.enkf.data.gen_kw tests.ert.enkf.data.test_gen_kw.GenKwTest) - -if (STATOIL_TESTDATA_ROOT) - addPythonTest(ert.enkf.data.gen_kw_config tests.ert.enkf.data.test_gen_kw_config.GenKwConfigTest LABELS StatoilData) - addPythonTest(ert.enkf.data.gen_data tests.ert.enkf.data.test_gen_data.GenDataTest LABELS StatoilData) - addPythonTest(ert.enkf.data.gen_data_config tests.ert.enkf.data.test_gen_data_config.GenDataConfigTest LABELS StatoilData) -endif() diff --git a/ThirdParty/Ert/python/tests/ert/enkf/data/__init__.py b/ThirdParty/Ert/python/tests/ert/enkf/data/__init__.py deleted file mode 100644 index 8b13789179..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/data/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/data/test_custom_kw.py b/ThirdParty/Ert/python/tests/ert/enkf/data/test_custom_kw.py deleted file mode 100644 index 804127472b..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/data/test_custom_kw.py +++ /dev/null @@ -1,123 +0,0 @@ -import os -from ert.enkf.config import CustomKWConfig -from ert.enkf.data import CustomKW -from ert.enkf.enkf_simulation_runner import EnkfSimulationRunner -from ert.enkf.export import custom_kw_collector -from ert.enkf.export.custom_kw_collector import CustomKWCollector -from ert.test.ert_test_context import ErtTestContext -from ert.test.extended_testcase import ExtendedTestCase -from ert.test.test_area import TestAreaContext -from ert.util import StringList - - -class CustomKWTest(ExtendedTestCase): - - def createResultFile(self, filename, data): - with open(filename, "w") as output_file: - for key in data: - output_file.write("%s %s\n" % (key, data[key])) - - def test_custom_kw_creation(self): - data = {"VALUE_1": 2345.234, - "VALUE_2": 0.001234, - "VALUE_3": "string_1", - "VALUE_4": "string_2"} - - with TestAreaContext("python/enkf/data/custom_kw_creation") as test_area: - - self.createResultFile("result_file", data) - - custom_kw_config = CustomKWConfig("CUSTOM_KW", "result_file") - - self.assertEqual(len(custom_kw_config), 0) - - custom_kw = CustomKW(custom_kw_config) - - custom_kw.fload("result_file") - - self.assertEqual(len(custom_kw_config), 4) - - for key in data: - index = custom_kw_config.indexOfKey(key) - self.assertEqual(data[key], custom_kw[key]) - - with self.assertRaises(KeyError): - value = custom_kw["VALUE_5"] - - - - def test_custom_kw_config_data_is_null(self): - data_1 = {"VALUE_1": 123453.3, - "VALUE_2": 0.234234} - - data_2 = {"VALUE_1": 965689, - "VALUE_3": 1.1222} - - with TestAreaContext("python/enkf/data/custom_kw_null_element") as test_area: - - self.createResultFile("result_file_1", data_1) - self.createResultFile("result_file_2", data_2) - - custom_kw_config = CustomKWConfig("CUSTOM_KW", "result_file") - - custom_kw_1 = CustomKW(custom_kw_config) - custom_kw_1.fload("result_file_1") - - custom_kw_2 = CustomKW(custom_kw_config) - custom_kw_2.fload("result_file_2") - - index_1 = custom_kw_config.indexOfKey("VALUE_1") - index_2 = custom_kw_config.indexOfKey("VALUE_2") - - self.assertEqual(custom_kw_1["VALUE_1"], data_1["VALUE_1"]) - self.assertEqual(custom_kw_2["VALUE_1"], data_2["VALUE_1"]) - - self.assertIsNone(custom_kw_2["VALUE_2"]) - self.assertFalse( "VALUE_3" in custom_kw_config ) - - - - def test_simulated_custom_kw(self): - config = self.createTestPath("local/custom_kw/mini_config") - with ErtTestContext("python/enkf/data/custom_kw_simulated", config) as context: - ert = context.getErt() - - ensemble_config = ert.ensembleConfig() - self.assertTrue("AGGREGATED" in ensemble_config) - - config = ensemble_config.getNode("AGGREGATED").getCustomKeywordModelConfig() - - self.assertEqual(len(config.getKeys()), 0) - - simulation_runner = EnkfSimulationRunner(ert) - simulation_runner.runEnsembleExperiment() - - config = ensemble_config.getNode("AGGREGATED").getCustomKeywordModelConfig() - - self.assertEqual(len(config.getKeys()), 4) - self.assertItemsEqual(config.getKeys(), ["PERLIN_1", "PERLIN_2", "PERLIN_3", "STATE"]) - - - def test_custom_kw_set_values(self): - definition = { - "STRING": str, - "FLOAT": float, - "INT": float - } - - ckwc = CustomKWConfig("Test", None, definition=definition) - - ckw = CustomKW(ckwc) - with self.assertRaises(KeyError): - ckw["ANOTHER_STRING"] = "another string" - - ckw["STRING"] = "string" - ckw["FLOAT"] = 3.1415 - ckw["INT"] = 1 - - self.assertEqual(ckw["STRING"], "string") - self.assertEqual(ckw["FLOAT"], 3.1415) - self.assertEqual(ckw["INT"], 1) - - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/data/test_custom_kw_config.py b/ThirdParty/Ert/python/tests/ert/enkf/data/test_custom_kw_config.py deleted file mode 100644 index a57b4dc9e8..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/data/test_custom_kw_config.py +++ /dev/null @@ -1,130 +0,0 @@ -from ert.enkf.config.custom_kw_config import CustomKWConfig -from ert.test.extended_testcase import ExtendedTestCase -from ert.test.test_area import TestAreaContext -from ert.util import StringList - - -class CustomKWConfigTest(ExtendedTestCase): - - def createResultFile(self, filename, data): - with open(filename, "w") as output_file: - for key in data: - output_file.write("%s %s\n" % (key, data[key])) - - def test_custom_kw_config_creation(self): - data = {"VALUE_1": 2345.234, - "VALUE_2": 0.001234, - "VALUE_3": "string_1", - "VALUE_4": "string_2"} - - with TestAreaContext("python/enkf/data/custom_kw_config") as test_area: - - self.createResultFile("result_file", data) - - custom_kw_config = CustomKWConfig("CUSTOM_KW", "result_file", "output_file") - - self.assertEqual(custom_kw_config.getName(), "CUSTOM_KW") - self.assertEqual(custom_kw_config.getResultFile(), "result_file") - self.assertEqual(custom_kw_config.getOutputFile(), "output_file") - - self.assertEqual(len(custom_kw_config), 0) - - result = StringList() - success = custom_kw_config.parseResultFile("result_file", result) - self.assertTrue(success) - - self.assertEqual(len(custom_kw_config), 4) - - for index, key in enumerate(data): - self.assertTrue(key in custom_kw_config) - - key_is_string = isinstance(data[key], str) - self.assertTrue(custom_kw_config.keyIsDouble(key) != key_is_string) - self.assertEqual(index, custom_kw_config.indexOfKey(key)) - - self.assertEqual(result[index], str(data[key])) - - self.assertTrue(len(custom_kw_config.getKeys()) == 4) - - for key in custom_kw_config: - self.assertTrue(key in data) - - - def test_custom_kw_config_multiple_identical_keys(self): - data = {"VALUE_1": 2345.234, - "VALUE_2": 0.001234, - "VALUE_3": "string_1", - "VALUE_4": "string_2 VALUE_4 repeat_of_value_4"} - - with TestAreaContext("python/enkf/data/custom_kw_config_multiple_identical_keys") as test_area: - - self.createResultFile("result_file", data) - - custom_kw_config = CustomKWConfig("CUSTOM_KW", "result_file") - - result = StringList() - success = custom_kw_config.parseResultFile("result_file", result) - self.assertTrue(success) - - index_of_value_4 = custom_kw_config.indexOfKey("VALUE_4") - self.assertEqual(result[index_of_value_4], "repeat_of_value_4") - - - - def test_custom_kw_config_define_and_read(self): - data_1 = {"VALUE_1": 123453.3, - "VALUE_2": 0.234234} - - data_2 = {"VALUE_1": 965689, - "VALUE_3": 1.1222} - - with TestAreaContext("python/enkf/data/custom_kw_config") as test_area: - - self.createResultFile("result_file_1", data_1) - self.createResultFile("result_file_2", data_2) - - custom_kw_config = CustomKWConfig("CUSTOM_KW", "result_file") - - result_1 = StringList() - success = custom_kw_config.parseResultFile("result_file_1", result_1) - self.assertTrue(success) - - result_2 = StringList() - success = custom_kw_config.parseResultFile("result_file_2", result_2) - self.assertFalse(success) - - for key in custom_kw_config: - self.assertTrue(key in data_1) - - self.assertFalse("VALUE_3" in custom_kw_config) - - - - - def test_custom_kw_config_parse_fail(self): - data = {"KEY_1": "Value Key_2"} - - with TestAreaContext("python/enkf/data/custom_kw_config_fail") as test_area: - - self.createResultFile("result_file", data) - - custom_kw_config = CustomKWConfig("CUSTOM_KW_FAIL", "result_file") - self.assertIsNone(custom_kw_config.getOutputFile()) - - self.assertFalse(custom_kw_config.parseResultFile("result_file", StringList())) - - - def test_custom_kw_config_construction_with_definition(self): - definition = { - "VALUE_1": float, - "VALUE_2": str - } - custom_kw_config = CustomKWConfig("TEST", None, definition=definition) - self.assertEqual(len(custom_kw_config.getKeys()), 2) - - self.assertTrue(custom_kw_config.keyIsDouble("VALUE_1")) - self.assertFalse(custom_kw_config.keyIsDouble("VALUE_2")) - - self.assertIn("VALUE_1", custom_kw_config) - self.assertIn("VALUE_2", custom_kw_config) - self.assertNotIn("VALUE_3", custom_kw_config) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/enkf/data/test_field_config.py b/ThirdParty/Ert/python/tests/ert/enkf/data/test_field_config.py deleted file mode 100644 index 04ba9303c9..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/data/test_field_config.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'test_field_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import os - -from ert.enkf import FieldConfig -from ert.enkf import ActiveList -from ert.test import ExtendedTestCase -from ert.ecl import EclGrid - -class FieldConfigTest(ExtendedTestCase): - - def test_create(self): - grid = EclGrid.createRectangular( (10,10,5) , (1,1,1) ) - field_config = FieldConfig("SWAT" , grid) - - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_data.py b/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_data.py deleted file mode 100644 index 2d4f80b617..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_data.py +++ /dev/null @@ -1,30 +0,0 @@ -import ert - -from ert.enkf.data.enkf_node import EnkfNode -from ert.enkf.node_id import NodeId -from ert.test import ErtTestContext -from ert.test.extended_testcase import ExtendedTestCase -from ert.util import BoolVector - - -class GenDataTest(ExtendedTestCase): - def setUp(self): - self.config_file = self.createTestPath("Statoil/config/with_GEN_DATA/config") - - - def test_create(self): - with ErtTestContext("gen_data_test", self.config_file) as test_context: - ert = test_context.getErt() - fs1 = ert.getEnkfFsManager().getCurrentFileSystem() - config_node = ert.ensembleConfig().getNode("TIMESHIFT") - - data_node = EnkfNode(config_node) - data_node.tryLoad(fs1, NodeId(60, 0)) - - gen_data = data_node.asGenData() - data = gen_data.getData() - - self.assertEqual(len(data) , 2560) - - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_data_config.py b/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_data_config.py deleted file mode 100644 index 9f06a307bd..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_data_config.py +++ /dev/null @@ -1,74 +0,0 @@ -import ert - -from ert.enkf.data import EnkfNode -from ert.enkf.config import GenDataConfig -from ert.enkf import EnkfPrototype -from ert.enkf import NodeId -from ert.enkf import ForwardLoadContext -from ert.test import ErtTestContext, ExtendedTestCase -from ert.util import BoolVector - -class GenDataConfigTest(ExtendedTestCase): - _get_active_mask = EnkfPrototype("bool_vector_ref gen_data_config_get_active_mask( gen_data_config )", bind = False) - _update_active_mask = EnkfPrototype("void gen_data_config_update_active( gen_data_config, forward_load_context , bool_vector)", bind = False) - _alloc_run_arg = EnkfPrototype("run_arg_obj run_arg_alloc_ENSEMBLE_EXPERIMENT( enkf_fs , int , int , char*) ", bind = False) - - def setUp(self): - self.config_file = self.createTestPath("Statoil/config/with_GEN_DATA/config") - - def load_active_masks(self, case1, case2 ): - with ErtTestContext("gen_data_config_test", self.config_file) as test_context: - ert = test_context.getErt() - - fs1 = ert.getEnkfFsManager().getFileSystem(case1) - config_node = ert.ensembleConfig().getNode("TIMESHIFT") - data_node = EnkfNode(config_node) - data_node.tryLoad(fs1, NodeId(60, 0)) - - active_mask = self._get_active_mask( config_node.getDataModelConfig() ) - first_active_mask_length = len(active_mask) - self.assertEqual(first_active_mask_length, 2560) - - fs2 = ert.getEnkfFsManager().getFileSystem(case2) - data_node = EnkfNode(config_node) - data_node.tryLoad(fs2, NodeId(60, 0)) - - active_mask = self._get_active_mask( config_node.getDataModelConfig() ) - second_active_mask_len = len(active_mask) - self.assertEqual(second_active_mask_len, 2560) - self.assertEqual(first_active_mask_length, second_active_mask_len) - - # Setting one element to False, load different case, check, reload, and check. - self.assertTrue(active_mask[10]) - active_mask_modified = active_mask.copy() - active_mask_modified[10] = False - - self.updateMask(config_node.getDataModelConfig(), 60, fs2 , active_mask_modified) - active_mask = self._get_active_mask( config_node.getDataModelConfig() ) - self.assertFalse(active_mask[10]) - - #Load first - check element is true - data_node = EnkfNode(config_node) - data_node.tryLoad(fs1, NodeId(60, 0)) - active_mask = self._get_active_mask( config_node.getDataModelConfig() ) - self.assertTrue(active_mask[10]) - - # Reload second again, should now be false at 10, due to the update further up - data_node = EnkfNode(config_node) - data_node.tryLoad(fs2, NodeId(60, 0)) - active_mask = self._get_active_mask( config_node.getDataModelConfig() ) - self.assertFalse(active_mask[10]) - - - def test_loading_two_cases_with_and_without_active_file(self): - self.load_active_masks("missing-active", "default") - - - - def test_create(self): - conf = GenDataConfig("KEY") - - def updateMask(self, gen_data_config , report_step , fs, active_mask): - run_arg = self._alloc_run_arg( fs , 0 , 0 , "Path") - load_context = ForwardLoadContext( run_arg = run_arg , report_step = report_step ) - self._update_active_mask( gen_data_config , load_context , active_mask ) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_kw.py b/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_kw.py deleted file mode 100644 index 63716dfffc..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_kw.py +++ /dev/null @@ -1,134 +0,0 @@ -import os.path -from ert.enkf.data import GenKw -from ert.enkf.config import GenKwConfig -from ert.test import TestAreaContext, ExtendedTestCase - - -def create_gen_kw(): - parameter_file ="MULTFLT.txt" - template_file ="MULTFLT.tmpl" - with open(parameter_file, "w") as f: - f.write("MULTFLT1 NORMAL 0 1\n") - f.write("MULTFLT2 RAW \n") - f.write("MULTFLT3 NORMAL 0 1\n") - - with open(template_file, "w") as f: - f.write(" \n") - f.write("/\n") - - - gen_kw_config = GenKwConfig("MULTFLT", template_file , parameter_file) - gen_kw = GenKw( gen_kw_config ) - - return (gen_kw_config , gen_kw) - - - -class GenKwTest(ExtendedTestCase): - - def test_gen_kw_get_set(self): - with TestAreaContext("enkf/data/gen_kwt"): - - (gen_kw_config , gen_kw) = create_gen_kw() - self.assertIsInstance(gen_kw, GenKw) - - gen_kw[0] = 3.0 - self.assertEqual(gen_kw[0], 3.0) - - gen_kw["MULTFLT1"] = 4.0 - self.assertEqual(gen_kw["MULTFLT1"], 4.0) - self.assertEqual(gen_kw[0], 4.0) - - gen_kw["MULTFLT2"] = 8.0 - self.assertEqual(gen_kw["MULTFLT2"], 8.0) - self.assertEqual(gen_kw[1], 8.0) - - gen_kw["MULTFLT3"] = 12.0 - self.assertEqual(gen_kw["MULTFLT3"], 12.0) - self.assertEqual(gen_kw[2], 12.0) - - self.assertEqual(len(gen_kw), 3) - - with self.assertRaises(IndexError): - gen_kw[4] - - with self.assertRaises(TypeError): - gen_kw[1.5] - - with self.assertRaises(KeyError): - gen_kw["MULTFLT_2"] - - self.assertTrue("MULTFLT1" in gen_kw ) - - items = gen_kw.items() - self.assertEqual( len(items) , 3 ) - self.assertEqual( items[0][0] , "MULTFLT1" ) - self.assertEqual( items[1][0] , "MULTFLT2" ) - self.assertEqual( items[2][0] , "MULTFLT3" ) - - self.assertEqual( items[0][1] , 4) - self.assertEqual( items[1][1] , 8) - self.assertEqual( items[2][1] , 12) - - - - def test_gen_kw_get_set_vector(self): - with TestAreaContext("enkf/data/gen_kwt"): - - (gen_kw_config , gen_kw) = create_gen_kw() - with self.assertRaises(ValueError): - gen_kw.setValues([0]) - - with self.assertRaises(TypeError): - gen_kw.setValues(["A","B","C"]) - - gen_kw.setValues([0,1,2]) - self.assertEqual(gen_kw[0], 0) - self.assertEqual(gen_kw[1], 1) - self.assertEqual(gen_kw[2], 2) - - self.assertEqual(gen_kw["MULTFLT1"] , 0) - self.assertEqual(gen_kw["MULTFLT2"] , 1) - self.assertEqual(gen_kw["MULTFLT3"] , 2) - - - - - - def test_gen_kw_ecl_write(self): - with TestAreaContext("enkf/data/gen_kwt"): - (gen_kw_config , gen_kw) = create_gen_kw() - - with self.assertRaises(IOError): - gen_kw.eclWrite( "tmp" , "file.txt") - - gen_kw.eclWrite( None , "file.txt") - self.assertTrue( os.path.isfile( "file.txt" )) - - os.mkdir("tmp") - gen_kw.eclWrite( "tmp" , "file.txt") - self.assertTrue( os.path.isfile( "tmp/file.txt" )) - - gen_kw.eclWrite( "tmp" , "file.txt" , "tmp/export.txt") - self.assertTrue( os.path.isfile( "tmp/export.txt" )) - - - - - - - - - - - - - - - - - - - - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_kw_config.py b/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_kw_config.py deleted file mode 100644 index f32ad7a1e2..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/data/test_gen_kw_config.py +++ /dev/null @@ -1,55 +0,0 @@ -from ert.enkf import ErtImplType, GenKwConfig -from ert.test import ErtTestContext, ExtendedTestCase - -class GenKwConfigTest(ExtendedTestCase): - - def setUp(self): - self.config = self.createTestPath("Statoil/config/with_data/config") - - - def test_gen_kw_config(self): - - with ErtTestContext("python/enkf/data/gen_kw_config", self.config) as context: - - ert = context.getErt() - - gen_kw_keys = ert.ensembleConfig().getKeylistFromImplType(ErtImplType.GEN_KW) - - self.assertEqual(gen_kw_keys[0], "GRID_PARAMS") - - node = ert.ensembleConfig().getNode(gen_kw_keys[0]) - gen_kw_config = node.getModelConfig() - self.assertIsInstance(gen_kw_config, GenKwConfig) - - self.assertEqual(gen_kw_config.getKey(), "GRID_PARAMS") - self.assertEqual(len(gen_kw_config), 2) - - self.assertEqual(gen_kw_config[0], "MULTPV2") - self.assertEqual(gen_kw_config[1], "MULTPV3") - - self.assertFalse(gen_kw_config.shouldUseLogScale(0)) - self.assertFalse(gen_kw_config.shouldUseLogScale(1)) - - - node = ert.ensembleConfig().getNode(gen_kw_keys[1]) - gen_kw_config = node.getModelConfig() - self.assertIsInstance(gen_kw_config, GenKwConfig) - - self.assertEqual(gen_kw_config.getKey(), "MULTFLT") - - self.assertTrue(gen_kw_config.shouldUseLogScale(0)) - - - node = ert.ensembleConfig().getNode(gen_kw_keys[2]) - gen_kw_config = node.getModelConfig() - self.assertIsInstance(gen_kw_config, GenKwConfig) - - self.assertEqual(gen_kw_config.getKey(), "FLUID_PARAMS") - - self.assertFalse(gen_kw_config.shouldUseLogScale(0)) - self.assertFalse(gen_kw_config.shouldUseLogScale(1)) - - expected = ["SWCR", "SGCR"] - - for index, keyword in enumerate(gen_kw_config): - self.assertEqual(keyword, expected[index]) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/enkf/export/CMakeLists.txt deleted file mode 100644 index d59e1c5044..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_arg_loader.py - test_custom_kw_collector.py - test_design_matrix.py - test_export_join.py - test_gen_data_collector.py - test_gen_data_observation_collector.py - test_gen_kw_collector.py - test_misfit_collector.py - test_numpy_and_pandas.py - test_summary_collector.py - test_summary_observation_collector.py -) - -add_python_package("python.tests.ert.enkf.export" ${PYTHON_INSTALL_PREFIX}/tests/ert/enkf/export "${TEST_SOURCES}" False) - -addPythonTest(ert.enkf.export.custom_kw_collector tests.ert.enkf.export.test_custom_kw_collector.CustomKwCollectorTest) -addPythonTest(ert.enkf.export.design_matrix tests.ert.enkf.export.test_design_matrix.DesignMatrixTest) -addPythonTest(ert.enkf.export.export_join tests.ert.enkf.export.test_export_join.ExportJoinTest) -addPythonTest(ert.enkf.export.gen_data_collector tests.ert.enkf.export.test_gen_data_collector.GenDataCollectorTest) -addPythonTest(ert.enkf.export.gen_data_observation_collector tests.ert.enkf.export.test_gen_data_observation_collector.GenDataObservationCollectorTest) -addPythonTest(ert.enkf.export.gen_kw_collector tests.ert.enkf.export.test_gen_kw_collector.GenKwCollectorTest) -addPythonTest(ert.enkf.export.numpy_and_pandas tests.ert.enkf.export.test_numpy_and_pandas.NumpyAndPandasTest) -addPythonTest(ert.enkf.export.misfit_collector tests.ert.enkf.export.test_misfit_collector.MisfitCollectorTest) -addPythonTest(ert.enkf.export.summary_collector tests.ert.enkf.export.test_summary_collector.SummaryCollectorTest) -addPythonTest(ert.enkf.export.summary_observation_collector tests.ert.enkf.export.test_summary_observation_collector.SummaryObservationCollectorTest) - -if (STATOIL_TESTDATA_ROOT) - addPythonTest(ert.enkf.export.arg_loader tests.ert.enkf.export.test_arg_loader.ArgLoaderTest LABELS StatoilData) -endif() \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/__init__.py b/ThirdParty/Ert/python/tests/ert/enkf/export/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/test_arg_loader.py b/ThirdParty/Ert/python/tests/ert/enkf/export/test_arg_loader.py deleted file mode 100644 index 58e510271c..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/test_arg_loader.py +++ /dev/null @@ -1,24 +0,0 @@ -import math - -from ert.enkf.export import ArgLoader -from ert.test import ErtTestContext, ExtendedTestCase - -class ArgLoaderTest(ExtendedTestCase): - - - def test_arg_loader(self): - - with self.assertRaises(IOError): - arg = ArgLoader.load("arg1X") - - arg_file = self.createTestPath("Statoil/config/with_GEN_DATA_RFT/wellpath/WI_1.txt") - - with self.assertRaises(ValueError): - arg = ArgLoader.load(arg_file , column_names = ["Col1" , "Col2" , "Col3" ,"COl5" , "Col6"]) - - arg = ArgLoader.load(arg_file , column_names = ["utm_x" , "utm_y" , "md" , "tvd"]) - self.assertFloatEqual( arg["utm_x"][0] , 461317.620646) - - - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/test_custom_kw_collector.py b/ThirdParty/Ert/python/tests/ert/enkf/export/test_custom_kw_collector.py deleted file mode 100644 index dba81ea80b..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/test_custom_kw_collector.py +++ /dev/null @@ -1,40 +0,0 @@ -from ert.enkf.export import CustomKWCollector -from ert.test import ErtTestContext, ExtendedTestCase - -class CustomKwCollectorTest(ExtendedTestCase): - - def test_custom_kw_collector_non_current_fs(self): - config = self.createTestPath("local/custom_kw/mini_config") - - with ErtTestContext("python/enkf/export/custom_kw_collector_from_fs", config) as context: - ert = context.getErt() - - data = CustomKWCollector.loadAllCustomKWData(ert, "test_run") - - self.assertTrue(len(data.columns) == 0) - - - def test_custom_kw_collector_current_fs(self): - config = self.createTestPath("local/custom_kw/mini_config") - - with ErtTestContext("python/enkf/export/custom_kw_collector_from_current_fs", config) as context: - ert = context.getErt() - fs = ert.getEnkfFsManager().getFileSystem("test_run") - ert.getEnkfFsManager().switchFileSystem(fs) - data = CustomKWCollector.loadAllCustomKWData(ert, "test_run") - - self.assertFloatEqual(data["AGGREGATED:PERLIN_1"][0], -0.167794) - self.assertFloatEqual(data["AGGREGATED:PERLIN_1"][8], -1.276058) - self.assertFloatEqual(data["AGGREGATED:PERLIN_1"][9], -0.137903) - - self.assertFloatEqual(data["AGGREGATED:PERLIN_2"][0], 1.00263) - self.assertFloatEqual(data["AGGREGATED:PERLIN_2"][8], -0.105634) - self.assertFloatEqual(data["AGGREGATED:PERLIN_2"][9], 1.032522) - - self.assertFloatEqual(data["AGGREGATED:PERLIN_3"][0], 0.190479) - self.assertFloatEqual(data["AGGREGATED:PERLIN_3"][8], -0.917785) - self.assertFloatEqual(data["AGGREGATED:PERLIN_3"][9], 0.220371) - - self.assertEqual(data["AGGREGATED:STATE"][0], "Positive") - self.assertEqual(data["AGGREGATED:STATE"][8], "Negative") - self.assertEqual(data["AGGREGATED:STATE"][9], "Positive") diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/test_design_matrix.py b/ThirdParty/Ert/python/tests/ert/enkf/export/test_design_matrix.py deleted file mode 100644 index 8c513a63fa..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/test_design_matrix.py +++ /dev/null @@ -1,94 +0,0 @@ -from ert.enkf.export import DesignMatrixReader -from ert.test import ExtendedTestCase -from ert.test.test_area import TestAreaContext - -def dumpDesignMatrix1(path): - with open(path, "w") as dm: - dm.write("Case CORR_SEIS_HEIMDAL VOL_FRAC_HEIMDAL AZIM_IND_HEIMDAL VARIO_PARAL_HEIMDAL VARIO_NORM_HEIMDAL VARIO_VERT_HEIMDAL SEIS_COND_HEIMDAL\n") - dm.write("0 0.8 0.08 125 1000 500 25 ON\n") - dm.write("1 0.8 0.15 125 2000 1000 25 ON\n") - dm.write("2 0.8 0.20 125 4000 2000 25 ON\n") - - -def dumpDesignMatrix2(path): - with open(path, "w") as dm: - dm.write("Case CORR_SEIS_HEIMDAL VOL_FRAC_HEIMDAL AZIM_IND_HEIMDAL VARIO_PARAL_HEIMDAL VARIO_NORM_HEIMDAL VARIO_VERT_HEIMDAL SEIS_COND_HEIMDAL\n") - dm.write("0 0.8 0.08 125 1000 500 25 ON\n") - dm.write("1 0.8 0.15 125 2000 1000 25 ON\n") - dm.write("2 0.8 0.20 125 4000 2000 25 ON\n") - dm.write("4 0.8 0.30 125 16000 8000 25 ON\n") - - - -class DesignMatrixTest(ExtendedTestCase): - - def test_read_design_matrix(self): - with TestAreaContext("python/enkf/export/design_matrix"): - dumpDesignMatrix1("DesignMatrix.txt") - dm = DesignMatrixReader.loadDesignMatrix("DesignMatrix.txt") - - self.assertEqual(dm["CORR_SEIS_HEIMDAL"][0], 0.8) - self.assertEqual(dm["VOL_FRAC_HEIMDAL"][0], 0.08) - self.assertEqual(dm["AZIM_IND_HEIMDAL"][0], 125) - self.assertEqual(dm["VARIO_PARAL_HEIMDAL"][0], 1000) - self.assertEqual(dm["VARIO_NORM_HEIMDAL"][0], 500) - self.assertEqual(dm["VARIO_VERT_HEIMDAL"][0], 25) - self.assertEqual(dm["SEIS_COND_HEIMDAL"][0], "ON") - - self.assertEqual(dm["CORR_SEIS_HEIMDAL"][1], 0.8) - self.assertEqual(dm["VOL_FRAC_HEIMDAL"][1], 0.15) - self.assertEqual(dm["AZIM_IND_HEIMDAL"][1], 125) - self.assertEqual(dm["VARIO_PARAL_HEIMDAL"][1], 2000) - self.assertEqual(dm["VARIO_NORM_HEIMDAL"][1], 1000) - self.assertEqual(dm["VARIO_VERT_HEIMDAL"][1], 25) - self.assertEqual(dm["SEIS_COND_HEIMDAL"][1], "ON") - - self.assertEqual(dm["CORR_SEIS_HEIMDAL"][2], 0.8) - self.assertEqual(dm["VOL_FRAC_HEIMDAL"][2], 0.20) - self.assertEqual(dm["AZIM_IND_HEIMDAL"][2], 125) - self.assertEqual(dm["VARIO_PARAL_HEIMDAL"][2], 4000) - self.assertEqual(dm["VARIO_NORM_HEIMDAL"][2], 2000) - self.assertEqual(dm["VARIO_VERT_HEIMDAL"][2], 25) - self.assertEqual(dm["SEIS_COND_HEIMDAL"][2], "ON") - - - def test_read_design_matrix_2(self): - with TestAreaContext("python/enkf/export/design_matrix_2"): - dumpDesignMatrix2("DesignMatrix2.txt") - dm = DesignMatrixReader.loadDesignMatrix("DesignMatrix2.txt") - - self.assertEqual(dm["CORR_SEIS_HEIMDAL"][0], 0.8) - self.assertEqual(dm["VOL_FRAC_HEIMDAL"][0], 0.08) - self.assertEqual(dm["AZIM_IND_HEIMDAL"][0], 125) - self.assertEqual(dm["VARIO_PARAL_HEIMDAL"][0], 1000) - self.assertEqual(dm["VARIO_NORM_HEIMDAL"][0], 500) - self.assertEqual(dm["VARIO_VERT_HEIMDAL"][0], 25) - self.assertEqual(dm["SEIS_COND_HEIMDAL"][0], "ON") - - self.assertEqual(dm["CORR_SEIS_HEIMDAL"][1], 0.8) - self.assertEqual(dm["VOL_FRAC_HEIMDAL"][1], 0.15) - self.assertEqual(dm["AZIM_IND_HEIMDAL"][1], 125) - self.assertEqual(dm["VARIO_PARAL_HEIMDAL"][1], 2000) - self.assertEqual(dm["VARIO_NORM_HEIMDAL"][1], 1000) - self.assertEqual(dm["VARIO_VERT_HEIMDAL"][1], 25) - self.assertEqual(dm["SEIS_COND_HEIMDAL"][1], "ON") - - self.assertEqual(dm["CORR_SEIS_HEIMDAL"][2], 0.8) - self.assertEqual(dm["VOL_FRAC_HEIMDAL"][2], 0.20) - self.assertEqual(dm["AZIM_IND_HEIMDAL"][2], 125) - self.assertEqual(dm["VARIO_PARAL_HEIMDAL"][2], 4000) - self.assertEqual(dm["VARIO_NORM_HEIMDAL"][2], 2000) - self.assertEqual(dm["VARIO_VERT_HEIMDAL"][2], 25) - self.assertEqual(dm["SEIS_COND_HEIMDAL"][2], "ON") - - - with self.assertRaises(KeyError): - self.assertEqual(dm["CORR_SEIS_HEIMDAL"][3], 0.8) - - self.assertEqual(dm["CORR_SEIS_HEIMDAL"][4], 0.8) - self.assertEqual(dm["VOL_FRAC_HEIMDAL"][4], 0.30) - self.assertEqual(dm["AZIM_IND_HEIMDAL"][4], 125) - self.assertEqual(dm["VARIO_PARAL_HEIMDAL"][4], 16000) - self.assertEqual(dm["VARIO_NORM_HEIMDAL"][4], 8000) - self.assertEqual(dm["VARIO_VERT_HEIMDAL"][4], 25) - self.assertEqual(dm["SEIS_COND_HEIMDAL"][4], "ON") diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/test_export_join.py b/ThirdParty/Ert/python/tests/ert/enkf/export/test_export_join.py deleted file mode 100644 index a46d5e9728..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/test_export_join.py +++ /dev/null @@ -1,90 +0,0 @@ -from ert.enkf.export import DesignMatrixReader, SummaryCollector, GenKwCollector, MisfitCollector -from ert.test import ExtendedTestCase, ErtTestContext -import pandas -import numpy -import os - -def dumpDesignMatrix(path): - with open(path, "w") as dm: - dm.write("REALIZATION EXTRA_FLOAT_COLUMN EXTRA_INT_COLUMN EXTRA_STRING_COLUMN\n") - dm.write("0 0.08 125 ON\n") - dm.write("1 0.07 225 OFF\n") - dm.write("2 0.08 325 ON\n") - dm.write("3 0.06 425 ON\n") - dm.write("4 0.08 525 OFF\n") - dm.write("5 0.08 625 ON\n") - dm.write("6 0.09 725 ON\n") - dm.write("7 0.08 825 OFF\n") - dm.write("8 0.02 925 ON\n") - dm.write("9 0.08 125 ON\n") - dm.write("10 0.08 225 ON\n") - dm.write("11 0.05 325 OFF\n") - dm.write("12 0.08 425 ON\n") - dm.write("13 0.07 525 ON\n") - dm.write("14 0.08 625 UNKNOWN\n") - dm.write("15 0.08 725 ON\n") - dm.write("16 0.08 825 ON\n") - dm.write("17 0.08 925 OFF\n") - dm.write("18 0.09 125 ON\n") - dm.write("19 0.08 225 ON\n") - dm.write("20 0.06 325 OFF\n") - dm.write("21 0.08 425 ON\n") - dm.write("22 0.07 525 ON\n") - dm.write("23 0.08 625 OFF\n") - dm.write("24 0.08 725 ON\n") - -class ExportJoinTest(ExtendedTestCase): - - def setUp(self): - os.environ["TZ"] = "CET" # The ert_statoil case was generated in CET - self.config = self.createTestPath("local/snake_oil/snake_oil.ert") - - def test_join(self): - - with ErtTestContext("python/enkf/export/export_join", self.config) as context: - dumpDesignMatrix("DesignMatrix.txt") - ert = context.getErt() - - summary_data = SummaryCollector.loadAllSummaryData(ert, "default_1") - gen_kw_data = GenKwCollector.loadAllGenKwData(ert, "default_1") - misfit = MisfitCollector.loadAllMisfitData(ert, "default_1") - dm = DesignMatrixReader.loadDesignMatrix("DesignMatrix.txt") - - result = summary_data.join(gen_kw_data, how='inner') - result = result.join(misfit, how='inner') - result = result.join(dm, how='inner') - - first_date = "2010-01-10" - last_date = "2015-06-23" - - self.assertFloatEqual(result["SNAKE_OIL_PARAM:OP1_OCTAVES"][0][first_date], 3.947766) - self.assertFloatEqual(result["SNAKE_OIL_PARAM:OP1_OCTAVES"][24][first_date], 4.206698) - self.assertFloatEqual(result["SNAKE_OIL_PARAM:OP1_OCTAVES"][24][last_date], 4.206698) - - self.assertFloatEqual(result["EXTRA_FLOAT_COLUMN"][0][first_date], 0.08) - self.assertEqual(result["EXTRA_INT_COLUMN"][0][first_date], 125) - self.assertEqual(result["EXTRA_STRING_COLUMN"][0][first_date], "ON") - - self.assertFloatEqual(result["EXTRA_FLOAT_COLUMN"][0][last_date], 0.08) - self.assertEqual(result["EXTRA_INT_COLUMN"][0][last_date], 125) - self.assertEqual(result["EXTRA_STRING_COLUMN"][0][last_date], "ON") - - self.assertFloatEqual(result["EXTRA_FLOAT_COLUMN"][1][last_date], 0.07) - self.assertEqual(result["EXTRA_INT_COLUMN"][1][last_date], 225) - self.assertEqual(result["EXTRA_STRING_COLUMN"][1][last_date], "OFF") - - self.assertFloatEqual(result["MISFIT:FOPR"][0][last_date], 489.191069) - self.assertFloatEqual(result["MISFIT:FOPR"][24][last_date], 1841.906872) - - self.assertFloatEqual(result["MISFIT:TOTAL"][0][first_date], 500.170035) - self.assertFloatEqual(result["MISFIT:TOTAL"][0][last_date], 500.170035) - self.assertFloatEqual(result["MISFIT:TOTAL"][24][last_date], 1925.793865) - - - with self.assertRaises(KeyError): - realization_13 = result.loc[60] - - column_count = len(result.columns) - self.assertEqual(result.dtypes[0], numpy.float64) - self.assertEqual(result.dtypes[column_count - 1], numpy.object) - self.assertEqual(result.dtypes[column_count - 2], numpy.int64) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_data_collector.py b/ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_data_collector.py deleted file mode 100644 index 12fe99c7ca..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_data_collector.py +++ /dev/null @@ -1,21 +0,0 @@ -from ert.enkf.export import GenDataCollector -from ert.test import ErtTestContext, ExtendedTestCase - - -class GenDataCollectorTest(ExtendedTestCase): - def test_gen_data_collector(self): - config = self.createTestPath("local/snake_oil/snake_oil.ert") - with ErtTestContext("python/enkf/export/gen_data_collector", config) as context: - ert = context.getErt() - - with self.assertRaises(KeyError): - data = GenDataCollector.loadGenData(ert, "default_0", "RFT_XX", 199) - - with self.assertRaises(ValueError): - data = GenDataCollector.loadGenData(ert, "default_0", "SNAKE_OIL_OPR_DIFF", 198) - - data1 = GenDataCollector.loadGenData(ert, "default_0", "SNAKE_OIL_OPR_DIFF", 199) - - self.assertFloatEqual(data1[0][0], -0.008206) - self.assertFloatEqual(data1[24][1], -0.119255) - self.assertFloatEqual(data1[24][1000], -0.258516) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_data_observation_collector.py b/ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_data_observation_collector.py deleted file mode 100644 index 58357f2ab5..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_data_observation_collector.py +++ /dev/null @@ -1,33 +0,0 @@ -from ert.enkf.export import GenDataObservationCollector -from ert.test import ErtTestContext, ExtendedTestCase - - -class GenDataObservationCollectorTest(ExtendedTestCase): - - def test_gen_data_collector(self): - config = self.createTestPath("local/custom_kw/mini_config") - with ErtTestContext("python/enkf/export/gen_data_observation_collector", config) as context: - ert = context.getErt() - - obs_key = GenDataObservationCollector.getObservationKeyForDataKey(ert, "PERLIN", 1) - self.assertEqual(obs_key, "GEN_PERLIN_1") - - obs_key = GenDataObservationCollector.getObservationKeyForDataKey(ert, "PERLIN", 2) - self.assertEqual(obs_key, "GEN_PERLIN_2") - - obs_key = GenDataObservationCollector.getObservationKeyForDataKey(ert, "PERLIN", 3) - self.assertEqual(obs_key, "GEN_PERLIN_3") - - obs_key = GenDataObservationCollector.getObservationKeyForDataKey(ert, "PERLIN", 4) - self.assertIsNone(obs_key) - - obs_key = GenDataObservationCollector.getObservationKeyForDataKey(ert, "PERLINk", 1) - self.assertIsNone(obs_key) - - data = GenDataObservationCollector.loadGenDataObservations(ert, "default", "GEN_PERLIN_1") - - self.assertFloatEqual(data["GEN_PERLIN_1"][0], -0.616789) - self.assertFloatEqual(data["STD_GEN_PERLIN_1"][0], 0.2) - - with self.assertRaises(KeyError): - GenDataObservationCollector.loadGenDataObservations(ert, "default", "GEN_PERLIN_4") \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_kw_collector.py b/ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_kw_collector.py deleted file mode 100644 index fd57b7664e..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/test_gen_kw_collector.py +++ /dev/null @@ -1,32 +0,0 @@ -from ert.enkf.export import GenKwCollector -from ert.test import ErtTestContext, ExtendedTestCase - - -class GenKwCollectorTest(ExtendedTestCase): - def setUp(self): - self.config = self.createTestPath("local/snake_oil/snake_oil.ert") - - def test_gen_kw_collector(self): - with ErtTestContext("python/enkf/export/gen_kw_collector", self.config) as context: - ert = context.getErt() - - data = GenKwCollector.loadAllGenKwData(ert, "default_0") - - self.assertFloatEqual(data["SNAKE_OIL_PARAM:OP1_PERSISTENCE"][0], 0.047517) - self.assertFloatEqual(data["SNAKE_OIL_PARAM:OP1_PERSISTENCE"][24], 0.160907) - - self.assertFloatEqual(data["SNAKE_OIL_PARAM:OP1_OFFSET"][0], 0.054539) - self.assertFloatEqual(data["SNAKE_OIL_PARAM:OP1_OFFSET"][12], 0.057807) - - realization_20 = data.loc[20] - - with self.assertRaises(KeyError): - realization_60 = data.loc[60] - - data = GenKwCollector.loadAllGenKwData(ert, "default_0", ["SNAKE_OIL_PARAM:OP1_PERSISTENCE", "SNAKE_OIL_PARAM:OP1_OFFSET"]) - - self.assertFloatEqual(data["SNAKE_OIL_PARAM:OP1_PERSISTENCE"][0], 0.047517) - self.assertFloatEqual(data["SNAKE_OIL_PARAM:OP1_OFFSET"][0], 0.054539) - - with self.assertRaises(KeyError): - data["SNAKE_OIL_PARAM:OP1_DIVERGENCE_SCALE"] diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/test_misfit_collector.py b/ThirdParty/Ert/python/tests/ert/enkf/export/test_misfit_collector.py deleted file mode 100644 index 057b571dea..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/test_misfit_collector.py +++ /dev/null @@ -1,23 +0,0 @@ -from ert.enkf.export import MisfitCollector -from ert.test import ErtTestContext, ExtendedTestCase - - -class MisfitCollectorTest(ExtendedTestCase): - def setUp(self): - self.config = self.createTestPath("local/snake_oil/snake_oil.ert") - - def test_misfit_collector(self): - with ErtTestContext("python/enkf/export/misfit_collector", self.config) as context: - ert = context.getErt() - data = MisfitCollector.loadAllMisfitData(ert, "default_0") - - self.assertFloatEqual(data["MISFIT:FOPR"][0], 798.378619) - self.assertFloatEqual(data["MISFIT:FOPR"][24], 1332.219633) - - self.assertFloatEqual(data["MISFIT:TOTAL"][0], 826.651491) - self.assertFloatEqual(data["MISFIT:TOTAL"][24], 1431.305646) - - realization_20 = data.loc[20] - - with self.assertRaises(KeyError): - realization_60 = data.loc[60] diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/test_numpy_and_pandas.py b/ThirdParty/Ert/python/tests/ert/enkf/export/test_numpy_and_pandas.py deleted file mode 100644 index e3763467ff..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/test_numpy_and_pandas.py +++ /dev/null @@ -1,82 +0,0 @@ -import numpy -from pandas import MultiIndex, DataFrame -import pandas as pandas -from ert.test import ExtendedTestCase - - -class NumpyAndPandasTest(ExtendedTestCase): - - def test_numpy(self): - data = numpy.empty(shape=(10, 10), dtype=numpy.float64) - data.fill(numpy.nan) - - self.assertTrue(numpy.isnan(data[0][0])) - self.assertTrue(numpy.isnan(data[9][9])) - - with self.assertRaises(IndexError): - v = data[10][9] - - data[5][5] = 1.0 - - self.assertEqual(data[5][5], 1.0) - - data[0] = 5.0 - - test_data = numpy.empty(shape=10) - test_data.fill(5.0) - - self.assertTrue(numpy.array_equal(data[0], test_data)) - - data = numpy.transpose(data) - - self.assertTrue(numpy.array_equal(data[:,0], test_data)) - - row = data[0] - row[5] = 11 - self.assertEqual(data[0][5], 11) - - - def test_pandas_join(self): - - multi_index = MultiIndex.from_product([[1, 2], ["A", "B", "C"]], names=["REALIZATION", "LABEL"]) - - data = DataFrame(data=[[1, 2, 3], [2, 4, 6], [4, 8, 12]] * 2, index=multi_index, columns=["C1", "C2", "C3"]) - - new_column = DataFrame(data=[4.0, 4.4, 4.8], index=[1, 2, 3], columns=["C4"]) - new_column.index.name = "REALIZATION" - - result = data.join(new_column, how='inner') - - self.assertFloatEqual(result["C4"][1]["A"], 4.0) - self.assertFloatEqual(result["C4"][1]["B"], 4.0) - self.assertFloatEqual(result["C4"][1]["C"], 4.0) - - self.assertFloatEqual(result["C4"][2]["A"], 4.4) - self.assertFloatEqual(result["C4"][2]["B"], 4.4) - self.assertFloatEqual(result["C4"][2]["C"], 4.4) - - - - def test_pandas_concatenate(self): - - d1 = DataFrame(data=[2, 4, 6, 8], columns=["A"], index=[1, 2, 3, 4]) - d2 = DataFrame(data=[[1, 1.1], [3, 3.3], [5, 5.5], [7, 7.7], [9, 9.9]], columns=["A", "B"], index=[1, 2, 3, 4, 5]) - - result = pandas.concat([d1, d2], keys=[1, 2]) - - self.assertEqual(result["A"][1][2], 4) - self.assertEqual(result["A"][2][2], 3) - self.assertTrue(numpy.isnan(result["B"][1][1])) - self.assertFloatEqual(result["B"][2][4], 7.7) - - - def test_pandas_extend_index(self): - d1 = DataFrame(data=[2, 4, 6, 8], columns=["A"], index=[1, 2, 3, 4]) - d1.index.name = "first" - - d1["second"] = "default" - d1.set_index(["second"], append=True, inplace=True) - self.assertEqual(d1.index.names, ["first", "second"]) - - d1 = d1.reorder_levels(["second", "first"]) - self.assertEqual(d1.index.names, ["second", "first"]) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/test_summary_collector.py b/ThirdParty/Ert/python/tests/ert/enkf/export/test_summary_collector.py deleted file mode 100644 index fea0d22776..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/test_summary_collector.py +++ /dev/null @@ -1,34 +0,0 @@ -from ert.enkf.export import SummaryCollector -from ert.test import ErtTestContext, ExtendedTestCase -import os - - -class SummaryCollectorTest(ExtendedTestCase): - def setUp(self): - os.environ["TZ"] = "CET" # The ert_statoil case was generated in CET - self.config = self.createTestPath("local/snake_oil/snake_oil.ert") - - def test_summary_collector(self): - with ErtTestContext("python/enkf/export/summary_collector", self.config) as context: - ert = context.getErt() - - data = SummaryCollector.loadAllSummaryData(ert, "default_0") - - self.assertFloatEqual(data["WWCT:OP2"][0]["2010-01-10"], 0.385549) - self.assertFloatEqual(data["WWCT:OP2"][24]["2010-01-10"], 0.498331) - - self.assertFloatEqual(data["FOPR"][0]["2010-01-10"], 0.118963) - self.assertFloatEqual(data["FOPR"][0]["2015-06-23"], 0.133601) - - realization_20 = data.loc[20] - - with self.assertRaises(KeyError): - realization_60 = data.loc[60] - - data = SummaryCollector.loadAllSummaryData(ert, "default_0", ["WWCT:OP1", "WWCT:OP2"]) - - self.assertFloatEqual(data["WWCT:OP1"][0]["2010-01-10"], 0.352953) - self.assertFloatEqual(data["WWCT:OP2"][0]["2010-01-10"], 0.385549) - - with self.assertRaises(KeyError): - data["FOPR"] diff --git a/ThirdParty/Ert/python/tests/ert/enkf/export/test_summary_observation_collector.py b/ThirdParty/Ert/python/tests/ert/enkf/export/test_summary_observation_collector.py deleted file mode 100644 index 92a3baf55f..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/export/test_summary_observation_collector.py +++ /dev/null @@ -1,45 +0,0 @@ -from ert.enkf.export import SummaryObservationCollector -from ert.test import ErtTestContext, ExtendedTestCase -import os - -class SummaryObservationCollectorTest(ExtendedTestCase): - - def setUp(self): - os.environ["TZ"] = "CET" # The ert_statoil case was generated in CET - self.config = self.createTestPath("local/snake_oil/snake_oil.ert") - - - def test_summary_observation_collector(self): - - with ErtTestContext("python/enkf/export/summary_observation_collector", self.config) as context: - - ert = context.getErt() - - self.assertTrue(SummaryObservationCollector.summaryKeyHasObservations(ert, "FOPR")) - self.assertFalse(SummaryObservationCollector.summaryKeyHasObservations(ert, "FOPT")) - - keys = SummaryObservationCollector.getAllObservationKeys(ert) - self.assertTrue("FOPR" in keys) - self.assertTrue("WOPR:OP1" in keys) - self.assertFalse("WOPR:OP2" in keys) - - data = SummaryObservationCollector.loadObservationData(ert, "default_0") - - self.assertFloatEqual(data["FOPR"]["2010-01-10"], 0.001696887) - self.assertFloatEqual(data["STD_FOPR"]["2010-01-10"], 0.1) - - self.assertFloatEqual(data["WOPR:OP1"]["2010-03-31"], 0.1) - self.assertFloatEqual(data["STD_WOPR:OP1"]["2010-03-31"], 0.05) - - - with self.assertRaises(KeyError): - fgir = data["FGIR"] - - - data = SummaryObservationCollector.loadObservationData(ert, "default_0", ["WOPR:OP1"]) - - self.assertFloatEqual(data["WOPR:OP1"]["2010-03-31"], 0.1) - self.assertFloatEqual(data["STD_WOPR:OP1"]["2010-03-31"], 0.05) - - with self.assertRaises(KeyError): - data["FOPR"] diff --git a/ThirdParty/Ert/python/tests/ert/enkf/plot/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/enkf/plot/CMakeLists.txt deleted file mode 100644 index 47f6f3dab5..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/plot/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_plot_data.py - test_plot_settings.py -) - -add_python_package("python.tests.ert.enkf.plot" ${PYTHON_INSTALL_PREFIX}/tests/ert/enkf/plot "${TEST_SOURCES}" False) - -addPythonTest(ert.enkf.plot.plot_settings tests.ert.enkf.plot.test_plot_settings.PlotSettingsTest) -if (STATOIL_TESTDATA_ROOT) - addPythonTest(ert.enkf.plot.plot_block_data tests.ert.enkf.plot.test_plot_data.PlotDataTest LABELS StatoilData) -endif() diff --git a/ThirdParty/Ert/python/tests/ert/enkf/plot/__init__.py b/ThirdParty/Ert/python/tests/ert/enkf/plot/__init__.py deleted file mode 100644 index 284bf2e772..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/plot/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = 'jpb' diff --git a/ThirdParty/Ert/python/tests/ert/enkf/plot/test_plot_data.py b/ThirdParty/Ert/python/tests/ert/enkf/plot/test_plot_data.py deleted file mode 100644 index 41c27231a3..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/plot/test_plot_data.py +++ /dev/null @@ -1,101 +0,0 @@ -from ert.enkf.plot_data import PlotBlockData, PlotBlockDataLoader, PlotBlockVector -from ert.util import DoubleVector -from ert.test import ExtendedTestCase, ErtTestContext - - -class PlotDataTest(ExtendedTestCase): - - def setUp(self): - self.config_file = self.createTestPath("Statoil/config/with_RFT/config") - - def test_plot_block_vector(self): - vector = DoubleVector() - vector.append(1.5) - vector.append(2.5) - vector.append(3.5) - plot_block_vector = PlotBlockVector(1, vector) - - self.assertEqual(plot_block_vector.getRealizationNumber(), 1) - self.assertEqual(plot_block_vector[0], 1.5) - self.assertEqual(plot_block_vector[2], 3.5) - - self.assertEqual(len(plot_block_vector), len(vector)) - - - def test_plot_block_data(self): - depth = DoubleVector() - depth.append(2.5) - depth.append(3.5) - - data = PlotBlockData(depth) - - self.assertEqual(data.getDepth(), depth) - - vector = PlotBlockVector(1, DoubleVector()) - data.addPlotBlockVector(vector) - data.addPlotBlockVector(PlotBlockVector(2, DoubleVector())) - - self.assertEqual(len(data), 2) - - self.assertEqual(vector, data[1]) - - - def compareLists(self, source, target): - self.assertEqual(len(source), len(target)) - for index, value in enumerate(source): - self.assertEqual(value, target[index]) - - - def checkBlockData(self, ert, obs_key, report_step): - """ - @type ert: EnKFMain - @type obs_key: str - @type report_step: int - """ - enkf_obs = ert.getObservations() - obs_vector = enkf_obs[obs_key] - loader = PlotBlockDataLoader(obs_vector) - - fs = ert.getEnkfFsManager().getCurrentFileSystem() - plot_block_data = loader.load(fs, report_step) - - self.assertEqual(ert.getEnsembleSize(), len(plot_block_data)) - - depth = plot_block_data.getDepth() - - depth_test_values = [1752.24998474, 1757.88926697, 1760.70924377] - if report_step == 56: - depth_test_values.append(1763.52885437) - - self.assertAlmostEqualList(depth_test_values, depth) - - block_obs = len(obs_vector.getNode(report_step)) - self.assertEqual(block_obs, len(plot_block_data[0])) - self.assertEqual(block_obs, len(plot_block_data[9])) - - - if report_step == 50: - rft_values = [244.681655884, 245.217041016, 245.48500061] - else: - rft_values = [239.7550354, 240.290313721, 240.558197021, 240.825881958] - - self.assertAlmostEqualList(rft_values, plot_block_data[0]) - - - if report_step == 50: - rft_values = [238.702560425, 239.237838745, 239.505737305] - else: - rft_values = [234.41583252, 234.95098877, 235.218841553, 235.486480713] - - self.assertAlmostEqualList(rft_values, plot_block_data[9]) - - - - - def test_plot_block_data_fs(self): - with ErtTestContext("plot_block_data_test", self.config_file) as test_context: - ert = test_context.getErt() - - self.checkBlockData(ert, "RFT2", 50) - self.checkBlockData(ert, "RFT5", 56) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/plot/test_plot_settings.py b/ThirdParty/Ert/python/tests/ert/enkf/plot/test_plot_settings.py deleted file mode 100644 index e426123989..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/plot/test_plot_settings.py +++ /dev/null @@ -1,56 +0,0 @@ -from ert.test import ExtendedTestCase, ErtTestContext,TestAreaContext -from ert.config import * -from ert.enkf import PlotSettings -from ert.enkf import EnkfPrototype - -#_plot_settings_init = EnkfPrototype("void plot_settings_init( plot_settings, config_content)", bind = False) -_plot_settings_config = EnkfPrototype("void plot_settings_add_config_items( config_parser)", bind = False) - - - - -class PlotSettingsTest(ExtendedTestCase): - - - def test_create(self): - ps = PlotSettings( ) - - - def test_keys(self): - ps = PlotSettings( ) - keys = ps.keys( ) - self.assertFalse( "XXX" in keys ) - self.assertTrue( "PATH" in keys ) - self.assertTrue( "SHOW_REFCASE" in keys ) - - - def test_set_get(self): - ps = PlotSettings( ) - with self.assertRaises(KeyError): - ps["UNKNOWN_KEY"] = 1000 - - with self.assertRaises(TypeError): - ps["SHOW_REFCASE"] = "Don-know" - - ps["SHOW_REFCASE"] = False - self.assertEqual( ps["SHOW_REFCASE"] , False ) - - ps["SHOW_REFCASE"] = True - self.assertEqual( ps["SHOW_REFCASE"] , True ) - - - - def test_config(self): - parser = ConfigParser( ) - ps = PlotSettings( ) - - with TestAreaContext("plot_config"): - with open("config_file" , "w") as f: - f.write("PLOT_SETTING PATH abc\n"); - f.write("PLOT_SETTING SHOW_REFCASE False\n") - f.write("PLOT_SETTING UnknownKey Value\n") - - #_plot_settings_config( parser ) - content = parser.parse( "config_file" ) - ps.apply( content ) - #_plot_settings_init( ps , content ) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_active_list.py b/ThirdParty/Ert/python/tests/ert/enkf/test_active_list.py deleted file mode 100644 index 38d4fa8f0b..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_active_list.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'test_active_list.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from ert.enkf import ActiveList -from ert.enkf import ActiveMode -from ert.test import ExtendedTestCase - - - -class ActiveListTest(ExtendedTestCase): - - def test_active_mode_enum(self): - self.assertEqual(ActiveMode.ALL_ACTIVE, 1) - self.assertEqual(ActiveMode.INACTIVE, 2) - self.assertEqual(ActiveMode.PARTLY_ACTIVE, 3) - self.assertEqual(ActiveMode(1).name, 'ALL_ACTIVE') - self.assertEqual(ActiveMode(2).name, 'INACTIVE') - self.assertEqual(ActiveMode(3).name, 'PARTLY_ACTIVE') - - def test_active_size(self): - al = ActiveList() - self.assertEqual(None, al.getActiveSize(None)) - self.assertEqual(7, al.getActiveSize(7)) - self.assertEqual(-1, al.getActiveSize(-1)) - - al.addActiveIndex( 10 ) - self.assertEqual(1, al.getActiveSize(7)) - al.addActiveIndex( 10 ) - self.assertEqual(1, al.getActiveSize(7)) - al.addActiveIndex( 100 ) - self.assertEqual(2, al.getActiveSize(7)) - - def test_create(self): - active_list = ActiveList() - self.assertEqual( active_list.getMode() , ActiveMode.ALL_ACTIVE ) - active_list.addActiveIndex( 10 ) - self.assertEqual( active_list.getMode() , ActiveMode.PARTLY_ACTIVE ) - - def test_repr(self): - al = ActiveList() - rep = repr(al) - self.assertFalse('PARTLY_ACTIVE' in rep) - self.assertFalse('INACTIVE' in rep) - self.assertTrue('ALL_ACTIVE' in rep) - pfx = 'ActiveList(' - self.assertEqual(pfx, rep[:len(pfx)]) - for i in range(150): - al.addActiveIndex( 3*i ) - rep = repr(al) - self.assertTrue('150' in rep) - self.assertTrue('PARTLY_ACTIVE' in rep) - self.assertFalse('INACTIVE' in rep) - self.assertFalse('ALL_ACTIVE' in rep) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_analysis_config.py b/ThirdParty/Ert/python/tests/ert/enkf/test_analysis_config.py deleted file mode 100644 index 630d7a0db2..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_analysis_config.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'test_analysis_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import os -from ert.enkf import AnalysisConfig -from ert.test import ExtendedTestCase - - -class AnalysisConfigTest(ExtendedTestCase): - - def test_keywords_for_monitoring_simulation_runtime(self): - ac = AnalysisConfig() - - # Unless the MIN_REALIZATIONS is set in config, one is required to have "all" realizations. - self.assertFalse(ac.haveEnoughRealisations(5, 10)) - self.assertTrue(ac.haveEnoughRealisations(10, 10)) - - ac.set_max_runtime( 50 ) - self.assertEqual( 50 , ac.get_max_runtime() ) - - ac.set_stop_long_running( True ) - self.assertTrue( ac.get_stop_long_running() ) - - - def test_analysis_modules(self): - ac = AnalysisConfig() - self.assertIsNone( ac.activeModuleName() ) - self.assertIsNotNone( ac.getModuleList() ) - - def test_analysis_config_global_std_scaling(self): - ac = AnalysisConfig() - self.assertFloatEqual(ac.getGlobalStdScaling(), 1.0) - ac.setGlobalStdScaling(0.77) - self.assertFloatEqual(ac.getGlobalStdScaling(), 0.77) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_analysis_iter_config.py b/ThirdParty/Ert/python/tests/ert/enkf/test_analysis_iter_config.py deleted file mode 100644 index dfe7f9d13e..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_analysis_iter_config.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2014 Statoil ASA, Norway. -# -# The file 'test_analysis_iter_config.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import os -from ert.enkf import AnalysisIterConfig -from ert.test import ExtendedTestCase - - -class AnalysisIterConfigTest(ExtendedTestCase): - - def test_set(self): - c = AnalysisIterConfig() - - self.assertFalse( c.caseFormatSet() ) - c.setCaseFormat("case%d") - self.assertTrue( c.caseFormatSet() ) - - self.assertFalse( c.numIterationsSet() ) - c.setNumIterations(1) - self.assertTrue( c.numIterationsSet() ) - - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_block_obs.py b/ThirdParty/Ert/python/tests/ert/enkf/test_block_obs.py deleted file mode 100644 index 9363c204fe..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_block_obs.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'test_block_obs.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import os - -from ert.enkf import BlockObservation -from ert.enkf import ActiveList, FieldConfig -from ert.test import ExtendedTestCase -from ert.ecl import EclGrid - - -class BlockObsTest(ExtendedTestCase): - - def test_create(self): - grid = EclGrid.createRectangular( (10,20,5) , (1,1,1) ) - field_config = FieldConfig("PRESSURE" , grid) - block_obs = BlockObservation("P-CONFIG" , field_config , grid) - - self.assertEqual( len(block_obs) , 0 ) - - block_obs.addPoint(1,2,3,100,25) - self.assertEqual( len(block_obs) , 1 ) - self.assertEqual( block_obs.getValue(0) , 100 ) - self.assertEqual( block_obs.getStd(0) , 25 ) - self.assertEqual( block_obs.getStdScaling(0) , 1 ) - - block_obs.addPoint(1,2,4,200,50) - self.assertEqual( len(block_obs) , 2 ) - self.assertEqual( block_obs.getValue(1) , 200 ) - self.assertEqual( block_obs.getStd(1) , 50 ) - self.assertEqual( block_obs.getStdScaling(1) , 1 ) - - active_list = ActiveList( ) - block_obs.updateStdScaling( 0.50 , active_list ) - self.assertEqual( block_obs.getStdScaling(0) , 0.50 ) - self.assertEqual( block_obs.getStdScaling(1) , 0.50 ) - - active_list.addActiveIndex( 1 ) - block_obs.updateStdScaling( 2.00 , active_list ) - self.assertEqual( block_obs.getStdScaling(0) , 0.50 ) - self.assertEqual( block_obs.getStdScaling(1) , 2.00 ) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_custom_kw_config_set.py b/ThirdParty/Ert/python/tests/ert/enkf/test_custom_kw_config_set.py deleted file mode 100644 index 7bbc4b27fa..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_custom_kw_config_set.py +++ /dev/null @@ -1,80 +0,0 @@ -import os -from ert.enkf import CustomKWConfigSet -from ert.enkf.config import CustomKWConfig -from ert.enkf.enkf_fs import EnkfFs -from ert.enkf.enkf_main import EnKFMain -from ert.test import ExtendedTestCase -from ert.test.ert_test_context import ErtTestContext -from ert.test.test_area import TestAreaContext -from ert.util.stringlist import StringList - - -class CustomKWConfigSetTest(ExtendedTestCase): - - def createCustomKWConfig(self, name, data): - with TestAreaContext("python/enkf/custom_kw_config_set_config") as test_area: - self.createResultFile("result_file", data) - - config = CustomKWConfig(name, "") - config.parseResultFile("result_file", StringList()) - - return config - - def createResultFile(self, filename, data): - with open(filename, "w") as output_file: - for key in data: - output_file.write("%s %s\n" % (key, data[key])) - - - def test_creation(self): - config_set = CustomKWConfigSet() - - config = self.createCustomKWConfig("TEST", {"VALUE_1": 0.5, "VALUE_2": 5, "VALUE_3": "string", "VALUE_4": "true"}) - self.assertItemsEqual(config.getKeys(), ["VALUE_1", "VALUE_2", "VALUE_3", "VALUE_4"]) - - config_set.addConfig(config) - keys = config_set.getStoredConfigKeys() - self.assertItemsEqual(keys, ["TEST"]) - - config_set.reset() - self.assertTrue(len(config_set.getStoredConfigKeys()) == 0) - - - def test_fwrite_and_fread(self): - with TestAreaContext("python/enkf/custom_kw_config_set_fwrite") as test_area: - trees_config = self.createCustomKWConfig("TREES", {"OAK": 0.1, "SPRUCE": 5, "FIR": "pines", "PALM": "coconut"}) - insects_config = self.createCustomKWConfig("INSECTS", {"MOSQUITO": "annoying", "FLY": 3.14, "BEETLE": 0.5}) - - config_set = CustomKWConfigSet() - config_set.addConfig(trees_config) - config_set.addConfig(insects_config) - - self.assertItemsEqual(config_set.getStoredConfigKeys(), ["TREES", "INSECTS"]) - - config_set.fwrite("config_set") - - self.assertTrue(os.path.exists("config_set")) - - config_set = CustomKWConfigSet("config_set") - - self.assertItemsEqual(config_set.getStoredConfigKeys(), ["TREES", "INSECTS"]) - - trees_config_from_file = CustomKWConfig("TREES", None) - config_set.updateConfig(trees_config_from_file) - - for key in ["OAK", "SPRUCE", "FIR", "PALM"]: - self.assertEqual(trees_config_from_file.indexOfKey(key), trees_config.indexOfKey(key)) - self.assertTrue(trees_config_from_file.keyIsDouble(key) == trees_config.keyIsDouble(key)) - - - insects_config_from_file = CustomKWConfig("INSECTS", None) - config_set.updateConfig(insects_config_from_file) - - for key in ["MOSQUITO", "FLY", "BEETLE"]: - self.assertEqual(insects_config_from_file.indexOfKey(key), insects_config.indexOfKey(key)) - self.assertTrue(insects_config_from_file.keyIsDouble(key) == insects_config.keyIsDouble(key)) - - - - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_deprecation.py b/ThirdParty/Ert/python/tests/ert/enkf/test_deprecation.py deleted file mode 100644 index 3a09b9f5e5..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_deprecation.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2011 Statoil ASA, Norway. -# -# The file 'test_deprecation.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import warnings - -from ert.test import ErtTestContext, ExtendedTestCase - - -class DeprecationTest(ExtendedTestCase): - def setUp(self): - self.config_file = self.createTestPath("local/simple_config/minimum_config") - self.obs_file = self.createTestPath("local/simple_config/minimum_config") - - - # Added in 1.10 development - def test(self): - with ErtTestContext("enkf_deprecation", self.config_file) as test_context: - ert = test_context.getErt() - - ecl_config = ert.eclConfig() - with warnings.catch_warnings(): - ecl_config.get_grid( ) - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_ecl_config.py b/ThirdParty/Ert/python/tests/ert/enkf/test_ecl_config.py deleted file mode 100644 index 563d69e9cd..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_ecl_config.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2013 Statoil ASA, Norway. -# -# This file is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import os.path -from ert.enkf import EclConfig -from ert.test import ExtendedTestCase -from ert.util import UIReturn -from ert.ecl import EclSum - -EGRID_file = "Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID" -SMSPEC_file = "Statoil/ECLIPSE/Gurbat/ECLIPSE.SMSPEC" -DATA_file = "Statoil/ECLIPSE/Gurbat/ECLIPSE.DATA" -INIT_file = "Statoil/ECLIPSE/Gurbat/EQUIL.INC" -DATA_INIT_file= "Statoil/ECLIPSE/Gurbat/ECLIPSE_INIT.DATA" -SCHEDULE_file = "Statoil/ECLIPSE/Gurbat/target.SCH" - - -class EclConfigTest(ExtendedTestCase): - - - def test_grid(self): - grid_file = self.createTestPath( EGRID_file ) - smspec_file = self.createTestPath( SMSPEC_file ) - ec = EclConfig() - ui = ec.validateGridFile( grid_file ) - self.assertTrue( ui ) - self.assertTrue( isinstance(ui , UIReturn )) - - ui = ec.validateGridFile( "Does/Not/Exist" ) - self.assertFalse( ui ) - - self.assertTrue( os.path.exists( smspec_file )) - ui = ec.validateGridFile( smspec_file ) - self.assertFalse( ui ) - - - - def test_eclbase(self): - ec = EclConfig() - ui = ec.validateEclBase( "MixedCase%d" ) - self.assertFalse( ui ) - - ui = ec.validateEclBase( "CASE%s" ) - self.assertFalse( ui ) - - ui = ec.validateEclBase( "CASE%d" ) - self.assertTrue( ui ) - ec.setEclBase("CASE%d") - self.assertEqual( "CASE%d" , ec.getEclBase()) - - - - def test_datafile(self): - ec = EclConfig() - ui = ec.validateDataFile( "DoesNotExist" ) - self.assertFalse( ui ) - - dfile = self.createTestPath( DATA_file ) - ui = ec.validateDataFile( dfile ) - self.assertTrue( ui ) - ec.setDataFile( dfile ) - self.assertEqual( dfile , ec.getDataFile() ) - - - def test_schedule_file(self): - ec = EclConfig() - ui = ec.validateScheduleFile( "DoesNotExist" ) - self.assertFalse( ui ) - - dfile = self.createTestPath( DATA_file ) - sfile = self.createTestPath( SCHEDULE_file ) - - # Setting the schedule file should fail before the datafile - # (i.e. startdate) has been set. - ui = ec.validateScheduleFile( sfile ) - self.assertFalse( ui ) - - ec.setDataFile( dfile ) - ui = ec.validateScheduleFile( sfile ) - self.assertTrue( ui ) - - ec.setScheduleFile( sfile ) - self.assertEqual( sfile , ec.getScheduleFile() ) - - - def test_init_section(self): - ec = EclConfig() - dfile = self.createTestPath( DATA_file ) - difile = self.createTestPath( DATA_INIT_file ) - ifile = self.createTestPath( INIT_file ) - - ui = ec.validateInitSection( ifile ) - self.assertFalse( ui ) - - ec.setDataFile( dfile ) - ui = ec.validateInitSection( ifile ) - self.assertFalse( ui ) - - ec.setDataFile( difile ) - ui = ec.validateInitSection( ifile ) - self.assertTrue( ui ) - ec.setInitSection( ifile ) - self.assertTrue( ifile , ec.getInitSection() ) - - - def test_refcase( self ): - ec = EclConfig() - dfile = self.createTestPath( DATA_file ) - - ui = ec.validateRefcase( "Does/not/exist" ) - self.assertFalse( ui ) - - ui = ec.validateRefcase( dfile ) - self.assertTrue( ui ) - ec.loadRefcase( dfile ) - refcase = ec.getRefcase() - self.assertTrue( isinstance( refcase , EclSum )) - refcaseName = ec.getRefcaseName() + ".DATA" - self.assertEqual( dfile , refcaseName ) - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf.py b/ThirdParty/Ert/python/tests/ert/enkf/test_enkf.py deleted file mode 100644 index 887e379a50..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf.py +++ /dev/null @@ -1,189 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'test_enkf.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import os - -from ert.util import BoolVector - -from ert.enkf import EnsembleConfig, AnalysisConfig, ModelConfig, SiteConfig, EclConfig, PlotSettings, EnkfObs, ErtTemplates, EnkfFs, EnKFState, EnkfVarType, ObsVector , RunArg -from ert.enkf.config import EnkfConfigNode -from ert.enkf.enkf_main import EnKFMain -from ert.enkf.enums import EnkfObservationImplementationType, LoadFailTypeEnum, EnkfInitModeEnum, ErtImplType, RealizationStateEnum , EnkfRunType, EnkfFieldFileFormatEnum, EnkfTruncationType, ActiveMode -from ert.enkf.observations.summary_observation import SummaryObservation -from ert.test import ExtendedTestCase , TestAreaContext - - - -class EnKFTest(ExtendedTestCase): - def setUp(self): - self.case_directory = self.createTestPath("local/simple_config/") - - - def test_repr( self ): - with TestAreaContext("enkf_test", store_area=True) as work_area: - work_area.copy_directory(self.case_directory) - main = EnKFMain("simple_config/minimum_config") - pfx = 'EnKFMain(ensemble_size' - self.assertEqual(pfx, repr(main)[:len(pfx)]) - main.free() - - def test_bootstrap( self ): - with TestAreaContext("enkf_test", store_area=True) as work_area: - work_area.copy_directory(self.case_directory) - main = EnKFMain("simple_config/minimum_config") - self.assertTrue(main, "Load failed") - main.free() - - - def test_site_bootstrap( self ): - with TestAreaContext("enkf_test", store_area=True) as work_area: - EnKFMain.loadSiteConfig() - - - def test_enum(self): - self.assertEnumIsFullyDefined(EnkfVarType, "enkf_var_type", "libenkf/include/ert/enkf/enkf_types.h") - self.assertEnumIsFullyDefined(ErtImplType, "ert_impl_type", "libenkf/include/ert/enkf/enkf_types.h") - self.assertEnumIsFullyDefined(EnkfInitModeEnum, "init_mode_type", "libenkf/include/ert/enkf/enkf_types.h") - self.assertEnumIsFullyDefined(RealizationStateEnum, "realisation_state_enum", "libenkf/include/ert/enkf/enkf_types.h") - self.assertEnumIsFullyDefined(EnkfTruncationType, "truncation_type", "libenkf/include/ert/enkf/enkf_types.h") - self.assertEnumIsFullyDefined(EnkfRunType, "run_mode_type" , "libenkf/include/ert/enkf/enkf_types.h") - - self.assertEnumIsFullyDefined(EnkfObservationImplementationType, "obs_impl_type", "libenkf/include/ert/enkf/obs_vector.h") - self.assertEnumIsFullyDefined(LoadFailTypeEnum, "load_fail_type", "libenkf/include/ert/enkf/summary_config.h") - self.assertEnumIsFullyDefined(EnkfFieldFileFormatEnum, "field_file_format_type", "libenkf/include/ert/enkf/field_config.h" ) - self.assertEnumIsFullyDefined(ActiveMode , "active_mode_type" , "libenkf/include/ert/enkf/enkf_types.h") - - - def test_observations(self): - with TestAreaContext("enkf_test") as work_area: - work_area.copy_directory(self.case_directory) - - main = EnKFMain("simple_config/minimum_config") - - count = 10 - summary_key = "test_key" - observation_key = "test_obs_key" - summary_observation_node = EnkfConfigNode.createSummaryConfigNode(summary_key, LoadFailTypeEnum.LOAD_FAIL_EXIT) - observation_vector = ObsVector(EnkfObservationImplementationType.SUMMARY_OBS, observation_key, summary_observation_node, count) - - main.getObservations().addObservationVector(observation_vector) - - values = [] - for index in range(0, count): - value = index * 10.5 - std = index / 10.0 - summary_observation_node = SummaryObservation(summary_key, observation_key, value, std) - observation_vector.installNode(index, summary_observation_node) - self.assertEqual(observation_vector.getNode(index), summary_observation_node) - self.assertEqual(value, summary_observation_node.getValue()) - values.append((index, value, std)) - - - - observations = main.getObservations() - test_vector = observations[observation_key] - index = 0 - for node in test_vector: - self.assertTrue( isinstance( node , SummaryObservation )) - self.assertEqual( node.getValue( ) , index * 10.5 ) - index += 1 - - - self.assertEqual(observation_vector, test_vector) - for index, value, std in values: - self.assertTrue(test_vector.isActive(index)) - - summary_observation_node = test_vector.getNode(index) - """@type: SummaryObservation""" - - self.assertEqual(value, summary_observation_node.getValue()) - self.assertEqual(std, summary_observation_node.getStandardDeviation()) - self.assertEqual(summary_key, summary_observation_node.getSummaryKey()) - - - main.free() - - - - def test_config( self ): - with TestAreaContext("enkf_test") as work_area: - work_area.copy_directory(self.case_directory) - - main = EnKFMain("simple_config/minimum_config") - - self.assertIsInstance(main.ensembleConfig(), EnsembleConfig) - self.assertIsInstance(main.analysisConfig(), AnalysisConfig) - self.assertIsInstance(main.getModelConfig(), ModelConfig) - #self.assertIsInstance(main.local_config(), LocalConfig) #warn: Should this be None? - self.assertIsInstance(main.siteConfig(), SiteConfig) - self.assertIsInstance(main.eclConfig(), EclConfig) - self.assertIsInstance(main.plotConfig(), PlotSettings) - - # self.main.load_obs(obs_config_file) - self.assertIsInstance(main.getObservations(), EnkfObs) - self.assertIsInstance(main.get_templates(), ErtTemplates) - self.assertIsInstance(main.getEnkfFsManager().getCurrentFileSystem(), EnkfFs) - # self.assertIsInstance(main.iget_member_config(0), MemberConfig) - self.assertIsInstance(main.getMemberRunningState(0), EnKFState) - - self.assertEqual( "Ensemble" , main.getMountPoint()) - - main.free() - - def test_enkf_create_config_file(self): - config_file = "test_new_config" - dbase_type = "BLOCK_FS" - num_realizations = 42 - - with TestAreaContext("python/ens_condif/create_config" , store_area = True) as ta: - EnKFMain.createNewConfig(config_file, "storage" , dbase_type, num_realizations) - main = EnKFMain(config_file) - self.assertEqual(main.getEnsembleSize(), num_realizations) - - - def test_run_context(self): - with TestAreaContext("enkf_test") as work_area: - work_area.copy_directory(self.case_directory) - main = EnKFMain("simple_config/minimum_config") - fs_manager = main.getEnkfFsManager() - fs = fs_manager.getCurrentFileSystem( ) - iactive = BoolVector(initial_size = 10 , default_value = True) - iactive[0] = False - iactive[1] = False - run_context = main.getRunContextENSEMPLE_EXPERIMENT( fs , iactive ) - - self.assertEqual( len(run_context) , 8 ) - - with self.assertRaises(IndexError): - run_context[8] - - with self.assertRaises(TypeError): - run_context["String"] - - run_arg = run_context[0] - self.assertTrue( isinstance( run_arg , RunArg )) - - with self.assertRaises(ValueError): - run_context.iensGet(0) - - - with self.assertRaises(ValueError): - run_context.iensGet(1) - - arg0 = run_context[0] - arg2 = run_context.iensGet( 2 ) - #self.assertEqual( arg0 , arg2 ) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs.py b/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs.py deleted file mode 100644 index 93de431075..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs.py +++ /dev/null @@ -1,67 +0,0 @@ -import os -from ert.enkf import EnkfFs -from ert.enkf import EnKFMain -from ert.enkf.enums import EnKFFSType -from ert.test import ExtendedTestCase , TestAreaContext -from ert.test import ErtTestContext - - -class EnKFFSTest(ExtendedTestCase): - def setUp(self): - self.mount_point = "storage/default" - self.config_file = self.createTestPath("Statoil/config/with_data/config") - - - def test_id_enum(self): - self.assertEnumIsFullyDefined(EnKFFSType, "fs_driver_impl", "libenkf/include/ert/enkf/fs_types.h") - - - def test_create(self): - with TestAreaContext("create_fs") as work_area: - work_area.copy_parent_content(self.config_file) - - self.assertTrue(EnkfFs.exists(self.mount_point)) - fs = EnkfFs(self.mount_point) - self.assertEqual(1, fs.refCount()) - fs.umount() - - self.assertFalse(EnkfFs.exists("newFS")) - arg = None - fs = EnkfFs.createFileSystem("newFS", EnKFFSType.BLOCK_FS_DRIVER_ID, arg) - self.assertTrue(EnkfFs.exists("newFS")) - self.assertTrue( fs is None ) - - with self.assertRaises(IOError): - version = EnkfFs.diskVersion("does/not/exist") - - version = EnkfFs.diskVersion("newFS") - self.assertTrue( version >= 106 ) - - - def test_create2(self): - with TestAreaContext("create_fs2") as work_area: - work_area.copy_parent_content(self.config_file) - - new_fs = EnkfFs.createFileSystem("newFS", EnKFFSType.BLOCK_FS_DRIVER_ID, mount = True) - self.assertTrue( isinstance( new_fs , EnkfFs )) - - - - def test_throws(self): - with self.assertRaises(Exception): - fs = EnkfFs("/does/not/exist") - - - def test_refcount(self): - with ErtTestContext("TEST", self.config_file) as testContext: - ert = testContext.getErt() - self.assertTrue(isinstance(ert, EnKFMain)) - - fsm = ert.getEnkfFsManager() - fs = fsm.getCurrentFileSystem() - self.assertEqual(2, fs.refCount()) - - fs.umount() - - with self.assertRaises(AssertionError): - fs.refCount() diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs_manager1.py b/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs_manager1.py deleted file mode 100644 index 03c8ca6b12..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs_manager1.py +++ /dev/null @@ -1,45 +0,0 @@ -import os -from ert.enkf import EnkfFs -from ert.enkf import EnKFMain -from ert.enkf import EnkfFsManager -from ert.test import ErtTestContext -from ert.test import ExtendedTestCase - - -class EnKFFSManagerTest1(ExtendedTestCase): - def setUp(self): - self.config_file = self.createTestPath("Statoil/config/with_data/config") - - - def test_create(self): - # We are indirectly testing the create through the create - # already in the enkf_main object. In principle we could - # create a separate manager instance from the ground up, but - # then the reference count will be weird. - with ErtTestContext("enkf_fs_manager_create_test", self.config_file) as testContext: - ert = testContext.getErt() - fsm = ert.getEnkfFsManager() - - self.assertTrue(fsm.isCaseMounted("default")) - self.assertTrue(fsm.caseExists("default")) - self.assertTrue(fsm.caseHasData("default")) - self.assertFalse(fsm.isCaseRunning("default")) - - fs = fsm.getCurrentFileSystem() - self.assertEqual(2, fs.refCount()) - self.assertEqual(1, fsm.getFileSystemCount()) - - self.assertFalse(fsm.isCaseMounted("newFS")) - self.assertFalse(fsm.caseExists("newFS")) - self.assertFalse(fsm.caseHasData("newFS")) - self.assertFalse(fsm.isCaseRunning("newFS")) - - fs2 = fsm.getFileSystem("newFS") - self.assertEqual(2, fsm.getFileSystemCount()) - self.assertEqual(1, fs2.refCount()) - - self.assertTrue(fsm.isCaseMounted("newFS")) - self.assertTrue(fsm.caseExists("newFS")) - self.assertFalse(fsm.caseHasData("newFS")) - self.assertFalse(fsm.isCaseRunning("newFS")) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs_manager2.py b/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs_manager2.py deleted file mode 100644 index 1441407ddd..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_fs_manager2.py +++ /dev/null @@ -1,37 +0,0 @@ -import os -from ert.enkf import EnkfFs -from ert.enkf import EnKFMain -from ert.enkf import EnkfFsManager -from ert.test import ErtTestContext -from ert.test import ExtendedTestCase - - -class EnKFFSManagerTest2(ExtendedTestCase): - def setUp(self): - self.config_file = self.createTestPath("Statoil/config/with_data/config") - - - def test_rotate(self): - - # We are indirectly testing the create through the create - # already in the enkf_main object. In principle we could - # create a separate manager instance from the ground up, but - # then the reference count will be weird. - with ErtTestContext("enkf_fs_manager_rotate_test", self.config_file) as testContext: - ert = testContext.getErt() - fsm = ert.getEnkfFsManager() - self.assertEqual(1, fsm.getFileSystemCount()) - - fs_list = [] - for index in range(EnkfFsManager.DEFAULT_CAPACITY): - fs_list.append(fsm.getFileSystem("fs_fill_%d" % index)) - - self.assertEqual(EnkfFsManager.DEFAULT_CAPACITY, fsm.getFileSystemCount()) - - for i in range(10): - fs = "fs_test_%d" % i - print("Mounting: %s" % fs) - fs_list.append(fsm.getFileSystem(fs)) - self.assertEqual(EnkfFsManager.DEFAULT_CAPACITY, fsm.getFileSystemCount()) - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_library.py b/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_library.py deleted file mode 100644 index 3ed1dbaa42..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_library.py +++ /dev/null @@ -1,56 +0,0 @@ -import os -from ert.ecl import EclSum -from ert.enkf import AnalysisConfig, EclConfig, GenKwConfig, EnkfConfigNode, SiteConfig, ObsVector -from ert.enkf import GenDataConfig, FieldConfig, EnkfFs, EnkfObs, EnKFState, EnsembleConfig -from ert.enkf import ErtTemplate, ErtTemplates, LocalConfig, ModelConfig -from ert.enkf.enkf_main import EnKFMain - -from ert.enkf.util import TimeMap -from ert.test import ExtendedTestCase , TestAreaContext - - -class EnKFLibraryTest(ExtendedTestCase): - def setUp(self): - self.case_directory = self.createTestPath("local/simple_config/") - - def test_failed_class_creation(self): - classes = [EnkfConfigNode, EnKFState, - ErtTemplate, ErtTemplates, LocalConfig, ModelConfig, SiteConfig] - - for cls in classes: - with self.assertRaises(NotImplementedError): - temp = cls() - - - def test_ecl_config_creation(self): - with TestAreaContext("enkf_library_test") as work_area: - work_area.copy_directory(self.case_directory) - - main = EnKFMain("simple_config/minimum_config") - - self.assertIsInstance(main.analysisConfig(), AnalysisConfig) - self.assertIsInstance(main.eclConfig(), EclConfig) - - with self.assertRaises(AssertionError): # Null pointer! - self.assertIsInstance(main.eclConfig().getRefcase(), EclSum) - - file_system = main.getEnkfFsManager().getCurrentFileSystem() - self.assertEqual(file_system.getCaseName(), "default") - time_map = file_system.getTimeMap() - self.assertIsInstance(time_map, TimeMap) - - main.free() - - - def test_enkf_state(self): - with TestAreaContext("enkf_library_test") as work_area: - work_area.copy_directory(self.case_directory) - - main = EnKFMain("simple_config/minimum_config") - state = main.getRealisation( 0 ) - - with self.assertRaises(TypeError): - state.addSubstKeyword( "GEO_ID" , 45) - - state.addSubstKeyword("GEO_ID" , "45") - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_load_results_manually.py b/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_load_results_manually.py deleted file mode 100644 index 03120b6d26..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_load_results_manually.py +++ /dev/null @@ -1,36 +0,0 @@ -from ert.enkf.enums.realization_state_enum import RealizationStateEnum -from ert.test import ErtTestContext, ExtendedTestCase -from ert.util import BoolVector - - -class LoadResultsManuallyTest(ExtendedTestCase): - def setUp(self): - self.config_file = self.createTestPath("Statoil/config/with_data/config") - - def test_load_results_manually(self): - with ErtTestContext("manual_load_test", self.config_file) as test_context: - ert = test_context.getErt() - load_into_case = "A1" - load_from_case = "default" - - load_into = ert.getEnkfFsManager().getFileSystem(load_into_case) - load_from = ert.getEnkfFsManager().getFileSystem(load_from_case) - - ert.getEnkfFsManager().switchFileSystem(load_from) - realisations = BoolVector(default_value=True,initial_size=25) - realisations[7] = False - iteration = 0 - - loaded = ert.loadFromForwardModel(realisations, iteration, load_into) - - load_into_case_state_map = load_into.getStateMap() - - load_into_states = [state for state in load_into_case_state_map] - - expected = [RealizationStateEnum.STATE_HAS_DATA] * 25 - expected[7] = RealizationStateEnum.STATE_UNDEFINED - - self.assertListEqual(load_into_states, expected) - self.assertEqual(24, loaded) - self.assertEqual(25, len(expected)) - self.assertEqual(25, len(realisations)) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_obs.py b/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_obs.py deleted file mode 100644 index daac7e062d..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_enkf_obs.py +++ /dev/null @@ -1,258 +0,0 @@ -from ert.test import ErtTestContext -from ert.test import ExtendedTestCase - -from ert.ecl import EclGrid, EclSum -from ert.sched import History - -from ert.util import BoolVector,IntVector -from ert.enkf import ActiveMode, EnsembleConfig -from ert.enkf import ObsVector , LocalObsdata, EnkfObs, TimeMap, LocalObsdataNode , ObsData , MeasData, ActiveList - - -class EnKFObsTest(ExtendedTestCase): - def setUp(self): - self.config_file = self.createTestPath("Statoil/config/obs_testing/config") - self.obs_config = self.createTestPath("Statoil/config/obs_testing/observations") - self.obs_config2 = self.createTestPath("Statoil/config/obs_testing/observations2") - self.refcase = self.createTestPath("Statoil/config/obs_testing/EXAMPLE_01_BASE") - self.grid = self.createTestPath("Statoil/config/obs_testing/EXAMPLE_01_BASE.EGRID") - - - def test_scale_obs(self): - with ErtTestContext("obs_test", self.config_file) as test_context: - ert = test_context.getErt() - obs = ert.getObservations() - - obs1 = obs["WWCT:OP_1"].getNode( 50 ) - obs2 = obs["WWCT:OP_1_50"].getNode( 50 ) - - self.assertEqual( obs1.getStandardDeviation( ) , obs2.getStandardDeviation( )) - std0 = obs1.getStandardDeviation( ) - - local_obsdata = LocalObsdata("obs" , obs) - node1 = local_obsdata.addNode( "WWCT:OP_1" ) - node2 = local_obsdata.addNode( "WWCT:OP_1_50" ) - node1.addTimeStep( 50 ) - node2.addTimeStep( 50 ) - - mask = BoolVector( default_value = True ) - mask[2] = True - meas_data = MeasData(mask) - obs_data = ObsData( ) - fs = ert.getEnkfFsManager().getCurrentFileSystem() - active_list = IntVector() - active_list.initRange(0,2,1) - obs.getObservationAndMeasureData( fs , local_obsdata , active_list , meas_data , obs_data ) - self.assertEqual( 2 , len(obs_data) ) - - v1 = obs_data[0] - v2 = obs_data[1] - - self.assertEqual( v1[1] , std0 ) - self.assertEqual( v2[1] , std0 ) - - meas_data = MeasData(mask) - obs_data = ObsData( 10 ) - obs.getObservationAndMeasureData( fs , local_obsdata , active_list , meas_data , obs_data ) - self.assertEqual( 2 , len(obs_data) ) - - v1 = obs_data[0] - v2 = obs_data[1] - - self.assertEqual( v1[1] , std0*10) - self.assertEqual( v2[1] , std0*10 ) - - actl = ActiveList() - obs1.updateStdScaling( 10 , actl) - obs2.updateStdScaling( 20 , actl) - meas_data = MeasData(mask) - obs_data = ObsData( ) - obs.getObservationAndMeasureData( fs , local_obsdata , active_list , meas_data , obs_data ) - self.assertEqual( 2 , len(obs_data) ) - - v1 = obs_data[0] - v2 = obs_data[1] - - self.assertEqual( v1[1] , std0*10) - self.assertEqual( v2[1] , std0*20) - - - - - - - def testObs(self): - with ErtTestContext("obs_test", self.config_file) as test_context: - ert = test_context.getErt() - obs = ert.getObservations() - - self.assertEqual(32, len(obs)) - for v in obs: - self.assertTrue(isinstance(v, ObsVector)) - - self.assertEqual(obs[-1].getKey(), 'RFT_TEST') - self.assertEqual(obs[-1].getDataKey(),'4289383' ) - self.assertEqual(obs[-1].getObsKey(), 'RFT_TEST') - - with self.assertRaises(IndexError): - v = obs[-40] - with self.assertRaises(IndexError): - v = obs[40] - - with self.assertRaises(KeyError): - v = obs["No-this-does-not-exist"] - - v1 = obs["WWCT:OP_3"] - v2 = obs["GOPT:OP"] - mask = BoolVector(True, ert.getEnsembleSize()) - current_fs = ert.getEnkfFsManager().getCurrentFileSystem() - - self.assertTrue(v1.hasData(mask, current_fs)) - self.assertFalse(v2.hasData(mask, current_fs)) - - local_node = v1.createLocalObs( ) - for t in v1.getStepList(): - self.assertTrue( local_node.tstepActive( t )) - - - - def test_obs_block_scale_std(self): - with ErtTestContext("obs_test_scale", self.config_file) as test_context: - ert = test_context.getErt() - fs = ert.getEnkfFsManager().getCurrentFileSystem() - active_list = IntVector( ) - active_list.initRange(0 , ert.getEnsembleSize() , 1 ) - - obs = ert.getObservations() - obs_data = LocalObsdata( "OBSxx" , obs ) - obs_vector = obs["WWCT:OP_1"] - obs_data.addObsVector( obs_vector ) - scale_factor = obs.scaleCorrelatedStd( fs , obs_data , active_list ) - - for obs_node in obs_vector: - for index in range(len(obs_node)): - self.assertEqual( scale_factor , obs_node.getStdScaling( index )) - - - - - def test_obs_block_all_active_local(self): - with ErtTestContext("obs_test_all_active", self.config_file) as test_context: - ert = test_context.getErt() - obs = ert.getObservations() - obs_data = obs.getAllActiveLocalObsdata( ) - - self.assertEqual( len(obs_data) , len(obs) ) - for obs_vector in obs: - self.assertTrue( obs_vector.getObservationKey() in obs_data ) - - tstep_list1 = obs_vector.getStepList() - local_node = obs_data[ obs_vector.getObservationKey() ] - for t in tstep_list1: - self.assertTrue( local_node.tstepActive( t )) - - active_list = local_node.getActiveList() - self.assertEqual( active_list.getMode() , ActiveMode.ALL_ACTIVE ) - - - - def test_create(self): - ensemble_config = EnsembleConfig() - obs = EnkfObs(ensemble_config) - self.assertEqual( len(obs) , 0 ) - self.assertFalse( obs.load(self.obs_config) ) - self.assertEqual( len(obs) , 0 ) - - - time_map = TimeMap() - obs = EnkfObs(ensemble_config , external_time_map = time_map) - self.assertEqual( len(obs) , 0 ) - - grid = EclGrid(self.grid) - refcase = EclSum(self.refcase) - - history = History( refcase , False ) - obs = EnkfObs( ensemble_config , grid = grid , history = history ) - with self.assertRaises(IOError): - obs.load("/does/not/exist") - - self.assertTrue( obs.load(self.obs_config) ) - self.assertEqual( len(obs) , 33 ) - obs.clear() - self.assertEqual( len(obs) , 0 ) - - obs.load(self.obs_config) - self.assertEqual( len(obs) , 33 ) - self.assertFalse( "RFT2" in obs ) - obs.load(self.obs_config2) - self.assertEqual( len(obs) , 35 ) - self.assertTrue( "RFT2" in obs ) - - def test_hookmanager_runpathlist(self): - with ErtTestContext("obs_test", self.config_file) as test_context: - ert = test_context.getErt() - hm = ert.getHookManager() - pfx = 'HookManager(size = ' - self.assertEqual(repr(hm)[:len(pfx)], pfx) - - rpl = hm.getRunpathList() - pfx = 'RunpathList(size = ' - self.assertEqual(repr(rpl)[:len(pfx)], pfx) - - ef = rpl.getExportFile() - self.assertTrue('.ert_runpath_list' in ef) - nf = 'myExportCamel' - rpl.setExportFile('myExportCamel') - ef = rpl.getExportFile() - self.assertTrue(nf in ef) - - - - def test_ert_obs_reload(self): - with ErtTestContext("obs_test_reload", self.config_file) as test_context: - ert = test_context.getErt() - local_config = ert.getLocalConfig( ) - update_step = local_config.getUpdatestep( ) - mini_step = update_step[0] - local_obs = mini_step.getLocalObsData( ) - self.assertTrue( "WGOR:OP_5" in local_obs ) - self.assertTrue( "RPR2_1" in local_obs ) - - - ens_config = ert.ensembleConfig( ) - wwct_op1 = ens_config["WWCT:OP_1"] - wopr_op5 = ens_config["WOPR:OP_5"] - - obs = ert.getObservations() - self.assertEqual( len(obs) , 32 ) - - keys = wwct_op1.getObservationKeys() - self.assertEqual( len(keys) , 2 ) - self.assertTrue( "WWCT:OP_1" in keys ) - self.assertTrue( "WWCT:OP_1_50" in keys ) - - self.assertEqual( wopr_op5.getObservationKeys() , [] ) - - ert.loadObservations("observations2") - self.assertEqual( len(obs) , 2 ) - self.assertEqual( wwct_op1.getObservationKeys() , [] ) - self.assertEqual( wopr_op5.getObservationKeys() , ["WOPR:OP_5"] ) - - local_config = ert.getLocalConfig( ) - update_step = local_config.getUpdatestep( ) - mini_step = update_step[0] - local_obs = mini_step.getLocalObsData( ) - self.assertTrue( "WOPR:OP_5" in local_obs ) - self.assertTrue( "RFT2" in local_obs ) - self.assertFalse( "WGOR:OP_5" in local_obs ) - self.assertFalse( "RPR2_1" in local_obs ) - - - ert.loadObservations("observations" , clear = False) - self.assertEqual( len(obs) , 34 ) - keys = wwct_op1.getObservationKeys() - self.assertEqual( len(keys) , 2 ) - self.assertTrue( "WWCT:OP_1" in keys ) - self.assertTrue( "WWCT:OP_1_50" in keys ) - - self.assertEqual( wopr_op5.getObservationKeys() , ["WOPR:OP_5"] ) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_ensemble_config.py b/ThirdParty/Ert/python/tests/ert/enkf/test_ensemble_config.py deleted file mode 100644 index e5f64250e2..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_ensemble_config.py +++ /dev/null @@ -1,17 +0,0 @@ -from ert.test import ErtTestContext -from ert.test import ExtendedTestCase - -from ert.util import BoolVector,IntVector -from ert.enkf import ActiveMode, EnsembleConfig -from ert.enkf import ObsVector , LocalObsdata - - -class EnsembleConfigTest(ExtendedTestCase): - - def test_create(self): - conf = EnsembleConfig( ) - self.assertEqual( len(conf) , 0 ) - self.assertFalse( "XYZ" in conf ) - - with self.assertRaises(KeyError): - node = conf["KEY"] diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_ert_context.py b/ThirdParty/Ert/python/tests/ert/enkf/test_ert_context.py deleted file mode 100644 index 6356f653d2..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_ert_context.py +++ /dev/null @@ -1,95 +0,0 @@ -from ert.test import ErtTestContext, ExtendedTestCase - - -class ErtTestContextTest(ExtendedTestCase): - def setUp(self): - self.config = self.createTestPath("Statoil/config/with_data/config") - - def test_raises(self): - with self.assertRaises(IOError): - testContext = ErtTestContext("ExistTest" , "Does/not/exist") - - - def initFromCaseTest(self, context, root_path): - ert = context.getErt() - - init_case_job = self.createSharePath("%s/INIT_CASE_FROM_EXISTING" % root_path) - self.assertTrue(context.installWorkflowJob("INIT_CASE_JOB", init_case_job)) - self.assertTrue(context.runWorkflowJob("INIT_CASE_JOB", "default", "new_not_current_case")) - - default_fs = ert.getEnkfFsManager().getFileSystem("default") - new_fs = ert.getEnkfFsManager().getFileSystem("new_not_current_case") - - self.assertIsNotNone(default_fs) - self.assertIsNotNone(new_fs) - - self.assertTrue(len(default_fs.getStateMap()) > 0) - self.assertEqual(len(default_fs.getStateMap()), len(new_fs.getStateMap())) - - - def createCaseTest(self, context, root_path): - create_case_job = self.createSharePath("%s/CREATE_CASE" % root_path) - self.assertTrue(context.installWorkflowJob("CREATE_CASE_JOB", create_case_job)) - self.assertTrue(context.runWorkflowJob("CREATE_CASE_JOB", "newly_created_case")) - self.assertDirectoryExists("storage/newly_created_case") - - - def selectCaseTest(self, context, root_path): - ert = context.getErt() - select_case_job = self.createSharePath("%s/SELECT_CASE" % root_path) - - default_fs = ert.getEnkfFsManager().getCurrentFileSystem() - - custom_fs = ert.getEnkfFsManager().getFileSystem("CustomCase") - - self.assertEqual(ert.getEnkfFsManager().getCurrentFileSystem(), default_fs) - - self.assertTrue(context.installWorkflowJob("SELECT_CASE_JOB", select_case_job)) - self.assertTrue(context.runWorkflowJob("SELECT_CASE_JOB", "CustomCase")) - - self.assertEqual(ert.getEnkfFsManager().getCurrentFileSystem(), custom_fs) - - - def loadResultsTest(self, context): - load_results_job = self.createSharePath("workflows/jobs/internal/config/LOAD_RESULTS") - self.assertTrue(context.installWorkflowJob("LOAD_RESULTS_JOB", load_results_job)) - self.assertTrue(context.runWorkflowJob("LOAD_RESULTS_JOB", 0, 1)) - - - def rankRealizationsOnObservationsTest(self, context): - rank_job = self.createSharePath("workflows/jobs/internal/config/OBSERVATION_RANKING") - - self.assertTrue(context.installWorkflowJob("OBS_RANK_JOB", rank_job)) - - self.assertTrue(context.runWorkflowJob("OBS_RANK_JOB", "NameOfObsRanking1", "|", "WOPR:*")) - self.assertTrue(context.runWorkflowJob("OBS_RANK_JOB", "NameOfObsRanking2", "1-5", "55", "|", "WWCT:*", "WOPR:*")) - self.assertTrue(context.runWorkflowJob("OBS_RANK_JOB", "NameOfObsRanking3", "5", "55", "|")) - self.assertTrue(context.runWorkflowJob("OBS_RANK_JOB", "NameOfObsRanking4", "1,3,5-10", "55")) - self.assertTrue(context.runWorkflowJob("OBS_RANK_JOB", "NameOfObsRanking5")) - self.assertTrue(context.runWorkflowJob("OBS_RANK_JOB", "NameOfObsRanking6", "|", "UnrecognizableObservation")) - - - def test_workflow_function_jobs(self): - - with ErtTestContext("python/enkf/ert_test_context_workflow_function_job", self.config) as context: - internal_config = "workflows/jobs/internal-tui/config" - self.createCaseTest(context, root_path=internal_config) - self.selectCaseTest(context, root_path=internal_config) - - # Due to EnKFFs caching and unmonitored C functions this will fail - #self.initFromCaseTest(context, root_path=internal_config) - - self.loadResultsTest(context) - self.rankRealizationsOnObservationsTest(context) - - - - def test_workflow_ert_script_jobs(self): - - with ErtTestContext("python/enkf/ert_test_context_workflow_ert_script_job", self.config) as context: - ert_scripts_config = "workflows/jobs/internal-gui/config" - self.createCaseTest(context, root_path=ert_scripts_config) - self.selectCaseTest(context, root_path=ert_scripts_config) - self.initFromCaseTest(context, root_path=ert_scripts_config) - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_ert_log.py b/ThirdParty/Ert/python/tests/ert/enkf/test_ert_log.py deleted file mode 100644 index f98551f566..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_ert_log.py +++ /dev/null @@ -1,31 +0,0 @@ -import os -from ert.enkf import ErtLog -from ert.test import ExtendedTestCase, TestAreaContext - - -class ErtLogTest(ExtendedTestCase): - - def test_log(self): - with TestAreaContext("python/ert_log/log") as work_area: - test_log_filename = "test_log" - ErtLog.init(1, test_log_filename, True) - message = "This is fun" - ErtLog.log(1, message) - - self.assertTrue(os.path.isfile(test_log_filename)) - - with open(test_log_filename, "r") as f: - text = f.readlines() - self.assertTrue(len(text) > 0) - self.assertTrue(message in text[-1]) - - - def test_getFilename(self): - with TestAreaContext("python/ert_log/log") as work_area: - test_log_filename = "log_test_file.txt" - ErtLog.init(1, test_log_filename, True) - message = "This is fun" - ErtLog.log(1, message) - - self.assertEqual(ErtLog.getFilename(), test_log_filename) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_es_update.py b/ThirdParty/Ert/python/tests/ert/enkf/test_es_update.py deleted file mode 100644 index 09b7202b97..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_es_update.py +++ /dev/null @@ -1,19 +0,0 @@ -from ert.test import ExtendedTestCase, ErtTestContext -from ert.enkf import ESUpdate - - -class ESUpdateTest(ExtendedTestCase): - - def test_create(self): - config = self.createTestPath("local/custom_kw/mini_config") - with ErtTestContext("python/enkf/data/custom_kw_simulated", config) as context: - ert = context.getErt() - es_update = ESUpdate( ert ) - - self.assertFalse( es_update.hasModule( "NO_NOT_THIS_MODULE" )) - with self.assertRaises(KeyError): - m = es_update.getModule( "STD_ENKF_XXX" ) - - module = es_update.getModule( "STD_ENKF" ) - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_field_config.py b/ThirdParty/Ert/python/tests/ert/enkf/test_field_config.py deleted file mode 100644 index eb5e8062d7..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_field_config.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright (C) 2017 Statoil ASA, Norway. -# -# This file is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -from os.path import abspath - -from ert.ecl import EclGrid -from ert.enkf.config import FieldTypeEnum, FieldConfig -from ert.enkf.enums import EnkfFieldFileFormatEnum -from ert.test import ExtendedTestCase, TestAreaContext - -class FieldConfigTest(ExtendedTestCase): - - def test_field_guess_filetype(self): - with TestAreaContext('field_config') as test_context: - fname = abspath('test.kw.grdecl') - print(fname) - with open(fname, 'w') as f: - f.write("-- my comment\n") - f.write("-- more comments\n") - f.write("SOWCR\n") - for i in range(256//8): # technicalities demand file has >= 256B - f.write("0 0 0 0\n") - - ft = FieldConfig.guessFiletype(fname) - grdecl_type = EnkfFieldFileFormatEnum(5) - self.assertEqual('ECL_GRDECL_FILE', grdecl_type.name) - self.assertEqual(grdecl_type, ft) - - def test_field_type_enum(self): - self.assertEqual(FieldTypeEnum(2), FieldTypeEnum.ECLIPSE_PARAMETER) - gen = FieldTypeEnum.GENERAL - self.assertEqual('GENERAL', str(gen)) - gen = FieldTypeEnum(3) - self.assertEqual('GENERAL', str(gen)) - - def test_export_format(self): - self.assertEqual(FieldConfig.exportFormat("file.grdecl"), EnkfFieldFileFormatEnum.ECL_GRDECL_FILE) - self.assertEqual(FieldConfig.exportFormat("file.xyz.grdecl"), EnkfFieldFileFormatEnum.ECL_GRDECL_FILE) - self.assertEqual(FieldConfig.exportFormat("file.roFF"), EnkfFieldFileFormatEnum.RMS_ROFF_FILE) - self.assertEqual(FieldConfig.exportFormat("file.xyz.roFF"), EnkfFieldFileFormatEnum.RMS_ROFF_FILE) - - with self.assertRaises(ValueError): - FieldConfig.exportFormat("file.xyz") - - with self.assertRaises(ValueError): - FieldConfig.exportFormat("file.xyz") - - def test_basics(self): - grid = EclGrid.createRectangular((17,13,11),(1,1,1)) - fc = FieldConfig('PORO',grid) - print(fc) - print(str(fc)) - print(repr(fc)) - pfx = 'FieldConfig(type' - rep = repr(fc) - self.assertEqual(pfx, rep[:len(pfx)]) - fc_xyz = fc.get_nx(),fc.get_ny(),fc.get_nz() - ex_xyz = 17,13,11 - self.assertEqual(ex_xyz, fc_xyz) - self.assertEqual(0, fc.get_truncation_mode()) - self.assertEqual(ex_xyz, (grid.getNX(), grid.getNY(), grid.getNZ())) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_field_export.py b/ThirdParty/Ert/python/tests/ert/enkf/test_field_export.py deleted file mode 100644 index 1f5b7b280b..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_field_export.py +++ /dev/null @@ -1,81 +0,0 @@ -import os - -from ert.util import IntVector - -from ert.ecl import EclGrid - -from ert.enkf.config import FieldTypeEnum, FieldConfig -from ert.enkf.data import EnkfNode -from ert.enkf.enums import EnkfFieldFileFormatEnum -from ert.enkf import NodeId - -from ert.test import ExtendedTestCase -from ert.test import ErtTestContext - - -class FieldExportTest(ExtendedTestCase): - def setUp(self): - self.config_file = self.createTestPath("Statoil/config/obs_testing/config") - - def test_field_type_enum(self): - with ErtTestContext("export_test", self.config_file) as test_context: - ert = test_context.getErt() - ens_config = ert.ensembleConfig() - fc = ens_config["PERMX"].getFieldModelConfig() - self.assertEqual(FieldTypeEnum.ECLIPSE_PARAMETER, fc.get_type()) - - def test_field_basics(self): - with ErtTestContext("export_test", self.config_file) as test_context: - ert = test_context.getErt() - ens_config = ert.ensembleConfig() - fc = ens_config["PERMX"].getFieldModelConfig() - pfx = 'FieldConfig(type' - rep = repr(fc) - self.assertEqual(pfx, rep[:len(pfx)]) - fc_xyz = fc.get_nx(),fc.get_ny(),fc.get_nz() - ex_xyz = 40,64,14 - self.assertEqual(ex_xyz, fc_xyz) - self.assertEqual(1, fc.get_truncation_mode()) - self.assertEqual(0.001, fc.get_truncation_min()) - self.assertEqual(-1.0, fc.get_truncation_max()) - self.assertEqual('LOG', fc.get_init_transform_name()) - self.assertEqual(None, fc.get_output_transform_name()) - grid = fc.get_grid() - self.assertEqual(ex_xyz, (grid.getNX(), grid.getNY(), grid.getNZ())) - - def test_field_export(self): - with ErtTestContext("export_test", self.config_file) as test_context: - ert = test_context.getErt() - fs_manager = ert.getEnkfFsManager( ) - ens_config = ert.ensembleConfig() - config_node = ens_config["PERMX"] - data_node = EnkfNode( config_node ) - node_id = NodeId( 0 , 0 ) - fs = fs_manager.getCurrentFileSystem( ) - data_node.tryLoad( fs , node_id ) - - data_node.export("export/with/path/PERMX.grdecl") - self.assertTrue( os.path.isfile("export/with/path/PERMX.grdecl") ) - - - def test_field_export_many(self): - with ErtTestContext("export_test", self.config_file) as test_context: - ert = test_context.getErt() - fs_manager = ert.getEnkfFsManager( ) - ens_config = ert.ensembleConfig() - config_node = ens_config["PERMX"] - iens_list = IntVector( ) - iens_list.append(0) - iens_list.append(2) - iens_list.append(4) - - fs = fs_manager.getCurrentFileSystem( ) - - # Filename without embedded %d - TypeError - with self.assertRaises(TypeError): - EnkfNode.exportMany( config_node , "export/with/path/PERMX.grdecl" , fs , iens_list ) - - EnkfNode.exportMany( config_node , "export/with/path/PERMX_%d.grdecl" , fs , iens_list ) - self.assertTrue( os.path.isfile("export/with/path/PERMX_0.grdecl") ) - self.assertTrue( os.path.isfile("export/with/path/PERMX_2.grdecl") ) - self.assertTrue( os.path.isfile("export/with/path/PERMX_4.grdecl") ) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_forward_load_context.py b/ThirdParty/Ert/python/tests/ert/enkf/test_forward_load_context.py deleted file mode 100644 index 82970a06aa..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_forward_load_context.py +++ /dev/null @@ -1,9 +0,0 @@ -from ert.test import ExtendedTestCase -from ert.enkf import ForwardLoadContext - -class ForwardLoadContextTest(ExtendedTestCase): - - def test_create(self): - ctx = ForwardLoadContext( report_step = 1 ) - self.assertEqual( 1 , ctx.getLoadStep( ) ) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_gen_obs.py b/ThirdParty/Ert/python/tests/ert/enkf/test_gen_obs.py deleted file mode 100644 index 429a3852cc..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_gen_obs.py +++ /dev/null @@ -1,52 +0,0 @@ -import os.path - -from ert.test import ExtendedTestCase, TestAreaContext - -from ert.enkf import GenObservation,GenDataConfig,ActiveList - - - - -class GenObsTest(ExtendedTestCase): - def setUp(self): - pass - - - def test_create(self): - data_config = GenDataConfig("KEY") - with self.assertRaises(ValueError): - gen_obs = GenObservation("KEY" , data_config ) - - with TestAreaContext("gen_obs/create"): - with open("obs1.txt","w") as f: - f.write("10 5 12 6\n") - - with self.assertRaises(ValueError): - gen_obs = GenObservation("KEY" , data_config , scalar_value = (1,2) , obs_file = "obs1.txt") - - with self.assertRaises(TypeError): - gen_obs = GenObservation("KEY" , data_config , scalar_value = 1 ) - - with self.assertRaises(IOError): - gen_obs = GenObservation("KEY" , data_config , obs_file = "does/not/exist" ) - - gen_obs = GenObservation("KEY" , data_config , obs_file = "obs1.txt" , data_index = "10,20") - self.assertEqual( len(gen_obs) , 2 ) - self.assertEqual( gen_obs[0] , (10,5) ) - self.assertEqual( gen_obs[1] , (12,6) ) - - self.assertEqual( gen_obs.getValue(0) , 10 ) - self.assertEqual( gen_obs.getDataIndex(1) , 20 ) - self.assertEqual( gen_obs.getStdScaling(0) , 1 ) - self.assertEqual( gen_obs.getStdScaling(1) , 1 ) - - active_list = ActiveList( ) - gen_obs.updateStdScaling( 0.25 , active_list ) - self.assertEqual( gen_obs.getStdScaling(0) , 0.25 ) - self.assertEqual( gen_obs.getStdScaling(1) , 0.25 ) - - active_list.addActiveIndex( 1 ) - gen_obs.updateStdScaling( 2.00 , active_list ) - self.assertEqual( gen_obs.getStdScaling(0) , 0.25 ) - self.assertEqual( gen_obs.getStdScaling(1) , 2.00 ) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_hook_workflow.py b/ThirdParty/Ert/python/tests/ert/enkf/test_hook_workflow.py deleted file mode 100644 index c5a105576c..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_hook_workflow.py +++ /dev/null @@ -1,9 +0,0 @@ -from ert.enkf.enums import HookRuntime -from ert.test import ExtendedTestCase - - -class HookWorkFlowTest(ExtendedTestCase): - - def test_enum(self): - self.assertEnumIsFullyDefined(HookRuntime, "hook_run_mode_enum" , "libenkf/include/ert/enkf/hook_workflow.h", verbose=True) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_labscale.py b/ThirdParty/Ert/python/tests/ert/enkf/test_labscale.py deleted file mode 100644 index 38db80bce9..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_labscale.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'test_labscale.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -from ert.enkf import ObsVector -from ert.test import ExtendedTestCase , ErtTestContext - - - -class LabScaleTest(ExtendedTestCase): - - - def testObs(self): - config_file = self.createTestPath("Statoil/config/labscale/config") - with ErtTestContext("labscale", config_file) as test_context: - ert = test_context.getErt() - obs = ert.getObservations() - - self.assertEqual(4, len(obs)) - for v in obs: - self.assertTrue(isinstance(v, ObsVector)) - - v1 = obs["WWCT_1"] - self.assertEqual( v1.activeStep() , 5 ) - node = v1.getNode( 5 ) - self.assertFloatEqual( node.getValue() , 0.00) - - v2 = obs["WWCT_2"] - self.assertEqual( v2.activeStep() , 31 ) - node = v2.getNode( 31 ) - self.assertFloatEqual( node.getValue() , 0.575828) - - v3 = obs["WWCT_3"] - self.assertEqual( v3.activeStep() , 73 ) - node = v3.getNode( 73 ) - self.assertFloatEqual( node.getValue() , 1.00) - - - bpr = obs["BPR"] - self.assertEqual( bpr.activeStep() , 31 ) - node = bpr.getNode( 31 ) - self.assertFloatEqual( node.getValue(0) , 10.284) - - - - def testObs_beijing(self): - config_file = self.createTestPath("Statoil/config/lab-beijing/labunits/config") - with ErtTestContext("labscale-beijing", config_file) as test_context: - ert = test_context.getErt() - obs = ert.getObservations() - - - v0 = obs["WCT0"] - self.assertEqual( v0.activeStep() , 18 ) - node = v0.getNode( 18 ) - self.assertEqual( node.getValue() , 0.12345 ) - - - v1 = obs["WCT1"] - self.assertEqual( v1.activeStep() , 18 ) - node = v1.getNode( 18 ) - self.assertEqual( node.getValue() , 0.12345 ) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_linalg.py b/ThirdParty/Ert/python/tests/ert/enkf/test_linalg.py deleted file mode 100644 index 0106b60c6e..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_linalg.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'test_labscale.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - - -from ert.enkf import ObsVector -from ert.util import Matrix -from ert.enkf.linalg import * - - -class LinalgTest(ExtendedTestCase): - - def test_num_PC(self): - S = Matrix(3,3) - s[0,0] = 1 - s[1,1] = 0.25 - s[2,2] = 0.125 - - with self.assertRaises(ValueError): - num_pc = numPC( S , -1 ) - - - with self.assertRaises(ValueError): - num_pc = numPC( S , 1.5 ) - - num_pc = numPC( S , 0.80 ) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_local_config.py b/ThirdParty/Ert/python/tests/ert/enkf/test_local_config.py deleted file mode 100644 index 0154d45b8b..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_local_config.py +++ /dev/null @@ -1,187 +0,0 @@ -import os.path -from ert.ecl import EclGrid - -from ert.test import ExtendedTestCase -from ert.test import ErtTestContext -from ert.enkf.local_ministep import LocalMinistep -from ert.enkf.active_list import ActiveList -from ert.enkf.local_obsdata import LocalObsdata -from ert.enkf.local_updatestep import LocalUpdateStep -from ert.enkf.local_obsdata_node import LocalObsdataNode -from ert.enkf import local_config -from ert.enkf.local_dataset import LocalDataset - -class LocalConfigTest(ExtendedTestCase): - - def setUp(self): - - self.config = self.createTestPath("local/custom_kw/mini_config") - - def testLocalConfig(self): - - with ErtTestContext("python/enkf/data/local_config", self.config) as test_context: - - main = test_context.getErt() - self.assertTrue(main, "Load failed") - - local_config = main.getLocalConfig() - analysis_module = main.analysisConfig().getModule("STD_ENKF") - - self.AllActive(local_config) - - local_config.clear() - - self.MiniStep(local_config, analysis_module) - - self.AttachMinistep(local_config) - - self.LocalDataset(local_config) - - self.LocalObsdata(local_config) - - local_config_file_summary = "local_config_summary.txt" - local_config.writeSummaryFile( local_config_file_summary ) - self.assertTrue( os.path.isfile( local_config_file_summary )) - - self.clear(local_config) - - grid = local_config.getGrid() - self.assertTrue( isinstance( grid , EclGrid )) - - def clear(self, local_config): - local_config.clear() - updateStep = local_config.getUpdatestep( ) - self.assertEqual( len(updateStep) , 0 ) - - - - def AllActive(self , local_config): - updateStep = local_config.getUpdatestep( ) - ministep = updateStep[0] - self.assertEqual( 1 , len(ministep) ) - dataset = ministep["ALL_DATA"] - - self.assertTrue( "PERLIN_PARAM" in dataset ) - - obsdata = ministep.getLocalObsData() - self.assertEqual( len(obsdata) , 3 ) - - - def MiniStep( self, local_config, analysis_module ): - - # Ministep - ministep = local_config.createMinistep("MINISTEP", analysis_module) - self.assertTrue(isinstance(ministep, LocalMinistep)) - - self.assertFalse( "DATA" in ministep ) - with self.assertRaises(KeyError): - ministep["DATA"] - - - def AttachMinistep( self, local_config): - - # Update step - updatestep = local_config.getUpdatestep( ) - self.assertTrue(isinstance(updatestep, LocalUpdateStep)) - n1 = len(updatestep) - - # Ministep - ministep = local_config.createMinistep("MINISTEP") - self.assertTrue(isinstance(ministep, LocalMinistep)) - - # Attach - updatestep.attachMinistep(ministep) - self.assertTrue(isinstance(updatestep[0], LocalMinistep)) - - self.assertEqual( len(updatestep) , n1 + 1 ) - - - def LocalDataset( self, local_config ): - - # Creating dataset - data_scale = local_config.createDataset("DATA_SCALE") - self.assertTrue(isinstance(data_scale, LocalDataset)) - - # Try to add existing dataset - with self.assertRaises(ValueError): - local_config.createDataset("DATA_SCALE") - - with self.assertRaises(KeyError): - data_scale.addNode("MISSING") - - data_scale.addNode("PERLIN_PARAM") - active_list = data_scale.getActiveList("PERLIN_PARAM") - self.assertTrue(isinstance(active_list, ActiveList)) - active_list.addActiveIndex(0) - - self.assertTrue("PERLIN_PARAM" in data_scale) - self.assertFalse("MISSING" in data_scale) - - ministep = local_config.createMinistep("MINISTEP") - ministep.attachDataset( data_scale ) - self.assertTrue( "DATA_SCALE" in ministep ) - data_scale_get = ministep["DATA_SCALE"] - self.assertTrue( "PERLIN_PARAM" in data_scale_get ) - - # Error when adding existing data node - with self.assertRaises(KeyError): - data_scale.addNode("PERLIN_PARAM") - - - - def LocalObsdata( self, local_config ): - - # Creating obsdata - local_obs_data_1 = local_config.createObsdata("OBSSET_1") - self.assertTrue(isinstance(local_obs_data_1, LocalObsdata)) - - # Try to add existing obsdata - with self.assertRaises(ValueError): - local_config.createObsdata("OBSSET_1") - - # Add node with range - with self.assertRaises(KeyError): - local_obs_data_1.addNodeAndRange("MISSING_KEY" , 0 , 1 ) - - local_obs_data_1.addNodeAndRange("GEN_PERLIN_1", 0, 1) - local_obs_data_1.addNodeAndRange("GEN_PERLIN_2", 0, 1) - - self.assertEqual( len(local_obs_data_1) , 2 ) - - # Delete node - del local_obs_data_1["GEN_PERLIN_1"] - self.assertEqual( len(local_obs_data_1) , 1 ) - - # Get node - node = local_obs_data_1["GEN_PERLIN_2"] - self.assertTrue(isinstance(node, LocalObsdataNode)) - - # Add node again with no range and check return type - node_again = local_obs_data_1.addNode("GEN_PERLIN_1") - self.assertTrue(isinstance(node_again, LocalObsdataNode)) - - # Error when adding existing obs node - with self.assertRaises(KeyError): - local_obs_data_1.addNode("GEN_PERLIN_1") - - - def AttachObsData( self , local_config): - - local_obs_data_2 = local_config.createObsdata("OBSSET_2") - self.assertTrue(isinstance(local_obs_data_2, LocalObsdata)) - - # Obsdata - local_obs_data_2.addNodeAndRange("GEN_PERLIN_1", 0, 1) - local_obs_data_2.addNodeAndRange("GEN_PERLIN_2", 0, 1) - - # Ministep - ministep = local_config.createMinistep("MINISTEP") - self.assertTrue(isinstance(ministep, LocalMinistep)) - - # Attach obsset - ministep.attachObsset(local_obs_data_2) - - # Retrieve attached obsset - local_obs_data_new = ministep.getLocalObsData() - self.assertEqual( len(local_obs_data_new) , 2 ) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_local_obsdata_node.py b/ThirdParty/Ert/python/tests/ert/enkf/test_local_obsdata_node.py deleted file mode 100644 index 903df7f61a..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_local_obsdata_node.py +++ /dev/null @@ -1,22 +0,0 @@ -from ert.enkf import LocalObsdataNode -from ert.test import ExtendedTestCase - - -class LocalObsdataNodeTest(ExtendedTestCase): - def setUp(self): - pass - - def test_tstep(self): - node = LocalObsdataNode("KEY") - self.assertTrue( node.allTimeStepActive() ) - self.assertTrue( node.tstepActive( 10 )) - self.assertTrue( node.tstepActive( 0 )) - - node.addTimeStep(10) - self.assertFalse( node.allTimeStepActive() ) - - self.assertTrue( node.tstepActive( 10 )) - self.assertFalse( node.tstepActive( 0 )) - - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_meas_block.py b/ThirdParty/Ert/python/tests/ert/enkf/test_meas_block.py deleted file mode 100644 index cff889fdab..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_meas_block.py +++ /dev/null @@ -1,103 +0,0 @@ -import datetime - -from ert.test import TestAreaContext -from ert.test import ExtendedTestCase -from ert.util import BoolVector -from ert.enkf import MeasBlock - - - -class MeasBlockTest(ExtendedTestCase): - - - def test_create(self): - key = "OBS" - ens_size = 100 - obs_size = 77 - ens_mask = BoolVector( default_value = True , initial_size = ens_size ) - - ens_mask[67] = False - block = MeasBlock( key , obs_size , ens_mask) - self.assertEqual( block.getObsSize() , obs_size ) - self.assertEqual( block.getActiveEnsSize() , ens_size - 1) - self.assertEqual( block.getTotalEnsSize() , ens_size ) - - self.assertTrue( block.iensActive( 66 ) ) - self.assertFalse( block.iensActive( 67 ) ) - - - - - def test_update(self): - key = "OBS" - obs_size = 4 - ens_size = 10 - ens_mask = BoolVector( default_value = True , initial_size = ens_size ) - block = MeasBlock( key , obs_size , ens_mask) - - with self.assertRaises(TypeError): - block["String"] = 10 - - with self.assertRaises(TypeError): - block[10] = 10 - - with self.assertRaises(IndexError): - block[obs_size,0] = 10 - - with self.assertRaises(IndexError): - block[0,ens_size] = 10 - - #----------------------------------------------------------------- - - with self.assertRaises(TypeError): - a = block["String"] - - with self.assertRaises(TypeError): - a = block[10] - - with self.assertRaises(IndexError): - val = block[obs_size,0] - - with self.assertRaises(IndexError): - val = block[0,ens_size] - - block[1,2] = 3 - self.assertEqual( 3 , block[1,2] ) - - - - def test_inactive(self): - key = "OBS" - obs_size = 2 - ens_size = 10 - ens_mask = BoolVector( default_value = True , initial_size = ens_size ) - ens_mask[5] = False - block = MeasBlock( key , obs_size , ens_mask) - - self.assertFalse( block.iensActive( 5 )) - - with self.assertRaises(ValueError): - block[0,5] = 10 - - - - - def test_stat(self): - key = "OBS" - obs_size = 2 - ens_size = 10 - ens_mask = BoolVector( default_value = True , initial_size = ens_size ) - block = MeasBlock( key , obs_size , ens_mask) - - for iens in range(ens_size): - block[0,iens] = iens - block[1,iens] = iens + 1 - - self.assertEqual( 4.5 , block.igetMean( 0 )) - self.assertEqual( 5.5 , block.igetMean( 1 )) - - self.assertFloatEqual( 2.872281 , block.igetStd( 0 )) - self.assertFloatEqual( 2.872281 , block.igetStd( 1 )) - - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_meas_data.py b/ThirdParty/Ert/python/tests/ert/enkf/test_meas_data.py deleted file mode 100644 index eb0d85e3ef..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_meas_data.py +++ /dev/null @@ -1,75 +0,0 @@ -import datetime - -from ert.util import BoolVector -from ert.test import TestAreaContext -from ert.test import ExtendedTestCase -from ert.enkf import MeasBlock,MeasData - - - -class MeasDataTest(ExtendedTestCase): - - - def test_create(self): - ens_size = 10 - ens_mask = BoolVector( default_value = True , initial_size = ens_size ) - data = MeasData( ens_mask ) - self.assertEqual( len(data) , 0) - self.assertTrue( isinstance( data , MeasData )) - - block1 = data.addBlock( "OBS1" , 10 , 5 ) - block2 = data.addBlock( "OBS2" , 27 , 10 ) - - with self.assertRaises(TypeError): - data[1.782] - - with self.assertRaises(KeyError): - data["NO-this-does-not-exist"] - - with self.assertRaises(IndexError): - data[2] - - last0 = data[-1] - last1 = data[1] - self.assertEqual( last0 , last1 ) - - self.assertTrue( "OBS1-10" in data ) - self.assertTrue( "OBS2-27" in data ) - self.assertEqual( len(data) , 2) - - self.assertTrue( isinstance( block1 , MeasBlock )) - self.assertTrue( isinstance( block2 , MeasBlock )) - - self.assertEqual( block1.getObsSize() , 5 ) - self.assertEqual( block2.getObsSize() , 10 ) - - l = [] - for b in data: - l.append(b) - - self.assertEqual(len(l) , 2) - self.assertEqual(l[0] , block1) - self.assertEqual(l[1] , block2) - - - with self.assertRaises(ValueError): - S = data.createS() - - for iens in range(ens_size): - block1[0,iens] = 5 - block2[0,iens] = 10 - block2[1,iens] = 15 - - self.assertEqual( 3 , data.activeObsSize() ) - S = data.createS() - - self.assertEqual( S.dims() , (3 , ens_size) ) - - for iens in range(ens_size): - self.assertEqual( S[0,iens] , 5 ) - self.assertEqual( S[1,iens] , 10 ) - self.assertEqual( S[2,iens] , 15 ) - - - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_obs_block.py b/ThirdParty/Ert/python/tests/ert/enkf/test_obs_block.py deleted file mode 100644 index 9862b9d8cd..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_obs_block.py +++ /dev/null @@ -1,51 +0,0 @@ -import datetime - -from ert.util import BoolVector -from ert.test import TestAreaContext -from ert.test import ExtendedTestCase -from ert.enkf import ObsBlock - - - -class ObsBlockTest(ExtendedTestCase): - - - def test_create(self): - block = ObsBlock("OBS" , 1000) - self.assertTrue( isinstance( block , ObsBlock )) - self.assertEqual( 1000 , block.totalSize()) - self.assertEqual( 0 , block.activeSize()) - - - - def test_access(self): - obs_size = 10 - block = ObsBlock("OBS" , obs_size) - - with self.assertRaises(IndexError): - block[100] = (1,1) - - with self.assertRaises(IndexError): - block[-100] = (1,1) - - with self.assertRaises(TypeError): - block[4] = 10 - - with self.assertRaises(TypeError): - block[4] = (1,1,9) - - #------ - - with self.assertRaises(IndexError): - v = block[100] - - with self.assertRaises(IndexError): - v = block[-100] - - block[0] = (10,1) - v = block[0] - self.assertEqual( v , (10,1)) - self.assertEqual( 1 , block.activeSize()) - - block[-1] = (17,19) - self.assertEqual( block[-1], (17,19)) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_obs_data.py b/ThirdParty/Ert/python/tests/ert/enkf/test_obs_data.py deleted file mode 100644 index def60a480f..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_obs_data.py +++ /dev/null @@ -1,53 +0,0 @@ -import datetime - -from ert.util import BoolVector , Matrix -from ert.test import TestAreaContext -from ert.test import ExtendedTestCase -from ert.enkf import ObsData , ObsBlock - - - - -class ObsDataTest(ExtendedTestCase): - - - def test_create(self): - obs_data = ObsData() - obs_size = 10 - block = obs_data.addBlock("OBS" , obs_size) - self.assertTrue( isinstance( block , ObsBlock )) - - block[0] = (100,10) - block[1] = (120,12) - D = obs_data.createDObs() - self.assertTrue( isinstance(D , Matrix )) - self.assertEqual( D.dims() , (2,2)) - - self.assertEqual( D[0,0] , 100 ) - self.assertEqual( D[1,0] , 120 ) - self.assertEqual( D[0,1] , 10 ) - self.assertEqual( D[1,1] , 12 ) - - obs_data.scaleMatrix( D ) - self.assertEqual( D[0,0] , 10 ) - self.assertEqual( D[1,0] , 10 ) - self.assertEqual( D[0,1] , 1 ) - self.assertEqual( D[1,1] , 1 ) - - R = obs_data.createR() - self.assertEqual( (2,2) , R.dims() ) - - with self.assertRaises(IndexError): - obs_data[10] - - v,s = obs_data[0] - self.assertEqual( v , 100 ) - self.assertEqual( s , 10 ) - - - v,s = obs_data[1] - self.assertEqual( v , 120 ) - self.assertEqual( s , 12 ) - - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_runpath_list.py b/ThirdParty/Ert/python/tests/ert/enkf/test_runpath_list.py deleted file mode 100644 index 82bf08f609..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_runpath_list.py +++ /dev/null @@ -1,155 +0,0 @@ -from os import path, symlink, remove - -import ert - -from ert.test import ExtendedTestCase, TestAreaContext,ErtTestContext -from ert.enkf import RunpathList, RunpathNode -from ert.util import BoolVector - -class RunpathListTest(ExtendedTestCase): - - def test_runpath_list(self): - runpath_list = RunpathList('') - - self.assertEqual(len(runpath_list), 0) - - test_runpath_nodes = [RunpathNode(0, 0, "runpath0", "basename0"), RunpathNode(1, 0, "runpath1", "basename0")] - - runpath_node = test_runpath_nodes[0] - runpath_list.add(runpath_node.realization, runpath_node.iteration, runpath_node.runpath, runpath_node.basename) - - self.assertEqual(len(runpath_list), 1) - self.assertEqual(runpath_list[0], test_runpath_nodes[0]) - - runpath_node = test_runpath_nodes[1] - runpath_list.add(runpath_node.realization, runpath_node.iteration, runpath_node.runpath, runpath_node.basename) - - self.assertEqual(len(runpath_list), 2) - self.assertEqual(runpath_list[1], test_runpath_nodes[1]) - - for index, runpath_node in enumerate(runpath_list): - self.assertEqual(runpath_node, test_runpath_nodes[index]) - - - runpath_list.clear() - - self.assertEqual(len(runpath_list), 0) - - - def test_collection(self): - """Testing len, adding, getting (idx and slice), printing, clearing.""" - def path(idx): - return 'path_%d' % idx - def base(idx): - return 'base_%d' % idx - with TestAreaContext("runpath_list"): - runpath_list = RunpathList("EXPORT.txt") - runpath_list.add( 3 , 1 , path(3) , base(3) ) - runpath_list.add( 1 , 1 , path(1) , base(1) ) - runpath_list.add( 2 , 1 , path(2) , base(2) ) - runpath_list.add( 0 , 0 , path(0) , base(0) ) - runpath_list.add( 3 , 0 , path(3) , base(3) ) - runpath_list.add( 1 , 0 , path(1) , base(1) ) - runpath_list.add( 2 , 0 , path(2) , base(2) ) - runpath_list.add( 0 , 1 , path(0) , base(0) ) - - self.assertEqual(8, len(runpath_list)) - pfx = 'RunpathList(size' # the __repr__ function - self.assertEqual(pfx, repr(runpath_list)[:len(pfx)]) - node2 = RunpathNode(2, 1 , path(2), base(2)) - self.assertEqual(node2, runpath_list[2]) - - node3 = RunpathNode(0,0,path(0),base(0)) - node4 = RunpathNode(3,0,path(3),base(3)) - node5 = RunpathNode(1,0,path(1),base(1)) - node6 = RunpathNode(2,0,path(2),base(2)) - nodeslice = [node3, node4, node5, node6] - self.assertEqual(nodeslice, runpath_list[3:7]) - self.assertEqual(node6, runpath_list[-2]) - with self.assertRaises(TypeError): - runpath_list["key"] - with self.assertRaises(IndexError): - runpath_list[12] - - runpath_list.clear() - self.assertEqual(0, len(runpath_list)) - with self.assertRaises(IndexError): - runpath_list[0] - self.assertEqual('EXPORT.txt', runpath_list.getExportFile()) - - - def test_sorted_export(self): - with TestAreaContext("runpath_list"): - runpath_list = RunpathList("EXPORT.txt") - runpath_list.add( 3 , 1 , "path" , "base" ) - runpath_list.add( 1 , 1 , "path" , "base" ) - runpath_list.add( 2 , 1 , "path" , "base" ) - runpath_list.add( 0 , 0 , "path" , "base" ) - - runpath_list.add( 3 , 0 , "path" , "base" ) - runpath_list.add( 1 , 0 , "path" , "base" ) - runpath_list.add( 2 , 0 , "path" , "base" ) - runpath_list.add( 0 , 1 , "path" , "base" ) - - runpath_list.export( ) - - path_list = [] - with open("EXPORT.txt") as f: - for line in f.readlines(): - tmp = line.split() - iens = int(tmp[0]) - iteration = int(tmp[3]) - - path_list.append( (iens , iteration) ) - - for iens in range(4): - t0 = path_list[iens] - t4 = path_list[iens + 4] - self.assertEqual( t0[0] , iens ) - self.assertEqual( t4[0] , iens ) - - self.assertEqual( t0[1] , 0 ) - self.assertEqual( t4[1] , 1 ) - - - def test_assert_export(self): - with ErtTestContext("create_runpath1" , self.createTestPath("local/snake_oil_no_data/snake_oil.ert")) as tc: - ert = tc.getErt( ) - runpath_list = ert.getRunpathList( ) - self.assertFalse( path.isfile( runpath_list.getExportFile( ) )) - - ens_size = ert.getEnsembleSize( ) - runner = ert.getEnkfSimulationRunner( ) - mask = BoolVector( initial_size = ens_size , default_value = True ) - runner.createRunPath( mask , 0 ) - - self.assertTrue( path.isfile( runpath_list.getExportFile( ) )) - self.assertEqual( "test_runpath_list.txt" , path.basename( runpath_list.getExportFile( ) )) - - - - def test_assert_symlink_deleted(self): - with ErtTestContext("create_runpath2" , self.createTestPath("local/snake_oil_field/snake_oil.ert")) as tc: - ert = tc.getErt( ) - runpath_list = ert.getRunpathList( ) - - ens_size = ert.getEnsembleSize( ) - runner = ert.getEnkfSimulationRunner( ) - mask = BoolVector( initial_size = ens_size , default_value = True ) - - # create directory structure - runner.createRunPath( mask , 0 ) - - # replace field file with symlink - linkpath = '%s/permx.grdcel' % str(runpath_list[0].runpath) - targetpath = '%s/permx.grdcel.target' % str(runpath_list[0].runpath) - open(targetpath, 'a').close() - remove(linkpath) - symlink(targetpath, linkpath) - - # recreate directory structure - runner.createRunPath( mask , 0 ) - - # ensure field symlink is replaced by file - self.assertFalse( path.islink(linkpath) ) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_state_map.py b/ThirdParty/Ert/python/tests/ert/enkf/test_state_map.py deleted file mode 100644 index e6d5c1cc5c..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_state_map.py +++ /dev/null @@ -1,105 +0,0 @@ -from ert.enkf.enums.realization_state_enum import RealizationStateEnum -from ert.enkf.state_map import StateMap -from ert.test import TestAreaContext -from ert.test import ExtendedTestCase - - -class StateMapTest(ExtendedTestCase): - - def test_state_map(self): - state_map = StateMap() - - self.assertEqual(len(state_map), 0) - - with self.assertRaises(TypeError): - r = state_map["r"] - - with self.assertRaises(IOError): - s2 = StateMap("DoesNotExist") - - with self.assertRaises(IOError): - state_map.load("/file/does/not/exist") - - with self.assertRaises(IndexError): - v = state_map[0] - - with self.assertRaises(TypeError): - state_map["r"] = RealizationStateEnum.STATE_INITIALIZED - - with self.assertRaises(TypeError): - state_map[0] = "INITIALIZED" - - with self.assertRaises(IndexError): - state_map[-1] = RealizationStateEnum.STATE_INITIALIZED - - - state_map[0] = RealizationStateEnum.STATE_INITIALIZED - - self.assertEqual(len(state_map), 1) - - state_map[1] = RealizationStateEnum.STATE_INITIALIZED - state_map[1] = RealizationStateEnum.STATE_HAS_DATA - - self.assertEqual(len(state_map), 2) - - index = 0 - for state in state_map: - self.assertEqual(state, state_map[index]) - index += 1 - - states = [state for state in state_map] - - self.assertEqual(states, [RealizationStateEnum.STATE_INITIALIZED, RealizationStateEnum.STATE_HAS_DATA]) - - - state_map[5] = RealizationStateEnum.STATE_INITIALIZED - self.assertEqual(len(state_map), 6) - - self.assertEqual(state_map[2], RealizationStateEnum.STATE_UNDEFINED) - self.assertEqual(state_map[3], RealizationStateEnum.STATE_UNDEFINED) - self.assertEqual(state_map[4], RealizationStateEnum.STATE_UNDEFINED) - self.assertEqual(state_map[5], RealizationStateEnum.STATE_INITIALIZED) - - self.assertFalse(state_map.isReadOnly()) - - with TestAreaContext("python/state-map/fwrite") as work_area: - state_map.save("MAP") - s2 = StateMap("MAP") - self.assertTrue( state_map == s2 ) - - - - def test_state_map_transitions(self): - self.assertTrue(StateMap.isLegalTransition(RealizationStateEnum.STATE_UNDEFINED, RealizationStateEnum.STATE_INITIALIZED)) - self.assertTrue(StateMap.isLegalTransition(RealizationStateEnum.STATE_INITIALIZED, RealizationStateEnum.STATE_HAS_DATA)) - self.assertTrue(StateMap.isLegalTransition(RealizationStateEnum.STATE_INITIALIZED, RealizationStateEnum.STATE_LOAD_FAILURE)) - self.assertTrue(StateMap.isLegalTransition(RealizationStateEnum.STATE_INITIALIZED, RealizationStateEnum.STATE_PARENT_FAILURE)) - self.assertTrue(StateMap.isLegalTransition(RealizationStateEnum.STATE_HAS_DATA, RealizationStateEnum.STATE_PARENT_FAILURE)) - - self.assertFalse(StateMap.isLegalTransition(RealizationStateEnum.STATE_UNDEFINED, RealizationStateEnum.STATE_LOAD_FAILURE)) - self.assertFalse(StateMap.isLegalTransition(RealizationStateEnum.STATE_UNDEFINED, RealizationStateEnum.STATE_HAS_DATA)) - - with self.assertRaises(TypeError): - StateMap.isLegalTransition("error", RealizationStateEnum.STATE_UNDEFINED) - - with self.assertRaises(TypeError): - StateMap.isLegalTransition(RealizationStateEnum.STATE_UNDEFINED, "error") - - with self.assertRaises(TypeError): - StateMap.isLegalTransition("error", "exception") - - - def test_active_list(self): - state_map = StateMap() - state_map[0] = RealizationStateEnum.STATE_INITIALIZED - state_map[2] = RealizationStateEnum.STATE_INITIALIZED - state_map[2] = RealizationStateEnum.STATE_HAS_DATA - - initialized = state_map.realizationList( RealizationStateEnum.STATE_INITIALIZED ) - self.assertEqual( len(initialized) , 1 ) - self.assertEqual( initialized[0] , 0 ) - - has_data = state_map.realizationList( RealizationStateEnum.STATE_HAS_DATA ) - self.assertEqual( len(has_data) , 1 ) - self.assertEqual( has_data[0] , 2) - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_summary_key_matcher.py b/ThirdParty/Ert/python/tests/ert/enkf/test_summary_key_matcher.py deleted file mode 100644 index fcd783fdc3..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_summary_key_matcher.py +++ /dev/null @@ -1,28 +0,0 @@ -from ert.enkf import SummaryKeyMatcher -from ert.test import ExtendedTestCase - -class SummaryKeyMatcherTest(ExtendedTestCase): - - def test_creation(self): - matcher = SummaryKeyMatcher() - - self.assertTrue(len(matcher) == 0) - - matcher.addSummaryKey("F*") - self.assertTrue(len(matcher) == 1) - - matcher.addSummaryKey("F*") - self.assertTrue(len(matcher) == 1) - - matcher.addSummaryKey("FOPT") - self.assertTrue(len(matcher) == 2) - - self.assertItemsEqual(["F*", "FOPT"], matcher.keys()) - - self.assertTrue("FGIR" in matcher) - self.assertTrue("FOPT" in matcher) - self.assertFalse("TCPU" in matcher) - - self.assertTrue(matcher.isRequired("FOPT")) - self.assertFalse(matcher.isRequired("FGIR")) - self.assertFalse(matcher.isRequired("TCPU")) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_summary_key_set.py b/ThirdParty/Ert/python/tests/ert/enkf/test_summary_key_set.py deleted file mode 100644 index 4c3a44e9ee..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_summary_key_set.py +++ /dev/null @@ -1,99 +0,0 @@ -import os -from ert.enkf import SummaryKeySet -from ert.enkf.enkf_fs import EnkfFs -from ert.enkf.enkf_main import EnKFMain -from ert.test import ExtendedTestCase -from ert.test.ert_test_context import ErtTestContext -from ert.test.test_area import TestAreaContext - - -class SummaryKeySetTest(ExtendedTestCase): - - def test_creation(self): - - keys = SummaryKeySet() - - self.assertEqual(len(keys), 0) - - self.assertTrue(keys.addSummaryKey("FOPT")) - - self.assertEqual(len(keys), 1) - - self.assertTrue("FOPT" in keys) - - self.assertItemsEqual(["FOPT"], keys.keys()) - - self.assertTrue(keys.addSummaryKey("WWCT")) - - self.assertEqual(len(keys), 2) - - self.assertTrue("WWCT" in keys) - - self.assertItemsEqual(["WWCT", "FOPT"], keys.keys()) - - - - def test_read_only_creation(self): - with TestAreaContext("enkf/summary_key_set/read_only_write_test"): - keys = SummaryKeySet() - - keys.addSummaryKey("FOPT") - keys.addSummaryKey("WWCT") - - filename = "test.txt" - keys.writeToFile(filename) - - keys_from_file = SummaryKeySet(filename, read_only=True) - self.assertItemsEqual(keys.keys(), keys_from_file.keys()) - - self.assertTrue(keys_from_file.isReadOnly()) - self.assertFalse(keys_from_file.addSummaryKey("WOPR")) - - - def test_write_to_and_read_from_file(self): - with TestAreaContext("enkf/summary_key_set/write_test"): - keys = SummaryKeySet() - - keys.addSummaryKey("FOPT") - keys.addSummaryKey("WWCT") - - filename = "test.txt" - - self.assertFalse(os.path.exists(filename)) - - keys.writeToFile(filename) - - self.assertTrue(os.path.exists(filename)) - - keys_from_file = SummaryKeySet(filename) - self.assertItemsEqual(keys.keys(), keys_from_file.keys()) - - - def test_with_enkf_fs(self): - config_file = self.createTestPath("Statoil/config/with_data/config") - - with TestAreaContext("enkf/summary_key_set/enkf_fs", store_area=True) as context: - context.copy_parent_content(config_file) - - fs = EnkfFs("storage/default") - summary_key_set = fs.getSummaryKeySet() - summary_key_set.addSummaryKey("FOPT") - summary_key_set.addSummaryKey("WWCT") - summary_key_set.addSummaryKey("WOPR") - fs.umount() - - ert = EnKFMain("config") - fs = ert.getEnkfFsManager().getCurrentFileSystem() - summary_key_set = fs.getSummaryKeySet() - self.assertTrue("FOPT" in summary_key_set) - self.assertTrue("WWCT" in summary_key_set) - self.assertTrue("WOPR" in summary_key_set) - - ensemble_config = ert.ensembleConfig() - - self.assertTrue("FOPT" in ensemble_config) - self.assertTrue("WWCT" in ensemble_config) - self.assertTrue("WOPR" in ensemble_config) - self.assertFalse("TCPU" in ensemble_config) - - diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_summary_obs.py b/ThirdParty/Ert/python/tests/ert/enkf/test_summary_obs.py deleted file mode 100644 index 981ce73f91..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_summary_obs.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'test_summary_obs.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import os - -from ert.enkf import SummaryObservation -from ert.enkf import ActiveList -from ert.test import ExtendedTestCase - - - -class SummaryObsTest(ExtendedTestCase): - - def test_create(self): - sum_obs = SummaryObservation("WWCT:OP_X" , "WWCT:OP_X" , 0.25 , 0.12) - - self.assertEqual( sum_obs.getValue() , 0.25 ) - self.assertEqual( sum_obs.getStandardDeviation() , 0.12 ) - self.assertEqual( sum_obs.getStdScaling() , 1.0 ) - - - def test_std_scaling(self): - sum_obs = SummaryObservation("WWCT:OP_X" , "WWCT:OP_X" , 0.25 , 0.12) - - active_list = ActiveList() - sum_obs.updateStdScaling(0.50 , active_list) - sum_obs.updateStdScaling(0.125 , active_list) - self.assertEqual( sum_obs.getStdScaling() , 0.125 ) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_time_map.py b/ThirdParty/Ert/python/tests/ert/enkf/test_time_map.py deleted file mode 100644 index 12706efc99..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_time_map.py +++ /dev/null @@ -1,184 +0,0 @@ -import datetime - -from ert.enkf.enums.realization_state_enum import RealizationStateEnum -from ert.enkf import TimeMap -from ert.test import TestAreaContext -from ert.test import ExtendedTestCase - - -class TimeMapTest(ExtendedTestCase): - - def test_time_map(self): - with self.assertRaises(IOError): - TimeMap("Does/not/exist") - - - tm = TimeMap() - with self.assertRaises(IndexError): - t = tm[10] - - pfx = 'TimeMap(' - rep = repr(tm) - print('repr(time_map) = "%s"' % repr(tm)) - self.assertEqual(pfx, rep[:len(pfx)]) - - self.assertTrue( tm.update(0 , datetime.date(2000 , 1, 1))) - self.assertEqual( tm[0] , datetime.date(2000 , 1, 1)) - - self.assertTrue( tm.isStrict() ) - with self.assertRaises(Exception): - tm.update(tm.update(0 , datetime.date(2000 , 1, 2))) - - tm.setStrict( False ) - self.assertFalse(tm.update(0 , datetime.date(2000 , 1, 2))) - - tm.setStrict( True ) - self.assertTrue( tm.update( 1 , datetime.date(2000 , 1, 2))) - d = tm.dump() - self.assertEqual( d , [(0 , datetime.date(2000,1,1) , 0), - (1 , datetime.date(2000,1,2) , 1)]) - - - def test_fscanf(self): - tm = TimeMap() - - with self.assertRaises(IOError): - tm.fload( "Does/not/exist" ) - - with TestAreaContext("timemap/fload1") as work_area: - with open("map.txt","w") as fileH: - fileH.write("10/10/2000\n") - fileH.write("12/10/2000\n") - fileH.write("14/10/2000\n") - fileH.write("16/10/2000\n") - - tm.fload("map.txt") - self.assertEqual( 4 , len(tm) ) - self.assertEqual( datetime.date(2000,10,10) , tm[0]) - self.assertEqual( datetime.date(2000,10,16) , tm[3]) - - with TestAreaContext("timemap/fload2") as work_area: - with open("map.txt","w") as fileH: - fileH.write("10/10/200X\n") - - with self.assertRaises(Exception): - tm.fload("map.txt") - - self.assertEqual( 4 , len(tm) ) - self.assertEqual( datetime.date(2000,10,10) , tm[0]) - self.assertEqual( datetime.date(2000,10,16) , tm[3]) - - - with TestAreaContext("timemap/fload2") as work_area: - with open("map.txt","w") as fileH: - fileH.write("12/10/2000\n") - fileH.write("10/10/2000\n") - - with self.assertRaises(Exception): - tm.fload("map.txt") - - self.assertEqual( 4 , len(tm) ) - self.assertEqual( datetime.date(2000,10,10) , tm[0]) - self.assertEqual( datetime.date(2000,10,16) , tm[3]) - - - def test_setitem(self): - tm = TimeMap() - tm[0] = datetime.date(2000,1,1) - tm[1] = datetime.date(2000,1,2) - self.assertEqual(2 , len(tm)) - - self.assertEqual( tm[0] , datetime.date(2000,1,1) ) - self.assertEqual( tm[1] , datetime.date(2000,1,2) ) - - - def test_in(self): - tm = TimeMap() - tm[0] = datetime.date(2000,1,1) - tm[1] = datetime.date(2000,1,2) - tm[2] = datetime.date(2000,1,3) - - self.assertTrue( datetime.date(2000,1,1) in tm ) - self.assertTrue( datetime.date(2000,1,2) in tm ) - self.assertTrue( datetime.date(2000,1,3) in tm ) - - self.assertFalse( datetime.date(2001,1,3) in tm ) - self.assertFalse( datetime.date(1999,1,3) in tm ) - - - def test_lookupDate(self): - tm = TimeMap() - tm[0] = datetime.date(2000,1,1) - tm[1] = datetime.date(2000,1,2) - tm[2] = datetime.date(2000,1,3) - - self.assertEqual( 0 , tm.lookupTime( datetime.date(2000,1,1))) - self.assertEqual( 0 , tm.lookupTime( datetime.datetime(2000,1,1,0,0,0))) - - self.assertEqual( 2 , tm.lookupTime( datetime.date(2000,1,3))) - self.assertEqual( 2 , tm.lookupTime( datetime.datetime(2000,1,3,0,0,0))) - - with self.assertRaises(ValueError): - tm.lookupTime( datetime.date(1999,10,10)) - - - - def test_lookupDays(self): - tm = TimeMap() - - with self.assertRaises(ValueError): - tm.lookupDays( 0 ) - - tm[0] = datetime.date(2000,1,1) - tm[1] = datetime.date(2000,1,2) - tm[2] = datetime.date(2000,1,3) - - self.assertEqual( 0 , tm.lookupDays( 0 )) - self.assertEqual( 1 , tm.lookupDays( 1 )) - self.assertEqual( 2 , tm.lookupDays( 2 )) - - with self.assertRaises(ValueError): - tm.lookupDays( -1 ) - - with self.assertRaises(ValueError): - tm.lookupDays( 0.50 ) - - with self.assertRaises(ValueError): - tm.lookupDays( 3 ) - - - - def test_nearest_date_lookup(self): - tm = TimeMap() - with self.assertRaises(ValueError): - tm.lookupTime(datetime.date( 1999 , 1 , 1)) - - with self.assertRaises(ValueError): - tm.lookupTime(datetime.date( 1999 , 1 , 1) , tolerance_seconds_before = 10 , tolerance_seconds_after = 10) - - tm[0] = datetime.date(2000,1,1) - tm[1] = datetime.date(2000,2,1) - tm[2] = datetime.date(2000,3,1) - - # Outside of total range will raise an exception, irrespective of - # the tolerances used. - with self.assertRaises(ValueError): - tm.lookupTime(datetime.date( 1999 , 1 , 1) , tolerance_seconds_before = -1 , tolerance_seconds_after = -1) - - with self.assertRaises(ValueError): - tm.lookupTime(datetime.date( 2001 , 1 , 1) , tolerance_seconds_before = -1 , tolerance_seconds_after = -1) - - self.assertEqual(0 , tm.lookupTime( datetime.datetime(2000 , 1 , 1 , 0 , 0 , 10) , tolerance_seconds_after = 15)) - self.assertEqual(1 , tm.lookupTime( datetime.datetime(2000 , 1 , 1 , 0 , 0 , 10) , tolerance_seconds_before = 3600*24*40)) - - self.assertEqual(0 , tm.lookupTime( datetime.date( 2000 , 1 , 10) , tolerance_seconds_before = -1 , tolerance_seconds_after = -1)) - self.assertEqual(1 , tm.lookupTime( datetime.date( 2000 , 1 , 20) , tolerance_seconds_before = -1 , tolerance_seconds_after = -1)) - - with self.assertRaises(ValueError): - tm.lookupTime(datetime.date( 2001 , 10 , 1) , tolerance_seconds_before = 10 , tolerance_seconds_after = 10) - - - def test_empty(self): - tm = TimeMap() - last_step = tm.getLastStep( ) - self.assertEqual( last_step , -1 ) diff --git a/ThirdParty/Ert/python/tests/ert/enkf/test_update.py b/ThirdParty/Ert/python/tests/ert/enkf/test_update.py deleted file mode 100644 index 757084be40..0000000000 --- a/ThirdParty/Ert/python/tests/ert/enkf/test_update.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'test_update.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import random - -import ert -from ert.test import ExtendedTestCase, ErtTestContext -from ert.util.enums import RngAlgTypeEnum, RngInitModeEnum -from ert.util import Matrix, BoolVector , RandomNumberGenerator -from ert.analysis import AnalysisModule, AnalysisModuleLoadStatusEnum, AnalysisModuleOptionsEnum -from ert.enkf import MeasData , ObsData , LocalObsdata - - - - -def update(rng , mask , module , ert , meas_data , obs_data , state_size): - S = meas_data.createS() - R = obs_data.createR() - dObs = obs_data.createDObs() - E = obs_data.createE( rng , meas_data.getActiveEnsSize() ) - D = obs_data.createD(E , S) - obs_data.scale(S , E = E , D = D , R = R , D_obs = dObs) - - A = Matrix(state_size , meas_data.getActiveEnsSize()) - A.randomInit( rng ) - - module.initUpdate( mask , S , R , dObs , E , D ) - module.updateA( A , S , R , dObs , E , D ) - - - - -class UpdateTest(ExtendedTestCase): - def setUp(self): - self.libname = ert.ert_lib_path + "/rml_enkf.so" - self.config_file = self.createTestPath("Statoil/config/obs_testing2/config") - self.rng = RandomNumberGenerator(RngAlgTypeEnum.MZRAN, RngInitModeEnum.INIT_DEFAULT) - - - def createAnalysisModule(self): - return AnalysisModule(self.rng, lib_name = self.libname) - - - def test_it(self): - state_size = 10 - with ErtTestContext("update" , self.config_file) as tc: - analysis = self.createAnalysisModule() - ert = tc.getErt() - obs = ert.getObservations() - local_obsdata = obs.getAllActiveLocalObsdata( ) - - fs = ert.getEnkfFsManager().getCurrentFileSystem() - - - mask = BoolVector( initial_size = ert.getEnsembleSize() , default_value = True) - meas_data = MeasData(mask) - obs_data = ObsData() - obs.getObservationAndMeasureData( fs , local_obsdata , mask.createActiveList() , meas_data , obs_data ) - update( self.rng , mask , analysis , ert , meas_data , obs_data , state_size) - - - mask[0] = False - mask[4] = False - meas_data = MeasData(mask) - obs_data = ObsData() - obs.getObservationAndMeasureData( fs , local_obsdata , mask.createActiveList() , meas_data , obs_data ) - update( self.rng , mask , analysis , ert , meas_data , obs_data , state_size) - - diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/job_queue/CMakeLists.txt deleted file mode 100644 index d7dcab80dc..0000000000 --- a/ThirdParty/Ert/python/tests/ert/job_queue/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_ert_plugin.py - test_ert_script.py - test_ext_job.py - test_function_ert_script.py - test_job_queue.py - test_workflow.py - test_workflow_job.py - test_workflow_joblist.py - test_workflow_runner.py - workflow_common.py -) - -add_python_package("python.tests.ert.job_queue" ${PYTHON_INSTALL_PREFIX}/tests/ert/job_queue "${TEST_SOURCES}" False) - -addPythonTest(ert.job_queue.job_status_type_enum tests.ert.job_queue.test_job_queue.JobQueueTest) -addPythonTest(ert.job_queue.workflow_job tests.ert.job_queue.test_workflow_job.WorkflowJobTest) -addPythonTest(ert.job_queue.workflow tests.ert.job_queue.test_workflow.WorkflowTest) -addPythonTest(ert.job_queue.workflow_joblist tests.ert.job_queue.test_workflow_joblist.WorkflowJoblistTest) -addPythonTest(ert.job_queue.ert_plugin tests.ert.job_queue.test_ert_plugin.ErtPluginTest) -addPythonTest(ert.job_queue.ert_script tests.ert.job_queue.test_ert_script.ErtScriptTest) -addPythonTest(ert.job_queue.function_ert_script tests.ert.job_queue.test_function_ert_script.FunctionErtScriptTest) -addPythonTest(ert.job_queue.workflow_runner tests.ert.job_queue.test_workflow_runner.WorkflowRunnerTest) -addPythonTest(ert.job_queue.ext_job tests.ert.job_queue.test_ext_job.ExtJobTest) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/__init__.py b/ThirdParty/Ert/python/tests/ert/job_queue/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/test_ert_plugin.py b/ThirdParty/Ert/python/tests/ert/job_queue/test_ert_plugin.py deleted file mode 100644 index 96fbef4fd7..0000000000 --- a/ThirdParty/Ert/python/tests/ert/job_queue/test_ert_plugin.py +++ /dev/null @@ -1,86 +0,0 @@ -from ert.enkf import ErtPlugin, CancelPluginException -from ert.test.extended_testcase import ExtendedTestCase - - -class SimplePlugin(ErtPlugin): - def run(self, parameter1, parameter2): - assert parameter1 == "one" - assert parameter2 == 2 - - def getArguments(self, parent=None): - return ["one", 2] - - -class FullPlugin(ErtPlugin): - def getName(self): - return "FullPlugin" - - def getDescription(self): - return "Fully described!" - - def run(self, arg1, arg2, arg3=None): - assert arg1 == 5 - assert arg2 == "No" - assert arg3 is None - - def getArguments(self, parent=None): - return [5, "No"] - - -class CanceledPlugin(ErtPlugin): - def run(self, arg1): - pass - - def getArguments(self, parent=None): - raise CancelPluginException("Cancel test!") - -# class GUIPlugin(ErtPlugin): -# def getArguments(self, parent=None): -# value1 = QInputDialog.getInt(parent, "Enter a number!", "Enter a nice number (nothing else than 5):", value=0, min=0, max=10) -# value2 = QInputDialog.getInt(parent, "Enter a number!", "Enter a nice number (nothing else than 6):", value=0, min=0, max=10) -# print(value1, value2) -# return [value1[0], value2[0]] -# -# def run(self, arg1, arg2, arg3=None): -# assert arg1 == 5 -# assert arg2 == 6 - - -class ErtPluginTest(ExtendedTestCase): - - def test_simple_ert_plugin(self): - - simple_plugin = SimplePlugin("ert") - - arguments = simple_plugin.getArguments() - - self.assertTrue("SimplePlugin" in simple_plugin.getName()) - self.assertEqual("No description provided!", simple_plugin.getDescription()) - - simple_plugin.initializeAndRun([str, int], arguments) - - - def test_full_ert_plugin(self): - plugin = FullPlugin("ert") - - self.assertEqual(plugin.getName(), "FullPlugin") - self.assertEqual(plugin.getDescription(), "Fully described!") - - arguments = plugin.getArguments() - - plugin.initializeAndRun([int, str, float], arguments) - - - def test_cancel_plugin(self): - plugin = CanceledPlugin("ert") - - with self.assertRaises(CancelPluginException): - plugin.getArguments() - - # def test_gui_ert_plugin(self): - # app = QApplication([]) - # plugin = GUIPlugin("ert") - # - # arguments = plugin.getArguments() - # plugin.initializeAndRun([int, int], arguments) - diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/test_ert_script.py b/ThirdParty/Ert/python/tests/ert/job_queue/test_ert_script.py deleted file mode 100644 index 5b99e414df..0000000000 --- a/ThirdParty/Ert/python/tests/ert/job_queue/test_ert_script.py +++ /dev/null @@ -1,82 +0,0 @@ -from ert.job_queue import ErtScript -from ert.test import TestAreaContext, ExtendedTestCase -from .workflow_common import WorkflowCommon - - -class ReturnErtScript(ErtScript): - def run(self): - return self.ert() - -class AddScript(ErtScript): - def run(self, arg1, arg2): - return arg1 + arg2 - -class FailScript(ErtScript): - def rum(self): - pass - -class NoneScript(ErtScript): - def run(self, arg): - assert arg is None - - -class ErtScriptTest(ExtendedTestCase): - - @staticmethod - def createScripts(): - WorkflowCommon.createErtScriptsJob() - - with open("syntax_error_script.py", "w") as f: - f.write("from ert.enkf not_legal_syntax ErtScript\n") - - with open("import_error_script.py", "w") as f: - f.write("from ert.enkf import DoesNotExist\n") - - with open("empty_script.py", "w") as f: - f.write("from ert.enkf import ErtScript\n") - - - def test_ert_script_return_ert(self): - script = ReturnErtScript("ert") - result = script.initializeAndRun([], []) - self.assertEqual(result, "ert") - - - def test_ert_script_add(self): - script = AddScript("ert") - - result = script.initializeAndRun([int, int], ["5", "4"]) - - self.assertEqual(result, 9) - - with self.assertRaises(ValueError): - result = script.initializeAndRun([int, int], ["5", "4.6"]) - - - def test_ert_script_failed_implementation(self): - with self.assertRaises(UserWarning): - script = FailScript("ert") - - - def test_ert_script_from_file(self): - with TestAreaContext("python/job_queue/ert_script") as work_area: - ErtScriptTest.createScripts() - - script_object = ErtScript.loadScriptFromFile("subtract_script.py") - - script = script_object("ert") - result = script.initializeAndRun([int, int], ["1", "2"]) - self.assertEqual(result, -1) - - - # with self.assertRaises(ErtScriptError): - self.assertIsNone(ErtScript.loadScriptFromFile("syntax_error_script.py")) - self.assertIsNone(ErtScript.loadScriptFromFile("import_error_script.py")) - self.assertIsNone(ErtScript.loadScriptFromFile("empty_script.py")) - - - def test_none_ert_script(self): - #Check if None is not converted to string "None" - script = NoneScript("ert") - - script.initializeAndRun([str], [None]) diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/test_ext_job.py b/ThirdParty/Ert/python/tests/ert/job_queue/test_ext_job.py deleted file mode 100644 index d6932d3316..0000000000 --- a/ThirdParty/Ert/python/tests/ert/job_queue/test_ext_job.py +++ /dev/null @@ -1,77 +0,0 @@ -import os.path - -from ert.test import TestAreaContext, ExtendedTestCase -from ert.job_queue.ext_job import ExtJob - - -def create_valid_config( config_file ): - with open(config_file , "w") as f: - f.write("EXECUTABLE script.sh\n") - - with open("script.sh" , "w") as f: - f.write("This is a script") - - -def create_config_missing_executable( config_file ): - with open(config_file , "w") as f: - f.write("EXECUTABLE missing_script.sh\n") - - -def create_config_missing_EXECUTABLE( config_file ): - with open(config_file , "w") as f: - f.write("EXECU missing_script.sh\n") - - -def create_config_executable_directory( config_file ): - with open(config_file , "w") as f: - f.write("EXECUTABLE /tmp\n") - - -def create_config_foreign_file( config_file ): - with open(config_file , "w") as f: - f.write("EXECUTABLE /etc/passwd\n") - - - - -class ExtJobTest(ExtendedTestCase): - def test_load_forward_model(self): - with self.assertRaises(IOError): - job = ExtJob("CONFIG_FILE" , True) - - with TestAreaContext("python/job_queue/forward_model1"): - create_valid_config("CONFIG") - job = ExtJob("CONFIG" , True) - self.assertEqual( job.name() , "CONFIG") - - self.assertEqual( job.get_executable() , os.path.join( os.getcwd() , "script.sh")) - self.assertTrue( os.access( job.get_executable() , os.X_OK )) - - - job = ExtJob("CONFIG" , True , name = "Job") - self.assertEqual( job.name() , "Job") - - - with TestAreaContext("python/job_queue/forward_model2"): - create_config_missing_executable( "CONFIG" ) - with self.assertRaises(ValueError): - job = ExtJob("CONFIG" , True) - - - with TestAreaContext("python/job_queue/forward_model3"): - create_config_missing_EXECUTABLE( "CONFIG" ) - with self.assertRaises(ValueError): - job = ExtJob("CONFIG" , True) - - - with TestAreaContext("python/job_queue/forward_model4"): - create_config_executable_directory( "CONFIG" ) - with self.assertRaises(ValueError): - job = ExtJob("CONFIG" , True) - - - with TestAreaContext("python/job_queue/forward_model5"): - create_config_foreign_file( "CONFIG" ) - with self.assertRaises(ValueError): - job = ExtJob("CONFIG" , True) - diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/test_function_ert_script.py b/ThirdParty/Ert/python/tests/ert/job_queue/test_function_ert_script.py deleted file mode 100644 index 4098c99487..0000000000 --- a/ThirdParty/Ert/python/tests/ert/job_queue/test_function_ert_script.py +++ /dev/null @@ -1,27 +0,0 @@ -from cwrap import clib -from ert.test import ExtendedTestCase, TestAreaContext -from ert.job_queue import WorkflowJob -from .workflow_common import WorkflowCommon - -class FunctionErtScriptTest(ExtendedTestCase): - - def test_compare(self): - with TestAreaContext("python/job_queue/workflow_job") as work_area: - WorkflowCommon.createInternalFunctionJob() - - parser = WorkflowJob.configParser( ) - with self.assertRaises(IOError): - workflow_job = WorkflowJob.fromFile("no/such/file") - - workflow_job = WorkflowJob.fromFile("compare_job", name = "COMPARE", parser = parser) - self.assertEqual( workflow_job.name() , "COMPARE") - - result = workflow_job.run(None , ["String", "string"]) - self.assertNotEqual(result, 0) - - result = workflow_job.run(None, ["String", "String"]) - # result is returned as c_void_p -> automatic conversion to None if value is 0 - self.assertIsNone(result) - - workflow_job = WorkflowJob.fromFile("compare_job") - self.assertEqual( workflow_job.name() , "compare_job") diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/test_job_queue.py b/ThirdParty/Ert/python/tests/ert/job_queue/test_job_queue.py deleted file mode 100644 index 6cacb1bf61..0000000000 --- a/ThirdParty/Ert/python/tests/ert/job_queue/test_job_queue.py +++ /dev/null @@ -1,11 +0,0 @@ -from ert.job_queue import JobStatusType -from ert.test import ExtendedTestCase - - -class JobQueueTest(ExtendedTestCase): - - def testStatusEnum(self): - source_path = "libjob_queue/include/ert/job_queue/queue_driver.h" - self.assertEnumIsFullyDefined(JobStatusType, "job_status_type", source_path) - - diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow.py b/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow.py deleted file mode 100644 index a21228fc30..0000000000 --- a/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow.py +++ /dev/null @@ -1,56 +0,0 @@ -from ert.job_queue import Workflow, WorkflowJoblist -from ert.test import ExtendedTestCase, TestAreaContext -from ert.util import SubstitutionList -from .workflow_common import WorkflowCommon - - -class WorkflowTest(ExtendedTestCase): - - def test_workflow(self): - with TestAreaContext("python/job_queue/workflow") as work_area: - WorkflowCommon.createExternalDumpJob() - - joblist = WorkflowJoblist() - self.assertTrue(joblist.addJobFromFile("DUMP", "dump_job")) - - with self.assertRaises(UserWarning): - joblist.addJobFromFile("KNOCK", "knock_job") - - self.assertTrue("DUMP" in joblist) - - - workflow = Workflow("dump_workflow", joblist) - - self.assertEqual(len(workflow), 2) - - job, args = workflow[0] - self.assertEqual(job, joblist["DUMP"]) - self.assertEqual(args[0], "dump1") - self.assertEqual(args[1], "dump_text_1") - - job, args = workflow[1] - self.assertEqual(job, joblist["DUMP"]) - - - def test_workflow_run(self): - with TestAreaContext("python/job_queue/workflow") as work_area: - WorkflowCommon.createExternalDumpJob() - - joblist = WorkflowJoblist() - self.assertTrue(joblist.addJobFromFile("DUMP", "dump_job")) - self.assertTrue("DUMP" in joblist) - - workflow = Workflow("dump_workflow", joblist) - - self.assertTrue(len(workflow), 2) - - context = SubstitutionList() - context.addItem("", "text") - - self.assertTrue(workflow.run(None, verbose=True, context=context)) - - with open("dump1", "r") as f: - self.assertEqual(f.read(), "dump_text_1") - - with open("dump2", "r") as f: - self.assertEqual(f.read(), "dump_text_2") diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_job.py b/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_job.py deleted file mode 100644 index de2cbe6ea3..0000000000 --- a/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_job.py +++ /dev/null @@ -1,101 +0,0 @@ -import ert - -from ert.job_queue import WorkflowJob -from ert.test import TestAreaContext, ExtendedTestCase -from .workflow_common import WorkflowCommon - -from cwrap import Prototype - -class _TestWorkflowJobPrototype(Prototype): - lib = ert.load('libjob_queue') - - def __init__(self, prototype, bind=True): - super(_TestWorkflowJobPrototype, self).__init__(_TestWorkflowJobPrototype.lib, prototype, bind=bind) - -class WorkflowJobTest(ExtendedTestCase): - _alloc_config = _TestWorkflowJobPrototype("void* workflow_job_alloc_config()", bind = False) - _alloc_from_file = _TestWorkflowJobPrototype("workflow_job_obj workflow_job_config_alloc(char*, void*, char*)", bind = False) - - - def test_workflow_job_creation(self): - workflow_job = WorkflowJob("Test") - - self.assertTrue(workflow_job.isInternal()) - self.assertEqual(workflow_job.name(), "Test") - - - def test_read_internal_function(self): - with TestAreaContext("python/job_queue/workflow_job") as work_area: - WorkflowCommon.createInternalFunctionJob() - WorkflowCommon.createErtScriptsJob() - - config = self._alloc_config() - workflow_job = self._alloc_from_file("SELECT_CASE", config, "select_case_job") - - self.assertEqual(workflow_job.name(), "SELECT_CASE") - self.assertTrue(workflow_job.isInternal()) - self.assertEqual(workflow_job.functionName(), "enkf_main_select_case_JOB") - - self.assertFalse(workflow_job.isInternalScript()) - self.assertIsNone(workflow_job.getInternalScriptPath()) - - - workflow_job = self._alloc_from_file("SUBTRACT", config, "subtract_script_job") - self.assertEqual(workflow_job.name(), "SUBTRACT") - self.assertTrue(workflow_job.isInternal()) - self.assertIsNone(workflow_job.functionName()) - - self.assertTrue(workflow_job.isInternalScript()) - self.assertTrue(workflow_job.getInternalScriptPath().endswith("subtract_script.py")) - - - - def test_arguments(self): - with TestAreaContext("python/job_queue/workflow_job") as work_area: - WorkflowCommon.createInternalFunctionJob() - - config = self._alloc_config() - job = self._alloc_from_file("PRINTF", config, "printf_job") - - self.assertEqual(job.minimumArgumentCount(), 4) - self.assertEqual(job.maximumArgumentCount(), 5) - self.assertEqual(job.argumentTypes(), [str, int, float, bool, str]) - - self.assertTrue(job.run(None, ["x %d %f %d", 1, 2.5, True])) - self.assertTrue(job.run(None, ["x %d %f %d %s", 1, 2.5, True, "y"])) - - with self.assertRaises(UserWarning): # Too few arguments - job.run(None, ["x %d %f", 1, 2.5]) - - with self.assertRaises(UserWarning): # Too many arguments - job.run(None, ["x %d %f %d %s", 1, 2.5, True, "y", "nada"]) - - - def test_run_external_job(self): - - with TestAreaContext("python/job_queue/workflow_job") as work_area: - WorkflowCommon.createExternalDumpJob() - - config = self._alloc_config() - job = self._alloc_from_file("DUMP", config, "dump_job") - - self.assertFalse(job.isInternal()) - argTypes = job.argumentTypes() - self.assertEqual( argTypes , [str , str] ) - self.assertIsNone(job.run(None, ["test", "text"])) - - with open("test", "r") as f: - self.assertEqual(f.read(), "text") - - - def test_run_internal_script(self): - with TestAreaContext("python/job_queue/workflow_job") as work_area: - WorkflowCommon.createErtScriptsJob() - - config = self._alloc_config() - job = self._alloc_from_file("SUBTRACT", config, "subtract_script_job") - - result = job.run(None, ["1", "2"]) - - self.assertEqual(result, -1) - diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_joblist.py b/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_joblist.py deleted file mode 100644 index a8a8a83db1..0000000000 --- a/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_joblist.py +++ /dev/null @@ -1,42 +0,0 @@ -from ert.job_queue import WorkflowJoblist, WorkflowJob -from ert.test import ExtendedTestCase, TestAreaContext -from .workflow_common import WorkflowCommon - - -class WorkflowJoblistTest(ExtendedTestCase): - - def test_workflow_joblist_creation(self): - joblist = WorkflowJoblist() - - job = WorkflowJob("JOB1") - - joblist.addJob(job) - - self.assertTrue(job in joblist) - self.assertTrue("JOB1" in joblist) - - job_ref = joblist["JOB1"] - - self.assertEqual(job.name(), job_ref.name()) - - - - def test_workflow_joblist_with_files(self): - with TestAreaContext("python/job_queue/workflow_joblist") as work_area: - WorkflowCommon.createErtScriptsJob() - WorkflowCommon.createExternalDumpJob() - WorkflowCommon.createInternalFunctionJob() - - joblist = WorkflowJoblist() - - joblist.addJobFromFile("DUMP_JOB", "dump_job") - joblist.addJobFromFile("SELECT_CASE_JOB", "select_case_job") - joblist.addJobFromFile("SUBTRACT_SCRIPT_JOB", "subtract_script_job") - - self.assertTrue("DUMP_JOB" in joblist) - self.assertTrue("SELECT_CASE_JOB" in joblist) - self.assertTrue("SUBTRACT_SCRIPT_JOB" in joblist) - - self.assertFalse((joblist["DUMP_JOB"]).isInternal()) - self.assertTrue((joblist["SELECT_CASE_JOB"]).isInternal()) - self.assertTrue((joblist["SUBTRACT_SCRIPT_JOB"]).isInternal()) diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_runner.py b/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_runner.py deleted file mode 100644 index e45a084ed1..0000000000 --- a/ThirdParty/Ert/python/tests/ert/job_queue/test_workflow_runner.py +++ /dev/null @@ -1,128 +0,0 @@ -import os -import time -from ert.job_queue import WorkflowJoblist, Workflow, WorkflowRunner -from ert.test import TestAreaContext, ExtendedTestCase -from ert.util.substitution_list import SubstitutionList -from .workflow_common import WorkflowCommon - - -class WorkflowRunnerTest(ExtendedTestCase): - - def test_workflow_thread_cancel_ert_script(self): - with TestAreaContext("python/job_queue/workflow_runner_ert_script") as work_area: - WorkflowCommon.createWaitJob() - - joblist = WorkflowJoblist() - self.assertTrue(joblist.addJobFromFile("WAIT", "wait_job")) - self.assertTrue("WAIT" in joblist) - - workflow = Workflow("wait_workflow", joblist) - - self.assertEqual(len(workflow), 3) - - - workflow_runner = WorkflowRunner(workflow) - - self.assertFalse(workflow_runner.isRunning()) - - workflow_runner.run() - - self.assertIsNone(workflow_runner.workflowResult()) - - time.sleep(1) # wait for workflow to start - self.assertTrue(workflow_runner.isRunning()) - self.assertFileExists("wait_started_0") - - time.sleep(1) # wait for first job to finish - - workflow_runner.cancel() - time.sleep(1) # wait for cancel to take effect - self.assertFileExists("wait_finished_0") - - - self.assertFileExists("wait_started_1") - self.assertFileExists("wait_cancelled_1") - self.assertFileDoesNotExist("wait_finished_1") - - self.assertTrue(workflow_runner.isCancelled()) - - workflow_runner.wait() # wait for runner to complete - - self.assertFileDoesNotExist("wait_started_2") - self.assertFileDoesNotExist("wait_cancelled_2") - self.assertFileDoesNotExist("wait_finished_2") - - - - - def test_workflow_thread_cancel_external(self): - with TestAreaContext("python/job_queue/workflow_runner_external") as work_area: - WorkflowCommon.createWaitJob() - - joblist = WorkflowJoblist() - self.assertTrue(joblist.addJobFromFile("WAIT", "external_wait_job")) - self.assertTrue("WAIT" in joblist) - - workflow = Workflow("wait_workflow", joblist) - - self.assertEqual(len(workflow), 3) - - - workflow_runner = WorkflowRunner(workflow, ert=None, context=SubstitutionList()) - - self.assertFalse(workflow_runner.isRunning()) - - workflow_runner.run() - - time.sleep(1) # wait for workflow to start - self.assertTrue(workflow_runner.isRunning()) - self.assertFileExists("wait_started_0") - - time.sleep(1) # wait for first job to finish - - workflow_runner.cancel() - time.sleep(1) # wait for cancel to take effect - self.assertFileExists("wait_finished_0") - - self.assertFileExists("wait_started_1") - self.assertFileDoesNotExist("wait_finished_1") - - self.assertTrue(workflow_runner.isCancelled()) - - workflow_runner.wait() # wait for runner to complete - - self.assertFileDoesNotExist("wait_started_2") - self.assertFileDoesNotExist("wait_cancelled_2") - self.assertFileDoesNotExist("wait_finished_2") - - - def test_workflow_success(self): - with TestAreaContext("python/job_queue/workflow_runner_fast") as work_area: - WorkflowCommon.createWaitJob() - - joblist = WorkflowJoblist() - self.assertTrue(joblist.addJobFromFile("WAIT", "wait_job")) - self.assertTrue(joblist.addJobFromFile("EXTERNAL_WAIT", "external_wait_job")) - - workflow = Workflow("fast_wait_workflow", joblist) - - self.assertEqual(len(workflow), 2) - - - workflow_runner = WorkflowRunner(workflow, ert=None, context=SubstitutionList()) - - self.assertFalse(workflow_runner.isRunning()) - - workflow_runner.run() - time.sleep(1) # wait for workflow to start - workflow_runner.wait() - - self.assertFileExists("wait_started_0") - self.assertFileDoesNotExist("wait_cancelled_0") - self.assertFileExists("wait_finished_0") - - self.assertFileExists("wait_started_1") - self.assertFileDoesNotExist("wait_cancelled_1") - self.assertFileExists("wait_finished_1") - - self.assertTrue(workflow_runner.workflowResult()) diff --git a/ThirdParty/Ert/python/tests/ert/job_queue/workflow_common.py b/ThirdParty/Ert/python/tests/ert/job_queue/workflow_common.py deleted file mode 100644 index 564c934ebc..0000000000 --- a/ThirdParty/Ert/python/tests/ert/job_queue/workflow_common.py +++ /dev/null @@ -1,140 +0,0 @@ -import os -import stat - -class WorkflowCommon(object): - - @staticmethod - def createExternalDumpJob(): - with open("dump_job", "w") as f: - f.write("INTERNAL FALSE\n") - f.write("EXECUTABLE dump.py\n") - f.write("MIN_ARG 2\n") - f.write("MAX_ARG 2\n") - f.write("ARG_TYPE 0 STRING\n") - - - with open("dump.py", "w") as f: - f.write("#!/usr/bin/env python\n") - f.write("import sys\n") - f.write("f = open('%s' % sys.argv[1], 'w')\n") - f.write("f.write('%s' % sys.argv[2])\n") - f.write("f.close()\n") - - st = os.stat("dump.py") - os.chmod("dump.py", st.st_mode | stat.S_IEXEC) # | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH - - with open("dump_workflow", "w") as f: - f.write("DUMP dump1 dump_text_1\n") - f.write("DUMP dump2 dump__2\n") - - - @staticmethod - def createInternalFunctionJob(): - with open("select_case_job", "w") as f: - f.write("INTERNAL True\n") - f.write("FUNCTION enkf_main_select_case_JOB\n") - f.write("MIN_ARG 1\n") - f.write("MAX_ARG 1\n") - f.write("ARG_TYPE 0 STRING\n") - - with open("printf_job", "w") as f: - f.write("INTERNAL True\n") - f.write("FUNCTION printf\n") - f.write("MIN_ARG 4\n") - f.write("MAX_ARG 5\n") - f.write("ARG_TYPE 0 STRING\n") - f.write("ARG_TYPE 1 INT\n") - f.write("ARG_TYPE 2 FLOAT\n") - f.write("ARG_TYPE 3 BOOL\n") - f.write("ARG_TYPE 4 STRING\n") - - - with open("compare_job", "w") as f: - f.write("INTERNAL True\n") - f.write("FUNCTION strcmp\n") - f.write("MIN_ARG 2\n") - f.write("MAX_ARG 2\n") - f.write("ARG_TYPE 0 STRING\n") - f.write("ARG_TYPE 1 STRING\n") - - - @staticmethod - def createErtScriptsJob(): - with open("subtract_script.py", "w") as f: - f.write("from ert.job_queue import ErtScript\n") - f.write("\n") - f.write("class SubtractScript(ErtScript):\n") - f.write(" def run(self, arg1, arg2):\n") - f.write(" return arg1 - arg2\n") - - - with open("subtract_script_job", "w") as f: - f.write("INTERNAL True\n") - f.write("SCRIPT subtract_script.py\n") - f.write("MIN_ARG 2\n") - f.write("MAX_ARG 2\n") - f.write("ARG_TYPE 0 FLOAT\n") - f.write("ARG_TYPE 1 FLOAT\n") - - - @staticmethod - def createWaitJob(): - with open("wait_job.py", "w") as f: - f.write("from ert.job_queue import ErtScript\n") - f.write("import time\n") - f.write("\n") - f.write("class WaitScript(ErtScript):\n") - f.write(" def dump(self, filename, content):\n") - f.write(" with open(filename, 'w') as f:\n") - f.write(" f.write(content)\n") - f.write("\n") - f.write(" def run(self, number, wait_time):\n") - f.write(" self.dump('wait_started_%d' % number, 'text')\n") - f.write(" start = time.time()\n") - f.write(" diff = 0\n") - f.write(" while not self.isCancelled() and diff < wait_time: \n") - f.write(" time.sleep(0.2)\n") - f.write(" diff = time.time() - start\n") - f.write("\n") - f.write(" if self.isCancelled():\n") - f.write(" self.dump('wait_cancelled_%d' % number, 'text')\n") - f.write(" else:\n") - f.write(" self.dump('wait_finished_%d' % number, 'text')\n") - f.write("\n") - f.write(" return None\n") - - - with open("external_wait_job.sh", "w") as f: - f.write("#!/usr/bin/env bash\n") - f.write("echo \"text\" > wait_started_$1\n") - f.write("sleep $2\n") - f.write("echo \"text\" > wait_finished_$1\n") - - st = os.stat("external_wait_job.sh") - os.chmod("external_wait_job.sh", st.st_mode | stat.S_IEXEC) # | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH - - with open("wait_job", "w") as f: - f.write("INTERNAL True\n") - f.write("SCRIPT wait_job.py\n") - f.write("MIN_ARG 2\n") - f.write("MAX_ARG 2\n") - f.write("ARG_TYPE 0 INT\n") - f.write("ARG_TYPE 1 INT\n") - - with open("external_wait_job", "w") as f: - f.write("INTERNAL False\n") - f.write("EXECUTABLE external_wait_job.sh\n") - f.write("MIN_ARG 2\n") - f.write("MAX_ARG 2\n") - f.write("ARG_TYPE 0 INT\n") - f.write("ARG_TYPE 1 INT\n") - - - with open("wait_workflow", "w") as f: - f.write("WAIT 0 1\n") - f.write("WAIT 1 10\n") - f.write("WAIT 2 1\n") - - with open("fast_wait_workflow", "w") as f: - f.write("WAIT 0 1\n") - f.write("EXTERNAL_WAIT 1 1\n") diff --git a/ThirdParty/Ert/python/tests/ert/run/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/run/CMakeLists.txt deleted file mode 100644 index 01114973d2..0000000000 --- a/ThirdParty/Ert/python/tests/ert/run/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_run.py -) - -add_python_package("python.tests.ert.run" ${PYTHON_INSTALL_PREFIX}/tests/ert/run "${TEST_SOURCES}" False) - -addPythonTest(ert.test_run tests.ert.run.test_run.RunTest ) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/run/__init__.py b/ThirdParty/Ert/python/tests/ert/run/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/ert/run/test_run.py b/ThirdParty/Ert/python/tests/ert/run/test_run.py deleted file mode 100644 index c5c76ea85d..0000000000 --- a/ThirdParty/Ert/python/tests/ert/run/test_run.py +++ /dev/null @@ -1,67 +0,0 @@ -from ert.test import TestRun , path_exists , ExtendedTestCase - - - -class RunTest(ExtendedTestCase): - def setUp(self): - self.testConfig = self.createTestPath("local/run/config.txt") - - def test_init(self): - with self.assertRaises(IOError): - TestRun("Does/notExist") - - tr = TestRun(self.testConfig) - self.assertEqual( tr.config_file , "config.txt") - self.assertEqual(tr.ert_version , "stable") - - - def test_args(self): - tr = TestRun(self.testConfig , args=["-v" , "latest"]) - self.assertEqual(tr.ert_version , "latest") - - - def test_cmd(self): - tr = TestRun(self.testConfig) - self.assertEqual( tr.ert_cmd , TestRun.default_ert_cmd ) - - tr.ert_cmd = "/tmp/test" - self.assertEqual( "/tmp/test" , tr.ert_cmd ) - - - def test_args2(self): - tr = TestRun(self.testConfig , args = ["arg1","arg2","-v","latest"]) - self.assertEqual( tr.get_args() , ["arg1","arg2"]) - self.assertEqual(tr.ert_version , "latest") - - - def test_workflows(self): - tr = TestRun(self.testConfig) - self.assertEqual( tr.get_workflows() , []) - - tr.add_workflow( "wf1" ) - tr.add_workflow( "wf2" ) - self.assertEqual( tr.get_workflows() , ["wf1" , "wf2"]) - - - def test_run_no_workflow(self): - tr = TestRun(self.testConfig) - with self.assertRaises(Exception): - tr.run() - - - - - def test_runpath(self): - tr = TestRun(self.testConfig , "Name") - self.assertEqual( TestRun.default_path_prefix , tr.path_prefix ) - - - def test_check(self): - tr = TestRun(self.testConfig , "Name") - tr.add_check( path_exists , "some/file" ) - - with self.assertRaises(Exception): - tr.add_check( 25 , "arg") - - with self.assertRaises(Exception): - tr.add_check( func_does_not_exist , "arg") diff --git a/ThirdParty/Ert/python/tests/ert/sched/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/sched/CMakeLists.txt deleted file mode 100644 index 3a0156b288..0000000000 --- a/ThirdParty/Ert/python/tests/ert/sched/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_sched.py -) - -add_python_package("python.tests.ert.sched" ${PYTHON_INSTALL_PREFIX}/tests/ert/sched "${TEST_SOURCES}" False) - -if (STATOIL_TESTDATA_ROOT) - addPythonTest(ert.sched.sched tests.ert.sched.test_sched.SchedFileTest LABELS StatoilData) -endif() \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/sched/__init__.py b/ThirdParty/Ert/python/tests/ert/sched/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/ert/sched/test_sched.py b/ThirdParty/Ert/python/tests/ert/sched/test_sched.py deleted file mode 100644 index 9e803d1073..0000000000 --- a/ThirdParty/Ert/python/tests/ert/sched/test_sched.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'test_sched.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import datetime -import os -from ert.sched import SchedFile -from ert.test import ExtendedTestCase - - - - -class SchedFileTest(ExtendedTestCase): - def setUp(self): - src_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/target.SCH") - self.start_time = datetime.date(2000, 1, 1) - - self.sched_file = SchedFile(src_file, self.start_time) - self.file_list = [] - - def test_missing(self): - with self.assertRaises(IOError): - SchedFile("/does/not/exist", datetime.date(2000 , 1 , 1)) - - - def addFile( self, filename ): - self.file_list.append(filename) - - def tearDown(self): - for f in self.file_list: - if os.path.exists(f): - os.unlink(f) - - def test_load(self): - self.assertTrue(self.sched_file, "Load failed") - - - def test_length(self): - self.assertEqual(self.sched_file.length, 63) - - - def test_write_loop(self): - self.sched_file.write("/tmp/schedule1", 62) - sched_file2 = SchedFile("/tmp/schedule1", self.start_time) - sched_file2.write("/tmp/schedule2", 62) - self.assertFilesAreEqual("/tmp/schedule1", "/tmp/schedule2") - - self.addFile("/tmp/schedule1") - self.addFile("/tmp/schedule2") diff --git a/ThirdParty/Ert/python/tests/ert/server/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/server/CMakeLists.txt deleted file mode 100644 index d34a452814..0000000000 --- a/ThirdParty/Ert/python/tests/ert/server/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_simulation_context.py - test_rpc_service.py - test_rpc_storage.py -) - -add_python_package("python.tests.ert.server" ${PYTHON_INSTALL_PREFIX}/tests/ert/server "${TEST_SOURCES}" False) - -addPythonTest(ert.server.simulation_context tests.ert.server.test_simulation_context.SimulationContextTest) -addPythonTest(ert.server.rpc_service tests.ert.server.test_rpc_service.RPCServiceTest) -addPythonTest(ert.server.rpc_storage tests.ert.server.test_rpc_storage.RPCStorageTest) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/server/__init__.py b/ThirdParty/Ert/python/tests/ert/server/__init__.py deleted file mode 100644 index 9171f9677e..0000000000 --- a/ThirdParty/Ert/python/tests/ert/server/__init__.py +++ /dev/null @@ -1,43 +0,0 @@ -from threading import Thread - -from ert.enkf import EnkfFsManager, EnkfFs, EnkfVarType -from ert.server import ErtRPCServer -from ert.test import ErtTest - - -def initializeCase(ert, name, size): - """ - @type ert: ert.enkf.enkf_main.EnKFMain - @type name: str - @type size: int - @rtype: - """ - current_fs = ert.getEnkfFsManager().getCurrentFileSystem() - fs = ert.getEnkfFsManager().getFileSystem(name) - ert.getEnkfFsManager().switchFileSystem(fs) - parameters = ert.ensembleConfig().getKeylistFromVarType(EnkfVarType.PARAMETER) - ert.getEnkfFsManager().initializeFromScratch(parameters, 0, size - 1) - - ert.getEnkfFsManager().switchFileSystem(current_fs) - return fs - - - -class RPCServiceContext(object): - def __init__(self, test_name, model_config, store_area=False): - self._test_context = ErtTest(test_name, model_config, store_area=store_area) - self._server = ErtRPCServer(self._test_context.getErt()) - - def __enter__(self): - """ @rtype: ErtRPCServer""" - thread = Thread(name="ErtRPCServerTest") - thread.run = self._server.start - thread.start() - - return self._server - - def __exit__(self, exc_type, exc_val, exc_tb): - self._server.stop() - del self._server - del self._test_context - return False \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/server/test_rpc_service.py b/ThirdParty/Ert/python/tests/ert/server/test_rpc_service.py deleted file mode 100644 index 58d8283caf..0000000000 --- a/ThirdParty/Ert/python/tests/ert/server/test_rpc_service.py +++ /dev/null @@ -1,186 +0,0 @@ -import datetime -import os -import time -from threading import Thread - -from ert import Version -from ert.enkf import EnKFMain -from ert.enkf.enums import RealizationStateEnum -from ert.server import ErtRPCServer, ErtRPCClient -from ert.test import ErtTestContext, ExtendedTestCase, ErtTest -from tests.ert.server import RPCServiceContext - - -def realizationIsInitialized(ert, case_name, realization_number): - assert isinstance(ert, EnKFMain) - fs = ert.getEnkfFsManager().getFileSystem(case_name) - state_map = fs.getStateMap() - state = state_map[realization_number] - return state == RealizationStateEnum.STATE_INITIALIZED or state == RealizationStateEnum.STATE_HAS_DATA - - -class RPCServiceTest(ExtendedTestCase): - def setUp(self): - self.config = self.createTestPath("local/snake_oil_no_data/snake_oil.ert") - - def test_server_creation(self): - with ErtTestContext("ert/server/rpc/server", self.config) as test_context: - ert = test_context.getErt() - server = ErtRPCServer(ert) - - self.assertIsNotNone(server.port) - self.assertEqual(ert, server._config) - self.assertEqual(os.path.basename(self.config), server._config_file) - - thread = Thread(name="ErtRPCServerTest") - thread.run = server.start - thread.start() - - server.stop() - - def test_client_interaction(self): - target_case_names = ["batch_1", ".batch_1", "batch_1", ".batch_1"] - kw = [ - {"SNAKE_OIL_PARAM": [0.50, 6, 1.750, 0.250, 0.990, 2, 1.770, 0.330, 0.550, 0.770]}, - {"SNAKE_OIL_PARAM": [0.51, 7, 1.751, 0.251, 0.991, 3, 1.771, 0.331, 0.551, 0.771]}, - {"SNAKE_OIL_PARAM": [0.52, 8, 1.752, 0.252, 0.992, 4, 1.772, 0.332, 0.552, 0.772]}, - {"SNAKE_OIL_PARAM": [0.53, 9, 1.753, 0.253, 0.993, 5, 1.773, 0.333, 0.553, 0.773]} - ] - - expected_state_map = { - "batch_1": [RealizationStateEnum.STATE_HAS_DATA, - RealizationStateEnum.STATE_UNDEFINED, - RealizationStateEnum.STATE_HAS_DATA - ], - - ".batch_1": [RealizationStateEnum.STATE_UNDEFINED, - RealizationStateEnum.STATE_HAS_DATA, - RealizationStateEnum.STATE_UNDEFINED, - RealizationStateEnum.STATE_HAS_DATA - ] - } - - expected_custom_kw = [ - {'RATING': 'EXCELLENT', 'NPV': 125692.534209}, - {'RATING': 'AVERAGE', 'NPV': 87423.5773042}, - {'RATING': 'GOOD', 'NPV': 113243.319848}, - {'RATING': 'AVERAGE', 'NPV': 91781.8557083} - ] - - with RPCServiceContext("ert/server/rpc/client", self.config) as server: - client = ErtRPCClient("localhost", server.port) - self.assertEqual(Version.currentVersion().versionTuple(), client.ertVersion()) - realization_count = len(target_case_names) - - client.startSimulationBatch("default", realization_count) - - self.assertTrue(server.isInitializationCaseAvailable()) - self.assertTrue(server.isRunning()) - - - for iens in range(realization_count): - client.addSimulation(target_case_names[iens], geo_id=0, pert_id=0, sim_id=iens, keywords=kw[iens]) - self.assertTrue(realizationIsInitialized(server.ert, target_case_names[iens], iens)) - - while client.isRunning(): - time.sleep(1) - - for case in expected_state_map: - fs = server.ert.getEnkfFsManager().getFileSystem(case) - state_map = fs.getStateMap() - states = expected_state_map[case] - - for index, state in enumerate(states): - self.assertEqual(state, state_map[index]) - - time_map = client.getTimeMap("batch_1") - self.assertEqual(datetime.datetime(2010, 1, 1), time_map[0]) - self.assertEqual(datetime.datetime(2015, 6, 13), time_map[199]) - - with self.assertRaises(KeyError): - client.getGenDataResult(target_case_names[0], 0, 199, "UNKNOWN_KEYWORD") - - for iens, case in enumerate(target_case_names): - self.assertTrue(client.isRealizationFinished(iens)) - self.assertTrue(client.didRealizationSucceed(iens)) - self.assertFalse(client.didRealizationFail(iens)) - - self.assertTrue(client.isCustomKWKey("SNAKE_OIL_NPV")) - self.assertFalse(client.isGenDataKey("SNAKE_OIL_NPV")) - self.assertTrue(client.isGenDataKey("SNAKE_OIL_OPR_DIFF")) - - result = client.getGenDataResult(case, iens, 199, "SNAKE_OIL_OPR_DIFF") - self.assertEqual(len(result), 2000) - - result = client.getCustomKWResult(case, iens, "SNAKE_OIL_NPV") - self.assertTrue("NPV" in result) - self.assertTrue("RATING" in result) - self.assertEqual(expected_custom_kw[iens]["RATING"], result["RATING"]) - self.assertAlmostEqual(expected_custom_kw[iens]["NPV"], result["NPV"]) - - - def test_multiple_threads(self): - expected_ckw = { - 0:{'RATING': 'EXCELLENT', 'NPV': 125692.534209}, - 1:{'RATING': 'AVERAGE', 'NPV': 87384.4316741}, - 2:{'RATING': 'GOOD', 'NPV': 113181.024141}, - 3:{'RATING': 'AVERAGE', 'NPV': 91659.8650599}, - 4:{'RATING': 'EXCELLENT', 'NPV': 134891.570703}, - 5:{'RATING': 'GOOD', 'NPV': 117270.977546}, - 6:{'RATING': 'GOOD', 'NPV': 106838.28455}, - 7:{'RATING': 'EXCELLENT', 'NPV': 144001.339}, - 8:{'RATING': 'AVERAGE', 'NPV': 95423.9155004}, - 9:{'RATING': 'AVERAGE', 'NPV': 96123.0227439} - } - - with RPCServiceContext("ert/server/rpc/multi_client", self.config, store_area=True) as server: - client_count = len(expected_ckw) - - # initializeCase(server.ert, "default", 1) - thread_success_state = {} - - def createClientInteractor(target_case_name, iens): - def clientInteraction(): - thread_success_state[iens] = False - keywords = {"SNAKE_OIL_PARAM": [0.50, iens + 2, 1.750, 0.250, 0.990, 2 + client_count - iens, 1.770, 0.330, 0.550, 0.770]} - client = ErtRPCClient("localhost", server.port) - client.startSimulationBatch("default", client_count) - - self.assertTrue(client.isRunning()) - self.assertTrue(client.isInitializationCaseAvailable()) - - client.addSimulation(target_case_name, 0, 0, iens, keywords) - self.assertTrue(realizationIsInitialized(server.ert, target_case_name, iens)) - - while not client.isRealizationFinished(iens): - time.sleep(0.5) - - self.assertTrue(client.didRealizationSucceed(iens)) - - result = client.getCustomKWResult(target_case_name, iens, "SNAKE_OIL_NPV") - self.assertTrue("NPV" in result) - self.assertTrue("RATING" in result) - self.assertEqual(expected_ckw[iens]["RATING"], result["RATING"]) - self.assertAlmostEqual(expected_ckw[iens]["NPV"], result["NPV"]) - - thread_success_state[iens] = True - - return clientInteraction - - threads = [] - for iens in range(client_count): - thread = Thread(name="client_%d" % iens) - target_case_name = "target" if iens % 2 == 0 else ".target" - thread.run = createClientInteractor(target_case_name, iens) - threads.append(thread) - - for thread in threads: - thread.start() - - while server.isRunning(): - time.sleep(0.1) - - for thread in threads: - thread.join() - - self.assertTrue(all(success for success in thread_success_state.values())) diff --git a/ThirdParty/Ert/python/tests/ert/server/test_rpc_storage.py b/ThirdParty/Ert/python/tests/ert/server/test_rpc_storage.py deleted file mode 100644 index f15ce7845c..0000000000 --- a/ThirdParty/Ert/python/tests/ert/server/test_rpc_storage.py +++ /dev/null @@ -1,124 +0,0 @@ -from itertools import product -from random import random - -import time - -from ert.enkf.enums import ErtImplType -from ert.enkf.export.custom_kw_collector import CustomKWCollector -from ert.server import ErtRPCClient -from ert.test import ExtendedTestCase -from tests.ert.server import RPCServiceContext, initializeCase - - -class RPCStorageTest(ExtendedTestCase): - def test_rpc_storage(self): - config = self.createTestPath("local/snake_oil_no_data/snake_oil.ert") - - with RPCServiceContext("ert/server/rpc_storage/storage", config) as server: - client = ErtRPCClient("localhost", server.port) - - group_name = "Test" - storage_definition = { - "PI": float, - "DakotaVersion": str, - "Gradient": float, - "GradientDirection": str - } - client.prototypeStorage(group_name, storage_definition) - - with self.assertRaises(UserWarning): - client.prototypeStorage(group_name, {"value": float}) - - with self.assertRaises(TypeError): - client.prototypeStorage(group_name, {"value": bool}) - - - ensemble_config = server.ert.ensembleConfig() - - self.assertIn(group_name, ensemble_config.getKeylistFromImplType(ErtImplType.CUSTOM_KW)) - - custom_kw_config = ensemble_config.getNode(group_name).getCustomKeywordModelConfig() - - self.assertIn("PI", custom_kw_config) - self.assertTrue(custom_kw_config.keyIsDouble("PI")) - - self.assertIn("DakotaVersion", custom_kw_config) - self.assertFalse(custom_kw_config.keyIsDouble("DakotaVersion")) - - self.assertIn("Gradient", custom_kw_config) - self.assertTrue(custom_kw_config.keyIsDouble("Gradient")) - - self.assertIn("GradientDirection", custom_kw_config) - self.assertFalse(custom_kw_config.keyIsDouble("GradientDirection")) - - - simulation_count = 10 - initializeCase(server.ert, "default", simulation_count) - - client.storeGlobalData("default", group_name, "PI", 3.1415) - client.storeGlobalData("default", group_name, "DakotaVersion", "DAKOTA 6.2.0") - - gradients = [random() * 20.0 - 10.0 for _ in range(simulation_count)] - gradient_directions = [("POSITIVE" if gradient >= 0.0 else "NEGATIVE") for gradient in gradients] - for sim_id in range(simulation_count): - gradient = gradients[sim_id] - gradient_direction = gradient_directions[sim_id] - client.storeSimulationData("default", group_name, "Gradient", gradient, sim_id) - client.storeSimulationData("default", group_name, "GradientDirection", gradient_direction, sim_id) - - - data = CustomKWCollector.loadAllCustomKWData(server.ert, "default") - for sim_id in range(simulation_count): - self.assertEqual(data["Test:PI"][sim_id], 3.1415) - self.assertEqual(data["Test:DakotaVersion"][sim_id], "DAKOTA 6.2.0") - self.assertEqual(data["Test:Gradient"][sim_id], gradients[sim_id]) - self.assertEqual(data["Test:GradientDirection"][sim_id], gradient_directions[sim_id]) - - - def test_rpc_storage_with_simulation(self): - config = self.createTestPath("local/snake_oil_no_data/snake_oil.ert") - - with RPCServiceContext("ert/server/rpc_storage/simulation_and_storage", config, store_area=True) as server: - client = ErtRPCClient("localhost", server.port) - realization_count = 2 - - client.prototypeStorage("SNAKEX", {"SNAKE_ID": float, "SNAKE_RUN": str}) - - batch_names = ["test_run_0", "test_run_1"] - - for batch_id, batch_name in enumerate(batch_names): - self.runSimulation(client, realization_count, batch_id, batch_name) - - for (batch_id, batch_name), iens in product(enumerate(batch_names), range(realization_count)): - result = client.getCustomKWResult(batch_name, iens, "SNAKEX") - self.assertEqual(result["SNAKE_RUN"], "batch_%d" % batch_id) - snake_id = realization_count * batch_id + iens - self.assertEqual(result["SNAKE_ID"], snake_id) - - - - def runSimulation(self, client, realization_count, batch_id, batch_name): - client.startSimulationBatch("default", 2) - kw = {"SNAKE_OIL_PARAM": [0.50, 6, 1.750, 0.250, 0.990, 2, 1.770, 0.330, 0.550, 0.770]} # identical runs - - for iens in range(realization_count): - client.addSimulation(batch_name, geo_id=0, pert_id=0, sim_id=iens, keywords=kw) - - while client.isRunning(): - time.sleep(0.2) - - for iens in range(realization_count): - self.assertTrue(client.didRealizationSucceed(iens)) - - - client.storeGlobalData(batch_name, "SNAKEX", "SNAKE_RUN", "batch_%d" % batch_id) - - for iens in range(realization_count): - client.storeSimulationData(batch_name, "SNAKEX", "SNAKE_ID", realization_count * batch_id + iens, iens) - - - - - - - diff --git a/ThirdParty/Ert/python/tests/ert/server/test_simulation_context.py b/ThirdParty/Ert/python/tests/ert/server/test_simulation_context.py deleted file mode 100644 index 33a4347331..0000000000 --- a/ThirdParty/Ert/python/tests/ert/server/test_simulation_context.py +++ /dev/null @@ -1,97 +0,0 @@ -import time -import os.path -import sys - -from ert.enkf import EnkfVarType -from ert.enkf.enums import RealizationStateEnum -from ert.server import SimulationContext -from ert.test import ErtTestContext, ExtendedTestCase -from tests.ert.server import initializeCase - - -class SimulationContextTest(ExtendedTestCase): - - def setUp(self): - self.config1 = self.createTestPath("local/snake_oil_no_data/snake_oil.ert") - self.config2 = self.createTestPath("local/snake_oil_no_data/snake_oil_GEO_ID.ert") - - - def test_simulation_context(self): - with ErtTestContext("ert/server/rpc/simulation_context", self.config1) as test_context: - ert = test_context.getErt() - - size = 4 - first_half = initializeCase(ert, "first_half", size) - other_half = initializeCase(ert, "other_half", size) - - simulation_context = SimulationContext(ert, size) - - for iens in range(size): - if iens % 2 == 0: - simulation_context.addSimulation(iens, first_half) - else: - simulation_context.addSimulation(iens, other_half) - self.assertFalse(simulation_context.isRealizationFinished(iens)) - - with self.assertRaises(UserWarning): - simulation_context.addSimulation(size, first_half) - - with self.assertRaises(UserWarning): - simulation_context.addSimulation(0, first_half) - - while simulation_context.isRunning(): - time.sleep(1.0) - - self.assertEqual(simulation_context.getNumFailed(), 0) - self.assertEqual(simulation_context.getNumRunning(), 0) - self.assertEqual(simulation_context.getNumSuccess(), size) - - first_half_state_map = first_half.getStateMap() - other_half_state_map = other_half.getStateMap() - - for iens in range(size): - self.assertTrue(simulation_context.didRealizationSucceed(iens)) - self.assertFalse(simulation_context.didRealizationFail(iens)) - self.assertTrue(simulation_context.isRealizationFinished(iens)) - if iens % 2 == 0: - self.assertEqual(first_half_state_map[iens], RealizationStateEnum.STATE_HAS_DATA) - self.assertEqual(other_half_state_map[iens], RealizationStateEnum.STATE_INITIALIZED) - else: - self.assertEqual(first_half_state_map[iens], RealizationStateEnum.STATE_INITIALIZED) - self.assertEqual(other_half_state_map[iens], RealizationStateEnum.STATE_HAS_DATA) - - pfx = 'SimulationContext(' - self.assertEqual(pfx, repr(simulation_context)[:len(pfx)]) - - def test_runpath(self): - with ErtTestContext("ert/server/rpc/simulation_context_runpath", self.config2) as test_context: - ert = test_context.getErt() - sys.stderr.write("cwd: %s \n" % os.getcwd()) - size = 10 - - fs = ert.getEnkfFsManager().getCurrentFileSystem() - parameters = ert.ensembleConfig().getKeylistFromVarType(EnkfVarType.PARAMETER) - ert.getEnkfFsManager().initializeFromScratch(parameters, 0, size - 1) - simulation_context = SimulationContext(ert, size) - - for iens in range(size): - state = ert.getRealisation(iens) - if iens % 2 == 0: - state.addSubstKeyword("GEO_ID", "EVEN") - else: - state.addSubstKeyword("GEO_ID", "ODD") - simulation_context.addSimulation(iens , fs) - - while simulation_context.isRunning(): - time.sleep(1.0) - - for iens in range(size): - if iens % 2 == 0: - path = "simulations/EVEN/realisation-%d/iter-%d" % (iens , 0) - self.assertTrue( os.path.isdir(path) ) - else: - path = "simulations/ODD/realisation-%d/iter-%d" % (iens , 0) - self.assertTrue( os.path.isdir(path) ) - - pfx = 'SimulationContext(' - self.assertEqual(pfx, repr(simulation_context)[:len(pfx)]) diff --git a/ThirdParty/Ert/python/tests/ert/testcase/CMakeLists.txt b/ThirdParty/Ert/python/tests/ert/testcase/CMakeLists.txt deleted file mode 100644 index 328614835f..0000000000 --- a/ThirdParty/Ert/python/tests/ert/testcase/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_testcase.py - test_mini_config.py -) - -add_python_package("python.tests.ert.testcase" ${PYTHON_INSTALL_PREFIX}/tests/ert/testcase "${TEST_SOURCES}" False) - -addPythonTest(ert.testcase.testcase tests.ert.testcase.test_testcase.TestTestCase) -addPythonTest(ert.testcase.mini_config tests.ert.testcase.test_mini_config.MiniConfigTest) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/ert/testcase/__init__.py b/ThirdParty/Ert/python/tests/ert/testcase/__init__.py deleted file mode 100644 index 5e08e797f5..0000000000 --- a/ThirdParty/Ert/python/tests/ert/testcase/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ThirdParty/Ert/python/tests/ert/testcase/test_mini_config.py b/ThirdParty/Ert/python/tests/ert/testcase/test_mini_config.py deleted file mode 100644 index 33f388578b..0000000000 --- a/ThirdParty/Ert/python/tests/ert/testcase/test_mini_config.py +++ /dev/null @@ -1,49 +0,0 @@ -from ert.enkf.enums.realization_state_enum import RealizationStateEnum -from ert.test import ErtTestContext -from ert.test.extended_testcase import ExtendedTestCase - - -class MiniConfigTest(ExtendedTestCase): - - def test_failed_realizations(self): - - # mini_fail_config has the following realization success/failures: - # - # 0 OK - # 1 GenData report step 1 missing - # 2 GenData report step 2 missing, Forward Model Component Target File not found. - # 3 GenData report step 3 missing, Forward Model Component Target File not found. - # 4 GenData report step 1 missing - # 5 GenData report step 2 missing, Forward Model Component Target File not found. - # 6 GenData report step 3 missing - # 7 Forward Model Target File not found. - # 8 OK - # 9 OK - - - config = self.createTestPath("local/custom_kw/mini_fail_config") - with ErtTestContext("python/enkf/data/custom_kw_simulated", config) as context: - ert = context.getErt() - - fs = ert.getEnkfFsManager().getCurrentFileSystem() - - realizations_list = fs.realizationList(RealizationStateEnum.STATE_HAS_DATA) - self.assertTrue(0 in realizations_list) - self.assertTrue(8 in realizations_list) - self.assertTrue(9 in realizations_list) - - realizations_list = fs.realizationList(RealizationStateEnum.STATE_LOAD_FAILURE) - self.assertTrue(1 in realizations_list) - self.assertTrue(2 in realizations_list) - self.assertTrue(3 in realizations_list) - self.assertTrue(4 in realizations_list) - self.assertTrue(5 in realizations_list) - self.assertTrue(6 in realizations_list) - self.assertTrue(7 in realizations_list) - - - - - - - diff --git a/ThirdParty/Ert/python/tests/ert/testcase/test_testcase.py b/ThirdParty/Ert/python/tests/ert/testcase/test_testcase.py deleted file mode 100644 index 6308d54264..0000000000 --- a/ThirdParty/Ert/python/tests/ert/testcase/test_testcase.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) 2015 Statoil ASA, Norway. -# -# The file 'test_testcase.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -import functools -import math -from ert.test import ExtendedTestCase - -class TestTestCase(ExtendedTestCase): - - def test_not_raises(self): - call_sin = functools.partial( math.sin , 0.5*math.pi ) - self.assertNotRaises( call_sin ) - diff --git a/ThirdParty/Ert/python/tests/geometry/CMakeLists.txt b/ThirdParty/Ert/python/tests/geometry/CMakeLists.txt new file mode 100644 index 0000000000..5cfaf5c6a7 --- /dev/null +++ b/ThirdParty/Ert/python/tests/geometry/CMakeLists.txt @@ -0,0 +1,28 @@ +set(TEST_SOURCES + __init__.py + test_convex_hull.py + test_cpolyline.py + test_cpolyline_collection.py + test_geometry_tools.py + test_intersection.py + test_point_in_polygon.py + test_polygon_slicing.py + test_polyline.py + test_surface.py + test_geo_pointset.py + test_geo_region.py +) + +add_python_package("python.tests.geometry" ${PYTHON_INSTALL_PREFIX}/tests/geometry "${TEST_SOURCES}" False) + +addPythonTest(geometry.geo_pointset tests.geometry.test_geo_pointset.GeoPointsetTest) +addPythonTest(geometry.geo_region tests.geometry.test_geo_region.GeoRegionTest) +addPythonTest(geometry.surface tests.geometry.test_surface.SurfaceTest) +addPythonTest(geometry.polyline tests.geometry.test_polyline.PolylineTest) +addPythonTest(geometry.intersection tests.geometry.test_intersection.IntersectionTest) +addPythonTest(geometry.convex_hull tests.geometry.test_convex_hull.ConvexHullTest) +addPythonTest(geometry.point_in_polygon tests.geometry.test_point_in_polygon.PointInPolygonTest) +addPythonTest(geometry.polygon_slicing tests.geometry.test_polygon_slicing.PolygonSlicingTest) +addPythonTest(geometry.cpolyline tests.geometry.test_cpolyline.CPolylineTest) +addPythonTest(geometry.cpolyline_collection tests.geometry.test_cpolyline_collection.CPolylineCollectionTest) +addPythonTest(geometry.geometry_tools tests.geometry.test_geometry_tools.GeometryToolsTest ) diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/__init__.py b/ThirdParty/Ert/python/tests/geometry/__init__.py similarity index 100% rename from ThirdParty/Ert/python/python/ert_gui/ide/__init__.py rename to ThirdParty/Ert/python/tests/geometry/__init__.py diff --git a/ThirdParty/Ert/python/tests/core/geometry/test_convex_hull.py b/ThirdParty/Ert/python/tests/geometry/test_convex_hull.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/geometry/test_convex_hull.py rename to ThirdParty/Ert/python/tests/geometry/test_convex_hull.py diff --git a/ThirdParty/Ert/python/tests/core/geometry/test_cpolyline.py b/ThirdParty/Ert/python/tests/geometry/test_cpolyline.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/geometry/test_cpolyline.py rename to ThirdParty/Ert/python/tests/geometry/test_cpolyline.py diff --git a/ThirdParty/Ert/python/tests/core/geometry/test_cpolyline_collection.py b/ThirdParty/Ert/python/tests/geometry/test_cpolyline_collection.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/geometry/test_cpolyline_collection.py rename to ThirdParty/Ert/python/tests/geometry/test_cpolyline_collection.py diff --git a/ThirdParty/Ert/python/tests/geometry/test_geo_pointset.py b/ThirdParty/Ert/python/tests/geometry/test_geo_pointset.py new file mode 100644 index 0000000000..5e67e4aabf --- /dev/null +++ b/ThirdParty/Ert/python/tests/geometry/test_geo_pointset.py @@ -0,0 +1,27 @@ +from ert.geo import GeoPointset, Surface +from ert.test import ExtendedTestCase, TestAreaContext + + +class GeoPointsetTest(ExtendedTestCase): + + def test_init(self): + gp = GeoPointset() + self.assertEqual(0, len(gp)) + + def test_repr(self): + gp = GeoPointset() + self.assertTrue(repr(gp).startswith('GeoPointset')) + + def test_from_surface(self): + srf_path = self.createTestPath("local/geometry/surface/valid_ascii.irap") + srf = Surface(srf_path) + gp = GeoPointset.fromSurface(srf) + self.assertEqual(3871, len(srf)) + self.assertEqual(len(srf), len(gp)) + + def test_getitem(self): + srf_path = self.createTestPath("local/geometry/surface/valid_ascii.irap") + srf = Surface(srf_path) + gp = GeoPointset.fromSurface(srf) + for i in (561, 1105, 1729, 2465, 2821): + self.assertEqual(gp[i], srf[i]) diff --git a/ThirdParty/Ert/python/tests/geometry/test_geo_region.py b/ThirdParty/Ert/python/tests/geometry/test_geo_region.py new file mode 100644 index 0000000000..771a2af59e --- /dev/null +++ b/ThirdParty/Ert/python/tests/geometry/test_geo_region.py @@ -0,0 +1,88 @@ +from ert.geo import GeoRegion, GeoPointset, CPolyline, Surface +from ert.test import ExtendedTestCase, TestAreaContext + + +class GeoRegionTest(ExtendedTestCase): + + def test_init(self): + pointset = GeoPointset() + georegion = GeoRegion(pointset) + self.assertEqual(0, len(georegion)) + + def test_repr(self): + pointset = GeoPointset() + georegion = GeoRegion(pointset) + self.assertTrue(repr(georegion).startswith('GeoRegion')) + + @staticmethod + def small_surface(): + ny,nx = 12,12 + xinc,yinc = 1, 1 + xstart,ystart = -1, -1 + angle = 0.0 + s_args = (None, nx, ny, xinc, yinc, xstart, ystart, angle) + return Surface(*s_args) + + def test_select_polygon(self): + surface = self.small_surface() + pointset = GeoPointset.fromSurface(surface) + georegion = GeoRegion(pointset) + self.assertEqual(0, len(georegion)) + points = [(-0.1,2.0), (1.9,8.1), (6.1,8.1), (9.1,5), (7.1,0.9)] + polygon = CPolyline(name='test_polygon', init_points=points) + picked = 52 # https://www.futilitycloset.com/2013/04/24/picks-theorem/ + georegion.select_inside(polygon) + self.assertEqual(picked, len(georegion)) + georegion.deselect_inside(polygon) + self.assertEqual(0, len(georegion)) + georegion.select_outside(polygon) + self.assertEqual(len(surface) - picked, len(georegion)) + georegion.deselect_outside(polygon) + self.assertEqual(0, len(georegion)) + + georegion.select_inside(polygon) + georegion.select_outside(polygon) + self.assertEqual(len(surface), len(georegion)) + georegion.deselect_inside(polygon) + georegion.deselect_outside(polygon) + self.assertEqual(0, len(georegion)) + + georegion.select_inside(polygon) + self.assertEqual(picked, len(georegion)) + internal_square = [(2.5,2.5), (2.5,6.5), (6.5,6.5), (6.5,2.5)] + georegion.deselect_inside(CPolyline(init_points=internal_square)) + self.assertEqual(picked - 4*4, len(georegion)) # internal square is 4x4 + + + def test_select_halfspace(self): + surface = self.small_surface() + pointset = GeoPointset.fromSurface(surface) + georegion = GeoRegion(pointset) + self.assertEqual(0, len(georegion)) + line = [(-0.1,2.0), (1.9,8.1)] + picked = 118 + georegion.select_above(line) + self.assertEqual(picked, len(georegion)) + georegion.deselect_above(line) + self.assertEqual(0, len(georegion)) + georegion.select_below(line) + self.assertEqual(len(surface) - picked, len(georegion)) + georegion.deselect_below(line) + self.assertEqual(0, len(georegion)) + + georegion.select_above(line) + georegion.select_below(line) + self.assertEqual(len(surface), len(georegion)) + georegion.deselect_above(line) + georegion.deselect_below(line) + self.assertEqual(0, len(georegion)) + + + def test_raises(self): + surface = self.small_surface() + pointset = GeoPointset.fromSurface(surface) + georegion = GeoRegion(pointset) + with self.assertRaises(ValueError): + georegion.select_above(((2,), (1, 3))) + with self.assertRaises(ValueError): + georegion.select_above((('not-a-number', 2), (1, 3))) diff --git a/ThirdParty/Ert/python/tests/core/geometry/test_geometry_tools.py b/ThirdParty/Ert/python/tests/geometry/test_geometry_tools.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/geometry/test_geometry_tools.py rename to ThirdParty/Ert/python/tests/geometry/test_geometry_tools.py diff --git a/ThirdParty/Ert/python/tests/core/geometry/test_intersection.py b/ThirdParty/Ert/python/tests/geometry/test_intersection.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/geometry/test_intersection.py rename to ThirdParty/Ert/python/tests/geometry/test_intersection.py diff --git a/ThirdParty/Ert/python/tests/core/geometry/test_point_in_polygon.py b/ThirdParty/Ert/python/tests/geometry/test_point_in_polygon.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/geometry/test_point_in_polygon.py rename to ThirdParty/Ert/python/tests/geometry/test_point_in_polygon.py diff --git a/ThirdParty/Ert/python/tests/core/geometry/test_polygon_slicing.py b/ThirdParty/Ert/python/tests/geometry/test_polygon_slicing.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/geometry/test_polygon_slicing.py rename to ThirdParty/Ert/python/tests/geometry/test_polygon_slicing.py diff --git a/ThirdParty/Ert/python/tests/core/geometry/test_polyline.py b/ThirdParty/Ert/python/tests/geometry/test_polyline.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/geometry/test_polyline.py rename to ThirdParty/Ert/python/tests/geometry/test_polyline.py diff --git a/ThirdParty/Ert/python/tests/core/geometry/test_surface.py b/ThirdParty/Ert/python/tests/geometry/test_surface.py similarity index 92% rename from ThirdParty/Ert/python/tests/core/geometry/test_surface.py rename to ThirdParty/Ert/python/tests/geometry/test_surface.py index 997f1c745f..1bfd204a04 100644 --- a/ThirdParty/Ert/python/tests/core/geometry/test_surface.py +++ b/ThirdParty/Ert/python/tests/geometry/test_surface.py @@ -11,6 +11,16 @@ class SurfaceTest(ExtendedTestCase): self.surface_valid2 = self.createTestPath("local/geometry/surface/valid2_ascii.irap") self.surface_small = self.createTestPath("local/geometry/surface/valid_small_ascii.irap") + def test_xyz(self): + s = Surface(self.surface_valid2) + self.assertEqual(s.getXYZ(i=5,j=13), s.getXYZ(idx=642)) + x,y,z = s.getXYZ(i=5,j=13) + self.assertFloatEqual(464041.44804, x) + self.assertFloatEqual(7336966.309535, y) + self.assertFloatEqual(0.0051, z) + self.assertAlmostEqualList(s.getXYZ(i=6,j=13), s.getXYZ(idx=643)) + self.assertFloatEqual(-0.0006, s.getXYZ(i=6,j=13)[2]) # z value + def test_create_new(self): with self.assertRaises(ValueError): s = Surface(None, 1, 1, 1) diff --git a/ThirdParty/Ert/python/tests/gui/CMakeLists.txt b/ThirdParty/Ert/python/tests/gui/CMakeLists.txt deleted file mode 100644 index 26d2b0e202..0000000000 --- a/ThirdParty/Ert/python/tests/gui/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_multiple_data_assimilation.py -) - -add_python_package("python.tests.gui" ${PYTHON_INSTALL_PREFIX}/tests/gui "${TEST_SOURCES}" False) - -addPythonTest(gui.mda_weights tests.gui.test_multiple_data_assimilation.MDAWeightsTest) - -add_subdirectory(ertshell) -add_subdirectory(ide) -add_subdirectory(plottery) diff --git a/ThirdParty/Ert/python/tests/gui/__init__.py b/ThirdParty/Ert/python/tests/gui/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/CMakeLists.txt b/ThirdParty/Ert/python/tests/gui/ertshell/CMakeLists.txt deleted file mode 100644 index d402395a86..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ertshell/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -set(TEST_SOURCES - __init__.py - ert_shell_test_context.py - test_ertshell_analysis.py - test_ertshell_context.py - test_ertshell_observations.py - test_ertshell_plot_settings.py - test_ertshell_smoother.py - test_ertshell_server.py - - test_shell_function.py - test_shell_property.py - test_shell_collection.py -) - -add_python_package("python.tests.gui.ertshell" ${PYTHON_INSTALL_PREFIX}/tests/gui/ertshell "${TEST_SOURCES}" False) - -addPythonTest(gui.ertshell.analysis gui.ertshell.test_ertshell_analysis.ErtShellAnalysisModuleTest) -addPythonTest(gui.ertshell.context gui.ertshell.test_ertshell_context.ErtShellContextTest) -addPythonTest(gui.ertshell.observations gui.ertshell.test_ertshell_observations.ErtShellObservationsTest) -addPythonTest(gui.ertshell.plot_settings gui.ertshell.test_ertshell_plot_settings.ErtShellPlotSettingsTest) -addPythonTest(gui.ertshell.smoother gui.ertshell.test_ertshell_smoother.ErtShellSmootherTest) -addPythonTest(gui.ertshell.server gui.ertshell.test_ertshell_server.ErtShellServerTest) - -addPythonTest(gui.ertshell.shell_function gui.ertshell.test_shell_function.ShellFunctionTest) -addPythonTest(gui.ertshell.shell_property gui.ertshell.test_shell_property.ShellPropertyTest) -addPythonTest(gui.ertshell.shell_collection gui.ertshell.test_shell_collection.ShellCollectionTest) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/__init__.py b/ThirdParty/Ert/python/tests/gui/ertshell/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/ert_shell_test_context.py b/ThirdParty/Ert/python/tests/gui/ertshell/ert_shell_test_context.py deleted file mode 100644 index b5f025e32d..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ertshell/ert_shell_test_context.py +++ /dev/null @@ -1,56 +0,0 @@ -from StringIO import StringIO -import os -import sys -from ert.test import TestAreaContext -from ert_gui.shell import ErtShell - -class ShellCapturing(list): - - def __init__(self, shell): - self.shell = shell - - def __enter__(self): - self._stdout = sys.stdout - self._shell_stdout = self.shell.stdout - sys.stdout = self.shell.stdout = self._stringio = StringIO() - return self - - def __exit__(self, *args): - self.extend(self._stringio.getvalue().splitlines()) - sys.stdout = self._stdout - self.shell.stdout = self._shell_stdout - - - -class ErtShellTestContext(object): - - def __init__(self, test_name, config_file, load_config=True, prefix=None, store_area=False): - self.config_file = config_file - self.load_config = load_config - self.test_area_context = TestAreaContext(test_name, prefix=prefix, store_area=store_area) - - - def __enter__(self): - """ :rtype: ErtShell """ - test_area = self.test_area_context.__enter__() - - if os.path.exists(self.config_file): - test_area.copy_parent_content(self.config_file) - elif self.config_file is not None: - raise IOError("The config file: '%s' does not exist!" % self.config_file) - - self.shell = ErtShell(forget_history=True) - - config_file = os.path.basename(self.config_file) - - if self.load_config: - self.shell.onecmd("load_config %s" % config_file) - - return self.shell - - - def __exit__(self, exc_type, exc_val, exc_tb): - self.shell.do_exit("") - self.shell._cleanup() - self.test_area_context.__exit__(exc_type, exc_val, exc_tb) - return False \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_analysis.py b/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_analysis.py deleted file mode 100644 index f974b17124..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_analysis.py +++ /dev/null @@ -1,46 +0,0 @@ -from ert.test.extended_testcase import ExtendedTestCase -from tests.gui.ertshell.ert_shell_test_context import ErtShellTestContext - - -class ErtShellAnalysisModuleTest(ExtendedTestCase): - - def test_analysis_module(self): - test_config = self.createTestPath("local/custom_kw/mini_config") - - with ErtShellTestContext("python/ertshell/analysis_module", test_config) as shell: - - self.assertTrue(shell.invokeCommand("analysis_module active_module")) - self.assertTrue(shell.invokeCommand("analysis_module list")) - - modules = shell.shellContext().ert().analysisConfig().getModuleList() - - for analysis_module in modules: - self.assertTrue(shell.invokeCommand("analysis_module active_module %s" % analysis_module)) - active_module_name = shell.shellContext().ert().analysisConfig().activeModuleName() - self.assertEqual(analysis_module, active_module_name) - - self.assertTrue(shell.invokeCommand("analysis_module variables")) - - analysis_module = shell.shellContext().ert().analysisConfig().getActiveModule() - variable_names = analysis_module.getVariableNames() - - for variable_name in variable_names: - value = analysis_module.getVariableValue(variable_name) - - variable_type = analysis_module.getVariableType(variable_name) - - if variable_type is float: - new_value = value + 0.5 - elif variable_type is int: - new_value = value + 2 - elif variable_type is str: - new_value = "New String Value" - else: - new_value = not value - - self.assertTrue(shell.invokeCommand("analysis_module set %s %s" % (variable_name, new_value))) - - updated_value = analysis_module.getVariableValue(variable_name) - - self.assertEqual(new_value, updated_value) - diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_context.py b/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_context.py deleted file mode 100644 index a83d860d7a..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_context.py +++ /dev/null @@ -1,31 +0,0 @@ -import os -from ert.test import ExtendedTestCase -from tests.gui.ertshell.ert_shell_test_context import ErtShellTestContext, ShellCapturing - - -class ErtShellContextTest(ExtendedTestCase): - - def test_ertshell_context(self): - test_config = self.createTestPath("local/custom_kw/mini_config") - - with ErtShellTestContext("python/ertshell/ert_shell_context", config_file=test_config, load_config=False) as shell: - self.assertIsNone(shell.shellContext().ert()) - self.assertTrue(shell.invokeCommand("load_config mini_config")) - self.assertIsNotNone(shell.shellContext().ert()) - - - def test_std_out_capture(self): - - test_config = self.createTestPath("local/custom_kw/mini_config") - - with ErtShellTestContext("python/ertshell/ert_shell_context", config_file=test_config, load_config=False) as shell: - - with ShellCapturing(shell) as out: - shell.onecmd("cwd") - - cwd = out[0] - prefix = "Current directory: " - self.assertTrue(cwd.startswith(prefix)) - - self.assertEqual(os.getcwd(), cwd[len(prefix):]) - diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_observations.py b/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_observations.py deleted file mode 100644 index 391f2516c0..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_observations.py +++ /dev/null @@ -1,28 +0,0 @@ -from ert.test import ExtendedTestCase -from tests.gui.ertshell.ert_shell_test_context import ErtShellTestContext - -class ErtShellObservationsTest(ExtendedTestCase): - - def test_load_observations(self): - test_config = self.createTestPath("local/custom_kw/mini_config") - - with ErtShellTestContext("python/ertshell/observations", test_config) as shell: - ert = shell.shellContext().ert() - original_observation_count = len(ert.getObservations()) - - self.assertTrue(shell.invokeCommand("observations list")) - - self.assertTrue(shell.invokeCommand("observations clear")) - self.assertEqual(0, len(ert.getObservations())) - - self.assertTrue(shell.invokeCommand("observations load Observations/observation_1")) - self.assertEqual(1, len(ert.getObservations())) - - self.assertTrue(shell.invokeCommand("observations load Observations/observation_2")) - self.assertEqual(2, len(ert.getObservations())) - - self.assertTrue(shell.invokeCommand("observations load Observations/observation_3")) - self.assertEqual(original_observation_count, len(ert.getObservations())) - - self.assertTrue(shell.invokeCommand("observations reload Observations/observation_1")) - self.assertEqual(1, len(ert.getObservations())) diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_plot_settings.py b/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_plot_settings.py deleted file mode 100644 index c5ba0793e7..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_plot_settings.py +++ /dev/null @@ -1,60 +0,0 @@ -from ert.test import ExtendedTestCase -from tests.gui.ertshell.ert_shell_test_context import ErtShellTestContext - - -class ErtShellPlotSettingsTest(ExtendedTestCase): - def checkStringProperties(self, shell, command, testFunction, allow_multiple_arguments=True): - self.assertTrue(shell.invokeCommand(command)) - - spacey_string = "new value with spaces" - if allow_multiple_arguments: - self.assertTrue(shell.invokeCommand("%s %s" % (command, spacey_string))) - self.assertEqual(testFunction(), spacey_string) - else: - self.assertFalse(shell.invokeCommand("%s %s" % (command, spacey_string))) - self.assertNotEqual(testFunction(), spacey_string) - - no_spacey_string = "new_value_without_spaces" - self.assertTrue(shell.invokeCommand("%s %s" % (command, no_spacey_string))) - self.assertEqual(testFunction(), no_spacey_string) - - - def checkBoolProperties(self, shell, command, testFunction): - start_value = testFunction() - self.assertTrue(shell.invokeCommand(command)) - self.assertTrue(shell.invokeCommand("%s %s" % (command, str(not start_value)))) - self.assertNotEqual(start_value, testFunction()) - self.assertFalse(shell.invokeCommand("%s not_a_bool" % command)) - - - def test_style_setting(self): - test_config = self.createTestPath("local/custom_kw/mini_config") - with ErtShellTestContext("python/ertshell/plot_settings", test_config, load_config=True) as shell: - plot_config = shell.shellContext()["plot_settings"].plotConfig() - - self.assertTrue(shell.invokeCommand("help plot_settings")) - - self.checkStringProperties(shell, "plot_settings title", plot_config.title) - self.checkStringProperties(shell, "plot_settings x_label", plot_config.xLabel) - self.checkStringProperties(shell, "plot_settings y_label", plot_config.yLabel) - - self.checkBoolProperties(shell, "plot_settings grid", plot_config.isGridEnabled) - self.checkBoolProperties(shell, "plot_settings legend", plot_config.isLegendEnabled) - self.checkBoolProperties(shell, "plot_settings refcase", plot_config.isRefcaseEnabled) - self.checkBoolProperties(shell, "plot_settings observations", plot_config.isObservationsEnabled) - - self.checkStringProperties(shell, "plot_settings path", shell.shellContext()["plot_settings"].getPath, allow_multiple_arguments=False) - - default_plot_cases = shell.shellContext()["plot_settings"].getCurrentPlotCases() - self.assertTrue(shell.invokeCommand("plot_settings current")) - self.assertTrue(shell.invokeCommand("plot_settings select test_run default")) - - plot_cases = shell.shellContext()["plot_settings"].getCurrentPlotCases() - self.assertSetEqual(set(plot_cases), {"test_run", "default"}) - - self.assertTrue(shell.invokeCommand("plot_settings select")) - plot_cases = shell.shellContext()["plot_settings"].getCurrentPlotCases() - self.assertListEqual(plot_cases, default_plot_cases) - - self.assertFalse(shell.invokeCommand("plot_settings select unknown")) - self.assertFalse(shell.invokeCommand("plot_settings select unknown1 unknown2")) diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_server.py b/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_server.py deleted file mode 100644 index 6aea6ce930..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_server.py +++ /dev/null @@ -1,23 +0,0 @@ -from ert.test import ExtendedTestCase -from tests.gui.ertshell.ert_shell_test_context import ErtShellTestContext - - -class ErtShellServerTest(ExtendedTestCase): - - def test_server(self): - config = self.createTestPath("local/snake_oil_no_data/snake_oil.ert") - with ErtShellTestContext("python/ertshell/server", config, load_config=False) as shell: - server_settings = shell.shellContext()["server_settings"] - self.assertTrue(shell.invokeCommand("help server")) - - self.assertTrue(shell.invokeCommand("server hostname")) - self.assertEqual(server_settings._hostname, "localhost") - - self.assertTrue(shell.invokeCommand("server hostname new.hostname.no")) - self.assertEqual(server_settings._hostname, "new.hostname.no") - - self.assertTrue(shell.invokeCommand("server port")) - self.assertEqual(server_settings._port, 0) - - self.assertTrue(shell.invokeCommand("server port 99")) - self.assertEqual(server_settings._port, 99) diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_smoother.py b/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_smoother.py deleted file mode 100644 index 3646b6d0ca..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ertshell/test_ertshell_smoother.py +++ /dev/null @@ -1,53 +0,0 @@ -from __future__ import print_function -import os -from ert.enkf.export import GenKwCollector -from ert.test.extended_testcase import ExtendedTestCase -from tests.gui.ertshell.ert_shell_test_context import ErtShellTestContext - -class ErtShellSmootherTest(ExtendedTestCase): - - def test_smoother(self): - test_config = self.createTestPath("local/custom_kw/mini_config") - - with ErtShellTestContext("python/ertshell/smoother", test_config) as shell: - print(os.getcwd()) - shell.invokeCommand("case select test_run") - - self.assertTrue(shell.invokeCommand("smoother update test_run_update")) - - shell.invokeCommand("case select test_run_update") - - ert = shell.shellContext().ert() - data = GenKwCollector.loadAllGenKwData(ert, "test_run", keys=["PERLIN_PARAM:SCALE"]) - update_data = GenKwCollector.loadAllGenKwData(ert, "test_run_update", keys=["PERLIN_PARAM:SCALE"]) - - self.assertTrue(data["PERLIN_PARAM:SCALE"].std() > update_data["PERLIN_PARAM:SCALE"].std()) - - - def test_config(self): - test_config = self.createTestPath("local/custom_kw/mini_config") - - with ErtShellTestContext("python/ertshell/smoother_config", test_config) as shell: - - analysis_config = shell.shellContext().ert().analysisConfig() - - self.assertTrue(shell.invokeCommand("smoother overlap_alpha")) - self.assertTrue(shell.invokeCommand("smoother overlap_alpha 3.1415")) - self.assertAlmostEqual(3.1415, analysis_config.getEnkfAlpha()) - self.assertFalse(shell.invokeCommand("smoother overlap_alpha threepointfourteen")) - - self.assertTrue(shell.invokeCommand("smoother std_cutoff")) - self.assertTrue(shell.invokeCommand("smoother std_cutoff 0.1")) - self.assertAlmostEqual(0.1, analysis_config.getStdCutoff()) - self.assertTrue(shell.invokeCommand("smoother std_cutoff -0.1")) - self.assertAlmostEqual(0.0, analysis_config.getStdCutoff()) - self.assertFalse(shell.invokeCommand("smoother std_cutoff zeropointthreefourteen")) - - - self.assertTrue(shell.invokeCommand("smoother global_std_scaling")) - self.assertTrue(shell.invokeCommand("smoother global_std_scaling 0.5")) - self.assertAlmostEqual(0.5, analysis_config.getGlobalStdScaling()) - self.assertTrue(shell.invokeCommand("smoother global_std_scaling -0.5")) - self.assertAlmostEqual(0.0, analysis_config.getGlobalStdScaling()) - self.assertFalse(shell.invokeCommand("smoother global_std_scaling zeropointfour")) - diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/test_shell_collection.py b/ThirdParty/Ert/python/tests/gui/ertshell/test_shell_collection.py deleted file mode 100644 index 763d9f1799..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ertshell/test_shell_collection.py +++ /dev/null @@ -1,97 +0,0 @@ -from ert.test import ExtendedTestCase -from ert_gui.shell.libshell import ShellCollection - - -class MockParent(object): - def __init__(self, name="DefaultMockParent"): - self.__name = name - self.__failed = False - - def shellContext(self): - return self - - def shell(self): - return self - - def columnize(self, items, size): - print(items) - - def lastCommandFailed(self, message): - print("[%s] Error: %s" % (self.__name, message)) - self.__failed = True - - def didLastCommandFail(self): - failed = self.__failed - self.__failed = False - return failed - - -def completeMock(line): - last_space_index = line.rfind(" ") - begin_index = 0 if last_space_index == -1 else last_space_index + 1 - end_index = len(line) - text = line[begin_index:end_index] - - return text, line, begin_index, end_index - - -class ShellCollectionTest(ExtendedTestCase): - - def test_creation(self): - name = "test" - shell_collection = ShellCollection(name) - - parent = MockParent() - shell_collection.setParent(parent) - - self.assertEqual(shell_collection.name, name) - - self.assertTrue(hasattr(parent, "do_%s" % name)) - self.assertTrue(hasattr(parent, "complete_%s" % name)) - self.assertTrue(hasattr(parent, "help_%s" % name)) - - - def test_sub_collection(self): - l1 = "level_1" - l2 = "level_2" - l3 = "level_3" - - root = MockParent() - level_1 = ShellCollection(l1) - level_1.setParent(root) - level_2 = ShellCollection(l2) - level_1.addCollection(level_2) - level_3 = ShellCollection(l3) - level_2.addCollection(level_3) - - tests = [(root, l1), (level_1, l2), (level_2, l3)] - - for parent, name in tests: - self.assertTrue(hasattr(parent, "do_%s" % name)) - self.assertTrue(hasattr(parent, "complete_%s" % name)) - self.assertTrue(hasattr(parent, "help_%s" % name)) - - root.do_level_1("level_2 ") - self.assertFalse(root.didLastCommandFail()) - - root.do_level_1("r ") - self.assertTrue(root.didLastCommandFail()) - - root.do_level_1(" level_2 level_3") - self.assertFalse(root.didLastCommandFail()) - - root.do_level_1("level_2 level_3 p") - self.assertTrue(root.didLastCommandFail()) - - result = root.complete_level_1(*completeMock("level_1 ")) - self.assertListEqual(result, [l2]) - - result = root.complete_level_1(*completeMock("level_1 lev")) - self.assertListEqual(result, [l2]) - - result = root.complete_level_1(*completeMock("level_1 level_2 ")) - self.assertListEqual(result, [l3]) - - root.help_level_1() - level_1.help_level_2() - level_2.help_level_3() diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/test_shell_function.py b/ThirdParty/Ert/python/tests/gui/ertshell/test_shell_function.py deleted file mode 100644 index 9b76956a2b..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ertshell/test_shell_function.py +++ /dev/null @@ -1,148 +0,0 @@ -from ert.test import ExtendedTestCase -from ert_gui.shell.libshell import ShellFunction - - -class TestTarget(object): - def __init__(self, name="DefaultTestTarget"): - self.__name = name - self.__failed = False - - def lastCommandFailed(self, message): - print("[%s] Error: %s" % (self.__name, message)) - self.__failed = True - - def didLastCommandFail(self): - return self.__failed - - def resetFailedFlag(self): - self.__failed = False - - def getModelForFunction(self, function_name): - if function_name == "test_function": - return self - else: - return {"key": "value"} - - -def dummyFunction(model, line): - print("[Dummy] Received line: %s" % line) - - -def completeMock(line): - last_space_index = line.rfind(" ") - begin_index = 0 if last_space_index == -1 else last_space_index + 1 - end_index = len(line) - text = line[begin_index:end_index] - - return text, line, begin_index, end_index - - -class ShellFunctionTest(ExtendedTestCase): - - def test_creation(self): - target = TestTarget() - name = "test_function" - shell_function = ShellFunction(name, dummyFunction, None) - shell_function.setParent(target) - - self.assertTrue(hasattr(target, "do_%s" % name)) - self.assertTrue(hasattr(target, "complete_%s" % name)) - self.assertTrue(hasattr(target, "help_tuple_%s" % name)) - - def test_no_parent(self): - target = TestTarget() - name = "test_function" - shell_function = ShellFunction(name, dummyFunction, None) - - self.assertFalse(hasattr(target, "do_%s" % name)) - self.assertFalse(hasattr(target, "complete_%s" % name)) - self.assertFalse(hasattr(target, "help_tuple_%s" % name)) - - with self.assertRaises(AttributeError): - shell_function.doFunction("nonsense") - - - def test_failed_creation(self): - shell_function = ShellFunction("test_function", dummyFunction) - with self.assertRaises(ValueError): - shell_function.setParent(None) - - with self.assertRaises(ValueError): - ShellFunction("test_function", None) - - - def test_duplicate_function(self): - target = TestTarget() - shell_function = ShellFunction("duplicate", dummyFunction) - shell_function.setParent(target) - - with self.assertRaises(ValueError): - duplicate = ShellFunction("duplicate", dummyFunction) - duplicate.setParent(target) - - def test_addition_of_help(self): - target = TestTarget() - - name = "test_function" - help_arguments = "%s args" % name - help_message = "%s msg" % name - shell_function = ShellFunction(name, str, None, help_arguments=help_arguments, help_message=help_message) - shell_function.setParent(target) - - help_function = getattr(target, "help_tuple_%s" % name) - - cmd_name, args, msg = help_function() - self.assertEqual(cmd_name, name) - self.assertEqual(args, help_arguments) - self.assertEqual(msg, help_message) - self.assertFalse(target.didLastCommandFail()) - - def test_function_with_target_as_model(self): - target = TestTarget() - - def checkModel(model, line): - self.assertIsInstance(model, TestTarget) - self.assertEqual(line, "some text to parse") - - shell_function = ShellFunction("test_function", checkModel) - shell_function.setParent(target) - target.do_test_function("some text to parse") - - def test_function_with_custom_model(self): - target = TestTarget() - - def checkModel(model, line): - self.assertIsInstance(model, dict) - self.assertTrue("key" in model) - self.assertEqual(line, "some other text to parse") - - shell_function = ShellFunction("other_test_function", checkModel) - shell_function.setParent(target) - target.do_other_test_function("some other text to parse") - - def test_completion(self): - target = TestTarget() - - def completer(model, text, line, begidx, endidx): - text = text.strip().lower() - - if text == "s": - return ["Large"] - elif text == "l": - return ["Small"] - elif text == "m": - return ["Medium"] - else: - return [] - - shell_function = ShellFunction("test_function", dummyFunction, completer) - shell_function.setParent(target) - - result = target.complete_test_function(*completeMock("s")) - self.assertEqual(result, ["Large"]) - - result = target.complete_test_function(*completeMock("l")) - self.assertEqual(result, ["Small"]) - - result = target.complete_test_function(*completeMock("")) - self.assertEqual(result, []) diff --git a/ThirdParty/Ert/python/tests/gui/ertshell/test_shell_property.py b/ThirdParty/Ert/python/tests/gui/ertshell/test_shell_property.py deleted file mode 100644 index 1925f424b3..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ertshell/test_shell_property.py +++ /dev/null @@ -1,317 +0,0 @@ -from ert.test.extended_testcase import ExtendedTestCase -from ert_gui.shell.libshell import ShellProperty, boolValidator, createListValidator, createFloatValidator - - -class TestModel(object): - STATUSES = ["OK", "Error", "Unknown"] - - def __init__(self, name="TestModel"): - self.__enabled = True - self.__status = "OK" - self.__name = name - self.__description = None - self.__threshold = 0.5 - self.__priority = 1 - - def setEnabled(self, enabled): - self.__enabled = enabled - - def isEnabled(self): - return self.__enabled - - def setStatus(self, status): - self.__status = status - - def status(self): - return self.__status - - def statusCompleter(self, text, line, begidx, endidx): - def test(status, text): - status = status.lower() - text = text.lower() - return status != self.status().lower() and status.startswith(text) - return [status for status in TestModel.STATUSES if test(status, text)] - - def statusValidator(self, value): - if value.lower() == self.status().lower(): - raise ValueError("Value can not be set to current value!") - - for status in TestModel.STATUSES: - if value.lower() == str(status).lower(): - return status - - raise ValueError("Unknown value") - - - def name(self): - return self.__name - - def setDescription(self, description): - self.__description = description - - def description(self): - return self.__description - - @property - def threshold(self): - return self.__threshold - - @threshold.setter - def threshold(self, threshold): - self.__threshold = max(0.0, min(threshold, 1.0)) - - @property - def priority(self): - return self.__priority - - @priority.setter - def priority(self, priority): - try: - priority = int(priority) - self.__priority = priority - except ValueError as error: - self.__priority = 0 - - -class TestTarget(object): - def __init__(self, model, name="DefaultTestTarget"): - self.__model = model - self.__name = name - self.__failed = False - - def lastCommandFailed(self, message): - print("[%s] Error: %s" % (self.__name, message)) - self.__failed = True - - def didLastCommandFail(self): - return self.__failed - - def resetFailedFlag(self): - self.__failed = False - - def getModelForProperty(self, property_name): - return self.__model - - -def completeMock(line): - last_space_index = line.rfind(" ") - begin_index = 0 if last_space_index == -1 else last_space_index + 1 - end_index = len(line) - text = line[begin_index:end_index] - - return text, line, begin_index, end_index - - -class ShellPropertyTest(ExtendedTestCase): - def setUp(self): - self.properties = { - "enabled": ("enabled", TestModel.isEnabled, TestModel.setEnabled), - "status": ("status", TestModel.status, TestModel.setStatus), - "priority": ("priority", TestModel.priority, TestModel.priority), - "name": ("name", TestModel.name, None), - "description": ("description", TestModel.description, TestModel.setDescription), - "threshold": ("threshold", TestModel.threshold, TestModel.threshold) - } - - self.completers = { - "enabled": ["true", "false"], - "status": TestModel.statusCompleter, - "threshold": None, - "priority": [1, 2, 3, 4, 5], - "name": None, - "description": None - } - - self.validators = { - "enabled": boolValidator, - "status": TestModel.statusValidator, - "threshold": createFloatValidator(0.0, 1.0), - "priority": createListValidator(self.completers["priority"]), - "name": None, - "description": None - } - - def test_creation_and_check_existence_of_do_complete_help(self): - target = TestTarget(TestModel()) - for key, (name, getter, setter) in self.properties.items(): - shell_property = ShellProperty(name, getter, setter) - shell_property.setParent(target) - - self.assertTrue(hasattr(target, "do_%s" % name)) - self.assertTrue(hasattr(target, "complete_%s" % name)) - self.assertTrue(hasattr(target, "help_tuple_%s" % name)) - - - def test_addition_of_help(self): - target = TestTarget(TestModel()) - - for key, (name, getter, setter) in self.properties.items(): - help_arguments = "%s args" % name - help_message = "%s msg" % name - shell_property = ShellProperty(name, getter, setter, help_arguments=help_arguments, help_message=help_message) - shell_property.setParent(target) - - help_function = getattr(target, "help_tuple_%s" % name) - - cmd_name, args, msg = help_function() - self.assertEqual(cmd_name, name) - self.assertEqual(args, help_arguments) - self.assertEqual(msg, help_message) - self.assertFalse(target.didLastCommandFail()) - - - def test_no_parent(self): - target = TestTarget(TestModel()) - for key, (name, getter, setter) in self.properties.items(): - shell_property = ShellProperty(name, getter, setter) - - self.assertFalse(hasattr(target, "do_%s" % name)) - self.assertFalse(hasattr(target, "complete_%s" % name)) - self.assertFalse(hasattr(target, "help_tuple_%s" % name)) - - with self.assertRaises(AttributeError): - shell_property.doFunction("") - - def test_duplicate_properties(self): - target = TestTarget(TestModel()) - shell_property = ShellProperty("test", str, None) - shell_property.setParent(target) - - with self.assertRaises(ValueError): - shell_property = ShellProperty("test", str, None) - shell_property.setParent(target) - - - - def test_read_only_property(self): - property_name = "name" - tests = [ - ("", "TestModel", False), - ("new_name", "TestModel", True), - ] - - completions = [ - ("", []), - ] - - self.runPropertyTests(property_name, tests, completions) - - - def test_bool_property(self): - property_name = "enabled" - tests = [ - ("", True, False), - ("False", False, False), - ("g", False, True), - ("yes", True, False), - ] - - completions = [ - ("", self.completers[property_name]), - ("f", ["false"]), - ("t", ["true"]), - ("q", []) - ] - - self.runPropertyTests(property_name, tests, completions) - - def test_string_property(self): - property_name = "description" - tests = [ - ("", None, False), - ("a description", "a description", False), - ("1234", "1234", False), - ] - - completions = [ - ("", []), - ("q", []), - ] - - self.runPropertyTests(property_name, tests, completions) - - - def test_choice_property(self): - property_name = "status" - tests = [ - ("", "OK", False), - ("ERROR", "Error", False), - ("DING", "Error", True), - ] - - completions = [ - ("", ["OK", "Unknown"]), - ("e", []), - ("u", ["Unknown"]), - ("q", []) - ] - - self.runPropertyTests(property_name, tests, completions) - - - def test_float_property(self): - property_name = "threshold" - tests = [ - ("", 0.5, False), - ("0.7", 0.7, False), - ("1.1", 1.0, False), - ("0", 0.0, False), - ("zero", 0.0, True) - ] - - completions = [ - ("", []), - ("1", []), - ("e", []) - ] - - self.runPropertyTests(property_name, tests, completions) - - - def test_int_list_property(self): - property_name = "priority" - tests = [ - ("", 1, False), - ("2", 2, False), - ("6", 2, True), - ] - - completions = [ - ("", self.completers[property_name]), - ("5", [5]), - ("e", []) - ] - - self.runPropertyTests(property_name, tests, completions) - - - def runPropertyTests(self, property_name, tests, completions): - model = TestModel() - target = TestTarget(model) - - name, getter, setter = self.properties[property_name] - shell_property = ShellProperty(name, getter, setter, self.validators[property_name], self.completers[property_name]) - shell_property.setParent(target) - - doFunc = getattr(target, "do_%s" % property_name) - for do_input, expected_value, fail in tests: - doFunc(do_input) - - if isinstance(getter, property): - model_value = getter.__get__(model) - else: - model_value = getter(model) - - self.assertEqual(expected_value, model_value) - - if fail: - self.assertTrue(target.didLastCommandFail()) - else: - self.assertFalse(target.didLastCommandFail()) - - target.resetFailedFlag() - - completeFunc = getattr(target, "complete_%s" % property_name) - for complete_input, expected_value in completions: - choices = completeFunc(*completeMock(complete_input)) - self.assertListEqual(choices, expected_value) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/gui/ide/CMakeLists.txt b/ThirdParty/Ert/python/tests/gui/ide/CMakeLists.txt deleted file mode 100644 index 64135b2519..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - test_bool_argument.py - test_configuration_line.py - test_configuration_line_builder.py - test_configuration_line_definition.py - test_configuration_line_parser.py - test_ert_keywords.py - test_float_argument.py - test_integer_argument.py - test_path_argument.py - test_percent_argument.py - test_proper_name_argument.py - test_proper_name_format_argument.py - test_proper_name_format_string_argument.py - test_range_string_argument.py - test_tokens.py -) - -add_python_package("python.tests.gui.ide" ${PYTHON_INSTALL_PREFIX}/tests/gui/ide "${PYTHON_SOURCES}" True) - -addPythonTest(gui.ide.bool_argument tests.gui.ide.test_bool_argument.BoolArgumentTest) -addPythonTest(gui.ide.integer_argument tests.gui.ide.test_integer_argument.IntegerArgumentTest) -addPythonTest(gui.ide.float_argument tests.gui.ide.test_float_argument.FloatArgumentTest) -addPythonTest(gui.ide.path_argument tests.gui.ide.test_path_argument.PathArgumentTest) -addPythonTest(gui.ide.proper_name_argument tests.gui.ide.test_proper_name_argument.ProperNameArgumentTest) -addPythonTest(gui.ide.proper_name_format_argument tests.gui.ide.test_proper_name_format_argument.ProperNameFormatArgumentTest) -addPythonTest(gui.ide.proper_name_format_string_argument tests.gui.ide.test_proper_name_format_string_argument.ProperNameFormatStringArgumentTest) -addPythonTest(gui.ide.range_string_argument tests.gui.ide.test_range_string_argument.RangeStringArgumentTest) -addPythonTest(gui.ide.test_configuration_line tests.gui.ide.test_configuration_line.ConfigurationLineTest) -addPythonTest(gui.ide.test_configuration_line_builder tests.gui.ide.test_configuration_line_builder.ConfigurationLineBuilderTest) -addPythonTest(gui.ide.test_configuration_line_definition tests.gui.ide.test_configuration_line_definition.ConfigurationLineDefinitionTest) -addPythonTest(gui.ide.test_configuration_line_parser tests.gui.ide.test_configuration_line_parser.ConfigurationLineParserTest) -addPythonTest(gui.ide.ert_keywords tests.gui.ide.test_ert_keywords.ErtKeywordTest) -addPythonTest(gui.ide.tokens tests.gui.ide.test_tokens.TokenTest) - -add_subdirectory(wizards) diff --git a/ThirdParty/Ert/python/tests/gui/ide/__init__.py b/ThirdParty/Ert/python/tests/gui/ide/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_bool_argument.py b/ThirdParty/Ert/python/tests/gui/ide/test_bool_argument.py deleted file mode 100644 index 5f9cdeea62..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_bool_argument.py +++ /dev/null @@ -1,53 +0,0 @@ -from ert_gui.ide.keywords.definitions import BoolArgument -from ert.test import ExtendedTestCase - - -class BoolArgumentTest(ExtendedTestCase): - - - - def test_bool_argument(self): - bool_arg = BoolArgument() - - validation_status = bool_arg.validate("TRUE") - self.assertTrue(validation_status) - self.assertTrue(validation_status.value()) - self.assertEqual(validation_status.message(), "") - - validation_status = bool_arg.validate("FALSE") - self.assertTrue(validation_status) - self.assertFalse(validation_status.value()) - self.assertEqual(validation_status.message(), "") - - validation_status = bool_arg.validate("True") - self.assertTrue(validation_status) - - validation_status = bool_arg.validate("False") - self.assertTrue(validation_status) - - validation_status = bool_arg.validate(" FALSE") - self.assertFalse(validation_status) - self.assertEqual(validation_status.message(), bool_arg.NOT_BOOL) - - self.assertTrue(bool_arg.validate("T")) - self.assertTrue(bool_arg.validate("F")) - self.assertTrue(bool_arg.validate("0")) - self.assertTrue(bool_arg.validate("1")) - self.assertTrue(bool_arg.validate("TrUe")) - self.assertTrue(bool_arg.validate("FaLsE")) - - self.assertFalse(bool_arg.validate("t")) - self.assertFalse(bool_arg.validate("f")) - self.assertFalse(bool_arg.validate("Tr")) - - self.assertTrue(bool_arg.validate("T").value()) - self.assertFalse(bool_arg.validate("F").value()) - - - - - - - - - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line.py b/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line.py deleted file mode 100644 index 8961cb3268..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line.py +++ /dev/null @@ -1,72 +0,0 @@ -from ert_gui.ide.keywords.data import ConfigurationLine, Keyword, Argument -from ert_gui.ide.keywords.definitions import StringArgument -from ert_gui.ide.keywords.definitions.keyword_definition import KeywordDefinition -from ert.test import ExtendedTestCase - - -class ConfigurationLineTest(ExtendedTestCase): - - def test_configuration_line_creation(self): - line = "KEYWORD arg1" - keyword = Keyword(0, 7, line) - argument = Argument(8, 12, line) - cl = ConfigurationLine(keyword=keyword, - arguments=[argument], - documentation_link="help/link", - group="group", - required=True) - - self.assertEqual(cl.keyword(), keyword) - self.assertEqual(cl.arguments()[0], argument) - - self.assertEqual(cl.documentationLink(), "help/link") - self.assertEqual(cl.group(), "group") - self.assertTrue(cl.isRequired()) - - self.assertFalse(cl.validationStatusForToken(keyword)) - self.assertFalse(cl.validationStatusForToken(argument)) - - - - def test_configuration_line(self): - - keyword_def = KeywordDefinition("KEYWORD") - arg1_def = StringArgument() - - line = "KEYWORD string 2" - keyword = Keyword(0, 7, line) - self.assertEqual(keyword.value(), "KEYWORD") - - keyword.setKeywordDefinition(keyword_def) - - arg1 = Argument(8, 14, line) - self.assertEqual(arg1.value(), "string") - arg1.setArgumentDefinition(arg1_def) - - arg2 = Argument(15, 16, line) - self.assertEqual(arg2.value(), "2") - - - cl = ConfigurationLine(keyword=keyword, - arguments=[arg1, arg2], - documentation_link="help", - group="test_group", - required=True) - - self.assertTrue(cl.keyword().hasKeywordDefinition()) - self.assertEqual(cl.keyword().keywordDefinition(), keyword_def) - - self.assertEqual(len(cl.arguments()), 2) - - self.assertEqual(cl.arguments()[0], arg1) - self.assertTrue(cl.arguments()[0].hasArgumentDefinition()) - self.assertEqual(cl.arguments()[0].argumentDefinition(), arg1_def) - - self.assertEqual(cl.arguments()[1], arg2) - self.assertFalse(cl.arguments()[1].hasArgumentDefinition()) - self.assertIsNone(cl.arguments()[1].argumentDefinition()) - - self.assertFalse(cl.validationStatusForToken(keyword)) - self.assertTrue(cl.validationStatusForToken(arg1)) - self.assertFalse(cl.validationStatusForToken(arg2)) - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_builder.py b/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_builder.py deleted file mode 100644 index bf052ea79d..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_builder.py +++ /dev/null @@ -1,130 +0,0 @@ -from ert_gui.ide.keywords import ErtKeywords -from ert_gui.ide.keywords.configuration_line_builder import ConfigurationLineBuilder -from ert_gui.ide.keywords.definitions import ArgumentDefinition -from ert_gui.ide.keywords.data.configuration_line import ConfigurationLine -from ert.test import ExtendedTestCase - - -class ConfigurationLineBuilderTest(ExtendedTestCase): - - - - def test_num_realizations(self): - keywords = ErtKeywords() - clb = ConfigurationLineBuilder(keywords) - - test_line = "NUM_REALIZATIONS 25" - - clb.processLine(test_line) - - self.assertTrue(clb.hasConfigurationLine()) - self.assertFalse(clb.hasComment()) - self.assertEqual(clb.commentIndex(), -1) - - config_line = clb.configurationLine() - - self.assertEqual(config_line.keyword().value(), "NUM_REALIZATIONS") - self.assertEqual(config_line.keyword().keywordDefinition(), keywords["NUM_REALIZATIONS"].keywordDefinition()) - self.assertEqual(config_line.arguments()[0].value(), "25") - - def test_num_realizations_no_argument(self): - keywords = ErtKeywords() - clb = ConfigurationLineBuilder(keywords) - - test_line = "NUM_REALIZATIONS" - - clb.processLine(test_line) - - self.assertTrue(clb.hasConfigurationLine()) - - config_line = clb.configurationLine() - - self.assertEqual(config_line.keyword().value(), "NUM_REALIZATIONS") - self.assertEqual(config_line.keyword().keywordDefinition(), keywords["NUM_REALIZATIONS"].keywordDefinition()) - - arguments = config_line.arguments() - self.assertEqual(len(arguments), 1) - - self.assertFalse(config_line.validationStatusForToken(config_line.keyword())) - self.assertFalse(config_line.validationStatusForToken(arguments[0])) - - - def test_unknown_keyword_with_comment(self): - keywords = ErtKeywords() - clb = ConfigurationLineBuilder(keywords) - - test_line = "KEYWORD nothing --comment" - - clb.processLine(test_line) - - self.assertTrue(clb.hasConfigurationLine()) - - config_line = clb.configurationLine() - keyword = config_line.keyword() - self.assertFalse(config_line.validationStatusForToken(keyword)) - message = ConfigurationLine.UNKNOWN_KEYWORD + '\n' + ConfigurationLine.ARGUMENT_ERROR + '\n' + ConfigurationLine.ARGUMENT_NOT_EXPECTED - self.assertEqual(config_line.validationStatusForToken(keyword).message(), message) - - self.assertEqual(keyword.value(), "KEYWORD") - arguments = config_line.arguments() - - self.assertEqual(arguments[0].value(), "nothing") - self.assertIsNone(keyword.keywordDefinition()) - - self.assertTrue(clb.hasComment()) - self.assertEqual(clb.commentIndex(), 16) - - self.assertFalse(config_line.validationStatusForToken(arguments[0])) - self.assertEqual(config_line.validationStatusForToken(arguments[0]).message(), ConfigurationLine.ARGUMENT_NOT_EXPECTED) - - - def test_queue_option_keyword(self): - keywords = ErtKeywords() - clb = ConfigurationLineBuilder(keywords) - - test_line = "QUEUE_OPTION LSF LSF_BJOBS_CMD STRING AND STRING" - - clb.processLine(test_line) - config_line = clb.configurationLine() - - arguments = config_line.arguments() - - self.assertEqual(len(arguments), 3) - self.assertEqual(arguments[0].value(), "LSF") - self.assertEqual(arguments[1].value(), "LSF_BJOBS_CMD") - self.assertEqual(arguments[2].value(), "STRING AND STRING") - - print(config_line.validationStatusForToken(config_line.keyword())) - - self.assertTrue(config_line.validationStatusForToken(arguments[0])) - self.assertTrue(config_line.validationStatusForToken(arguments[1])) - self.assertTrue(config_line.validationStatusForToken(arguments[2])) - - - def test_queue_option_keyword_too_few_arguments(self): - keywords = ErtKeywords() - clb = ConfigurationLineBuilder(keywords) - - test_line = "QUEUE_OPTION LSF LSF_BJOBS_CMD" - - clb.processLine(test_line) - config_line = clb.configurationLine() - - arguments = config_line.arguments() - - self.assertEqual(len(arguments), 3) - - self.assertEqual(arguments[0].value(), "LSF") - self.assertEqual(arguments[1].value(), "LSF_BJOBS_CMD") - self.assertEqual(arguments[2].value(), "") - - self.assertFalse(config_line.validationStatusForToken(config_line.keyword())) - - self.assertTrue(config_line.validationStatusForToken(arguments[0])) - self.assertTrue(config_line.validationStatusForToken(arguments[1])) - self.assertFalse(config_line.validationStatusForToken(arguments[2])) - - self.assertEqual(config_line.validationStatusForToken(arguments[2]).message(), ArgumentDefinition.MISSING_ARGUMENT) - - - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_definition.py b/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_definition.py deleted file mode 100644 index bcccb60472..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_definition.py +++ /dev/null @@ -1,45 +0,0 @@ -from ert_gui.ide.keywords.definitions import ArgumentDefinition, KeywordDefinition, ConfigurationLineDefinition, IntegerArgument -from ert.test import ExtendedTestCase - - - - - -class ConfigurationLineDefinitionTest(ExtendedTestCase): - - def test_keyword_definition(self): - keyword = KeywordDefinition("KEYWORD") - self.assertEqual(keyword.name(), "KEYWORD") - - - def test_argument_definition(self): - arg_def = ArgumentDefinition(optional=True, built_in=True, rest_of_line=True) - - self.assertTrue(arg_def.isBuiltIn()) - self.assertTrue(arg_def.isOptional()) - self.assertTrue(arg_def.consumeRestOfLine()) - - - def test_configuration_line_definition(self): - - cld = ConfigurationLineDefinition(keyword=KeywordDefinition("KEYWORD"), - arguments=[IntegerArgument(from_value=1)], - documentation_link="help/path", - required=True, - group="Group") - - self.assertTrue(cld.isRequired()) - self.assertEqual(cld.documentationLink(), "help/path") - - keyword_definition = cld.keywordDefinition() - self.assertIsInstance(keyword_definition, KeywordDefinition) - self.assertEqual(keyword_definition.name(), "KEYWORD") - - argument_definitions = cld.argumentDefinitions() - self.assertIsInstance(argument_definitions, list) - self.assertEqual(len(argument_definitions), 1) - self.assertIsInstance(argument_definitions[0], IntegerArgument) - - - self.assertEqual(cld.group(), "Group") - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_parser.py b/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_parser.py deleted file mode 100644 index e02d154cd6..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_configuration_line_parser.py +++ /dev/null @@ -1,98 +0,0 @@ -from ert_gui.ide.keywords import ConfigurationLineParser -from ert_gui.ide.keywords.data import Argument -from ert.test import ExtendedTestCase - - -class ConfigurationLineParserTest(ExtendedTestCase): - - - def test_comments(self): - keyword_parser = ConfigurationLineParser() - - test_line = "-- comment" - keyword_parser.parseLine(test_line) - - self.assertTrue(keyword_parser.hasComment()) - self.assertEqual(keyword_parser.commentIndex(), 0) - self.assertFalse(keyword_parser.hasKeyword()) - self.assertIsNone(keyword_parser.keyword()) - self.assertEqual(keyword_parser.uncommentedText(), "") - - - test_line = " -- comment" - keyword_parser.parseLine(test_line) - - self.assertTrue(keyword_parser.hasComment()) - self.assertEqual(keyword_parser.commentIndex(), 5) - self.assertFalse(keyword_parser.hasKeyword()) - self.assertIsNone(keyword_parser.keyword()) - self.assertEqual(keyword_parser.uncommentedText(), " ") - - test_line = "NUM_REALIZATIONS-- comment" - keyword_parser.parseLine(test_line) - - self.assertTrue(keyword_parser.hasComment()) - self.assertEqual(keyword_parser.commentIndex(), 16) - self.assertTrue(keyword_parser.hasKeyword()) - self.assertEqual(keyword_parser.keyword().value(), "NUM_REALIZATIONS") - self.assertEqual(keyword_parser.uncommentedText(), "NUM_REALIZATIONS") - - test_line = "NUM_REALIZATIONS -- comment" - keyword_parser.parseLine(test_line) - - self.assertTrue(keyword_parser.hasComment()) - self.assertEqual(keyword_parser.commentIndex(), 17) - self.assertTrue(keyword_parser.hasKeyword()) - self.assertEqual(keyword_parser.keyword().value(), "NUM_REALIZATIONS") - self.assertEqual(keyword_parser.uncommentedText(), "NUM_REALIZATIONS ") - - - def test_argument_text(self): - keyword_parser = ConfigurationLineParser() - - test_line = "NUM_REALIZATIONS 25" - keyword_parser.parseLine(test_line) - - self.assertFalse(keyword_parser.hasComment()) - self.assertEqual(keyword_parser.commentIndex(), -1) - self.assertTrue(keyword_parser.hasKeyword()) - self.assertEqual(keyword_parser.keyword().value(), "NUM_REALIZATIONS") - self.assertEqual(keyword_parser.uncommentedText(), "NUM_REALIZATIONS 25") - self.assertEqual(keyword_parser.argumentsText(), " 25") - - - test_line = "NUM_REALIZATIONS 25--comment" - keyword_parser.parseLine(test_line) - - self.assertTrue(keyword_parser.hasComment()) - self.assertEqual(keyword_parser.commentIndex(), 19) - self.assertTrue(keyword_parser.hasKeyword()) - self.assertEqual(keyword_parser.keyword().value(), "NUM_REALIZATIONS") - self.assertEqual(keyword_parser.uncommentedText(), "NUM_REALIZATIONS 25") - self.assertEqual(keyword_parser.argumentsText(), " 25") - - test_line = "NUM_REALIZATIONS 25 something_else" - keyword_parser.parseLine(test_line) - - self.assertTrue(keyword_parser.hasKeyword()) - self.assertEqual(keyword_parser.keyword().value(), "NUM_REALIZATIONS") - self.assertEqual(keyword_parser.uncommentedText(), "NUM_REALIZATIONS 25 something_else") - self.assertEqual(keyword_parser.argumentsText(), " 25 something_else") - - - - - def test_argument_list(self): - keyword_parser = ConfigurationLineParser() - - test_line = "KEYWORD arg1 arg2" - keyword_parser.parseLine(test_line) - - keyword = keyword_parser.keyword() - self.assertEqual(keyword.value(), "KEYWORD") - - arguments = keyword_parser.arguments() - self.assertEqual(arguments[0].value(), "arg1") - self.assertEqual(arguments[1].value(), "arg2") - - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_ert_keywords.py b/ThirdParty/Ert/python/tests/gui/ide/test_ert_keywords.py deleted file mode 100644 index fc1b93588a..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_ert_keywords.py +++ /dev/null @@ -1,186 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument, StringArgument, BoolArgument, PathArgument, FloatArgument , PercentArgument -from ert_gui.ide.keywords import ErtKeywords -from ert_gui.ide.keywords.definitions.proper_name_argument import ProperNameArgument -from ert_gui.ide.keywords.definitions.proper_name_format_argument import ProperNameFormatArgument -from ert.test import ExtendedTestCase - - -class ErtKeywordTest(ExtendedTestCase): - - def setUp(self): - self.keywords = ErtKeywords() - - def keywordTest(self, name, argument_types, documentation_link, group, required=False): - self.assertTrue(name in self.keywords) - - cld = self.keywords[name] - - self.assertEqual(cld.keywordDefinition().name(), name) - self.assertEqual(cld.group(), group) - self.assertEqual(cld.documentationLink(), documentation_link) - self.assertEqual(cld.isRequired(), required) - - arguments = cld.argumentDefinitions() - - self.assertEqual(len(arguments), len(argument_types)) - - for index in range(len(arguments)): - self.assertIsInstance(arguments[index], argument_types[index]) - - - def test_eclipse_keywords(self): - self.keywordTest("DATA_FILE", [PathArgument], "keywords/data_file", "Eclipse", True) - self.keywordTest("EQUIL_INIT_FILE", [PathArgument], "keywords/equil_init_file", "Eclipse") - self.keywordTest("ECLBASE", [StringArgument], "keywords/eclbase", "Eclipse", True) - self.keywordTest("JOBNAME", [StringArgument], "keywords/job_name", "Eclipse", True) - self.keywordTest("GRID", [PathArgument], "keywords/grid", "Eclipse", True) - self.keywordTest("INIT_SECTION", [PathArgument], "keywords/init_section", "Eclipse", True) - self.keywordTest("SCHEDULE_FILE", [PathArgument], "keywords/schedule_file", "Eclipse", True) - self.keywordTest("DATA_KW", [StringArgument, StringArgument], "keywords/data_kw", "Eclipse") - self.keywordTest("IGNORE_SCHEDULE", [BoolArgument], "keywords/ignore_schedule", "Eclipse") - - - def test_ensemble_keywords(self): - self.keywordTest("NUM_REALIZATIONS", [IntegerArgument], "keywords/num_realizations", "Ensemble", True) - self.keywordTest("END_DATE", [StringArgument], "keywords/end_date", "Ensemble") - self.keywordTest("ENSPATH", [PathArgument], "keywords/enspath", "Ensemble") - self.keywordTest("SELECT_CASE", [StringArgument], "keywords/select_case", "Ensemble") - self.keywordTest("HISTORY_SOURCE", [StringArgument], "keywords/history_source", "Ensemble") - self.keywordTest("REFCASE", [PathArgument], "keywords/refcase", "Ensemble") - self.keywordTest("REFCASE_LIST", [StringArgument], "keywords/refcase_list", "Ensemble") - self.keywordTest("INCLUDE", [PathArgument], "keywords/include", "Ensemble") - self.keywordTest("OBS_CONFIG", [PathArgument], "keywords/obs_config", "Ensemble") - self.keywordTest("RESULT_PATH", [PathArgument], "keywords/result_path", "Ensemble") - self.keywordTest("LICENSE_PATH", [PathArgument], "keywords/license_path", "Ensemble") - self.keywordTest("LOCAL_CONFIG", [StringArgument], "keywords/local_config", "Ensemble") - - def test_run_keywords(self): - self.keywordTest("INSTALL_JOB", [StringArgument, PathArgument], "keywords/install_job", "Run") - self.keywordTest("DELETE_RUNPATH", [StringArgument], "keywords/delete_runpath", "Run") - self.keywordTest("KEEP_RUNPATH", [StringArgument], "keywords/keep_runpath", "Run") - self.keywordTest("RUNPATH", [PathArgument], "keywords/runpath", "Run") - self.keywordTest("RUNPATH_FILE", [PathArgument], "keywords/runpath_file", "Run") - self.keywordTest("FORWARD_MODEL", [StringArgument], "keywords/forward_model", "Run") - self.keywordTest("JOB_SCRIPT", [PathArgument], "keywords/job_script", "Run") - self.keywordTest("RUN_TEMPLATE", [PathArgument, StringArgument], "keywords/run_template", "Run") - self.keywordTest("LOG_LEVEL", [IntegerArgument], "keywords/log_level", "Run") - self.keywordTest("LOG_FILE", [PathArgument], "keywords/log_file", "Run") - self.keywordTest("MAX_SUBMIT", [IntegerArgument], "keywords/max_submit", "Run") - self.keywordTest("MAX_RESAMPLE", [IntegerArgument], "keywords/max_resample", "Run") - self.keywordTest("PRE_CLEAR_RUNPATH", [BoolArgument], "keywords/pre_clear_runpath", "Run") - - - - def test_control_simulations_keywords(self): - self.keywordTest("MAX_RUNTIME", [IntegerArgument], "keywords/max_runtime", "Simulation Control") - self.keywordTest("MIN_REALIZATIONS", [IntegerArgument,PercentArgument], "keywords/min_realizations", "Simulation Control") - self.keywordTest("STOP_LONG_RUNNING", [BoolArgument], "keywords/stop_long_running", "Simulation Control") - - def test_parametrization_keywords(self): - self.keywordTest("FIELD", [StringArgument,StringArgument,StringArgument], "keywords/field", "Parametrization") - self.keywordTest("GEN_DATA", [StringArgument,StringArgument,StringArgument], "keywords/gen_data", "Parametrization") - self.keywordTest("GEN_KW", [StringArgument,StringArgument,StringArgument], "keywords/gen_kw", "Parametrization") - self.keywordTest("GEN_KW_TAG_FORMAT", [StringArgument], "keywords/gen_kw_tag_format", "Parametrization") - self.keywordTest("GEN_PARAM", [StringArgument,StringArgument,StringArgument], "keywords/gen_param", "Parametrization") - self.keywordTest("SUMMARY", [StringArgument], "keywords/summary", "Parametrization") - self.keywordTest("DBASE_TYPE", [StringArgument], "keywords/dbase_type", "Parametrization") - self.keywordTest("STORE_SEED", [StringArgument], "keywords/store_seed", "Parametrization") - self.keywordTest("LOAD_SEED", [StringArgument], "keywords/load_seed", "Parametrization") - self.keywordTest("SURFACE", [StringArgument], "keywords/surface", "Parametrization") - - - def test_enkf_control_keywords(self): - self.keywordTest("ENKF_ALPHA", [FloatArgument], "keywords/enkf_alpha", "Enkf Control") - self.keywordTest("ENKF_BOOTSTRAP", [BoolArgument], "keywords/enkf_bootstrap", "Enkf Control") - self.keywordTest("ENKF_CV_FOLDS", [IntegerArgument], "keywords/enkf_cv_folds", "Enkf Control") - self.keywordTest("ENKF_FORCE_NCOMP", [BoolArgument], "keywords/enkf_force_ncomp", "Enkf Control") - self.keywordTest("ENKF_LOCAL_CV", [BoolArgument], "keywords/enkf_local_cv", "Enkf Control") - self.keywordTest("ENKF_PEN_PRESS", [BoolArgument], "keywords/enkf_pen_press", "Enkf Control") - self.keywordTest("ENKF_MODE", [StringArgument], "keywords/enkf_mode", "Enkf Control") - self.keywordTest("ENKF_MERGE_OBSERVATIONS", [BoolArgument], "keywords/enkf_merge_observations", "Enkf Control") - self.keywordTest("ENKF_NCOMP", [IntegerArgument], "keywords/enkf_ncomp", "Enkf Control") - self.keywordTest("ENKF_RERUN", [BoolArgument], "keywords/enkf_rerun", "Enkf Control") - self.keywordTest("RERUN_START", [IntegerArgument], "keywords/rerun_start", "Enkf Control") - self.keywordTest("ENKF_SCALING", [BoolArgument], "keywords/enkf_scaling", "Enkf Control") - self.keywordTest("ENKF_TRUNCATION", [FloatArgument], "keywords/enkf_truncation", "Enkf Control") - self.keywordTest("UPDATE_LOG_PATH", [PathArgument], "keywords/update_log_path", "Enkf Control") - self.keywordTest("UPDATE_RESULTS", [BoolArgument], "keywords/update_results", "Enkf Control") - self.keywordTest("ENKF_CROSS_VALIDATION", [StringArgument], "keywords/enkf_cross_validation", "Enkf Control") - self.keywordTest("ENKF_KERNEL_REGRESSION", [StringArgument], "keywords/enkf_kernel_regression", "Enkf Control") - self.keywordTest("ENKF_KERNEL_FUNCTION", [StringArgument], "keywords/enkf_kernel_function", "Enkf Control") - self.keywordTest("ENKF_KERNEL_PARAM", [StringArgument], "keywords/enkf_kernel_param", "Enkf Control") - self.keywordTest("ENKF_SCHED_FILE", [PathArgument], "keywords/enkf_sched_file", "Enkf Control") - self.keywordTest("CASE_TABLE", [StringArgument], "keywords/case_table", "Enkf Control") - self.keywordTest("CONTAINER", [StringArgument], "keywords/container", "Enkf Control") - - - - def test_analysis_module_keywords(self): - self.keywordTest("ANALYSIS_LOAD", [StringArgument,StringArgument], "keywords/analysis_load", "Analysis Module") - self.keywordTest("ANALYSIS_SELECT", [StringArgument], "keywords/analysis_select", "Analysis Module") - self.keywordTest("ANALYSIS_SET_VAR", [StringArgument, StringArgument, StringArgument], "keywords/analysis_set_var", "Analysis Module") - self.keywordTest("ANALYSIS_COPY", [StringArgument, StringArgument], "keywords/analysis_copy", "Analysis Module") - self.keywordTest("ITER_CASE", [ProperNameFormatArgument], "keywords/iter_case", "Analysis Module") - self.keywordTest("ITER_COUNT", [IntegerArgument], "keywords/iter_count", "Analysis Module") - self.keywordTest("STD_CUTOFF", [FloatArgument], "keywords/std_cutoff", "Analysis Module") - self.keywordTest("SINGLE_NODE_UPDATE", [BoolArgument], "keywords/single_node_update", "Analysis Module") - - - def test_advanced_keywords(self): - self.keywordTest("ADD_FIXED_LENGTH_SCHEDULE_KW", [StringArgument, StringArgument], "keywords/add_fixed_length_schedule_kw", "Advanced") - self.keywordTest("ADD_STATIC_KW", [StringArgument, StringArgument], "keywords/add_static_kw", "Advanced") - self.keywordTest("DEFINE", [ProperNameArgument, StringArgument], "keywords/define", "Advanced") - self.keywordTest("SCHEDULE_PREDICTION_FILE", [PathArgument], "keywords/schedule_prediction_file", "Advanced") - - def test_queue_system_keywords(self): - self.keywordTest("QUEUE_SYSTEM", [StringArgument], "keywords/queue_system", "Queue System") - self.keywordTest("QUEUE_OPTION", [StringArgument, StringArgument, StringArgument], "keywords/queue_option", "Queue System") - self.keywordTest("LSF_SERVER", [StringArgument], "keywords/lsf_server", "Queue System") - self.keywordTest("LSF_QUEUE", [StringArgument], "keywords/lsf_queue", "Queue System") - self.keywordTest("LSF_RESOURCES", [StringArgument], "keywords/lsf_resources", "Queue System") - self.keywordTest("MAX_RUNNING_LSF", [IntegerArgument], "keywords/max_running_lsf", "Queue System") - self.keywordTest("TORQUE_QUEUE", [StringArgument], "keywords/torque_queue", "Queue System") - self.keywordTest("MAX_RUNNING_LOCAL", [IntegerArgument], "keywords/max_running_local", "Queue System") - self.keywordTest("RSH_HOST", [StringArgument, StringArgument], "keywords/rsh_host", "Queue System") - self.keywordTest("RSH_COMMAND", [PathArgument], "keywords/rsh_command", "Queue System") - self.keywordTest("MAX_RUNNING_RSH", [IntegerArgument], "keywords/max_running_rsh", "Queue System") - self.keywordTest("HOST_TYPE", [StringArgument], "keywords/host_type", "Queue System") - - - def test_plot_keywords(self): - self.keywordTest("IMAGE_VIEWER", [PathArgument], "keywords/image_viewer", "Plot") - self.keywordTest("IMAGE_TYPE", [StringArgument], "keywords/image_type", "Plot") - self.keywordTest("PLOT_DRIVER", [StringArgument], "keywords/plot_driver", "Plot") - self.keywordTest("PLOT_ERRORBAR", [BoolArgument], "keywords/plot_errorbar", "Plot") - self.keywordTest("PLOT_ERRORBAR_MAX", [IntegerArgument], "keywords/plot_errorbar_max", "Plot") - self.keywordTest("PLOT_WIDTH", [IntegerArgument], "keywords/plot_width", "Plot") - self.keywordTest("PLOT_HEIGHT", [IntegerArgument], "keywords/plot_height", "Plot") - self.keywordTest("PLOT_REFCASE", [BoolArgument], "keywords/plot_refcase", "Plot") - self.keywordTest("PLOT_REFCASE_LIST", [StringArgument], "keywords/plot_refcase_list", "Plot") - self.keywordTest("PLOT_PATH", [PathArgument], "keywords/plot_path", "Plot") - self.keywordTest("RFT_CONFIG", [PathArgument], "keywords/rft_config", "Plot") - self.keywordTest("RFTPATH", [PathArgument], "keywords/rftpath", "Plot") - - def test_workflow_keywords(self): - self.keywordTest("INTERNAL", [BoolArgument], "keywords/internal", "Workflow Jobs") - self.keywordTest("FUNCTION", [StringArgument], "keywords/function", "Workflow Jobs") - self.keywordTest("MODULE", [PathArgument], "keywords/module", "Workflow Jobs") - self.keywordTest("EXECUTABLE", [PathArgument], "keywords/executable", "Workflow Jobs") - self.keywordTest("MIN_ARG", [IntegerArgument], "keywords/min_arg", "Workflow Jobs") - self.keywordTest("MAX_ARG", [IntegerArgument], "keywords/max_arg", "Workflow Jobs") - self.keywordTest("ARG_TYPE", [StringArgument], "keywords/arg_type", "Workflow Jobs") - self.keywordTest("LOAD_WORKFLOW_JOB", [StringArgument], "keywords/load_workflow_job", "Workflow Jobs") - self.keywordTest("WORKFLOW_JOB_DIRECTORY", [PathArgument], "keywords/workflow_job_directory", "Workflow Jobs") - self.keywordTest("LOAD_WORKFLOW", [PathArgument, StringArgument], "keywords/load_workflow", "Workflow Jobs") - - def test_qc_keywords(self): - self.keywordTest("QC_WORKFLOW", [StringArgument], "keywords/qc_workflow", "Quality Check") - self.keywordTest("QC_PATH", [PathArgument], "keywords/qc_path", "Quality Check") - - def test_unix_environment_keywords(self): - self.keywordTest("SETENV", [StringArgument, StringArgument], "keywords/setenv", "Unix") - self.keywordTest("UMASK", [IntegerArgument], "keywords/umask", "Unix") - self.keywordTest("UPDATE_PATH", [StringArgument,PathArgument], "keywords/update_path", "Unix") - - - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_float_argument.py b/ThirdParty/Ert/python/tests/gui/ide/test_float_argument.py deleted file mode 100644 index 376ea3e87d..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_float_argument.py +++ /dev/null @@ -1,99 +0,0 @@ -from ert_gui.ide.keywords.definitions import FloatArgument -from ert.test import ExtendedTestCase - - -class FloatArgumentTest(ExtendedTestCase): - - def test_default_float_argument(self): - f = FloatArgument() - - validation_status = f.validate("45.0") - - self.assertTrue(validation_status) - self.assertEqual(validation_status.value(), 45.0) - self.assertEqual(validation_status.message(), "") - - - validation_status = f.validate("-45.0") - - self.assertTrue(validation_status) - self.assertEqual(validation_status.value(), -45) - - - validation_status = f.validate("45.0 ") - - self.assertFalse(validation_status) - self.assertNotEqual(validation_status.message(), "") - self.assertIsNone(validation_status.value()) - - validation_status = f.validate("gx") - - self.assertFalse(validation_status) - self.assertNotEqual(validation_status.message(), "") - - - def test_float_range_argument_from(self): - from_value = 9.9 - f = FloatArgument(from_value=from_value) - - validation_status = f.validate("%f" % from_value) - self.assertTrue(validation_status) - - value = 9.85 - validation_status = f.validate("%f" % value) - self.assertFalse(validation_status) - - range_string = "%f <= %f" % (from_value, value) - self.assertEqual(validation_status.message(), FloatArgument.NOT_IN_RANGE % range_string) - - - def test_float_range_argument_to(self): - to_value = 9.9 - f = FloatArgument(to_value=to_value) - - validation_status = f.validate("%f" % to_value) - self.assertTrue(validation_status) - - value = 9.91 - validation_status = f.validate("%f" % value) - self.assertFalse(validation_status) - - range_string = "%f <= %f" % (value, to_value) - self.assertEqual(validation_status.message(), FloatArgument.NOT_IN_RANGE % range_string) - - - def test_float_range_argument(self): - from_value = 1.0 - to_value = 1.1 - f = FloatArgument(from_value=from_value, to_value=to_value) - - validation_status = f.validate("%f" % to_value) - self.assertTrue(validation_status) - - validation_status = f.validate("%f" % from_value) - self.assertTrue(validation_status) - - validation_status = f.validate("%f" % 1.05) - self.assertTrue(validation_status) - - value = 0.9 - validation_status = f.validate("%f" % value) - self.assertFalse(validation_status) - - range_string = "%f <= %f <= %f" % (from_value, value, to_value) - self.assertEqual(validation_status.message(), FloatArgument.NOT_IN_RANGE % range_string) - - value = 1.15 - validation_status = f.validate("%f" % value) - self.assertFalse(validation_status) - - range_string = "%f <= %f <= %f" % (from_value, value, to_value) - self.assertEqual(validation_status.message(), FloatArgument.NOT_IN_RANGE % range_string) - - - - - - - - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_integer_argument.py b/ThirdParty/Ert/python/tests/gui/ide/test_integer_argument.py deleted file mode 100644 index e40597416c..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_integer_argument.py +++ /dev/null @@ -1,99 +0,0 @@ -from ert_gui.ide.keywords.definitions import IntegerArgument -from ert.test import ExtendedTestCase - - -class IntegerArgumentTest(ExtendedTestCase): - - def test_default_integer_argument(self): - integer = IntegerArgument() - - validation_status = integer.validate("45") - - self.assertTrue(validation_status) - self.assertEqual(validation_status.value(), 45) - self.assertEqual(validation_status.message(), "") - - - validation_status = integer.validate("-45") - - self.assertTrue(validation_status) - self.assertEqual(validation_status.value(), -45) - - - validation_status = integer.validate("45 ") - - self.assertFalse(validation_status) - self.assertNotEqual(validation_status.message(), "") - self.assertIsNone(validation_status.value()) - - validation_status = integer.validate("gx") - - self.assertFalse(validation_status) - self.assertNotEqual(validation_status.message(), "") - - - def test_integer_range_argument_from(self): - from_value = 99 - integer = IntegerArgument(from_value=from_value) - - validation_status = integer.validate("%d" % from_value) - self.assertTrue(validation_status) - - value = 98 - validation_status = integer.validate("%d" % value) - self.assertFalse(validation_status) - - range_string = "%d <= %d" % (from_value, value) - self.assertEqual(validation_status.message(), IntegerArgument.NOT_IN_RANGE % range_string) - - - def test_integer_range_argument_to(self): - to_value = 99 - integer = IntegerArgument(to_value=to_value) - - validation_status = integer.validate("%d" % to_value) - self.assertTrue(validation_status) - - value = 100 - validation_status = integer.validate("%d" % value) - self.assertFalse(validation_status) - - range_string = "%d <= %d" % (value, to_value) - self.assertEqual(validation_status.message(), IntegerArgument.NOT_IN_RANGE % range_string) - - - def test_integer_range_argument(self): - from_value = 10 - to_value = 20 - integer = IntegerArgument(from_value=from_value, to_value=to_value) - - validation_status = integer.validate("%d" % to_value) - self.assertTrue(validation_status) - - validation_status = integer.validate("%d" % from_value) - self.assertTrue(validation_status) - - validation_status = integer.validate("%d" % 15) - self.assertTrue(validation_status) - - value = 9 - validation_status = integer.validate("%d" % value) - self.assertFalse(validation_status) - - range_string = "%d <= %d <= %d" % (from_value, value, to_value) - self.assertEqual(validation_status.message(), IntegerArgument.NOT_IN_RANGE % range_string) - - value = 21 - validation_status = integer.validate("%d" % value) - self.assertFalse(validation_status) - - range_string = "%d <= %d <= %d" % (from_value, value, to_value) - self.assertEqual(validation_status.message(), IntegerArgument.NOT_IN_RANGE % range_string) - - - - - - - - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_path_argument.py b/ThirdParty/Ert/python/tests/gui/ide/test_path_argument.py deleted file mode 100644 index 1bac902d4e..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_path_argument.py +++ /dev/null @@ -1,15 +0,0 @@ -from ert_gui.ide.keywords.definitions import PathArgument -from ert.test import ExtendedTestCase - - -class PathArgumentTest(ExtendedTestCase): - - def test_path_argument(self): - - path_arg = PathArgument() - - validation_status = path_arg.validate("/non_existing_file") - self.assertFalse(validation_status) - - validation_status = path_arg.validate(__file__) - self.assertTrue(validation_status) diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_percent_argument.py b/ThirdParty/Ert/python/tests/gui/ide/test_percent_argument.py deleted file mode 100644 index d7afffc7c0..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_percent_argument.py +++ /dev/null @@ -1,99 +0,0 @@ -from ert_gui.ide.keywords.definitions import PercentArgument -from ert.test import ExtendedTestCase - - -class PercentArgumentTest(ExtendedTestCase): - - def test_default_percent_argument(self): - percent = PercentArgument() - - validation_status = percent.validate("45%") - - self.assertTrue(validation_status) - self.assertEqual(validation_status.value(), 0.45) - self.assertEqual(validation_status.message(), "") - - - validation_status = percent.validate("-45%") - - self.assertTrue(validation_status) - self.assertEqual(validation_status.value(), -0.45) - - - validation_status = percent.validate("45") - - self.assertFalse(validation_status) - self.assertNotEqual(validation_status.message(), "") - self.assertIsNone(validation_status.value()) - - validation_status = percent.validate("gx") - - self.assertFalse(validation_status) - self.assertNotEqual(validation_status.message(), "") - - - def test_percent_range_argument_from(self): - from_value = 99 - percent = PercentArgument(from_value=from_value) - - validation_status = percent.validate("%d%%" % from_value) - self.assertTrue(validation_status) - - value = 98 - validation_status = percent.validate("%d%%" % value) - self.assertFalse(validation_status) - - range_string = "%g %% <= %g %%" % (from_value, value) - self.assertEqual(validation_status.message(), PercentArgument.NOT_IN_RANGE % range_string) - - - def test_percent_range_argument_to(self): - to_value = 99 - percent = PercentArgument(to_value=to_value) - - validation_status = percent.validate("%d%%" % to_value) - self.assertTrue(validation_status) - - value = 100 - validation_status = percent.validate("%d%%" % value) - self.assertFalse(validation_status) - - range_string = "%g%% <= %g%%" % (value, to_value) - self.assertEqual(validation_status.message(), PercentArgument.NOT_IN_RANGE % range_string) - - - def test_percent_range_argument(self): - from_value = 10 - to_value = 20 - percent = PercentArgument(from_value=from_value, to_value=to_value) - - validation_status = percent.validate("%d%%" % to_value) - self.assertTrue(validation_status) - - validation_status = percent.validate("%d%%" % from_value) - self.assertTrue(validation_status) - - validation_status = percent.validate("%d%%" % 15) - self.assertTrue(validation_status) - - value = 9 - validation_status = percent.validate("%d%%" % value) - self.assertFalse(validation_status) - - range_string = "%g%% <= %g%% <= %g%%" % (from_value, value, to_value) - self.assertEqual(validation_status.message(), PercentArgument.NOT_IN_RANGE % range_string) - - value = 21 - validation_status = percent.validate("%d%%" % value) - self.assertFalse(validation_status) - - range_string = "%g%% <= %g%% <= %g%%" % (from_value, value, to_value) - self.assertEqual(validation_status.message(), PercentArgument.NOT_IN_RANGE % range_string) - - - - - - - - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_proper_name_argument.py b/ThirdParty/Ert/python/tests/gui/ide/test_proper_name_argument.py deleted file mode 100644 index 1d754feef1..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_proper_name_argument.py +++ /dev/null @@ -1,18 +0,0 @@ -from ert_gui.ide.keywords.definitions import ProperNameArgument -from ert.test import ExtendedTestCase - - -class ProperNameArgumentTest(ExtendedTestCase): - - def test_proper_name_argument(self): - - argument = ProperNameArgument() - - self.assertTrue(argument.validate("NAME")) - self.assertTrue(argument.validate("__NAME__")) - self.assertTrue(argument.validate("")) - self.assertTrue(argument.validate("-NAME-")) - - self.assertFalse(argument.validate("-NA ME-")) - self.assertFalse(argument.validate("NAME*")) - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_proper_name_format_argument.py b/ThirdParty/Ert/python/tests/gui/ide/test_proper_name_format_argument.py deleted file mode 100644 index f6f1ccb180..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_proper_name_format_argument.py +++ /dev/null @@ -1,18 +0,0 @@ -from ert_gui.ide.keywords.definitions import ProperNameFormatArgument -from ert.test import ExtendedTestCase - - -class ProperNameFormatArgumentTest(ExtendedTestCase): - - def test_proper_name_format_argument(self): - - argument = ProperNameFormatArgument() - - self.assertTrue(argument.validate("NAME%d")) - self.assertTrue(argument.validate("__NA%dME__")) - self.assertTrue(argument.validate("%d")) - self.assertTrue(argument.validate("%d-NAME-")) - - self.assertFalse(argument.validate("-%dNA ME-")) - self.assertFalse(argument.validate("NAME*%d")) - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_proper_name_format_string_argument.py b/ThirdParty/Ert/python/tests/gui/ide/test_proper_name_format_string_argument.py deleted file mode 100644 index 8fa3ecd2ef..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_proper_name_format_string_argument.py +++ /dev/null @@ -1,21 +0,0 @@ -from ert_gui.ide.keywords.definitions import ProperNameFormatStringArgument -from ert.test import ExtendedTestCase - - -class ProperNameFormatStringArgumentTest(ExtendedTestCase): - - def test_proper_name_format_string_argument(self): - - argument = ProperNameFormatStringArgument() - - self.assertTrue(argument.validate("NAME%s")) - self.assertTrue(argument.validate("__NA%sME__")) - self.assertTrue(argument.validate("%s")) - self.assertTrue(argument.validate("%s-NAME-")) - self.assertTrue(argument.validate("%s")) - self.assertTrue(argument.validate(".NA.ME%s.")) - - self.assertFalse(argument.validate("-%sNA ME-")) - self.assertFalse(argument.validate("NAME*%s")) - self.assertFalse(argument.validate("")) - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_range_string_argument.py b/ThirdParty/Ert/python/tests/gui/ide/test_range_string_argument.py deleted file mode 100644 index a3612cec84..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_range_string_argument.py +++ /dev/null @@ -1,28 +0,0 @@ -from ert_gui.ide.keywords.definitions.range_string_argument import RangeStringArgument -from ert.test import ExtendedTestCase - - -class RangeStringArgumentTest(ExtendedTestCase): - - def test_proper_name_argument(self): - - argument = RangeStringArgument() - - self.assertTrue(argument.validate("1")) - self.assertTrue(argument.validate("1-10")) - self.assertTrue(argument.validate("1-10,11-20")) - self.assertTrue(argument.validate("1-10,11,12,13,14,15,16-20")) - - self.assertFalse(argument.validate("s5")) - self.assertFalse(argument.validate("1-10,5-4*")) - - - self.assertTrue(argument.validate("1 - 5, 2,3 ,4")) - self.assertTrue(argument.validate("1 - 5, 2 ,3 ,4")) - - - argument = RangeStringArgument(max_value=10) - - self.assertTrue(argument.validate("1-5, 9")) - self.assertFalse(argument.validate("10")) - diff --git a/ThirdParty/Ert/python/tests/gui/ide/test_tokens.py b/ThirdParty/Ert/python/tests/gui/ide/test_tokens.py deleted file mode 100644 index 60285f0dc5..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/test_tokens.py +++ /dev/null @@ -1,60 +0,0 @@ -from ert_gui.ide.keywords.data import Keyword, Argument, Token -from ert_gui.ide.keywords.definitions import KeywordDefinition, StringArgument -from ert.test import ExtendedTestCase - - -class TokenTest(ExtendedTestCase): - def test_token(self): - line = "some words in a line" - token = Token(5, 10, line) - - self.assertEqual(token.value(), "words") - self.assertEqual(token.fromIndex(), 5) - self.assertEqual(token.toIndex(), 10) - self.assertEqual(token.count(), 5) - self.assertTrue(5 in token) - self.assertTrue(9 in token) - self.assertTrue(not 10 in token) - - - def test_empty_token(self): - token = Token(4, 4, "text") - - self.assertEqual(token.value(), "") - - def test_keyword(self): - num_realizations = "NUM_REALIZATIONS" - - keyword_def = KeywordDefinition(num_realizations) - - keyword = Keyword(0, 16, num_realizations) - keyword.setKeywordDefinition(keyword_def) - - self.assertEqual(keyword.value(), num_realizations) - self.assertEqual(keyword_def, keyword.keywordDefinition()) - self.assertTrue(keyword.hasKeywordDefinition()) - - - def test_argument(self): - text = "KEYWORD arg1 arg2" - - arg1 = Argument(8, 12, text) - arg1.setArgumentDefinition(StringArgument()) - - arg2 = Argument(13, 17, text) - - self.assertEqual(arg1.value(), "arg1") - self.assertEqual(arg2.value(), "arg2") - - self.assertEqual(arg2.line(), text) - - self.assertTrue(arg1.hasArgumentDefinition()) - self.assertIsInstance(arg1.argumentDefinition(), StringArgument) - - self.assertFalse(arg2.hasArgumentDefinition()) - self.assertIsNone(arg2.argumentDefinition()) - - - - - diff --git a/ThirdParty/Ert/python/tests/gui/ide/wizards/CMakeLists.txt b/ThirdParty/Ert/python/tests/gui/ide/wizards/CMakeLists.txt deleted file mode 100644 index 3125ba406f..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/wizards/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_tree_structure.py -) - -add_python_package("python.tests.gui.ide.wizards" ${PYTHON_INSTALL_PREFIX}/tests/gui/ide/wizards "${TEST_SOURCES}" False) - -addPythonTest(gui.ide.wizards.tree_structure tests.gui.ide.wizards.test_tree_structure.TreeStructureTest) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/gui/ide/wizards/__init__.py b/ThirdParty/Ert/python/tests/gui/ide/wizards/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/gui/ide/wizards/test_tree_structure.py b/ThirdParty/Ert/python/tests/gui/ide/wizards/test_tree_structure.py deleted file mode 100644 index 402a7346fd..0000000000 --- a/ThirdParty/Ert/python/tests/gui/ide/wizards/test_tree_structure.py +++ /dev/null @@ -1,65 +0,0 @@ -from PyQt4.QtCore import Qt -from ert_gui.ide.wizards import TreeItem, TreeModel -from ert.test import ExtendedTestCase - - -class TreeStructureTest(ExtendedTestCase): - - def test_tree_item(self): - - root = TreeItem("Root") - - self.assertIsNone(root.parent()) - self.assertEqual(root.name(), "Root") - self.assertEqual(len(root), 0) - - with self.assertRaises(IndexError): - root.child(0) - - self.assertIsNone(root.data()) - - child_1 = TreeItem("Child1") - - child = root.addChild(child_1) - - self.assertEqual(child, child_1) - self.assertEqual(len(root), 1) - self.assertEqual(root.child(0), child_1) - self.assertEqual(child_1.parent(), root) - - def test_tree_model(self): - root = TreeItem("Wizards") - - root.addChild(TreeItem("One")) - - child = root.addChild(TreeItem("Two")) - child.addChild(TreeItem("SubOne")) - child.addChild(TreeItem("SubTwo")) - - child_item = root.addChild(TreeItem("Three")) - - tree = TreeModel(root) - - self.assertEqual(tree.headerData(0, Qt.Horizontal), root.name()) - - name1 = tree.data(tree.index(0, 0)) - self.assertEqual(name1, "One") - - name2_index = tree.index(1, 0) - sub_name2_index = tree.index(1, 0, name2_index) - - self.assertEqual(tree.data(sub_name2_index), "SubTwo") - - - tree_item = tree.item(tree.index(2, 0)) - - self.assertEqual(child_item, tree_item) - - self.assertTrue(tree.data(tree.index(3, 0)).isNull()) - - - - - - - diff --git a/ThirdParty/Ert/python/tests/gui/plottery/CMakeLists.txt b/ThirdParty/Ert/python/tests/gui/plottery/CMakeLists.txt deleted file mode 100644 index 3dd35e54c7..0000000000 --- a/ThirdParty/Ert/python/tests/gui/plottery/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(TEST_SOURCES - __init__.py - test_plot_style.py - test_plot_config_history.py - test_plot_limits.py -) - -add_python_package("python.tests.gui.plottery" ${PYTHON_INSTALL_PREFIX}/tests/gui/plottery "${TEST_SOURCES}" False) - -addPythonTest(gui.plottery.plot_style gui.plottery.test_plot_style.PlotStyleTest) -addPythonTest(gui.plottery.plot_config_history gui.plottery.test_plot_config_history.PlotConfigHistoryTest) -addPythonTest(gui.plottery.plot_limits gui.plottery.test_plot_limits.PlotLimitsTest) \ No newline at end of file diff --git a/ThirdParty/Ert/python/tests/gui/plottery/__init__.py b/ThirdParty/Ert/python/tests/gui/plottery/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/python/tests/gui/plottery/test_plot_config_history.py b/ThirdParty/Ert/python/tests/gui/plottery/test_plot_config_history.py deleted file mode 100644 index 4a3a2a053e..0000000000 --- a/ThirdParty/Ert/python/tests/gui/plottery/test_plot_config_history.py +++ /dev/null @@ -1,46 +0,0 @@ -from ert.test import ExtendedTestCase -from ert.enkf import PlotSettings -from ert_gui.plottery import PlotConfig, PlotConfigHistory - - -class PlotConfigHistoryTest(ExtendedTestCase): - - def test_plot_config_history(self): - ps = PlotSettings( ) - test_pc = PlotConfig(ps , title = "test_1") - history = PlotConfigHistory("test", test_pc) - - self.assertEqual(history.getPlotConfig().title(), test_pc.title()) - self.assertNotEqual(history.getPlotConfig(), test_pc) - - self.assertFalse(history.isUndoPossible()) - self.assertFalse(history.isRedoPossible()) - - history.applyChanges(PlotConfig(ps, title = "test_2")) - self.assertTrue(history.isUndoPossible()) - self.assertFalse(history.isRedoPossible()) - self.assertEqual(history.getPlotConfig().title(), "test_2") - - history.undoChanges() - self.assertFalse(history.isUndoPossible()) - self.assertTrue(history.isRedoPossible()) - self.assertEqual(history.getPlotConfig().title(), "test_1") - - history.redoChanges() - self.assertTrue(history.isUndoPossible()) - self.assertFalse(history.isRedoPossible()) - self.assertEqual(history.getPlotConfig().title(), "test_2") - - history.resetChanges() - self.assertTrue(history.isUndoPossible()) - self.assertFalse(history.isRedoPossible()) - self.assertEqual(history.getPlotConfig().title(), "test_1") - - history.undoChanges() - self.assertTrue(history.isUndoPossible()) - self.assertTrue(history.isRedoPossible()) - self.assertEqual(history.getPlotConfig().title(), "test_2") - - - - diff --git a/ThirdParty/Ert/python/tests/gui/plottery/test_plot_limits.py b/ThirdParty/Ert/python/tests/gui/plottery/test_plot_limits.py deleted file mode 100644 index f85140916c..0000000000 --- a/ThirdParty/Ert/python/tests/gui/plottery/test_plot_limits.py +++ /dev/null @@ -1,124 +0,0 @@ -import datetime - -from ert.test import ExtendedTestCase -from ert_gui.plottery import PlotLimits - - -class PlotLimitsTest(ExtendedTestCase): - - def test_plot_limits_construction(self): - plot_limits = PlotLimits() - self.assertEqual(plot_limits.value_minimum, None) - self.assertEqual(plot_limits.value_maximum, None) - self.assertEqual(plot_limits.value_limits, (None, None)) - - self.assertEqual(plot_limits.index_minimum, None) - self.assertEqual(plot_limits.index_maximum, None) - self.assertEqual(plot_limits.index_limits, (None, None)) - - self.assertEqual(plot_limits.count_minimum, None) - self.assertEqual(plot_limits.count_maximum, None) - self.assertEqual(plot_limits.count_limits, (None, None)) - - self.assertEqual(plot_limits.density_minimum, None) - self.assertEqual(plot_limits.density_maximum, None) - self.assertEqual(plot_limits.density_limits, (None, None)) - - self.assertEqual(plot_limits.depth_minimum, None) - self.assertEqual(plot_limits.depth_maximum, None) - self.assertEqual(plot_limits.depth_limits, (None, None)) - - self.assertEqual(plot_limits.date_minimum, None) - self.assertEqual(plot_limits.date_maximum, None) - self.assertEqual(plot_limits.date_limits, (None, None)) - - - def test_plot_limits(self): - plot_limits = PlotLimits() - limit_names = ["value", "index", "count", "density", "depth", "date"] - - non_numbers = ["string", datetime.date(2001, 1, 1), "3.0", "1e-5", "-5.5", "-.5"] - - positive_floats = [1.0, 1.5, 3.1415, 1e10, 5.2e-7] - negative_floats = [-1.0, -1.5, -3.1415, -1e10, -5.2e-7] - positive_ints = [1, 5, 1000] - negative_ints = [-1, -5, -1000] - - non_dates = ["string", "3.4", "2001-01-01", datetime.time()] - dates = [datetime.date(2001, 1, 1), datetime.datetime(2010, 3, 3)] - - setter_should_fail_values = { - "value": non_numbers + dates, - "index": non_numbers + positive_floats + negative_floats + dates, - "depth": non_numbers + negative_floats + negative_ints + negative_ints, - "count": non_numbers + negative_ints + negative_floats + positive_floats, - "density": non_numbers + negative_floats + negative_ints, - "date": non_dates - } - - setter_should_succeed_values = { - "value": positive_floats + negative_floats + positive_ints + negative_ints, - "index": positive_ints, - "depth": positive_floats + positive_ints, - "count": positive_ints, - "density": positive_floats + positive_ints, - "date": dates - } - - for attribute_name in limit_names: - self.assertIsNone(getattr(plot_limits, "%s_minimum" % attribute_name)) - self.assertIsNone(getattr(plot_limits, "%s_maximum" % attribute_name)) - self.assertTupleEqual(getattr(plot_limits, "%s_limits" % attribute_name), (None, None)) - - with self.assertNotRaises(): - setattr(plot_limits, "%s_minimum" % attribute_name, None) - setattr(plot_limits, "%s_maximum" % attribute_name, None) - setattr(plot_limits, "%s_limits" % attribute_name, (None, None)) - - with self.assertRaises(TypeError): - setattr(plot_limits, "%s_limits" % attribute_name, None) - - for value in setter_should_fail_values[attribute_name]: - with self.assertRaises((TypeError, ValueError)): - setattr(plot_limits, "%s_minimum" % attribute_name, value) - - with self.assertRaises((TypeError, ValueError)): - setattr(plot_limits, "%s_maximum" % attribute_name, value) - - self.assertTupleEqual(getattr(plot_limits, "%s_limits" % attribute_name), (None, None)) - - for value in setter_should_succeed_values[attribute_name]: - with self.assertNotRaises(): - setattr(plot_limits, "%s_minimum" % attribute_name, value) - setattr(plot_limits, "%s_maximum" % attribute_name, value) - - minimum = getattr(plot_limits, "%s_minimum" % attribute_name) - maximum = getattr(plot_limits, "%s_maximum" % attribute_name) - - self.assertEqual(minimum, value) - self.assertEqual(maximum, value) - - self.assertTupleEqual(getattr(plot_limits, "%s_limits" % attribute_name), (minimum, maximum)) - - - def test_copy_plot_limits(self): - plot_limits = PlotLimits() - plot_limits.value_limits = 1, 2 - plot_limits.index_limits = 3, 4 - plot_limits.count_limits = 5, 6 - plot_limits.depth_limits = 7, 8 - plot_limits.density_limits = 9, 10 - plot_limits.date_limits = datetime.date(1999, 1, 1), datetime.date(1999, 12, 31) - - copy_of_plot_limits = PlotLimits() - - copy_of_plot_limits.copyLimitsFrom(plot_limits) - - self.assertEqual(copy_of_plot_limits, plot_limits) - - self.assertEqual(copy_of_plot_limits.value_limits, (1, 2)) - self.assertEqual(copy_of_plot_limits.index_limits, (3, 4)) - self.assertEqual(copy_of_plot_limits.count_limits, (5, 6)) - self.assertEqual(copy_of_plot_limits.depth_limits, (7, 8)) - self.assertEqual(copy_of_plot_limits.density_limits, (9, 10)) - self.assertEqual(copy_of_plot_limits.date_limits, (datetime.date(1999, 1, 1), datetime.date(1999, 12, 31))) diff --git a/ThirdParty/Ert/python/tests/gui/plottery/test_plot_style.py b/ThirdParty/Ert/python/tests/gui/plottery/test_plot_style.py deleted file mode 100644 index 2fdd098281..0000000000 --- a/ThirdParty/Ert/python/tests/gui/plottery/test_plot_style.py +++ /dev/null @@ -1,164 +0,0 @@ -import datetime - -from ert.test import ExtendedTestCase -from ert.enkf import PlotSettings -from ert_gui.plottery import PlotStyle, PlotConfig, PlotLimits - - -class PlotStyleTest(ExtendedTestCase): - - def test_plot_style_test_defaults(self): - style = PlotStyle("Test") - - self.assertEqual(style.name, "Test") - self.assertEqual(style.color, "#000000") - self.assertEqual(style.line_style, "-") - self.assertEqual(style.alpha, 1.0) - self.assertEqual(style.marker, "") - self.assertEqual(style.width, 1.0) - self.assertEqual(style.size, 7.5) - self.assertTrue(style.isEnabled()) - - style.line_style = None - style.marker = None - - self.assertEqual(style.line_style, "") - self.assertEqual(style.marker, "") - - - def test_plot_style_builtin_checks(self): - style = PlotStyle("Test") - - style.name = None - self.assertIsNone(style.name) - - style.color = "notacolor" - self.assertEqual(style.color, "notacolor") # maybe make this a proper check in future ? - - style.line_style = None - self.assertEqual(style.line_style, "") - - style.marker = None - self.assertEqual(style.marker, "") - - style.width = -1 - self.assertEqual(style.width, 0.0) - - style.size = -1 - self.assertEqual(style.size, 0.0) - - style.alpha = 1.1 - self.assertEqual(style.alpha, 1.0) - - style.alpha = -0.1 - self.assertEqual(style.alpha, 0.0) - - style.setEnabled(False) - self.assertFalse(style.isEnabled()) - - - def test_plot_style_copy_style(self): - style = PlotStyle("Test", "red", 0.5, ".", "o", 2.5) - style.setEnabled(False) - - copy_style = PlotStyle("Copy") - - copy_style.copyStyleFrom(style) - - self.assertNotEqual(style.name, copy_style.name) - self.assertEqual(style.color, copy_style.color) - self.assertEqual(style.alpha, copy_style.alpha) - self.assertEqual(style.line_style, copy_style.line_style) - self.assertEqual(style.marker, copy_style.marker) - self.assertEqual(style.width, copy_style.width) - self.assertEqual(style.size, copy_style.size) - self.assertNotEqual(style.isEnabled(), copy_style.isEnabled()) - - another_copy_style = PlotStyle("Another Copy") - another_copy_style.copyStyleFrom(style, copy_enabled_state=True) - self.assertEqual(style.isEnabled(), another_copy_style.isEnabled()) - - - def test_plot_config(self): - ps = PlotSettings( ) - plot_config = PlotConfig(ps , "Golden Sample", x_label="x", y_label="y") - - limits = PlotLimits() - limits.count_limits = 1, 2 - limits.depth_limits = 3, 4 - limits.density_limits = 5, 6 - limits.date_limits = datetime.date(2005, 2, 5), datetime.date(2006, 2, 6) - limits.index_limits = 7, 8 - limits.value_limits = 9.0, 10.0 - - plot_config.limits = limits - self.assertEqual(plot_config.limits, limits) - - plot_config.setDistributionLineEnabled(True) - plot_config.setLegendEnabled(False) - plot_config.setGridEnabled(False) - plot_config.setRefcaseEnabled(False) - plot_config.setObservationsEnabled(False) - - style = PlotStyle("test_style", line_style=".", marker="g", width=2.5, size=7.5) - - plot_config.setDefaultStyle(style) - plot_config.setRefcaseStyle(style) - plot_config.setStatisticsStyle("mean", style) - plot_config.setStatisticsStyle("min-max", style) - plot_config.setStatisticsStyle("p50", style) - plot_config.setStatisticsStyle("p10-p90", style) - plot_config.setStatisticsStyle("p33-p67", style) - plot_config.setStatisticsStyle("std", style) - - copy_of_plot_config = PlotConfig(ps , "Copy of Golden Sample") - copy_of_plot_config.copyConfigFrom(plot_config) - - self.assertEqual(plot_config.isLegendEnabled(), copy_of_plot_config.isLegendEnabled()) - self.assertEqual(plot_config.isGridEnabled(), copy_of_plot_config.isGridEnabled()) - self.assertEqual(plot_config.isObservationsEnabled(), copy_of_plot_config.isObservationsEnabled()) - self.assertEqual(plot_config.isDistributionLineEnabled(), copy_of_plot_config.isDistributionLineEnabled()) - - self.assertEqual(plot_config.refcaseStyle(), copy_of_plot_config.refcaseStyle()) - self.assertEqual(plot_config.observationsStyle(), copy_of_plot_config.observationsStyle()) - - self.assertEqual(plot_config.histogramStyle(), copy_of_plot_config.histogramStyle()) - self.assertEqual(plot_config.defaultStyle(), copy_of_plot_config.defaultStyle()) - self.assertEqual(plot_config.currentColor(), copy_of_plot_config.currentColor()) - - self.assertEqual(plot_config.getStatisticsStyle("mean"), copy_of_plot_config.getStatisticsStyle("mean")) - self.assertEqual(plot_config.getStatisticsStyle("min-max"), copy_of_plot_config.getStatisticsStyle("min-max")) - self.assertEqual(plot_config.getStatisticsStyle("p50"), copy_of_plot_config.getStatisticsStyle("p50")) - self.assertEqual(plot_config.getStatisticsStyle("p10-p90"), copy_of_plot_config.getStatisticsStyle("p10-p90")) - self.assertEqual(plot_config.getStatisticsStyle("p33-p67"), copy_of_plot_config.getStatisticsStyle("p33-p67")) - self.assertEqual(plot_config.getStatisticsStyle("std"), copy_of_plot_config.getStatisticsStyle("std")) - - self.assertEqual(plot_config.title(), copy_of_plot_config.title()) - - self.assertEqual(plot_config.limits, copy_of_plot_config.limits) - - - plot_config.currentColor() # cycle state will not be copied - plot_config.nextColor() - - copy_of_plot_config = PlotConfig(ps, "Another Copy of Golden Sample") - copy_of_plot_config.copyConfigFrom(plot_config) - - self.assertEqual(plot_config.refcaseStyle(), copy_of_plot_config.refcaseStyle()) - self.assertEqual(plot_config.observationsStyle(), copy_of_plot_config.observationsStyle()) - - self.assertNotEqual(plot_config.histogramStyle(), copy_of_plot_config.histogramStyle()) - self.assertNotEqual(plot_config.defaultStyle(), copy_of_plot_config.defaultStyle()) - self.assertNotEqual(plot_config.currentColor(), copy_of_plot_config.currentColor()) - - self.assertNotEqual(plot_config.getStatisticsStyle("mean"), copy_of_plot_config.getStatisticsStyle("mean")) - self.assertNotEqual(plot_config.getStatisticsStyle("min-max"), copy_of_plot_config.getStatisticsStyle("min-max")) - self.assertNotEqual(plot_config.getStatisticsStyle("p50"), copy_of_plot_config.getStatisticsStyle("p50")) - self.assertNotEqual(plot_config.getStatisticsStyle("p10-p90"), copy_of_plot_config.getStatisticsStyle("p10-p90")) - self.assertNotEqual(plot_config.getStatisticsStyle("p33-p67"), copy_of_plot_config.getStatisticsStyle("p33-p67")) - self.assertNotEqual(plot_config.getStatisticsStyle("std"), copy_of_plot_config.getStatisticsStyle("std")) - - - - - diff --git a/ThirdParty/Ert/python/tests/gui/test_multiple_data_assimilation.py b/ThirdParty/Ert/python/tests/gui/test_multiple_data_assimilation.py deleted file mode 100644 index 8b8cd8ed54..0000000000 --- a/ThirdParty/Ert/python/tests/gui/test_multiple_data_assimilation.py +++ /dev/null @@ -1,44 +0,0 @@ -from ert.test import ExtendedTestCase -from ert_gui.simulation.models import MultipleDataAssimilation as mda - - -class MDAWeightsTest(ExtendedTestCase): - - def test_weights(self): - - weights = mda.parseWeights("2, 2, 2, 2") - print(weights) - self.assertAlmostEqualList([2, 2, 2, 2], weights) - - weights = mda.parseWeights("1, 2, 3, ") - self.assertAlmostEqualList([1, 2, 3], weights) - - weights = mda.parseWeights("1, 0, 1") - self.assertAlmostEqualList([1, 1], weights) - - weights = mda.parseWeights("1.414213562373095, 1.414213562373095") - self.assertAlmostEqualList([1.414213562373095, 1.414213562373095], weights) - - with self.assertRaises(ValueError): - mda.parseWeights("2, error, 2, 2") - - - def test_normalized_weights(self): - - weights = mda.normalizeWeights([1]) - self.assertAlmostEqualList([1.0], weights) - - weights = mda.normalizeWeights([1, 1]) - self.assertAlmostEqualList([1.414214, 1.414214], weights) - - weights = mda.normalizeWeights([1, 0, 1]) - self.assertAlmostEqualList([1.414214, 1.414214], weights) - - weights = mda.normalizeWeights([1, 1, 1]) - self.assertAlmostEqualList([1.732051, 1.732051, 1.732051], weights) - - weights = mda.normalizeWeights([8, 4, 2, 1]) - self.assertAlmostEqualList([9.219544457292887, 4.6097722286464435, 2.3048861143232218, 1.1524430571616109], weights) - - weights = mda.normalizeWeights([9.219544457292887, 4.6097722286464435, 2.3048861143232218, 1.1524430571616109]) - self.assertAlmostEqualList([9.219544457292887, 4.6097722286464435, 2.3048861143232218, 1.1524430571616109], weights) diff --git a/ThirdParty/Ert/python/tests/share/test_synthesizer.py b/ThirdParty/Ert/python/tests/share/test_synthesizer.py index 0efb611bf2..e6b75e2015 100644 --- a/ThirdParty/Ert/python/tests/share/test_synthesizer.py +++ b/ThirdParty/Ert/python/tests/share/test_synthesizer.py @@ -5,7 +5,7 @@ from ert.test import ExtendedTestCase try: from synthesizer import OilSimulator except ImportError as e: - share_lib_path = os.path.join(ExtendedTestCase.findShareRoot(), "lib") + share_lib_path = os.path.join(ExtendedTestCase.createSharePath("lib")) sys.path.insert(0, share_lib_path) synthesizer_module = __import__("synthesizer") diff --git a/ThirdParty/Ert/python/python/ert/enkf/config/field_type_enum.py b/ThirdParty/Ert/python/tests/test_pylint.py similarity index 50% rename from ThirdParty/Ert/python/python/ert/enkf/config/field_type_enum.py rename to ThirdParty/Ert/python/tests/test_pylint.py index 901a019060..1d327ef380 100644 --- a/ThirdParty/Ert/python/python/ert/enkf/config/field_type_enum.py +++ b/ThirdParty/Ert/python/tests/test_pylint.py @@ -1,4 +1,5 @@ -# Copyright (C) 2016 Statoil ASA, Norway. +#!/usr/bin/env python +# Copyright (C) 2017 Statoil ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. # @@ -14,16 +15,20 @@ # See the GNU General Public License at # for more details. -from cwrap import BaseCEnum +from ert.test import LintTestCase -class FieldTypeEnum(BaseCEnum): - TYPE_NAME = "field_type_enum" - ECLIPSE_RESTART = None - ECLIPSE_PARAMETER = None - GENERAL = None - UNKNOWN_FIELD_TYPE = None +class LintErt(LintTestCase): + """Tests that no file in ert needs linting""" -FieldTypeEnum.addEnum('ECLIPSE_RESTART', 1) -FieldTypeEnum.addEnum('ECLIPSE_PARAMETER', 2) -FieldTypeEnum.addEnum('GENERAL', 3) -FieldTypeEnum.addEnum('UNKNOWN_FIELD_TYPE', 4) + def test_lint_ecl(self): + white = ['ecl_kw.py', 'ecl_type.py', 'ecl_sum.py', 'ecl_grid.py', 'ecl_npv.py'] # TODO fix issues and remove + self.assertLinted('ert/ecl', whitelist=white) + + def test_lint_geo(self): + self.assertLinted('ert/geo') + + def test_lint_util(self): + self.assertLinted('ert/util') + + def test_lint_well(self): + self.assertLinted('ert/well') diff --git a/ThirdParty/Ert/python/tests/util/CMakeLists.txt b/ThirdParty/Ert/python/tests/util/CMakeLists.txt new file mode 100644 index 0000000000..38485b80f9 --- /dev/null +++ b/ThirdParty/Ert/python/tests/util/CMakeLists.txt @@ -0,0 +1,41 @@ +set(TEST_SOURCES + __init__.py + test_ctime.py + test_cstring.py + test_hash.py + test_lookup_table.py + test_matrix.py + test_rng.py + test_stat.py + test_string_list.py + test_substitution_list.py + test_thread_pool.py + test_cthread_pool.py + test_ui_return.py + test_vectors.py + test_version.py + test_work_area.py + test_path_context.py + test_arg_pack.py + test_spawn.py +) + +add_python_package("python.tests.util" ${PYTHON_INSTALL_PREFIX}/tests/util "${TEST_SOURCES}" False) + +addPythonTest(util.ctime util.test_ctime.CTimeTest) +addPythonTest(util.cstring util.test_cstring.CStringTest) +addPythonTest(util.hash util.test_hash.HashTest) +addPythonTest(util.lookup_table util.test_lookup_table.LookupTableTest ) +addPythonTest(util.matrix util.test_matrix.MatrixTest ) +addPythonTest(util.rng util.test_rng.RngTest ) +addPythonTest(util.stat util.test_stat.StatTest ) +addPythonTest(util.stringlist util.test_string_list.StringListTest) +addPythonTest(util.tvector util.test_vectors.UtilTest) +addPythonTest(util.ui_return util.test_ui_return.UIReturnTest) +addPythonTest(util.work_area util.test_work_area.WorkAreaTest) +addPythonTest(util.version util.test_version.VersionTest) +addPythonTest(util.path_context util.test_path_context.PathContextTest) +addPythonTest(util.thread_pool util.test_thread_pool.ThreadPoolTest) +addPythonTest(util.cthread_pool util.test_cthread_pool.CThreadPoolTest) +addPythonTest(util.arg_pack util.test_arg_pack.ArgPackTest) +addPythonTest(util.spawn util.test_spawn.SpawnTest) diff --git a/ThirdParty/Ert/python/python/ert_gui/ide/completers/__init__.py b/ThirdParty/Ert/python/tests/util/__init__.py similarity index 100% rename from ThirdParty/Ert/python/python/ert_gui/ide/completers/__init__.py rename to ThirdParty/Ert/python/tests/util/__init__.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_arg_pack.py b/ThirdParty/Ert/python/tests/util/test_arg_pack.py similarity index 95% rename from ThirdParty/Ert/python/tests/core/util/test_arg_pack.py rename to ThirdParty/Ert/python/tests/util/test_arg_pack.py index a433f44fc0..fdd1ceef69 100644 --- a/ThirdParty/Ert/python/tests/core/util/test_arg_pack.py +++ b/ThirdParty/Ert/python/tests/util/test_arg_pack.py @@ -2,7 +2,7 @@ import ert from ert.test import ExtendedTestCase from ert.util import ArgPack, StringList -TEST_LIB = ert.load("libtest_util") +TEST_LIB = ert.load("libert_util") class ArgPackTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/core/util/test_cstring.py b/ThirdParty/Ert/python/tests/util/test_cstring.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_cstring.py rename to ThirdParty/Ert/python/tests/util/test_cstring.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_cthread_pool.py b/ThirdParty/Ert/python/tests/util/test_cthread_pool.py similarity index 97% rename from ThirdParty/Ert/python/tests/core/util/test_cthread_pool.py rename to ThirdParty/Ert/python/tests/util/test_cthread_pool.py index 698fdc80ec..d3ab2cfb11 100644 --- a/ThirdParty/Ert/python/tests/core/util/test_cthread_pool.py +++ b/ThirdParty/Ert/python/tests/util/test_cthread_pool.py @@ -3,7 +3,7 @@ import ert from ert.test import ExtendedTestCase from ert.util import CThreadPool, startCThreadPool -TEST_LIB = ert.load("libtest_util") +TEST_LIB = ert.load("libert_util") class CThreadPoolTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/core/util/test_ctime.py b/ThirdParty/Ert/python/tests/util/test_ctime.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_ctime.py rename to ThirdParty/Ert/python/tests/util/test_ctime.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_hash.py b/ThirdParty/Ert/python/tests/util/test_hash.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_hash.py rename to ThirdParty/Ert/python/tests/util/test_hash.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_lookup_table.py b/ThirdParty/Ert/python/tests/util/test_lookup_table.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_lookup_table.py rename to ThirdParty/Ert/python/tests/util/test_lookup_table.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_matrix.py b/ThirdParty/Ert/python/tests/util/test_matrix.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_matrix.py rename to ThirdParty/Ert/python/tests/util/test_matrix.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_path_context.py b/ThirdParty/Ert/python/tests/util/test_path_context.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_path_context.py rename to ThirdParty/Ert/python/tests/util/test_path_context.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_rng.py b/ThirdParty/Ert/python/tests/util/test_rng.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_rng.py rename to ThirdParty/Ert/python/tests/util/test_rng.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_spawn.py b/ThirdParty/Ert/python/tests/util/test_spawn.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_spawn.py rename to ThirdParty/Ert/python/tests/util/test_spawn.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_stat.py b/ThirdParty/Ert/python/tests/util/test_stat.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_stat.py rename to ThirdParty/Ert/python/tests/util/test_stat.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_string_list.py b/ThirdParty/Ert/python/tests/util/test_string_list.py similarity index 95% rename from ThirdParty/Ert/python/tests/core/util/test_string_list.py rename to ThirdParty/Ert/python/tests/util/test_string_list.py index c965ec5c42..627603546b 100644 --- a/ThirdParty/Ert/python/tests/core/util/test_string_list.py +++ b/ThirdParty/Ert/python/tests/util/test_string_list.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + try: from unittest2 import TestCase except ImportError: @@ -83,7 +85,9 @@ class StringListTest(TestCase): self.assertFalse(s1 == ["A","B","D"]) self.assertFalse(s1 == ["A","B","C" , "D"]) - + pfx = 'StringList(size' # __repr__ + self.assertEqual(pfx, repr(s2)[:len(pfx)]) + def test_append_not_string(self): s = StringList() s.append(10) diff --git a/ThirdParty/Ert/python/tests/core/util/test_substitution_list.py b/ThirdParty/Ert/python/tests/util/test_substitution_list.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_substitution_list.py rename to ThirdParty/Ert/python/tests/util/test_substitution_list.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_thread_pool.py b/ThirdParty/Ert/python/tests/util/test_thread_pool.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_thread_pool.py rename to ThirdParty/Ert/python/tests/util/test_thread_pool.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_ui_return.py b/ThirdParty/Ert/python/tests/util/test_ui_return.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_ui_return.py rename to ThirdParty/Ert/python/tests/util/test_ui_return.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_vectors.py b/ThirdParty/Ert/python/tests/util/test_vectors.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_vectors.py rename to ThirdParty/Ert/python/tests/util/test_vectors.py diff --git a/ThirdParty/Ert/python/tests/core/util/test_version.py b/ThirdParty/Ert/python/tests/util/test_version.py similarity index 86% rename from ThirdParty/Ert/python/tests/core/util/test_version.py rename to ThirdParty/Ert/python/tests/util/test_version.py index 5e4e729a46..67f394cd6b 100644 --- a/ThirdParty/Ert/python/tests/core/util/test_version.py +++ b/ThirdParty/Ert/python/tests/util/test_version.py @@ -39,6 +39,9 @@ class VersionTest(ExtendedTestCase): v2 = Version(1, 2, 3) self.assertTrue(v1 == v2) + self.assertEqual(v1, v2) + self.assertEqual(str(v1), str(v2)) + self.assertEqual(repr(v1), repr(v2)) self.assertFalse(v1 != v2) v1 = Version(1, 2, "X") @@ -66,6 +69,9 @@ class VersionTest(ExtendedTestCase): v2 = Version(1, 2, 3) v3 = (1, 2, 2) + self.assertEqual(str(v1), str(v2)) + self.assertEqual(repr(v1), repr(v2)) + self.assertTrue(v1 >= v2) self.assertFalse(v1 < v2) @@ -82,9 +88,15 @@ class VersionTest(ExtendedTestCase): v2 = Version(1, 2, 0) self.assertFalse(v1 >= v2) + self.assertNotEqual(str(v1), str(v2)) + self.assertNotEqual(repr(v1), repr(v2)) + + def test_current(self): current = Version.currentVersion() self.assertTrue(current > (0, 0, 0)) + pfx = 'Version(major=' + self.assertEqual(pfx, repr(current)[:len(pfx)]) def test_import(self): from ert import Version as globalVersion @@ -92,6 +104,9 @@ class VersionTest(ExtendedTestCase): v2 = Version(1, 1, 2) self.assertTrue(v1 == v2) + self.assertEqual(v1, v2) + self.assertEqual(repr(v1), repr(v2)) + def test_root_version(self): cv = Version.currentVersion( ) diff --git a/ThirdParty/Ert/python/tests/core/util/test_work_area.py b/ThirdParty/Ert/python/tests/util/test_work_area.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/util/test_work_area.py rename to ThirdParty/Ert/python/tests/util/test_work_area.py diff --git a/ThirdParty/Ert/python/tests/well/CMakeLists.txt b/ThirdParty/Ert/python/tests/well/CMakeLists.txt new file mode 100644 index 0000000000..33eeea468e --- /dev/null +++ b/ThirdParty/Ert/python/tests/well/CMakeLists.txt @@ -0,0 +1,14 @@ +set(TEST_SOURCES + __init__.py + test_ecl_well.py + test_ecl_well2.py + test_ecl_well3.py +) + +add_python_package("python.tests.well" ${PYTHON_INSTALL_PREFIX}/tests/well "${TEST_SOURCES}" False) + +if (STATOIL_TESTDATA_ROOT) + addPythonTest(well.ecl_well well.test_ecl_well.EclWellTest LABELS StatoilData) + addPythonTest(well.ecl_well2 well.test_ecl_well2.EclWellTest2 LABELS StatoilData) + addPythonTest(well.ecl_well3 well.test_ecl_well3.EclWellTest3 LABELS StatoilData) +endif() diff --git a/ThirdParty/Ert/python/tests/core/__init__.py b/ThirdParty/Ert/python/tests/well/__init__.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/__init__.py rename to ThirdParty/Ert/python/tests/well/__init__.py diff --git a/ThirdParty/Ert/python/tests/core/well/test_ecl_well.py b/ThirdParty/Ert/python/tests/well/test_ecl_well.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/well/test_ecl_well.py rename to ThirdParty/Ert/python/tests/well/test_ecl_well.py diff --git a/ThirdParty/Ert/python/tests/core/well/test_ecl_well2.py b/ThirdParty/Ert/python/tests/well/test_ecl_well2.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/well/test_ecl_well2.py rename to ThirdParty/Ert/python/tests/well/test_ecl_well2.py diff --git a/ThirdParty/Ert/python/tests/core/well/test_ecl_well3.py b/ThirdParty/Ert/python/tests/well/test_ecl_well3.py similarity index 100% rename from ThirdParty/Ert/python/tests/core/well/test_ecl_well3.py rename to ThirdParty/Ert/python/tests/well/test_ecl_well3.py diff --git a/ThirdParty/Ert/release-notes.txt b/ThirdParty/Ert/release-notes.txt index d2a844df15..193ab6d37f 100644 --- a/ThirdParty/Ert/release-notes.txt +++ b/ThirdParty/Ert/release-notes.txt @@ -1,39 +1,142 @@ -Versjon 2.1.0, October 2016 +Version 2.1.0 February 2017 PR: 1150 - 1415 +Open PR: 1352, 1358, 1362 -* Made ecl_file_view 1st class citizen, exposed to API -* Added EXCLUDE_HOSTS to LSF driver with dynamic blacklisting -* Fixed MAX_RUNTIME is respected by WPRO -* Added functionality to open restart files in RW mode with seek -* Improved date handling (all is UTC now) -* As a result of this the filesystem version has been upgraded to 107, to use an old case you must upgrade it: "ert_upgradefs_107 config_file". -* Bug fixes (EclKW and EclGrid) -* Improved jobs and plugin loading -* The entire source tree was changed with the removal of devel -* ecl_sum can load aquifer variables. +Queue system/workflows: + + - Functionality to blacklist nodes from LSF [1240, 1256, 1258, 1274, 1412, 1415]. + - Use bhist command to check lsf job status if job has expired from bjobs [1301]. + - Debug output from torque goes to stdout [1151]. + - Torque driver will not abort if qstat returns invalid status [1411]. + - Simulation status USER_EXIT - count as failed [1166]. + - Added Enum identifier 'JOB_QUEUE_DO_KILL_NODE_FAILURE [1268]. + - Have deprecated the ability to set queue options directly on the drivers [1288]. + - Added system for version specific loading for workflow job model + description files [1177]. + - Job loader should not try to load from directory [1187]. + - Refactoring of max runtime - initiated from WPRO [1237]. + - Determine which nodes are running a job [1251]. + +Build updates: + + - Check if python modules are present in the required version [1150]. + - Do not build ERT_GUI if PyQt4 is not found [1150, 1230]. + - Do not fail build numpy is not found [1153]. + - Allow for user provided CMAKE_C_FLAGS on linux [1300]. + - Require exactly version 2.7 of Python [1307]. + - Travis testing improvements [1363]. + - Removed devel/ directory from source [1196]. + - Setting correct working directory, and build target dependency + for sphinx-apidoc / html generation [1385]. + +Eclipse library: + + - C++ move constructor and operator= for smspec_node [1155, 1200]. + - fortio_ftruncate( ) [1161]. + - INIT writer will write keywords DEPTH, DX, DY, DZ [1164, 1172, 1311, 1388]. + - Grid writer will take unit system enum argument [1164]. + - New function ecl_kw_first_different( ) [1165]. + - Completion variables can be treated as totals [1167]. + - Fixed bug in ecl_kw_compare_numeric( ) [1168]. + - Refactored / inlined volume calculations in ecl_grid [1173, 1184]. + - Made function ecl_kw_size_and_type_equal() public [1192]. + - Fixed bug in ecl_grid_cell_contains() [1402, 1404, 1195, 1419]. + - OOM bug in ecl_kw_grdecl loader for large files [1207]. + - Cache cell volumes in ecl_grid [1228]. + - Geertsma / gravity functionality [1227, 1284, 1289, 1292, 1364, 1408]. + - Summary + restart - will allow some keyword differences [1296]. + - Implemented ecl_rst_file_open_write_seek( ) [1236]. + - Optionally apply mapaxes [1242, 1281]. + - Expose and use ecl_file_view datastructere - stop using 'blocks' in ecl_file objects [1250]. + - ecl_sum will internalize Aquifer variables [1275]. + - Make sure region properties RxxT are marked as total + depreecated some properties [1285]. + - ecl_kw_resize() + C++ operator[] [1316] + - Added small C++ utility to create eclipse filenames[1396]. + - Make sure restart and INIT files are written with correct unit ID [1399, 1407]. + - Skip keyword data type: 'C010' without failing [1406, 1410]. + - Adding parsing of the last (optional) config token for the SLAVES kwd [1409]. + - Add nnc index to the information exported by ecl_nnc_export() [1204]. + - Marked solvent related total keywords ?NIT and ?NPT.* as totals [1241]. + - Top active cell in grid [1322]. + - Added absolute epsilon to ecl_kw comparsion [1345,1351]. + +Smoother, updates and 'running': + + - Fixed bug with local updates of GEN_DATA [1291]. + - Changed default MDA weights and removed file input [1156, 1190, 1191]. + - Bug in handling of failed realisations [1163]. + - Fix bug missing assignment of analysis module in ES-MDA [1179]. + - OpenMP implementation of fwd_step [1185, 1324,1342]. + - Removes the ability to update dynamic variables [1189]. + - Allow max CV FOLD to be the number of ensembles [1205, 1208]. + - Fix for min_realizations logic [1206]. + - Can assign a specific analyis module for one local update [1224]. + - Handle updates when some summary relaisations are "too short" [1400, 1405]. + - Extending hook manager to support PRE_UPDATE and POST_UPDATE hooks [1340,1360]. + - RML logging is on by default [1318]. + - Changed default ENKF_ALPHA value to 3.0 [??] + - Implemented subsspacce inversion algorithm [1334, 1344]. + +libgeometry: + + - Added function to create new geo_surface (i.e. IRAP) object [1308]. + - Get (x, y) pos from surface [1395]. + +Python code: + + - cwrap has been moved out to stand-alone module, out of ert + package [1159, 1320, 1325, 1326, 1328, 1332, 1338, 1341, 1343, 1347, 1350, 1353] + - Simplified loading of shared libraries [1234]. + - Python3 preparations [1231, 1347]. + - Added __repr__ methods: [1266, 1327, 1329, 1331, 1348, 1373, 1375, 1377, 1384, 1387]. + - Implement __getitem__( ) for gen_data [1331]. + - Removed cstring_obj Python class [1387]. + - EclKW.numpy_array returns shared buffer ndarray [1180]. + - Minor bug in ecl_kw.py [1171]. + - Added EclKW.numpyView( ) and EclKW.numpyCopy( ) [1188]. + - Bug in EclKW slice access [1203]. + - Expose active_list better in Python [1392]. + - @TYPE@_vector suppports negative indices in __getitem__ and + __setitem__; added repr method [1378]. + - added root() methdo ert/__init__.py [1293]. + +GUI / Configuration / Documentation + + - Bug when viewing plots while simulating [1157.] + - Bug when plotting short vectors [1303]. + - Completely refactored the ERT Gui event system [1158, 1162]. + - Marked keywords INIT_SECTION and SCHEDULE_FILE as deprecated [1181]. + - Removed outdated keywords from documentation [1390]. + - Documented UMASK keyword [1186]. + - ConfigParser: Can turn off validation + warnings [1233, 1249, 1287]. + - Make ies advanced option only [1401]. + - Removing MAX_RUNNING_LOCAL and MAX_RUNNING_LSF from user doc [1398]. + - Apply plot style to other plots [1397]. + - Fig bug in initialization when out of range [1394]. + - Added new object for generic config settings [1391]. + - Changes to plot settings [11359,376,1380,1382,1386]. + - Fix bug in load case manually [1368]. + - Documentation of plugins [1194]. + - Changed all time handling to UTC. This will affect loading old cases [1229, 1257]. + - Removed keyword QC_PATH + updated GRID [1263]. + - Making sure the ertshell is creating the run path [1280]. + - Create Doxygen [1277,1278,1294,1309,1317]. + - Ability to run analysis from GUI [1314]. + - Improved documentation of priors [1319]. + - Bug in config parsing with relative paths [1333]. + - Field documentation updates [1337]. -Version 2.0.5, August 2016 -* rel_eps & abs_eps +libwecl_well: -Version 2.0, July 2016 -* functions to write keywords DEPTH, DX, DY and DZ keyword to the INIT file. -* failed realizations are correctly propagated back to the main running scope -* MDA is made first-class citizen and no longer a plugin + - Internalize rates for wells and connections in the well library + [1403]. + - New function well_ts_get_name() [1393]. -Version 1.10, November 2011 -* Set the the verbose flag from the environment variable ERT_VERBOSE. -* Abort if field transformation does not exist among the supported - transformations. -* Added small class EclCmp for comparing Eclipse simulation cases. -* Added function ecl_grid_cell_invalid / EclGrid.validCellGeometry( ). Typically - interesting for GRID files where not necessarily all cells are entered. -* Added function util_update_signalse() which will install util_abort_signal() - signal handler for all fatal signals in default state; using new function from - python ert/__init__py. -* Removed reference to undefined EnkFMain.__len__() method. +libutil: + + - Functions for parsing and outputting dates in ISO format[1248]. + - stringlist_join - like Python str.join [1243]. + - bug in matrix_dgemm [1286]. + - Resurrected block_fs utilities from the past [1297]. + - Slicing for runpath_list [1356]. -Version 1 -* Fixed crash when stopping running simulations from gui. -* Ertshell refactored. Implementing shell functionality has been simplified. -* Ertshell. Added dumping of entries in block mount files. -* Removed LaTeX reporting diff --git a/ThirdParty/Ert/script/download-pr b/ThirdParty/Ert/script/download-pr new file mode 100644 index 0000000000..6c20e4c4ca --- /dev/null +++ b/ThirdParty/Ert/script/download-pr @@ -0,0 +1,78 @@ +#!/usr/bin/env python +import requests +import json +import os +import sys + +closed_pr = set( [1197 , 1201, 1235, 1244, 1245, 1252, 1261, 1262, 1366, + 1357, 1282, 1279, 1267, 1273, 1305, 1312, 1313, 1339 , 1346, + 1354, 1370,1371, 1381]) + +def getPRList( api_token, first_pr ): + pr = first_pr + pr_list = [] + prev_len = 0 + sys.stderr.write("Downloading PR: ") + while True: + if pr in closed_pr: + pr += 1 + else: + url = "https://api.github.com/repos/Ensembles/ert/pulls/%d" % pr + response = requests.get( url , {"access_token" : api_token}) + for i in range(prev_len): + sys.stdout.write("\b") + + sys.stdout.write("%d" % pr ) + sys.stdout.flush() + prev_len = len("%s" % pr) + + if response.status_code == 200: + pr_list.append( json.loads( response.content ) ) + pr += 1 + else: + break + + + + return pr_list + + +def printPRList( pr_list , fileH): + for pr in pr_list: + title = pr["title"] + body = pr["body"] + nr = pr["number"] + + try: + fileH.write( "[%d] *%s*\n\n" % (nr , title)) + except UnicodeEncodeError: + fileH.write(" [%d] : UnicodeError") + + try: + fileH.write( "%s\n\n\n" % body ) + except UnicodeEncodeError: + fileH.write("UnicodeError") + + +def main(): + if "GITHUB_API_TOKEN" in os.environ: + github_api_token = os.getenv("GITHUB_API_TOKEN") + else: + sys.exit("You must create a github access token and set the environment variable 'GITHUB_API_TOKEN' to proceed") + + pr1 = int(sys.argv[1]) + pr_list = getPRList( github_api_token, pr1) + pr2 = pr_list[-1]["number"] + + filename = "/tmp/relnotes-%d-%d" % (pr1 , pr2) + printPRList( pr_list , open(filename , "w")) + + print "Have created file: %s which can be a starting point for release notes" % filename + + + + +if __name__ == "__main__": + main( ) + + diff --git a/ThirdParty/Ert/script/job_dispatch.py b/ThirdParty/Ert/script/job_dispatch.py deleted file mode 100644 index 5c0ada4de2..0000000000 --- a/ThirdParty/Ert/script/job_dispatch.py +++ /dev/null @@ -1,354 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -import os -import os.path -import socket -import time -import random -import subprocess - - -OK_file = "OK" -EXIT_file = "EXIT" -STATUS_file = "STATUS" -run_path = sys.argv[1] -sleep_time = 10 # Time to sleep before exiting the script - to let the disks sync up. -short_sleep = 2 - -################################################################# - -def redirect(file , fd , open_mode): - new_fd = os.open(file , open_mode , 0644) - os.dup2(new_fd , fd) - os.close(new_fd) - - -def cond_symlink(target , src): - if not os.path.exists(src): - os.symlink( target , src ) - - -def cond_unlink(file): - if os.path.exists(file): - os.unlink(file) - - - -def exec_job(job , executable): - if job.get("stdin"): - redirect(job["stdin"] , 0 , os.O_RDONLY) - - if job.get("stdout"): - redirect(job["stdout"] , 1 , os.O_WRONLY | os.O_TRUNC | os.O_CREAT ) - - if job.get("stderr"): - redirect(job["stderr"] , 2 , os.O_WRONLY | os.O_TRUNC | os.O_CREAT ) - - if job.get("environment"): - env = job["environment"] - for key in env.keys(): - os.putenv(key , env[key]) - argList = [ executable ] - if job.get("argList"): - argList += job["argList"] - os.execvp(executable , argList ) - - -def job_process(job , executable): - import subprocess - argList = [ executable ] - if job.get("argList"): - argList += job["argList"] - - P = subprocess.Popen( argList , - stdin = job.get("stdin"), - stdout = job.get("stdout"), - stderr = job.get("stderr"), - env = job.get("environment") ) - return P - - -def kill_process( job , P ): - fileH = open( EXIT_file , "a") - fileH.write("Job:%s has been running for more than %d minutes - explicitly killed.\n" % (job["name"] , job["max_running_minutes"])) - fileH.close() - - try: - P.kill() # P.kill became available in Python2.6 - except AttributeError: - os.system("kill -9 %s" % P.pid) - - -def unlink_empty(file): - if os.path.exists(file): - st = os.stat( file ) - if st.st_size == 0: - os.unlink( file ) - - - -def cleanup( job ): - if job.get("stdout"): - unlink_empty( job["stdout"] ) - if job.get("stderr"): - unlink_empty( job["stderr"] ) - if job.get("license_link"): - os.unlink(job["license_link"]) - - - -# This function implements a simple "personal license" system limiting -# how many instances of this job can run concurrently. Observe that the -# limiting is based on pr. invocation of the queue system (i.e. ERT -# binary) and pr user. The system works as follows: -# -# 1. The job is initilized with a license_path and a max_running -# variable. -# -# 2. In the licens_path directory a license file is made. -# -# 3. For each instance a random hard-link is created to the license -# file - this is how the number of concurrent uses is counted. -# -# 4. When the external program is finished the hard link is removed. - - -def license_check( job ): - job["license_link"] = None - if job.has_key("max_running"): - if job["max_running"]: - job["license_file"] = "%s/%s" % (job["license_path"] , job["name"]) - max_running = job["max_running"] - license_file = job["license_file"] - while True: - job["license_link"] = "%s/%d" % (job["license_path"] , random.randint(100000,999999)) - if not os.path.exists(job["license_link"]): - break - - - if not os.path.exists(license_file): - fileH = open(license_file , "w") - fileH.write("This is a license file for job:%s" % job["name"]) - fileH.close() - - - stat_info = os.stat(license_file) - currently_running = stat_info[3] - 1 - - while True: - stat_info = os.stat(license_file) - currently_running = stat_info[3] - 1 - if currently_running < max_running: - break - else: - time.sleep(5) - - os.link(license_file , job["license_link"]) - - while True: - stat_info = os.stat(license_file) - currently_running = stat_info[3] - 1 - if currently_running <= max_running: - break # OK - now we can leave the building - and let the job start - else: - time.sleep(5) - - -# Compatibility mode which must be retained until all ert prior to -# svn 2709 has been removed. - -def get_executable( job ): - executable = job.get("executable") - if not executable: - executable = job.get("portable_exe") - if not executable: - cpu = os.uname()[4] - if job["platform_exe"].has_key(cpu): - executable = job["platform_exe"][cpu] - else: - return (False, 0 , "%s : did not recognize platform:%s" % (job["name"] , cpu)) - - return executable - - - -def run_one(job): - license_check( job ) - if job.get("stdin"): - if not os.path.exists(job["stdin"]): - return (False , 0 , "Could not locate stdin file: %s" % job["stdin"]) - - if job.get("start_file"): - if not os.path.exists(job["start_file"]): - return (False , -1 , "Could not locate start_file:%s" % job["start_file"]) - - if job.get("error_file"): - if os.path.exists( job.get("error_file")): - os.unlink( job.get("error_file") ) - - - executable = get_executable( job ) - start_time = time.time() - - if job.get("max_running_minutes"): - P = job_process( job , executable) - while True: - time.sleep( short_sleep ) - run_time = time.time() - start_time - poll = P.poll() - if poll is None: - # Still running - if run_time > job["max_running_minutes"] * 60: - # Have been running to long - kill it - kill_process( job , P ) - break - else: - # Have completed within the time limits - break - exit_status = 0 # NOOOT properly used - else: - pid = os.fork() - if pid == 0: - exec_job(job , executable) - else: - (return_pid , exit_status) = os.waitpid(pid , 0) - - - # Check success of job; look for both target_file and - # error_file. Both can be used to signal failure - # independently. - - if job.get("target_file"): - if os.path.exists(job["target_file"]): - stat = os.stat(job["target_file"]) - if stat.st_ctime > start_time: - status = (True , 0 , "") - else: - status = (True , 0 , "Hmmm - seems the target file has not been updated - let the job suceed anyway...??") - else: - status = (False , exit_status , "%s : could not find target_file:%s" % (job["name"] , job["target_file"])) - else: - status = (True , exit_status , "Target file not specified") # Do not really look at exit status yet... - - if status[0]: - if job.get("error_file"): - if os.path.exists( job.get("error_file") ): - status = (False , -1 , "Found the error file:%s - job failed" % job.get("error_file")) - - return status - - - - - -################################################################# - -################################################################# - -os.nice(19) -if not os.path.exists( run_path ): - sys.stderr.write("*****************************************************************\n"); - sys.stderr.write("** FATAL Error: Could not find directory: %s \n" % run_path) - sys.stderr.write("** CWD: %s\n" % os.getcwd()) - sys.stderr.write("*****************************************************************\n"); - - fileH = open(EXIT_file , "w") - fileH.write("Could not locate:%s " % run_path) - fileH.write("CWD: %s" % os.getcwd()) - fileH.close() - sys.exit(-1) - - -################################################################# -# 1. Change current directory to the runpath. -# 2. Modify the sys.path variable to include the runpath -# 3. Import the jobs module. -################################################################# -os.chdir( run_path ) -sys.path.append( os.getcwd() ) -import jobs - -# The jobs module can optionally have a dictionary 'options', which can be -# used to modify some of the global run time properties of the script. -if hasattr(jobs , "options"): - options = getattr( jobs , "options") - OK_file = options.get("OK_file" , OK_file ) - EXIT_file = options.get("EXIT_file" , EXIT_file ) - STATUS_file = options.get("STATUS_file" , STATUS_file ) - sleep_time = options.get("sleep_time" , sleep_time ) - -cond_unlink(EXIT_file) -cond_unlink(STATUS_file) -cond_unlink(OK_file) -fileH = open(STATUS_file , "a") -fileH.write("%-32s: %s/%s\n" % ("Current host" , socket.gethostname() , os.uname()[4])) -fileH.close() - - -random.seed() - -for job in jobs.jobList: - # To ensure compatibility with old versions. - if not job.has_key("max_running_minutes"): - job["max_running_minutes"] = None - -if len(sys.argv) == 2: - # Normal batch run. - for job in jobs.jobList: - fileH = open(STATUS_file , "a") - now = time.localtime() - fileH.write("%-32s: %02d:%02d:%02d .... " % (job["name"] , now.tm_hour , now.tm_min , now.tm_sec)) - fileH.close() - (OK , exit_status, error_msg) = run_one(job) - now = time.localtime() - if OK: - fileH = open(STATUS_file , "a") - fileH.write("%02d:%02d:%02d \n" % (now.tm_hour , now.tm_min , now.tm_sec)) - fileH.close() - else: - fileH = open(EXIT_file , "a") - fileH.write("%02d:%02d:%02d \n" % (now.tm_hour , now.tm_min , now.tm_sec)) - fileH.write("%s : failed\n" % job["name"]) - fileH.write("%s\n" % error_msg) - fileH.close() - sys.exit(exit_status) - - - if OK: - fileH = open("OK" , "w") - fileH.write("All jobs complete") - fileH.close() - time.sleep( sleep_time ) # Let the disks sync up -else: - #Interactive run - jobHash = {} - for job in jobs.jobList: - jobHash[job["name"]] = job - - for job_name in sys.argv[2:]: - # This is totally unpredictable if there more jobs with - # the same name. - if jobHash.has_key( job_name ): - job = jobHash[job_name] - print('Running job: %s ... ' % job_name, end='') - sys.stdout.flush() - (OK , exit_status, error_msg) = run_one( job ) - if OK: - print('OK') - else: - print('failed ...') - print('-----------------------------------------------------------------') - if job.get("stderr"): - print('Error:%s ' % error_msg) - if os.path.exists(job["stderr"]): - fileH = open(job["stderr"],"r") - for line in fileH.readlines(): - print(line, end='') - fileH.close() - print('-----------------------------------------------------------------') - sys.exit() - else: - print('Job: %s does not exist. Available jobs:' % job_name) - for j in jobs.jobList: - print(' %s' % j['name']) diff --git a/ThirdParty/Ert/share/gui/doc/documentation.txt b/ThirdParty/Ert/share/gui/doc/documentation.txt deleted file mode 100644 index 7a25a71ffc..0000000000 --- a/ThirdParty/Ert/share/gui/doc/documentation.txt +++ /dev/null @@ -1,70 +0,0 @@ -ERTGUI core documentation - - Codebase in C Codebase in Python - -+--------------------+ +-------------------------+ -| ERT |/------------\| ErtWrapper | -| shared C library |\------------/| ctypes wrapper | -+--------------------+ | (C <-> Python comm.) | - +-------------------------+ - /\ - || - || - \/ - +-------------------------+ - | ContentModel | - | Class for fetching and | - | updating data in ERT | - +-------------------------+ - /\ - || - || - \/ - +-------------------------+ - | Widgets | - | GUI components that | - | enables presentation | - | and modification of | - | data in ERT | - +-------------------------+ - - -ERT: - the base software which the GUI controls. - -ErtWrapper: - this class simplifies the link between Python code and the exposed - functions of the shared library of ERT. - All communication between ERT and the GUI is performed through this - class and type safety of the functions in the shared library are - provided through a prototyping functionality. - -ContentModel: - This class is a base class for all widgets and algorithms that need - to communicate with ERT. Several abstract functions are defined that - must/can be implemented: - * initialize(model): typically used for prototyping of functions - * getter(model): used to fetch data from ERT - * setter(model, value): used for updating data values - * insert(model, value): used for adding data values - * remove(model, value): used for removing data values - - The program should never call these functions directly but use: - * getFromModel(): which will call the getter automatically - * updateContent(value, operation = UPDATE|INSERT|REMOVE): - which will call setter/insert/remove respectively automatically. - - A final function that must be implemented is fetchContent(). This function - will automatically be called when the model (ERT) is ready or has been - changed. This is also safe to be called by the program. Typical use of this - function is to call getFromModel() which returns the data generated by the - implemented getter function and then populate the widgets with the data. - - Whenever changes are made to the GUI ERT should be updated by calls - to updateContent(). - -Widgets: - Several widgets have been implemented. Most of these subclass HelpedWidget - which subclass ContentModel and provide built-in help functionality. - - diff --git a/ThirdParty/Ert/share/gui/doc/info.txt b/ThirdParty/Ert/share/gui/doc/info.txt deleted file mode 100644 index 09b28d82a0..0000000000 --- a/ThirdParty/Ert/share/gui/doc/info.txt +++ /dev/null @@ -1,244 +0,0 @@ -forward_model: --------------- - -get: ----- -model_config = enkf_main_get_model_config( enkf_main ) -forward_model = model_config_get_forward_model( model_config ) -names = forward_model_alloc_joblist( forward_model ) <- Allokerer en stringlist() med navnene på jobbene. - - - -set ---- -forward_model_clear( forward_model ) - -forward_model_add_job( forward_model , job_name ); -forward_model_iset_job_arg( forward_model , job_nr , key , value); <- Set argument - observe that the jobs are identified with the index in - the forward model, and not by name. - -more ----- -s = enkf_main_get_site_config( enkf_main ) -joblist = site_config_get_installed_jobs( s ); -job_names = ext_joblist_alloc_list( joblist ); <- Stringlist - - - -forward_model_get_job( forward_model , ?NAME?) -ext_joblist_get_job( joblist , ?NAME?) - -ext_job = forward_model_iget_job( forward_model , job_nr ) -arg_string = ext_job_get_private_args_as_string( ext_job ); -ext_job_set_private_args_from_string( ext_job , "KEY1=Value1 , Key2=value2" ) - - -ext_job_get_help_text( job ); - - --------------------------------------- - - -LOG: - -Get ---- -log_file = enkf_main_get_log_file( enkf_main ) -log_level = enkf_main_get_log_level( enkf_main ) - - -Set ---- -enkf_main_set_log_file( enkf_main , "log_file" ) -enkf_main_set_log_level( enkf_main , log_level ) - - -analysis_config = enkf_main_get_analysis_config( enkf_main ) -log_path = analysis_config_get_log_path( analysis_config ); -analysis_config_set_log_path( analysis_config , log_path ); - - - - -INITIALIZED ------------ - -enkf_main_is_initialized(enkf_main , active_mask); - -active_mask er nå en vector av typen: bool_vector som er implementert i -libutil. Dersom alle elemementene er aktive kan du sende inn None / -NULL, ellers må allokere og initialisere en active_mask instans: - -mask = bool_vector_alloc(0 , false) -for index in selectedMembers: - bool_vector_iset( mask , index , true ) - -enkf_main_is_initialized( enkf_main , mask ) -bool_vector_free( mask ) - - - - -TEMPLATES: ----------- -Get: ----- -templates = enkf_main_get_templates( enkf_main ); -s = ert_templates_alloc_list( templates ); <- Returnerer en stringlist med navn -template = ert_templates_get_template( templates , "Navn") -template_file = ert_template_get_template_file( template ); -target_file = ert_template_get_target_file( template ); -arg_string = ert_template_get_args_as_string( template ) - - -Set: (kan enten gjøres med manuelle add / del eller ved hjelp av clear og add). ----- -templates = enkf_main_get_templates( enkf_main ); -ert_templates_clear( templates ); -ert_templates_del_template( templates , "Key"); -template = ert_templates_add_template( templates , "Key", "Template_file" , "target_file" , arg_string /* Can be None / NULL */); - -template = ert_templates_get_template( templates , Key) -ert_template_set_target_file(template , target_file ); -ert_template_set_template_file(template , template_file ); -ert_template_set_args_as_string(template , arg_string); - - - - - -INITIALIZATION --------------- - -enkf_main_initialize_from_existing__( enkf_main , source_case , source_step , source_state , - iens_mask , ranking_key /* Will be NULL*/ , - node_list); - - - -node_list ~ stringlist med de valgt nodene. - -iens_mask = bool_vector_alloc(0 , false); <- Allokereres med false som default. -iens_mask ~ bool_vector hvor alle de aktive indeksene er satt til true - - - -SCHEDULE_PREDICTION_FILE ------------------------- -Get: enkf_main_get_schedule_prediction_file( enkf_main ) -Set: enkf_main_set_schedule_prediction_file( enkf_main , filename ) - - -REFCASE -------- -Get: -ecle_config = enkf_main_get_ecl_config( enkf_main ); -refacse = ecl_config_get_refcase_name( ecl_config ) - -Set: -enkf_main_set_refcase( enkf_main , refcase ) ???????????????????? Ikkje load? - - - -HISTORY_SOURCE --------------- -Get: -m = enkf_main_get_model_config( enkf_main ) -history_source = model_config_get_history_source( m ) <- History_source ~ enum history_source_type fra libsched/src/history.y - - -Set: -m = enkf_main_get_model_config( enkf_main ) -model_config_get_history_source( m , source) <- NB Hvis source har en av verdiene REFCASE_HISTORY / REFCASE_SMULATED du maa satt ett REFACSE forst. - - - -PRE_CLEAR_RUNPATH: ------------------ -Get: enkf_main_get_pre_clear_runpath( enkf_main ) <- Return value: true | false -Set: enkf_main_set_pre_clear_runpath( enkf_main , true | false ) - - - - -CASE_TABLE ----------- -model_config = enkf_main_get_model_config( enkf_main ); - -get: model_config_get_case_table_file( model_config ) -set: enkf_main_set_case_table( model_config , filename ); <- File must exist - - - -REFCASE - Plotting: ------------------- -Get: - -ecl_config = enkf_main_get_ecl_config( enkf_main ) -ecl_sum = ecl_config_get_refcase( ecl_config ) - -Plotting: - - 1. Sjekk om refcase har variabel: - - ecl_sum_has_general_var( ecl_sum , key) - - hvor 'key' er en summary key, som for eksempel "WWCT:OP_1". Dersom denne funksjonen returnerer true, maa du - sporre ecl_sum som en "oversettelse" fra key til en integer index, og siden bruke den indeksen: - - key_index = ecl_sum_get_general_var_index( ecl_sum , key ); - - - 2. Alloker en tidsakse: - - time_vector = ecl_sum_alloc_time_vector( ecl_sum , true /* Report_only kan vre true */); - - Denne kan selvflgelig gjenbrukes mellom flere summary plott. - - 3. Alloker datavektor - - data_vektor1 = ecl_sum_alloc_data_vector( ecl_sum , key_index1 , true ); - - - Da har du x og y i en hhv time_t_vector og double_vector - en av joakims hjemmelade datastrukturer: - - size: xxx_vector_get_size( ) - get1: xxx_vector_iget( ) - get2: xxx_vector_get_ptr() <- Returnerer en peker til underliggende data. - - - 4. xxx_vector_free () naar du er ferdi. - - -5. (Ekstraoppgave:) en ecl_sum instans kan også loades fra filsystemet (helt utenfor ERT sin database) med - - ecl_sum = ecl_sum_fread_alloc_case( "Navn på en ECLIPSE.DATA fil" ) - ---------------------- - -Gen_data: -size: ------ -ensemble_config = enkf_main_get_ensemble_config( enkf_main ) -config_node = ensemble_config_get_node( ensemble_config , "KEY") -gen_data_config = enkf_config_node_get_ref( config_node ) - -size = gen_date_config_get_initial_size( gen_data_config ) - -Value: ------ -value = enkf_node_user_get( enkf_node , "KEY:tall" , &valid) <----- NB Det er helt avgjørende å sjekke at valid returnerer true, - gen_data typen er (altfor) fleksibel, og kan endre størrelse runtime. - At du har sjekket initiell størrelse er derfor desverre ikke tilstrekkelig - til å validere input. - - ----------------- -Saving: - -1. Sette config file: enkf_main_set_user_config_file( enkf_main , "config_file" ) [Denne trengs for "Save AS"] -2. enkf_main_fprintf_config( enkf_main ); - - - - \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/doc/initializers b/ThirdParty/Ert/share/gui/doc/initializers deleted file mode 100644 index 26ec3d9224..0000000000 --- a/ThirdParty/Ert/share/gui/doc/initializers +++ /dev/null @@ -1,201 +0,0 @@ - -mask = util.bool_vector_alloc(ens_size , false) -# Første arg: størrelse -# Andre arg: init verdi. - -util.bool_vector_iset( mask , 67 , true ) -# bool_ptr = util.bool_vector_get_ptr( mask ) -# Send inn int_ptr -.... -#util.bool_vector_free( mask ) - - - - - - - -#Missing initializer: job_script -# s = enkf_main_get_site_config( enkf_main ) -# site_config_get_job_script( s ); -# site_config_set_job_script( s , EXECUTABLE_FILE ); - - - - -Missing initializer: install_job - s = enkf_main_get_site_config( enkf_main ); - site_config_install_job( s , JOB_KEY , EXISTING_FILE ); <- Should have a GUI option for creating the - config file EXISTING_FILE - -INSTALL_JOB: ------------ -1. Denne bør endre navn til "Private jobs" - -2. Her blir get/set ganske komplisert - det er to grunner til det: - - a) Listen over installerte jobber inneholder både globale jobber, - som brukeren ikke har anledning til å manipulere, og "Private" - jobber som brukeren har installert og således må få lov til å - manipulere. - - b) Foreløpig er det bare basert en config_file, men når vi først - lager GUI ville det være veldig naturlig å lage mulighet for å - konfigurere en jobb via GUI. - -3. Det opprinnelige GUI panelet består av to felt. Kutt ut det ene - feltet, men la det sprette opp ett vindu når man legger til en - jobb. - - -Get: -s = enkf_main_get_site_config( enkf_main ) -jl = site_config_get_installed_jobs( s ) -h = ext_joblist_get_jobs( jl ) <- Nå er h en hash tabell. - -#Itererer over hash_tabellen: -python_joblist = [] -job = hash_get( h , job_name ); -if ext_job_is_private( job ): <- Denne funksjonen er i libjob_queue - python_joblist.append( job_name ) - -OK : python_joblist skal inneholde de job_navnene som skal - vises i GUI. - - - -Set: Her tror jeg det er enklest å respondere eksplisitt på add_job og - del_job events, istedet for å ta en batch prosess til slutt - -add_job: --------- -job = ext_job_fscanf_alloc( job_name , site_config_get_license_root_path__( s ) , job_config_file ) # job_name and job_config_file from GUI. -ext_joblist_add_job( jl , job ) - - -del_job -------- -ext_joblist_del_job( jl , job_name ) - - - - - - -#Missing initializer: num_realizations -# enkf_main_get_ensemble_size( enkf_main ); -# enkf_main_resize_ensemble( enkf_main ); <- Denne kan potensielt ta en del tid, og - bør være beskyttet av en APPLY knapp. - - -Missing initializer: parameters -Missing initializer: param_type -Missing initializer: param_min -Missing initializer: param_max -Missing initializer: param_init -Missing initializer: param_output -Missing initializer: param_init_files -Missing initializer: param_file_generated_by_enkf -Missing initializer: param_file_loaded_by_enkf -Missing initializer: history_source -Missing initializer: obs_config - - - -#Missing initializer: max_submit -# s = enkf_main_get_site_config( enkf_main ); -# site_config_get_max_submit( s ); -# site_config_set_max_submit( s , max_submit ); - - - - -#Missing initializer: max_resample -# m = enkf_main_get_model_config( enkf_main ); -# model_config_get_max_resample( m ); -# model_config_set_max_resample( m , max_resample ); - - - -Missing initializer: forward_model -Missing initializer: case_table -Missing initializer: license_path - -Missing initializer: runpath -# m = enkf_main_get_model_config( enkf_main ) -# model_config_get_runpath_fmt( m ) -# model_config_set_runpath_fmt( m , "/path/to/run%d" ) - - - -Missing initializer: pre_clear_runpath -Missing initializer: delete_runpath -Missing initializer: keep_runpath -Missing initializer: run_template -Missing initializer: dbase_type -Missing initializer: enspath -Missing initializer: select_case - - -#Missing initializer: log_file -#Missing initializer: log_level -# lg = enkf_main_get_logh( enkf_main ); -# log_reset_filename( lg , "/some/path/to/FILENAME" ); -# log_get_filename( lg ); -# -# log_get_level( lg ); -# log_set_level( lg , LOG_LEVEL) - - - -Missing initializer: update_log_path - - - - -#Get: s = enkf_main_get_data_kw( enkf_main ) -# subst_list_get_size( s ) -# subst_list_iget_key( s ) -# subst_list_iget_value( s ) -#Set: enkf_main_clear_data_kw( enkf_main ) -# enkf_main_add_data_kw( enkf_main , key , value ) - -#Get: m = enkf_main_get_model_config( enkf_main ) -# model_config_get_enkf_sched_file( m ) -#Set: model_config_set_enkf_sched_file( m , "FILENAME" ) - -#Get l = enkf_main_get_local_config( enkf_main ); -# s = local_config_get_config_files( l ) # Stringlist -#Set local_config_clear_config_files( l ) -# local_config_add_config_file(l , "FILENAME") - -#Get s = enkf_main_get_site_config( enkf_main ) -# site_config_get_max_running_(lsf|rsh|local)( s ) -#Set site_config_get_max_running_(lsf|rsh|local)( s , value ) - -#Get s = enkf_main_get_site_config( enkf_main ) -# h = site_config_get_rsh_host_list( s ) -# Iterer over hash - men bruk hash_get_int() for aa faa antall jobber en host kan ta. -#Set site_config_clear_rsh_host_list( s ) -# site_config_add_rsh_host( s , host_name , max_running ) - -#Get s = enkf_main_get_site_config( enkf_main ) -# queue_name = site_config_get_lsf_queue( s ) -#Set site_config_set_lsf_queue( s , "NORMAL" ) - -# site_config_set_job_queue( s , "LOCAL|LSF|RSH" ); -# site_config_get_job_queue_name( s ); - -#self.job_script = "..." -#self.setenv = [["LSF_BINDIR", "/prog/LSF/7.0/linux2.6-glibc2.3-x86_64/bin"], ["LSF_LIBDIR", "/prog/LSF/7.0/linux2.6-glibc2.3-x86_64/lib"]] -#Get: s = enkf_main_get_site_config( enkf_main ) -# h = site_config_get_env_hash( s ) -#Set site_config_clear_env( s ) -# site_config_setenv( s , var , value ) - -#self.update_path = [["PATH", "/prog/LSF/7.0/linux2.6-glibc2.3-x86_64/bin"], ["LD_LIBRARY_PATH", "/prog/LSF/7.0/linux2.6-glibc2.3-x86_64/lib"]] -#Get: s = enkf_main_get_site_config( enkf_main ) -# pathlist = site_config_get_path_variables( s ) -# valuelist = site_config_get_path_values( s ) -#Set: site_config_clear_pathvar( s ) -# site_config_update_pathvar( s , path , value ); diff --git a/ThirdParty/Ert/share/gui/doc/run_info b/ThirdParty/Ert/share/gui/doc/run_info deleted file mode 100644 index 3c7280a722..0000000000 --- a/ThirdParty/Ert/share/gui/doc/run_info +++ /dev/null @@ -1,36 +0,0 @@ -state = enkf_main_iget_state( enkf_main , iens ); -status = enkf_state_get_run_status( state ); -sim_start = enkf_state_get_start_time( state ); -submit_time = enkf_state_get_submit_time( state ); - - -Queue running: -------------- -s = enkf_main_get_site_config( enkf_main ) -site_config_queue_is_running( s ) - - -Kill simulation ---------------- -enkf_state_kill_simulation( state ) - - -Restart simulation ------------------- -enkf_state_restart_simulation( state , resample ) /* Resample er en bool - True: Kjør ny initialisering */ - - - - -Main queue pausing: -------------------- -job_queue_get_pause( jq ) - -job_queue_set_pause_on( jq ) - -job_queue_set_pause_off( jp ) - - - - - diff --git a/ThirdParty/Ert/share/gui/doc/tmp_info.txt b/ThirdParty/Ert/share/gui/doc/tmp_info.txt deleted file mode 100644 index bc63f69f66..0000000000 --- a/ThirdParty/Ert/share/gui/doc/tmp_info.txt +++ /dev/null @@ -1,69 +0,0 @@ -GEN_DATA (Det er ikke skille p GEN_DATA og GEN_PARAM - alt er GEN_DATA) --------- - -1. Opprette en ny: ensemble_config_add_gen_data( ensemble_config , new_key ); - - -2 Get: - - gen_data_config = enkf_config_node_get_ref( config_node ); - - output_format = gen_data_config_get_output_format( gen_data_config ); <- Returverdien her er en enum: gen_data_file_format_type, - input_format = gen_data_config_get_input_format( gen_data_config ); definert i gen_data_config.h - template_file = gen_data_config_get_template_file( gen_data_config ); - template_key = gen_data_config_get_template_key( gen_data_config ); - init_file_fmt = gen_data_config_get_init_file_fmt( gen_data_config ); - ..... - enkf_config_node_get_enkf_outfile( config_node ) -> Include file (parameter/general) - enkf_config_node_get_min_std_file( config_node ) -> Min. std. (parameter/general) - enkf_config_node_get_enkf_infile( config_node ) -> File loaded by EnKF (general) - - - -3. Update: - - enkf_config_node_update_gen_data( config_node , input_format , output_format , /* Enum: gen_data_file_format_type */ - init_file_format , - template_file , - template_key , - enkf_outfile_fmt , - enkf_infile_fmt , - min_std_file ); - - Legg merke til at det er ganske MAANGE innbyrdes krav mellom de - forskjellige variablene som maa vaere tilfredsstilt; dette er - "dokumentert" i funksjonene enkf_config_node_update_gen_data() og - gen_data_config_update(). - - - - - -OBS_CONFIG: ----------- - -Get: ----- -obs = enkf_main_get_obs( enkf_main ); -enkf_obs_get_config_file( obs ); - - -Set: -enkf_main_load_obs( enkf_main , obs_config_file ); - - - - - -KEEP_RUNPATH / DELETE_RUNPATH ------------------------------ - -Denne variabelen er definert som en streng i tui - jeg foreslaar at du -heller bruker en tilsvarende tilnaerming som naar vi skal velge hvilke -realisasjoner som skal simuleres paa, hver av de smaa boksene skal ha -tre mulige verdier, tilsvarende enum keep_runpath_type i enkf_types.h. - -Deretter: - -enkf_main_iget_keep_runpath( enkf_main , index ); -enkf_main_iset_keep_runpath( enkf_main , index , enum_value ); diff --git a/ThirdParty/Ert/share/gui/help/config/analysis/analysis_module.html b/ThirdParty/Ert/share/gui/help/config/analysis/analysis_module.html deleted file mode 100644 index f0b8207c57..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/analysis/analysis_module.html +++ /dev/null @@ -1 +0,0 @@ -Select which type of ensemble smoother to use for perform updates \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/analysis/iterated_analysis_module.html b/ThirdParty/Ert/share/gui/help/config/analysis/iterated_analysis_module.html deleted file mode 100644 index adea08022e..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/analysis/iterated_analysis_module.html +++ /dev/null @@ -1 +0,0 @@ -Select which type of iterated ensemble smoother to use for perform updates \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/init/history_length.html b/ThirdParty/Ert/share/gui/help/config/init/history_length.html deleted file mode 100644 index df8285cb42..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/init/history_length.html +++ /dev/null @@ -1 +0,0 @@ -The timestep of the source case from which the initial values are copied \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/add_fixed_length_schedule_kw.html b/ThirdParty/Ert/share/gui/help/config/keywords/add_fixed_length_schedule_kw.html deleted file mode 100644 index 7fd6807ce1..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/add_fixed_length_schedule_kw.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/add_static_kw.html b/ThirdParty/Ert/share/gui/help/config/keywords/add_static_kw.html deleted file mode 100644 index c78e0cbbc3..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/add_static_kw.html +++ /dev/null @@ -1,15 +0,0 @@ -The restart files from ECLIPSE are organized by keywords, which are of three different types: -
    -
  1. Keywords containing the dynamic solution, e.g. pressure and saturations.
  2. -
  3. Keywords containing various types of header information which is needed for a restart.
  4. -
  5. Keywords containing various types of diagnostic information which is not needed for a restart.
  6. -
- -Keywords in category 2 and 3 are referred to as static keywords. To be able to restart ECLIPSE, the ERT application has to store the keywords in category 2, whereas keywords in category 3 can safely be dropped. To determine whether a particular keyword is in category 2 or 3 ERT considers an internal list of keywords. The current list contains the keywords: - -
INTEHEAD LOGIHEAD DOUBHEAD IGRP SGRP XGRP ZGRP IWEL SWEL XWEL ZWEL
- ICON SCON XCON HIDDEN STARTSOL PRESSURE SWAT SGAS RS RV ENDSOL ICAQNUM ICAQ IAAQ
- SCAQNUM SCAQ SAAQ ACAQNUM ACAQ XAAQ
- ISEG ILBS ILBR RSEG ISTHW ISTHG
-
-Here you can dynamically add to this list. The magic string __ALL__ will add all static keywords, but use of this option is strongly discouraged, as it wastes a lot of disk space. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_copy.html b/ThirdParty/Ert/share/gui/help/config/keywords/analysis_copy.html deleted file mode 100644 index bb65f45d44..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_copy.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_enkf_update.html b/ThirdParty/Ert/share/gui/help/config/keywords/analysis_enkf_update.html deleted file mode 100644 index ba92057398..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_enkf_update.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_load.html b/ThirdParty/Ert/share/gui/help/config/keywords/analysis_load.html deleted file mode 100644 index 0439e95c26..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_load.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_select.html b/ThirdParty/Ert/share/gui/help/config/keywords/analysis_select.html deleted file mode 100644 index 5be06c89cb..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_select.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_set_var.html b/ThirdParty/Ert/share/gui/help/config/keywords/analysis_set_var.html deleted file mode 100644 index 7513aae255..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_set_var.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_update.html b/ThirdParty/Ert/share/gui/help/config/keywords/analysis_update.html deleted file mode 100644 index be8ec82a19..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/analysis_update.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/case_table.html b/ThirdParty/Ert/share/gui/help/config/keywords/case_table.html deleted file mode 100644 index a0597c4844..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/case_table.html +++ /dev/null @@ -1 +0,0 @@ -For running sensitivies you can give the cases descriptive names. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/config_help.py b/ThirdParty/Ert/share/gui/help/config/keywords/config_help.py deleted file mode 100644 index 079efe92f3..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/config_help.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/prog/sdpsoft/python2.6.7/bin/python - - -f= open('keywords.txt', "r") -for line in f: - tokens=line.split() - fname = tokens[0]+".html" - href = "Click here to view help on the wiki page." - file= open(fname, "w") - file.write (href) - file.close() -f.close() \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/create_case.html b/ThirdParty/Ert/share/gui/help/config/keywords/create_case.html deleted file mode 100644 index 7a634a6b3a..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/create_case.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/data_file.html b/ThirdParty/Ert/share/gui/help/config/keywords/data_file.html deleted file mode 100644 index 280a668f08..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/data_file.html +++ /dev/null @@ -1 +0,0 @@ -The ECLIPSE data file used to control the simulations. The standard ECLIPSE data file needs to be modified in some ways in order to work with ERT. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/data_kw.html b/ThirdParty/Ert/share/gui/help/config/keywords/data_kw.html deleted file mode 100644 index 50e7d08a0d..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/data_kw.html +++ /dev/null @@ -1 +0,0 @@ -Using Data keywords you can assign arbitrary (Keyword , Value) pairs where all occurences of <Keyword> in the ECLIPSE Data file will be replaced by Value. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/data_ranking.html b/ThirdParty/Ert/share/gui/help/config/keywords/data_ranking.html deleted file mode 100644 index 9336015252..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/data_ranking.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/define.html b/ThirdParty/Ert/share/gui/help/config/keywords/define.html deleted file mode 100644 index b1f1a19e61..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/define.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/delete_runpath.html b/ThirdParty/Ert/share/gui/help/config/keywords/delete_runpath.html deleted file mode 100644 index 397ba46143..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/delete_runpath.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/eclbase.html b/ThirdParty/Ert/share/gui/help/config/keywords/eclbase.html deleted file mode 100644 index e4ba02e992..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/eclbase.html +++ /dev/null @@ -1,5 +0,0 @@ -The basename used for the ECLIPSE simulations. The name should contain a %d-specifier, which will be replazed by the realization number when running ECLIPSE.
- -Example: BASE_%04d will be replaced by BASE_0007 for realization number 7.
- -Note that due to limitations in ECLIPSE, the basename must be in strictly upper or lower case. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/end_date.html b/ThirdParty/Ert/share/gui/help/config/keywords/end_date.html deleted file mode 100644 index 13ea1a5f5b..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/end_date.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_alpha.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_alpha.html deleted file mode 100644 index 5534d25dc1..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_alpha.html +++ /dev/null @@ -1 +0,0 @@ -A parameter controlling outlier behaviour in the EnKF algorithm. The default value is 1.50. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_bootstrap.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_bootstrap.html deleted file mode 100644 index 62c4d5e1e0..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_bootstrap.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_cv_folds.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_cv_folds.html deleted file mode 100644 index 8d32df09a6..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_cv_folds.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_force_ncomp.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_force_ncomp.html deleted file mode 100644 index bff2df9366..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_force_ncomp.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_local_cv.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_local_cv.html deleted file mode 100644 index 7ea90f84f9..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_local_cv.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_merge_observations.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_merge_observations.html deleted file mode 100644 index 274c5023ea..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_merge_observations.html +++ /dev/null @@ -1 +0,0 @@ -If you use the ENKF schedule file option to jump over several dates at a time you can choose whether you want to use all the observations in between, or just the final. Select Perform merge if you want all observations to be used, unselect to use only the final observation. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_mode.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_mode.html deleted file mode 100644 index 3a31f07936..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_mode.html +++ /dev/null @@ -1 +0,0 @@ -Here you select which EnKF algorithm to use. Use ENKF_STANDARD for the original EnKF algorithm, or ENKF_SQRT for the square root scheme. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_ncomp.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_ncomp.html deleted file mode 100644 index 438e8b761d..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_ncomp.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_pen_press.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_pen_press.html deleted file mode 100644 index 7385cf5292..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_pen_press.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_rerun.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_rerun.html deleted file mode 100644 index 3f7b3ec169..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_rerun.html +++ /dev/null @@ -1 +0,0 @@ -Select if the simulation should be started from time zero after each update. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_scaling.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_scaling.html deleted file mode 100644 index 26f232374d..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_scaling.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_truncation.html b/ThirdParty/Ert/share/gui/help/config/keywords/enkf_truncation.html deleted file mode 100644 index cc87ad385f..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enkf_truncation.html +++ /dev/null @@ -1 +0,0 @@ -Cutoff used on singular value spectrum. Default value: 0.99. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/ensemble_run.html b/ThirdParty/Ert/share/gui/help/config/keywords/ensemble_run.html deleted file mode 100644 index d0c173a933..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/ensemble_run.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/enspath.html b/ThirdParty/Ert/share/gui/help/config/keywords/enspath.html deleted file mode 100644 index cc2d44680e..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/enspath.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/export_field.html b/ThirdParty/Ert/share/gui/help/config/keywords/export_field.html deleted file mode 100644 index e1cf6dddec..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/export_field.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/export_field_ecl_grdecl.html b/ThirdParty/Ert/share/gui/help/config/keywords/export_field_ecl_grdecl.html deleted file mode 100644 index 256e994c04..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/export_field_ecl_grdecl.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/export_field_rms_roff.html b/ThirdParty/Ert/share/gui/help/config/keywords/export_field_rms_roff.html deleted file mode 100644 index 69b24e56a4..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/export_field_rms_roff.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/export_ranking.html b/ThirdParty/Ert/share/gui/help/config/keywords/export_ranking.html deleted file mode 100644 index 82e3807b97..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/export_ranking.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/field.html b/ThirdParty/Ert/share/gui/help/config/keywords/field.html deleted file mode 100644 index 7002f52e4e..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/field.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/forward_model.html b/ThirdParty/Ert/share/gui/help/config/keywords/forward_model.html deleted file mode 100644 index ef7799a67b..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/forward_model.html +++ /dev/null @@ -1 +0,0 @@ -The Forward model defines how the simulations are executed. E.g., which version of ECLIPSE to use, which rel.perm script to run, which rock physics model to use etc. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/gen_data.html b/ThirdParty/Ert/share/gui/help/config/keywords/gen_data.html deleted file mode 100644 index 4225d803d4..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/gen_data.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/gen_kw.html b/ThirdParty/Ert/share/gui/help/config/keywords/gen_kw.html deleted file mode 100644 index 92666c8c31..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/gen_kw.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/gen_param.html b/ThirdParty/Ert/share/gui/help/config/keywords/gen_param.html deleted file mode 100644 index d8ac1acef5..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/gen_param.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/grid.html b/ThirdParty/Ert/share/gui/help/config/keywords/grid.html deleted file mode 100644 index 163472e188..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/grid.html +++ /dev/null @@ -1 +0,0 @@ -This should point to an existing GRID/EGRID-file belonging to your ECLIPSE-model. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/history_source.html b/ThirdParty/Ert/share/gui/help/config/keywords/history_source.html deleted file mode 100644 index eddb472db1..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/history_source.html +++ /dev/null @@ -1,9 +0,0 @@ -ERT will read the historic rates from the Schedule file, but it is also possible to use historic data from another ECLIPSE run (e.g if historic data do not exist in the Schedule file). -
-
SCHEDULE -
ERT will use the historic data provided in the Schedule file. -
REFCASE_SIMULATED -
ERT will use simulated values from another ECLIPSE run (a Reference case) as historic data. -
REFCASE_HISTORY -
ERT will use historic data from a reference case. -
diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/image_type.html b/ThirdParty/Ert/share/gui/help/config/keywords/image_type.html deleted file mode 100644 index 012875d225..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/image_type.html +++ /dev/null @@ -1 +0,0 @@ -In which format should the plots created by PLPLOT be saved (default: png). diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/image_viewer.html b/ThirdParty/Ert/share/gui/help/config/keywords/image_viewer.html deleted file mode 100644 index 422c6d7417..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/image_viewer.html +++ /dev/null @@ -1,5 +0,0 @@ -Here you may decide which application to use to view the plots. The default is a program called /usr/bin/display. -
-
-In order to avoid the plots from flashing in your face as they are created, set Image viewer to /d/proj/bg/enkf/bin/noplot.sh -. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/init_case_from_existing.html b/ThirdParty/Ert/share/gui/help/config/keywords/init_case_from_existing.html deleted file mode 100644 index ba679851bf..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/init_case_from_existing.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/init_misfit_table.html b/ThirdParty/Ert/share/gui/help/config/keywords/init_misfit_table.html deleted file mode 100644 index a242e1e5ce..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/init_misfit_table.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/init_section.html b/ThirdParty/Ert/share/gui/help/config/keywords/init_section.html deleted file mode 100644 index cd2dacddcc..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/init_section.html +++ /dev/null @@ -1,6 +0,0 @@ -The Init section is used to handle initialization of the ECLIPSE run. -This can be used in two different ways: -
    -
  • If it is set to the name of an existing file, the contents of this file will be used for the initialization. -
  • If it is set to the name of a non-existing file, it will be assumed that a file with this name in the simulation folder will be generated when simulations are submitted, either by the ERT application itself, or by some job installed by the user. This generated file will then be used by ECLIPSE for initialization. -
diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/install_job.html b/ThirdParty/Ert/share/gui/help/config/keywords/install_job.html deleted file mode 100644 index 8c97722da7..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/install_job.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/job_script.html b/ThirdParty/Ert/share/gui/help/config/keywords/job_script.html deleted file mode 100644 index bb05afd9a4..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/job_script.html +++ /dev/null @@ -1,7 +0,0 @@ -Running the forward model from enkf is a multi-level process which can be summarized as follows: -
    -
  1. A Python module called jobs.py is written and stored in the directory where the forward simulation is run. This module contains a list of job-elements, where each element is a Python representation of the code entered when installing the job.
  2. -
  3. The ERT application submits a Python script to the EnKF queue system, this script then loads the jobs.py module to find out which programs to run, and how to run them.
  4. -
  5. The Job script starts and monitors the individual jobs in the jobs.py module.
  6. -
-Job script should point at the Python script which is managing the forward model. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/jobname.html b/ThirdParty/Ert/share/gui/help/config/keywords/jobname.html deleted file mode 100644 index c1b4e7290e..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/jobname.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/keywords.txt b/ThirdParty/Ert/share/gui/help/config/keywords/keywords.txt deleted file mode 100644 index ed221111e0..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/keywords.txt +++ /dev/null @@ -1,94 +0,0 @@ -data_file http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#DATA_FILE -eclbase http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ECLBASE -jobname http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#JOBNAME -grid http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#GRID -init_section http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#INIT_SECTION -num_realizations http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#NUM_REALIZATIONS -schedule_file http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SCHEDULE_FILE -data_kw http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#DATA_KW -delete_runpath http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#DELETE_RUNPATH -enkf_sched_file http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_SCHED_FILE -end_date http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#END_DATE -enspath http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENSPATH -select_case http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SELECT_CASE -history_source http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#HISTORY_SOURCE -refcase http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#REFCASE -install_job http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#INSTALL_JOB -keep_runpath http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#KEEP_RUNPATH -obs_config http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#OBS_CONFIG -result_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RESULT_PATH -runpath http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RUNPATH -runpath_file http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RUNPATH_FILE -min_realizations http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#MIN_REALIZATIONS -stop_long_running http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#STOP_LONG_RUNNING -max_runtime http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNTIME -field http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#FIELD -gen_data http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#GEN_DATA -gen_kw http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#GEN_KW -gen_param http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#GEN_PARAM -surface http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SURFACE -summary http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SUMMARY -enkf_alpha http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_ALPHA -enkf_bootstrap http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_BOOTSTRAP -enkf_cv_folds http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_CV_FOLDS -enkf_force_ncomp http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_FORCE_NCOMP -enkf_local_cv http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_LOCAL_CV -enkf_pen_press http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_PEN_PRESS -enkf_mode http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_MODE -enkf_merge_observations http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_MERGE_OBSERVATIONS -enkf_ncomp http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_NCOMP -enkf_rerun http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_RERUN -enkf_scaling http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_SCALING -enkf_truncation http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENKF_TRUNCATION -update_log_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#UPDATE_LOG_PATH -analysis_load http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_LOAD -analysis_select http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_SELECT -analysis_set_var http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_SET_VAR -analysis_copy http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_COPY -add_fixed_length_schedule_kw http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ADD_FIXED_LENGTH_SCHEDULE_KW -add_static_kw http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ADD_STATIC_KW -define http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#DEFINE -schedule_prediction_file http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SCHEDULE_PREDICTION_FILE -forward_model http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#FORWARD_MODEL -job_script http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#JOB_SCRIPT -queue_system http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#QUEUE_SYSTEM -lsf_server http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#LSF_SERVER -lsf_queue http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#LSF_QUEUE -max_running_lsf http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNNING_LSF -max_running_local http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNNING_LOCAL -rsh_host http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RSH_HOST -rsh_command http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RSH_COMMAND -max_running_rsh http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#MAX_RUNNING_RSH -image_viewer http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#IMAGE_VIEWER -image_type http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#IMAGE_TYPE -plot_driver http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_DRIVER -plot_errorbar http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_ERRORBAR -plot_errorbar_max http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_ERRORBAR_MAX -plot_height http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_HEIGHT -plot_refcase http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_REFCASE -refcase_list http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#REFCASE_LIST -plot_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_PATH -plot_width http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#PLOT_WIDTH -rft_config http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RFT_CONFIG -rftpath http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RFTPATH -select_case http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SELECT_CASE -create_case http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#CREATE_CASE -init_case_from_existing http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#INIT_CASE_FROM_EXISTING -export_field http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#EXPORT_FIELD -export_field_rms_roff http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#EXPORT_FIELD_RMS_ROFF -export_field_ecl_grdecl http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#EXPORT_FIELD_ECL_GRDECL -analysis_update http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_UPDATE -analysis_enkf_update http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ANALYSIS_ENKF_UPDATE -run_smoother http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RUN_SMOOTHER -run_smoother_with_iter http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#RUN_SMOOTHER_WITH_ITER -ensemble_run http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#ENSEMBLE_RUN -load_results http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#LOAD_RESULTS -load_results_iter http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#LOAD_RESULTS_ITER -observation_ranking http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#OBSERVATION_RANKING -data_ranking http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#DATA_RANKING -export_ranking http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#EXPORT_RANKING -init_misfit_table http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#INIT_MISFIT_TABLE -qc_workflow http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#QC_WORKFLOW -qc_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#QC_PATH -setenv http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#SETENV -update_path http://ert.nr.no/ert/index.php/Creating_a_configuration_file_for_ERT#UPDATE_PATH \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/license_path.html b/ThirdParty/Ert/share/gui/help/config/keywords/license_path.html deleted file mode 100644 index cd8d4a08f3..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/license_path.html +++ /dev/null @@ -1 +0,0 @@ -The path where the ERT-licenses for the different programs (such as RMS) are stored. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/load_results.html b/ThirdParty/Ert/share/gui/help/config/keywords/load_results.html deleted file mode 100644 index 2def17d6d9..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/load_results.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/load_results_iter.html b/ThirdParty/Ert/share/gui/help/config/keywords/load_results_iter.html deleted file mode 100644 index 11a79d6e59..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/load_results_iter.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/local_config.html b/ThirdParty/Ert/share/gui/help/config/keywords/local_config.html deleted file mode 100644 index cfa726e6db..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/local_config.html +++ /dev/null @@ -1 +0,0 @@ -This can point to a file with configuration information for local analysis. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/log_file.html b/ThirdParty/Ert/share/gui/help/config/keywords/log_file.html deleted file mode 100644 index 2e2eb3503b..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/log_file.html +++ /dev/null @@ -1 +0,0 @@ -The name of the log file. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/log_level.html b/ThirdParty/Ert/share/gui/help/config/keywords/log_level.html deleted file mode 100644 index dd3c264cbc..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/log_level.html +++ /dev/null @@ -1 +0,0 @@ -The amount of logging. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/lsf_queue.html b/ThirdParty/Ert/share/gui/help/config/keywords/lsf_queue.html deleted file mode 100644 index 7007bb48e0..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/lsf_queue.html +++ /dev/null @@ -1,2 +0,0 @@ -Select which LSF queue to use. - diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/lsf_resources.html b/ThirdParty/Ert/share/gui/help/config/keywords/lsf_resources.html deleted file mode 100644 index 266ae8a750..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/lsf_resources.html +++ /dev/null @@ -1 +0,0 @@ -Specify special LSF requirements here. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/lsf_server.html b/ThirdParty/Ert/share/gui/help/config/keywords/lsf_server.html deleted file mode 100644 index fd9aac3cc2..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/lsf_server.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/max_resample.html b/ThirdParty/Ert/share/gui/help/config/keywords/max_resample.html deleted file mode 100644 index 0e22f3505e..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/max_resample.html +++ /dev/null @@ -1 +0,0 @@ -How many times ERT should resample & retry a simulation. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/max_running_local.html b/ThirdParty/Ert/share/gui/help/config/keywords/max_running_local.html deleted file mode 100644 index 2fe1a41c97..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/max_running_local.html +++ /dev/null @@ -1 +0,0 @@ -Controls the maximum number of simultaneous jobs running when using the LOCAL option. It is strongly recommended to not let this number exceed the number of processors on the workstation used. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/max_running_lsf.html b/ThirdParty/Ert/share/gui/help/config/keywords/max_running_lsf.html deleted file mode 100644 index 607149cd96..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/max_running_lsf.html +++ /dev/null @@ -1 +0,0 @@ -Controls the maximum number of simultaneous jobs submitted to the LSF queue when using the LSF option. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/max_running_rsh.html b/ThirdParty/Ert/share/gui/help/config/keywords/max_running_rsh.html deleted file mode 100644 index a7d64dcd5c..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/max_running_rsh.html +++ /dev/null @@ -1 +0,0 @@ -Controls the maximum number of simultaneous jobs running when using the RSH option. If this number exceeds the total capacity defined in the RSH Host List, it will automatically be truncated to that capacity. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/max_runtime.html b/ThirdParty/Ert/share/gui/help/config/keywords/max_runtime.html deleted file mode 100644 index 3e1de4739b..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/max_runtime.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/max_submit.html b/ThirdParty/Ert/share/gui/help/config/keywords/max_submit.html deleted file mode 100644 index 3fcc40c76c..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/max_submit.html +++ /dev/null @@ -1 +0,0 @@ -How many times the queue system should retry a simulation. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/min_realizations.html b/ThirdParty/Ert/share/gui/help/config/keywords/min_realizations.html deleted file mode 100644 index 4f54035717..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/min_realizations.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/num_realizations.html b/ThirdParty/Ert/share/gui/help/config/keywords/num_realizations.html deleted file mode 100644 index 2b94172324..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/num_realizations.html +++ /dev/null @@ -1 +0,0 @@ -The number of members/realizations in your ensemble, i.e the ensemble size. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/obs_config.html b/ThirdParty/Ert/share/gui/help/config/keywords/obs_config.html deleted file mode 100644 index 267ab3e64b..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/obs_config.html +++ /dev/null @@ -1 +0,0 @@ -This should point to an observation file, a file defining observations and associated uncertainties. It is optional, but strongly recommended to provide an observation file. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/observation_ranking.html b/ThirdParty/Ert/share/gui/help/config/keywords/observation_ranking.html deleted file mode 100644 index be2ff2fe01..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/observation_ranking.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/plot_driver.html b/ThirdParty/Ert/share/gui/help/config/keywords/plot_driver.html deleted file mode 100644 index 249a95f9e0..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/plot_driver.html +++ /dev/null @@ -1,7 +0,0 @@ -The Plot Driver is the sub system used for creating plots. -
-
PLPLOT: -
This is the default system. All the other options regarding plotting are sub options which are only relevant when you are using this. -
TEXT: -
This will not produce any plots, just textfiles which can be used for plotting with your favorite plotting program. This is particularly relevant if you have some special requirements to the plots. -
diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/plot_errorbar.html b/ThirdParty/Ert/share/gui/help/config/keywords/plot_errorbar.html deleted file mode 100644 index 0568bb659d..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/plot_errorbar.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/plot_errorbar_max.html b/ThirdParty/Ert/share/gui/help/config/keywords/plot_errorbar_max.html deleted file mode 100644 index 011fec7881..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/plot_errorbar_max.html +++ /dev/null @@ -1,5 +0,0 @@ -When plotting summary vectors for which observations have been 'installed' with the Observation config, ERT will plot the observed values. If the number of observations is less than Errorbar max, ERT will use errorbars to show the observed values, otherwise it will use two dashed lines indicating +/- one standard deviation. -
-To ensure that you always get errorbars you can set Errorbar max to a very large value. On the other hand, setting Errorbar max to zero will ensure that ERT always plots observation uncertainty using dashed lines of +/- one standard deviation. -
-The setting here will also affect the output when you are using the TEXT driver to plot. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/plot_height.html b/ThirdParty/Ert/share/gui/help/config/keywords/plot_height.html deleted file mode 100644 index e33e7dfe74..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/plot_height.html +++ /dev/null @@ -1,2 +0,0 @@ -When the PLPLOT driver creates a plot file, it will have the height (in pixels) given by the PLOT_HEIGHT keyword. -The default value for PLOT_HEIGHT is 1024 pixels. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/plot_path.html b/ThirdParty/Ert/share/gui/help/config/keywords/plot_path.html deleted file mode 100644 index f40b2a22c5..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/plot_path.html +++ /dev/null @@ -1,3 +0,0 @@ -The plotting engine creates files with plots, they are stored in a directory. -You can tell what that directory should be. -Observe that the current casename automatically will be appended to the plot path. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/plot_refcase.html b/ThirdParty/Ert/share/gui/help/config/keywords/plot_refcase.html deleted file mode 100644 index a7d3d67fb9..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/plot_refcase.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/plot_width.html b/ThirdParty/Ert/share/gui/help/config/keywords/plot_width.html deleted file mode 100644 index 281295d50b..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/plot_width.html +++ /dev/null @@ -1,2 +0,0 @@ -When the PLPLOT driver creates a plot file, it will have the width (in pixels) given by the PLOT_WIDTH keyword. -The default value for PLOT_WIDTH is 1024 pixels. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/pre_clear_runpath.html b/ThirdParty/Ert/share/gui/help/config/keywords/pre_clear_runpath.html deleted file mode 100644 index a67c334861..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/pre_clear_runpath.html +++ /dev/null @@ -1 +0,0 @@ -Select Perform pre clear if you would like the runpath to be cleared before initilaizing. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/qc_path.html b/ThirdParty/Ert/share/gui/help/config/keywords/qc_path.html deleted file mode 100644 index 26029f50f1..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/qc_path.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/qc_workflow.html b/ThirdParty/Ert/share/gui/help/config/keywords/qc_workflow.html deleted file mode 100644 index 61ebf75d26..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/qc_workflow.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/queue_system.html b/ThirdParty/Ert/share/gui/help/config/keywords/queue_system.html deleted file mode 100644 index d23625073f..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/queue_system.html +++ /dev/null @@ -1,8 +0,0 @@ -Controls where the simulation jobs are executed. -
-
LSF: Submits the jobs to the LSF cluster at your location. -
RSH: Submits the jobs to a defined set of workstations. -
LOCAL: Submits the jobs to your local workstation. -
-
-More information in the wiki. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/refcase.html b/ThirdParty/Ert/share/gui/help/config/keywords/refcase.html deleted file mode 100644 index 519d42c654..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/refcase.html +++ /dev/null @@ -1 +0,0 @@ -Here you may supply ERT with a reference case, i.e an existing ECLIPSE data file, which can be used as observations. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/refcase_list.html b/ThirdParty/Ert/share/gui/help/config/keywords/refcase_list.html deleted file mode 100644 index 9fa95da112..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/refcase_list.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/rerun_start.html b/ThirdParty/Ert/share/gui/help/config/keywords/rerun_start.html deleted file mode 100644 index db11b245c1..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/rerun_start.html +++ /dev/null @@ -1 +0,0 @@ -If using EnKF rerun, select here which time step to start from after each update. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/result_path.html b/ThirdParty/Ert/share/gui/help/config/keywords/result_path.html deleted file mode 100644 index 5ca7fa5241..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/result_path.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/rft_config.html b/ThirdParty/Ert/share/gui/help/config/keywords/rft_config.html deleted file mode 100644 index fa68edbb47..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/rft_config.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/rftpath.html b/ThirdParty/Ert/share/gui/help/config/keywords/rftpath.html deleted file mode 100644 index ca1df0aa92..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/rftpath.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/rsh_command.html b/ThirdParty/Ert/share/gui/help/config/keywords/rsh_command.html deleted file mode 100644 index e0e268f88c..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/rsh_command.html +++ /dev/null @@ -1 +0,0 @@ -The name of the executable used to invoke remote shell operations. Will typically be either rsh or ssh. The command given to RSH Command must either be in PATH or an absolute path. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/rsh_host.html b/ThirdParty/Ert/share/gui/help/config/keywords/rsh_host.html deleted file mode 100644 index c8413d6180..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/rsh_host.html +++ /dev/null @@ -1,6 +0,0 @@ -To use the RSH queue system you must first set a list of computers which ERT can use for running jobs. The first column takes the computer names, the second takes the number of jobs for each computer.
- -When using the RSH option, note the following:
    -
  1. You must have passwordless login to the computers listed in the Host List.
  2. -
  3. ERT will not consider the total load on the various computers; if having said a computer can take two jobs, it will get two jobs, irrespective of the existing load.
  4. -
diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/run_smoother.html b/ThirdParty/Ert/share/gui/help/config/keywords/run_smoother.html deleted file mode 100644 index 5d61059e82..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/run_smoother.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/run_smoother_with_iter.html b/ThirdParty/Ert/share/gui/help/config/keywords/run_smoother_with_iter.html deleted file mode 100644 index f71187c49e..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/run_smoother_with_iter.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/run_template.html b/ThirdParty/Ert/share/gui/help/config/keywords/run_template.html deleted file mode 100644 index 113f283454..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/run_template.html +++ /dev/null @@ -1 +0,0 @@ -You may use this option to install arbitrary files in the runpath directory. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/runpath.html b/ThirdParty/Ert/share/gui/help/config/keywords/runpath.html deleted file mode 100644 index 7f30da7d36..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/runpath.html +++ /dev/null @@ -1,12 +0,0 @@ -The Runpath should give the name of the folders where the -ECLIPSE simulations are to be executed. It should contain at least one -%d-specifier, which will be replaced by the realization number when -ERT creates the folders.

- -Optionally, the Runpath can contain two more %d specifers, which will -be replaced by the first and last report step of the simulation. By -default, Runpath is set to "simulations/realization%d".

- -When running with LSF it is essential that the Runpath points -to a network disk which is accessible with the same path from all the -nodes in the cluster. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/runpath_file.html b/ThirdParty/Ert/share/gui/help/config/keywords/runpath_file.html deleted file mode 100644 index e5839c9695..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/runpath_file.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/schedule_file.html b/ThirdParty/Ert/share/gui/help/config/keywords/schedule_file.html deleted file mode 100644 index 2ea01382cd..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/schedule_file.html +++ /dev/null @@ -1 +0,0 @@ -A text file containing the SCHEDULE section of the ECLIPSE data file. The Schedule file is used to control the ECLIPSE simulations. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/schedule_prediction_file.html b/ThirdParty/Ert/share/gui/help/config/keywords/schedule_prediction_file.html deleted file mode 100644 index 9d9ee7bb4b..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/schedule_prediction_file.html +++ /dev/null @@ -1 +0,0 @@ -This is the name of a schedule prediction file. It may contain a %d-specifier to get different files for different members. Observe that the ECLIPSE datafile should include only one schedule file, even if you are doing predictions. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/select_case.html b/ThirdParty/Ert/share/gui/help/config/keywords/select_case.html deleted file mode 100644 index 68f628f3c3..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/select_case.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/setenv.html b/ThirdParty/Ert/share/gui/help/config/keywords/setenv.html deleted file mode 100644 index b22ce6a2d0..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/setenv.html +++ /dev/null @@ -1,4 +0,0 @@ -You can use setenv to alter the unix environment ERT is running -in. This is probably most relevant for setting up the environment for -the external jobs invoked by ERT. It is possible to use $VAR to refer -to an existing environment variable. diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/stop_long_running.html b/ThirdParty/Ert/share/gui/help/config/keywords/stop_long_running.html deleted file mode 100644 index 0abd696273..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/stop_long_running.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/summary.html b/ThirdParty/Ert/share/gui/help/config/keywords/summary.html deleted file mode 100644 index 8083f8729b..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/summary.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/surface.html b/ThirdParty/Ert/share/gui/help/config/keywords/surface.html deleted file mode 100644 index c26f69080a..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/surface.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/update_log_path.html b/ThirdParty/Ert/share/gui/help/config/keywords/update_log_path.html deleted file mode 100644 index c321b261c8..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/update_log_path.html +++ /dev/null @@ -1 +0,0 @@ -Click here to view help on the wiki page. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/keywords/update_path.html b/ThirdParty/Ert/share/gui/help/config/keywords/update_path.html deleted file mode 100644 index 99db43fb90..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/keywords/update_path.html +++ /dev/null @@ -1 +0,0 @@ -The Update path option will prepend a new element to an existing PATH variable. diff --git a/ThirdParty/Ert/share/gui/help/config/run/runpath.html b/ThirdParty/Ert/share/gui/help/config/run/runpath.html deleted file mode 100644 index 36685bc466..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/run/runpath.html +++ /dev/null @@ -1,3 +0,0 @@ -basic runpath info - -Click here diff --git a/ThirdParty/Ert/share/gui/help/config/simulation/active_realizations.html b/ThirdParty/Ert/share/gui/help/config/simulation/active_realizations.html deleted file mode 100644 index adff4f4ce7..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/simulation/active_realizations.html +++ /dev/null @@ -1 +0,0 @@ -These are the realizations that will be used to perform simulations. For example, if "Number of realizations:50 and Active realizations is 0-9", then only realizations 0,1,2,3,...,9 will be used to perform simulations while realizations 10,11, 12,...,49 will be excluded. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/simulation/analysis_module.html b/ThirdParty/Ert/share/gui/help/config/simulation/analysis_module.html deleted file mode 100644 index a0597c4844..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/simulation/analysis_module.html +++ /dev/null @@ -1 +0,0 @@ -For running sensitivies you can give the cases descriptive names. diff --git a/ThirdParty/Ert/share/gui/help/config/simulation/iterated_target_case_format.html b/ThirdParty/Ert/share/gui/help/config/simulation/iterated_target_case_format.html deleted file mode 100644 index de622b8418..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/simulation/iterated_target_case_format.html +++ /dev/null @@ -1 +0,0 @@ -The "Iterated Ensemble Smoother" creates multiple cases for the different iterations. The case names will follow the specified format. For example, "Target case format: iter_%d" will generate cases with the names iter_0, iter_1, iter_2, iter_3, .... \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/simulation/iteration_weights.html b/ThirdParty/Ert/share/gui/help/config/simulation/iteration_weights.html deleted file mode 100644 index 7e6a9edf4f..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/simulation/iteration_weights.html +++ /dev/null @@ -1,7 +0,0 @@ -

- The normalized weights are the actual α values used in the scaling of the standard deviation. -

-

- Example Custom Relative Weights: '8,4,2,1'. This means Multiple Data Assimilation Ensemble Smoother will half the - weight applied to the Observation Errors from one iteration to the next across 4 iterations. -

diff --git a/ThirdParty/Ert/share/gui/help/config/simulation/number_of_iterations.html b/ThirdParty/Ert/share/gui/help/config/simulation/number_of_iterations.html deleted file mode 100644 index 5d649052ff..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/simulation/number_of_iterations.html +++ /dev/null @@ -1 +0,0 @@ -Specify the number of times to perform updates/iterations. In general, the more updates the better, however, this could be time consuming. The default value is 4. \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_parameter_constant_value.html b/ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_parameter_constant_value.html deleted file mode 100644 index 792bce12bb..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_parameter_constant_value.html +++ /dev/null @@ -1 +0,0 @@ -Constant value used when the parameter is kept constant in the sensitivity study. diff --git a/ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_parameter_is_included.html b/ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_parameter_is_included.html deleted file mode 100644 index 549294c6e8..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_parameter_is_included.html +++ /dev/null @@ -1 +0,0 @@ -Check this box if you want the parameter to be included in the sensitivity study. diff --git a/ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_target_case_format.html b/ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_target_case_format.html deleted file mode 100644 index b602cba8dd..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/simulation/sensitivity_target_case_format.html +++ /dev/null @@ -1 +0,0 @@ -The "Sensitivity Study" creates a case for each parameter that is tested. The case names will follow the specified format. For example, "Target case format: iter_%s" and parameter name trans_mult will generate cases with the names iter_trans_mult. diff --git a/ThirdParty/Ert/share/gui/help/config/simulation/target_case.html b/ThirdParty/Ert/share/gui/help/config/simulation/target_case.html deleted file mode 100644 index b3f6cb2063..0000000000 --- a/ThirdParty/Ert/share/gui/help/config/simulation/target_case.html +++ /dev/null @@ -1 +0,0 @@ -This is the name of the case where the results for the updated parameters will be stored \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/init/case_list.html b/ThirdParty/Ert/share/gui/help/init/case_list.html deleted file mode 100644 index 21d1bbc77b..0000000000 --- a/ThirdParty/Ert/share/gui/help/init/case_list.html +++ /dev/null @@ -1 +0,0 @@ -List of available cases. diff --git a/ThirdParty/Ert/share/gui/help/init/current_case_selection.html b/ThirdParty/Ert/share/gui/help/init/current_case_selection.html deleted file mode 100644 index fbcc72af96..0000000000 --- a/ThirdParty/Ert/share/gui/help/init/current_case_selection.html +++ /dev/null @@ -1 +0,0 @@ -The case to initialize and use for simulation. diff --git a/ThirdParty/Ert/share/gui/help/init/initialize_from_existing.html b/ThirdParty/Ert/share/gui/help/init/initialize_from_existing.html deleted file mode 100644 index c05dccad1b..0000000000 --- a/ThirdParty/Ert/share/gui/help/init/initialize_from_existing.html +++ /dev/null @@ -1 +0,0 @@ -Click on this button to perform the initialization process \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/init/initialize_from_scratch.html b/ThirdParty/Ert/share/gui/help/init/initialize_from_scratch.html deleted file mode 100644 index c05dccad1b..0000000000 --- a/ThirdParty/Ert/share/gui/help/init/initialize_from_scratch.html +++ /dev/null @@ -1 +0,0 @@ -Click on this button to perform the initialization process \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/init/select_case_for_info.html b/ThirdParty/Ert/share/gui/help/init/select_case_for_info.html deleted file mode 100644 index f27d05c573..0000000000 --- a/ThirdParty/Ert/share/gui/help/init/select_case_for_info.html +++ /dev/null @@ -1 +0,0 @@ -The case you want to view information on \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/init/select_members.html b/ThirdParty/Ert/share/gui/help/init/select_members.html deleted file mode 100644 index 616ac700be..0000000000 --- a/ThirdParty/Ert/share/gui/help/init/select_members.html +++ /dev/null @@ -1 +0,0 @@ -Select which members of realizations to initialize \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/init/select_parameters.html b/ThirdParty/Ert/share/gui/help/init/select_parameters.html deleted file mode 100644 index ddb2f22741..0000000000 --- a/ThirdParty/Ert/share/gui/help/init/select_parameters.html +++ /dev/null @@ -1 +0,0 @@ -Select which parameters you want to initialize \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/init/selected_case_info.html b/ThirdParty/Ert/share/gui/help/init/selected_case_info.html deleted file mode 100644 index ba7763102b..0000000000 --- a/ThirdParty/Ert/share/gui/help/init/selected_case_info.html +++ /dev/null @@ -1 +0,0 @@ -Information for the selected case \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/init/source_case.html b/ThirdParty/Ert/share/gui/help/init/source_case.html deleted file mode 100644 index 5eec505e79..0000000000 --- a/ThirdParty/Ert/share/gui/help/init/source_case.html +++ /dev/null @@ -1 +0,0 @@ -The case from which the initial values are copied \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/run/simulation_mode.html b/ThirdParty/Ert/share/gui/help/run/simulation_mode.html deleted file mode 100644 index 3be738a9b6..0000000000 --- a/ThirdParty/Ert/share/gui/help/run/simulation_mode.html +++ /dev/null @@ -1,4 +0,0 @@ -Here you can select which type of simulation to run.
-1. Ensemble Experiment: this will run simulations without performing any updates on the parameters.
-2. Ensemble Smoother: this will run simulations while performing one update on the parameters by using the ensemble smoother algorithm.
-3. Iterated Ensemble Smoother: this will run simulations while performing multiple updates on the parameters by using the iterated ensemble smoother algorithm. diff --git a/ThirdParty/Ert/share/gui/help/run/start_simulation.html b/ThirdParty/Ert/share/gui/help/run/start_simulation.html deleted file mode 100644 index cd0892535e..0000000000 --- a/ThirdParty/Ert/share/gui/help/run/start_simulation.html +++ /dev/null @@ -1 +0,0 @@ -Click on this button to start running simulations diff --git a/ThirdParty/Ert/share/gui/help/run/workflow.html b/ThirdParty/Ert/share/gui/help/run/workflow.html deleted file mode 100644 index 986b0130b1..0000000000 --- a/ThirdParty/Ert/share/gui/help/run/workflow.html +++ /dev/null @@ -1 +0,0 @@ -Select the workflow to run diff --git a/ThirdParty/Ert/share/gui/help/template.html b/ThirdParty/Ert/share/gui/help/template.html deleted file mode 100644 index d11776e51a..0000000000 --- a/ThirdParty/Ert/share/gui/help/template.html +++ /dev/null @@ -1 +0,0 @@ -%s \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/help/tools/export.html b/ThirdParty/Ert/share/gui/help/tools/export.html deleted file mode 100644 index 5a3f2061d7..0000000000 --- a/ThirdParty/Ert/share/gui/help/tools/export.html +++ /dev/null @@ -1 +0,0 @@ -This will open the "Export Data to Other Formats" dialog window where you can export data stored in ERT to formats usable by other applications diff --git a/ThirdParty/Ert/share/gui/help/tools/help.html b/ThirdParty/Ert/share/gui/help/tools/help.html deleted file mode 100644 index ecbb174173..0000000000 --- a/ThirdParty/Ert/share/gui/help/tools/help.html +++ /dev/null @@ -1 +0,0 @@ -This will open the "Help" window where help information are displayed for various functionality diff --git a/ThirdParty/Ert/share/gui/help/tools/ide.html b/ThirdParty/Ert/share/gui/help/tools/ide.html deleted file mode 100644 index c04f7eca8b..0000000000 --- a/ThirdParty/Ert/share/gui/help/tools/ide.html +++ /dev/null @@ -1 +0,0 @@ -This will open the "Configuration" dialog window where you can set the values for various keywords and parameters in ERT diff --git a/ThirdParty/Ert/share/gui/help/tools/manage_cases.html b/ThirdParty/Ert/share/gui/help/tools/manage_cases.html deleted file mode 100644 index 6420f762a1..0000000000 --- a/ThirdParty/Ert/share/gui/help/tools/manage_cases.html +++ /dev/null @@ -1 +0,0 @@ -This will open the "Manage Cases" dialog window where you can create, delete, and initialize cases diff --git a/ThirdParty/Ert/share/gui/help/tools/plot.html b/ThirdParty/Ert/share/gui/help/tools/plot.html deleted file mode 100644 index 5110a84c4d..0000000000 --- a/ThirdParty/Ert/share/gui/help/tools/plot.html +++ /dev/null @@ -1 +0,0 @@ -This will open the "Plotting" page where you can view the plot profiles for various data types diff --git a/ThirdParty/Ert/share/gui/help/tools/workflows.html b/ThirdParty/Ert/share/gui/help/tools/workflows.html deleted file mode 100644 index dcf597397b..0000000000 --- a/ThirdParty/Ert/share/gui/help/tools/workflows.html +++ /dev/null @@ -1 +0,0 @@ -This will open the "Workflow" dialog window where you can select and run workflows which you have configured in ERT diff --git a/ThirdParty/Ert/share/gui/help/welcome_to_ert.html b/ThirdParty/Ert/share/gui/help/welcome_to_ert.html deleted file mode 100644 index 8d6993316d..0000000000 --- a/ThirdParty/Ert/share/gui/help/welcome_to_ert.html +++ /dev/null @@ -1,17 +0,0 @@ -
- _________________________________
-/                                 \
-|    ______   ______   _______    |
-|   |  ____| |  __  \ |__   __|   |
-|   | |__    | |__) |    | |      |
-|   |  __|   |  _  /     | |      |
-|   | |____  | | \ \     | |      |
-|   |______| |_|  \_\    |_|      |
-|                                 |
-|  Ensemble based Reservoir Tool  |
-\_________________________________/
-
-
-

-Welcome to ERT -

diff --git a/ThirdParty/Ert/share/gui/img/add.png b/ThirdParty/Ert/share/gui/img/add.png deleted file mode 100644 index 4aadc248dbc5c5b7c33b5e19d210bf88db66f0d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPi3on;~o=u#)KLZ1!xTlL_h{fsTKmY&RGh1au${uat zz0#t0SRgs+0N*l01A{;Ahc9o?OgX6bF4KPeqe7IIa>fD`M4TsDFxg8$*$3&hz00bvK{l2abRKV7DIDDGn1LhZ>3~F`u*Evbt zudhp2U_J0fQSw8t4f6uOnRTz8uugHfVjALnvEb()-4f$v#s)x;A6951J diff --git a/ThirdParty/Ert/share/gui/img/application/window_icon.png b/ThirdParty/Ert/share/gui/img/application/window_icon.png deleted file mode 100644 index 94e19b30d5612c08ac12bec8ad6433f60020e7ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11344 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 diff --git a/ThirdParty/Ert/share/gui/img/checked.png b/ThirdParty/Ert/share/gui/img/checked.png deleted file mode 100644 index 8ca5395d729e99774a5765f2151859f38ffaef10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 243 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 A%K!iX diff --git a/ThirdParty/Ert/share/gui/img/copy_to.png b/ThirdParty/Ert/share/gui/img/copy_to.png deleted file mode 100644 index 4af7902c39c33793ca3cfbf56019406b276238d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3795 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 diff --git a/ThirdParty/Ert/share/gui/img/ide/chart_curve_add.png b/ThirdParty/Ert/share/gui/img/ide/chart_curve_add.png deleted file mode 100644 index 45b61c5656afed6ee19ca12987f582efb25f1c29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2257 zcmV;?2rl=DP)qe-xBVuFSi;wT9^jXIs!j*g_`bTlQ^{8M7Y_ZW><8z%v&wnSpYSMY&m zVhlrSB#8>;wJ&y8Lx0&>EiNuDpjUrbFOozs;{}C<2m}H@7yv;KP;>b3TxO4?e>eag+j$@$!)&&w zNZAu+BmDmV=-9i#UPNHifG8w-m-(q->b|9_iKl(h6) z2PFE>4VmGFGb7$XLTGPv*`Oz*{Wt8PSqfzO7DYNX=9d*Hp`D3>2)oTTVz*%(o5XV> zBtZ+kHV!u(eMn19yW93i03vabG|qsP$6IjL?uW}GGwv`cF%tP{99GQ8f|lpt4G;)g zhaFd1TG|Kz7K=rtnx|#8q8@*{v>5MQsfNb~Tz*s;#e4_=r!oK(9BzeyPUuw81mwi) zRN9WV_M!Zu8SlPx9eeYPn4S^^uM#@nVdsv}JI{;I2vOK_HXm(04cPePX*`rQjo9-e z$loXcnA%SpKJ!90EVQ%KSRDp@iaPRCW;CYgVsP|^4)bc-Q8G0ir8CBn5gr1emgS)^ z6F8pqIy9L7g^$|L;oxE?Y*st5b{hd%QW+in2xx$gmx7ark0ihew4$O?G#dEs_yrG1qeFyt40fJhijrAdXgrF1$On#R^pBon#4vqq z2WGRCC=_6|SP7G?QpQN;Xs68`orokqsrY3yit2i?+NVMJ3@2O=RNxGNMjwMi4X;Bc z{68N19NI0d^jq>5iy5)8F{45dhZ2Q^><1^qYPP|UZiL_Oq1}1ZIOy!`gfSyMXhf$$ zeUt@Hywil$E!VL2;7WKDfo2Ja&?n)<3(a_5TY$tUqC9yL+W*sn%+wSD!jH-T9}Z1+ zezSMzP+Xmbyf;PEG?gJzqgO+Vr}O3{5nN;h?3I6qdEP8k4xB)<@eyp?)QF$AeT|>B z^}<@V9PT&~Gi~E>HGdjf3UcAAt%mINk|klJ)86X?3Qm{!h<-Z)5e~do`#4&hpWxLw zb&#}?;3!jCOH1JT>T_iN<0Nj8?#P%p%&qzY`TJe?=lrQSb8{~Wvsb{lbR!bqC`ZqG z73iut1oN^w#JyiXY8djtC}02r@F|1v1p1MlFa^68IdP%&H0qjnBVtTEOv`_Z!E0Y& z;=xnUWo5(f@gjw2{`kcycz}*2b8`(ow>H5it-!}^4nzms$awB~q?T>RPpWAX%C|Y8 z>S%z;)S)_KTSqfxF&$RtR^p8_3-LK)-D-Y<4?^hELs1D>_nsC1JJhtUGAZOB}q0AOsx7XZ_n6!BHyM~YY zhD1aQ@(cnul+?(v;c>e$dqX=uT_R!Yg+*95_XD^ozsrhW&3IZd0$#rxr8SRX(ezbF zh?`@bA&(U_T3GjOhcNj^SU%5AuAQilLQZla))el<&SPtrKK<8j ze;x#Wlw{Y^X29pXaZ~C*~bw*a8nVUE7}xdj86z932-`+c5^rG`@^&N7ljKK9F0# z2^U7Br}0@?D*X={4e*`%0GTUSBQq(HaQewH$6;Jr5|UG6k(3fc3?w3XTr5(IF*wn> z83ogeaK*l#BEX`S_PYxu)7^BL@o(Ecd3+`94^`mZ!1KJPbR z#ZF-jB?+qz0s0KEKXODll-*B%c>#vxSXlb6!A~mIN_gd=W!ZP8V`Jw2uaJ@u1q!m6 ztUnY-*e6F2LR<}Lt?E(N}BC(@VwF&H8oGe7{CgN7@I8Y!IWxZzM5@S0Sb|7Um12j_+(egpuM z*-VijAZb?>Y)&T>)}|8$tfe-YOe5Marn6A_)@vV7TeM!cgX%x&eC@^`)Os5K+Omy1gTz?ect$dI3i(+-=ZB^_0B)i`Uk zTH66@BepXCWJHW5$t)@=dcx!J$lv+O1zz!cA>YnKn!%?$hi$DA&rdzAbik=gul<57h5Ct@l{xxV8pZ8l%FW`LJWDBpTN-l1lLxfJtVh7I((l1!s|()8?a{B`iu)|3^7RJ f3%#q)e+3u-w{P) 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 Ef@!BliU0rr diff --git a/ThirdParty/Ert/share/gui/img/ide/control_play_blue.png b/ThirdParty/Ert/share/gui/img/ide/control_play_blue.png deleted file mode 100644 index a1f7345f3713a730b613faf82026caaa0adb375c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1971 zcmV;k2Tb^hP)FuzPnw&Ga@2NOxDg`J$q# zyMDH*0$W!WL8Ha4>l%7TG>k;`q?i4whyuTa`Ew*l^#AdeAZp(J6tQUZrBl^gpQ0u0 zb_ghy`O6CHT< zz4qRZsyEM{OhTS&d1Lpkdza)rM9Q0cqUauqfy1pxw@w(xB!@^#Zy5cf3U=PJki20O zh(crc>HVAUNF*U8#=LTG-J!b{6>iwGr2^-IQCt~`LniGKnJx;P=@vv$Bv_d*B&<*D zo9|c{j_9}%HL!6-E-qgF%BNOrEa*A;_a-MX9Rk9Noz;sn3QGQ1^VoVyGM(ZbgG_Fe z9Jkw$XhEe7nS5-8!?1EfmFwbhEGZlLO(QlW*SG=N* zbxsf{TDvvd<8ha7q&olNdd#$lW6p_`2-0m@-_jPufydY3=PxwC>yl_qF!v_E@4(5Q z0C{!u>iJLC+=i@{uPDhjlSO1JZUKt`bw7`an)kb~_o21;>GN;G z*fNhxF{D`W&?PVA$+$aS8o<8fn=%_(S@mbetvJeZA9DAnVJCFzu&ZcJ^} zk|89`Mmcd)CKqUek(xk)2cm`u7r9%oW!IKu;<-0I#9#JqqY8q?5WZ>15q} zTs$1=ZaCZ43!fs)q6#bmnkZvlrWbYfC-B#O+vx^mK-aD7SxQ-Akwy*pTzenJLzf#^ zHxmd4{_*nR=C-TkQczc$*$eD5jeHyvDf5s06G!%w^0+>uh0XkB)e{tz}Z1oZdi5)jvZ;j(Q3Aw{K%IT2-C~hkm<|} zYCA_xc0iAgbqh%o2)oGEN$=&a-Ao0XD5$NRm`Fx^*|4 zZX74VM}|cxK@S`~kIuIaK60Zk5FoK}=RTm*!kE9TvgE6ny7-=D^URvojp<47I^PE- zuH`c+Hxp09oHPN?{<#^~dIHDWj{oj861&c+G(mv>={?(cA-?dw2lMA8e zsVTP}yHKs~ff+!abkm&9@Ctab@e*1-4-R~M;Nc&UXdlOa@|BFQ&3f=;?b|(B>+dhj z$@DHR@|$YRHa!bBC*7P#xrb(5x)(Uu(294@c7&RLy=@B}(?b}xjZPxK{*3aRxpJ!Z zonY4bZT-V>&o>v%BP$Z`gSdI`n{MP%Xk65;)2N!p!Ww>g_#Do(b`O&Bt^8R*807Ms z?o#T6BEm$1r)rzVvX|$d>KG}@O!uJTYd&ktCe^hC$(|8R)Z;Se4URQ;;$mZyjnF8@R%C-cR7$@7V2rnkDWlHjy+!Iw6DLNw`rbhHsoO zWGC6EtvL4oewPcJdE4r6-{OF diff --git a/ThirdParty/Ert/share/gui/img/ide/database_gear.png b/ThirdParty/Ert/share/gui/img/ide/database_gear.png deleted file mode 100644 index 373a0adb0c360abeb8e224e87062a640f26d5fe0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1923 zcmV-}2YmR6P)i~N^**d`(rPsH9^t>obPq^}3C@d^QQBfge zS%$Z`m~EbW6G4D~Xb7oP3d6%e1cO0Dq7i7S`r<=tZhM+uQF9p}zqaMW?QV}}Rb5Rj zoX&h`n#Pryil<_LIWiGN5s5?shmIUUcx2@Bhwr}qR+>(oZ>>y{C&|*P`dS~4S2P-% zRNS_GUVA86dEg zWu?=2=zGr$ATc%uK{O1Qf*~2jY|wPrtX7oIDCK)vEtYJoo!0<9eW2qP%&)J-^inUB zcml!D2omuzL}F0_mzvW6S(f0+cfw}3qOib&Ji86i(HP%zESb!`)`&Tj(KyAs*-t+Q!2*mQqOnmVi3RG z5)LCUau+l= zE?ta0Kepn;?DUQ!BFided2 zYkWS>VdKoHxM(K4-eTBob{r>X;)(b;+a@qTOw%Zaj-L;~?Q)@ry!ZLaU?Jq^=jXx1 zk#6#FoP_B@MSo&Zh0`!ZdGG1%LpU7C0Mp*Bw4a(C>S(k z^h@$Wm8PM_X~-hOXqzsw;-oAfu3|z!jZ2!M23s@t<~-xQY>~Nv63O2uPvBtd_t3%t ztbbv{+w92CK|_C##Vy5!(<&o`gFL$(R$_rDO57_ZX)h%XLN=yZpk;~-#Q}#pTHz+V zl$X!Ik1gM#V$K}o6LUrg3!`+zU$$`JlZzHz;qZ7|RrT{PS@hkv-+auR=a#tL?&gLD zqT$|&X~^!!c|J}<)&<2B1^$74l=x~f-{*s`u9mOu={9sJUk)E(>#sI@ z1cQb;(eQ7g;gShy_!ljfvuUWNDX3Grtd#S4bqmn8e-CXgp`^r%t`lA8p)@e?4hM!& zSyhR_K|k8t+wt7GXP23I^Dd?)qzu3Qb{t(@UGQCg zB~JbM2Yx+vOd*`))z(zwqS>?Y%(Lq{Y3&ze$j$P(EVvLFQvK#(ZEM?yr=EC{cRyVx zPvZ3H9{3h6g14j$J!j5f=k{%nIi1eU<>k}S+}s2URn%8EZCc6FaL#Fn3!C#pHBhQg()iNECM&3vq;Zx}Zg{5j8HAnpC`oBi{uYKle`r9LnmK%8jBDn09X+%6C0 zOeV4N29u4f%(4_v1v1hi;j3LcuwcO@m^*hKoe4>lcuP@TRgL=kdQ2;t#>=+L>866k z9lNS+f9raNeHHz||X&4wG6Us~g)qWXE%e_(Vl%3xIEBt!x^vAv>l_Y8-R8I6xZ}PD9{geYObDW_*QlII@~P>*eS z=j}($E=f4wry48IhD=4dc`;*)j5X?=YwmvCZqK`pO~m8MzW29odC-_+4)>7+*?$55 z-z6L6)pTMyNwG0EWGGD;(NfGd?f*33e8$*~`*^m}?CT!^1^_AuH~7P83Vr|p002ov JPDHLkV1kVyozDOO diff --git a/ThirdParty/Ert/share/gui/img/ide/disk.png b/ThirdParty/Ert/share/gui/img/ide/disk.png deleted file mode 100644 index 3a9dcf37ec21415647543eab105dcdc124734cb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1555 zcmV+u2JHEXP)?^ z2%;b=w1PtMK_Qq6`eacwRwJ4Q8^y-Is!u)$27D2rLL>CSB6%sb6-%oiXr7c36;X@$ z6a=Lp+WfU?kTm!1%y_;tvp4sKySF42x?%2ac6Yw>oo~)Lb5?op>3SXsew0!;r8ka$ z`B&zt52PIP;%hl?mLgC!|0F7$VaIrTW_EnfAV13FrKkXm&%HCfJ|rDAFRg+97maiYRz4tU*D(sbX) zbJSikRJD$Nd;T_>_`38kKW^u-tmC^SD6z_xy4q6mXD6wBONkQJPBR%9iK$&H8FkN^ z+*5K^f&naG0vk4>>Raj+kQJ+1Pi=`N$Ho9)v?0Fa>y#9`<9MR40eI3{%RKzwc#mVp zIa1ED3W`dM$7*8EH@1!c92|>dX4~{;|-Wcld?-yXlz=I

0ykMq`Y4{8q!E{{~|sxdD4#g0bNzcnK0& z0;sSC!Je{LPrrDO#-16hTPDlSTN)aDi52jIB@VHb)m92v@1kLnLE;h7kz=QD$;R`# zp=tyWl#u(#vCkUb$(KNiPjn`?K}7^AhyfESSE@rqV+~_qQ!ve7M!2yNCCdVXcn2mt zNI+{cF)IRAs+BAYY&0i;^|5$SOSC330mcmN-}?v+l*=OP$jfig=#!60u0!rD%V;0p z+rRfwDkCE(q@?967#@2)WPvOJibO1q$08VP77kol{{00*JLBv#Pin!#;cHWfD}S0|&&Bhoc)TDTvAn548r zS$nk@$dCn0kL^+i6PWsAg&w@M{hIayU;r!SSkOM$C?tSqk_9}mlV`m5{XD%p?XQUd z=|K%btEMJ*i6pSklzAZH=zxRWJ`k-->{9nqNlj`ZWTGVw7ie zu4&3kz%3gJR+0*6=zt0cD7B7&5*x(?_zxQg)fAxE6(yny&IaujgJ6$$y_MD|n8 zSB?i4n$9$I6Vh-C@M>9;JXIt;sm6eOiW>s43yKC1E=VlIMwt1ljfeZXmGV#?6b(eHd z09Kb~r{@lhyuz1P!mcSftWv)2<8c#@ZfY!6`LV)dA)b*GT|7XxZ37h=--8!<{2k9( zPC&j7p%_#xm|Ts9sv%KDGf>vsGnzyR|_*l9HsN^<}J002ovPDHLk FV1gfG(G36q diff --git a/ThirdParty/Ert/share/gui/img/ide/gear_in_play.png b/ThirdParty/Ert/share/gui/img/ide/gear_in_play.png deleted file mode 100644 index 6f73cbb4d94c34c3b2ca641dc716ee2dd027b6c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2019 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 D^>?LD diff --git a/ThirdParty/Ert/share/gui/img/ide/plugin.png b/ThirdParty/Ert/share/gui/img/ide/plugin.png deleted file mode 100644 index c1ee68def07b0233c90b5c5559b77fe886ef6780..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1743 zcmV;=1~B=FP)6oCaYew9;}o6M(2iI53E2lJsbEC_gNJXzL18)psGUBg!gKW~Kw2>X zQFNKP4m|Z0(9uiJWqL^%6&)$&)qb*+5ML`HiB399J9tIfe?X9haMti zGs0?vC|3s5Z0A}z-sl6-nH%GP+MO>!Zb_wNMEfKFk<@tZ2j2lGgaw6rTqnWrJ6|B> ztoq!YT`=d(-S|qzQ~^Q}Yg!wA+y=$V(_DK`-@hLYfLZfgkui2FQ6YNB4SU6no)m{m zO%{D@;2yx`qVfEr#tEKCemVHNI{}Rcm=ZD>0Ja$cm@r}-6%*TMVqjSMjR3;zBom~+ z2EdOJ8eU5#Gj0Gt4d79wt-}MEjnTlo@4p4mU4>4{y7yD6xClVSGzG;7AS?-iH=&my zKX{r5^tJp2yd?r+XU~P`>}3FVe?Xph8KM#ffL56mc$zFg-2&Vw+XMCYx{e;X)_FWD z$(B->RlhOi`8;Q8;oAVWze3%rfg4YHIHpp5DgerntDfRR)$MKdt$l9%_E9%V0gj#C zqVBUNC#Ofpynx5?_b4AG1z^&uB~eGBZ@OHXzeC{REe?n)M7RqcpZw0M&#D_)ere6b z&UO#7!a^;@loX|}*{~}2oAi|h0L{PQ3NZ`-G^!$(GB?Am-+zYwcDJ^E#=IPG zuCoH9jA9^!P-WK1S}DJHwxc*|rVBZR3VDG=0LB!l38FyfG~>jumLGjp2S?hyRtf7q zT^bC9NN2BK-cY#X(#fya=UARgiY##^#;s1sorec>nnhqD((&U{QNYkU=A(a3{KOL; z#75TJfH6hGNa$dD2i7%S8R-Rhvw@5i`SI?m>&I%gF9yLPf#cbkkXo<^H`k#fSW(T` z2doMB8>btVu@MfoqSD~_{xM@AxGS$i$F;*CSS3izn+wjoLZrJH1{#~8@#HBucKzXI znt@t3BnZHkkqntBcI~#KRkNXPOvo!}s0XQ%f}7K!tKl9DblnCeFa-AG1c=K*fXV}` znvI4?VAusSbksJ$f{&|KSVW%tW79xMQuROibap62x__#4e^ge{e2UUj;{efUi0RXP zg?VDA`<4V4lAUn#z@O0M@twQT=BuVNIZ3t`XC>4XWWTW-?}ur6n1_#qlYzDArhu&a zU;Vu1J(lW}L<5wHOo9dyhV&FN8mHdaT+n>@3RM2<{r3G|>i6SdKbt)C`a;+IZIW1) zv+)&F)xpXNr#tGy4kP9!X&eLL+=U1006&Dw96St#UY_YGxWK;0F9U7NE_Qs zAL(FqyKmF-)CWOtPog9t@f5#)M|k`WqA<|?VcM}myOO~RqP6Fs$4g^F%d?kxGF+@^ zuNOlEdelH5QM(zcCLI8I%4VduV@31!u?C96lG6&3RkX3tsbdmewMjy@6m8bqxyVwL zzEANFlNN8D$Hiv!Gtx0$gb>7KI^q1bC0{ZUjWn4vTbGo^WyS*^ivS|+qkGIm*E!V) zs66MZ-E-cis^jku9FmF0Ru*9umeSJ6x}}yM_6Tup&s{Hg_nfDtb<`^~jyn4j9TwAr zo3}nKB0m-!NOz`iBFupXQJPHRu)NaNYxG>QQvJ8+%FNPZR lq$jK&VmUwQ?c_fJ1^{wJV6Voy&Yl1O002ovPDHLkV1lTdJ$wKF diff --git a/ThirdParty/Ert/share/gui/img/ide/readme-fatcow.txt b/ThirdParty/Ert/share/gui/img/ide/readme-fatcow.txt deleted file mode 100644 index 1f3e716286..0000000000 --- a/ThirdParty/Ert/share/gui/img/ide/readme-fatcow.txt +++ /dev/null @@ -1,21 +0,0 @@ -FatCow Farm Fresh Icons - -03/29/2013, v3.5.0, 9.12 Mb - -© Copyright 2013 FatCow Web Hosting. All rights reserved. - -These icons are licensed under a Creative Commons -Attribution 3.0 License. -http://creativecommons.org/licenses/by/3.0/us/ - -We are unavailable for custom icon design work. But we -plan to draw 500 more metaphors and suggestions are welcome. -https://twitter.com/FatCow http://www.facebook.com/FatCow -or Google+ https://plus.google.com/101826539018374982925 - ------------------------------------------------------------- - -All other trademarks and copyrights -are property of their respective owners. - ------------------------------------------------------------- \ No newline at end of file diff --git a/ThirdParty/Ert/share/gui/img/ide/save_as.png b/ThirdParty/Ert/share/gui/img/ide/save_as.png deleted file mode 100644 index 915e280c54f1eb5b0131c9a34504926c7519b1e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1590 zcmV-62Fdw}P)XSZLrRQ_f8RlXIewtiR+uo1yVx5M+;1V^%$F~2f+YZ z3Tu%Xi$_2H32_)=aw>;=`w{$h>2LY)b}l~1@}+lUEy=8;5wfDd54%@^b+OJ802v4| zKV;5fQ6+)>axcep*?c`tSsS$1@<$Yve>itAk!9uS@gdQ!%7Uaz0aUYjeqNLEp)i0oWAW~NyxD(y9u zIYh>xY55vhqY5Gdu&rwo0k0Gx1TYwvdSw6~#uU=T%~qpNP7Wf?jr~`N(ND z2MY4HrNJ^HP{p7ctS#)ijklth5RleD+$no zz9B*f6mqDO$)9BQ|CFv-V2S|86fWc{8mb^7iQSvq5K=I2+rCpyHa#rZ5)M6mJJ7wQ zja)_h`gfw5RngVe>t(1+*1|d(TA(1m^5(Dvz$T~D9XsJ&Q0Qqzgjh)5m!vy7dP*#1 z3kXoh4;Eggsp&u?09D%0*GtHY9KC&g=zM;ogj?T^UC8rH*4j6&$H3rjAF58G zrMstBw6ZK70g-@pG>n3r-pNLzcSg_59zJ4) zpE%Xg7=TsZhe27p8IY6YVP}9aa{wrL#AR6J(VA5qjR81KL_TC`?yz%Zfc_`%_pY6x zR%3Ja+5e17OKz8*S&mNdb$n|iQopdS~n zUYkXI>8}835>h!<0J6ko9YG@!I>~5aK>-j*7sGX6aZ8Akhd#lBYd7OWwi+jXyn&Zr zJxn3#Y9Z=o0N{fpb#;ZW0%}Iox_q3-`eN4xtxtyj?F2RA1;gn9!`Jwo? zitGD37u+i@d-IsIX314d0auGC}86xd~Bxx zxP#@W3Co^7j1+)JURom{Vl}rkO9i|o0Im)I3*qi{Q3~I5l7i65snb~7GU<@HJ+BL7 zo-1@CjqC0Hez=#$!%N>E`?e$zXTg7}7H7LxVS@V8gxcz-)~wjT?-su{H1^lN4s7k% zLL{tUa&i*GBO|x0c**NWaCLuAD_dZK#>GqTY9RMI!{ZD`a0Q}aWIiYa<#sB~S07*qoM6N<$f{r2UDF6Tf diff --git a/ThirdParty/Ert/share/gui/img/ide/small/add.png b/ThirdParty/Ert/share/gui/img/ide/small/add.png deleted file mode 100644 index 0ea124a744763ffe056b84a56b6100c45303068a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 698 zcmV;r0!96aP)CkTpyMMUf(3l}b2gjyF`6&DIhc6Ox{+>|cFg@&|{O2tC7 zAdLz6G)>ax`#zm{`4v-e;e~nJcjwMIGjrw&!!Yna%fcTaMC0Jn42DzTT{&|D$NC3RR&&_ON0G>EAhaGrFuaO#MVp(S z!sQkK3V!D~*f;U)njb5Xw^&~Hqoi_nfR*x8ItH*)bYU^Hf$uyT+2_3l$ZQ#zw~R?awQu z3Nb1e(3@?6#zy}}TLpGy6TNQoYnWl5tlc?xq~|cg$&V&;nIcMh6M*+cDu+w5D`hwp zv%6;-DsZADZHwyc#Lba(i&WmzO{rfl3saT4`m!n`kl9H0FDvj@pFqLSh-dG8MW(4)oG4Zq#0^#T{7)3X1R;rWC+RGNHrJB`nNlX#((`&os&^9v6tF4a6zNEWb8L%K7_v#KHSMrrP2$@sK(H5->{^ gAb%707*qoM6N<$f(m;$tN;K2 diff --git a/ThirdParty/Ert/share/gui/img/ide/small/chart_curve_go.png b/ThirdParty/Ert/share/gui/img/ide/small/chart_curve_go.png deleted file mode 100644 index aa7dc60db963c3ec1abe79341f6c4a47271549cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 819 zcmV-31I+x1P)QE?@VhI5@hA>rC(RKa1^rOQGm+QC) z3L$)wp)1%Ue1UG!e$LOwxZe!);p8at~v zP@YP=PyV1l;4Zx0E9`JEL2qLGww?Tv1T4!SerznR2kUv{tt4;35mrvirRk%GiHQj) z>VGq_`)e|our`ZfY7`9>xoo{WhBjXlN0-(z-?^RaYYoh~@&mK5He8{p`XB|ezfF+5 zUy<@5&JU|<5?Pd2iD3#ByPq>TCYrfsGHFgIy1tIl>YBdp8mj19UF|N57x{w2t350> z)9K0CNdCPa;21}F)-1YvAR{f0j?POw?m85%aVR5f1tPrukm5&J8dikGi2SP$1#2d zZp#LeSawm>QPh9Cz>1{JI1G2z(+@=UPh#x?8 z5$xoiZr^R&e(qcH&wevfHn8XPc{C-wIjj(5XZAjqrdGK7kXzLSnhA}Ra6oa{~D@xZ%h32hg5wvlJ7x)Eyh zrI{wvADOz;9~l|ZufizkhZIrxVj6vDWEf;ZK~Yg+ApH?bLajEf`LSuu zoTi3iZsxx3wtIWuTUG>}%jJAN=bZOF=OxvbuYeK9aWW5uLg0BGq9{s~KnP(z!t9Gg zeZOTH#R93Zh5pZ&?DzW-2n4XNpg`tKXCRtnmhxs6^KXKdOifN9 zH#ZlNQIT*s93&<>2Ayxa;qrXv!uIji;!nNN#s}W*SOfiC{1Y>)_z^?yk4=`2hJsC@p`if@2?eP#rrAeDeSUb!h5MfIp`kD#-_**R6{P z5C5~uH*eG)GMP*ry*)iIZ`NJg(olEV@MK^GUUX0}r^VggH8@ajHrOohoTfKjuWnqw zdU)|IkdvoQ%R+TkWfFT9rR5d&NVgRMF-+oxdF)N)kzCSjC@C|VYcHK+V_KjX`|kw! jKV|+UoBtQ|Lx2GQyN8^jYI)Nr00000NkvXXu0mjfSwEYW diff --git a/ThirdParty/Ert/share/gui/img/ide/small/delete.png b/ThirdParty/Ert/share/gui/img/ide/small/delete.png deleted file mode 100644 index ace289edd9f926ac7efbb4fdec05a31bebff5c50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 695 zcmV;o0!aOdP)QxDlb83q-g)V>(Fk^6xXjEs=gr)Cm*Fo<^mL4I$34wC5BNF8n89S}#-XQ~^YvJP z0rP`oZ*;)1tns$P{b=pl2d$+AUX=r8v50)?1wKtaf~=~8v8iq7@iUs@V!3vC9|bnoZDKlrp!MjH|$pBKJ@cq?f{ zCVHcD`}cGp5YXv%Ya$H|FfqRb!>HoL)()ikK8 z3Pm`bUM%udCmi94x3Wgy;_K{9I_=cV)$Lo`5e|pMWd*@_tw+Z&FrWK^cOU1F`1W(y z$NMAr)+~I-tpmF*Y*Lkz;vzI~AHmE;%f37G?9C++ycJ$*c#U-y5x&t|@v6DP3x3=6 d&-s@C0{~E>2o(vq?o0px002ovPDHLkV1inyM1%kU diff --git a/ThirdParty/Ert/share/gui/img/ide/small/folder.png b/ThirdParty/Ert/share/gui/img/ide/small/folder.png deleted file mode 100644 index f1ed9abe0338be5a0401f4aee1b3bb168b4d815f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 632 zcmV-;0*C#HP)4gUbq(tw1lgoXx`HVs0gK|-QT;Nk*gBnKlTn_z-{ zmhYU)-7d3t&KJ-ik94}dotgJ$-pr9P27{QufTqgxGmAP3uNoaE7bGM|sxpx{$6x!S zseeO+ZJ)Bq=VzY*TTvP$C03r?ILjc0=nnu+A|W7D<`Wa0NdS!2oVvxShDKmPGuu1Z{X#D3g|-0BZ&qN9*G%zO46N zD4sVu^%@Qrc`Ds1baRPAMG7LbeA>HftOGIA&>{S+y14WB!(!4xyYUUh=}X*79hA*; zs@NUjK4So91b$-;-y6->tMfCSvO&Q{3%OG#fnJLTF^s=9aIa;Dv9bIfwI98O6QfM# z&RzC+V0j(IuuEljHs;@Ei!vnIlXu^Ym7iYmY~+PRvHvr>_inmd1OCpx1sDLU%fF)P S!b7P50000 diff --git a/ThirdParty/Ert/share/gui/img/ide/table_export.png b/ThirdParty/Ert/share/gui/img/ide/table_export.png deleted file mode 100644 index a96837ed1e4c8d95126ddd9d05cd28825f102add..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1144 zcmV-;1c&>HP)J6ufSp>Q?%~>|y?r+_)gP>A$`~~xl-od|JSO@8v8&&R*WO(MPJZ>VBb2I@nGW^{n zv<#hx6ZLzzyT(&s%r7|sur3c;2MrD*Q3C)?f7w>V0IB|G9Ku*oXn&``6s`kJFoOfsir5srmekzfGm#^w!;%0w$-r(*-O zcfW+@jmx0qrN@}i7z$+-1A-6;^#zta>U%)&gGTdIG|I~)4MyU7Q$V$J!Ik##yY{<3TQpw`&IO02!zKO7WDk7e~ z*Q@Gk*n5)C^xk&A7Y9m+{q+8mH<|+-YV6G6JX_gNdoN%PlIe;^T2Sg#;7L`Ztd8+u zIda)-3dJ1qZ5{Yz?3)BAoY)HXq0Rv#YgH$qxn!8d3b*2fGcm;#dhE?VgT1$3l)vA; zx=~H!^%!jeC!0uNXTdwQEvwRIjD(g?yC?~HeY>P3OSNs}1{1@;gJ*ZfV*KWpKTh9- zZ$w7q3&oR7$_U3ykk=o)P+3?+GNw($a!IZ|d6EQY`!`HlNxt|ua6ZzfYKkO-b z4AbY66pn?tyM@8l&DjtMhlo7ii+&x*Fv%#jo$KmR^>7Vr#6u(wV}WFngm|g2Zv=dy zKR-%n5^@E}>`(|ecSlc10SBaqs$DxEhOy7Gw9@MK-S9UwU3RT$ge$vN0cUGoi03)5^t_@Ar4WRWiT|D}O`srNV)7 zCgjkG*lCD6xny0I6*`sW6UBIj9|lK_b5Uh!Wm;~1Jwrz_EXT#<0 zSLAM46Jv5-AdEwqrE|f$rS%{V=AnL;%Rc{TDvxDC;tQ4{;^`yR#Yes6K4~zSd?af~ z-j0p*<6)cw96zZWJR^nH!b*BTNAsiT$rRgh!m&Y=YmDXYsW5XaS?fGdJ_qQPka&Rz z*gqXiB&GR;-S8hC%M&?(xx(<1`K@=?a-6DOOoYz$)5O%pgjNRY_?d7p6#BBTgk)iq z6MwKUC%^H26ulP&d8STZ8pK~RfM-s7p*oe7;D0J&rmyF}1sDLLHh6HXc5;LO0000< KMNUMnLSTY!su+U+ diff --git a/ThirdParty/Ert/share/gui/img/ide/table_import.png b/ThirdParty/Ert/share/gui/img/ide/table_import.png deleted file mode 100644 index 5c25faddacc7a4436bddda47d10f504a52c6c2b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1122 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 diff --git a/ThirdParty/Ert/share/gui/img/notchecked.png b/ThirdParty/Ert/share/gui/img/notchecked.png deleted file mode 100644 index 11765214ba8bb1ffe932876f7aa5949c6f053feb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`ot`d^Ar-flp1I4$swmO=@a|o; zNs7u7y;PJZd6e(2zoGuvI&yL8hI9AY_nIBA6L+ex=iSe{oAF+?MW12N0ZVpfO;xUl z>_mmM2Re$u)78&qol`;+00jp`bN~PV diff --git a/ThirdParty/Ert/share/gui/img/page_copy.png b/ThirdParty/Ert/share/gui/img/page_copy.png deleted file mode 100644 index a61ec134324c862aeb41cd9e4c43bf9167af17f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 593 zcmV-X0jJ0s@#c!`CXF{bxYYha;0^sl*3zsYxr8L$P+o8Qk^bX_y6uO$+mqEuDxg*oODQ@>5{d3> z%Y%n&izW!2Ktl8WYT8;kw#MS0d7Mm9z-W3ssC{oit==*@lK=AauOVxX&{`0wYCJ0BF+rQ^(8%VfC9>e@!c3DZ+xyKq+pHF|AD4?5OC<+-aBuhBt8< z_kd|@oFFf(zh^hLr=wJY?nWdv_>nX+ODBr(>Pr)XP?}4WwkG!PtX#&Gk4`PEKYx3; zxe7Z6KY=bQ?)X4aV%Gw3;la+{XfsXu7ewZLxpZ=(HL@?V62zS2du$VR9KSJGCMn>9NO>48w`i6~dv|?pJy!d=!YXt$UETVJ60Uc@b!T@E?{4dD zI9rJjW=Pz?I46r@^iKlQ#KeGOI0??!jc7DX9T{Sb4;DKz&4A6G*Rc-&uwHWad*t)^ zd|#hjPq<rBP^6Qj`QBFC)YO9OS43 zhyaS|eBldF2SMcs8;vQk&|ZQTI5Snim{m^H*$`CcRz-?V0tJqP1k1aS-1!j%W*HaK zY!6`}(GObL`Ys7Hb~Qxlt|aYb5cgAXol58e98f4&<=S|eP+iE9E}`!W*C+xnL6oEm zxtCNd6o&nR1Yo-vGtrm>haEOEZo`~5=MLC{;TVcrP^`v;V}!kiz;Jl^LG)-6(?UeZ zUCXiblM8886p=vDR4QdoSiO+|2Tfkdl}1p%4+|WrgBt z5F}lQu3%8thEVwfXPW3kztfg+a_=yne9N|DRl=hl?u z7OcRDdSntvYzJU=NdgBil}xaubFr1wTjnyQbFr7?qIxoDVX*%ibn!}ePhq=aTm7(N ze8B5&mvmciyY|sH5LEVJkn~2?@8gS_<}QCc)AO1kv__Fq`O-5*y0qT5iAh~VmI9d2N1p^J_8Q+0J{{ZG| B)nEVs diff --git a/ThirdParty/Ert/share/gui/img/remove.png b/ThirdParty/Ert/share/gui/img/remove.png deleted file mode 100644 index 5be9040ec949d49b2b45c945a2f27baef919aceb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 266 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPi3on-vv-kGO9YCS!o-U3d7N?U_4lvFNcm3or^S^|I zL`3%CY4t~z^|4N8JY*wO&wNI>-q^t4&-|^cTjw`6K2$#Zfu)BB2!2kUyWG&gAZ5~u z@?S^p?2Xg`3GT1^cj^p(zN+WwBW}nqe(nJ{=ODhlB)mv=jeyO z&&z@Qufm5L@}Ee5_wr4ke0(yag!PC{xWt~$(69Cdv BW0L>? diff --git a/ThirdParty/Ert/share/gui/img/remove_favorite.png b/ThirdParty/Ert/share/gui/img/remove_favorite.png deleted file mode 100644 index e716db68cafd62ffd8cbb6c3507879ef3948132c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 661 zcmV;G0&4wz@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ;3rR#lRCwB?lg(-qQ5c4wnI=uE_Q&RAal$}`K!bIg z=I09B6p9-+6-6QPAqAV0Wp<*eM)4A?jmotT_5$#Ij0HZ2JD zgR}Yg&iC{1zNXfi+dM;S&21t!n=lMx4%h@901_Ajr@&X>v(|carT+2;hG8rNJHUNl z04N~3H0&4fQEUDC;*U8q`6;lxzrWwLZMz5bfxeWoU#r!IKmypB)LuJb6IeYsIOrZ8 z9;O|~=@*N|u2O2;ZnslX%9VwMg;U3I?g0;hFIP@54C4i`YTI_N*=!0S#9hzx{zOqU zvMg&U2!dg$R2sOhI|NR()}Lk@ya#$f-?r^oqtOtlRO$|Z@B6A;E=R8GY9IiHTI&y2 z7?`H1C%_`5)VWe>N_#LEjKeTw!bHX6@#q@FWHRXkNGWNz+bPSkmVDn=p63nI>GWc& z)iN`g%oxx@i2k((8yg$nfSBVr2`S}D5Cp?=xg6#5`H|;&11aU=?(Xg!kSG)iKd0y~ zB-!b7thKeZmq6v{=;&20mwN~70dF#y%RmAibzaZwgWs2t`1UDoBUWJA#0U zbfkCbH=c9vIp_b@y7&LqH(6`;lbLsB&oeW7_Vdo3o0*#hfI?ecOC11#K!7Ip2iz=@ zSZJxJJT@@WSJ%=}!)5>giKdRT$5R{%0C4y4MjB}-vszeMu|kFc9DoqO2ZRB@7VhP# zYpiYpV1t&L3ab~^=r8_vIQa@-YXX1?0Zju|)_@ zv8p_E_q6p00DymT{#y#5`rEgx*iM!ZmXeSV5D~<7|G&cjGxJ|o|8MYjZ2xI-X!wsY z1Kk?@ciO+p{yXjII{<(kWBVrY-)T=W0H8h!0O)4_oyM650OXMXP&e`)d~W@nFHYXx zp3?X3`T6+?I@`kq|90rV!vC+qzbyan;6Lss`1gMQ>N{3ddk0$|H*eOzoeF>I_S6T- z>g8z*w`Udjuao$HT<|}d^&joHYh>?WkF@u|-pUL+%bYzNvBT|Q=j`qL)PvR82fzae03v`S zAOk1@YJfJN510U!z#{+-I05be67U0_0bxKi@Crx-(tu1L7bpNqfC``*s0W&XcAy6s z07ii+U=COSR)9@l4>$oXunQRkL<*t?(Suk(cR>6g5fBU{4^ji^fQ&$vARCY)$OGg9 zdIpLBy#ghJGC}#E5>OSW5!4Rq1C4>cfqsEDKnI|6954HE~UG;kXFgVBA>TOx$AJI@~VY z3EW?}d$`wlqZoDbH6}%ICeEeJZ-1w6Cn)sIZ zF8G1?vH02emH2J=WB5z>#}EjF9>NcigXlwSA>NQ^NCxBsq!ls_S%Lf^ASPfT5Ft<} zup;mv2q#DbBjLrzG3hg^yL5jl!H zo%|E|2>BKTAq5wO3WY62FvVMnMv7^QV@hgDVM={Ucgk4GQp!Hcbt(uI7nK^79aSXN zd#X;VC2BA=2ek?{oH~NKfV!J{g$AF7n?{Sqh2|AaIn6N59xWBE7_AwtKkZxEFSHA{ zz_++=Y29+Wm2j*2*4JC-x0!A$-L}8|@^;1T@!O|#jC6{0_H;3Hm2^{d=k%=fYV@x3 zN%Zyf-x+Wj_!tZs{1|c=x*4_@X&7Y~;fyhi)r_-H94H^u2pR}|4;_RaGchx1FnKa% zFm*C*G2dcVWOiXrWo}{KV4-G_XK`jpWoc#k%}UFv#OlWShP8`zj}6ME$>zhB&o<0< z!OqQY${x;M$^M;#hy%vqz>&()!Li55!l}#ojI)e$_7344*d3=kukT>)oN{q1=r3F-)j3)Tzn+~d4wbuZ~2=H9iCxR9GrfzX^V zm9VyOxbSD;0}(zExX4?PNl{W!bSka3kMm06eNmbI5HkX@2v zm$Q}2ms^l$mA8@4lV4C^Q?ONdr?9BVp=hUAq`0QUtK_2eL1{->NExYIt9+^=trDct zrV3WoP>oR?R-;lgRm)WSq0X-Es9vVNry;HpsL`g0r+Hs9Npo6@Neix3qP3?jsU4)< zb)V$E@%_yEi#mKdNS)8RIJ(-pDZ2A|cl12;>h%GAE&UYz?*`lk2!kd=d_x1nw}z`m z!bZ=GFvirzkBv)>PfV0e5=`byc}#swJIu(bs&{Z`{n?D%}a(ZQL6@s61Rfx}GvW^?y3%$?qBMxqy&Hq#^c@_mM?jAg_mB z4c;_ZF*WGJ;}hlc%U9m_t?wT{Grv#%l>Q$6g8_U2F9X(4>Zrm%+(39>$1}EPVb6XA zDFx*RgMyy~cZ6_+M24({YJ?Vt5rw&i4TTGZCx;(Jm`8k$WQq)pT#C|&DvKtIMn+FR zmwBH10{4aUi{Y1|FEd_V$JoX6zY=E|oPkCiN)oaav!xSbFYjqSrpJ7vAW+X~^KrNX)p*bjqB1tNgYy z3!3#Z>onUgdpt)mry`dr_f_tBo^#$zzD9oCJFa)>@A2RJzF#dcE5H=O3QLL@ie436 zp*_$G#YV+lC6Xm2rO?uZGMqA>vW*YcA4bbn%Nr^LD)K9DRlfQNeDwMFyUM2OYxVu= zj!&>p6*YHivTCVoW9mS40d;%zPW1~7mJMT#+KnBbWj@z72{xgd*_z*eq5YE3Levu3 za?^@xJ#O=C+iG`gU+Q?=G1qC)IoV~{HQar_ySGQZrxT-uY3-HkZSIrqYwU;h*AGYx z)D4Oc)((je)ecJx*NsSyG>l4(ejbw@YZ+G~k@e;c^^MWr4}Py~dTw59MQ>AXXYKIp)a)wm4(?g(t?VQBZw_J)=?~FI zVn-dv2FE{6+)pk}WB$m& zmX4a5mYSN5lH?!Ze_#Ij=fB2(D*=%b6O)pWQjn2R(2$Xl(fp0bX#QD@^1oF{8$d~b z!v#tOgV+HaN)VV5bkhZ}U|Hc|#SAw5gXUkBIAB~ndp#K@*xy9s$+yPgS@^B}$igQ> z=t1`KRJALD$Qy7&to+S4l17&F=(%Z@4q}P$SseSr3-ycJZ-B)T62rY*u2H%* z)}=`@p5xwLIeir1DlrlNBa|eBuaa|+koZ>6f$+J>fh{#_SPp)WOF>lbG{?u1V3ijW z97xOXu?A`CCVyHzi}`TnG;oPHgG~OfR*=CEO%QQw6H6d?Q_noMVl3jQG}!Jr-Qx{o zCFlnw+bA>wmOlNoP`i5jVcx=pX#g=Z^+(K#4ro8zlZVntbEfCFf#|4-P$;?V4ZxSw zQ5OtPZ~;+6K@roN218u5(VqTmH^8(OQRobP+m3U+rP^AeG>Z$)Y}zU6a6|i@hKB`T z$fs^qFtf(@;}S#P5)4N0mm9WJn)9CTTV2xf z6;;4ZG~@XFzX()Dmts%5)$z%^BDVE?q-@BP)?2SoYISZNZRa>zCC;gtJ7S6IT1Cl( zBWRa551{zA7=(6J>9S|5l^Oi=j!LsHguRF=w;4&W@#A&B((tb{qt88hgmVd-x@=nc zRaJbx@t|P{tMO!o-VS1-QjF6n$T#dX8u7=dz!BHu>;d}eaCQ^|S7wsxyZ(1Mg>3bG z^@N(`ZD^7iiFO6fa?UYLa-C%~AxE-kk|zGMCB6tG^Rgj_CWnbYEriWtiDhRB5&o^+ z?X>T@_O2@#K~ngF9Tj5a6gg?_OR}O&$VfkLyxJ4;rG95BLx6)5KPi0sjF7_vb#6j+ zABUGf@0x7E4}4~PJ!xl$5>C! zV>9=9PMV`dT;sT*jC02i1JXQ}b1IqcH4J|{avHiAW0x5NLqAFME<7&fv)Rj30jHx92V>t)f*DO zTNb82DiG<{2@A2x8rzpSl>@%?dr&z^4slL7u`N=IPBF0>i z6$0zlriMWs8;f{A(fabKYu-N)!#oXLHc8=1K(79H{-I?wM1MGKrBAB(RpYi=$DsOv z&w|l{8-N(%Q{$-9YCGOE4oV_u^M!3r)c?{Udj7N$Cy`3Ozfpe5Z|mzmN!t8_qNU6X zQyL(Y=Y+AiAb@h>QS>+hLrF52Zi=-DD?Zt0b*9zGPJ^-=@{xmu!OE&;>(MJq@ zk(Atp_qzpprfBDV+L4kT#bTsBEqjraY>eQoJ3q)t+b)00HA(>zC~B3mY6n>|uaS_R zWSyS8f;Zg792{bAMz`KfL>#jG!r+vNAzvFtOdpg`o~|KS4E0rQys|Cafnmc82ZU&;zY{a7a4#q-s;*BBcYldL$Um2eUXp+0@>L(1(I4njhpzD=Ee z-eV5*7g<@3-Dhp#q8nNtKaR#;@+Ir%-2fmxi33&#o^Er-ks_31xjt#NW?|Z!&P%0- zz6&gi5BvM4psOM{AA+r_IH7fj+}Dk!`J`!m;GCApfYALJgU$3|Eji@3J~YX4q7r}< z-i~>vkwIw#dcd8i4z!)$0JLgU(XUCv8~Xa@&KS)3@|YUo^ZQ5L!Ze@Yex#E*lPIF4 zEKWOGnV0mk;R>{8C6sfX9&e;L$rN^zbQ6W(4a@OI#foms&&zLr9rPVv-VPK*8d~K1 zITbS|so{TBD4-mj7zT!2ZrOCX!%hlBl)K2UYq_>gulTqQAGM~z>(Tl*>Wmu0+Wa>fl!S?5i(z_Y_`rCUdQ4b{$q*FV;N(FY>KUDyeXAnQ0nbx<${Mo(4RFiz}(%;W3 z0(g6w^lguyHYp{=Y0^f=u*ic5<{o zcN>)j${d-~-I&;sI4|U^s6U+EqcSsmZt(u1U486$PX9J2kph!YDAq?@Vc|YP2TjN? za(e;Io6GrjTn;y!9lilFhK$K7X6xUdhT!N94ic^TRrsUtbM|7Ww&~U~VaN3}t)>kzI97Ttj>_T;W2v=!KK(O0TrSY)e& z^tnUAr#g`S59Z~g%NyW=F9+8`>5$zz%kGvO?<*sSh*%)v0Gu;LnHb%BrdcNX!@f>~ zK~Q*@?gm)b888@N*ZIZ=`Mm6SeIcNCh12EX7uuC|v^JaM88V`suJ-sI-LfA17RaPzxS0rtX z6J12P$OyYNi5ZH0NFbbG)i*{#G?}inJz5*R#jAvN?Pf=<6 zfhLVBpzh$t9iEm@jT*8m-ohy*DOi!m@;GTzP^pJ71y85C^zoB`_wM(rg;_G#W~Gan zHkw}3W5&Z@=QDSpj9;Gya3_ao`+GvPwH|75p0*#Y(SY6J3b_j@Ib<+X>Y81kLUA>El%h!Yasf=nz$RGYgd^s3C;R_*ZCY+vuD7g#=fEL=U$WM(qFGC zP=aHIbsJV@4E;=@hV_1ms2ku!T+B`tSpR-ua+er~oMU=Z-6XV8@Y_Yhx&l*;c;0&f z@B6Ek_LhLRy_9TRr__1Sc|7cgvhNaq-&(@ge1pzVqP1z7y@wEp^SW@NuvYoqSGwq3 z4;lGKD7$#CVQ1B*Hqua~bv#w5;1Vk*W$1T=X4eibvp?&k$LCBr=Kl4J`79uWNM}EK zIdC*qVc}uPwednSpnzVZ$o??CTLDTIHE&V^e$b>68TMF&JTS_gf_PkDh!2&^Oo@Zd`Z~8#GPf9 zRFM<+Y>+!V^(jx&+yjf^Z$MOk(j-~hozGm~$De)MHj4#PMkD^jgm%gX;K&AM`fdY*La5}!lbPd!acmRi;Xf5=0BRZfua=`&QCp@ zN)JUn=(+PS<1uAKtCJ5CYPILHObqu#jlfuMqad6ZJxu#3> zg$}W;X+d5N`lM-l*N|XSZs^vxlu&a(iaUb;a#m*kKWKeDS=Vn661c&(?l9FbjhXYLAluv2y6s5 z*atVIw_kAq8X9PXW0oo}C6JSGgibe{oVs-eK%~H#YGmqCfS(wrqe=IaK)By6*~^(Z!v*PZ46u}$R-pc*7l&s7 zeAI3G$XW1ljqgH-zuUo(G4u=+rfrLIj@(%!h)CI+4xojD~l zp-=4tj1;9#zU%GGMZ~!CyQqE`^nG`<<9v}NG4DY-G0n1Vl+HmQiI3R_r6ioB)+z_c z#q&J~EU=1{rgW{RhS3;yhwF{RQ~dwxRo5SUmy(U=-G3L>ksRcu9x;s`Oob_mNLK3R{nglL;&o=1rro|`_%dEt-K~Ar(Y7g0UXZlT( z1fN%kJRB+4{7`Kh0iXA&c%h$RWhMHY^7)C!-m|elg+sQ3C0xG~?);O2WL`qXPbr(- z`dpBFtP|{s;Z7Q_=pl?Xk|fDWgN7uj9A7y-dnx}ueo_){64_fIkQ6n-6e7)&`m9q9 zaivSsC$YrB(=EdZ%GFl=r7>zu1A_#5$hBmY;0ua$pouSvIBM13@0Cba7b}gfi3!n= z@p3NTn>f#Wl=@XR<_Uua&Buy0jEk#DVl2r-AaRN1%voIYuAb==)ZsLH0dKNaJ5w>Z zPKZyNwZXx(O~I;?tqYNB5TauI9iKn#oan=E9m??FP1w>;SEIlCVz({F$lmzsuoA<+@`P<)Txz)7T#W`E_q35D-Bz*fl+FMoCzQLLR0e6A9k5IW`P z=T$A-kTU8uUKV0V^(-$mKrEnC(>mAIsM9sB#noNTQ#euP_?j=%(0w(RM>z6G9lIYB z=FxLLX83kJvGM(U`6^{1ntoyIAnDL6GsA6>o3(C!Pjijsbc(ZXU#$jz-U1E{SC~EX zGtr}pUw1}-VtbfPu(Ua(MG`JWCwAb$f9BY+)scu;g9Um&D~BMV78E(0OLa4Ek2=oHM*Xe{*-%qF#AT(N*&+L!IiAdg z0#SQBG2|y;YZ-XK0I!5`$EZ5=cxmhD=Zg;)OniF4?)vyiOQSq*Lgxu*~c4z0gw?LCBrTyqs5vl7`{%z^fvop6n?3?N3%tHjb0!kq#K#5aQ)~*#DugyfS?4B-z33tyvVl`QmnTXlESPY{ z@sbwP@?4Mgeqk?nON_3$x)wC%PhUGtwCDgCAe*!voJJ1%WL7?vB}E6qw>T+xo=kC; zZ-V;A%5vQ1d8|9JJNa@^fcf|=hNONxqy992B~5Nh8=A>#G=tR_>zYGPy%NLS`%MBJ zkHt)1B^_4MpP?dloJzr(-YnX}Il1Lh>Lx61;B9mcE zsL?h!SuLYu{EuT9%y1w>*kq1EISzeFj-K;eo0Tih7sS~(?Gq7y49bt`CEeQ21QKF= zO|$T&ZV&QfDbv+PFi6ftT|^^pDy>KJqNq%UPa`ZVA}eq)U7Z8Xc~YAElE4?53M6f$ z)ZYLOg^dr`qRkxcVqlk1s&g4tyBbP0#@4?yX_Yy0thY6<_kV>jR9^^mw6hS&UywKJ zn!a)xj1`(WBUCt@2&uj9);eGh4|aUUjLJHn)}=$Dd7Xn|SC6aMAU`1$0a%GwGAhJ9 zm~v&6g?D^eN=U$+K2i++Vp*%6R@cq^04iz&K=vh1UGH}v&mmmh>p7J#q9->;9WyO8 zLw1!V9cTzpA&v~!0Zo!eeq6NcZSwhWhq)GCo*XaB7MkVcndF#5k z+Ov47K6)NT{&m>35Bq!r{oR1$WfN{rG9*MvlQ<%p+i{=l&j}ie4D9Ke96+-~9iHDB zKNm5zUe1XD$zDvB!#L_7XxbD`#X7j$pYQF(v-D*5eJ+Pw88&_=hlr+|+_~+Ld923_LasOK0(s&xDEwx6d(oSGVlOpV~)gkA%O{0elbH!x` zSxfShiyGC2Cv&g=UTt{7sgA5zC&Wt|} zqfp~%9s7N9>j}~An4$TJb+xzfaM4gbs2|e}u>Z43tD0S1acM3y={=F;9=gsSo~s?B zF0~Z#^GAuGef_+?=&PUla?yh?WAm4Nn5P)39%($9cRWNt$J0|9DK0PqEoH^?xx2?1 zub)!DWQAq|BThpW1T?#0?f79?m-9(86M9Or?(*5r+(G@dA5!jsUSO0qCzob(w3sxQ zj~TTZ!eL9tg&Kln6HTL2++!3|$B6|tB*pFMnm_=;BFRCc#Y|(fe9WHoO_TnjAK$6w zZS9d=Jpm?jj?`WT0-d1$NXS9At&vG6U(=)~f-+t~pb~PZ6PiwwddyTpJu$U9F$>QY zONSsbla%rPWd>T%sz{q>ZNVp~nCUdVuOR^g+uT|M84p85E(Z)g=%0pe^rEXVBwXTj zKl~&oYDMUvK1Sxni|GqqDM>lPTm1fNg(dA~&V2{-{_Pzuo3|Va&whK(_dpMQ3^<}4k@#b=(WtDPOTYXu2dz0z2soio-X!jq z+0GP6sMOM&LRg7qi$P2Fx}v$on=ICm#*$n3BO_lKyN#KItAZ>BxrjU!N$sq1_8XWi;_Sm|83V)ouGd=SQ@YyKp8 zFx>be=RR~lyL@Hs8lueGlxEDAci1oy$!r5>V*{i(S|@G*r4siEuh{bgUHyr5vO%G01=M-Qa(%b>p!iHOwv=Sv@3xE$=}nIBTEO;Wxo7WHHqPfThZ)WU|y_z zxlAEO@J`HAaw*-->rmlTVWz0>ZgR_+byJSW{DhaaDMF+;>q#U0Ppk1%epnP&;XTxS z>=vSm9^!YP(Y->;`0-T(63;5gdz-~dmHdYvtwWE8xff!@AnRXWkGsG zGHV+TmO4+~*46eM-o{JvjfY$)pi(W@t6I}7ZbK8T@+Th>TD&=W75rlDBxyDUEdE6- z^UkMz^6aKWbvm-2-G*fwUizO|*$w3FS$W|awP!S?GLOGCJ@C6$SMKAqIdkjFY0_ez zjAgKmP40(rkJod4`V^?{Ye+>RvAYNsj}p0y{1`V7yN5!k@}qrohC2+=MjL7+_cjq6 zBp}=NcBpZZ%*O?9a8A->=QElSZ|Ro~cs--B%Pv5H0UWQ4BMMWTJX ze9pTlx2*Ut8-stI&}4s6JijpF3q=yF6+WE&Y`NpG#OHC^?E8ti`Dkf2`=U-pajn(G z*?>&MBtCEa!_&mRL$VI^z&_sw|L^AK0f61f2(ZkM#-_^nlDlN_jbmEy`iz|PXmUR8 zN2${V(}Od5?V>v58DSGQ8d57roxgEeQZ4P#ak3Pnr>>ADaKHJ{t5p$yI0v8R(-SA$ z(uMtQ&44v2`Rr1{ho&(}!(L4{fIXW2vAUWjGH~oH8J{~!){sGB(ZoyFC<^(0=W4-4 zwU06FqlN+Mn&!bng@uG{*tc(w`!`qhojG@Y(Y};3m5!7tVh;Lu?43F2?^YZ(t-XBUpfrQ(RTGZ7Ro7#%oDaURR*>WkpUY3=r1 zx|AxUUN!E{meUJOdVXS$mSx4Y^BF+Ij+s_IeB^cv*f7uZZESC-ST%l#=MI1;|2`)KeLZ4W(_@M^>`R)*qBq4= z$V1hv34`E;EphCIw7C?xW+BeUeS%US-uJR}|Lv~)ysm`7Z)G*`oILdGeiRGrqH;9B zZ0_oJl5M)5dtMW>#evpo$%hYjJ}2_@lXyU&fnE7c=eul{wSYFy6q)gFa! zG>=_GhRaDy1|8{qdgZS|zL?~XSK22T5AZi74~>$eM&9ZN?osI>JPM{@H-Ny_5dCra z_;#(qSaC->-T9PP$z#oerw2X$GeRM|rHxO2{aIoi5e)eTB^rw-wlH>ckqDGJKPC*j#C5bHPO zcvmeuxrw^FZ|gmcLmV-2f{{+T#l0KgQSDb%+cf!aJyN9%X>*ZIOBYE? z!y%P>n5$JZz3JO$A5ql$lx9Zvv-w-xm+eT6Y5EtAo}3>)$N%WuyPRIGxk=*X#+vpngbDezcTyd!BGNCFu{=r73X< zaWJ)Xe__vA2HQwl=Z8&ZIoi{!U!61}D)q_?Yi|G*v0KaV1nq};yqq>yy!)M=YXp%y zC)YLg6ta#39>UX;*jj2=SJTpJre>y)-B#yGKxdJs|6(>ft?9hVEvBX*7YB(==K18A z-+VYjY{zX2M1pfIUw<3bzPPrNIzoGJQny2D#lt+53W%0CeU3_N9GT?VpYnN4Jz@pU z>d7>|i|yCgFh?$27%M_5Y36PA{{+*dEuJoKOw zT{$nSQL|&5TP_b#OM5n|6Vd~L&=r9(vXp1WlQ;u8_uoF2LO)PI_jrF38nk2?7n}*$L)V-!wSH<&{?(}J_x%q8q%hiHy_`g*3ip^wL=R1= zj6a)EEqG)8j2S%&DSxC886v7C6E?>OlGXGw zuuDQs_N|=vU@<^rYNVAVii3hKrAInf+qIVl4(nFFPazs*IHrG?cUQua)0&m6* zCofh~S?skgnKQ`EaE2x7vkZt^PI(>eIMGvhtI0%LM8tQobd>JQs@fpel4Z!IJhS3r zgd@^XHfp4e(VEA3aBaMe%@`WnPV!&7yZYG!m-CM36(+%arTZfu7s2*6+JjwkE&%=p}M zrKLwU&8~jmsUjg>nJul!qrEF-3SOa`vplhSHtj}04~FJyiw#ivusMrx=s1E)t`{nz zWmQ|OwQ2k?PeNwJmp_;0y!?IPGNS%rW6U~rYVD+`N5v8EBR%xgYg6B~FdrKtFk zYx-#KXjg&{f(6fbC*pd-%zgOnhu@Ba>85c6oa{#s1uqYctJ4P>5VOK8^w#2WZ6(KW znrqXgej{?NE8VaKH2-IKsh4Gs7JG1|w6>+OymV^Bfn%s&A?F2|>hper1Al@?z;XZz+JEgdVl(B!=T=ShIj zsigf}q6&`2b<{&ZAeJnmg4cJcQXf^b#1bu>@Q&r4FZ}+yJ}CS)RfA!IK(L}lHKs0K zTD~_zeK3V`lxgPDs&0k*kNzm=%IR*K&xVFrWy95ExqV}|D}#LAn;hAGg_nx$(4gJd zyJpWM-A;ObAWdIhP2_~NHVyej-+t1SwU)VdoK3uq3@CoqXaJ{MI4$2WM>va0b!Nz~ z1|KD{YG$>|z+(JQnF?E@^-pfasSmr0_TQ%K`sp2Uuzx*v{`FbUl8m5fBIe*F!CFF- z@k8C>-+Gk@4r?(@T12RFf*S4g08zZax7kzu^T`*(-V=ttt&fVL(!LL_M3PlY1D50@ zCLz9W1|2j^2K?JPZ}%RJXdrS@-7c7JkV6S44>lW3T;ID z)-s3ds8U`bVq(kRYmbbMM+Nj0JV^EoimR&50ncD_6rwVTN5fLt3 z%&Faf^<~jq%)~0^`vpZb{IpU2XcS!`I?v$05E93A`8D1U^@Zd;Jw~nckfALli$czc z@olV44&J>tggrumMAj=GVVny@P_sC;j>3w9>wV9D;f+ayWH<*nDVFjENDvU5Pu6OK z6w0sM;+dMx1+X zH`K^YMuo(OgMPK3{?*_Uy0CaPafijqX=S_Rd`b6rJG#&~O7-LI%%tzDcfm+hOythJ zh)Y@U5xTR#ms}Bv_*v-tzS~X^SZ`8?w7RINaX#Jn%@?q2)Bp{!D$B0+P>8eSxX130 zN;jH@fd*#sIw}CEeTCuwF|$O>t(}px?#>SE(lFEYML(1 zO^r1g4Ww@h-ciB|8C~|?hngfA2et#6Ed>jFlSpSjZQoSRP(%%N?s(17opgTZuc|z< z?S~W^d(-m5wd(FJ&RPxq8{aaOOchmeVAG?X@}Z{0B|DYVTXll$p|Sc3URNv6Z-97{ z`k0ADx*7H7tVzijtao@Z6PLpe2sSmoW}D*W8=y%`ykloJvWn?E%ofb!%>4&UJ<$j$TzE{zBiq=hw)5q$Mt;6(U3Jx;ltjDDS-c?tBdYLDeb8geeF3s%gZ9OYsh|eH@&6#9BAV?Hq zTJh+CA@u^)mtj=IrHrnx{i}Phx$B_c+1=GTH-MOJ_(}v~&g0b^jU70^99^i?|&5gJ(Yl9(}2fvA*kE+c>Q8>?`f0E;WTg6a@FA zqQM+#_OmZzI4zF&i~56-*{8fu%-YV7ikPdTAv5a@?1mmG?ynW#*>isE;V2y1k+V=? z9A#iVpzy&RVbGp_Mlz{r`rQQ{~bO!8yJ`% z@W{z_?lDR@qvrF>{4`1VAWs&>z+etD+Y*vbUDj~pJCy?eh*k;r>MdK-z36js*wE(X z>D&0&etV$V6Z=_z;^D&p=!HpX48WNzhv;$Pf9?PMwv_tDx=TLS_mqpl-`#fx#~&fa zJGyxs4D{6fPtZd2tjyV0zso4snBIdLF<%};-g^_fkfsnwi;ONCjPa=n3V3|{#Nvds zB3Bf?3aO%Xkc?~S>0y$SDy^b`;z;|PmR(y5F#9^rGrRgL3tMqSf5C1JH@|%#nCWXD zAQ0vj-I1eTDb_)x`bTOh#aP6i7!)dPY_h~L9bpAs37$XQFs$dw6;yrG#|n2kI-&XV z2%u|}iIzwdJ>HDTr$6OWZP;iV`5N=ZKSeCR{sowapXHfdsD5LQE={zDGDYkfKoUR2 zD8aaS_Gl+l2O%z3lBdzK<5=F0g>ix+~$8akoArO00U#L}#H=VS^Od^(hOE9@CL zHolh%*U8fyZEW68=dZ=Cg;pq)&2BKqto72DyRX<|xg^Pd$sw*!Y05czhKsV7R++8a`{m z&4DcQu>A>H5x~9^tu_)hJk6ZQ$jJ4skNf$`dQ8aQAdZg8vjxv}w%EYxd3XTn0%>_o zNbskU+pc*!(~jOgMk465i5&GLO_eqU$wITt)vwE?c!>vew6ONmxl8d!0R^>J{kv}1 z>3Ekor1lc)NjbWUs|a)zzN*-s3qGyCU@tGZV?y0_Sz7)s^#zCI5ZjNL(=xJ6sLr6G z9EDHc(PAQ*Dna*W39l5b8qG_Il}9ZZrPKo=Je&t>$$>#3f3TwPol$5MC-`T${%On8 zU6V$E3h~>Gl4%F$)NNv&ZoaEp3VCJ5GT}I(NEF#ju@(Drh6N83L`h4=DW;0fX*!be z#qMnMUGvqT)}2r%y8!w7UbPzLataG#op2YB>vLxdW-T}JJ{K#v83kQ?r>JJop288O z9{$f!a-Gb$!U?b&h(Q@qgZz1Es=@yapR$HLVxA2)#4l2_)z@5Xw;)sF#nMz{{e(4j9UbIA8=2FYUBTKqA8 z_c`&sIEz1ezvr(w0*r%ftr-6jgQ^# zSc1xZ`;OUHZ%TbwBpVGrjR}BU6&6tO*9{){gMXwk^QOu=a$N4Y)KrlRQ6>$$W{cnR zbxn8Lsaa?&sfEe8|9D0~i?Ev=%b+4e120X|Jy}(Tr~Q7c&i|} zet#}kAC%Xi`D($RYw16&ATVJ$sUkw}xN?qZU}szep=*OST!#Ej5C& zGotI0Q9<ayNl@hE%c zG>u}k7csZLU6Jx@SYy)%mv$Yd5mb+j4H`z0yWe(Pc$AEWs_OPlPTiRNvF9aQX|mg3+#S(7&h`f$C|mtMSH_0&>CKMBM1 zBd`LdT;vDj$w3A<+*3%(cpCcwxYk15{K0SQ_YRgXyBckXw&jLH(&Uv3?5n~iX7lSb z>*|IEwbnS7j*3Pa=bjR&D`H(L<$`SlTYQHlT*p13cjU6 zxRYePl1b~fJ@WIcl=s7(`q+UaPSv#`l?E@&k8)Gk++_dO2E3)ZvF8|+Ad?uX|H-5~ zZr{Ja^ zb;BC)UInv6nbj$@IOF?n&w`GJf4gHc2YaQUh(C5;U52c`WWRu?SuKU9IG%>m}oRCK(h`l&ZDYz1{d7zAx;q1 zgkR-XF#~OF$B@b;6OV0knF-bqN}9!SKV_?|fi`VgMEkm~!vLYF+zS}%v=%ZnHfXUk zTwU5s_vi_Xe!ow=`3{nsm_I|2?0Kt>0gVu67K8rY`&h^PEq-IFuNg@A+kW_g7H0GY zAS|CVq<^MQY)ZApvt@p#Egf>h z)OqP;>^4=mD3yx`SenUDepYFTQGJF@Ko&GCSH-mOS^6;-U=dat1;m0E?yE?YvjOzp^Wd>&k+3i}!!!Cmv3P~%Wj1a^cbTU{guAW=I zR(gn}0Y{N>^cXF&fNYLGvLxDi*|{c=#{5nEt_n#5I9};k{%FNI;Vr9Qw+8jrYdB&g z*g3*}I$hS&g!xS|@quSsuA->E4Z)fI&^m;BzgvkFgj|CBgk2U>s!iJ!_+C?Q>uIRT zBENs(!+xs5&~1msRJ=g)0H5g-Z^optdILw2>^O-yq_`Dot z$LKp)nL-OWGn?ML#AqwGqxQS;!ecWl`Ki7!Nt;w9^FdTn8kmdTd#kpw(zfXJ56Kc1Bbv2~t$F>K3^SxdtMhQ$SbYm{@OJofL z+}1zbCIW3Y#55HS@mGHH6lED<49p@C_nHoAN_&OgS6^DnF1N|LXT}Xd8=ANY78vzt zblE|}u_xWWUtj-j?%!n^k84^u!#o3DpfRT{$8b!uHV2;yKgGZf>_ahsiR9d#c$xd{ zj3$!yYT=q?Z@RS~$rcRecbn_=-6mM!4Pl2`Nlh)fZYm(Pv(Qudqva1TB0kZ>otJs; zid=_RV8Y2lc5_|ggc?>0X7fm!DSwJTf7BEA)6>)Ie*s8Ax4!c9`r@-L=eAjy8NqeN zb3T&*0Xfw$5BLbpbjA^mui|EHx1lsQLIN2a zvi3}n1#Q{f3#hlR7#LyiSS@7RL5b3J#^48W_je80r|I)Zv!Wr|2_vpQ14QE%xt8OL zY1q-fwk*53$`VJWE1cE8q(7XCwsyi1r7qbezO&2sj-2S3AHN8$}X-D5g*K`f4$L5{{XvJ+DTlrj^v&}JmiD?ANwt3Ry^w7cRDcDeVm)N zjaZ)F%y8;B8*%HBDkn|Dj-sDyHZrZp{{UX5DmM~(dUyONib+`xZOT__*CK{BC_CU| z9SEnSd2oc}5!V#VV~Fk070j@${dl8e41sb0Pe@&b4`I@+oHDI z;Yj}Tp8o(!j#w2A>~rb&zu;JEc?5%i0mlRqI{yH=DI*V&xMXz6EGYp->wI#lal@z} z;Ed8h$O$BL?NZ;q=LopMbipT+?$qme(HC=lF-?fizd+LlbArkaKRPJCW%K*=7z3c{ zarjYBQq8Q5tB*hhD0EDh$sWfQ5|U9zu%wY(u>}01rYekVB#o30>PT*Lk4kPbqttOo zqPzSC#G=X^Lot%%Y0LCA??rJF%o}-USv$SM%;-is( z9Q8F;704Dc6XxS_ClwRK&g@WdqNf>l1J{y$g$y3p?!o!SdFlAldJI7`2+VoPDb77O z`KYzIlHPTdNdO*4Vgb$#Mst#Jj{8MR3NhU=I0z2aARWYZT-I*Zcj{Kgq>{yLc+SIp zt-|6(9dOt@f4Jhajhv$LLvDAXo(TRWCvNqv5iD1bM$7?ln@auP_Ic^^RqHEwV1Taj z{c=db=cwCUYEBKuww|cnw9 z2=vVolW1J2JqerFw`zL17$?0~SKq;Jr92&=eAOG=s}=zaFhD)&7yxo=F#LKNVUwOo zG;Oe2;>wG+g_(cT#WzaNqDT{D1H) zRm|NtSx(+ZT!a4reA7%aF(j!Nz!EUVexH?JJ@;R6Di*$_ix~s1=FUjwvM+6|r;+59 z1cWgWv-BHI-<$oKzhY#K=PUxK1CE}*cm3)>n~*8tx^e4@RP38#sP;xb_I{pD3~C5C z;NzNchQi$gMF27m<0PN=x&HvrYR%oGgqdSfzE9r5w!y& z6(B;4I&Jw!x6W$CxKAgsCzfUCYALOVkIe)+cNH8WK-*&_cYW-8ccG0J7BQ2w0DUo> z)0t511whAA2|uG!ERP!EOiBLHQJjCgC{P`@A>jIqAJgTfVT-eIINq>G)d-_nA5iihC4ox#L7y`K;=h~PRL+7?COk|ospl7by1~I`2?@B=!QQNIZ(HB1_ zEB+KZ1?l+EwPdz4+2`LKw<{S_ANB7#A(7U;sbGeAZuV5)k*<#+?$;XyY z9;Z1qZ8C6AQ~c?%$gaD|!kl8BaJ-N6ij<#r{Y9mU+Ky5(+2MP7)^G)|Sm)H%o!gff z$0~DGf-W*g;ns`l#}%NctG6Se>-f@nXj5qbj^dhyp`XcqcMZsWzxx`P_2U%V1d7Ji zEcD~ORJf8bg%=<%IQA8KX2O&Hc&dCBC)9VQhKOTcS&lHEgU>wl`G4J}D=GP1u)Rxn z82&1jCM_JLf{?!|p5Pz6D>G7^)OiY9++*6FP5L7olxyK($5(|xoW(pKJ z9dq0M`lXgV*(;C$&RZ13SlPPm1CzAyefHG5VgU2<`kwy)_tBt4FdfaGnYrnK{xvBGkH5S`A1y9`=`g27w zno*KtU!dzpC6Cu6(jm-heW^!UqanyS_NKAka0j5J9%;{E&{M({T%NSI4TTMYK>R8> zatF$Aan_|#fJy3Uk}mF~^Hp+6(GVEtoQxdzAH_tBT1IizyL)<6&k!H#`6OqWfs_H0 z^v8M|8bSv2d``zuu`` z_cHpPq*ZBgBL!YP2e9?0#2w_?i@1T?+xU$n$0+UHmM?Eby{J&CXPfTI2h0^uK5ysy zy2D}!UO~wu@yI8SoARw4aNNgqA-GMuR4N`YM|T^4h5rDCv&#b!Ooah~0FF;p&hNax z?o(fxnP*SBn%eOsg#5l>3`ZcZ-7E8dd27)lWnsrmab9U^H_8_{&j9)oYtn7Jzb$rT zC_%S9aa{HODEc#6dodXfPI%|}Qc0b>44ROV&5=!)kLg*IRFDv$cQqBV32!&!h|>W3 zvH8F8)vFAkx6F70G`7kD82~$^=NQ57)KU&9 zEd=#rB#U=BsHe9{Bf}4-YRTzLV1A;SV>15FcVjZo1caa;ypM6(dt(K**5$3_R|ql5 z?lYchjIp~fWA&;bO|yRN6>xbXns<8c4lAL#buvb|Bn~o1TF;LB9mL=u9A>CVb8zfK zGh^KLr`uaJfNuF?C*)DyoRaDhOq$~9<|!mOK1*`se+m1`{{Vc}j`CDvsU2ys+CvI$ zjdp|gk8|~?*}Svm6Y~y+g=W18Yf-LwDsh2TWqh#%IX!B5nQ_nF>r`4ofuzX!LH_{j z(~A5?_8D<7K%E%p4Wcm3;`A0u}ldU{k+$Cf9c#!0TY z#YI@hcG(0fyH&$w`-A>9G%U#HcilYa(9~OSxL$w8r%x_bR7{q}Ty!A+0O(Z1p=n)8 zl6e4BPd7yhPI|U~_F7`R!x2mKFYuGs^Az?}IKaX5JLh^u^fY+kpBP~2NcA_X8{Pw!Rv}$@CCqS9;@D*%aAZYAKm`|8VpO{iU5gZj5xz! zcgK34%|jUiMN#RGoBC3O9UJEMrc9jhpnyNECJ2rV&G$iJ+XozdD#&Tn5LArz#(1i5 zutzw?0m;he6>V;m4XPtdf)CW{5Zn;f2lwKY|k<+%3rpywkUsmDFf z0Cc1TQaT_Ze)nps83ehM_2?>ju5h4*UV1U-ilSBb7bouY{Ao5)L+ZuYV&5{JFnVpr`!$VP zi&!VCTKXMWN)A(u;0IDm7)n8o!&IvV=PramZxl zw|}!&8e5P1Y2V@>-3l1G-N)EaJXocuW$gzYV)U8L!1$V&ukj*bX%yUw2a0{KmZ%M z@H^37FGtwqr_~xb0D=ZjN^H43KD74r>J2f&5;6BSkVn2nbENFcx>7}X`Xco693lK_ z(Hlq|hf1$5e9L?sVn7ZCdp8wejGlXQkEcp;O)Yu^o%9$$rjw5JN=gIV^{n}>rZbCc zWbD0Cu5*%K36`CRX%Nrx^SSwLVKrvY;%{ z9Q6zj@(oXscM_8pSvz$Y=j&AFSqtt($Wc?ZzMzK$!s>YprIh2-Yi_8L?UXPvNIi<2 zeqyTKhNa|Ij@{&KcXJu57;0~?9`>MbC8`Xa@JAh=jD(bwGkPrL{x+z0u{zh|_>3rD} zu;EF`#y)^lWs^CO75BzRAMVqfF5H&G4xaSX4Cn|1=e9f6tb_=lwigl;&&qR2G)azE zpI`pSQcDnCNIA}OqyfizYfCvzo5@geRGuh6DBeP%F&j_I>Ob9oy-pGp7?VHmbrlG5 zI)C3M`WjVtCn()G+DHEY6HE(3Y3KuIq3Q)mZ5}z#1n>q&Pi|@}bdq3xML0h;fA&^V zwQ4w;K010*6C7KPKUy+#o6X~2{kwnp;GI9aVJJq9W7CRLm!@>Tw4Y7}A$r}eBdmVkLUBNq7r{hVD4`d2D zWapvu?ZqfjyM+h7I-FBoWpoTaW9>?^j1>{Kc{{Ritff;ZJ$E8vwly86652yIiOL{+iIL`y0&Wd1ZN1coGr6Zr`OB&)e zBC!P@150F{?>bIw=!}G+^^V!{{Y0(ZV|H?9Cg9(+OFAM+ulNS z{Y{8+e{plhK|geEuRgqaYdNiMl9KZBJv=OAsYasrqpFhYYxFZ1@5}b!W|8`YGw91$oPU-%dITBw7Zb|wjEXPWDwFKGuC(DCyMDwS0z zt0`Tb@(|ICb;Th)2%1c!(B!)BRSkN*qUm=6im$;?Jdi^$gA`i{{YacwaM~W0~??Aw&Yau$v)=1@M~66)n!}DUoKSwc+O&QIpp$; z-`%cwHN*}>$ja(?89QsB^AV=X41&C$L!N32tuAY{4QK$JK5v_XslfiyA{G*#pa+3 zf3_-1Xxs zXp1|7{r2mX2Osb%NWf#aBaU{rAC*j`A?K&CCYX&IMGF}tI46w%07{gCe-71J)^X(# z(+8m#{J5t*&JNSbAC)1Gkbns%IOnZ4DG`n`ewgp|rVL1VAdf-Tq>N*NHuJ~7y%N|K zte*U4b5gl(S>080*{r0E(!&b|8@xcge@-KU!*S&JS8i zTat6Y??{d9oKV=*O9h)~Jbe_O*d|bT>Ff2Ps0|pK zbZhkdDd`!J_Kv-AQAL1?JCRan2d)X~YeNC$r07r714*1IKg+EmjAxpL>TQd(923@u zq6MiH+^onHeNH`pg=k53g9`JUDLsH3wN>*@GCPyBe_Ar2b;6FmzV$4$iLQy*inzh# zfzy-nulxm8q5FpigXz@J336m38R!qCM(lUzpgd9_Z>NqEP8=+OMF zg1O?FvPRs-!1u>-^{g=zpT)m()XQ-ZOW8MVZm-np^j%l&iuM;M(z2&nM5cnB;GmlD{xg zf4#Q2?Blmnu2kJAx{&xAT=DJwhgrBm}0)3~l?+gxc|%OIlxl7}QeyaB*H@k|>?%CKQWN{YjG{{UN>hb?p|AazhO z$C2KnK40**X|qlg{KReTfmI~A?Os=Fai7AXwoT|6 zxhIf%92&R2IAdpK2oPkG{D=EZMcdGsS!`lz_P=MB?Y6OpY?E;Ve9G#6`)#aeXt38d zqxWy}9o&FV{Iihp{{R4be~5LbyqRHxDGWzB92Rcv$No84(M@n=Y2aWb2QG*1zEAf* z)$XpkX~ip?)79y?OB75<8Ce(aA?^L|_o@es5xGV%cAs%t6I+}6Up~xl>87=Q6~cI*kKqtIeUAdyUecwmg2@mscxuNawnoU1RVA9k_i17;8( zlaFv}?v~E1#e-m|@TV7z7<1Q>JN^`t$hq9D%VQiI z;*b?ekO2d6&IUbd)*KFcQlqmRfwT^d^zT*VCnQOd59R*=eA5DdkYo~|^~P{%>dhjD zA29X*0PEB+!DtXVfLrOv{{X&ePQk!ak5BSxp%eM28C5a30#6yK(Ejgt+GMRS+ldIC78(TecH2i$b2rH(XZRdPlu@)7|#b4MCehwW@$z?jyWHl6t}U)CIfQx@7JmKqJYrRg90_{ zoC=P1ZLPOFbu}8!HicdQUcU6leZVhrarNz5H=&J*46d;#&Pg3TsyH;2ha{FJw`ElXYd}NfALLCDoX@EyF>SnQ;zhYmSB;L zvvdQkXxeEz$DMdYX^tZ&pZAL?`D;3rY18=O!6wT zDPb7p_#ZC-e-&BOb(?z_n%cnz{+?j~{{XF^$TW90QK^deZJ&ITmOM5By`X8T+-dtyx8>+NIs1hnt4V;1Y~C zZIFKxukhD2Wy>plpVZMmVN?E{RQsbNn2+qvkLD7xfEqR&f% zfsxeXzG|3oK2|^es)^%h+jPOw{RRW#Bx5~r6twU{a zOMKrk#{(c|*i(%A-<5Q1WCl~yrhnb6`7GI_WZuHNvwsoe*N`dj=W;W02R_vn_?h++ zx&HuYg$MPj^WDrgq;}q7hRHeFzwWbr{gqDL>{5*0(QnY&Ys+hR%+p8!UWh$?D+>Pr zR+jvE5Q7{lb0mk3zrut60B4}AlS*c~B1un0QMNS$?uAOHs9Y+m1%6WiNcdFtvTu7v@e}vV=-y}g>jDSmhX_6p0LC0^x ztxDQI=@BYQUi4M2ude*VV4isH1>{F-^krTHkAL>6<6GP6L9QSGO^itq>QB@A)m0Eg zqXhB%>B%h6+%439eSY>h+`j(+-({N2Be;SunRUmWG4arw|{!G;)d$dWtI@>lYSynEg zrG*iA0D;uyhtuR6suV`t7@#Az?mzoFE+SY~6+l!gGiM}mjC%B`P$L2`5TD`$9Qso& z!O2sDyPThDu?38>NEyC$&QxOvJqiBxCej41DrP)nU<2RQq?wDy(<_co{{XJEA-71* z;x|4pSn@yMBB8yJ;$;W|gUdDnIX`!;N3^@q8aP>8$#~el=XJ$eeDB3U&)bse!OjkuX=S77HKQS4{r7^Bu$yFOu*P;Ia zEm5IufOR`~{C#TOm6P2{u^|e1W@FF+_nE4klv9+QlGV0nZAJ+3$m%){wR#OA=6$T> zLWjBK&(VK|w4&2(EsCdLSUUghu zYSVP^vASAHtd@)XCW;Y?yx;x0O>nwyhitP+mXWwze9nLPm9A@1*Y0l#2t1g{;X%(H z^;-V=>h@DL!+h<~4#TpoS6Istxa|YKYU`tgj6LZ$Qmfuf&QreHAqi{%Gn3TPtZc`T z_|vu(d@%f~!Z->>0LaEoc19Q6mc)s+U;&W7=Zdi-?@(8j@9Gb|Rp@$P)PQG`*SD=` zw9uOp$DDsptyY@V*Djo{dUq8v@wtxyc_elEQi(IhbDqBRG@gtKGDsRVi_1kSNiu+U zHhVuiep-Ak*vKbv?by@qAm?!EbDY(7M@$k3KDCso@1@sL<0hJE*`rM)E~D4dv~-K- zw4ZiL#@tMxXK)_J_?EG(-JGZ=EKbl*e^2-oT^U!#2qU$5c$!|$R!iNMw>|tFWr(EV zJ2z`J`kI=ph?_c{nGFl^B9XN5#{U5JzuNvf%D^Cl$*pZGRa<}bTa0~`$t01Tr1$>- zX_7_WuB6f3sZaww<-HttR0=Wl>#!%ei-7%KreoW*FjQi2>W6 zyocr=?O^=1U8HDbXxxX7_)oXvR=_Ls93NxT{sl$EKWU6@z>t03)!T)|wA3m)r=oq1 zOnzS$omxuGYbdV1gbQld4yNA>#Na67ukh8F;aGyOJBZGB=~?R1+RL%?9Ef=x{Z_Rj zD=K+_=Ol*u{{Z$?(TIcPa*NZk=iuBurKYv%e&eH7e_lHpke(DN+E*uo(9|)K7>wsU zW2H=xJ1NIc*1Y#7w7rq*s4t4wZ|)vt0obApw^C|Q>`=2FovAH!`|0E^XDM#$P3Ua1J@C5QRbj?io%TjC{=-e;568t5Lk9`I0G)V~0HQ5BoKRxb6fVLC9|T ztxJ2hm>uUbFW&d}tz~;?am6Psb}UI7Kg_=?_B80>ot;KLVtV8CJ9kv}w$okAvBWUP zmTY7y{{VXx)Y@3uTB7g^r~t@uxPkrbRxWL9YSK>Dzmb6+i+)%U7nXSka}0muzcoJV zO1MjKBtXcFNh_20zY6IX#kV7;tu{F@#3{k;nqJwWc@9OF5+>F=7lNeZ6aN6%)Pgf6 z?U+;t?;d~en$y&D{n5=d3A*DSBz=iJbAl_Hhfvj{BQF?S;|!~}k74sx(VA-LhZlPr za9c#Ba7#0hxsQKtD_$hv4uiFF*80@YN*?Y2(XafqgXSOi!TuWPY&8pO*tfvh^#iE- zii(%{7aJ$$US$fo;<=4N=0};N4Y>g+jQ;@WHM^+EB3o@k^DrZKzAK+=ap- ze7rFpqMsvzxl*b)$W;R$l{XAd22MHSANw^rb;lS&Hsc=k8WpM{jzRPztxg;s zwE~52YLG@3l_%-V1G_8UOK>FvJBB_}?al{I)KXn%%pCUqriyxnmtp#4qRi2+t^xJ; zYUynBm@Pq*c4T3UoMBh}-@8rI?4Yz&3CrUp+Z%%a0JPuT{^HhNzv2yt?6xed{O^9D zPfz>qyy;Y{jGL!TT9=>N{`9=NM0~0iZ{jNWk5`&0#heX=RR&M@k45MGpPsqmcV*8w z?V2!MnWSROa!V7EPy0mBj|w5ohjwx!1DyW=v`u={sVY?CO>1Rq?Q@;Gw)=>7@XIgn zOLPiw20rr0e~OF}aL0RO9mmt@KzW-5`i>VqpYGzGo0wpnp4@c*0Cu#5de|EyWAhyF zd(@GPammMTN=Xzh2YN`-MkE_R_1qaCVXj7$hE}(A0TlIR}p4 zTF$i}#+}%~IFB;b1FdO4;Bty}Z_N&&jyb>&_jmUBX zat~%!{{UsGmHnW#xWebjkO?6tx}J;w003{2y$m&8Xt+Jr-e~f3EIOxARD!f++oX zQj(0C-r8Tkp`58&Oe61sZBT{kK^R6^XX1kHw4U7Zz71M)*bM}u&#Xp%6f^q)<6s(CALLeLr^NL^c zDILZMIO`JP$!uE~gSm z@u~gZ;z;aIZ~Nw|$Ws^#&#iSvHdZ{!wK?S2u`9^o6cSGW0g_F1R$dRgHp1x0Jp67* zF~J0V(%D^&Ry-r2Lj-Gobh(|mhdc!b`2PUjuCZ7*Lz>EUb+QP{gDmnupjJqgLI3+D?ffG`gr4{F-J>WGA% zn5+xNGDykUPE^)(wQI=^T1V80908H|gI6uWOiKmWz;@~VYdCem;EL0++LrGj1zhxD z-_!k?*^wQ_DUn+rbdEETPm)k$+ryrm@&0zy0OX!|@4MEeh${`Gayoia*rcv8BXBZu z2c|PpZz{hpQ%+wkSZ-7Q00A6>{{W8C$Q9)q6op>x!Tx4}*r{}xkZ05SnkjC$eQfC+>V;MRB02+P8#f7vwfs-pw9R_XA~=NTrsu~q$=cGdJdFj!x0E6d26 HQML@~z_X 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 diff --git a/ThirdParty/Ert/share/gui/img/undo.png b/ThirdParty/Ert/share/gui/img/undo.png deleted file mode 100644 index 0c196ec096e723d2074006e40215e54a4046817d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1307 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%uvD1M9IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr4|esh*)icxGNo zet9uiy|1s8XI^nhVqS8pr;Du;&;-5A%oHn2V^ecO3kx$t14lzcLsw%*0~d2Q0~b>Z zXA3uDGe=99UYGpj(%jU%5}4i;gkE!;dO=Acw*Y9fOKMSOS!#+~QGTuh*vnR#xZPrc z(>$o&6x?nx#i>^x=oo!a#3DsBObD2IKumbD1#;jCKQ#}S+KYh6dgn2wNCpPReoq(2 zkcwMxf_*hy0!99vtIanu{^a9)%Kzqx2m?)N?MXb+sfQyXPH;&_Mrc^8Zu8nEW~R(- zZ6DaRY0|`-6aGB0?=igG^Wom^b6@vQn9|xC9RIxJT={;#`+KJ^nexMzAzInp-`{#zZ4i^^R01xF?53F3**WOLrrutMR{c?fjt?WOn8YjOW zn7M54{IDkxpBQKV4nMf{ZTEuAsK-q%+h@I6mb!T5sq5Q>ES=L2v~Rv$y+%%@plE8t zp8d^Fb_NBctbgc~9cno3kbCTN^OHIEmbh-uk>*XU{P48OKzQe|!asuL7qe}SJU)5k z<++SE2Af<}TBdB98yWG6|NYc2Pb%){P0L9;TNS%@hji_cCvGBqzRfdtxV(B)QJK1A z>vVVZo+s+(#Uz8T{#}^3{2_0F?Q(8MgG;d|zNKkR7Wk5$s8b@x&7<4$^6bif4@14@ zzh7Hrvn^AX$y+=ri#`4EHW#+Nk^kOoW8l7Ae*L(T>l`DIm2(!>9*q2d(t5%F{SE4j aYz*y^(l0X9KYi)B`pkZS64i$=K zYreF6+52|y?!BFRbv8ph++ndIkJn&wHiVa-16YWpdi&cPCuJKWPu{Ec z+KSSG@P%VlXrYcRC-x#OimNw}fe(lL_??t+#$E|aiJ{5X>AAZKpyOR&A!_t}4Wi3E zhPOW!0qLIvh7v-d7+y~-qI-B64g1Ss(5lbZyF5D-0Hw9pR+x~23OX$dbD>^2lo{Wj z-EU0JO!hF*2%?;Tfr$|6s>&dw#hc4F5XCEbMm^@DJXkJ?9^c0?CM&R0gHPQ9w@$al zgZ>`EarhbLq1EYV1WD5}fDmnnBgkPj^y(r;?lqsH=TljUkk|hAkFPmJE`=Pe24R5# zp*j_S{I8{?fV^A{_(T%nz}SaZuBJoTsdRMpsbWF@R4N`v9tAAXfRaoQ<;9;QP@Jzt zSxG+4yGO;vLZjILn(nZz!<}Q^QlR)ncmi4FiUfHfBEkV%3yly2@dno90iZRa+g4-< zSxYxzJ^}DNPodxx03TcOCSx%WMh$DZ2?d7SOSbFo+jf`NngP&4L!)gEYc`vp(WsG# zMiHO?^+*8(MxJ-hPtSs7Rq#iFqjlA&t~58(L*rQ*@F^(39|KJ`5S*FC(4DjG3SivV zJ)Bsa>z(}a4Y9O@K!U;UT~=B5nqmU0MT*hDT%?D^v^h+-r%6^bZLe#6@<3l$Twi9{ zi7lpLyy+jri?+jx(eCm{vJ6RX7V6J1j0{ba|GLpqapc@VQ;q#1n`<~A@Ao+!8RNcn s8dW0ev@ 0.0: - well["opr"] = opr_value - well["opt"] += opr_value - self._fopr += opr_value - - if self._fgip > 0.0: - well["gpr"] = gpr_value - well["gpt"] += gpr_value - self._fgpr += gpr_value - - if self._fwip > 0.0: - well["wpr"] = wpr_value - well["wpt"] += wpr_value - self._fwpr += wpr_value - - self._fgor += self.gor(key) - self._fwct += self.wct(key) - - self._foip -= self._fopr - self._fgip -= self._fgpr - self._fwip -= self._fwpr - - if self._foip < 0.0: - self._foip = 0.0 # This may lead to the total (FOPT) larger than OOIP - - if self._fgip < 0.0: - self._fgip = 0.0 - - if self._fwip < 0.0: - self._fwip = 0.0 - - self._fopt += self._fopr - self._fgpt += self._fgpr - self._fwpt += self._fwpr - - self._fgor /= len(self._wells) - self._fwct /= len(self._wells) - - for key in self._bpr: - bprFunction = self._bprFunc[key] - self._bpr[key] = bprFunction(self._current_step, scale) - - self._current_step += 1 - - def fopt(self): - return self._fopt - - def fopr(self): - return self._fopr - - def fgpt(self): - return self._fgpt - - def fgpr(self): - return self._fgpr - - def fwpt(self): - return self._fwpt - - def fwpr(self): - return self._fwpr - - def fgor(self): - return self._fgor - - def fwct(self): - return self._fwct - - def foip(self): - return self._foip - - def fgip(self): - return self._fgip - - def fwip(self): - return self._fwip - - def opr(self, well_name): - return self._wells[well_name]["opr"] - - def gpr(self, well_name): - return self._wells[well_name]["gpr"] - - def wpr(self, well_name): - return self._wells[well_name]["wpr"] - - def wct(self, well_name): - opr = self.opr(well_name) - wpr = self.wpr(well_name) - opr = max(opr, 0.1) - return wpr / (wpr + opr) if (wpr + opr) > 0.0 else 0.0 - - def gor(self, well_name): - opr = self.opr(well_name) - gpr = self.gpr(well_name) - opr = max(opr, 0.1) - gpr = max(gpr, 0.1) - return gpr / opr - - def bpr(self, block_name): - return self._bpr[block_name] diff --git a/ThirdParty/Ert/share/lib/synthesizer/perlin.py b/ThirdParty/Ert/share/lib/synthesizer/perlin.py deleted file mode 100644 index b3da8ae7e1..0000000000 --- a/ThirdParty/Ert/share/lib/synthesizer/perlin.py +++ /dev/null @@ -1,57 +0,0 @@ -import math - -from .prime_generator import PrimeGenerator - - -class PerlinNoise(object): - def __init__(self, persistence=0.5, number_of_octaves=4, prime_generator=None): - self.persistence = persistence - self.number_of_octaves = number_of_octaves - - self.octave_primes = prime_generator if prime_generator is not None else PrimeGenerator() - - def cosineInterpolation(self, a, b, x): - ft = x * 3.1415927 - f = (1.0 - math.cos(ft)) * 0.5 - return a * (1 - f) + b * f - - MAX_INT = (1 << 31) - 1 - - def noise(self, x, perturbation): - x += perturbation - x = ((x << 13) & PerlinNoise.MAX_INT) ^ x - x = (x * (x * x * 15731 + 789221) + 1376312589) & PerlinNoise.MAX_INT - return 1.0 - x / 1073741824.0 - - def smoothedNoise(self, x, perturbation): - return self.noise(x, perturbation) / 2.0 + self.noise(x - 1, perturbation) / 4.0 + self.noise(x + 1, perturbation) / 4.0 - - def interpolatedNoise(self, x, octave_number): - int_x = int(x) - frac_x = x - int_x - - perturbation = self.octave_primes[octave_number] - - v1 = self.smoothedNoise(int_x, perturbation) - v2 = self.smoothedNoise(int_x + 1, perturbation) - - return self.cosineInterpolation(v1, v2, frac_x) - - def perlinNoise1D(self, x): - total = 0.0 - - for octave in range(self.number_of_octaves - 1): - frequency = math.pow(2, octave) - amplitude = math.pow(self.persistence, octave) - - total += self.interpolatedNoise(x * frequency, octave_number=octave) * amplitude - - return total - - def __getitem__(self, x): - """ :rtype: float """ - return self.perlinNoise1D(x * 10.0) - - def __call__(self, x): - """ :rtype: float """ - return self[x] diff --git a/ThirdParty/Ert/share/lib/synthesizer/prime_generator.py b/ThirdParty/Ert/share/lib/synthesizer/prime_generator.py deleted file mode 100644 index d7c35107b4..0000000000 --- a/ThirdParty/Ert/share/lib/synthesizer/prime_generator.py +++ /dev/null @@ -1,40 +0,0 @@ -import random - -def rwh_primes2(n): - # http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188 - """ Input n>=6, Returns a list of primes, 2 <= p < n """ - correction = (n % 6 > 1) - n = {0: n, 1: n - 1, 2: n + 4, 3: n + 3, 4: n + 2, 5: n + 1}[n % 6] - sieve = [True] * (n / 3) - sieve[0] = False - for i in xrange(int(n ** 0.5) / 3 + 1): - if sieve[i]: - k = 3 * i + 1 | 1 - sieve[((k * k) / 3)::2 * k] = [False] * ((n / 6 - (k * k) / 6 - 1) / k + 1) - sieve[(k * k + 4 * k - 2 * k * (i & 1)) / 3::2 * k] = [False] * ( - (n / 6 - (k * k + 4 * k - 2 * k * (i & 1)) / 6 - 1) / k + 1) - return [2, 3] + [3 * i + 1 | 1 for i in xrange(1, n / 3 - correction) if sieve[i]] - - - -class PrimeGenerator(object): - LIST_OF_PRIMES = rwh_primes2(10000) - - def __init__(self, seed=None): - self.__primes = {} - self.__random = random.Random(seed) - random.seed(seed) - - def __getitem__(self, index): - if not isinstance(index, (int, long)) or index < 0: - raise IndexError("Index must be a positive integer: %d" % index) - - if not index in self.__primes: - p1 = self.randomPrime() - self.__primes[index] = p1 - - return self.__primes[index] - - def randomPrime(self): - random_index = self.__random.randint(0, len(PrimeGenerator.LIST_OF_PRIMES) - 1) - return PrimeGenerator.LIST_OF_PRIMES[random_index] diff --git a/ThirdParty/Ert/share/lib/synthesizer/shaped_perlin.py b/ThirdParty/Ert/share/lib/synthesizer/shaped_perlin.py deleted file mode 100644 index 65b63a1f02..0000000000 --- a/ThirdParty/Ert/share/lib/synthesizer/shaped_perlin.py +++ /dev/null @@ -1,106 +0,0 @@ -import math -from . import PrimeGenerator, PerlinNoise - - -class Interpolator(object): - def __init__(self, x, y): - self.x = x - self.y = y - - assert len(x) == len(y) - - def __call__(self, x): - if x <= self.x[0]: - y = self.y[0] - elif x >= self.x[len(self.x) - 1]: - y = self.y[len(self.x) - 1] - else: - y = None - for i in range(len(self.x) - 1): - if self.x[i] <= x < self.x[i + 1]: - x_diff = self.x[i + 1] - self.x[i] - frac_x = (x - self.x[i]) / x_diff - y = self.cosineInterpolation(self.y[i], self.y[i + 1], frac_x) - break - - return y - - def cosineInterpolation(self, a, b, x): - ft = x * 3.1415927 - f = (1.0 - math.cos(ft)) * 0.5 - return a * (1 - f) + b * f - - -class ShapeFunction(object): - def __init__(self, x, y, scale=1.0): - self.scale = scale - self.interpolator = Interpolator(x, y) - - def __call__(self, x): - return self.interpolator(x) * self.scale - - def scaledCopy(self, scale=1.0): - return ShapeFunction(self.interpolator.x, self.interpolator.y, scale) - - -class ConstantShapeFunction(ShapeFunction): - def __init__(self, value): - super(ConstantShapeFunction, self).__init__([0.0], [value]) - - - -class ShapedNoise(object): - - def __init__(self, noiseFunction, shapeFunction, divergenceFunction, offset=0.0, cutoff=None): - self.shapeFunction = shapeFunction - self.divergenceFunction = divergenceFunction - self.noiseFunction = noiseFunction - self.offset = offset - self.cutoff = cutoff - - def __call__(self, x, scale=1.0): - scaled_x = x * scale - result = self.shapeFunction(scaled_x) + self.noiseFunction(scaled_x) * self.divergenceFunction(scaled_x) - result += self.offset - if self.cutoff is not None: - result = max(result, self.cutoff) - return result - - -class ShapeCreator(object): - - @staticmethod - def createShapeFunction(count=1000, persistence=0.2, octaves=8, seed=1): - """ @rtype: ShapeFunction """ - prime_generator = PrimeGenerator(seed=seed) - perlininator = PerlinNoise(persistence=persistence, number_of_octaves=octaves, prime_generator=prime_generator) - - x_values = [x / float(count) for x in range(count)] - y_values = [perlininator(x) for x in x_values] - - return ShapeFunction(x_values, y_values) - - @staticmethod - def createShapedPerlinFunction(divergence_x, divergence_y, shape_seed=None, perlin_seed=None, count=1000, persistence=0.2, octaves=8, offset=0.0, cutoff=None): - """ @rtype: ShapedNoise """ - shapeFunction = ShapeCreator.createShapeFunction(count, persistence, octaves, shape_seed) - divergenceFunction = ShapeFunction(divergence_x, divergence_y) - prime_generator = PrimeGenerator(perlin_seed) - perlin_noise = PerlinNoise(persistence, octaves, prime_generator) - - return ShapedNoise(perlin_noise, shapeFunction, divergenceFunction, offset=offset, cutoff=cutoff) - - @staticmethod - def createNoiseFunction(shapeFunction=None, divergenceFunction=None, seed=None, persistence=0.2, octaves=8, offset=0.0, cutoff=None): - """ @rtype: ShapedNoise """ - if shapeFunction is None: - shapeFunction = ConstantShapeFunction(0.0) - - if divergenceFunction is None: - divergenceFunction = ConstantShapeFunction(1.0) - - prime_generator = PrimeGenerator(seed) - perlin_noise = PerlinNoise(persistence, octaves, prime_generator) - - noise = ShapedNoise(perlin_noise, shapeFunction, divergenceFunction, offset=offset, cutoff=cutoff) - return noise diff --git a/ThirdParty/Ert/share/site-config b/ThirdParty/Ert/share/site-config deleted file mode 100644 index c751e4e9ba..0000000000 --- a/ThirdParty/Ert/share/site-config +++ /dev/null @@ -1,7 +0,0 @@ --- This is a very basic site config file, mainly used for testing. - -WORKFLOW_JOB_DIRECTORY workflows/jobs/internal/config -WORKFLOW_JOB_DIRECTORY workflows/jobs/internal-gui/config -JOB_SCRIPT bin/job_dispatch.py -QUEUE_OPTION LOCAL MAX_RUNNING 1 - diff --git a/ThirdParty/Ert/share/viewer/shaders/default.fp b/ThirdParty/Ert/share/viewer/shaders/default.fp deleted file mode 100644 index bd6ba38d8e..0000000000 --- a/ThirdParty/Ert/share/viewer/shaders/default.fp +++ /dev/null @@ -1,4 +0,0 @@ -void main() { - gl_FragColor.rgb = gl_TexCoord[0].zyx; - gl_FragColor.a = 1.0; -} \ No newline at end of file diff --git a/ThirdParty/Ert/share/viewer/shaders/default.vp b/ThirdParty/Ert/share/viewer/shaders/default.vp deleted file mode 100644 index 9ead80e635..0000000000 --- a/ThirdParty/Ert/share/viewer/shaders/default.vp +++ /dev/null @@ -1,33 +0,0 @@ -#version 120 -uniform sampler3D grid; -uniform ivec3 grid_size; - -vec4 DELTA = vec4(1.0 / grid_size.x, 1.0 / grid_size.y, 1.0 / grid_size.z, 0.0); - -varying vec3 normal; - -vec4 fetchTexel(sampler3D sampler, vec3 p, vec3 offset) { - return texture3D(sampler, p + offset); -} - -void main() { - gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - - vec3 xyz = texture3D(grid, gl_TexCoord[0].xyz).rgb; - vec4 p = vec4(gl_Vertex); - p.xyz = xyz; - //p.z = 1800.0; - - float s01 = fetchTexel(grid, gl_TexCoord[0].xyz, DELTA.xww).z; - float s21 = fetchTexel(grid, gl_TexCoord[0].xyz, -DELTA.xww).z; - float s10 = fetchTexel(grid, gl_TexCoord[0].xyz, DELTA.wyw).z; - float s12 = fetchTexel(grid, gl_TexCoord[0].xyz, -DELTA.wyw).z; - - vec3 va = normalize(vec3(2.0, 0.0, s21 - s01)); - vec3 vb = normalize(vec3(0.0, 2.0, s12 - s10)); - normal = normalize(cross(va, vb)); - - //normal = (gl_ModelViewMatrix * vec4(normal, 0.0)).xyz; - - gl_Position = gl_ModelViewProjectionMatrix * p; -} \ No newline at end of file diff --git a/ThirdParty/Ert/share/viewer/shaders/texturing.fp b/ThirdParty/Ert/share/viewer/shaders/texturing.fp deleted file mode 100644 index 298cff2c63..0000000000 --- a/ThirdParty/Ert/share/viewer/shaders/texturing.fp +++ /dev/null @@ -1,49 +0,0 @@ -#version 120 -uniform sampler3D grid; -uniform sampler3D grid_data; -uniform sampler1D color_scale; - -uniform bool hide_inactive_cells; -uniform bool lighting; -uniform bool region_scaling; -uniform float data_range; - -// From python code: self.__shader.setUniformi("grid_size", texture.getWidth(), texture.getHeight(), texture.getDepth()) - - -varying vec3 normal; - - -void main() { - vec4 cell = texture3D(grid, gl_TexCoord[0].xyz); - - if(hide_inactive_cells && cell.w < 0.5) { - discard; - } - - float color_pos = texture3D(grid_data, gl_TexCoord[0].xyz).a; - - if (color_pos < 0.001) { - discard; - } - - if(region_scaling) { - // data_range + 1 because [0-9] count = 10 - color_pos = color_pos * (data_range + 1) / 16.0; - } - - vec3 color = texture1D(color_scale, color_pos).rgb; - - //color = gl_TexCoord[0].yxz; - - if(lighting) { - float d = dot(normalize(normal), normalize(vec3(0.0, 0.0, 0.5))); - //d = clamp(d, 0.0, 1.0); - color = color + ((0.5 * color * d) - 0.25); - } - - - - gl_FragColor.rgb = color; - gl_FragColor.a = 1.0; -} diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/CREATE_CASE b/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/CREATE_CASE deleted file mode 100644 index 6875fee2d0..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/CREATE_CASE +++ /dev/null @@ -1,6 +0,0 @@ -INTERNAL True -SCRIPT ../scripts/create_case.py -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 STRING - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/CSV_EXPORT b/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/CSV_EXPORT deleted file mode 100644 index abef52b476..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/CSV_EXPORT +++ /dev/null @@ -1,9 +0,0 @@ -INTERNAL True -SCRIPT ../scripts/csv_export.py -MIN_ARG 1 -MAX_ARG 4 -ARG_TYPE 0 STRING -ARG_TYPE 1 STRING -ARG_TYPE 2 STRING -ARG_TYPE 3 BOOL - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/EXPORT_MISFIT_DATA b/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/EXPORT_MISFIT_DATA deleted file mode 100644 index c4aac369aa..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/EXPORT_MISFIT_DATA +++ /dev/null @@ -1,6 +0,0 @@ -INTERNAL True -SCRIPT ../scripts/export_misfit_data.py -MIN_ARG 0 -MAX_ARG 1 -ARG_TYPE 0 STRING - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/GEN_DATA_RFT_CSV_EXPORT b/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/GEN_DATA_RFT_CSV_EXPORT deleted file mode 100644 index e6ca1dcc58..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/GEN_DATA_RFT_CSV_EXPORT +++ /dev/null @@ -1,8 +0,0 @@ -INTERNAL True -SCRIPT ../scripts/gen_data_rft_export.py -MIN_ARG 2 -MAX_ARG 4 -ARG_TYPE 0 STRING -ARG_TYPE 1 STRING -ARG_TYPE 2 STRING -ARG_TYPE 3 BOOL diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/INIT_CASE_FROM_EXISTING b/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/INIT_CASE_FROM_EXISTING deleted file mode 100644 index 4c37a13fca..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/INIT_CASE_FROM_EXISTING +++ /dev/null @@ -1,7 +0,0 @@ -INTERNAL True -SCRIPT ../scripts/init_case_from_existing.py -MIN_ARG 1 -MAX_ARG 2 -ARG_TYPE 0 STRING -ARG_TYPE 1 STRING - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/SELECT_CASE b/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/SELECT_CASE deleted file mode 100644 index bdd49d8888..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/SELECT_CASE +++ /dev/null @@ -1,6 +0,0 @@ -INTERNAL True -SCRIPT ../scripts/select_case.py -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 STRING - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/UPDATE_RUNPATH_LIST b/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/UPDATE_RUNPATH_LIST deleted file mode 100644 index dbaa256d05..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/config/UPDATE_RUNPATH_LIST +++ /dev/null @@ -1,6 +0,0 @@ -INTERNAL True -SCRIPT ../scripts/update_runpath_list.py -MIN_ARG 0 -MAX_ARG 1 -ARG_TYPE 0 STRING - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/create_case.py b/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/create_case.py deleted file mode 100644 index 74c6380f1b..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/create_case.py +++ /dev/null @@ -1,7 +0,0 @@ -from ert.enkf import ErtScript - -class CreateCaseJob(ErtScript): - - def run(self, case_name): - ert = self.ert() - fs = ert.getEnkfFsManager().getFileSystem(case_name) diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/csv_export.py b/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/csv_export.py deleted file mode 100644 index 4c0a93b08b..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/csv_export.py +++ /dev/null @@ -1,189 +0,0 @@ -import os -import re - -import pandas -from PyQt4.QtGui import QCheckBox - -from ert.enkf import ErtPlugin, CancelPluginException -from ert.enkf.export import SummaryCollector, GenKwCollector, MisfitCollector, DesignMatrixReader, CustomKWCollector -from ert_gui.ertwidgets.customdialog import CustomDialog -from ert_gui.ertwidgets.listeditbox import ListEditBox -from ert_gui.ertwidgets.models.path_model import PathModel -from ert_gui.ertwidgets.pathchooser import PathChooser - - -class CSVExportJob(ErtPlugin): - """ - Export of summary, custom_kw, misfit, design matrix data and gen kw into a single CSV file. - - The script expects a single argument: - - output_file: this is the path to the file to output the CSV data to - - Optional arguments: - - case_list: a comma separated list of cases to export (no spaces allowed) - if no list is provided the current case is exported - a single * can be used to export all cases - - design_matrix: a path to a file containing the design matrix - - infer_iteration: If True the script will try to infer the iteration number by looking at the suffix of the case name - (i.e. default_2 = iteration 2) - If False the script will use the ordering of the case list: the first item will be iteration 0, - the second item will be iteration 1... - - The script also looks for default values for output path and design matrix path to present in the GUI. These can - be specified with DATA_KW keyword in the config file: - DATA_KW CSV_OUTPUT_PATH - DATA_KW DESIGN_MATRIX_PATH - """ - - INFER_HELP = ("" - "If this is checked the iteration number will be inferred from the name i.e.:" - "

    " - "
  • case_name -> iteration: 0
  • " - "
  • case_name_0 -> iteration: 0
  • " - "
  • case_name_2 -> iteration: 2
  • " - "
  • case_0, case_2, case_5 -> iterations: 0, 2, 5
  • " - "
" - "Leave this unchecked to set iteration number to the order of the listed cases:" - "
  • case_0, case_2, case_5 -> iterations: 0, 1, 2
" - "
" - "") - - def getName(self): - return "CSV Export" - - def getDescription(self): - return "Export GenKW, CustomKW, design matrix, misfit data and summary data into a single CSV file." - - def inferIterationNumber(self, case_name): - pattern = re.compile("_([0-9]+$)") - match = pattern.search(case_name) - - if match is not None: - return int(match.group(1)) - return 0 - - - def run(self, output_file, case_list=None, design_matrix_path=None, infer_iteration=True): - cases = [] - - if case_list is not None: - if case_list.strip() == "*": - cases = self.getAllCaseList() - else: - cases = case_list.split(",") - - if case_list is None or len(cases) == 0: - cases = [self.ert().getEnkfFsManager().getCurrentFileSystem().getCaseName()] - - if design_matrix_path is not None: - if not os.path.exists(design_matrix_path): - raise UserWarning("The design matrix file does not exists!") - - if not os.path.isfile(design_matrix_path): - raise UserWarning("The design matrix is not a file!") - - data = pandas.DataFrame() - - for index, case in enumerate(cases): - case = case.strip() - - if not self.ert().getEnkfFsManager().caseExists(case): - raise UserWarning("The case '%s' does not exist!" % case) - - if not self.ert().getEnkfFsManager().caseHasData(case): - raise UserWarning("The case '%s' does not have any data!" % case) - - if infer_iteration: - iteration_number = self.inferIterationNumber(case) - else: - iteration_number = index - - case_data = GenKwCollector.loadAllGenKwData(self.ert(), case) - - custom_kw_data = CustomKWCollector.loadAllCustomKWData(self.ert(), case) - if not custom_kw_data.empty: - case_data = case_data.join(custom_kw_data, how='outer') - - if design_matrix_path is not None: - design_matrix_data = DesignMatrixReader.loadDesignMatrix(design_matrix_path) - if not design_matrix_data.empty: - case_data = case_data.join(design_matrix_data, how='outer') - - misfit_data = MisfitCollector.loadAllMisfitData(self.ert(), case) - if not misfit_data.empty: - case_data = case_data.join(misfit_data, how='outer') - - summary_data = SummaryCollector.loadAllSummaryData(self.ert(), case) - if not summary_data.empty: - case_data = case_data.join(summary_data, how='outer') - else: - case_data["Date"] = None - case_data.set_index(["Date"], append=True, inplace=True) - - case_data["Iteration"] = iteration_number - case_data["Case"] = case - case_data.set_index(["Case", "Iteration"], append=True, inplace=True) - - data = pandas.concat([data, case_data]) - - data = data.reorder_levels(["Realization", "Iteration", "Date", "Case"]) - data.to_csv(output_file) - - export_info = "Exported %d rows and %d columns to %s." % (len(data.index), len(data.columns), output_file) - return export_info - - - def getArguments(self, parent=None): - description = "The CSV export requires some information before it starts:" - dialog = CustomDialog("CSV Export", description, parent) - - default_csv_output_path = self.getDataKWValue("CSV_OUTPUT_PATH", default="output.csv") - output_path_model = PathModel(default_csv_output_path) - output_path_chooser = PathChooser(output_path_model) - - design_matrix_default = self.getDataKWValue("DESIGN_MATRIX_PATH", default="") - design_matrix_path_model = PathModel(design_matrix_default, is_required=False, must_exist=True) - design_matrix_path_chooser = PathChooser(design_matrix_path_model) - - list_edit = ListEditBox(self.getAllCaseList()) - - infer_iteration_check = QCheckBox() - infer_iteration_check.setChecked(True) - infer_iteration_check.setToolTip(CSVExportJob.INFER_HELP) - - dialog.addLabeledOption("Output file path", output_path_chooser) - dialog.addLabeledOption("Design Matrix path", design_matrix_path_chooser) - dialog.addLabeledOption("List of cases to export", list_edit) - dialog.addLabeledOption("Infer iteration number", infer_iteration_check) - - dialog.addButtons() - - success = dialog.showAndTell() - - if success: - design_matrix_path = design_matrix_path_model.getPath() - if design_matrix_path.strip() == "": - design_matrix_path = None - - case_list = ",".join(list_edit.getItems()) - - return [output_path_model.getPath(), case_list, design_matrix_path, infer_iteration_check.isChecked()] - - raise CancelPluginException("User cancelled!") - - - def getDataKWValue(self, name, default): - data_kw = self.ert().getDataKW() - if name in data_kw: - return data_kw[data_kw.indexForKey(name)][1] - return default - - def getAllCaseList(self): - fs_manager = self.ert().getEnkfFsManager() - all_case_list = fs_manager.getCaseList() - all_case_list = [case for case in all_case_list if fs_manager.caseHasData(case)] - return all_case_list \ No newline at end of file diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/export_misfit_data.py b/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/export_misfit_data.py deleted file mode 100644 index 0cda52f916..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/export_misfit_data.py +++ /dev/null @@ -1,78 +0,0 @@ -from collections import OrderedDict -import os -from ert.enkf import ErtScript, RealizationStateEnum -from ert.util import BoolVector - -""" -This job exports misfit data into a chosen file or to the default gen_kw export file (parameters.txt) -""" - -class ExportMisfitDataJob(ErtScript): - - def run(self, target_file=None): - ert = self.ert() - fs = ert.getEnkfFsManager().getCurrentFileSystem() - - if target_file is None: - target_file = ert.getModelConfig().getGenKWExportFile() - - runpath_list = ert.getHookManager().getRunpathList() - - active_list = self.createActiveList(fs) - - for runpath_node in runpath_list: - if runpath_node.realization in active_list: - - if not os.path.exists(runpath_node.runpath): - os.makedirs(runpath_node.runpath) - - target_path = os.path.join(runpath_node.runpath, target_file) - - parameters = self.parseTargetFile(target_path) - - misfit_sum = 0.0 - for obs_vector in ert.getObservations(): - misfit = obs_vector.getTotalChi2(fs, runpath_node.realization ) - - key = "MISFIT:%s" % obs_vector.getObservationKey() - parameters[key] = misfit - - misfit_sum += misfit - - parameters["MISFIT:TOTAL"] = misfit_sum - - self.dumpParametersToTargetFile(parameters, target_path) - - - - def parseTargetFile(self, target_path): - parameters = OrderedDict() - - if os.path.exists(target_path) and os.path.isfile(target_path): - with open(target_path, "r") as input_file: - lines = input_file.readlines() - - for line in lines: - tokens = line.split() - - if len(tokens) == 2: - parameters[tokens[0]] = tokens[1] - else: - raise UserWarning("The file '%s' contains errors. Expected format for each line: KEY VALUE" % target_path) - - return parameters - - - def dumpParametersToTargetFile(self, parameters, target_path): - with open(target_path, "w") as output: - for key in parameters: - output.write("%s %s\n" % (key, parameters[key])) - - - def createActiveList(self, fs): - state_map = fs.getStateMap() - ens_mask = BoolVector(False, self.ert().getEnsembleSize()) - state_map.selectMatching(ens_mask, RealizationStateEnum.STATE_HAS_DATA) - active_list = BoolVector.createActiveList(ens_mask) - - return active_list diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py b/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py deleted file mode 100644 index 0cac7e970f..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py +++ /dev/null @@ -1,199 +0,0 @@ -import os -import re - -import numpy -import pandas -from PyQt4.QtGui import QCheckBox - -from ert.ecl.rft import WellTrajectory -from ert.enkf import ErtPlugin, CancelPluginException -from ert.enkf import RealizationStateEnum -from ert.enkf.enums import EnkfObservationImplementationType -from ert.enkf.export import GenDataCollector, ArgLoader -from ert_gui.ertwidgets.customdialog import CustomDialog -from ert_gui.ertwidgets.listeditbox import ListEditBox -from ert_gui.ertwidgets.models.path_model import PathModel -from ert_gui.ertwidgets.pathchooser import PathChooser - - -class GenDataRFTCSVExportJob(ErtPlugin): - """Export of GEN_DATA based rfts to a CSV file. The csv file will in - addition contain the depth as duplicated seperate row. - - The script expects four arguments: - - output_file: this is the path to the file to output the CSV data to - - key: this is the ert GEN_DATA key used for this particular RFT. - - report_step: This is the report step configured in the ert - configuration file for this RFT. - - trajectory_file: This is the the file containing the - - Optional arguments: - - case_list: a comma separated list of cases to export (no spaces allowed) - if no list is provided the current case is exported - - infer_iteration: If True the script will try to infer the iteration number by looking at the suffix of the case name - (i.e. default_2 = iteration 2) - If False the script will use the ordering of the case list: the first item will be iteration 0, - the second item will be iteration 1... - """ - - INFER_HELP = ("" - "If this is checked the iteration number will be inferred from the name i.e.:" - "
    " - "
  • case_name -> iteration: 0
  • " - "
  • case_name_0 -> iteration: 0
  • " - "
  • case_name_2 -> iteration: 2
  • " - "
  • case_0, case_2, case_5 -> iterations: 0, 2, 5
  • " - "
" - "Leave this unchecked to set iteration number to the order of the listed cases:" - "
  • case_0, case_2, case_5 -> iterations: 0, 1, 2
" - "
" - "") - - def getName(self): - return "GEN_DATA RFT CSV Export" - - def getDescription(self): - return "Export gen_data RFT results into a single CSV file." - - def inferIterationNumber(self, case_name): - pattern = re.compile("_([0-9]+$)") - match = pattern.search(case_name) - - if match is not None: - return int(match.group(1)) - return 0 - - def run(self, output_file, trajectory_path, case_list=None, infer_iteration=True): - """The run method will export the RFT's for all wells and all cases. - - The successfull operation of this method hinges on two naming - conventions: - - 1. All the GEN_DATA RFT observations have key RFT_$WELL - 2. The trajectory files are in $trajectory_path/$WELL.txt or $trajectory_path/$WELL_R.txt - - """ - - wells = set() - obs_pattern = "RFT_*" - enkf_obs = self.ert().getObservations() - obs_keys = enkf_obs.getMatchingKeys(obs_pattern, obs_type=EnkfObservationImplementationType.GEN_OBS) - - cases = [] - if case_list is not None: - cases = case_list.split(",") - - if case_list is None or len(cases) == 0: - cases = [self.ert().getEnkfFsManager().getCurrentFileSystem().getCaseName()] - - data_frame = pandas.DataFrame() - for index, case in enumerate(cases): - case = case.strip() - case_frame = pandas.DataFrame() - - if not self.ert().getEnkfFsManager().caseExists(case): - raise UserWarning("The case '%s' does not exist!" % case) - - if not self.ert().getEnkfFsManager().caseHasData(case): - raise UserWarning("The case '%s' does not have any data!" % case) - - if infer_iteration: - iteration_number = self.inferIterationNumber(case) - else: - iteration_number = index - - for obs_key in obs_keys: - well = obs_key.replace("RFT_", "") - wells.add(well) - obs_vector = enkf_obs[obs_key] - data_key = obs_vector.getDataKey() - report_step = obs_vector.activeStep() - obs_node = obs_vector.getNode(report_step) - - rft_data = GenDataCollector.loadGenData(self.ert(), case, data_key, report_step) - fs = self.ert().getEnkfFsManager().getFileSystem(case) - realizations = fs.realizationList(RealizationStateEnum.STATE_HAS_DATA) - - # Trajectory - trajectory_file = os.path.join(trajectory_path, "%s.txt" % well) - if not os.path.isfile(trajectory_file): - trajectory_file = os.path.join(trajectory_path, "%s_R.txt" % well) - - trajectory = WellTrajectory(trajectory_file) - arg = ArgLoader.load(trajectory_file, column_names=["utm_x", "utm_y", "md", "tvd"]) - tvd_arg = arg["tvd"] - data_size = len(tvd_arg) - - # Observations - obs = numpy.empty(shape=(data_size, 2), dtype=numpy.float64) - obs.fill(numpy.nan) - for obs_index in range(len(obs_node)): - data_index = obs_node.getDataIndex(obs_index) - value = obs_node.getValue(obs_index) - std = obs_node.getStandardDeviation(obs_index) - obs[data_index, 0] = value - obs[data_index, 1] = std - - for iens in realizations: - realization_frame = pandas.DataFrame(data={"TVD": tvd_arg, - "Pressure": rft_data[iens], - "ObsValue": obs[:, 0], - "ObsStd": obs[:, 1]}, - columns=["TVD", "Pressure", "ObsValue", "ObsStd"]) - - realization_frame["Realization"] = iens - realization_frame["Well"] = well - realization_frame["Case"] = case - realization_frame["Iteration"] = iteration_number - - case_frame = case_frame.append(realization_frame) - - data_frame = data_frame.append(case_frame) - - data_frame.set_index(["Realization", "Well", "Case", "Iteration"], inplace=True) - data_frame.to_csv(output_file) - export_info = "Exported RFT information for wells: %s to: %s " % (", ".join(list(wells)), output_file) - return export_info - - def getArguments(self, parent=None): - description = "The GEN_DATA RFT CSV export requires some information before it starts:" - dialog = CustomDialog("Robust CSV Export", description, parent) - - output_path_model = PathModel("output.csv") - output_path_chooser = PathChooser(output_path_model) - - trajectory_model = PathModel("wellpath", must_be_a_directory=True, must_be_a_file=False, must_exist=True) - trajectory_chooser = PathChooser(trajectory_model) - - fs_manager = self.ert().getEnkfFsManager() - all_case_list = fs_manager.getCaseList() - all_case_list = [case for case in all_case_list if fs_manager.caseHasData(case)] - list_edit = ListEditBox(all_case_list) - - infer_iteration_check = QCheckBox() - infer_iteration_check.setChecked(True) - infer_iteration_check.setToolTip(GenDataRFTCSVExportJob.INFER_HELP) - - dialog.addLabeledOption("Output file path", output_path_chooser) - dialog.addLabeledOption("Trajectory file", trajectory_chooser) - dialog.addLabeledOption("List of cases to export", list_edit) - dialog.addLabeledOption("Infer iteration number", infer_iteration_check) - - dialog.addButtons() - - success = dialog.showAndTell() - - if success: - case_list = ",".join(list_edit.getItems()) - try: - return [output_path_model.getPath(), trajectory_model.getPath(), case_list, infer_iteration_check.isChecked()] - except ValueError: - pass - - raise CancelPluginException("User cancelled!") diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/init_case_from_existing.py b/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/init_case_from_existing.py deleted file mode 100644 index abb028820c..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/init_case_from_existing.py +++ /dev/null @@ -1,16 +0,0 @@ -from ert.enkf import ErtScript - - -class InitCaseFromExistingJob(ErtScript): - - def run(self, source_case, target_case=None): - ert = self.ert() - source_fs = ert.getEnkfFsManager().getFileSystem(source_case) - - if target_case is None: - target_fs = ert.getEnkfFsManager().getCurrentFileSystem() - - else: - target_fs = ert.getEnkfFsManager().getFileSystem(target_case) - - ert.getEnkfFsManager().initializeCaseFromExisting(source_fs, 0 , target_fs) diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/select_case.py b/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/select_case.py deleted file mode 100644 index 63f4456f9d..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/select_case.py +++ /dev/null @@ -1,9 +0,0 @@ -from ert.enkf import ErtScript - -class SelectCaseJob(ErtScript): - - def run(self, case_name): - ert = self.ert() - fs = ert.getEnkfFsManager().getFileSystem(case_name) - ert.getEnkfFsManager().switchFileSystem(fs) - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/update_runpath_list.py b/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/update_runpath_list.py deleted file mode 100644 index 4a4300fb6c..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-gui/scripts/update_runpath_list.py +++ /dev/null @@ -1,37 +0,0 @@ -from ert.enkf import ErtScript - -""" -This job is useful if you are running a workflow that requires the hook_manager runpath_list -to be populated but your are not running any simulations. -""" - -class UpdateRunpathListJob(ErtScript): - def run(self): - ert = self.ert() - - realization_count = ert.getEnsembleSize() - iteration = 0 - - ecl_config = ert.eclConfig() - model_config = ert.getModelConfig() - basename_fmt = ecl_config.getEclBase() - runpath_fmt = model_config.getRunpathAsString() - hook_manager = ert.getHookManager() - - runpath_list = hook_manager.getRunpathList() - - runpath_list.clear() - - for realization_number in range(realization_count): - - if basename_fmt is not None: - basename = basename_fmt % realization_number - else: - raise UserWarning("EclBase not set!") - - if model_config.runpathRequiresIterations(): - runpath = runpath_fmt % (realization_number, iteration) - else: - runpath = runpath_fmt % realization_number - - runpath_list.add(realization_number, iteration, runpath, basename) diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/CREATE_CASE b/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/CREATE_CASE deleted file mode 100644 index e59df565d8..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/CREATE_CASE +++ /dev/null @@ -1,6 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_create_case_JOB -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 STRING - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/INIT_CASE_FROM_EXISTING b/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/INIT_CASE_FROM_EXISTING deleted file mode 100644 index f9a1ba7a5e..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/INIT_CASE_FROM_EXISTING +++ /dev/null @@ -1,7 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_init_case_from_existing_JOB -MIN_ARG 1 -MAX_ARG 2 -ARG_TYPE 0 STRING -ARG_TYPE 1 STRING - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/PLOT_ALL_SUMMARY b/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/PLOT_ALL_SUMMARY deleted file mode 100644 index 76ce548a86..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/PLOT_ALL_SUMMARY +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION enkf_tui_plot_all_summary_JOB -MIN_ARG 0 - - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/SELECT_CASE b/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/SELECT_CASE deleted file mode 100644 index 3d77f14369..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal-tui/config/SELECT_CASE +++ /dev/null @@ -1,6 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_select_case_JOB -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 STRING - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/ANALYSIS_SELECT_MODULE b/ThirdParty/Ert/share/workflows/jobs/internal/config/ANALYSIS_SELECT_MODULE deleted file mode 100644 index 7e12173079..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/ANALYSIS_SELECT_MODULE +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_select_module_JOB -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 STRING \ No newline at end of file diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/ANALYSIS_UPDATE b/ThirdParty/Ert/share/workflows/jobs/internal/config/ANALYSIS_UPDATE deleted file mode 100644 index 186f1d7122..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/ANALYSIS_UPDATE +++ /dev/null @@ -1,6 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_analysis_update_JOB -MIN_ARG 2 -MAX_ARG 2 -ARG_TYPE 0 STRING -ARG_TYPE 1 STRING diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/DATA_RANKING b/ThirdParty/Ert/share/workflows/jobs/internal/config/DATA_RANKING deleted file mode 100644 index 514aac9c2e..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/DATA_RANKING +++ /dev/null @@ -1,8 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_rank_on_data_JOB -MIN_ARG 3 -MAX_ARG 4 -ARG_TYPE 0 STRING -ARG_TYPE 1 STRING -ARG_TYPE 2 BOOL -ARG_TYPE 3 INT diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/ENSEMBLE_RUN b/ThirdParty/Ert/share/workflows/jobs/internal/config/ENSEMBLE_RUN deleted file mode 100644 index 8bdc4b1da2..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/ENSEMBLE_RUN +++ /dev/null @@ -1,6 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_ensemble_run_JOB -MIN_ARG 0 -ARG_TYPE 0 STRING - - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXIT_ERT b/ThirdParty/Ert/share/workflows/jobs/internal/config/EXIT_ERT deleted file mode 100644 index ef2e4b9d1e..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXIT_ERT +++ /dev/null @@ -1,4 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_exit_JOB -MIN_ARG 0 -MAX_ARG 0 diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD b/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD deleted file mode 100644 index ca01bc461a..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD +++ /dev/null @@ -1,7 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_export_field_JOB -MIN_ARG 3 -ARG_TYPE 0 STRING -ARG_TYPE 1 STRING -ARG_TYPE 2 INT -ARG_TYPE 3 STRING diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD_ECL_GRDECL b/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD_ECL_GRDECL deleted file mode 100644 index 75e0020f1e..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD_ECL_GRDECL +++ /dev/null @@ -1,7 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_export_field_to_ECL_JOB -MIN_ARG 3 -ARG_TYPE 0 STRING -ARG_TYPE 1 STRING -ARG_TYPE 2 INT -ARG_TYPE 3 STRING diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD_RMS_ROFF b/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD_RMS_ROFF deleted file mode 100644 index cfc6a2f4f5..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_FIELD_RMS_ROFF +++ /dev/null @@ -1,7 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_export_field_to_RMS_JOB -MIN_ARG 3 -ARG_TYPE 0 STRING -ARG_TYPE 1 STRING -ARG_TYPE 2 INT -ARG_TYPE 3 STRING diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_RANKING b/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_RANKING deleted file mode 100644 index 0ef0614609..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_RANKING +++ /dev/null @@ -1,7 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_export_ranking_JOB -MIN_ARG 2 -MAX_ARG 2 -ARG_TYPE 0 STRING -ARG_TYPE 1 STRING - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_RUNPATH b/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_RUNPATH deleted file mode 100644 index 753f9e9c9f..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/EXPORT_RUNPATH +++ /dev/null @@ -1,3 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_export_runpath_file_JOB - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/INIT_MISFIT_TABLE b/ThirdParty/Ert/share/workflows/jobs/internal/config/INIT_MISFIT_TABLE deleted file mode 100644 index a798874f59..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/INIT_MISFIT_TABLE +++ /dev/null @@ -1,4 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_init_misfit_table_JOB -MIN_ARG 0 - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/LOAD_RESULTS b/ThirdParty/Ert/share/workflows/jobs/internal/config/LOAD_RESULTS deleted file mode 100644 index 8be9a06ecd..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/LOAD_RESULTS +++ /dev/null @@ -1,3 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_load_results_JOB - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/LOAD_RESULTS_ITER b/ThirdParty/Ert/share/workflows/jobs/internal/config/LOAD_RESULTS_ITER deleted file mode 100644 index e81802426e..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/LOAD_RESULTS_ITER +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_load_results_iter_JOB -MIN_ARG 1 -ARG_TYPE 0 INT - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/OBSERVATION_RANKING b/ThirdParty/Ert/share/workflows/jobs/internal/config/OBSERVATION_RANKING deleted file mode 100644 index 23b8402bb6..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/OBSERVATION_RANKING +++ /dev/null @@ -1,4 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_rank_on_observations_JOB -MIN_ARG 1 -ARG_TYPE 0 STRING diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_ITERATED_SMOOTHER b/ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_ITERATED_SMOOTHER deleted file mode 100644 index ed425d5f97..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_ITERATED_SMOOTHER +++ /dev/null @@ -1,4 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_iterated_smoother_JOB -MIN_ARG 0 -MAX_ARG 0 diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_SMOOTHER b/ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_SMOOTHER deleted file mode 100644 index 44e1bf217b..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_SMOOTHER +++ /dev/null @@ -1,7 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_smoother_JOB -MIN_ARG 1 -MAX_ARG 2 -ARG_TYPE 0 STRING -ARG_TYPE 1 BOOL - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_SMOOTHER_WITH_ITER b/ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_SMOOTHER_WITH_ITER deleted file mode 100644 index 15ab1a9dcf..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/RUN_SMOOTHER_WITH_ITER +++ /dev/null @@ -1,8 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_smoother_with_iter_JOB -MIN_ARG 1 -MAX_ARG 3 -ARG_TYPE 0 INT -ARG_TYPE 1 STRING -ARG_TYPE 2 BOOL - diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/SCALE_STD b/ThirdParty/Ert/share/workflows/jobs/internal/config/SCALE_STD deleted file mode 100644 index 26ebee4fc8..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/SCALE_STD +++ /dev/null @@ -1,5 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_scale_obs_std_JOB -MIN_ARG 1 -MAX_ARG 1 -ARG_TYPE 0 FLOAT diff --git a/ThirdParty/Ert/share/workflows/jobs/internal/config/STD_SCALE_CORRELATED_OBS b/ThirdParty/Ert/share/workflows/jobs/internal/config/STD_SCALE_CORRELATED_OBS deleted file mode 100644 index 10baf75313..0000000000 --- a/ThirdParty/Ert/share/workflows/jobs/internal/config/STD_SCALE_CORRELATED_OBS +++ /dev/null @@ -1,3 +0,0 @@ -INTERNAL True -FUNCTION enkf_main_std_scale_correlated_obs_JOB - diff --git a/ThirdParty/Ert/test-data/local/config/gen_data/REFCASE.SMSPEC b/ThirdParty/Ert/test-data/local/config/gen_data/REFCASE.SMSPEC deleted file mode 100644 index 04373c55f977a790111638ee1f1417755a4c1098..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 340 zcmbu5!3x4K42I(b71^OjkGcB>o-DR%k#*8$jNSFBuj(7=A9b+d(UgxrNq<6GA~MNm zu}PSS7Q3TOPy@F7XXp%_QM~rR3KZb-WeKGx0-|^3&NeGr)`e++f}vqzkkVDK|LM3qeMOVFn>VH E7w6J08vpN^c(Z+%X>S z-#gT6linxPTPD44sJC2t?D@Vzc_Z!$)=IC6dh4V&je73viXWe|sJB6S?ESq{dQZ@N z8>ROY^)^ZG8R~789{aqsMS3sLd|lFeiF#Y5_X_p4NpBwY66w80z3tL_gL>W4dy9HI zq{lwb@08wqG~X`ieL%h4());dJCKGn#L&^uC~;dwPyPzkEf#{nBIKH+!Y` z9nE(@dOuL_p!9yC-XZC+@9&4D_Z!XEC%r$YcSL%BQSYeo^6Y$wds~iPU-B)+ex*^w ze8_P-QrvShh`tD~-wqY`+DytJ^Dif)$IdUElwLcU@09f142>_Mf2ZwG@&0v~ltcPA zAU$@z?u_(0(R^p6=iY#Q5&d(sWAXlVnUq8NHz>U%aELb~y>1ggVt?kO=iV@U5#F#J zD&D^ylXA%Z9FZP7pPZLoFPg6)J@*9Xi|F5ZJ5;=XeJ16Q{#}qBJ3n8PUO$?zBt3VB z^hNY<)D9Kz-+)Ouq<Zi{>o`RaD4c)q$xIV9gD>0JpN;$4>B zlnEfQKi$^H_vdurkbGCAH)8@w%fkX1mNbi9OAd&B;^yUJG=2012.0.1, =/rms/rms_project_2012 , =MAIN_WORKFLOW) -FORWARD_MODEL ECLIPSE100_2009.1 ---FORWARD_MODEL PRESSURE33 ---FORWARD_MODEL RMS_TEST( = , = , = 2011.0.2, =/rms/rms_project_2012 , =/d/proj/bg/ior_fsenter/GRM_TDP/Gimle/work/tfen/r0004/models/eclipse/refcase/, =Forward_Seismic,=SEISMIC_FORWARD_TARGET.INC) - ---FORWARD_MODEL AVGP ---FORWARD_MODEL NULL - - -UMASK 0 -MAX_SUBMIT 10 -MAX_RESAMPLE 1 - - -ADD_FIXED_LENGTH_SCHEDULE_KW Jalla 7 -ADD_FIXED_LENGTH_SCHEDULE_KW Jalla2 70 - - - -DBASE_TYPE BLOCK_FS - --- The ensemble -NUM_REALIZATIONS 25 - -IMAGE_TYPE png -PLOT_DRIVER PLPLOT - -RUN_TEMPLATE Template1 File1 File:1 -RUN_TEMPLATE Template1 File2 File:2 - - -INSTALL_JOB PRESSURE100 PRESSURE100 - - -GEN_KW MULTFLT FAULT_TEMPLATE MULTFLT.INC Config/MULTFLT.txt -GEN_KW GRID_PARAMS GRID_PARAM_TEMPLATE GRID_PARAMS.INC Config/GRID_PARAMS.txt --MIN_STD:Config/GRID_PARAMS.min_std -GEN_KW FLUID_PARAMS FLUID_PARAM_TEMPLATE FLUID_PARAMS.INC Config/FLUID_PARAMS.txt --MIN_STD:Config/FLUID_PARAMS.min_std - -GEN_PARAM GP GP.txt INIT_FILES:GP/GP.txt INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII - - - - -UPDATE_RESULTS TRUE -ENKF_RERUN FALSE -RERUN_START 0 - -INSTALL_JOB SGOF_TAB jobs/SGOF_TAB - - - -ENKF_MERGE_OBSERVATIONS TRUE ---ENKF_SCHED_FILE sched_config - - ---ADD_STATIC_KW __ALL__ -ADD_STATIC_KW BJARNE KW2 - -ENKF_ALPHA 1.50 ------------------------------------------------------------------ -IMAGE_VIEWER /tmp/echo.sh -IMAGE_VIEWER /usr/bin/display - - -QUEUE_SYSTEM LSF -QUEUE_SYSTEM LOCAL -QUEUE_SYSTEM RSH - -MAX_RUNNING_LOCAL 3 -MAX_RUNNING_LSF 100 -MAX_RUNNING_RSH 6 ---LSF_QUEUE SUPERKO - -RSH_HOST be-lx655082:2 be-lx633214:2 - - - -LOG_LEVEL 3 -LOG_FILE /tmp/log/log.txt -UPDATE_LOG_PATH /tmp/UP - -KEEP_RUNPATH 0 - 9 -DATA_KW __INCLUDE_PATH__ -DATA_KW WhatEver SomeThing - - - - --- Quantities to estimate on - -HISTORY_SOURCE REFCASE_HISTORY -REFCASE __NAME__.DATA - - -STORE_SEED RandomSeed -LOAD_SEED RandomSeed - - ---EQUIL EQUIL EQUIL.INC equil_config - -RUN_TEMPLATE GEN_DATA_TEMPLATE GEN_DATA_FILE ---GEN_DATA PRESSURE100 INPUT_FORMAT:ASCII RESULT_FILE:PRESSURE%04d - - - ---ANALYSIS_LOAD RML_ENKF /project/res/x86_64_RH_5/lib/rml_enkf.so ---ANALYSIS_LOAD RML_ENKF rml_enkf.so -ANALYSIS_LOAD RML_ENKF /private/joaho/ERT/NR/libanalysis/src/rml_enkf.so - ---ANALYSIS_LOAD FWD_ENKF /private/joaho/ERT/NR/tmp-build/libanalysis/src/sqrt_enkf.so ---ANALYSIS_LOAD SFWD_ENKF /private/joaho/ERT/NR/tmp-build/libanalysis/src/std_enkf.so -ANALYSIS_SET_VAR STD_ENKF ENKF_TRUNCATION 0.95 ---ANALYSIS_SET_VAR SQRT_ENKF ENKF_TRUNCATION 0.99 -ANALYSIS_SET_VAR STD_ENKF ENKF_NCOMP 2 -ANALYSIS_SET_VAR STD_ENKF ENKF_TRUNCATION 0.98 -ANALYSIS_SELECT STD_ENKF - -ANALYSIS_LOAD TEST_ENKF /private/joaho/ERT/NR/libanalysis/src/test_enkf.so - - -QUEUE_OPTION LSF LSF_LOGIN_SHELL /bin/csh - - -FIELD PRESSURE DYNAMIC -FIELD SWAT DYNAMIC MIN:0 MAX:1 -FIELD SGAS DYNAMIC MIN:0 MAX:1 -FIELD RS DYNAMIC MIN:0 -FIELD RV DYNAMIC MIN:0.0034 - ---CONTAINER CXX PRESSURE SWAT - - ---SURFACE TOP OUTPUT_FILE:surf.irap INIT_FILES:Surfaces/d_BCU_%d.irap BASE_SURFACE:Surfaces/d_BCU_0.irap - --- Observations -OBS_CONFIG observations - - ---SUMMARY F* RPR:* - -PLOT_PATH plots - - -IMAGE_VIEWER /tmp/noplot.sh - ------------------------------------------------------------------ - -WORKFLOW_JOB_DIRECTORY WorkflowJobs -LOAD_WORKFLOW Workflows/PLOT_AND_EXIT diff --git a/ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_1 b/ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_1 deleted file mode 100644 index 9468fb3092..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_1 +++ /dev/null @@ -1,5 +0,0 @@ -GENERAL_OBSERVATION GEN_PERLIN_1 { - DATA = PERLIN; - RESTART = 1; - OBS_FILE = Observations/perlin_obs_1.txt; -}; diff --git a/ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_2 b/ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_2 deleted file mode 100644 index a52d2ddb9c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_2 +++ /dev/null @@ -1,5 +0,0 @@ -GENERAL_OBSERVATION GEN_PERLIN_2 { - DATA = PERLIN; - RESTART = 2; - OBS_FILE = Observations/perlin_obs_2.txt; -}; diff --git a/ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_3 b/ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_3 deleted file mode 100644 index 7465c4c124..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/Observations/observation_3 +++ /dev/null @@ -1,5 +0,0 @@ -GENERAL_OBSERVATION GEN_PERLIN_3 { - DATA = PERLIN; - RESTART = 3; - OBS_FILE = Observations/perlin_obs_3.txt; -}; \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/Observations/observations b/ThirdParty/Ert/test-data/local/custom_kw/Observations/observations deleted file mode 100644 index bff0c5823b..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/Observations/observations +++ /dev/null @@ -1,17 +0,0 @@ -GENERAL_OBSERVATION GEN_PERLIN_1 { - DATA = PERLIN; - RESTART = 1; - OBS_FILE = Observations/perlin_obs_1.txt; -}; - -GENERAL_OBSERVATION GEN_PERLIN_2 { - DATA = PERLIN; - RESTART = 2; - OBS_FILE = Observations/perlin_obs_2.txt; -}; - -GENERAL_OBSERVATION GEN_PERLIN_3 { - DATA = PERLIN; - RESTART = 3; - OBS_FILE = Observations/perlin_obs_3.txt; -}; \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_1.txt deleted file mode 100644 index fbfbf08d9e..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.616789 0.200000 --0.626286 0.200000 --0.642772 0.200000 --0.623396 0.200000 --0.601028 0.200000 --0.587671 0.200000 --0.545803 0.200000 --0.548698 0.200000 --0.576106 0.200000 --0.547830 0.200000 --0.499566 0.200000 --0.390302 0.200000 --0.274769 0.200000 --0.218078 0.200000 --0.206531 0.200000 --0.256190 0.200000 --0.286962 0.200000 --0.290826 0.200000 --0.279457 0.200000 --0.220628 0.200000 --0.175666 0.200000 --0.134717 0.200000 --0.041140 0.200000 -0.004634 0.200000 --0.003586 0.200000 --0.044667 0.200000 --0.084128 0.200000 --0.096405 0.200000 --0.146272 0.200000 --0.192659 0.200000 --0.240387 0.200000 --0.315781 0.200000 --0.353862 0.200000 --0.373289 0.200000 --0.395017 0.200000 --0.362747 0.200000 --0.314473 0.200000 --0.207889 0.200000 --0.078605 0.200000 --0.003939 0.200000 -0.034326 0.200000 -0.005587 0.200000 -0.013544 0.200000 -0.095579 0.200000 -0.191848 0.200000 -0.291420 0.200000 -0.337769 0.200000 -0.309285 0.200000 -0.283094 0.200000 -0.246823 0.200000 -0.190450 0.200000 -0.194585 0.200000 -0.244807 0.200000 -0.290661 0.200000 -0.329075 0.200000 -0.306089 0.200000 -0.264557 0.200000 -0.288901 0.200000 -0.331039 0.200000 -0.413380 0.200000 -0.466520 0.200000 -0.460285 0.200000 -0.444206 0.200000 -0.386893 0.200000 -0.350833 0.200000 -0.314020 0.200000 -0.255650 0.200000 -0.237356 0.200000 -0.229103 0.200000 -0.216303 0.200000 -0.232054 0.200000 -0.206562 0.200000 -0.164036 0.200000 -0.215742 0.200000 -0.336400 0.200000 -0.517183 0.200000 -0.654671 0.200000 -0.732607 0.200000 -0.814735 0.200000 -0.835433 0.200000 -0.826283 0.200000 -0.770065 0.200000 -0.673958 0.200000 -0.624376 0.200000 -0.615341 0.200000 -0.601582 0.200000 -0.585811 0.200000 -0.522072 0.200000 -0.459689 0.200000 -0.462806 0.200000 -0.463663 0.200000 -0.490711 0.200000 -0.483229 0.200000 -0.416017 0.200000 -0.344176 0.200000 -0.307064 0.200000 -0.311372 0.200000 -0.314551 0.200000 -0.275854 0.200000 -0.138191 0.200000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_2.txt deleted file mode 100644 index 1c0ee7d131..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.553636 0.200000 -0.562210 0.200000 -0.577093 0.200000 -0.516574 0.200000 -0.453354 0.200000 -0.438536 0.200000 -0.362335 0.200000 -0.299754 0.200000 -0.294947 0.200000 -0.258916 0.200000 -0.199226 0.200000 -0.154968 0.200000 -0.076430 0.200000 -0.038162 0.200000 -0.047076 0.200000 -0.040351 0.200000 -0.044383 0.200000 --0.022339 0.200000 --0.098926 0.200000 --0.182296 0.200000 --0.239174 0.200000 --0.175066 0.200000 --0.098687 0.200000 -0.046630 0.200000 -0.163052 0.200000 -0.239754 0.200000 -0.379917 0.200000 -0.457436 0.200000 -0.500511 0.200000 -0.547066 0.200000 -0.589134 0.200000 -0.630865 0.200000 -0.648067 0.200000 -0.546752 0.200000 -0.382873 0.200000 -0.254339 0.200000 -0.167602 0.200000 -0.165063 0.200000 -0.107654 0.200000 -0.014283 0.200000 --0.003453 0.200000 --0.014968 0.200000 -0.001727 0.200000 -0.011346 0.200000 -0.009215 0.200000 -0.083611 0.200000 -0.234321 0.200000 -0.391352 0.200000 -0.455607 0.200000 -0.429702 0.200000 -0.462148 0.200000 -0.563361 0.200000 -0.647466 0.200000 -0.778980 0.200000 -0.862696 0.200000 -0.876752 0.200000 -0.897362 0.200000 -0.858848 0.200000 -0.813029 0.200000 -0.815672 0.200000 -0.829471 0.200000 -0.883008 0.200000 -0.938118 0.200000 -0.943737 0.200000 -0.943930 0.200000 -0.887728 0.200000 -0.749709 0.200000 -0.570611 0.200000 -0.427346 0.200000 -0.279535 0.200000 -0.134481 0.200000 -0.091839 0.200000 -0.092425 0.200000 -0.142324 0.200000 -0.217527 0.200000 -0.182289 0.200000 -0.063206 0.200000 --0.052929 0.200000 --0.124322 0.200000 --0.149079 0.200000 --0.160036 0.200000 --0.180000 0.200000 --0.213176 0.200000 --0.191568 0.200000 --0.140832 0.200000 --0.131431 0.200000 --0.164401 0.200000 --0.253597 0.200000 --0.316338 0.200000 --0.275519 0.200000 --0.191733 0.200000 --0.019671 0.200000 -0.187348 0.200000 -0.371249 0.200000 -0.532809 0.200000 -0.604516 0.200000 -0.620637 0.200000 -0.517488 0.200000 -0.382527 0.200000 -0.308772 0.200000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_3.txt deleted file mode 100644 index f2cad960e0..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/Observations/perlin_obs_3.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.258515 0.200000 --0.356107 0.200000 --0.525515 0.200000 --0.663313 0.200000 --0.770373 0.200000 --0.752177 0.200000 --0.720117 0.200000 --0.712752 0.200000 --0.678174 0.200000 --0.634873 0.200000 --0.510858 0.200000 --0.401601 0.200000 --0.371298 0.200000 --0.399836 0.200000 --0.388296 0.200000 --0.362204 0.200000 --0.377951 0.200000 --0.339453 0.200000 --0.258223 0.200000 --0.088966 0.200000 -0.113885 0.200000 -0.276111 0.200000 -0.391728 0.200000 -0.418974 0.200000 -0.416504 0.200000 -0.381174 0.200000 -0.323184 0.200000 -0.270447 0.200000 -0.279357 0.200000 -0.328360 0.200000 -0.328559 0.200000 -0.323026 0.200000 -0.327307 0.200000 -0.348794 0.200000 -0.376927 0.200000 -0.383302 0.200000 -0.372235 0.200000 -0.356978 0.200000 -0.397867 0.200000 -0.522396 0.200000 -0.601574 0.200000 -0.657218 0.200000 -0.723345 0.200000 -0.698378 0.200000 -0.639636 0.200000 -0.584196 0.200000 -0.523544 0.200000 -0.490729 0.200000 -0.486421 0.200000 -0.409534 0.200000 -0.286329 0.200000 -0.120963 0.200000 --0.046326 0.200000 --0.129596 0.200000 --0.224071 0.200000 --0.277277 0.200000 --0.271037 0.200000 --0.304891 0.200000 --0.363780 0.200000 --0.395722 0.200000 --0.438535 0.200000 --0.504110 0.200000 --0.546085 0.200000 --0.616035 0.200000 --0.673682 0.200000 --0.650552 0.200000 --0.604866 0.200000 --0.567949 0.200000 --0.539873 0.200000 --0.552954 0.200000 --0.570381 0.200000 --0.517706 0.200000 --0.474400 0.200000 --0.373474 0.200000 --0.263037 0.200000 --0.203820 0.200000 --0.103226 0.200000 --0.051460 0.200000 -0.023379 0.200000 -0.085632 0.200000 -0.073926 0.200000 -0.114264 0.200000 -0.210600 0.200000 -0.367117 0.200000 -0.493523 0.200000 -0.541983 0.200000 -0.555534 0.200000 -0.507462 0.200000 -0.468411 0.200000 -0.494860 0.200000 -0.511384 0.200000 -0.505254 0.200000 -0.497490 0.200000 -0.404108 0.200000 -0.324978 0.200000 -0.329421 0.200000 -0.331172 0.200000 -0.357684 0.200000 -0.334654 0.200000 -0.226313 0.200000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/Parameters/PERLIN_PARAMS.txt b/ThirdParty/Ert/test-data/local/custom_kw/Parameters/PERLIN_PARAMS.txt deleted file mode 100644 index 24926666bb..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/Parameters/PERLIN_PARAMS.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE UNIFORM 0.1 1 -OFFSET UNIFORM -1 1 -PERSISTENCE UNIFORM 0.01 1 -OCTAVES UNIFORM 1 64 -PRIME_1 UNIFORM 0 127 -PRIME_2 UNIFORM 0 127 -PRIME_3 UNIFORM 0 127 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/RandomSeed b/ThirdParty/Ert/test-data/local/custom_kw/RandomSeed deleted file mode 100644 index a4571d8b82..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/RandomSeed +++ /dev/null @@ -1 +0,0 @@ -103 95 15 -86 -95 -5 16 -18 24 -60 -89 101 70 22 -104 -41 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/Refcase/CASE.EGRID b/ThirdParty/Ert/test-data/local/custom_kw/Refcase/CASE.EGRID deleted file mode 100644 index 33da9f7a70ee0800280622f32e6ac3737cf2615e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22000 zcmeI4QBD+55JevvgV7IW32!I94vazqgBc((e!Gxff=hTy=_UB3zr6?-VBOoddMX4z zFa)EiN_zUd!<%8M`ohd4gi^}p{l(?>d^?<#Qoda5Znt*clydad&M!+j{$c0)b#!0k z`Z*@RYqGf-KHlvvZg1>69-W>Kdpq0pDzC4$xBKl)tzfth`-?MdG=35GZG2x3i^E`YCuZ{T#d)emLlr>5)>^Af~Tw?Y?4ol=tZj59i()zLkS_rniOf z#~i@)c3!=hz6UR+pMn?D&%uk~F$aHqXL{>>^a3|>s%gBR0J!HenV;KlIhz1e|srnlZ3t$8th4PFe7!t?fG4_$L;i{(s= zu^-C!JJZ`@^20xkG5r|4n7#)urk{cr)6c<+;o19GSkCn5-MyH;1}}z3`Pmt3&cV(oXZU7o z-|tLsi`9$i$Kb{EJ$Nzw6ug*z4qgn;-tCNXrbq9cdil99rmw+^eP5f(T3~qgZj5q< zZ?^XR&h)ley_kLsUQFME7t>F{i|Oa!#qjLi_Mx2VF^7qInS(KX4PFe7YBNu~0mHL* zW0W&|v$gMcrnklF#q?wFV)`Dun0^XgOg{%NhG*}#Mmf`C4m0&K2V?pgyciyZ`+M=R z`qI05%)x!LjqaWCIL#KT7t@cyi|KptV)`j~G5s987#`o#zppdB&0+Oo`Wn0#9_8;d zoZ;EK-5=!)-)!yso#}0{dNKVNyqLZRFQ%V@7t_zdi{aV3o~JWCdUr3TufdDqQA5S; zQbS$x!`_Wi&e-21u%s^%!Gmsg0WCoVc>18vV-tO+MYPEkG_Ve(6-j2T& k6M5teG6R``%s^%!Gw`oxfUoJB?d}Z!0<_xoEdF}`3t>$U6951J diff --git a/ThirdParty/Ert/test-data/local/custom_kw/Template/PERLIN_TEMPLATE b/ThirdParty/Ert/test-data/local/custom_kw/Template/PERLIN_TEMPLATE deleted file mode 100644 index 527a92907c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/Template/PERLIN_TEMPLATE +++ /dev/null @@ -1,7 +0,0 @@ -SCALE: -OFFSET: -PERSISTENCE: -OCTAVES: -PRIME_1: -PRIME_2: -PRIME_3: \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/aggregated.txt deleted file mode 100644 index de8aedc562..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 0.190479 -PERLIN_2 1.002630 -PERLIN_1 -0.167794 -STATE Positive \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/parameters.txt deleted file mode 100644 index 142dbecaab..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.249225 -PERLIN_PARAM:OFFSET 0.185709 -PERLIN_PARAM:PERSISTENCE 0.936132 -PERLIN_PARAM:OCTAVES 22.4008 -PERLIN_PARAM:PRIME_1 70.2373 -PERLIN_PARAM:PRIME_2 73.2881 -PERLIN_PARAM:PRIME_3 73.2557 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_1.txt deleted file mode 100644 index fec0fd107e..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.167794 --0.533157 --0.582564 --0.581187 --0.544394 --0.617389 --0.471483 --0.570636 --0.513164 --0.094431 --0.489078 --0.363713 --0.116233 -0.104267 --0.185805 --0.200709 --0.150918 --0.384297 -0.293484 -0.122875 --0.157933 -0.066183 -0.043334 -0.083941 -0.237257 -0.510188 -0.247252 -0.238908 --0.087547 --0.330292 --0.126747 --0.035823 --0.234230 -0.031125 --0.470002 -0.277528 -0.333005 -0.208194 -0.329248 -0.183316 -0.030305 -0.292607 -0.207885 --0.055542 -0.267287 -0.489294 -0.351695 -0.473816 -0.486845 -0.161185 -0.750709 -0.334430 -0.487895 --0.083531 -0.631333 -0.189402 -0.293179 -0.416287 -0.071861 -0.343657 -0.530727 -0.295893 -0.707495 -0.705177 -0.364062 --0.028729 -0.627459 -0.665644 -0.110239 -0.074890 -0.898952 -0.507702 -0.793900 -0.376955 -0.740932 -0.768612 -1.072116 -0.641052 -0.951385 -1.114482 -0.779685 -1.030575 -0.960609 -0.819774 -0.728183 -0.880717 -0.390042 -0.616292 -0.534190 -0.332035 -0.597337 -0.310784 -0.480825 -0.510514 -0.527712 -0.106739 -0.459289 -0.091994 -0.167754 -0.291767 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_2.txt deleted file mode 100644 index a4c8ae2281..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -1.002630 -0.655338 -0.637300 -0.558783 -0.509989 -0.408818 -0.436655 -0.277816 -0.357889 -0.712315 -0.209713 -0.181557 -0.234966 -0.360507 -0.067803 -0.095832 -0.180428 --0.115810 -0.474014 -0.161206 --0.221441 -0.025834 --0.014213 -0.125937 -0.403895 -0.794609 -0.711298 -0.792749 -0.559236 -0.409434 -0.702774 -0.910823 -0.767699 -0.951166 -0.307889 -0.894615 -0.815080 -0.581146 -0.515508 -0.201538 --0.007474 -0.272051 -0.196068 --0.139775 -0.084654 -0.281485 -0.248246 -0.555883 -0.659358 -0.344063 -1.022407 -0.703206 -0.890554 -0.404788 -1.164953 -0.760065 -0.925984 -0.986234 -0.553851 -0.745948 -0.893678 -0.718616 -1.201408 -1.262021 -0.957160 -0.544980 -1.121517 -0.998898 -0.308482 -0.138122 -0.801380 -0.392979 -0.722289 -0.303537 -0.622059 -0.433718 -0.480651 --0.144483 -0.012328 -0.129970 --0.206634 -0.080509 -0.073475 -0.003830 --0.027990 -0.147703 --0.360170 --0.159376 --0.241837 --0.406290 --0.058059 --0.199599 -0.184944 -0.465746 -0.716346 -0.404191 -0.768554 -0.294930 -0.274427 -0.462347 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_3.txt deleted file mode 100644 index 13a10a9e5d..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.190479 --0.262978 --0.465308 --0.621105 --0.713738 --0.781896 --0.645797 --0.734690 --0.615233 --0.181474 --0.500371 --0.375013 --0.212762 --0.077491 --0.367569 --0.306723 --0.241907 --0.432924 -0.314717 -0.254536 -0.131618 -0.477011 -0.476202 -0.498281 -0.657347 -0.936028 -0.654565 -0.605760 -0.338082 -0.190727 -0.442199 -0.602984 -0.446939 -0.753207 -0.301943 -1.023577 -1.019714 -0.773061 -0.805721 -0.709651 -0.597553 -0.944238 -0.917685 -0.547257 -0.715075 -0.782070 -0.537469 -0.655260 -0.690172 -0.323895 -0.846589 -0.260808 -0.196762 --0.503788 -0.078186 --0.393964 --0.242415 --0.177505 --0.622958 --0.465445 --0.374328 --0.668502 --0.282796 --0.297752 --0.660453 --0.993300 --0.233057 --0.139662 --0.658737 --0.694367 -0.096517 --0.216566 -0.155464 --0.212261 -0.141495 -0.047609 -0.314219 --0.143014 -0.160029 -0.364682 -0.027328 -0.374773 -0.497251 -0.562515 -0.606365 -0.821117 -0.359765 -0.601682 -0.542912 -0.364089 -0.645058 -0.325327 -0.495087 -0.498606 -0.508514 -0.129097 -0.479090 -0.135126 -0.226554 -0.379889 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_fail.status b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_fail.status deleted file mode 100644 index 6ac0122a28..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_fail.status +++ /dev/null @@ -1 +0,0 @@ -Did nothing! \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_params.txt deleted file mode 100644 index 99b2ec3ff6..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.249225 -OFFSET:0.185709 -PERSISTENCE:0.936132 -OCTAVES:22.4008 -PRIME_1:70.2373 -PRIME_2:73.2881 -PRIME_3:73.2557 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/realization.ok b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/realization.ok deleted file mode 100644 index a0aba9318a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-0/iter-0/realization.ok +++ /dev/null @@ -1 +0,0 @@ -OK \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/aggregated.txt deleted file mode 100644 index c42ebc2573..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 -0.584204 -PERLIN_2 0.227947 -PERLIN_1 -0.942477 -STATE Negative \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/parameters.txt deleted file mode 100644 index d931876083..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.24275 -PERLIN_PARAM:OFFSET -0.29096 -PERLIN_PARAM:PERSISTENCE 0.860518 -PERLIN_PARAM:OCTAVES 14.7858 -PERLIN_PARAM:PRIME_1 11.8217 -PERLIN_PARAM:PRIME_2 48.9187 -PERLIN_PARAM:PRIME_3 89.5122 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_2.txt deleted file mode 100644 index 296be5b8cd..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.227947 -0.461424 -0.496254 -0.385250 -0.382965 -0.294599 -0.215538 -0.354808 -0.194641 -0.061050 -0.006348 --0.033658 --0.137511 --0.052176 -0.054974 -0.004020 --0.119814 --0.186461 --0.385196 --0.286967 --0.540945 --0.434223 --0.424480 --0.139600 --0.216224 -0.069846 -0.120217 -0.327327 -0.326008 -0.431300 -0.341933 -0.550826 -0.259922 -0.392107 -0.003858 -0.014051 --0.354946 --0.083760 --0.201720 --0.372664 --0.515754 --0.416670 --0.452153 --0.378276 --0.502741 --0.226850 --0.117039 --0.170353 --0.103309 -0.018785 -0.134857 -0.299396 -0.256928 -0.466775 -0.638846 -0.679726 -0.643554 -0.744558 -0.717986 -0.632070 -0.597780 -0.726447 -0.907347 -0.748545 -0.576996 -0.711178 -0.663988 -0.233265 -0.069050 --0.047240 --0.055375 --0.163060 --0.421085 --0.171631 -0.043688 --0.021042 --0.190991 --0.247524 --0.463284 --0.413005 --0.644291 --0.650833 --0.570592 --0.466943 --0.568175 --0.409936 --0.512981 --0.655652 --0.830461 --0.878072 --0.495081 --0.517236 --0.159439 -0.026080 --0.084928 -0.074934 -0.020797 -0.156703 --0.069071 -0.019410 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_3.txt deleted file mode 100644 index d43e140291..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.584204 --0.456892 --0.606354 --0.794637 --0.840762 --0.896115 --0.866915 --0.657698 --0.778480 --0.832740 --0.703736 --0.590227 --0.585239 --0.490175 --0.380398 --0.398535 --0.542149 --0.503575 --0.544492 --0.193638 --0.187886 -0.016954 -0.065935 -0.232744 -0.037229 -0.211265 -0.063484 -0.140338 -0.104854 -0.212594 -0.081358 -0.242987 --0.060839 -0.194148 --0.002088 -0.143014 --0.150313 -0.108155 -0.088492 -0.135449 -0.089272 -0.255517 -0.269465 -0.308757 -0.127679 -0.273734 -0.172184 --0.070976 --0.072495 --0.001383 --0.040962 --0.143002 --0.436864 --0.441800 --0.447921 --0.474303 --0.524845 --0.419181 --0.458823 --0.579324 --0.670226 --0.660671 --0.576856 --0.811227 --1.040616 --0.827102 --0.690587 --0.905295 --0.898169 --0.879729 --0.760237 --0.772606 --0.987910 --0.687429 --0.436876 --0.407151 --0.357423 --0.246055 --0.315583 --0.178294 --0.410329 --0.356569 --0.146816 -0.091742 -0.066180 -0.263478 -0.206954 -0.105406 --0.045712 --0.107693 -0.208035 -0.007690 -0.150704 -0.058939 --0.292759 --0.200161 --0.268667 --0.003101 --0.116944 --0.063049 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_fail.status b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_fail.status deleted file mode 100644 index 46a71f4e16..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_fail.status +++ /dev/null @@ -1 +0,0 @@ -Deleted report step: 1 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_params.txt deleted file mode 100644 index fb78e8c3e9..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.24275 -OFFSET:-0.29096 -PERSISTENCE:0.860518 -OCTAVES:14.7858 -PRIME_1:11.8217 -PRIME_2:48.9187 -PRIME_3:89.5122 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/realization.ok b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/realization.ok deleted file mode 100644 index a0aba9318a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-1/iter-0/realization.ok +++ /dev/null @@ -1 +0,0 @@ -OK \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/ERROR b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/ERROR deleted file mode 100644 index f5c9d83c76..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/ERROR +++ /dev/null @@ -1,8 +0,0 @@ - - - REALIZATION_FAIL - Could not find target_file:realization.ok - - - - diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/EXIT b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/EXIT deleted file mode 100644 index f5c9d83c76..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/EXIT +++ /dev/null @@ -1,8 +0,0 @@ - - - REALIZATION_FAIL - Could not find target_file:realization.ok - - - - diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/aggregated.txt deleted file mode 100644 index 39c71d12aa..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 -0.294383 -PERLIN_2 0.517768 -PERLIN_1 -0.652656 -STATE Negative \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/parameters.txt deleted file mode 100644 index 0850de9c61..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.187883 -PERLIN_PARAM:OFFSET -0.512383 -PERLIN_PARAM:PERSISTENCE 0.850056 -PERLIN_PARAM:OCTAVES 39.9199 -PERLIN_PARAM:PRIME_1 76.7337 -PERLIN_PARAM:PRIME_2 54.1086 -PERLIN_PARAM:PRIME_3 16.0042 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_1.txt deleted file mode 100644 index 122d4089ea..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.652656 --0.856575 --0.907574 --0.921559 --0.907052 --0.798535 --0.892001 --0.898300 --0.932647 --0.887530 --0.745258 --0.774438 --0.680597 --0.707552 --0.616984 --0.784930 --0.705796 --0.672207 --0.677662 --0.517634 --0.460960 --0.512998 --0.485822 --0.377630 --0.469687 --0.463782 --0.644529 --0.631042 --0.610238 --0.645129 --0.841183 --0.813056 --0.824549 --0.985474 --0.818724 --1.021755 --0.749654 --0.643111 --0.382287 --0.319701 --0.240893 --0.293783 --0.356379 --0.315861 --0.243741 --0.061641 --0.016073 --0.078540 --0.166452 --0.204278 --0.206156 --0.339674 --0.324650 --0.218586 --0.220018 --0.365619 --0.213129 --0.161173 --0.144854 --0.088350 --0.193806 --0.111286 --0.100984 --0.235155 --0.165413 --0.278588 --0.429381 --0.254946 --0.240835 --0.227267 --0.524615 --0.423858 --0.341032 --0.369948 --0.180422 -0.176827 -0.282667 -0.455645 -0.421888 -0.461117 -0.478802 -0.408361 -0.301001 -0.266791 -0.167743 -0.066362 -0.101881 -0.183729 --0.037895 -0.191528 -0.077918 -0.193353 -0.109073 -0.001759 --0.061599 --0.001108 --0.164077 --0.253534 --0.200586 --0.275259 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_3.txt deleted file mode 100644 index 1e03faf793..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.294383 --0.586396 --0.790317 --0.961476 --1.076396 --0.963042 --1.066316 --1.062354 --1.034715 --0.974573 --0.756551 --0.785737 --0.777126 --0.889310 --0.798749 --0.890944 --0.796785 --0.720834 --0.656429 --0.385973 --0.171410 --0.102170 --0.052955 -0.036709 --0.049597 --0.037941 --0.237216 --0.264190 --0.184608 --0.124110 --0.272236 --0.174249 --0.143380 --0.263391 --0.046779 --0.275706 --0.062945 --0.078243 -0.094185 -0.206634 -0.326354 -0.357848 -0.353421 -0.286938 -0.204047 -0.231135 -0.169701 -0.102903 -0.036875 --0.041568 --0.110276 --0.413296 --0.615784 --0.638843 --0.773164 --0.948985 --0.748723 --0.754966 --0.839672 --0.897452 --1.098861 --1.075682 --1.091275 --1.238084 --1.189928 --1.243159 --1.289897 --1.060251 --1.009811 --0.996525 --1.327050 --1.148126 --0.979468 --0.959163 --0.779859 --0.544176 --0.475229 --0.328422 --0.369468 --0.288684 --0.273556 --0.247441 --0.162358 -0.009532 -0.045926 -0.006763 -0.071604 -0.169119 --0.029173 -0.223582 -0.125639 -0.207896 -0.123334 --0.010150 --0.080797 -0.021249 --0.144276 --0.210401 --0.141786 --0.187137 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_fail.status b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_fail.status deleted file mode 100644 index 2494f445e5..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_fail.status +++ /dev/null @@ -1 +0,0 @@ -Deleted report step: 2 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_params.txt deleted file mode 100644 index a069d36ab8..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-2/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.187883 -OFFSET:-0.512383 -PERSISTENCE:0.850056 -OCTAVES:39.9199 -PRIME_1:76.7337 -PRIME_2:54.1086 -PRIME_3:16.0042 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/ERROR b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/ERROR deleted file mode 100644 index f5c9d83c76..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/ERROR +++ /dev/null @@ -1,8 +0,0 @@ - - - REALIZATION_FAIL - Could not find target_file:realization.ok - - - - diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/EXIT b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/EXIT deleted file mode 100644 index f5c9d83c76..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/EXIT +++ /dev/null @@ -1,8 +0,0 @@ - - - REALIZATION_FAIL - Could not find target_file:realization.ok - - - - diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/aggregated.txt deleted file mode 100644 index b986f1b481..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 -0.871387 -PERLIN_2 -0.059236 -PERLIN_1 -1.229660 -STATE Negative \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/parameters.txt deleted file mode 100644 index a7472afccf..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.542054 -PERLIN_PARAM:OFFSET -0.936072 -PERLIN_PARAM:PERSISTENCE 0.66513 -PERLIN_PARAM:OCTAVES 59.6891 -PERLIN_PARAM:PRIME_1 58.3958 -PERLIN_PARAM:PRIME_2 51.6271 -PERLIN_PARAM:PRIME_3 37.3286 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_1.txt deleted file mode 100644 index 1f0aabd193..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --1.229660 --1.403213 --1.494882 --1.481222 --1.545058 --1.605346 --1.466829 --1.460689 --1.589462 --1.462504 --1.586371 --1.419953 --1.184666 --1.064367 --1.081730 --1.130531 --1.307146 --1.330892 --1.147255 --1.230522 --1.290812 --1.243312 --1.053225 --0.837831 --0.815416 --0.794856 --0.780118 --0.867346 --0.868595 --0.844661 --0.949974 --1.135521 --1.278698 --1.237066 --1.353473 --1.274754 --1.024540 --1.062374 --1.018191 --0.989482 --1.082235 --1.083477 --1.111900 --0.884140 --0.804378 --0.649785 --0.414051 --0.453314 --0.426393 --0.376335 --0.433952 --0.369796 --0.319725 --0.318209 --0.380495 --0.274543 --0.410077 --0.265464 --0.276032 --0.293185 --0.259478 --0.307654 --0.469020 --0.606702 --0.727993 --0.657698 --0.738949 --0.779068 --0.929409 --0.925120 --0.888902 --0.818882 --0.691387 --0.806321 --0.774223 --0.725947 --0.616177 --0.575377 --0.546778 --0.619225 --0.739783 --0.805058 --0.854443 --1.003113 --0.978222 --0.724971 --0.804323 --0.920953 --0.973738 --0.936418 --0.905518 --0.717744 --0.616881 --0.785126 --0.782606 --0.680625 --0.739233 --0.708171 --0.640854 --0.813288 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_2.txt deleted file mode 100644 index 58ac16bef2..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.059236 --0.214718 --0.275017 --0.341253 --0.490676 --0.579139 --0.558691 --0.612236 --0.718408 --0.655757 --0.887580 --0.874683 --0.833466 --0.808127 --0.828123 --0.833990 --0.975800 --1.062405 --0.966725 --1.192190 --1.354320 --1.283661 --1.110772 --0.795835 --0.648779 --0.510435 --0.316072 --0.313505 --0.221812 --0.104936 --0.120453 --0.188875 --0.276769 --0.317026 --0.575582 --0.657667 --0.542465 --0.689421 --0.831931 --0.971260 --1.120014 --1.104033 --1.123718 --0.968373 --0.987011 --0.857594 --0.517499 --0.371248 --0.253880 --0.193457 --0.162254 --0.001019 -0.082934 -0.170110 -0.153126 -0.296120 -0.222728 -0.304483 -0.205958 -0.109107 -0.103474 -0.115069 -0.024892 --0.049858 --0.134896 --0.083989 --0.244890 --0.445814 --0.731166 --0.861888 --0.986474 --0.933604 --0.762998 --0.879739 --0.893096 --1.060842 --1.207642 --1.360912 --1.485835 --1.603737 --1.726102 --1.755124 --1.741578 --1.819057 --1.734395 --1.457985 --1.554534 --1.696621 --1.749765 --1.674743 --1.560913 --1.228126 --0.912762 --0.829894 --0.593973 --0.383174 --0.429968 --0.505235 --0.534181 --0.642708 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_fail.status b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_fail.status deleted file mode 100644 index 6842226365..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_fail.status +++ /dev/null @@ -1 +0,0 @@ -Deleted report step: 3 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_params.txt deleted file mode 100644 index f51328cc14..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-3/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.542054 -OFFSET:-0.936072 -PERSISTENCE:0.66513 -OCTAVES:59.6891 -PRIME_1:58.3958 -PRIME_2:51.6271 -PRIME_3:37.3286 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/aggregated.txt deleted file mode 100644 index 35536135e9..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 0.585905 -PERLIN_2 1.398056 -PERLIN_1 0.227632 -STATE Positive \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/parameters.txt deleted file mode 100644 index 43486a893a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.434448 -PERLIN_PARAM:OFFSET 0.831105 -PERLIN_PARAM:PERSISTENCE 0.630867 -PERLIN_PARAM:OCTAVES 8.00407 -PERLIN_PARAM:PRIME_1 85.4235 -PERLIN_PARAM:PRIME_2 21.3039 -PERLIN_PARAM:PRIME_3 104.858 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_2.txt deleted file mode 100644 index b747326d4e..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -1.398056 -1.370914 -1.363998 -1.279446 -1.232190 -1.280908 -1.103097 -1.044700 -1.071948 -1.061684 -1.094715 -0.964632 -0.831411 -0.781949 -0.814620 -0.849516 -0.851001 -0.765851 -0.758157 -0.773463 -0.753641 -0.789955 -0.752934 -0.828227 -0.915443 -0.973537 -1.081467 -1.241200 -1.241392 -1.257672 -1.377862 -1.470086 -1.421784 -1.325527 -1.150346 -1.051501 -1.044802 -1.106502 -1.157155 -1.178239 -1.131983 -1.091121 -1.099748 -1.022758 -0.922794 -1.005841 -1.071597 -1.179689 -1.248927 -1.203617 -1.238719 -1.303884 -1.370907 -1.578622 -1.711466 -1.711839 -1.668280 -1.577131 -1.546602 -1.622520 -1.688682 -1.788272 -1.882089 -1.796176 -1.789849 -1.824672 -1.596314 -1.354986 -1.209724 -1.109246 -0.923528 -0.922481 -0.911951 -0.973918 -1.090397 -1.192352 -1.060059 -0.993187 -1.014380 -0.913349 -0.932815 -0.882706 -0.835195 -0.874574 -0.888107 -0.876224 -0.749712 -0.614713 -0.449095 -0.520278 -0.614327 -0.737773 -0.860582 -0.969577 -1.155922 -1.219523 -1.274034 -1.070757 -0.993013 -0.832009 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_3.txt deleted file mode 100644 index c5dd1d518a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.585905 -0.452598 -0.261390 -0.099559 -0.008463 -0.090195 -0.020645 -0.032193 -0.098826 -0.167894 -0.384631 -0.408063 -0.383683 -0.343951 -0.379248 -0.446961 -0.428666 -0.448737 -0.598860 -0.866793 -1.106700 -1.241132 -1.243349 -1.200570 -1.168896 -1.114956 -1.024733 -1.054210 -1.020238 -1.038965 -1.117287 -1.162247 -1.101024 -1.127568 -1.144400 -1.180464 -1.249435 -1.298417 -1.447368 -1.686352 -1.737009 -1.763308 -1.821366 -1.709790 -1.553214 -1.506426 -1.360820 -1.279066 -1.279741 -1.183449 -1.062901 -0.861486 -0.677115 -0.670046 -0.624699 -0.557809 -0.499881 -0.413392 -0.369794 -0.411126 -0.420676 -0.401154 -0.397886 -0.236404 -0.172236 -0.286392 -0.241739 -0.216426 -0.242506 -0.276757 -0.218665 -0.312935 -0.345126 -0.458120 -0.609833 -0.806243 -0.893627 -0.994656 -1.162081 -1.148060 -1.166777 -1.176970 -1.258971 -1.433259 -1.522462 -1.549638 -1.469646 -1.375772 -1.233844 -1.290657 -1.317444 -1.262699 -1.170724 -1.002436 -0.948090 -0.944428 -0.984570 -0.910954 -0.945140 -0.749551 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_fail.status b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_fail.status deleted file mode 100644 index 46a71f4e16..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_fail.status +++ /dev/null @@ -1 +0,0 @@ -Deleted report step: 1 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_params.txt deleted file mode 100644 index 324cbda2ee..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.434448 -OFFSET:0.831105 -PERSISTENCE:0.630867 -OCTAVES:8.00407 -PRIME_1:85.4235 -PRIME_2:21.3039 -PRIME_3:104.858 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/realization.ok b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/realization.ok deleted file mode 100644 index a0aba9318a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-4/iter-0/realization.ok +++ /dev/null @@ -1 +0,0 @@ -OK \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/ERROR b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/ERROR deleted file mode 100644 index 48bc5b6354..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/ERROR +++ /dev/null @@ -1,8 +0,0 @@ - - - REALIZATION_FAIL - Could not find target_file:realization.ok - - - - diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/EXIT b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/EXIT deleted file mode 100644 index 48bc5b6354..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/EXIT +++ /dev/null @@ -1,8 +0,0 @@ - - - REALIZATION_FAIL - Could not find target_file:realization.ok - - - - diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/aggregated.txt deleted file mode 100644 index 72e58cbf64..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 0.638889 -PERLIN_2 1.451039 -PERLIN_1 0.280615 -STATE Positive \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/parameters.txt deleted file mode 100644 index 463f5c41d8..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.72828 -PERLIN_PARAM:OFFSET 0.48251 -PERLIN_PARAM:PERSISTENCE 0.878696 -PERLIN_PARAM:OCTAVES 62.5026 -PERLIN_PARAM:PRIME_1 10.3564 -PERLIN_PARAM:PRIME_2 34.9666 -PERLIN_PARAM:PRIME_3 46.2883 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_1.txt deleted file mode 100644 index 11da497a09..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.280615 -0.140016 -0.101814 --0.129046 -0.108540 -0.255758 --0.136433 -0.402995 -0.060006 -0.243033 -0.270699 -1.032076 --0.013904 --0.123877 -0.661223 -0.260982 -0.218027 -1.382060 -0.399264 -0.483361 -0.472825 --0.400746 -1.339330 -0.692467 -0.043042 -0.542935 --0.239154 -0.322095 -0.568886 --0.253825 -0.069002 -0.151587 --0.060719 -0.071557 -1.232762 -0.806173 -0.197592 -0.775339 -0.485706 --0.340968 -0.563185 --0.301442 --0.470657 -0.391865 -1.604934 -1.366571 -0.978296 -0.533236 -0.199409 -0.640021 -0.724001 -0.620437 --0.062286 -0.448127 -0.681424 -0.211811 -0.962468 -0.569284 -0.153403 -0.463251 -0.717336 -1.047732 -0.879313 -0.557671 -0.589243 -0.475895 -0.668305 -1.261389 -1.992548 -0.514705 -1.480108 -0.964709 -0.672593 -0.541782 -1.389203 -0.533862 -1.237538 -0.892042 -0.376384 -0.676731 -1.374955 -1.291646 -0.276911 -0.706050 -0.032507 -1.074094 -0.914922 -1.747032 -2.087744 -1.287205 -1.735100 -1.305039 -1.283753 -0.989592 -0.686460 -0.373096 -0.309114 -0.349820 -0.814016 -0.915557 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_3.txt deleted file mode 100644 index 4b5a132c2c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.638889 -0.410195 -0.219070 --0.168964 --0.060804 -0.091251 --0.310748 -0.238941 --0.042062 -0.155990 -0.259406 -1.020776 --0.110433 --0.305635 -0.479458 -0.154968 -0.127038 -1.333433 -0.420498 -0.615022 -0.762375 -0.010082 -1.772197 -1.106807 -0.463132 -0.968775 -0.168158 -0.688947 -0.994515 -0.267193 -0.637949 -0.790394 -0.620450 -0.793639 -2.004706 -1.552222 -0.884301 -1.340207 -0.962178 -0.185367 -1.130433 -0.350189 -0.239143 -0.994664 -2.052722 -1.659346 -1.164070 -0.714679 -0.402736 -0.802732 -0.819881 -0.546816 --0.353419 -0.027870 -0.128278 --0.371555 -0.426874 --0.024508 --0.541415 --0.345851 --0.187719 -0.083337 --0.110978 --0.445258 --0.435272 --0.488676 --0.192211 -0.456083 -1.223572 --0.254552 -0.677673 -0.240441 -0.034157 --0.047433 -0.789765 --0.187141 -0.479641 -0.107975 --0.414972 --0.073069 -0.622598 -0.635844 --0.186447 -0.448791 --0.089311 -1.014494 -0.884645 -1.732422 -2.096466 -1.319259 -1.782821 -1.319583 -1.298015 -0.977683 -0.667262 -0.395453 -0.328915 -0.392952 -0.872816 -1.003679 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_fail.status b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_fail.status deleted file mode 100644 index 2494f445e5..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_fail.status +++ /dev/null @@ -1 +0,0 @@ -Deleted report step: 2 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_params.txt deleted file mode 100644 index 6ffe51857b..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-5/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.72828 -OFFSET:0.48251 -PERSISTENCE:0.878696 -OCTAVES:62.5026 -PRIME_1:10.3564 -PRIME_2:34.9666 -PRIME_3:46.2883 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/aggregated.txt deleted file mode 100644 index 07f12f2a08..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 0.870550 -PERLIN_2 1.682701 -PERLIN_1 0.512277 -STATE Positive \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/parameters.txt deleted file mode 100644 index 04dc1adb80..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.105108 -PERLIN_PARAM:OFFSET 0.913379 -PERLIN_PARAM:PERSISTENCE 0.962764 -PERLIN_PARAM:OCTAVES 54.2875 -PERLIN_PARAM:PRIME_1 12.1353 -PERLIN_PARAM:PRIME_2 108.225 -PERLIN_PARAM:PRIME_3 58.2668 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_1.txt deleted file mode 100644 index 309c31a80b..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.512277 -0.536404 -0.520619 -0.520234 -0.561383 -0.536841 -0.593527 -0.431159 -0.579716 -0.595432 -0.613877 -0.832759 -0.851509 -0.830369 -0.752398 -0.701988 -0.854139 -0.813144 -0.848016 -0.675839 -0.919173 -1.078956 -1.165071 -1.045397 -1.099168 -1.049976 -0.934854 -0.813458 -0.777245 -0.747191 -0.680688 -0.492784 -0.756629 -0.639112 -0.677362 -0.560299 -0.783620 -0.757035 -0.781494 -1.092201 -1.102767 -1.052654 -1.207713 -1.115009 -1.380213 -1.620005 -1.355587 -1.358326 -1.365758 -1.049275 -1.264629 -1.182026 -1.240226 -1.329804 -1.210895 -1.340758 -1.160254 -1.099240 -1.243394 -1.267952 -1.359115 -1.457122 -1.219766 -1.225781 -1.439935 -1.367284 -1.242810 -1.155161 -1.278395 -1.180081 -1.125988 -1.131542 -1.239492 -1.086901 -1.273243 -1.532824 -1.482385 -1.810195 -1.887451 -1.774089 -1.870171 -1.843973 -1.696110 -1.740468 -1.791604 -1.614504 -1.582554 -1.758357 -1.634232 -1.684106 -1.786180 -1.619646 -1.484936 -1.430948 -1.379634 -1.352505 -1.382218 -1.487943 -1.057155 -0.971585 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_2.txt deleted file mode 100644 index 463edcab27..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -1.682701 -1.724900 -1.740484 -1.660204 -1.615765 -1.563048 -1.501665 -1.279611 -1.450770 -1.402179 -1.312668 -1.378029 -1.202709 -1.086610 -1.006006 -0.998528 -1.185484 -1.081631 -1.028546 -0.714171 -0.855664 -1.038607 -1.107524 -1.087393 -1.265806 -1.334397 -1.398900 -1.367299 -1.424028 -1.486916 -1.510209 -1.439430 -1.758558 -1.559152 -1.455253 -1.177386 -1.265695 -1.129987 -0.967754 -1.110422 -1.064988 -1.032099 -1.195895 -1.030776 -1.197580 -1.412196 -1.252139 -1.440393 -1.538272 -1.232153 -1.536327 -1.550802 -1.642885 -1.818122 -1.744516 -1.911422 -1.793059 -1.669187 -1.725384 -1.670243 -1.722066 -1.879845 -1.713679 -1.782625 -2.033032 -1.940992 -1.736869 -1.488416 -1.476638 -1.243313 -1.028416 -1.016820 -1.167881 -1.013483 -1.154370 -1.197929 -0.890921 -1.024660 -0.948394 -0.789577 -0.883852 -0.893907 -0.808975 -0.924524 -1.035431 -0.881490 -0.832342 -0.982689 -0.858205 -0.945780 -1.130784 -1.109264 -1.189055 -1.386180 -1.568267 -1.649957 -1.691483 -1.690880 -1.163828 -1.142166 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_fail.status b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_fail.status deleted file mode 100644 index 6842226365..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_fail.status +++ /dev/null @@ -1 +0,0 @@ -Deleted report step: 3 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_params.txt deleted file mode 100644 index 29d18ec899..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.105108 -OFFSET:0.913379 -PERSISTENCE:0.962764 -OCTAVES:54.2875 -PRIME_1:12.1353 -PRIME_2:108.225 -PRIME_3:58.2668 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/realization.ok b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/realization.ok deleted file mode 100644 index a0aba9318a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-6/iter-0/realization.ok +++ /dev/null @@ -1 +0,0 @@ -OK \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/ERROR b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/ERROR deleted file mode 100644 index 1eb5bf0114..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/ERROR +++ /dev/null @@ -1,8 +0,0 @@ - - - REALIZATION_FAIL - Could not find target_file:realization.ok - - - - diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/EXIT b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/EXIT deleted file mode 100644 index 1eb5bf0114..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/EXIT +++ /dev/null @@ -1,8 +0,0 @@ - - - REALIZATION_FAIL - Could not find target_file:realization.ok - - - - diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/aggregated.txt deleted file mode 100644 index 6b3b4204d7..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 -0.223092 -PERLIN_2 0.589059 -PERLIN_1 -0.581365 -STATE Negative \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/parameters.txt deleted file mode 100644 index 0fec4832fd..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.100905 -PERLIN_PARAM:OFFSET 0.749785 -PERLIN_PARAM:PERSISTENCE 0.960394 -PERLIN_PARAM:OCTAVES 27.0099 -PERLIN_PARAM:PRIME_1 40.6138 -PERLIN_PARAM:PRIME_2 61.0175 -PERLIN_PARAM:PRIME_3 87.8034 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_1.txt deleted file mode 100644 index f4ab414309..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.581365 -0.196529 -0.251092 -0.129792 -0.331063 -0.243506 -0.276892 -0.080451 -0.396119 -0.359775 -0.367571 -0.375403 -0.583877 -0.600213 -0.433206 -0.667000 -0.730207 -0.597004 -0.652034 -0.663611 -0.746119 -0.692967 -0.730701 -0.876335 -0.892405 -0.727578 -0.723739 -0.564331 -0.468088 -0.488808 -0.664805 -0.660028 -0.630792 -0.524399 -0.474312 -0.443139 -0.580488 -0.481039 -0.800572 -1.001564 -0.911524 -0.901357 -0.788429 -0.858484 -0.905262 -1.091118 -1.153703 -1.092191 -1.125297 -0.931559 -0.887913 -0.949225 -1.000548 -1.157858 -0.916321 -0.916039 -0.825100 -0.963569 -0.946300 -1.325529 -1.317807 -1.051895 -1.371837 -1.120878 -1.290153 -1.132642 -1.106899 -0.951717 -1.053646 -1.097485 -0.993622 -1.071263 -1.003207 -1.060272 -0.945896 -1.081059 -1.483716 -1.639907 -1.778137 -1.743444 -1.658571 -1.670091 -1.528567 -1.360096 -1.348333 -1.247859 -1.311556 -1.223970 -1.139654 -1.236625 -1.220851 -1.388255 -1.244178 -1.146154 -1.093360 -0.984612 -1.125281 -1.104519 -0.927790 -0.740832 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_2.txt deleted file mode 100644 index 3b2079e9c1..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.589059 -1.385024 -1.470957 -1.269762 -1.385446 -1.269712 -1.185030 -0.928904 -1.267172 -1.166521 -1.066362 -0.920673 -0.935076 -0.856454 -0.686814 -0.963540 -1.061552 -0.865491 -0.832564 -0.701943 -0.682610 -0.652618 -0.673153 -0.918331 -1.059042 -1.011999 -1.187784 -1.118172 -1.114871 -1.228534 -1.494326 -1.606674 -1.632721 -1.444440 -1.252203 -1.060226 -1.062564 -0.853991 -0.986832 -1.019786 -0.873746 -0.880802 -0.776611 -0.774251 -0.722629 -0.883309 -1.050254 -1.174258 -1.297810 -1.114437 -1.159611 -1.318001 -1.403207 -1.646177 -1.449942 -1.486702 -1.457905 -1.533516 -1.428289 -1.727821 -1.680758 -1.474617 -1.865750 -1.677722 -1.883250 -1.706351 -1.600958 -1.284972 -1.251889 -1.160717 -0.896049 -0.956541 -0.931596 -0.986854 -0.827023 -0.746164 -0.892252 -0.854372 -0.839080 -0.758932 -0.672252 -0.720025 -0.641433 -0.544152 -0.592160 -0.514846 -0.561344 -0.448302 -0.363627 -0.498299 -0.565455 -0.877873 -0.948297 -1.101386 -1.281993 -1.282064 -1.434546 -1.307456 -1.034463 -0.911412 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_3.txt deleted file mode 100644 index 520a51e79f..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.223092 -0.466707 -0.368349 -0.089874 -0.161719 -0.078999 -0.102578 --0.083603 -0.294051 -0.272732 -0.356278 -0.364104 -0.487348 -0.418455 -0.251441 -0.560986 -0.639218 -0.548377 -0.673267 -0.795272 -1.035669 -1.103795 -1.163568 -1.290674 -1.312494 -1.153418 -1.131051 -0.931183 -0.893717 -1.009827 -1.233752 -1.298835 -1.311961 -1.246482 -1.246256 -1.189188 -1.267197 -1.045907 -1.277045 -1.527899 -1.478772 -1.552988 -1.498229 -1.461283 -1.353050 -1.383894 -1.339477 -1.273635 -1.328624 -1.094269 -0.983792 -0.875603 -0.709414 -0.737601 -0.363175 -0.332673 -0.289505 -0.369777 -0.251481 -0.516427 -0.412752 -0.087499 -0.381547 -0.117950 -0.265638 -0.168071 -0.246383 -0.146412 -0.284670 -0.328228 -0.191186 -0.346995 -0.364771 -0.471056 -0.346459 -0.360055 -0.725820 -0.855841 -0.986781 -0.993643 -0.906214 -1.014289 -1.065209 -1.102837 -1.226516 -1.188260 -1.281279 -1.209360 -1.148376 -1.268678 -1.268572 -1.402798 -1.258439 -1.134246 -1.074161 -1.006970 -1.145082 -1.147652 -0.986590 -0.828954 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_fail.status b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_fail.status deleted file mode 100644 index 6ac0122a28..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_fail.status +++ /dev/null @@ -1 +0,0 @@ -Did nothing! \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_params.txt deleted file mode 100644 index 4455122772..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-7/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.100905 -OFFSET:0.749785 -PERSISTENCE:0.960394 -OCTAVES:27.0099 -PRIME_1:40.6138 -PRIME_2:61.0175 -PRIME_3:87.8034 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/aggregated.txt deleted file mode 100644 index 244709c651..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 -0.917785 -PERLIN_2 -0.105634 -PERLIN_1 -1.276058 -STATE Negative \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/parameters.txt deleted file mode 100644 index 59ba741905..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.494279 -PERLIN_PARAM:OFFSET -0.526799 -PERLIN_PARAM:PERSISTENCE 0.0911083 -PERLIN_PARAM:OCTAVES 43.0492 -PERLIN_PARAM:PRIME_1 123.299 -PERLIN_PARAM:PRIME_2 42.4258 -PERLIN_PARAM:PRIME_3 14.0702 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_1.txt deleted file mode 100644 index 6aa944dccf..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --1.276058 --1.289017 --1.314341 --1.306601 --1.296437 --1.293440 --1.259407 --1.266510 --1.294486 --1.261902 --1.202479 --1.080475 --0.954164 --0.885534 --0.858941 --0.894787 --0.919912 --0.916939 --0.886507 --0.799550 --0.721154 --0.650200 --0.537956 --0.483812 --0.489635 --0.525394 --0.546662 --0.527208 --0.534832 --0.533549 --0.538252 --0.584050 --0.611137 --0.630059 --0.650202 --0.616093 --0.568181 --0.463276 --0.334508 --0.259597 --0.221372 --0.259230 --0.279580 --0.244302 --0.207325 --0.170186 --0.177288 --0.240439 --0.278604 --0.325685 --0.411518 --0.447688 --0.438482 --0.430901 --0.426508 --0.473419 --0.523455 --0.492174 --0.429854 --0.320462 --0.242691 --0.226471 --0.221185 --0.262628 --0.292571 --0.326766 --0.377534 --0.383441 --0.373359 --0.364832 --0.330290 --0.341756 --0.378785 --0.325450 --0.201339 --0.014930 -0.131198 -0.218084 -0.307262 -0.331535 -0.323047 -0.275638 -0.204499 -0.189781 -0.216423 -0.234694 -0.244237 -0.196780 -0.140343 -0.139795 -0.132064 -0.149348 -0.135500 -0.067575 --0.002818 --0.038351 --0.033175 --0.039802 --0.104931 --0.282153 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_2.txt deleted file mode 100644 index 9527f5ea7a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.105634 --0.100522 --0.094477 --0.166631 --0.242055 --0.267233 --0.351269 --0.418058 --0.423433 --0.455156 --0.503687 --0.535205 --0.602964 --0.629293 --0.605334 --0.598246 --0.588567 --0.648452 --0.705977 --0.761218 --0.784663 --0.690549 --0.595504 --0.441816 --0.322998 --0.240974 --0.082616 -0.026633 -0.111952 -0.206176 -0.291269 -0.362596 -0.390792 -0.289982 -0.127689 -0.000994 --0.086106 --0.090324 --0.148248 --0.241375 --0.259151 --0.279786 --0.291397 --0.328535 --0.389958 --0.377995 --0.280737 --0.158372 --0.106091 --0.142807 --0.139820 --0.078912 --0.035823 -0.057418 -0.107112 -0.097244 -0.109350 -0.077772 -0.052136 -0.081830 -0.120261 -0.196251 -0.272728 -0.294216 -0.300526 -0.246943 -0.116525 --0.050187 --0.175115 --0.301600 --0.427862 --0.456478 --0.450396 --0.398868 --0.320212 --0.349825 --0.460267 --0.567451 --0.631795 --0.652977 --0.663271 --0.674428 --0.682635 --0.626163 --0.539750 --0.498320 --0.505975 --0.578888 --0.635684 --0.598530 --0.523332 --0.361034 --0.160381 -0.022807 -0.185816 -0.259100 -0.276090 -0.163135 -0.001742 --0.111572 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_3.txt deleted file mode 100644 index cd80bec7c2..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.917785 --1.018838 --1.197085 --1.346518 --1.465782 --1.457947 --1.433721 --1.430564 --1.396554 --1.348945 --1.213771 --1.091774 --1.050692 --1.067291 --1.040706 --1.000801 --1.010901 --0.965566 --0.865274 --0.667889 --0.431604 --0.239372 --0.105089 --0.069473 --0.069545 --0.099554 --0.139350 --0.160356 --0.109202 --0.012531 -0.030695 -0.054757 -0.070031 -0.092023 -0.121743 -0.129957 -0.118527 -0.101591 -0.141964 -0.266738 -0.345876 -0.392401 -0.430221 -0.358497 -0.240463 -0.122590 -0.008486 --0.058995 --0.075277 --0.162975 --0.315639 --0.521310 --0.729615 --0.851158 --0.979655 --1.056785 --1.059049 --1.085967 --1.124672 --1.129564 --1.147745 --1.190867 --1.211475 --1.265556 --1.317086 --1.291337 --1.238050 --1.188747 --1.142334 --1.134089 --1.132725 --1.066024 --1.017221 --0.914666 --0.800777 --0.735933 --0.626698 --0.565983 --0.484094 --0.418266 --0.429310 --0.380164 --0.258859 --0.067478 -0.094606 -0.175094 -0.213959 -0.182170 -0.149065 -0.171849 -0.179785 -0.163891 -0.149761 -0.055666 --0.022016 --0.015994 --0.013374 -0.003331 --0.046131 --0.194030 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_fail.status b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_fail.status deleted file mode 100644 index 6ac0122a28..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_fail.status +++ /dev/null @@ -1 +0,0 @@ -Did nothing! \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_params.txt deleted file mode 100644 index 219b62155c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.494279 -OFFSET:-0.526799 -PERSISTENCE:0.0911083 -OCTAVES:43.0492 -PRIME_1:123.299 -PRIME_2:42.4258 -PRIME_3:14.0702 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/realization.ok b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/realization.ok deleted file mode 100644 index a0aba9318a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-8/iter-0/realization.ok +++ /dev/null @@ -1 +0,0 @@ -OK \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/aggregated.txt deleted file mode 100644 index 48b8531624..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 0.220371 -PERLIN_2 1.032522 -PERLIN_1 -0.137903 -STATE Positive \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/parameters.txt deleted file mode 100644 index 2e4f0f7b04..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.971949 -PERLIN_PARAM:OFFSET 0.568165 -PERLIN_PARAM:PERSISTENCE 0.332226 -PERLIN_PARAM:OCTAVES 8.48231 -PERLIN_PARAM:PRIME_1 106.04 -PERLIN_PARAM:PRIME_2 17.4819 -PERLIN_PARAM:PRIME_3 56.9629 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_1.txt deleted file mode 100644 index 36798a3f53..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.137903 --0.157851 --0.192276 --0.201670 --0.192839 --0.193214 --0.209423 --0.243628 --0.261796 --0.213269 --0.207591 --0.203993 --0.142490 --0.122206 --0.157129 --0.193732 --0.206432 --0.177612 --0.114381 --0.050740 --0.070342 --0.154469 --0.151716 --0.137877 --0.155888 --0.199095 --0.226091 --0.254674 --0.326284 --0.337833 --0.312344 --0.317023 --0.346853 --0.332528 --0.238504 --0.042655 -0.146262 -0.376535 -0.617211 -0.752626 -0.797129 -0.714055 -0.660213 -0.707589 -0.786058 -0.902157 -0.982988 -0.972517 -0.950945 -0.917937 -0.833802 -0.834170 -0.874761 -0.874663 -0.835114 -0.714452 -0.615202 -0.641686 -0.698232 -0.833272 -0.978281 -1.070483 -1.118218 -1.061277 -1.031902 -0.998036 -0.965574 -1.010296 -1.079127 -1.148032 -1.260956 -1.285149 -1.247059 -1.290888 -1.424147 -1.629905 -1.764537 -1.819917 -1.898802 -1.893787 -1.855403 -1.728917 -1.536779 -1.375375 -1.281240 -1.209446 -1.131790 -1.009449 -0.933443 -0.938227 -0.970148 -1.049769 -1.076923 -1.035402 -0.981504 -0.949433 -0.958861 -0.977078 -0.958006 -0.802606 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_2.txt deleted file mode 100644 index ba557199f4..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -1.032522 -1.030645 -1.027589 -0.938300 -0.861544 -0.832993 -0.698715 -0.604825 -0.609257 -0.593477 -0.491201 -0.341277 -0.208709 -0.134035 -0.096478 -0.102808 -0.124913 -0.090875 -0.066149 --0.012408 --0.133850 --0.194818 --0.209263 --0.095881 -0.010749 -0.085326 -0.237955 -0.299167 -0.320499 -0.401893 -0.517178 -0.629623 -0.655076 -0.587512 -0.539387 -0.574432 -0.628337 -0.749487 -0.803470 -0.770847 -0.759350 -0.693500 -0.648396 -0.623356 -0.603426 -0.694348 -0.879540 -1.054584 -1.123458 -1.100816 -1.105500 -1.202947 -1.277420 -1.362982 -1.368734 -1.285116 -1.248007 -1.211633 -1.180222 -1.235564 -1.341232 -1.493206 -1.612131 -1.618121 -1.625000 -1.571745 -1.459633 -1.343551 -1.277370 -1.211264 -1.163383 -1.170426 -1.175448 -1.217470 -1.305274 -1.295011 -1.173072 -1.034382 -0.959745 -0.909275 -0.869084 -0.778851 -0.649645 -0.559430 -0.525067 -0.476432 -0.381578 -0.233781 -0.157416 -0.199901 -0.314752 -0.539386 -0.781042 -0.990634 -1.170137 -1.246885 -1.268126 -1.180015 -1.064679 -0.973186 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_3.txt deleted file mode 100644 index 2bb0cef781..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.220371 -0.112328 --0.075019 --0.241588 --0.362184 --0.357721 --0.383737 --0.407682 --0.363864 --0.300312 --0.218883 --0.215292 --0.239019 --0.303964 --0.338894 --0.299746 --0.297421 --0.226239 --0.093147 -0.080922 -0.219209 -0.256359 -0.281152 -0.276463 -0.264202 -0.226745 -0.181221 -0.112178 -0.099345 -0.183186 -0.256603 -0.321784 -0.334316 -0.389554 -0.533441 -0.703395 -0.832970 -0.941402 -1.093683 -1.278960 -1.364377 -1.365686 -1.370013 -1.310389 -1.233846 -1.194933 -1.168762 -1.153961 -1.154271 -1.080648 -0.929681 -0.760549 -0.583628 -0.454406 -0.281967 -0.131086 -0.079608 -0.047894 -0.003413 -0.024170 -0.073226 -0.106088 -0.127928 -0.058349 -0.007387 -0.033465 -0.105058 -0.204991 -0.310151 -0.378775 -0.458521 -0.560881 -0.608623 -0.701672 -0.824709 -0.908902 -1.006640 -1.035850 -1.107446 -1.143986 -1.103046 -1.073115 -1.073421 -1.118115 -1.159422 -1.149846 -1.101513 -0.994839 -0.942165 -0.970280 -1.017869 -1.064312 -1.091185 -1.023493 -0.962306 -0.971791 -0.978662 -1.020211 -1.016806 -0.890728 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_fail.status b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_fail.status deleted file mode 100644 index 6ac0122a28..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_fail.status +++ /dev/null @@ -1 +0,0 @@ -Did nothing! \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_params.txt deleted file mode 100644 index c3e63c5f53..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.971949 -OFFSET:0.568165 -PERSISTENCE:0.332226 -OCTAVES:8.48231 -PRIME_1:106.04 -PRIME_2:17.4819 -PRIME_3:56.9629 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/realization.ok b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/realization.ok deleted file mode 100644 index a0aba9318a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/Run/realisation-9/iter-0/realization.ok +++ /dev/null @@ -1 +0,0 @@ -OK \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/current_case b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/current_case deleted file mode 100644 index 331d858ce9..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/current_case +++ /dev/null @@ -1 +0,0 @@ -default \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/0001/files/PERLIN_active b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/0001/files/PERLIN_active deleted file mode 100644 index c72400474a6698dd549e01355c6aaf9d3cd52a3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 OcmYdcU|?XR2LJ#)i~!02 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/0002/files/PERLIN_active b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/0002/files/PERLIN_active deleted file mode 100644 index c72400474a6698dd549e01355c6aaf9d3cd52a3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 OcmYdcU|?XR2LJ#)i~!02 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/0003/files/PERLIN_active b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/0003/files/PERLIN_active deleted file mode 100644 index c72400474a6698dd549e01355c6aaf9d3cd52a3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 OcmYdcU|?XR2LJ#)i~!02 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/ANALYZED.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/ANALYZED.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/ANALYZED.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/ANALYZED.index deleted file mode 100644 index 05ba4b90c1027104445f084cc63f28f4aeeca9d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|{%sDlZgB!2tj|ZUbll diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/ANALYZED.mnt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/ANALYZED.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/FORECAST.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/FORECAST.data_0 deleted file mode 100644 index efbe7f58b3c0f66dbe4731350fb34507d98489b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2816 zcma);c~p(-9>;g3ltY|EDr72-aW^OxeI=Dnr3@7!(VguF!5SB;A*L&RX}6d(XMgTHp1)&-;DXyVm>sp3nFB+1c6IO`y?ewx*k{ zEH*CJTu!H*m7>u=X+r5SJIbMXP-0M$pmZ`yVvZF1YsWtgmCR1RA+eqHk}b!- z81IVX5sAR8)6>FvB+705aFQ#Rh}6!6CFJu-=o4pI=28~P@yt1zu#QLeolEJccjb`5 zfXofCOEXBQV_C%{Yc@&WEGtkjZy?DQFV#KsbI7MnlSbC0W+KB!&&H>SNiM~oQ>%Mg zOc>kgz2=)Ejk zdqo14sh3(TI+G6h81}H6Q#qtRHx>D8;oz!Ux5_|#1=4oxxqA6#Io`FmcAa*4LB_TP z%AcEGM+#cSLL>b=l6aqgnBj1boc_v6z{oq2G;;^TkbM_!ey`UDD6&ZQ4sqGI*HxhL zm30Pe>aZw0s#!Uq1Q+~&);Xw92b?m8L#Nn4wF+Wm*`iyvY+QLA&@rgxj1YLf|Oph(Z zh~#N*xpW7XZqS}??Ocbw9;^Bv>$6dwuN`Z#FP((h|HFi9t_g>QM?5>7Z5-+6ez6cf>)Xc9X~e1b*JWO&x5GjDu;$6z9Z+gWH&d<85&-9?WsC}AEju?wWrBZ%3e2)QT zTQ@W7b~KOCTf-2`r{0pIx_x37Ta6qg_+WF*`B0KS-egQ8R9YU3N^x@8dgv z@eIs>+K)mqp^y{2?^S#b(O)=JX=KlWMC@SCfqR9ZFZIt|wylh8Z}n#wct_w^+>z^P zsv)E|YT2B$*?EXimpFX5sR`-F0-D{9c0wj|NP3_^1mDlm8rn{sn8b1rt`l;Rl0KZc zSf?4)TWzQ)5y8+P+3dJ_7uK9L^&7p`fiLR3C;e_>lqz~n@lLCO$Bv$RDKQ^GAM8(< zH|;%kxy$&I+dM>isN9?2&%unHUgl$^#h5;<7A_y{M;=QL-QM6*1uus1R{o4)eAW~t zs|)f8o1F6CJx)j7+^vaCQq{s2l2{?G{UNYY<(3)OO@aKIjae$L(>Q(C=Hz zxUSKJJ@$*LM`yMpe6p;!#?cy(`gpUBc0Q)|xGs<@Xu;kqo-SVtSZMju30J=YlEVzw zID*R_!y3q1PqiDRr91b4`|I~KSbdnQi39 z|8w}{t=6bQZ@q}@?~N?@Rl1Y7J35|pdL$qt4)zf@&$pAk?(b%ertnGW`OCOsz$Am& zsy|JT;t-pXxQn{9Mq=guUaHuzlz5J28F|$|CrtlybJkvLAoqXsJ-0o!hS=%Ue=8p< zCz3TTZ8GUCgqM2v&E^HQ;0Zf-Zu+$n*Qix%Y0N{4$x8L@msl7GQlOTYh1)~#M(g-& zcn$6k`zkBMnlt0R_4IdP)4>2Mtv&(RS`SM1?c;;y;gB-#ejVZuXUXNd6rnM*R(8~? z6=pkWD)E+le2SYYmk`kkUXj#wQ z2P#~qA39Ogi44aZQpeLpsGX#Ea-kX@A$~ehT6z?}{Ty-9t}b-zKb<)@fQz8f1H%HY z2#t;Ek6y}j!ZS{r-ls+JF{P}EKP&aa*9JsXylNS&X2Z^UijNwNhdUEPZ#X#fapLEMMYqh} z=6;z5-04w>`m&af@8u8N&Bb}U!9GLl29)OHCE3OaAawek47HfQ!j)>#*s#wK z&i|#8jZLk+8pM=?fA7P*Klo;0(lOVcDlGFca&!N)jIlC=Ph|Eh+cv^x_QT`_Nv-_p+4e%Qf}sI(qs)CRDRZ*V5Id)8r^;8D;6} Y>FMkIux#DDT)bV5AE1o?J-+k*FEBqTumAu6 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/FORECAST.index deleted file mode 100644 index b0e9ebe688916da99d2d4396d86b2c153c368c58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|=vjofitE7+8Rq3y1?;gM2*w^bGY37(#&nBn1Ku%nS_DK-wNiBPlb6 xDPsq#!lldzstjZb2q2rr2jn}ty9c?tJBGNr=o!G2f@}eT1|XIPVn-kb0RZs*7uo;- diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/PARAMETER.data_0 deleted file mode 100644 index a9c2968ca3402ebc560003b7aa05528f86d42587..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmWFy4Gk4wU|Pp+Jfu8;ECkEk2(v_I)54!E^QoVke7QJ%8A{>1m$JDZaIT74zynK0*iWndP5c3Vn3KzT?tXhwo=j*n{+A K0sk5PGXMb5=qB<2 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/PARAMETER.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_0/PARAMETER.index deleted file mode 100644 index d16822022a2e94844eb68e1fd933f5bb646dec6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmeZo6=GmyU|{%lDlZgBf!P8;I>0r^$I~x9z%j_tSIsVGt%76qZo zfb5G5OTq}jV7#)(7Lc_B0x=;8AWH{9gMm6QKRU;A=AW6~bH3-i_wGIKzIWgIyyxKH z;GjSvk?bu`SRb*~H_|sG{kV!m0zwMxOAdsG6iCQ}kSw9_3>oq&{>S$xH?4Kk>wo~J zXPh*S2jOXCt?YU}DC<>b&J+#6SDo28(J=#%$NpPG6}JayZLw{b#)gcKs+l{h`r-Qp zrqc363#bKiHq0HYfQfg2vIIi`@U7*NmaYd7IZ24Pe!>On-@M51LIxihS)xuzgm+!me!y zyVHWVm+KB;TZ4I-&+9r2{EMx-Ss5Fz<=6T9kI-Sp(J$pr({nI2mz$fO>jTkpVzE81 z4rK-%~Y}*XIC+9Gn6mg z@n?(T|s z#VhYbQNF=UU?C4Td#|}wdWnn0{tY_vkHpxnV9Ctt6=PqN@3y1nLY&vWCH4>!aqs<3 zN9qfazvN=#v7d{YYwR??yC}es9>a09-^6&sjwpD_B#J)|4Axbf#tqLuP`oSnxJgmr zhEak5w?sNwMte76?$5_}GM=QvgZdlab68bq-RL~d*Z&8syR>rBsqlgJrNV%6Bh+Z9 ztLBx{(IIYFi6TgW+@fjak>sFx`VRgxYe*TBY)w7Qy1(jNheQ!+YK^yPBo?V zy)f-XS84t31(bOQXAIr!hW5xH6|zDT#IEfqzqX?iWwSO@<&!EgwaR9;rua0rOx5K} zrTLhdky9hGsYjVz#(wuDLns;ITo0xWS}Xn;6QLQKS;DVEPpyPMMuLnJk$=(xz+k zE`@KA{7^abQP?D!x?O*BL~RUp1FZJyNvBbJNoTU1HI1s$JC|76)BnkH@(pSk^ivF; zzQGlWBpEYEx6xJiT^>cP_3Cv^#CpHbIlsO^nTy5+62@vlKknNjJIjpfMApU?F#3?| zc>9ObJxxgW8@tV zVK39Xw@ep>MFlATeZ4=+hs#nrMGUNY6lj_g)ht0~3-w m(KFCDGNPE8P(Ha#O^i$^l;2&po?hodd_p~msQ+mz`Tq?JFqSv~ diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/FORECAST.index deleted file mode 100644 index fb519c3d539f8fea2ace5a7cf60a09a18a126f9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 145 zcmeZo6=GmyU|=vjofitE7?^>W4~QMz-Gf}+9Yb7Q^bGV28A5@8fgPlPfuRA2<$>4< ph`E3`z%|In(@)PBs;mKI1Q38|X&`M6q>+>v!At`yLRAJ50sz?F5{>`> diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_1/PARAMETER.data_0 deleted file mode 100644 index 5e8b2f1b1759c6b45715180e8cb8e680780cbbec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmWFy4Gk4wU|Pp+Jfu8;I3iwl3et@L@m4 z{y)`oA70-ttW0r^$I~x9z%j_tSIPp+Jfu8;C6y+zOqw0r^$I~x9z%j_tSIPp+Jfu8;Db*FR0&IIc>lF zz2c2Cmi*oSGTp0)Y0EA9S8i_YmS?})Cv~siUVnAxeveiB_Em1@_HQ+q+PyOT;eL>Q KEZ{%Ge+B@_`6{0P diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/PARAMETER.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_3/PARAMETER.index deleted file mode 100644 index cd8301dcf3e0cd7570127bcbe58159bbc15c1005..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmeZo6=GmyU|{%lDlZgBf!P8;I>0r^$I~x9z%j_tSID@sC+=#CmW?B!b<-7^wlt1db*o!d4_Y^M z-*L6uXyew@x~h({$~rc?-+nXSAK&ckoB7SWW8S>Ke)F(cES47l0NA4Ktt_ln;i?*d zpV$EaBnt^zAeJ=&5LtM$U}F)U2ThBzr2zr`IvF&a)!9kEYBxYzq+g}g*2l(Q-&!$ zQ-wQE9mwf8bC<{W@g>f>)R)hAFcxn3C9P;WgIt!tFI4Htj6h zgDOCmFo-vz%F;;%V1I9fpR%ooY?tB5g*k7`J+u#btkOxL4sVDIN~vEL%#w`_y*>N# z0$+kpa_MVfzE=CG#^jqKj@xO$0a-jklD!o@V;FPgGf(lk*SaL4yhq6Nqq8>ri%q|0 zsVUUXynC)zf`SYM8H>iHW)zU-8S=tTCcP+E8!z%?_Q$0Tb`$Z>A3k|!s1D$b57qVb#J8grY^&v(qmns3&q2qGVg2}Q=q zK`Yj{T4CYQ$t(Q17RG|nYi|j1@mZfvn`XqLZ_I9Q$aOi7JFeVokPwqhIT*q>H=X2@ z+rsT$ihsEpS_;~GBw0-Z&aNimt3vgvBMunfu-NuDFj2a&u-*fySbk55+eIao1k)RJ z#zl{H3PXtVZfIIhX0P?~dBoIo#Ub#$d)L<>0txld^>u02{q2-3ArC&zEls4HQ<_)* za`F2Ocd)biAQ2Yi4NA&LtdEQk;h#x(OUgsBt#7!ULPF!ZDQrjS`y73b5D(HhQ#UQO z_~fX*-rQ4Q@m6Q|`#ahi!=?)(kAAi=dST(H80Hh>X<4*Wv)cK&jH5Og=i$c{m&a_> z{DFOb%WL;~oj7Fu3X%K^2?M!&k>n59J#0S;Ea8-y(i_|Dy8>pT-S28{(I*gf`i_2F zCTqk<&TW(nz5ece^!B-^afYPgq2s%|(B{I;f>&aB!>(<0bV|>{S_nsm->KpZbQ3UJ z*;+EkKKaYX@x~KUL#PDBH|WO&8csMc?R{wu{`w*Nz51ddmL&f+P5>tWmVW>1AL4KS zwEmBOtQN~ZmGLA8mVaCX7lCsS{j<b%m-!S|q55pSp`w0~xMcWkxm$_zyVamELY_1E-tra&_1q7<=_Onsi z4b}BqNxg&${(#5ZsUHV@Q?+)fXU-eXDBh)-gkzgxgWhneH#4>#)HHk=C^*#3&4CzS z`}tZ*6b1C8Bda?Y4BdHqlvl15?~H5d=zQ+VKDPM*y9ig|b&5IT|CtVP%P$=Es6_WJ zUC){S4!HOWCNMaSGXk+Bf49G?GZVw#ux4NKelOnv>_CA}C2b^qd7P%v3e`0#>a?Z- z`+SgFb5(K1o6QIQaG-Tl_?{hS+;Ad8)Ds$a%+*KYtrE+=ykZE+xmBpB7hvP+%TXD5 zAkiGbQKE_a$W%nQ?@fYrm_fky=W!wn0lf*`LL19^!;KoT{WkGE3G%r4=<-~iHvOt2 z&WOmvK+PQ+-SX~%k+z}VZc2gHC_tWWj!CgOgRKtJ_`HY8nd9f;wO7IdCT;z|qhkcG z57Mjbbkm6}JeFjt!ri8{LY_{mssAo<4P^F25O6tp|>PliX@*C{mDGys5#t0EObVkH=eU^s6~I+u**lJ?FnUca1R1 zQrioOW&=%2ORar;M5{gIuf<8+uuCFe(P?wGTUKdw0*=S?h0<7L zCqR2xB!!n@ShHW$m=6Jwv7adg7uoQ^Nip_eLXGy`rn*QTvsP>{PbIV(m3UecZbzBijkN2={Xhk0+60t7?f|WhSG#mC=Zr{( zTs;;X3dvy$dW!8VaRSq74?Dn1)Iza;Yaf7R-+%lQV67OLnc1Vwj2zJ>s%n2a$ZB0+ z@!ucF!OFQ=sHtjdYwDW4~QMz-Gf}+9Yb7Q^bGV&7(#)7fgPlPfuRA2<$>4% rh`E3`z%|In(@)O`rVJPp+Jfu8;EDV^okDser5lW zyX{8u%-`&}h0dSkIe5i>>yNx85pAFMuP|)i)I9HweN?u_^`jTx?XTEka+dY)TYHdx KEZ{%Ge+B@$)+)XL diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/PARAMETER.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_4/PARAMETER.index deleted file mode 100644 index 8ebbf01df8b2c5ac34b289c5d87dc4069f64e4cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmeZo6=GmyU|{%lDlZgBf!P8;I>0r^$I~x9z%j_tSIPp+Jfu8;C!8@$|i)^}wEq z`O77iZBOj$5`=@pXMVDuv|LhCam#;u^Ny|B_XED|FP?8vc~;`_{v*?lHf8Hx+Yi!@ K1^j3D&j0`!87L0r^$I~x9z%j_tSIQ%{EH`7hMz*q~Omz{WBv~#M<{Ocv#nzQA zqKFs@UAeZ%2$5xGFf(Q>ckVs+p7Z_joqNCMoZmU`^FHtUynnpscOF+)S64v<0^wxs z?0`O@p{=2hxWi)uoc&k}rNU}a4SAX*eM%c8s zG0f{krrQfI+Rbdw_m#(&otzunTx~=Nwlf1JrVVxr&bC%pxFx(*7Q;fKAAhQ8p-?FBzm4w z4#|gv&VO8=>9ZYucIubjNwLA32LsiN^mEfA5*=_4-rE-MeIIEU5pClCiTEbeK1^e0 z_-OI+Ci9`msjni~=+4JPa|h?2HK~{szKf5Pr%MHwp0PvnS=kB)FcK$!4k{;Cm*2S8 z_3AcJ`f8ee#(L3*2?cRWb1ODJdS{xr;jMLNXNd9+c}mIl{;5(&h1&T>y$w9lD3ry@ z4N?>wEw3vXwkyQ<_BBr{zy2w?d3J->nJEzvJ>KK2ShYk*DZ(ao;x1RD<1tYyGIMda zP~sG2dWwi+5(;z!dNCqr@|341?JolohWtrEOMbwehMiw zdbx_a)+&liOF8X5guYavI&K zY>JkQ|4-TdGYh*@CSH@Z$QgnWUcUA*dj~V*{R=QnhKUQGls($jJ;#f7=SqgGx%ckd z(qB1u{X<>%`pGQ$jpj5$g$th@DlqZGF>YsX9$ucx-1epDZR7R+{Z?!Dg6Wo~EqMQi zJmH1@JdbZ=WJ%&2My@+*s6A^woBHvh)R^j#vseA3UQk*>J1?3xSKW0`zc;VoC^RC) z!U|a~Smlou^KlD5+alERZLX*`*?d#Uu6i&@HV)1>7dqkcsmi*ef8H?9L4a6c^tSJG zd~0CaBVLXs|6lANb`Tu>{@XvDKmCLM;omM!S3H4BfqQauLM7NY&om)9TweJ#&Zp8=YB z$H66x4ws}=RI3r|kix%%3KXV8a>WSA-fR^n<%SQx_M<|(jYn&)3FdhFZD(dDbStHlniO0Lg^3h zb?G=N2x10EFU{8=TT0_;wZ}T7Zs8bTeCe=OmbMV}c^wLaQgQ~m=rHaVdp?lFfQX&U z`F>R`QR}vK`PX>)|g&Nq`;(3S&tuT6=;0-H}=F*pgs;) zf>vDx*>b~=p7-g%^)h^}jeiZ|bUJU02r=Nx!w%VY0uvmc1&htrt-`e*`iMQ*ObAsH zXp`(`f^Vo|mj#*ywR$L--O^hSn!TQ%GS7yF3iV@}IopuX=}?5N-UPzU*mGOYS@7sd zzqwjI8xk3=jZTd$K#wu^=A^Mfr@PBzc<(m6!M}TI9Kr@<;ww^N(kA@Wv1MCoi7=OI zCp`G~o*n39@f|WCvEj#<3j4Hv26)DPKJ55_0b64G)CgZzL1B5p)t~b}5;a)i87m6p zEp%@_tfImAp!uqi0R`fk-6|aLG%%RL=GGrx1$$%C>(GQnaBy@dbKxk^{9V1bna46b zPnX=(x0(kxl+#wC-6Gt!cO50?EyBbufm`2A&%?=9q3>&Qmf*Qbv5Z0{1(Ns;uOHT1 zgnUv_b!yQ9m_!!qYDKPqcsRdn@TG5XqxDe8pye{mg;&t4rD=eae3GBqN(FHjR0@`F z6|%nKBzn~8aOkwn!2;`Xk{C jOG6z4E$u%mdfGZV1_pm5PGJ{W4~QMz-Gf}+9Yb7Q^bGXO7(#)7fgPlPfuRA2<$>4% qh`E3`z%|In(@)O`s;mKI1Q38|X&`M6q>+>v!b}4zLMXFPp+Jfu8;CVqH(9)PU^x)$ zGgGA|>$g33YyAg<@;~+yPsHWbC)pvTxC-44Xf0vDq!KHTBevp1F J;6KBE1^~ZWCL90& diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/PARAMETER.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/PARAMETER.index deleted file mode 100644 index a3ec21810e91515fb248373beeca938e7d346aba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmeZo6=GmyU|{%lDlZgBf!P8;I>0r^$I~x9z%j_tSIVKng&h0f-fW*ae6| F006Dk3KakV diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/PARAMETER.mnt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/PARAMETER.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/STATIC.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/STATIC.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/STATIC.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/STATIC.index deleted file mode 100644 index 05ba4b90c1027104445f084cc63f28f4aeeca9d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|{%sDlZgB!2tj|ZUbll diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/STATIC.mnt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_6/STATIC.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/ANALYZED.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/ANALYZED.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/ANALYZED.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/ANALYZED.index deleted file mode 100644 index 05ba4b90c1027104445f084cc63f28f4aeeca9d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|{%sDlZgB!2tj|ZUbll diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/ANALYZED.mnt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/ANALYZED.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/FORECAST.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/FORECAST.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/FORECAST.index deleted file mode 100644 index 05ba4b90c1027104445f084cc63f28f4aeeca9d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|{%sDlZgB!2tj|ZUbll diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/PARAMETER.data_0 deleted file mode 100644 index 57a1b2511a061877774d7d14d817553d3e1d4965..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmWFy4Gk4wU|Pp+Jfu8;CjfE-%X5%5h+i ztnSi{sh{kZt(uV1!Su)8Lp0N2v;LX=56u=#wES^*|NAvcTW?CN+|S#Q5m5R2zCB1k K7Vw|pKLY?O4=85< diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/PARAMETER.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_7/PARAMETER.index deleted file mode 100644 index 51cada30a8b9d6bad6095c34667d67da0a6f07f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmeZo6=GmyU|{%lDlZgBf!P8;I>0r^$I~x9z%j_tSI8^m;&UtAx8f`X(LfNNlVyM4Y zMNMTB#g|H<5TRsh+-O1%#a$>zp{5CSE_#|Awdb>A)zX?=R{iQk&lDeqjjNmU$M7?!QMI&Dmh+ z#4rL<)_R7T4@2#4#PAN=_qZ4ItnY2aTilROyOAzEfUt{`n@`rW@nVwZ`$4l0pB${B z%E!CmAMkaSidhfp&T^$^H1=ZN+lza3F7|;ZS#Heg?!|hus44Sheb_v6vsH^!A1In~ z+pV?w@NIcP&-xJ{dR^s22n#MTJRf%@HVT|y9rF;*Q+}-K(abCslGBogf>io(&OztU zzN9Y9oG!U7{BR4t$4l3?E1Bi>7|>eYlgOaMSAx$GV>0leVmQ*+tR1sQGs1?F zI&n7kT>S#cPTZExtm?bf0ok7J4TF0+;Qz}ljZ22z2zk0SV`X74?&@5ytGLvIh|5%~ z9KQ~PE^wK1+K+)j1JOs9Bpcu}gSb<^)Iy8?WP7!7Ev~T&Q#tjGF!NW<@_yBXkTad! z+_wy^$;e*P zqKJf#Pd|9uFrCPn_HQnq?}GfaAhCk`4={tfVE4Yy_wc=Uyzj7G0+>o>;>DdgaGU7z zsF7%b^<-hYkd}WbQ!$#i?~usSGqQBadk_>k(ou=VhYs0#RE&9eko2MXW2b`}>pgh|HSkgx?*iiD()v zS0SN^=S%r+?Ay5 zLD|>m-lM9$sJL`l?x%o$%;z*s{9?{V?Cml8Rf;Uc3!`W`dV$!dmMSuB=v3yL*<39} z4!kIM5=AG?|e2m^T_cRM0!NnSMd9cKh$fqskk zKO4e3&)`CfgB)B;)(}Q$2X0MO_2fUO$B$OZ?Mnx8;NmR^n5<04uTSn=$f!$4QuMlU z+Y7HSW?&hxskI27nmXcw14<#`lzc5kkPD{1k7avG5G>5@hWok2k;?5JGndXvBm9a? z%^Sn%&RJ3{&WymP4v)?ppLJ7nA(s zN!zuh=p;)?c45o%RuY)&HGlE4*QCm7M@oKR2cc#@c8=k-lCAtxOrMH+V)8wGP{JNW z)U*15%%RJ~$UrA6QsW847p?TM(#=4GFj{RoOYw{oF?3v=0jke(<6ocjLg~C`$TZ6V z%r(i%c&a^wtmr-NG|LZI?P2Q>ImktJb#3nZe|?fLkyM39(81V}fglvPTNL70_%-j^c4mT5*;#2ff< z@S)z45#wVpUrm&vH;U)totHPuk78LBha~(k`e)uC!NWI9f_8Bcee`xbZ|5-LP8lxv z821*=etp&@*9Xx0wSIh1oDCPA{h`36{g|h4-Pvif8;z|+Mct+C_#k&CsquUVJUuJy zqfD6?j-i{$hczN`uKJ|*u5_5#O*34)DVx*{bPjtRDJS<*+SZCV)Q}~g6tgXUt{@Yd zUtZswS3*i!k8$Lu%1C1SLzWt~f=CYCusZaql;}N)GO<-IAw?lmB09clMDwfw*1^AF z0BHw;1|XIPVrL*mGSLX83}^xfAe)G!%n)WVL=}oMkPrY* CQy2UI diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/PARAMETER.data_0 deleted file mode 100644 index 703bfe7edb8e6df398dd0528e783368e562d1a85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmWFy4Gk4wU|Pp+Jfu8$`Uiar5@a!}~99 zed+$~^RxYjnCBhpa{IQwJ#R~$%a+^r`{r?#pY;A`zqhi6!@A)1{{F%@*SGh5-Vf4> K1^j3D&j0|we=cwU diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/PARAMETER.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_8/PARAMETER.index deleted file mode 100644 index 21f092b0c6d14a5629a7ca2b798455a3a48808d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 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 O7ra|m_}^ok|33hPBsPNp diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/FORECAST.index deleted file mode 100644 index fd35646b637862890bfb99084f9f502ec04ada21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|=vjofitE7+8Rq3y1?;gM2*w^o;c^8A5@8fgL2tz|g?Vz#t8z?SV8O zkal!;4{~*P3~_bQGk_{>0BHw;1|XIPVn-lGGSLX83}^xfAe)G!%n)WVL=}oMkPrY+ C4Hy0Z diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/PARAMETER.data_0 deleted file mode 100644 index c78a7697775e7156c1c66a791567b39f0817fb43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmWFy4Gk4wU|Pp+Jfu8;E<8(` K0{%1nX8-^k1uOLc diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/PARAMETER.index b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/Ensemble/mod_9/PARAMETER.index deleted file mode 100644 index a8013e439c45e97c98c2fbd0cb3b5247be53e281..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69 zcmeZo6=GmyU|{%tDlZgBf!P8;I>0r^$I~x9z%j_tSI0wPR&iqN!8EIPl;De(GPG8a`bf#aShVT%`0JG zf~u6lqB1zdF~rjutc(?^Oa_ZGH~%14XUE_WutGLG3LX6%eIlb=UBC)ifC@p*- diff --git a/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/files/summary-key-set b/ThirdParty/Ert/test-data/local/custom_kw/fail_storage/ertensemble/default/files/summary-key-set deleted file mode 100644 index 593f4708db84ac8fd0f5cc47c634f38c013fe9e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4 LcmZQzU|;|M00aO5 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/jobs/AGGREGATOR b/ThirdParty/Ert/test-data/local/custom_kw/jobs/AGGREGATOR deleted file mode 100644 index f9571d60f9..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/jobs/AGGREGATOR +++ /dev/null @@ -1,4 +0,0 @@ -STDOUT aggregator.stdout -STDERR aggregator.stderr - -EXECUTABLE aggregator.py \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/jobs/PERLIN b/ThirdParty/Ert/test-data/local/custom_kw/jobs/PERLIN deleted file mode 100644 index fbf5c2ac87..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/jobs/PERLIN +++ /dev/null @@ -1,4 +0,0 @@ -STDOUT perlin.stdout -STDERR perlin.stderr - -EXECUTABLE perlin.py \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/jobs/PERLIN_FAIL b/ThirdParty/Ert/test-data/local/custom_kw/jobs/PERLIN_FAIL deleted file mode 100644 index f6da4542e8..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/jobs/PERLIN_FAIL +++ /dev/null @@ -1,3 +0,0 @@ -EXECUTABLE perlin_fail.py -TARGET_FILE perlin_fail.status -ARGLIST \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/jobs/REALIZATION_FAIL b/ThirdParty/Ert/test-data/local/custom_kw/jobs/REALIZATION_FAIL deleted file mode 100644 index 533677cf99..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/jobs/REALIZATION_FAIL +++ /dev/null @@ -1,3 +0,0 @@ -EXECUTABLE realization_fail.py -TARGET_FILE realization.ok -ARGLIST \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/jobs/aggregator.py b/ThirdParty/Ert/test-data/local/custom_kw/jobs/aggregator.py deleted file mode 100644 index 72561296f9..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/jobs/aggregator.py +++ /dev/null @@ -1,26 +0,0 @@ -#! /usr/bin/env python - -if __name__ == "__main__": - files = {"PERLIN_1": "perlin_1.txt", - "PERLIN_2": "perlin_2.txt", - "PERLIN_3": "perlin_3.txt"} - - with open("aggregated.txt", "w") as output_file: - sum_of_sum = 0.0 - for key in files: - sum = 0.0 - with open(files[key], "r") as input_file: - sum += float(input_file.readline()) - sum_of_sum += sum - output_file.write("%s %f\n" % (key, sum)) - - if sum_of_sum < 0: - state = "Negative" - elif abs(sum_of_sum) < 0.00000001: - state = "Zero" - else: - state = "Positive" - - output_file.write("STATE %s" % state) - - diff --git a/ThirdParty/Ert/test-data/local/custom_kw/jobs/perlin.py b/ThirdParty/Ert/test-data/local/custom_kw/jobs/perlin.py deleted file mode 100644 index 7cccc0d1f6..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/jobs/perlin.py +++ /dev/null @@ -1,176 +0,0 @@ -#! /usr/bin/env python -import math -import random - -PRIME_INDEX_1 = [49193,11887,23819,93983,28283,87179,74933,82561,29741,98453,72719,48193,66883,95071,12841,89603, - 49261,52529,57697,70321,54617,49363,41233,39883,35393,33149,37493,42989,58073,62507,99829,41999, - 44087,31907,10627,29231,57559,36809,17123,50593,38449,71317,38149,60637,10607,48677,23189,83701, - 78853,35617,28477,86117,46901,80819,89491,36097,54881,94781,20707,20011,69457,14593,49253,35257, - 14753,44851,10289,36097,62017,82723,10037,77551,89513,70429,30269,30703,77711,69313,20021,31657, - 33851,27749,85667,42793,47599,92789,97771,84551,61637,68659,93263,62201,42131,78823,17747,31183, - 89611,91009,76673,47051,94099,96757,90977,65141,46051,11093,19073,44633,27967,25171,41221,96223, - 88997,74941,49559,11909,11593,97369,55733,35869,55849,87931,81131,99023,76561,78977,48857,74717] - -PRIME_INDEX_2 = [7360349,1287757,3764759,5276833,2735671,7351777,7705903,2034551, - 2427493,3883639,4260859,6814097,3226933,2648249,4458793,8015303, - 2323733,7991233,5560879,9826913,3634811,3746299,1051543,2954789, - 7874983,9380681,4577789,4306829,6714599,8395733,2718493,1429867, - 5675147,6104573,3118727,2657243,9750043,1853377,9441353,7247969, - 7669553,5334157,9376649,9518137,9368297,3912679,3230237,7291939, - 1361677,1034167,4998089,1178239,5160677,6130199,8056553,8527361, - 4261093,8640553,5553391,6024797,7275019,7245019,7661483,5120033, - 4388117,5941147,7682189,9303467,7165777,1509163,5223929,9696487, - 8012383,6254273,1400731,9958177,7733573,1498993,1553467,4791257, - 4524521,7048633,3630821,7931179,2341457,6432269,9597703,4338011, - 6665059,7911653,8384317,2230531,7904621,1633559,9096533,6873301, - 2717821,5897977,3608543,2248243,3174599,8634233,4028963,6435001, - 6611399,3250469,4046353,1429943,8552111,1970261,1045043,9552523, - 6993799,6141467,5723479,9578867,9233299,7224641,3165023,4583899, - 3905861,1633993,5013137,5092613,2197163,7732213,6559019,2538499] - -PRIME_INDEX_3 = [1368916889,3054015583,6066123341,8673964289,9002483141,7187080993,5319345529,6961795349, - 1653814157,3416288497,6454122317,2480898239,3878100221,5956454227,9767569853,5981528503, - 4962084931,4489312199,3013312061,9818685161,4061204663,1816202221,7567463471,9839749459, - 3993070667,5872839331,9256050443,4854483611,4876755749,3823459247,6244209637,4199084081, - 6053970359,1093521049,7385602219,7289318273,9333908789,9701161343,8139801689,5013046681, - 4094649187,2372669671,9010267157,4298511787,7575340187,9252205969,5923706413,7112626819, - 6531270523,8379490583,4521945149,6804302789,6984132251,9173492033,1657527653,1532523367, - 3132088123,5910371431,7551540169,1643193353,6127000571,2637510193,7904761379,2954227033, - 7344843263,8077648457,9397237879,6775740173,1950824101,1152859999,2990299673,8197021109, - 2184824123,4309539167,1742841137,9113517421,4752058561,5594292329,9565022153,8519292151, - 6553311239,5204301593,8405487593,1987918357,3175759277,5659428917,6611421781,8765753053, - 3781235599,5651365571,8399394649,3867050417,3258145379,9836441977,2499690049,2742615479, - 7720787857,6135275183,9580731373,1860360379,2879750459,4302251633,8019104719,3889658671, - 7242891343,2516043583,8081336113,7718332591,4940550151,2216825899,7387662781,5562762407, - 2486416781,9111045257,1197705721,6649659239,6110149477,4548595937,3169540631,8993669479, - 6444114251,3098519969,1609592407,5803463207,8385117647,3056488453,1046337653,8165632597] - -class PerlinNoise(object): - - def __init__(self, persistence=0.5, number_of_octaves=4, prime_1=15731, prime_2=789221, prime_3=1376312589): - self.persistence = persistence - self.number_of_octaves = number_of_octaves - self.prime_1 = prime_1 - self.prime_2 = prime_2 - self.prime_3 = prime_3 - - - def cosineInterpolation(self, a, b, x): - ft = x * 3.1415927 - f = (1.0 - math.cos(ft)) * 0.5 - return a * (1 - f) + b * f - - - def noise(self, x): - x = (x << 13) ^ x - return 1.0 - ((x * (x * x + self.prime_1 + self.prime_2) + self.prime_3) & 0x7fffffff) / 1073741824.0 - - - def smoothedNoise(self, x): - return self.noise(x) / 2.0 + self.noise(x - 1) / 4.0 + self.noise(x + 1) / 4.0 - - - def interpolatedNoise(self, x): - int_x = int(x) - frac_x = x - int_x - - v1 = self.smoothedNoise(int_x) - v2 = self.smoothedNoise(int_x + 1) - - return self.cosineInterpolation(v1, v2, frac_x) - - - def perlinNoise1D(self, x): - total = 0.0 - - for octave in range(self.number_of_octaves - 1): - frequency = math.pow(2, octave) - amplitude = math.pow(self.persistence, octave) - - total += self.interpolatedNoise(x * frequency) * amplitude - - return total - - - @staticmethod - def isPrime(num): - for j in range(2, int(math.sqrt(num) + 1)): - if (num % j) == 0: - return False - return True - - @staticmethod - def createPrime(digits=10): - done = False - low = int("1" + "0" * (digits - 1)) - high = int("9" * digits) - - if low == 1: - low = 2 - - while not done: - num = random.randint(low, high) - if PerlinNoise.isPrime(num): - return num - - -def createObservationFile(report_step, observation, count, std=0.2): - with open("perlin_obs_%d.txt" % report_step, "w") as f: - - for index in range(count): - x = index / 8.0 - f.write("%f %f\n" % (observation.perlinNoise1D(x), std)) - - - -def readParameters(filename): - params = {} - with open(filename, "r") as f: - for line in f: - key, value = line.split(":", 1) - params[key] = float(value) - - return params - - -if __name__ == "__main__": - count = 100 - - # primes = [] - # for p in range(128): - # primes.append(str(PerlinNoise.createPrime(7))) - # - # print(",".join(primes)) - - observations = {1: PerlinNoise(prime_1=15731, prime_2=789221, prime_3=1376312589), - 2: PerlinNoise(prime_1=8831, prime_2=1300237, prime_3=32416187567), - 3: PerlinNoise(prime_1=10657, prime_2=105767, prime_3=2902956923)} - - for report_step in observations: - observation = observations[report_step] - # createObservationFile(report_step, observation, count) - - params = readParameters("perlin_params.txt") - - scale = params["SCALE"] - offset = params["OFFSET"] - octaves = int(round(params["OCTAVES"])) - persistence = params["PERSISTENCE"] - p1_index = int(round(params["PRIME_1"])) - p2_index = int(round(params["PRIME_2"])) - p3_index = int(round(params["PRIME_3"])) - - with open("perlin_%d.txt" % report_step, "w") as f: - P1 = PRIME_INDEX_1[p1_index] - P2 = PRIME_INDEX_2[p2_index] - P3 = PRIME_INDEX_3[p3_index] - # P1 = PerlinNoise.createPrime() - # P2 = PerlinNoise.createPrime() - # P3 = PerlinNoise.createPrime() - report_step_noise = PerlinNoise(persistence=persistence, number_of_octaves=octaves, prime_1=P1, prime_2=P2, prime_3=P3) - - for i in range(count): - x = i / 8.0 - obs = observation.perlinNoise1D(x) - noise = report_step_noise.perlinNoise1D(x) - f.write("%f\n" % (obs + offset + noise * scale)) diff --git a/ThirdParty/Ert/test-data/local/custom_kw/jobs/perlin_fail.py b/ThirdParty/Ert/test-data/local/custom_kw/jobs/perlin_fail.py deleted file mode 100644 index fed238f4b2..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/jobs/perlin_fail.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -iens = None -if len(sys.argv) > 1: - iens = int(sys.argv[1]) - -numbers = [1, 2, 3, 4, 5, 6] -if iens in numbers: - random_report_step = (numbers.index(iens) % 3) + 1 - os.remove("perlin_%d.txt" % random_report_step) - - with open("perlin_fail.status", "w") as f: - f.write("Deleted report step: %d" % random_report_step) - -else: - with open("perlin_fail.status", "w") as f: - f.write("Did nothing!") - - diff --git a/ThirdParty/Ert/test-data/local/custom_kw/jobs/realization_fail.py b/ThirdParty/Ert/test-data/local/custom_kw/jobs/realization_fail.py deleted file mode 100644 index 33a16ae523..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/jobs/realization_fail.py +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python -import sys - -iens = None -if len(sys.argv) > 1: - iens = int(sys.argv[1]) - -if iens is None or not iens in [2, 3, 5, 7]: - with open("realization.ok", "w") as f: - f.write("OK") - diff --git a/ThirdParty/Ert/test-data/local/custom_kw/mini_config b/ThirdParty/Ert/test-data/local/custom_kw/mini_config deleted file mode 100644 index 630ad828c4..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/mini_config +++ /dev/null @@ -1,40 +0,0 @@ -QUEUE_SYSTEM LOCAL -DBASE_TYPE BLOCK_FS - -JOBNAME MINI_%d - -DEFINE storage - -NUM_REALIZATIONS 10 - -STORE_SEED RandomSeed -LOAD_SEED RandomSeed - -RUNPATH /Run/realisation-%d/iter-%d -ENSPATH /ertensemble - -INSTALL_JOB AGGREGATOR jobs/AGGREGATOR -INSTALL_JOB PERLIN jobs/PERLIN - -FORWARD_MODEL PERLIN -FORWARD_MODEL AGGREGATOR - -TIME_MAP time_map -GEN_KW PERLIN_PARAM Template/PERLIN_TEMPLATE perlin_params.txt Parameters/PERLIN_PARAMS.txt -GEN_DATA PERLIN INPUT_FORMAT:ASCII RESULT_FILE:perlin_%d.txt REPORT_STEPS:1,2,3 - -UPDATE_RESULTS TRUE - -ENKF_MERGE_OBSERVATIONS TRUE - -LOG_LEVEL 3 -LOG_FILE log/log.txt -UPDATE_LOG_PATH log/UP - -DATA_KW CSV_OUTPUT_PATH custom_output.csv - -OBS_CONFIG Observations/observations - -CUSTOM_KW AGGREGATED aggregated.txt aggregated_out.txt - -GRID Refcase/CASE.EGRID \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/mini_fail_config b/ThirdParty/Ert/test-data/local/custom_kw/mini_fail_config deleted file mode 100644 index 2c45bc5eed..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/mini_fail_config +++ /dev/null @@ -1,43 +0,0 @@ -QUEUE_SYSTEM LOCAL -DBASE_TYPE BLOCK_FS - -JOBNAME MINI_FAIL_%d - -DEFINE fail_storage - -NUM_REALIZATIONS 10 -MAX_SUBMIT 1 - -STORE_SEED RandomSeed -LOAD_SEED RandomSeed - -RUNPATH /Run/realisation-%d/iter-%d -ENSPATH /ertensemble - -INSTALL_JOB AGGREGATOR jobs/AGGREGATOR -INSTALL_JOB PERLIN jobs/PERLIN -INSTALL_JOB PERLIN_FAIL jobs/PERLIN_FAIL -INSTALL_JOB REALIZATION_FAIL jobs/REALIZATION_FAIL - -FORWARD_MODEL PERLIN -FORWARD_MODEL AGGREGATOR -FORWARD_MODEL PERLIN_FAIL -FORWARD_MODEL REALIZATION_FAIL - -TIME_MAP time_map -GEN_KW PERLIN_PARAM Template/PERLIN_TEMPLATE perlin_params.txt Parameters/PERLIN_PARAMS.txt -GEN_DATA PERLIN INPUT_FORMAT:ASCII RESULT_FILE:perlin_%d.txt REPORT_STEPS:1,2,3 - -UPDATE_RESULTS TRUE - -ENKF_MERGE_OBSERVATIONS TRUE - -LOG_LEVEL 3 -LOG_FILE log/fail_log.txt -UPDATE_LOG_PATH log/UP - -DATA_KW CSV_OUTPUT_PATH custom_output.csv - -OBS_CONFIG Observations/observations - -CUSTOM_KW AGGREGATED aggregated.txt aggregated_out.txt diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/aggregated.txt deleted file mode 100644 index de8aedc562..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 0.190479 -PERLIN_2 1.002630 -PERLIN_1 -0.167794 -STATE Positive \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/parameters.txt deleted file mode 100644 index 142dbecaab..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.249225 -PERLIN_PARAM:OFFSET 0.185709 -PERLIN_PARAM:PERSISTENCE 0.936132 -PERLIN_PARAM:OCTAVES 22.4008 -PERLIN_PARAM:PRIME_1 70.2373 -PERLIN_PARAM:PRIME_2 73.2881 -PERLIN_PARAM:PRIME_3 73.2557 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_1.txt deleted file mode 100644 index fec0fd107e..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.167794 --0.533157 --0.582564 --0.581187 --0.544394 --0.617389 --0.471483 --0.570636 --0.513164 --0.094431 --0.489078 --0.363713 --0.116233 -0.104267 --0.185805 --0.200709 --0.150918 --0.384297 -0.293484 -0.122875 --0.157933 -0.066183 -0.043334 -0.083941 -0.237257 -0.510188 -0.247252 -0.238908 --0.087547 --0.330292 --0.126747 --0.035823 --0.234230 -0.031125 --0.470002 -0.277528 -0.333005 -0.208194 -0.329248 -0.183316 -0.030305 -0.292607 -0.207885 --0.055542 -0.267287 -0.489294 -0.351695 -0.473816 -0.486845 -0.161185 -0.750709 -0.334430 -0.487895 --0.083531 -0.631333 -0.189402 -0.293179 -0.416287 -0.071861 -0.343657 -0.530727 -0.295893 -0.707495 -0.705177 -0.364062 --0.028729 -0.627459 -0.665644 -0.110239 -0.074890 -0.898952 -0.507702 -0.793900 -0.376955 -0.740932 -0.768612 -1.072116 -0.641052 -0.951385 -1.114482 -0.779685 -1.030575 -0.960609 -0.819774 -0.728183 -0.880717 -0.390042 -0.616292 -0.534190 -0.332035 -0.597337 -0.310784 -0.480825 -0.510514 -0.527712 -0.106739 -0.459289 -0.091994 -0.167754 -0.291767 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_2.txt deleted file mode 100644 index a4c8ae2281..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -1.002630 -0.655338 -0.637300 -0.558783 -0.509989 -0.408818 -0.436655 -0.277816 -0.357889 -0.712315 -0.209713 -0.181557 -0.234966 -0.360507 -0.067803 -0.095832 -0.180428 --0.115810 -0.474014 -0.161206 --0.221441 -0.025834 --0.014213 -0.125937 -0.403895 -0.794609 -0.711298 -0.792749 -0.559236 -0.409434 -0.702774 -0.910823 -0.767699 -0.951166 -0.307889 -0.894615 -0.815080 -0.581146 -0.515508 -0.201538 --0.007474 -0.272051 -0.196068 --0.139775 -0.084654 -0.281485 -0.248246 -0.555883 -0.659358 -0.344063 -1.022407 -0.703206 -0.890554 -0.404788 -1.164953 -0.760065 -0.925984 -0.986234 -0.553851 -0.745948 -0.893678 -0.718616 -1.201408 -1.262021 -0.957160 -0.544980 -1.121517 -0.998898 -0.308482 -0.138122 -0.801380 -0.392979 -0.722289 -0.303537 -0.622059 -0.433718 -0.480651 --0.144483 -0.012328 -0.129970 --0.206634 -0.080509 -0.073475 -0.003830 --0.027990 -0.147703 --0.360170 --0.159376 --0.241837 --0.406290 --0.058059 --0.199599 -0.184944 -0.465746 -0.716346 -0.404191 -0.768554 -0.294930 -0.274427 -0.462347 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_3.txt deleted file mode 100644 index 13a10a9e5d..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.190479 --0.262978 --0.465308 --0.621105 --0.713738 --0.781896 --0.645797 --0.734690 --0.615233 --0.181474 --0.500371 --0.375013 --0.212762 --0.077491 --0.367569 --0.306723 --0.241907 --0.432924 -0.314717 -0.254536 -0.131618 -0.477011 -0.476202 -0.498281 -0.657347 -0.936028 -0.654565 -0.605760 -0.338082 -0.190727 -0.442199 -0.602984 -0.446939 -0.753207 -0.301943 -1.023577 -1.019714 -0.773061 -0.805721 -0.709651 -0.597553 -0.944238 -0.917685 -0.547257 -0.715075 -0.782070 -0.537469 -0.655260 -0.690172 -0.323895 -0.846589 -0.260808 -0.196762 --0.503788 -0.078186 --0.393964 --0.242415 --0.177505 --0.622958 --0.465445 --0.374328 --0.668502 --0.282796 --0.297752 --0.660453 --0.993300 --0.233057 --0.139662 --0.658737 --0.694367 -0.096517 --0.216566 -0.155464 --0.212261 -0.141495 -0.047609 -0.314219 --0.143014 -0.160029 -0.364682 -0.027328 -0.374773 -0.497251 -0.562515 -0.606365 -0.821117 -0.359765 -0.601682 -0.542912 -0.364089 -0.645058 -0.325327 -0.495087 -0.498606 -0.508514 -0.129097 -0.479090 -0.135126 -0.226554 -0.379889 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_params.txt deleted file mode 100644 index 99b2ec3ff6..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-0/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.249225 -OFFSET:0.185709 -PERSISTENCE:0.936132 -OCTAVES:22.4008 -PRIME_1:70.2373 -PRIME_2:73.2881 -PRIME_3:73.2557 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/aggregated.txt deleted file mode 100644 index c42ebc2573..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 -0.584204 -PERLIN_2 0.227947 -PERLIN_1 -0.942477 -STATE Negative \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/parameters.txt deleted file mode 100644 index d931876083..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.24275 -PERLIN_PARAM:OFFSET -0.29096 -PERLIN_PARAM:PERSISTENCE 0.860518 -PERLIN_PARAM:OCTAVES 14.7858 -PERLIN_PARAM:PRIME_1 11.8217 -PERLIN_PARAM:PRIME_2 48.9187 -PERLIN_PARAM:PRIME_3 89.5122 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_1.txt deleted file mode 100644 index 20e4b55793..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.942477 --0.727071 --0.723611 --0.754719 --0.671417 --0.731608 --0.692600 --0.493644 --0.676412 --0.745697 --0.692443 --0.578927 --0.488710 --0.308417 --0.198633 --0.292521 --0.451160 --0.454948 --0.565726 --0.325299 --0.477437 --0.393874 --0.366932 --0.181596 --0.382861 --0.214575 --0.343829 --0.226514 --0.320776 --0.308425 --0.487588 --0.395820 --0.742008 --0.527934 --0.774032 --0.603036 --0.837021 --0.456712 --0.387980 --0.390885 --0.477976 --0.396114 --0.440335 --0.294043 --0.320108 --0.019041 --0.013591 --0.252420 --0.275822 --0.164093 --0.136841 --0.069380 --0.145731 --0.021543 -0.105226 -0.109063 -0.010749 -0.174611 -0.235996 -0.229778 -0.234829 -0.303725 -0.413435 -0.191701 --0.016101 -0.137470 -0.169930 --0.099989 --0.129193 --0.110471 -0.042198 --0.048338 --0.349474 --0.098213 -0.162561 -0.313852 -0.400474 -0.538012 -0.475773 -0.571507 -0.342028 -0.299233 -0.316542 -0.349001 -0.187998 -0.323078 -0.237231 -0.120016 --0.054434 --0.139747 -0.160315 --0.006853 -0.136442 -0.070848 --0.273561 --0.222518 --0.288468 --0.046234 --0.175744 --0.151171 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_2.txt deleted file mode 100644 index 296be5b8cd..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.227947 -0.461424 -0.496254 -0.385250 -0.382965 -0.294599 -0.215538 -0.354808 -0.194641 -0.061050 -0.006348 --0.033658 --0.137511 --0.052176 -0.054974 -0.004020 --0.119814 --0.186461 --0.385196 --0.286967 --0.540945 --0.434223 --0.424480 --0.139600 --0.216224 -0.069846 -0.120217 -0.327327 -0.326008 -0.431300 -0.341933 -0.550826 -0.259922 -0.392107 -0.003858 -0.014051 --0.354946 --0.083760 --0.201720 --0.372664 --0.515754 --0.416670 --0.452153 --0.378276 --0.502741 --0.226850 --0.117039 --0.170353 --0.103309 -0.018785 -0.134857 -0.299396 -0.256928 -0.466775 -0.638846 -0.679726 -0.643554 -0.744558 -0.717986 -0.632070 -0.597780 -0.726447 -0.907347 -0.748545 -0.576996 -0.711178 -0.663988 -0.233265 -0.069050 --0.047240 --0.055375 --0.163060 --0.421085 --0.171631 -0.043688 --0.021042 --0.190991 --0.247524 --0.463284 --0.413005 --0.644291 --0.650833 --0.570592 --0.466943 --0.568175 --0.409936 --0.512981 --0.655652 --0.830461 --0.878072 --0.495081 --0.517236 --0.159439 -0.026080 --0.084928 -0.074934 -0.020797 -0.156703 --0.069071 -0.019410 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_3.txt deleted file mode 100644 index d43e140291..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.584204 --0.456892 --0.606354 --0.794637 --0.840762 --0.896115 --0.866915 --0.657698 --0.778480 --0.832740 --0.703736 --0.590227 --0.585239 --0.490175 --0.380398 --0.398535 --0.542149 --0.503575 --0.544492 --0.193638 --0.187886 -0.016954 -0.065935 -0.232744 -0.037229 -0.211265 -0.063484 -0.140338 -0.104854 -0.212594 -0.081358 -0.242987 --0.060839 -0.194148 --0.002088 -0.143014 --0.150313 -0.108155 -0.088492 -0.135449 -0.089272 -0.255517 -0.269465 -0.308757 -0.127679 -0.273734 -0.172184 --0.070976 --0.072495 --0.001383 --0.040962 --0.143002 --0.436864 --0.441800 --0.447921 --0.474303 --0.524845 --0.419181 --0.458823 --0.579324 --0.670226 --0.660671 --0.576856 --0.811227 --1.040616 --0.827102 --0.690587 --0.905295 --0.898169 --0.879729 --0.760237 --0.772606 --0.987910 --0.687429 --0.436876 --0.407151 --0.357423 --0.246055 --0.315583 --0.178294 --0.410329 --0.356569 --0.146816 -0.091742 -0.066180 -0.263478 -0.206954 -0.105406 --0.045712 --0.107693 -0.208035 -0.007690 -0.150704 -0.058939 --0.292759 --0.200161 --0.268667 --0.003101 --0.116944 --0.063049 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_params.txt deleted file mode 100644 index fb78e8c3e9..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-1/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.24275 -OFFSET:-0.29096 -PERSISTENCE:0.860518 -OCTAVES:14.7858 -PRIME_1:11.8217 -PRIME_2:48.9187 -PRIME_3:89.5122 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/aggregated.txt deleted file mode 100644 index 39c71d12aa..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 -0.294383 -PERLIN_2 0.517768 -PERLIN_1 -0.652656 -STATE Negative \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/parameters.txt deleted file mode 100644 index 0850de9c61..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.187883 -PERLIN_PARAM:OFFSET -0.512383 -PERLIN_PARAM:PERSISTENCE 0.850056 -PERLIN_PARAM:OCTAVES 39.9199 -PERLIN_PARAM:PRIME_1 76.7337 -PERLIN_PARAM:PRIME_2 54.1086 -PERLIN_PARAM:PRIME_3 16.0042 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_1.txt deleted file mode 100644 index 122d4089ea..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.652656 --0.856575 --0.907574 --0.921559 --0.907052 --0.798535 --0.892001 --0.898300 --0.932647 --0.887530 --0.745258 --0.774438 --0.680597 --0.707552 --0.616984 --0.784930 --0.705796 --0.672207 --0.677662 --0.517634 --0.460960 --0.512998 --0.485822 --0.377630 --0.469687 --0.463782 --0.644529 --0.631042 --0.610238 --0.645129 --0.841183 --0.813056 --0.824549 --0.985474 --0.818724 --1.021755 --0.749654 --0.643111 --0.382287 --0.319701 --0.240893 --0.293783 --0.356379 --0.315861 --0.243741 --0.061641 --0.016073 --0.078540 --0.166452 --0.204278 --0.206156 --0.339674 --0.324650 --0.218586 --0.220018 --0.365619 --0.213129 --0.161173 --0.144854 --0.088350 --0.193806 --0.111286 --0.100984 --0.235155 --0.165413 --0.278588 --0.429381 --0.254946 --0.240835 --0.227267 --0.524615 --0.423858 --0.341032 --0.369948 --0.180422 -0.176827 -0.282667 -0.455645 -0.421888 -0.461117 -0.478802 -0.408361 -0.301001 -0.266791 -0.167743 -0.066362 -0.101881 -0.183729 --0.037895 -0.191528 -0.077918 -0.193353 -0.109073 -0.001759 --0.061599 --0.001108 --0.164077 --0.253534 --0.200586 --0.275259 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_2.txt deleted file mode 100644 index 6e35f0db00..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.517768 -0.331920 -0.312291 -0.218411 -0.147331 -0.227672 -0.016137 --0.049848 --0.061594 --0.080783 --0.046467 --0.229168 --0.329398 --0.451311 --0.363377 --0.488389 --0.374451 --0.403720 --0.497132 --0.479302 --0.524469 --0.553347 --0.543370 --0.335634 --0.303049 --0.179361 --0.180483 --0.077200 -0.036546 -0.094596 --0.011662 -0.133590 -0.177380 --0.065433 --0.040833 --0.404669 --0.267578 --0.270158 --0.196027 --0.301479 --0.278672 --0.314339 --0.368196 --0.400094 --0.426374 --0.269450 --0.119522 -0.003527 -0.006061 --0.021400 -0.065542 -0.029102 -0.078009 -0.269733 -0.313603 -0.205045 -0.419677 -0.408773 -0.337136 -0.313942 -0.169145 -0.311436 -0.392928 -0.321689 -0.427685 -0.295121 -0.064678 -0.078309 --0.042592 --0.164036 --0.622187 --0.538581 --0.412642 --0.443366 --0.299295 --0.158067 --0.308798 --0.329891 --0.517169 --0.523395 --0.507517 --0.541705 --0.586134 --0.549153 --0.588430 --0.666651 --0.648330 --0.591939 --0.813922 --0.546797 --0.577477 --0.317029 --0.186808 --0.043009 -0.127034 -0.296344 -0.145188 --0.050597 --0.093913 --0.104679 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_3.txt deleted file mode 100644 index 1e03faf793..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.294383 --0.586396 --0.790317 --0.961476 --1.076396 --0.963042 --1.066316 --1.062354 --1.034715 --0.974573 --0.756551 --0.785737 --0.777126 --0.889310 --0.798749 --0.890944 --0.796785 --0.720834 --0.656429 --0.385973 --0.171410 --0.102170 --0.052955 -0.036709 --0.049597 --0.037941 --0.237216 --0.264190 --0.184608 --0.124110 --0.272236 --0.174249 --0.143380 --0.263391 --0.046779 --0.275706 --0.062945 --0.078243 -0.094185 -0.206634 -0.326354 -0.357848 -0.353421 -0.286938 -0.204047 -0.231135 -0.169701 -0.102903 -0.036875 --0.041568 --0.110276 --0.413296 --0.615784 --0.638843 --0.773164 --0.948985 --0.748723 --0.754966 --0.839672 --0.897452 --1.098861 --1.075682 --1.091275 --1.238084 --1.189928 --1.243159 --1.289897 --1.060251 --1.009811 --0.996525 --1.327050 --1.148126 --0.979468 --0.959163 --0.779859 --0.544176 --0.475229 --0.328422 --0.369468 --0.288684 --0.273556 --0.247441 --0.162358 -0.009532 -0.045926 -0.006763 -0.071604 -0.169119 --0.029173 -0.223582 -0.125639 -0.207896 -0.123334 --0.010150 --0.080797 -0.021249 --0.144276 --0.210401 --0.141786 --0.187137 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_params.txt deleted file mode 100644 index a069d36ab8..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-2/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.187883 -OFFSET:-0.512383 -PERSISTENCE:0.850056 -OCTAVES:39.9199 -PRIME_1:76.7337 -PRIME_2:54.1086 -PRIME_3:16.0042 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/aggregated.txt deleted file mode 100644 index b986f1b481..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 -0.871387 -PERLIN_2 -0.059236 -PERLIN_1 -1.229660 -STATE Negative \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/parameters.txt deleted file mode 100644 index a7472afccf..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.542054 -PERLIN_PARAM:OFFSET -0.936072 -PERLIN_PARAM:PERSISTENCE 0.66513 -PERLIN_PARAM:OCTAVES 59.6891 -PERLIN_PARAM:PRIME_1 58.3958 -PERLIN_PARAM:PRIME_2 51.6271 -PERLIN_PARAM:PRIME_3 37.3286 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_1.txt deleted file mode 100644 index 1f0aabd193..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --1.229660 --1.403213 --1.494882 --1.481222 --1.545058 --1.605346 --1.466829 --1.460689 --1.589462 --1.462504 --1.586371 --1.419953 --1.184666 --1.064367 --1.081730 --1.130531 --1.307146 --1.330892 --1.147255 --1.230522 --1.290812 --1.243312 --1.053225 --0.837831 --0.815416 --0.794856 --0.780118 --0.867346 --0.868595 --0.844661 --0.949974 --1.135521 --1.278698 --1.237066 --1.353473 --1.274754 --1.024540 --1.062374 --1.018191 --0.989482 --1.082235 --1.083477 --1.111900 --0.884140 --0.804378 --0.649785 --0.414051 --0.453314 --0.426393 --0.376335 --0.433952 --0.369796 --0.319725 --0.318209 --0.380495 --0.274543 --0.410077 --0.265464 --0.276032 --0.293185 --0.259478 --0.307654 --0.469020 --0.606702 --0.727993 --0.657698 --0.738949 --0.779068 --0.929409 --0.925120 --0.888902 --0.818882 --0.691387 --0.806321 --0.774223 --0.725947 --0.616177 --0.575377 --0.546778 --0.619225 --0.739783 --0.805058 --0.854443 --1.003113 --0.978222 --0.724971 --0.804323 --0.920953 --0.973738 --0.936418 --0.905518 --0.717744 --0.616881 --0.785126 --0.782606 --0.680625 --0.739233 --0.708171 --0.640854 --0.813288 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_2.txt deleted file mode 100644 index 58ac16bef2..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.059236 --0.214718 --0.275017 --0.341253 --0.490676 --0.579139 --0.558691 --0.612236 --0.718408 --0.655757 --0.887580 --0.874683 --0.833466 --0.808127 --0.828123 --0.833990 --0.975800 --1.062405 --0.966725 --1.192190 --1.354320 --1.283661 --1.110772 --0.795835 --0.648779 --0.510435 --0.316072 --0.313505 --0.221812 --0.104936 --0.120453 --0.188875 --0.276769 --0.317026 --0.575582 --0.657667 --0.542465 --0.689421 --0.831931 --0.971260 --1.120014 --1.104033 --1.123718 --0.968373 --0.987011 --0.857594 --0.517499 --0.371248 --0.253880 --0.193457 --0.162254 --0.001019 -0.082934 -0.170110 -0.153126 -0.296120 -0.222728 -0.304483 -0.205958 -0.109107 -0.103474 -0.115069 -0.024892 --0.049858 --0.134896 --0.083989 --0.244890 --0.445814 --0.731166 --0.861888 --0.986474 --0.933604 --0.762998 --0.879739 --0.893096 --1.060842 --1.207642 --1.360912 --1.485835 --1.603737 --1.726102 --1.755124 --1.741578 --1.819057 --1.734395 --1.457985 --1.554534 --1.696621 --1.749765 --1.674743 --1.560913 --1.228126 --0.912762 --0.829894 --0.593973 --0.383174 --0.429968 --0.505235 --0.534181 --0.642708 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_3.txt deleted file mode 100644 index 3e28703234..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.871387 --1.133034 --1.377625 --1.521140 --1.714403 --1.769853 --1.641143 --1.624743 --1.691530 --1.549547 --1.597664 --1.431252 --1.281194 --1.246125 --1.263495 --1.236545 --1.398135 --1.379519 --1.126021 --1.098861 --1.001261 --0.832484 --0.620357 --0.423492 --0.395326 --0.369015 --0.372806 --0.500494 --0.442966 --0.323643 --0.381027 --0.496714 --0.597530 --0.514984 --0.581528 --0.528705 --0.337832 --0.497506 --0.541718 --0.463147 --0.514987 --0.431846 --0.402100 --0.281341 --0.356591 --0.357009 --0.228277 --0.271871 --0.223066 --0.213625 --0.338073 --0.443417 --0.610858 --0.738466 --0.933641 --0.857909 --0.945672 --0.859256 --0.970850 --1.102287 --1.164532 --1.272049 --1.459311 --1.609631 --1.752508 --1.622269 --1.599465 --1.584374 --1.698385 --1.694377 --1.691337 --1.543150 --1.329823 --1.395537 --1.373660 --1.446951 --1.374073 --1.359444 --1.338134 --1.369026 --1.492140 --1.460860 --1.317801 --1.260372 --1.100040 --0.784571 --0.834600 --0.935563 --0.965016 --0.904364 --0.857797 --0.703201 --0.602620 --0.797035 --0.801804 --0.658268 --0.719432 --0.665039 --0.582054 --0.725166 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_params.txt deleted file mode 100644 index f51328cc14..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-3/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.542054 -OFFSET:-0.936072 -PERSISTENCE:0.66513 -OCTAVES:59.6891 -PRIME_1:58.3958 -PRIME_2:51.6271 -PRIME_3:37.3286 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/aggregated.txt deleted file mode 100644 index 35536135e9..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 0.585905 -PERLIN_2 1.398056 -PERLIN_1 0.227632 -STATE Positive \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/parameters.txt deleted file mode 100644 index 43486a893a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.434448 -PERLIN_PARAM:OFFSET 0.831105 -PERLIN_PARAM:PERSISTENCE 0.630867 -PERLIN_PARAM:OCTAVES 8.00407 -PERLIN_PARAM:PRIME_1 85.4235 -PERLIN_PARAM:PRIME_2 21.3039 -PERLIN_PARAM:PRIME_3 104.858 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_1.txt deleted file mode 100644 index 7ea431597a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.227632 -0.182419 -0.144134 -0.139476 -0.177808 -0.254702 -0.194959 -0.196247 -0.200894 -0.254938 -0.395923 -0.419362 -0.480212 -0.525709 -0.561013 -0.552975 -0.519655 -0.497365 -0.577627 -0.735132 -0.817150 -0.830304 -0.810482 -0.786231 -0.748806 -0.689116 -0.617421 -0.687358 -0.594608 -0.517947 -0.548341 -0.523440 -0.419855 -0.405486 -0.372455 -0.434415 -0.562727 -0.733549 -0.970895 -1.160018 -1.169762 -1.111676 -1.111566 -1.106991 -1.105426 -1.213650 -1.175046 -1.097622 -1.076414 -1.020738 -0.967021 -0.935108 -0.968248 -1.090303 -1.177846 -1.141175 -1.035475 -1.007184 -1.064612 -1.220228 -1.325731 -1.365550 -1.388177 -1.239332 -1.196752 -1.250964 -1.102255 -1.021732 -1.011481 -1.046014 -1.021100 -1.037203 -0.983562 -1.047336 -1.209270 -1.527246 -1.651524 -1.778722 -1.953437 -1.897861 -1.919134 -1.832772 -1.722330 -1.690519 -1.644280 -1.609237 -1.499923 -1.390382 -1.225122 -1.258604 -1.269723 -1.248156 -1.156463 -1.014345 -0.967288 -0.922071 -0.964769 -0.867821 -0.886340 -0.661428 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_2.txt deleted file mode 100644 index b747326d4e..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -1.398056 -1.370914 -1.363998 -1.279446 -1.232190 -1.280908 -1.103097 -1.044700 -1.071948 -1.061684 -1.094715 -0.964632 -0.831411 -0.781949 -0.814620 -0.849516 -0.851001 -0.765851 -0.758157 -0.773463 -0.753641 -0.789955 -0.752934 -0.828227 -0.915443 -0.973537 -1.081467 -1.241200 -1.241392 -1.257672 -1.377862 -1.470086 -1.421784 -1.325527 -1.150346 -1.051501 -1.044802 -1.106502 -1.157155 -1.178239 -1.131983 -1.091121 -1.099748 -1.022758 -0.922794 -1.005841 -1.071597 -1.179689 -1.248927 -1.203617 -1.238719 -1.303884 -1.370907 -1.578622 -1.711466 -1.711839 -1.668280 -1.577131 -1.546602 -1.622520 -1.688682 -1.788272 -1.882089 -1.796176 -1.789849 -1.824672 -1.596314 -1.354986 -1.209724 -1.109246 -0.923528 -0.922481 -0.911951 -0.973918 -1.090397 -1.192352 -1.060059 -0.993187 -1.014380 -0.913349 -0.932815 -0.882706 -0.835195 -0.874574 -0.888107 -0.876224 -0.749712 -0.614713 -0.449095 -0.520278 -0.614327 -0.737773 -0.860582 -0.969577 -1.155922 -1.219523 -1.274034 -1.070757 -0.993013 -0.832009 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_3.txt deleted file mode 100644 index c5dd1d518a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.585905 -0.452598 -0.261390 -0.099559 -0.008463 -0.090195 -0.020645 -0.032193 -0.098826 -0.167894 -0.384631 -0.408063 -0.383683 -0.343951 -0.379248 -0.446961 -0.428666 -0.448737 -0.598860 -0.866793 -1.106700 -1.241132 -1.243349 -1.200570 -1.168896 -1.114956 -1.024733 -1.054210 -1.020238 -1.038965 -1.117287 -1.162247 -1.101024 -1.127568 -1.144400 -1.180464 -1.249435 -1.298417 -1.447368 -1.686352 -1.737009 -1.763308 -1.821366 -1.709790 -1.553214 -1.506426 -1.360820 -1.279066 -1.279741 -1.183449 -1.062901 -0.861486 -0.677115 -0.670046 -0.624699 -0.557809 -0.499881 -0.413392 -0.369794 -0.411126 -0.420676 -0.401154 -0.397886 -0.236404 -0.172236 -0.286392 -0.241739 -0.216426 -0.242506 -0.276757 -0.218665 -0.312935 -0.345126 -0.458120 -0.609833 -0.806243 -0.893627 -0.994656 -1.162081 -1.148060 -1.166777 -1.176970 -1.258971 -1.433259 -1.522462 -1.549638 -1.469646 -1.375772 -1.233844 -1.290657 -1.317444 -1.262699 -1.170724 -1.002436 -0.948090 -0.944428 -0.984570 -0.910954 -0.945140 -0.749551 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_params.txt deleted file mode 100644 index 324cbda2ee..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-4/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.434448 -OFFSET:0.831105 -PERSISTENCE:0.630867 -OCTAVES:8.00407 -PRIME_1:85.4235 -PRIME_2:21.3039 -PRIME_3:104.858 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/aggregated.txt deleted file mode 100644 index 72e58cbf64..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 0.638889 -PERLIN_2 1.451039 -PERLIN_1 0.280615 -STATE Positive \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/parameters.txt deleted file mode 100644 index 463f5c41d8..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.72828 -PERLIN_PARAM:OFFSET 0.48251 -PERLIN_PARAM:PERSISTENCE 0.878696 -PERLIN_PARAM:OCTAVES 62.5026 -PERLIN_PARAM:PRIME_1 10.3564 -PERLIN_PARAM:PRIME_2 34.9666 -PERLIN_PARAM:PRIME_3 46.2883 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_1.txt deleted file mode 100644 index 11da497a09..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.280615 -0.140016 -0.101814 --0.129046 -0.108540 -0.255758 --0.136433 -0.402995 -0.060006 -0.243033 -0.270699 -1.032076 --0.013904 --0.123877 -0.661223 -0.260982 -0.218027 -1.382060 -0.399264 -0.483361 -0.472825 --0.400746 -1.339330 -0.692467 -0.043042 -0.542935 --0.239154 -0.322095 -0.568886 --0.253825 -0.069002 -0.151587 --0.060719 -0.071557 -1.232762 -0.806173 -0.197592 -0.775339 -0.485706 --0.340968 -0.563185 --0.301442 --0.470657 -0.391865 -1.604934 -1.366571 -0.978296 -0.533236 -0.199409 -0.640021 -0.724001 -0.620437 --0.062286 -0.448127 -0.681424 -0.211811 -0.962468 -0.569284 -0.153403 -0.463251 -0.717336 -1.047732 -0.879313 -0.557671 -0.589243 -0.475895 -0.668305 -1.261389 -1.992548 -0.514705 -1.480108 -0.964709 -0.672593 -0.541782 -1.389203 -0.533862 -1.237538 -0.892042 -0.376384 -0.676731 -1.374955 -1.291646 -0.276911 -0.706050 -0.032507 -1.074094 -0.914922 -1.747032 -2.087744 -1.287205 -1.735100 -1.305039 -1.283753 -0.989592 -0.686460 -0.373096 -0.309114 -0.349820 -0.814016 -0.915557 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_2.txt deleted file mode 100644 index 1a12f1d5e3..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -1.451039 -1.328511 -1.321678 -1.010924 -1.162923 -1.281965 -0.771705 -1.251448 -0.931060 -1.049780 -0.969490 -1.577345 -0.337295 -0.132363 -0.914830 -0.557523 -0.549373 -1.650547 -0.579795 -0.521693 -0.409316 --0.441095 -1.281782 -0.734463 -0.209679 -0.827356 -0.224891 -0.875937 -1.215669 -0.485900 -0.898524 -1.098233 -0.941210 -0.991598 -2.010653 -1.423259 -0.679667 -1.148292 -0.671966 --0.322746 -0.525407 --0.321998 --0.482474 -0.307632 -1.422302 -1.158762 -0.874847 -0.615302 -0.371922 -0.822899 -0.995699 -0.989214 -0.340374 -0.936446 -1.215045 -0.782475 -1.595273 -1.139231 -0.635393 -0.865543 -1.080287 -1.470455 -1.373225 -1.114515 -1.182340 -1.049604 -1.162364 -1.594643 -2.190791 -0.577937 -1.382536 -0.849987 -0.600982 -0.468364 -1.270330 -0.198968 -0.646073 -0.106506 --0.562673 --0.307781 -0.388636 -0.341580 --0.610223 --0.109894 --0.723666 -0.341080 -0.164710 -0.971363 -1.311717 -0.548880 -1.079704 -0.794657 -0.987872 -0.944824 -0.875093 -0.670548 -0.618379 -0.552756 -0.920689 -1.086138 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_3.txt deleted file mode 100644 index 4b5a132c2c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.638889 -0.410195 -0.219070 --0.168964 --0.060804 -0.091251 --0.310748 -0.238941 --0.042062 -0.155990 -0.259406 -1.020776 --0.110433 --0.305635 -0.479458 -0.154968 -0.127038 -1.333433 -0.420498 -0.615022 -0.762375 -0.010082 -1.772197 -1.106807 -0.463132 -0.968775 -0.168158 -0.688947 -0.994515 -0.267193 -0.637949 -0.790394 -0.620450 -0.793639 -2.004706 -1.552222 -0.884301 -1.340207 -0.962178 -0.185367 -1.130433 -0.350189 -0.239143 -0.994664 -2.052722 -1.659346 -1.164070 -0.714679 -0.402736 -0.802732 -0.819881 -0.546816 --0.353419 -0.027870 -0.128278 --0.371555 -0.426874 --0.024508 --0.541415 --0.345851 --0.187719 -0.083337 --0.110978 --0.445258 --0.435272 --0.488676 --0.192211 -0.456083 -1.223572 --0.254552 -0.677673 -0.240441 -0.034157 --0.047433 -0.789765 --0.187141 -0.479641 -0.107975 --0.414972 --0.073069 -0.622598 -0.635844 --0.186447 -0.448791 --0.089311 -1.014494 -0.884645 -1.732422 -2.096466 -1.319259 -1.782821 -1.319583 -1.298015 -0.977683 -0.667262 -0.395453 -0.328915 -0.392952 -0.872816 -1.003679 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_params.txt deleted file mode 100644 index 6ffe51857b..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-5/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.72828 -OFFSET:0.48251 -PERSISTENCE:0.878696 -OCTAVES:62.5026 -PRIME_1:10.3564 -PRIME_2:34.9666 -PRIME_3:46.2883 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/aggregated.txt deleted file mode 100644 index 07f12f2a08..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 0.870550 -PERLIN_2 1.682701 -PERLIN_1 0.512277 -STATE Positive \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/parameters.txt deleted file mode 100644 index 04dc1adb80..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.105108 -PERLIN_PARAM:OFFSET 0.913379 -PERLIN_PARAM:PERSISTENCE 0.962764 -PERLIN_PARAM:OCTAVES 54.2875 -PERLIN_PARAM:PRIME_1 12.1353 -PERLIN_PARAM:PRIME_2 108.225 -PERLIN_PARAM:PRIME_3 58.2668 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_1.txt deleted file mode 100644 index 309c31a80b..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.512277 -0.536404 -0.520619 -0.520234 -0.561383 -0.536841 -0.593527 -0.431159 -0.579716 -0.595432 -0.613877 -0.832759 -0.851509 -0.830369 -0.752398 -0.701988 -0.854139 -0.813144 -0.848016 -0.675839 -0.919173 -1.078956 -1.165071 -1.045397 -1.099168 -1.049976 -0.934854 -0.813458 -0.777245 -0.747191 -0.680688 -0.492784 -0.756629 -0.639112 -0.677362 -0.560299 -0.783620 -0.757035 -0.781494 -1.092201 -1.102767 -1.052654 -1.207713 -1.115009 -1.380213 -1.620005 -1.355587 -1.358326 -1.365758 -1.049275 -1.264629 -1.182026 -1.240226 -1.329804 -1.210895 -1.340758 -1.160254 -1.099240 -1.243394 -1.267952 -1.359115 -1.457122 -1.219766 -1.225781 -1.439935 -1.367284 -1.242810 -1.155161 -1.278395 -1.180081 -1.125988 -1.131542 -1.239492 -1.086901 -1.273243 -1.532824 -1.482385 -1.810195 -1.887451 -1.774089 -1.870171 -1.843973 -1.696110 -1.740468 -1.791604 -1.614504 -1.582554 -1.758357 -1.634232 -1.684106 -1.786180 -1.619646 -1.484936 -1.430948 -1.379634 -1.352505 -1.382218 -1.487943 -1.057155 -0.971585 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_2.txt deleted file mode 100644 index 463edcab27..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -1.682701 -1.724900 -1.740484 -1.660204 -1.615765 -1.563048 -1.501665 -1.279611 -1.450770 -1.402179 -1.312668 -1.378029 -1.202709 -1.086610 -1.006006 -0.998528 -1.185484 -1.081631 -1.028546 -0.714171 -0.855664 -1.038607 -1.107524 -1.087393 -1.265806 -1.334397 -1.398900 -1.367299 -1.424028 -1.486916 -1.510209 -1.439430 -1.758558 -1.559152 -1.455253 -1.177386 -1.265695 -1.129987 -0.967754 -1.110422 -1.064988 -1.032099 -1.195895 -1.030776 -1.197580 -1.412196 -1.252139 -1.440393 -1.538272 -1.232153 -1.536327 -1.550802 -1.642885 -1.818122 -1.744516 -1.911422 -1.793059 -1.669187 -1.725384 -1.670243 -1.722066 -1.879845 -1.713679 -1.782625 -2.033032 -1.940992 -1.736869 -1.488416 -1.476638 -1.243313 -1.028416 -1.016820 -1.167881 -1.013483 -1.154370 -1.197929 -0.890921 -1.024660 -0.948394 -0.789577 -0.883852 -0.893907 -0.808975 -0.924524 -1.035431 -0.881490 -0.832342 -0.982689 -0.858205 -0.945780 -1.130784 -1.109264 -1.189055 -1.386180 -1.568267 -1.649957 -1.691483 -1.690880 -1.163828 -1.142166 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_3.txt deleted file mode 100644 index bb7c009032..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.870550 -0.806583 -0.637876 -0.480317 -0.392038 -0.372334 -0.419213 -0.267105 -0.477648 -0.508389 -0.602584 -0.821460 -0.754981 -0.648612 -0.570634 -0.595973 -0.763150 -0.764517 -0.869249 -0.807500 -1.208723 -1.489784 -1.597939 -1.459736 -1.519258 -1.475816 -1.342167 -1.180310 -1.202874 -1.268209 -1.249634 -1.131591 -1.437798 -1.361194 -1.449307 -1.306349 -1.470329 -1.321902 -1.257966 -1.618535 -1.670015 -1.704286 -1.917513 -1.717808 -1.828000 -1.912781 -1.541362 -1.539769 -1.569085 -1.211985 -1.360508 -1.108404 -0.949092 -0.909547 -0.657749 -0.757392 -0.624659 -0.505448 -0.548575 -0.458850 -0.454060 -0.492727 -0.229476 -0.222852 -0.415420 -0.402712 -0.382294 -0.349856 -0.509419 -0.410824 -0.323553 -0.407274 -0.601056 -0.497685 -0.673805 -0.811821 -0.724489 -1.026129 -1.096095 -1.024289 -1.117814 -1.188171 -1.232752 -1.483209 -1.669786 -1.554904 -1.552277 -1.743747 -1.642953 -1.716159 -1.833900 -1.634190 -1.499198 -1.419039 -1.360436 -1.374862 -1.402018 -1.531076 -1.115955 -1.059708 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_params.txt deleted file mode 100644 index 29d18ec899..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-6/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.105108 -OFFSET:0.913379 -PERSISTENCE:0.962764 -OCTAVES:54.2875 -PRIME_1:12.1353 -PRIME_2:108.225 -PRIME_3:58.2668 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/aggregated.txt deleted file mode 100644 index 6b3b4204d7..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 -0.223092 -PERLIN_2 0.589059 -PERLIN_1 -0.581365 -STATE Negative \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/parameters.txt deleted file mode 100644 index 0fec4832fd..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.100905 -PERLIN_PARAM:OFFSET 0.749785 -PERLIN_PARAM:PERSISTENCE 0.960394 -PERLIN_PARAM:OCTAVES 27.0099 -PERLIN_PARAM:PRIME_1 40.6138 -PERLIN_PARAM:PRIME_2 61.0175 -PERLIN_PARAM:PRIME_3 87.8034 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_1.txt deleted file mode 100644 index f4ab414309..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.581365 -0.196529 -0.251092 -0.129792 -0.331063 -0.243506 -0.276892 -0.080451 -0.396119 -0.359775 -0.367571 -0.375403 -0.583877 -0.600213 -0.433206 -0.667000 -0.730207 -0.597004 -0.652034 -0.663611 -0.746119 -0.692967 -0.730701 -0.876335 -0.892405 -0.727578 -0.723739 -0.564331 -0.468088 -0.488808 -0.664805 -0.660028 -0.630792 -0.524399 -0.474312 -0.443139 -0.580488 -0.481039 -0.800572 -1.001564 -0.911524 -0.901357 -0.788429 -0.858484 -0.905262 -1.091118 -1.153703 -1.092191 -1.125297 -0.931559 -0.887913 -0.949225 -1.000548 -1.157858 -0.916321 -0.916039 -0.825100 -0.963569 -0.946300 -1.325529 -1.317807 -1.051895 -1.371837 -1.120878 -1.290153 -1.132642 -1.106899 -0.951717 -1.053646 -1.097485 -0.993622 -1.071263 -1.003207 -1.060272 -0.945896 -1.081059 -1.483716 -1.639907 -1.778137 -1.743444 -1.658571 -1.670091 -1.528567 -1.360096 -1.348333 -1.247859 -1.311556 -1.223970 -1.139654 -1.236625 -1.220851 -1.388255 -1.244178 -1.146154 -1.093360 -0.984612 -1.125281 -1.104519 -0.927790 -0.740832 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_2.txt deleted file mode 100644 index 3b2079e9c1..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.589059 -1.385024 -1.470957 -1.269762 -1.385446 -1.269712 -1.185030 -0.928904 -1.267172 -1.166521 -1.066362 -0.920673 -0.935076 -0.856454 -0.686814 -0.963540 -1.061552 -0.865491 -0.832564 -0.701943 -0.682610 -0.652618 -0.673153 -0.918331 -1.059042 -1.011999 -1.187784 -1.118172 -1.114871 -1.228534 -1.494326 -1.606674 -1.632721 -1.444440 -1.252203 -1.060226 -1.062564 -0.853991 -0.986832 -1.019786 -0.873746 -0.880802 -0.776611 -0.774251 -0.722629 -0.883309 -1.050254 -1.174258 -1.297810 -1.114437 -1.159611 -1.318001 -1.403207 -1.646177 -1.449942 -1.486702 -1.457905 -1.533516 -1.428289 -1.727821 -1.680758 -1.474617 -1.865750 -1.677722 -1.883250 -1.706351 -1.600958 -1.284972 -1.251889 -1.160717 -0.896049 -0.956541 -0.931596 -0.986854 -0.827023 -0.746164 -0.892252 -0.854372 -0.839080 -0.758932 -0.672252 -0.720025 -0.641433 -0.544152 -0.592160 -0.514846 -0.561344 -0.448302 -0.363627 -0.498299 -0.565455 -0.877873 -0.948297 -1.101386 -1.281993 -1.282064 -1.434546 -1.307456 -1.034463 -0.911412 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_3.txt deleted file mode 100644 index 520a51e79f..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.223092 -0.466707 -0.368349 -0.089874 -0.161719 -0.078999 -0.102578 --0.083603 -0.294051 -0.272732 -0.356278 -0.364104 -0.487348 -0.418455 -0.251441 -0.560986 -0.639218 -0.548377 -0.673267 -0.795272 -1.035669 -1.103795 -1.163568 -1.290674 -1.312494 -1.153418 -1.131051 -0.931183 -0.893717 -1.009827 -1.233752 -1.298835 -1.311961 -1.246482 -1.246256 -1.189188 -1.267197 -1.045907 -1.277045 -1.527899 -1.478772 -1.552988 -1.498229 -1.461283 -1.353050 -1.383894 -1.339477 -1.273635 -1.328624 -1.094269 -0.983792 -0.875603 -0.709414 -0.737601 -0.363175 -0.332673 -0.289505 -0.369777 -0.251481 -0.516427 -0.412752 -0.087499 -0.381547 -0.117950 -0.265638 -0.168071 -0.246383 -0.146412 -0.284670 -0.328228 -0.191186 -0.346995 -0.364771 -0.471056 -0.346459 -0.360055 -0.725820 -0.855841 -0.986781 -0.993643 -0.906214 -1.014289 -1.065209 -1.102837 -1.226516 -1.188260 -1.281279 -1.209360 -1.148376 -1.268678 -1.268572 -1.402798 -1.258439 -1.134246 -1.074161 -1.006970 -1.145082 -1.147652 -0.986590 -0.828954 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_params.txt deleted file mode 100644 index 4455122772..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-7/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.100905 -OFFSET:0.749785 -PERSISTENCE:0.960394 -OCTAVES:27.0099 -PRIME_1:40.6138 -PRIME_2:61.0175 -PRIME_3:87.8034 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/STATUS b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/STATUS deleted file mode 100644 index bfebf7ba94..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/STATUS +++ /dev/null @@ -1,3 +0,0 @@ -Current host : lx-774616.local/x86_64 -PERLIN : 17:15:11 .... 17:15:12 -AGGREGATOR : 17:15:12 .... 17:15:12 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/aggregated.txt deleted file mode 100644 index 244709c651..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 -0.917785 -PERLIN_2 -0.105634 -PERLIN_1 -1.276058 -STATE Negative \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/jobs.py b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/jobs.py deleted file mode 100644 index 72a3af4e0a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/jobs.py +++ /dev/null @@ -1,28 +0,0 @@ -jobList = [ {"name" : "PERLIN", - "executable" : "/Users/jpb/projects/ert/test-data/local/custom_kw/jobs/perlin.py", - "target_file" : None, - "error_file" : None, - "start_file" : None, - "stdout" : "perlin.stdout", - "stderr" : "perlin.stderr", - "stdin" : None, - "argList" : [], - "environment" : None, - "license_path" : None, - "max_running_minutes" : None, - "max_running" : None, -}, - {"name" : "AGGREGATOR", - "executable" : "/Users/jpb/projects/ert/test-data/local/custom_kw/jobs/aggregator.py", - "target_file" : None, - "error_file" : None, - "start_file" : None, - "stdout" : "aggregator.stdout", - "stderr" : "aggregator.stderr", - "stdin" : None, - "argList" : [], - "environment" : None, - "license_path" : None, - "max_running_minutes" : None, - "max_running" : None, -}] diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/parameters.txt deleted file mode 100644 index 59ba741905..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.494279 -PERLIN_PARAM:OFFSET -0.526799 -PERLIN_PARAM:PERSISTENCE 0.0911083 -PERLIN_PARAM:OCTAVES 43.0492 -PERLIN_PARAM:PRIME_1 123.299 -PERLIN_PARAM:PRIME_2 42.4258 -PERLIN_PARAM:PRIME_3 14.0702 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_1.txt deleted file mode 100644 index 6aa944dccf..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --1.276058 --1.289017 --1.314341 --1.306601 --1.296437 --1.293440 --1.259407 --1.266510 --1.294486 --1.261902 --1.202479 --1.080475 --0.954164 --0.885534 --0.858941 --0.894787 --0.919912 --0.916939 --0.886507 --0.799550 --0.721154 --0.650200 --0.537956 --0.483812 --0.489635 --0.525394 --0.546662 --0.527208 --0.534832 --0.533549 --0.538252 --0.584050 --0.611137 --0.630059 --0.650202 --0.616093 --0.568181 --0.463276 --0.334508 --0.259597 --0.221372 --0.259230 --0.279580 --0.244302 --0.207325 --0.170186 --0.177288 --0.240439 --0.278604 --0.325685 --0.411518 --0.447688 --0.438482 --0.430901 --0.426508 --0.473419 --0.523455 --0.492174 --0.429854 --0.320462 --0.242691 --0.226471 --0.221185 --0.262628 --0.292571 --0.326766 --0.377534 --0.383441 --0.373359 --0.364832 --0.330290 --0.341756 --0.378785 --0.325450 --0.201339 --0.014930 -0.131198 -0.218084 -0.307262 -0.331535 -0.323047 -0.275638 -0.204499 -0.189781 -0.216423 -0.234694 -0.244237 -0.196780 -0.140343 -0.139795 -0.132064 -0.149348 -0.135500 -0.067575 --0.002818 --0.038351 --0.033175 --0.039802 --0.104931 --0.282153 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_2.txt deleted file mode 100644 index 9527f5ea7a..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.105634 --0.100522 --0.094477 --0.166631 --0.242055 --0.267233 --0.351269 --0.418058 --0.423433 --0.455156 --0.503687 --0.535205 --0.602964 --0.629293 --0.605334 --0.598246 --0.588567 --0.648452 --0.705977 --0.761218 --0.784663 --0.690549 --0.595504 --0.441816 --0.322998 --0.240974 --0.082616 -0.026633 -0.111952 -0.206176 -0.291269 -0.362596 -0.390792 -0.289982 -0.127689 -0.000994 --0.086106 --0.090324 --0.148248 --0.241375 --0.259151 --0.279786 --0.291397 --0.328535 --0.389958 --0.377995 --0.280737 --0.158372 --0.106091 --0.142807 --0.139820 --0.078912 --0.035823 -0.057418 -0.107112 -0.097244 -0.109350 -0.077772 -0.052136 -0.081830 -0.120261 -0.196251 -0.272728 -0.294216 -0.300526 -0.246943 -0.116525 --0.050187 --0.175115 --0.301600 --0.427862 --0.456478 --0.450396 --0.398868 --0.320212 --0.349825 --0.460267 --0.567451 --0.631795 --0.652977 --0.663271 --0.674428 --0.682635 --0.626163 --0.539750 --0.498320 --0.505975 --0.578888 --0.635684 --0.598530 --0.523332 --0.361034 --0.160381 -0.022807 -0.185816 -0.259100 -0.276090 -0.163135 -0.001742 --0.111572 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_3.txt deleted file mode 100644 index cd80bec7c2..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.917785 --1.018838 --1.197085 --1.346518 --1.465782 --1.457947 --1.433721 --1.430564 --1.396554 --1.348945 --1.213771 --1.091774 --1.050692 --1.067291 --1.040706 --1.000801 --1.010901 --0.965566 --0.865274 --0.667889 --0.431604 --0.239372 --0.105089 --0.069473 --0.069545 --0.099554 --0.139350 --0.160356 --0.109202 --0.012531 -0.030695 -0.054757 -0.070031 -0.092023 -0.121743 -0.129957 -0.118527 -0.101591 -0.141964 -0.266738 -0.345876 -0.392401 -0.430221 -0.358497 -0.240463 -0.122590 -0.008486 --0.058995 --0.075277 --0.162975 --0.315639 --0.521310 --0.729615 --0.851158 --0.979655 --1.056785 --1.059049 --1.085967 --1.124672 --1.129564 --1.147745 --1.190867 --1.211475 --1.265556 --1.317086 --1.291337 --1.238050 --1.188747 --1.142334 --1.134089 --1.132725 --1.066024 --1.017221 --0.914666 --0.800777 --0.735933 --0.626698 --0.565983 --0.484094 --0.418266 --0.429310 --0.380164 --0.258859 --0.067478 -0.094606 -0.175094 -0.213959 -0.182170 -0.149065 -0.171849 -0.179785 -0.163891 -0.149761 -0.055666 --0.022016 --0.015994 --0.013374 -0.003331 --0.046131 --0.194030 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_params.txt deleted file mode 100644 index 219b62155c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-8/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.494279 -OFFSET:-0.526799 -PERSISTENCE:0.0911083 -OCTAVES:43.0492 -PRIME_1:123.299 -PRIME_2:42.4258 -PRIME_3:14.0702 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/OK b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/OK deleted file mode 100644 index 9590cb949c..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/OK +++ /dev/null @@ -1 +0,0 @@ -All jobs complete \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/aggregated.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/aggregated.txt deleted file mode 100644 index 48b8531624..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/aggregated.txt +++ /dev/null @@ -1,4 +0,0 @@ -PERLIN_3 0.220371 -PERLIN_2 1.032522 -PERLIN_1 -0.137903 -STATE Positive \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/aggregator.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/aggregator.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/aggregator.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/aggregator.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/parameters.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/parameters.txt deleted file mode 100644 index 2e4f0f7b04..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/parameters.txt +++ /dev/null @@ -1,7 +0,0 @@ -PERLIN_PARAM:SCALE 0.971949 -PERLIN_PARAM:OFFSET 0.568165 -PERLIN_PARAM:PERSISTENCE 0.332226 -PERLIN_PARAM:OCTAVES 8.48231 -PERLIN_PARAM:PRIME_1 106.04 -PERLIN_PARAM:PRIME_2 17.4819 -PERLIN_PARAM:PRIME_3 56.9629 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin.stderr b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin.stdout b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin.stdout deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_1.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_1.txt deleted file mode 100644 index 36798a3f53..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_1.txt +++ /dev/null @@ -1,100 +0,0 @@ --0.137903 --0.157851 --0.192276 --0.201670 --0.192839 --0.193214 --0.209423 --0.243628 --0.261796 --0.213269 --0.207591 --0.203993 --0.142490 --0.122206 --0.157129 --0.193732 --0.206432 --0.177612 --0.114381 --0.050740 --0.070342 --0.154469 --0.151716 --0.137877 --0.155888 --0.199095 --0.226091 --0.254674 --0.326284 --0.337833 --0.312344 --0.317023 --0.346853 --0.332528 --0.238504 --0.042655 -0.146262 -0.376535 -0.617211 -0.752626 -0.797129 -0.714055 -0.660213 -0.707589 -0.786058 -0.902157 -0.982988 -0.972517 -0.950945 -0.917937 -0.833802 -0.834170 -0.874761 -0.874663 -0.835114 -0.714452 -0.615202 -0.641686 -0.698232 -0.833272 -0.978281 -1.070483 -1.118218 -1.061277 -1.031902 -0.998036 -0.965574 -1.010296 -1.079127 -1.148032 -1.260956 -1.285149 -1.247059 -1.290888 -1.424147 -1.629905 -1.764537 -1.819917 -1.898802 -1.893787 -1.855403 -1.728917 -1.536779 -1.375375 -1.281240 -1.209446 -1.131790 -1.009449 -0.933443 -0.938227 -0.970148 -1.049769 -1.076923 -1.035402 -0.981504 -0.949433 -0.958861 -0.977078 -0.958006 -0.802606 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_2.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_2.txt deleted file mode 100644 index ba557199f4..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_2.txt +++ /dev/null @@ -1,100 +0,0 @@ -1.032522 -1.030645 -1.027589 -0.938300 -0.861544 -0.832993 -0.698715 -0.604825 -0.609257 -0.593477 -0.491201 -0.341277 -0.208709 -0.134035 -0.096478 -0.102808 -0.124913 -0.090875 -0.066149 --0.012408 --0.133850 --0.194818 --0.209263 --0.095881 -0.010749 -0.085326 -0.237955 -0.299167 -0.320499 -0.401893 -0.517178 -0.629623 -0.655076 -0.587512 -0.539387 -0.574432 -0.628337 -0.749487 -0.803470 -0.770847 -0.759350 -0.693500 -0.648396 -0.623356 -0.603426 -0.694348 -0.879540 -1.054584 -1.123458 -1.100816 -1.105500 -1.202947 -1.277420 -1.362982 -1.368734 -1.285116 -1.248007 -1.211633 -1.180222 -1.235564 -1.341232 -1.493206 -1.612131 -1.618121 -1.625000 -1.571745 -1.459633 -1.343551 -1.277370 -1.211264 -1.163383 -1.170426 -1.175448 -1.217470 -1.305274 -1.295011 -1.173072 -1.034382 -0.959745 -0.909275 -0.869084 -0.778851 -0.649645 -0.559430 -0.525067 -0.476432 -0.381578 -0.233781 -0.157416 -0.199901 -0.314752 -0.539386 -0.781042 -0.990634 -1.170137 -1.246885 -1.268126 -1.180015 -1.064679 -0.973186 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_3.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_3.txt deleted file mode 100644 index 2bb0cef781..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_3.txt +++ /dev/null @@ -1,100 +0,0 @@ -0.220371 -0.112328 --0.075019 --0.241588 --0.362184 --0.357721 --0.383737 --0.407682 --0.363864 --0.300312 --0.218883 --0.215292 --0.239019 --0.303964 --0.338894 --0.299746 --0.297421 --0.226239 --0.093147 -0.080922 -0.219209 -0.256359 -0.281152 -0.276463 -0.264202 -0.226745 -0.181221 -0.112178 -0.099345 -0.183186 -0.256603 -0.321784 -0.334316 -0.389554 -0.533441 -0.703395 -0.832970 -0.941402 -1.093683 -1.278960 -1.364377 -1.365686 -1.370013 -1.310389 -1.233846 -1.194933 -1.168762 -1.153961 -1.154271 -1.080648 -0.929681 -0.760549 -0.583628 -0.454406 -0.281967 -0.131086 -0.079608 -0.047894 -0.003413 -0.024170 -0.073226 -0.106088 -0.127928 -0.058349 -0.007387 -0.033465 -0.105058 -0.204991 -0.310151 -0.378775 -0.458521 -0.560881 -0.608623 -0.701672 -0.824709 -0.908902 -1.006640 -1.035850 -1.107446 -1.143986 -1.103046 -1.073115 -1.073421 -1.118115 -1.159422 -1.149846 -1.101513 -0.994839 -0.942165 -0.970280 -1.017869 -1.064312 -1.091185 -1.023493 -0.962306 -0.971791 -0.978662 -1.020211 -1.016806 -0.890728 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_params.txt b/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_params.txt deleted file mode 100644 index c3e63c5f53..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/Run/realisation-9/iter-0/perlin_params.txt +++ /dev/null @@ -1,7 +0,0 @@ -SCALE:0.971949 -OFFSET:0.568165 -PERSISTENCE:0.332226 -OCTAVES:8.48231 -PRIME_1:106.04 -PRIME_2:17.4819 -PRIME_3:56.9629 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/current_case b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/current_case deleted file mode 100644 index 331d858ce9..0000000000 --- a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/current_case +++ /dev/null @@ -1 +0,0 @@ -default \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/0001/files/PERLIN_active b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/0001/files/PERLIN_active deleted file mode 100644 index c72400474a6698dd549e01355c6aaf9d3cd52a3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 OcmYdcU|?XR2LJ#)i~!02 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/0002/files/PERLIN_active b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/0002/files/PERLIN_active deleted file mode 100644 index c72400474a6698dd549e01355c6aaf9d3cd52a3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 OcmYdcU|?XR2LJ#)i~!02 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/0003/files/PERLIN_active b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/0003/files/PERLIN_active deleted file mode 100644 index c72400474a6698dd549e01355c6aaf9d3cd52a3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 OcmYdcU|?XR2LJ#)i~!02 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/ANALYZED.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/ANALYZED.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/ANALYZED.index b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/ANALYZED.index deleted file mode 100644 index e1de74ede38847ae9ea3fbab4b8848bf368fd192..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|=XU5D5iRZ~y=#oB{R# diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/ANALYZED.mnt b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/ANALYZED.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/FORECAST.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/FORECAST.data_0 deleted file mode 100644 index 8dcc722d5a1cffa4005c8b9c908d82e59e322b5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2816 zcma);c~nhnAIDFnluO)1DkK!wcp8+7zLH8r87f4kLlT-zU4>jCnQ|{p6cv#YMVg*U zoF>ilaOQI=beaoI@8-RCt@n@jz4v|A`mVj7{oQM?wV&Vf`942eTU*<4G#bsuY_pZ+ z#wA)y=(Mv^G#V)VMpv|@9GW{N1|SS)z1qE zV>`XeV$)la)tKSF`EDHv3_3N#J--5tUwsc}coB?w|4l|yKaXrz4*J!x>p5mCh3BxB z#$vHXk>&g|DUgq354bv(K>BNazV{XmuDf=q^v0ATdB>jXmv5KgLrYWpY3EmDbX$P@ zxjEG&w@EBCHpnJ%5BY}~_7BMEAyzB~Kalw8I~Ydn`*8JryT)IUMKX4Xi^sez2aT_+ z+iP8o`61yA%CUvG;PFF->UJEwig;x{hEH9WEL)8&=}>bDeLl=+hEn9wWuLCTM$!N; zu>a&c_-=jcYaL$!R$$~6ik5#EqqI>Ph2MYjr~NnlNm8HtlfSYub| z22^adrlLdyBf|vq;~MQ)dDhH#_(m(fY4D!)xQbDv=sC$Nxf1R>Iv*rPeg?g-CwBIf zkJ#lV<45lD5azD(V4NQZ({_4Vj20DO>VR5^e1tD~D&2o~t#dg%8Nxd`(+coaOO&7? z$RTWU%ANN#1=;Fb~QnQ+K9A zC$xj?L}I(=jK*Ol?Q9bMYUt@IhioS z>m5jP@k!Ts!-agnB>NIp3v_z~p^_n=p}fLsP&6V!CY5pn%X`pX8zEky)eE=P>XPzN zVmw)RUwF!miw&1HmZo=gLDk%(^GkmRG(_7i7iLu=qUNa0;Ikai8QxD@qT685y^3*D zvmSfw=2r|)Z$ZdJSuf3_l^``S=B+J!Ozw1|bjX^$($fACgujteJJFIV3b zx8%ZDI{T!|gj$lL$16B?Fpqc}4Ho+MmJn5o_;-(J4Ww7;bYAP5XJm%a<2>)H1tkAv z(QD&)CakVpx6UtVhG)YTkBy&2&xMC#$&df% z@X34aVTG<55!v4rmb*^6jkq~DoOFC5AcOXHp|{VskiBjnW(+6tNzwVsxMIj8eHp4h zjg#UK>%!=ZdbB!X<@Qmkz^I6L45u4=*1RN4zjL!zU92S!fA=}JJ*tw}>eh^u^p_CH zO6O*olt#i!y8mwT+$!*dZ96xuE5i+H)f(%vk!ZS1WBVl*dIJ@xC1&An|A*mfJ{z8W z`-6vMg;;rJ%t&WXJ2oBkx6D4v|B#z&B^Zn(BS#cvNs9KWj_9R|;*tNU{iIDBA0z!jmc zPUFdInKpPt>(INkDLy6@m-7b%*!gVo9sU$5FQ^oMkyZum)(d4ON}r&$>VceMQW?e@ zUA6RES^&RnDJfYs4%x9@!g*9G8Otqun8|weq~`IZLtbM`i66bQ$tU$a36l(oFzeux zimPUo^##o&JizzpaBnTy-RZp1ks%~cXE!mnDp!!Q{kNSQI11Tz&m$N4ryQ87qMGWNF;rO=9(<0_JREQYj!EA7&!6D!Zo#syjt53 zWGs3Mi-fSvjth&(oGI_8o}W%}5KFt1;Zx$vTbNQ)seGUe1?|+dxT8xnK%pPT%I#|zqeEk3CPo8?! z#KK~;nT5$#vo%ZT-x>V=h|*s@=oso=mJ)r5mH}N?-{8lDYF6pmdOCEP9OW#gEIoaF X1Kl5%jjN}#m-F!hl<~jEcmDqcbT%i* diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/FORECAST.index deleted file mode 100644 index 0a01a88233f0d5180fa31cdabe260c2ebed8a384..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|?8nAQB3s7+8Rq3y1?;gM2*w^bGY37(#&nBn1Ku%nS_DK-wNiBPlb6 xDPsq#!lldzstjZb2q2rr2jn}ty9c?tJBGNr=o!G2f@}eT1|XIPVn-kb0RWx67heDX diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_0/PARAMETER.data_0 deleted file mode 100644 index 1d8b6c18da5dcf0dbc19c0197d66470d6b485df7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmWFy4Gk4wU|-#k_itkI+GTX89+VLLZ&5@3^$p;rp2r_8|RO Jz<-AS3;;3 zvG422ayZU$jwQw12_`?;R``Q5+gbKj4-xw$zni9|Bh zJz;2Ite~WzM7qjFA_1W=MPYNoL-HWxK!}5oUm}MD7vt0S7bC*!WM^@2-{4PjIuqF0 zbM;8K%mk{qzq*_${Tj_owueB#7^=S5r(o_pfqX^jzclO~$2y<)B>Dpe@=Tm;kV_lG zYBk??I5dHxT+;`FWXJJPp5N4+a2D=OXgB88XW+vH$xN}T9vtTKKGW{ngkEx@q^#0z z9Hp5mwKIm0Wo@B8EKbMR@fc?}F&56OB#aeyQPJ*+#`MYPVbprI@3@xQ0RC3LWYy{4 zhr8NuW!^m0fR6*NxVBvF$B+$mF-pEI_*Hs><#CQ)tmWpDab9gj%VG0x;v=ZIQB`pN zK_Y%Hr@vvUDg)og);o!t51;_;c}&EM33N9Q=zlfJ#Liv{Ww`b=j=eFE5i(@sVUZMV zX5$ndRhxNVt4T-U9n8&H)P5v3eVx2v0403|(`6qFql!A?#;oN4=Ij%qc`6Ly;0>9I zhh5$Hd{e7-dH@w2XC+7cgX2(*D!cRHt6y=UZNGZDOedypJ!>YI(S^My4%601b$AJw zAsp8!XezpPh+SQP#>F98rWw_kUQ9h=_sx9_w9Y@ZF{BD~(0D1OX=N;5X zpwgEbzu9XTw#^vvHyN;C^P#&=P3%`N7kgk&igXWrKkQ|%L8ii#joC4t)4lM{bTHg( zb0eI};IcHyp+c9BA^o0hJ8Y3#v$89D0l$~reOovD9J!sW+cen}boSmfD`ebj)`tSo*`JiZlPZMy5b?E*p5X1O$+My77(TpTB*4o`JQq zTHy^r^>|D>iX3ZMgEh258-kXWu;Yc1#zBSXcAzgtmyI`RwTFFQp62{^~3fkxD@^uzxp;`&qB5GGQT!^}I zL(lgT+_Flrmdt*Eopyl--_aY;N9F1EuQU3wXpN&c%eEUeCj;3oCL`E7&#Pn7JcwQQ zy>{oy4PtW*ImdaJf*#)++iT{upnodG&26Lr<}6&}Zq>g44Knw_%mNkIYtfmebSeZa zT1Fd_M%(M2l~)w&EkeY2ouTH?P;Z1G&J>E*zxU~ zA>1Ubek)t89|L{&9QPJsqHIuPnafvg=%;6WPiLtLm9*J6CEDw7_vBfp%bw*}Ao7IM z{$L#V1(}7ek|{9iDAi}Qy9Wl1t))UeIzhZ?3{n|%SguQxbMqJl*P@6j)0bnQSUMiP z`d}39ss@`a~{Uv{ypimq`@|5ooymAT>uSw5_Wz2GEqi}CwrS! zHa5kjx=1r>G40x7u)tdy8ae+{o@2QV^`pJH_3Y9iINh#l&AC4B~kUc6U#%46U*KHh7} zQB2$!Xr&wMREsGO%=VW2kpS`4*M91&Dni3r>j{R!@9_1-^*?B|iDes4zQ!fp^%FRS z`mqu=9AV?gH(g&L#b)8#wJa(9au#~)-Cg27L-fl$TiPXyemwDK&wPBy01`!N=&0og z#ytx)GZ1H@Df1E0(MFIXEm=>psS#y&=abU;8*$*suH5rBcRO-Y<@)a_M9wGM^>|_m@m`V9d}-!sY@DW~E-$Czqr~J= zwox^5>{D^QyEur8gMA@hdP8_gJF>4bYY6XX%M^!`%6YUGae;w+f;i=lm zoz}K=4Bf90(0!AI*URWFfu3VnZfF#$zH%)>1M)mk-!BFncfR!PtNJI=}1D5cn|u2}XO*C|>| zoWlYmIWd>DF_aP%qtp}o{Z{szV2uC`RnitqHZXfpYd`0Fc~A#dZCwY0iZqLxznt!_ z#{$>!+f*_QuZVjza(DM)Z-X|2-b{SA+jC3DfD%wAZV7wm^C7y~h}u2W2~qa!559rT z@VVW6EQbv(g37lYGcZS(v#j<`1wKU|Hvs_9RLSOEn8;J2&gyawy`6n75VQWTt;hctj7wFI diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/FORECAST.index deleted file mode 100644 index 9e25666ab4f81188f8c048fb98c99578d48a466f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|?8nAQB3s7+8Rq4~QMz-Gf}+9Yb7Q^bGV28A5@efeWO7fuRA2<$>4< zh(SUDu0cMYetO1GWen^pF diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_1/PARAMETER.data_0 deleted file mode 100644 index ff8922efbf2a6712c38dbe9f89c69744e7d03ea1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 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 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/FORECAST.index deleted file mode 100644 index d90f7a9f75f8592a273bf46092a3362b2acd9859..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|?8nAQB3s7+8Rq3y1?;gM2*w^o;e47(#)7fgL2tz|g?Vz#t8z?SV9s zGDDa$up(4td_XZrclRJycgGM{7d->0(gu)rAZP$$c_4NIVk8rdV9J0NfdI0_AU*)K CfEQ>0 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_2/PARAMETER.data_0 deleted file mode 100644 index aad9490e0c2c6ac9e83a2f802e1065174a756d7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmWFy4Gk4wU|X-u_kG{{obx^B+0S#H^L);E&}cN8AAvyFqfS~|*=lNQ z>LQ}K5Qu~9{H7&_W{)7Qv*XDQ2Rk8;1=|w$b#fp!Qv>FY@~N5+ovmvsZZ(G#S13Se{|J`|~r`6iX^T#d)EIvd3HZ_8~v-%}=cA2DUG z@}~WA{S77C@k*JqUX7GfH8f}6^xh-)Hl6(`WKqP~V}52ldYlw@(D9n$lE5sz z=vm?O$(IAK2`9R=%do{f=xbeFfgj`r`NB7=)W+9jMXsm0an%9kO^I>$zfSrAK-^ARI5 z&>_`t%nDyh;^c8*I`e;b=%VAIho3-VV8Jy)r*BK@I~n zvf}%7jXOpizw~1KY!{}o7M0AyuL(eK7;kPX2G^e>RmXGebWUrn>8k>3I~PWh5{VJ9 zUWnw<8Wd8T)EC?_uKpeOiXxN0E4x4h%jN9n{LuBQ=qOTc?fr~h$+nE|Z_0PoAM@yK z#H8io>MKKQd^cI*N?JTSn@Y-4jy(4n=RKb<5`KG=63%3^!YQA_+%Fw%-A^4M%AS*y ze`7vYUs<-(Q}s(A*{x$$Z22-Z!D@zm{4in={>paxglLUHl~fvy5!5GHaDCSHYaT&X zM8eIB6w2kXD+jylM7ho$p@5A8H&hiHFUx9RPAPS+wI^emZXCVGJAk%*f)af2EbHSB z`=95qsq0Z;R{p;aHndecjGr}m=PQAyxu)izVnZhf@QD*$A@rL&^6@)Rb_Gqvmv2jH zxArM3{NUFbs}H)mo2Lf#anL>dDF=Rs0ptC}Uic6e?3yR`9pgT*vG-IA>iYRQ!ExfUxX$=id<5okwb=MgS9@4*c>FTw>3YY(4fMi>9%|k4TSJj<*-VF*n}c?5^EMz zUCJdhv2)NkG`Z|^odTgP62dMR0{AGuUA|k>15PxHiBx18lsHOKb!r>H6WgI%`RyC* z;@6<8zq5zLmGWHGgJsCRa90_%`a0y2ulQPSRxNVKblN(1p#vH9VqxTTOf&NJ=H??W z!|})$Rq8XHu8qjVueGIDXDg7GB3Um`5ucG^$qm7(H!G1@UY~ocBC?S6cEn$-yM^Fj ztXYII{|Z)?MwvFzWnjUJF-Uf9h3)9O*A3$bfof}V2zPN3j71;q%1EccO(%hA?bJCS zp=Kh*2{Vv)K&~OoZwgkU4|{j0OvCNXn}ki$r@=LiD@cEZ3b}rZe$givz`W{s;qm$< z=;QrHS*>FLR&_#g>eUL|r-vxXJ!L{hlf@)Uj0LkZ8Dr5yOfX(L8ap7p2E_QXWwB}| z49(e#O*t@N-^o1!?!(Ip2(~6WH0Nq6U z%RDxHP)ya7q&?{YeYI=v1qXXzlQ!k9Iajg%*!yH4WA__T*bD;O)kM$ zzrA+LFat12hrblNGayjIB^oEb1izQw@4Th92NMaleR#KxeJ|BPS{^yk6F@t@_NDMB5e$=^6YXx3 zpuezu@Z2jB9Fd6@j29jUtU28@gJ%*zIN;ZYiRP;Pdej~xvy&HaYjy88|PYH8^k>F65#+0xe3 d(J?YG&_eLCXWCx$K7YeE=pwuN-^w5U{{@w9WOM)k diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/FORECAST.index deleted file mode 100644 index 718956c2429ac107ac6a949bdf99ae9822cfbd6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|?8nAQB3s7+8Rq3y1?;gM2*w^o;b38A5@eff*#pzyPA9fwVo4<^$4> z?(RXZ?v5d@E_wzqr6BD<&;Z2pKtS;0A`{!&_pC<#xP~; CUl(Zr diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_3/PARAMETER.data_0 deleted file mode 100644 index 2fc669aaf73f0167488b0af351c37e2df9143ad2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 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 Tc-?n>;Ogg0nfMp`{rvv}Xmaj` diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/FORECAST.index deleted file mode 100644 index a879653abd85c68280bf0c8479d8b8644805da79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|?8nAQB3s7+8Rq4~QMz-Gf}+9Yb7Q^bGV&7(#)dfeWO7fuRA2<$>4% zh(SUDu0cMYetJeQWz0Y^AZP&6(m>h_NFymThALxV2djcBGe=cs2vY`81y^PdH5~ve Cix*u0 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_4/PARAMETER.data_0 deleted file mode 100644 index 90b4c5e871dbcd891c74ca6124bd4b58b42a60d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmWFy4Gk4wU|=+q#9{3i8e-KDmR6!c_Ru*q$?Cj3rf-y(WVn=NJ%u=lcgHuTFctk zI@WY8*Uj$Y+TClpwp4z%Y37{YAHOs6`<(MW=kxhKpXYO)@AG|L&*w{_P$)tq63JBm zkg=f&c?VgUbc>Hf0#AVoq74daIZSe^SEM@U4X9+F7%e*LvZWA}70K zYd?NB5lD}2=>g;5g4JXXl~}gMrb8;F4Z4{YnQFBxoN$@><*8IPrVQDsel={wS?h@g zt8~M@ZDnj$YzYM3WZmgcXve9lyD?|EeGqxL{n_o3F-V(hEuqMaK#*$F;`)J!*o+!! z(bjG_t)m=R<<^1DwI8+=*|X4k&r#z!nF~If`Ndb63)ov*9PRGWg{!3lId@WKAjqHK z$m(FD;)!Vy^9~CkGZ&TiSunv6tr*#+J`Dkn`r^}KOxzfJYiE4;a^`~?f700$avVG4z^q=k?~F4mW+4Gm=1f!=?1>-3X8JW;P0E{c!A^xjtr zH@1(%`gXuAp?#y+wj!v3F*%RuW9Az(GDzB9(=z&}Lb*_i%~Y8!o=4Q`Rl%-IF1G1U zJl6K-!gWsoBR`RYsFT{$S7%trl@D58+r@y3_;zvMiUv4u?sUF%vI$A<2Mo@w7((%M z@D45GQT(bJKgpxzU&aDyfyBe_zxmtw5Bx3W9rqW1R(Io)F00HymS4OuL}v=muSGRJ zk)48K`*8f*ZDTm8TO&(}m_Tv6Ro>`rE+nL6skLbXFg5kJVDob^5@&uyt9ldy!wXV< z)nmvH^6V8}%E3`tOQ~ATIgnrZmhS$I4uh8xhxEq_L9TLsXt;M2-9a9n>I^3O%lxSB zAxxxi3!RN~{0J*!XRVa`-4IMl^T|ruyEq)5 zfLN(E`oerK^LGUZ~lqmD+%rhhqgq z(KLbs+xd8Nd#d%HNIf%Q=85pTgK;y#63>iu< zhWIKq?xqhzAoDVRtHC((=$Go}eP{4<^{VpR*(rQY^GfLA8}+M8uFRiC(!dM(eZEGDE&A7@kgwu+OD|zwT(yioEnMfc@lpDB@VnFQR?s~g%RE))% z{tJ9O^Z(#a@gMl(U5S75S5>ygvixE%x_fWljn(GW`NdM}>q0e%FOw*Vj42~7KW3+7 zY@!mY6>{^{j=e#?pn1sto(AIlE(`nU$F)!wc<-~>FM;^hS4trDCiJOfI1QDFf+`Y} zF?4M|v)@8LpRj1OTk9Lh^Lub9!j;+qkI?CNpXnv|IWu{_T(=M<-e(vElqnpQxqZ=f zum!O?LeaV@Jup`B)3G}}faE?k>COZn^h?(59=863@d85UTGlwaD_zcTw)foDQz-!-LHS;< zT_9!xHfMcqKJVy5>Vmq;`9GRrbe+9qo;rx6U`5d@n!Nt|HcHROiwXMf^qjNNO$7Uj zoDkP95~U-jTb<4oVlw#b(+A}Y;zydDdB0gJ1Z1X{#jFVQ|c=Bu>DHN693>nd4@&%7mT?#)i>MAiA5%y?$6n6ICEgzm{|L3qV&C&u&u@zDm5nr_zsRhhjV`uDSIAf zj#e{)Wh8B7U6@lPr%*mAVS2&$6T-47tN7MUA@=GyyQESs{A^lVM3OdfasmX5K+>9?#qji$(VK@#7y%rH3!!^ff@&BK{?|55v_U${Q zzfb3|z8+cOD}%g8+C2UJ54wam7vxESyh~A4RaNcJ#SXHP@(u;XZwm$TPF00nJCy&l Um|nQ#blJ)MG|%H7##jFT1A6%&X#fBK diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/FORECAST.index deleted file mode 100644 index 7e09d8c4826b52cd91af4653373e0addaa64c232..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|?8nAQB3s7+8Rq3y1?;gM2*w^bGY(8A5>oBn1Ku%nS_DK-wNi^8sl` zclRJycgGM{7d->0(gu)rAZP$$c_4NGVk8rdVJ5Nz#eo3XL?mTKFw=k*p(_LN0pHOV AasU7T diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_5/PARAMETER.data_0 deleted file mode 100644 index b47d88c6cebf625aa84aca892c8a3772cfb3ee18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 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 Schf7->$W>}$G^l6{{H~ef&@AM diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/FORECAST.index deleted file mode 100644 index 2f03d8d11b2b9174a5ee325aecfacc2ff9e01069..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|?8nAQB3s7+8Rq4~QMz-Gf}+9Yb7Q^bGXO7(#)dfeWO7fuRA2<$>4% zh(SUDu0cMYetJeQWz0Y^AZP&6(m>iCNFymThALxV2dl!R%n+swq6)6e0%|${GL;u^ diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_6/PARAMETER.data_0 deleted file mode 100644 index bb97f570e88295188751eab59de46eb5ace3c113..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 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 N*w4(W|7w5m|2x}W2VwvK diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/FORECAST.index deleted file mode 100644 index 7ef99ebfde3178eff7b7dee85729c786d78e6ba8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|?8nAQB3s7+8Rq4~QMz-Gf}+9Yb7Q^bGXO8A5@efeWO7fuRA2<$>4< zh(SUDu0cMYetJeQWz0Y^AZP&6(m>iCNFymThALxV2dl!R%n+swq6)6e9BMiMH0c*~ diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_7/PARAMETER.data_0 deleted file mode 100644 index 9bc6a115435720b4db859ae1ea7c1d1a2e21e5fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmWFy4Gk4wU|L>eUt0ts$F#WOj5Y2Shtbb8^mzP*XXL~LQ1qEB^Ik9Qi$jxirl{L z_uDWS_sh&giDt}@O=YKNcc16?$M3iMJJ0idp7WmfJm>m;&UtAx8f_MZLfNllY@oMK zSyg#6#fM6v5TWj>%%urE6gQz9gqkMQ`RHkK)Sk}{l}oF0Tm_h{Td&^`D?n*V>hbF{ z#_%O)`l40R=BUngF#X+*Ee7UMLp}C_L{!OY1Qd1ZWo7;Wsz&X@WFe;(wy{% zP7cFAd7Vdy*)UY^Mhx$?d5`;n&->m+yv0rV)SGEC0|>n|x#d(H8!snmJ|8st@X6jX zs%*R)e*Rx)Dx3D8_8eDcMnf;=zP+?h`%)ixQe{T0?p|y#jhZrB)`us|v=sd6LlXfnpLU#_gdbtc?19?LJ|w8Bqy`OilzS`i;GJLUX}X5`(h4L0d%hDSy1 zDe8763f{+Ptz|G^=cqn!h&(YGcj^ubpf&Dv(~SBS4|v`AJ9^M+(cT0 z-tJA!q%lzRKy506@VE4bNW|00<~;$UV(Y5N6;CzSeEkZdFz@C|q*oKmxIG`w%&H?K zB=^kfo%Q5&-%oqyt5lL2uV|N|@j^29!msYN>_RegpSRqFfdXR z7yQpisHw~Lf;Q={;T@ktEA;jg=zbZS_1!D% z-S*v%3qNGy@vgRmRlgU(U{j#BEvF83ZYN|$A{y{!>qH=RkdC4vy}Kl_5lp81hree_VPuQ_CeV^Dn8 zU^?;lV0DG2JtmWbjEMTt45B_US$eE8pLo)oUlzz#6292FmA3A55_$65#W#{iKRG$m zw>FVt-o@#RsCuG$XU)P0Mjo-Zx6xhtA{jfUL>DNzmf@_C?0i?lCOqjeFj!#M@z*=p zh1L99`Fc&AxX5i!khsVV~ zF23~t7x;wk|H7ZzKkz5~694A!iNQp|C7WRgFGohvkc(_T=A9i1e2m^T^Dqq>!`j)Q zO|54>VqIg&)`9~cq2TIr;ur2XMh-raiDZq#Jd{37&wL#D@v4@(5o2gK=~@wWln9V9cKh$0lte4 zJRib4kDvncLmXU6QWr*O2g0T*d-5LE;YUlQ_N4>aaP|`TPgbPi*Qa+brq`w+F?#*D z&BfOk)3@;7+){{7jUBN;{w0ufOuC*d$N^K&+oC-=5ayak|HAA=~(;ncn4f#Q1yqprjp$ zs7KYqC5NvNLw)VcNcE?XSh&*LQYRe|!f3VbEWvY5#L#gy2B_Z4jedRF3&jf_!P6`T zFvmDE{h8JfGNbpp(JVe-jk}F~t5^Om0><$Mk?Z@0zH=GPp=W;Tk z@ult7++tGPa*QKCRZ0@tAF))asH%I^8Tmk9d@@D`4{7DMCYU}D6 z>*#8m=+}^*=3DqSp8q+8~=X*4_I$h diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/FORECAST.index deleted file mode 100644 index c56041336052c7c11a2329a7ce301aee044e2ec8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|?8nAQB3s7+8Rq3y1?;gM2*w^o;c^7(#)7fgL2tz|g?Vz#t8z?SV8O zkal!;4{~*P3~_bQGk_{>0BHw;1|XIPVrL*mGSLX83}^xfAe)G!%n)WVL=}oMkPra; C0~dh+ diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_8/PARAMETER.data_0 deleted file mode 100644 index 674b8594d6374253673db7d04ddb484748b9ce82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmWFy4Gk4wU|*DxE<>V8DUnN&c5F$F(O2c3+R`wUQ$|;nh)^*l8KPWrNzIIglu)^p zVk`9!MH@Tiwsmpa+s>_hM+wc=oLTGqan8(n*7~mXKJV{c@AF>1pYQK+b#--}DkCG~ zY~$kOu#sXyStWByPDTb&{c5b{Dy_))Nwr%lS*ebt%4*5AkJer~ZN|J_PC6A`41$(d zlIhy-#zIr8$!CURl1u$FGG{BbN|aYkw#1ze`|d$CdHq%{z=O#kuilw3OqV?;CA7G& ztjp_(zna$6y-qcx`{jp-9}*elPymzWH;+LIxH9GQEFY6Y;~s$=dqP~jv{LHkRg!)B z>P)lRYBKYTx7K!V2Km{xz;EoqQ*tiT{?SbPhs5I^we#Xg4jG;l{hlX#hZr19V_$tz zL4=JuU;7-aAo0HZxsuFs;^EQnq9dswlNGr=!jNYqs4VbFjG&h6Q*v0E>{L$%oHsZ$ zcQ%rW)btHXX-&l8%R&t#NyDaju45xvkIsQ+YBO15YZakm-$eA!eTsKF!z42j<()d3 zGs$R|%Y`EPV-zngT%$jSg>Sr$+MATIVf#XELHMj5oTseFRXg1azQ0O)bSoFrQoZGl zYIP&VsVqO?8W$Stw`lBI)QkOx-QAD14S*3f&FX3ZA6M>|e0Z(N$5x;HX1YE+P`=%I z;GxHRYUck9$ z-Q3cAHmowHsNIg@U`tMVM&A!ytcR@<$#eLIvM&>HOhY)9x z89o>)LAn3W(>YtkNSQ(!pKFLvkefDMs4qZj#l2S*ZSQfxXwemkJP*c_s24}3@p1N+ zS@NqI0WJ?Er>a^AallKiKsG^uVd*r)ix0)>i_YbqJe-{$yKXFxhnjGS+A3>4E_U}* zN3(eN)AzkN=zG^uO3Oct&oZB7r1?@*g7x$T2gaFz}F{u$J1lV)4 z#z59j0F|oy^jHNRa@D>nsZ8jH@2Ow-9a(*_GPa9vcjuzMaO+^nHZ~$oSVSv^vQbuO z8C)^eh0@xBP0haTxTH|kGq+$eSb8`>anMM)-ETGif&Cc{AwbbdBs-y8H0E+ zHX{2RojfQic2AUxgzx3h2Lmnlph^!krv)-$R=jpgtX=~aX10E(6yAt_zxD%{>8%)i z7}-IO>A)@Ss)g-(92BL+2t9{5XtT5$?yl`Z!`{@$?6sW`HPFq8XBT`+EvRl99Qd@Y zG^qXb4y}4OiWQ1_(K-3u=BgV#NFGw~xa8D>@y27l`X*dB`@9~`CL9c%SZN<6V&iO$ zaH=(p4VNEfo#w3M!l^=_Vxl*IeT#X=lG+6bZ;w>Z|0o3OGVeQKsu1kV-zv2VgizN# zvCRfzu;(n7&<;yrmQt|dDRU47Pkho`xq~QDK3>x#^?%6Qg~rXpVsKR6*thN!k zgz_&U?d)yCFwoxOx-4`MH`e(?YDm{VwP@+T+&sm28K-g5{IUqw%oHxqxGzHCk6rN@ zOcC^}F25`f7UOG;J!5;jq|dvZ7O=IONRG{#7MHR`KpQN#n?>U39? z`g)99orInjn&9mU#D z53<0IDKd;6sDtx3Z@!s+CA<~rTJ9;&Fz0YeVz+K19{N8#bY1!%BXe6B>&JT_Q$0o1 zwvZ2|&(fq$x(J!WvH6zL-1ugb>WS5k62x3d_4=Vxglgt%)_|fA%D-+OcGKk}W@(Pj zKfos~{}=vD|As$lOZ4rpn>k63l0xJ$Kc=3YyZmqj=ZDS4F*FDd1ET)duhy{K``NtjJvpt5=470lsK9;!P;Yg`*0QB}wA^~uc#H_~pWON@_lQu(^;54+6XLA)s$b|$eC!j|tuWW; zq3`+0Yf;nrm}nm+4g!R*rpbFx7DClXY2V2}A&w3jQosFCfP{t?u~`idI;Z^(_p0*| zRv-LE9*zRby7C_(Zt}N@+00f4qxBq|sl%$ugv9oirv0L-KjWxx1 zg29PXQvJ0Dog_V0l**Vwr5c->n|zs=P>fBfW>l)o6lrCtF~!8xe3h~3my)yZk^KSt NgZ4-Z|9edE{|EIuG@}3j diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/FORECAST.index b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/FORECAST.index deleted file mode 100644 index 9bbcfc9ea707136381238b3647f5e3bb80653c3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeZo6=GmyU|?8nAQB3s7+8Rq3y1?;gM2*w^o;c^8A5@8fgL2tz|g?Vz#t8z?SV8O zkal!;4{~*P3~_bQGk_{>0BHw;1|XIPVn-lGGSLX83}^xfAe)G!%n)WVL=}oMkPra; Cy%&Q3 diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/FORECAST.mnt b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/custom_kw/storage/ertensemble/test_run/Ensemble/mod_9/PARAMETER.data_0 deleted file mode 100644 index a6ce92b471921fff1fc2fa40f4ba21c97038afe8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 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
?jG$+1)_W1>LAd~~6A;uQ9CTO*nHX%bo8 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�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%0AQMR1ozJ3uixAwD9 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

nk``Gh_LU+1ML(HV$(dfvEpaSg^! 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 storage/ - -STORE_SEED SEED -LOAD_SEED SEED - -RUNPATH /runpath/realisation-%d/iter-%d -ENSPATH /ensemble -ECLBASE SNAKE_OIL_FIELD -SUMMARY * - -HISTORY_SOURCE REFCASE_HISTORY -REFCASE refcase/SNAKE_OIL_FIELD - -TIME_MAP refcase/time_map.txt -OBS_CONFIG observations/observations.txt - -INSTALL_JOB SNAKE_OIL_SIMULATOR jobs/SNAKE_OIL_SIMULATOR -INSTALL_JOB SNAKE_OIL_NPV jobs/SNAKE_OIL_NPV -INSTALL_JOB SNAKE_OIL_DIFF jobs/SNAKE_OIL_DIFF - -FORWARD_MODEL SNAKE_OIL_SIMULATOR -FORWARD_MODEL SNAKE_OIL_NPV -FORWARD_MODEL SNAKE_OIL_DIFF - -RUN_TEMPLATE templates/seed_template.txt seed.txt -GEN_KW SNAKE_OIL_PARAM templates/snake_oil_template.txt snake_oil_params.txt parameters/snake_oil_parameters.txt -CUSTOM_KW SNAKE_OIL_NPV snake_oil_npv.txt -GEN_DATA SNAKE_OIL_OPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_opr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_WPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_wpr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_GPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_gpr_diff_%d.txt REPORT_STEPS:199 - -LOG_LEVEL 3 -LOG_FILE log/log.txt -UPDATE_LOG_PATH log/update diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/current_case b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/current_case deleted file mode 100644 index abe2ad0fa3..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/current_case +++ /dev/null @@ -1 +0,0 @@ -default_0 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/0199/files/SNAKE_OIL_GPR_DIFF_active b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/0199/files/SNAKE_OIL_GPR_DIFF_active deleted file mode 100644 index 200047ee9ed9d94ff54214fc414e19400eab75e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2005 gcmcb>&cMJp3PwXsQ>@~ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/0199/files/SNAKE_OIL_OPR_DIFF_active b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/0199/files/SNAKE_OIL_OPR_DIFF_active deleted file mode 100644 index 200047ee9ed9d94ff54214fc414e19400eab75e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2005 gcmcb>&cMJp3PwXsQ>@~ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/0199/files/SNAKE_OIL_WPR_DIFF_active b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/0199/files/SNAKE_OIL_WPR_DIFF_active deleted file mode 100644 index 200047ee9ed9d94ff54214fc414e19400eab75e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2005 gcmcb>&cMJp3PwXsQ>@~ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/ANALYZED.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/ANALYZED.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/ANALYZED.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/ANALYZED.index deleted file mode 100644 index 4377afdcd79e9bcdb445912d8aa2a302b61f9750..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|`rkT_X%g!2tj;Y683f diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/ANALYZED.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/ANALYZED.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/FORECAST.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/FORECAST.data_0 deleted file mode 100644 index f903ae21cf7f02e20b21228d9c5ad40634e5f862..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 107136 zcmb^4b$C_1_9yV*P~08z7I!JG!QI`1YjKA{aQEUCC|cYdf?FxYiwE~o++oOf?UDPN z`D5OB=HBN%pSzN5-#f|Lr{~b9QKLpN8DkBr)vA;?KU07Izx?~Z(D~UL|1D)b|Nif+ z`#*pGqb3|T|ErAo3KuixCjcu=stTS}J!_Go9%&kQabquT>cuU*xE0AIDch2|9ckN> zydx<)k-D>2-^Hu%=GAxi>U((g{$71AGJkI}%(HhNiWBuEw|ds?M{%U*%>ESTA3%nA z_8v%aqCwp74C_nQS?=FXj1% z{b7HHAB;bh>(p)d@5UdS`Of>Y?C-F2Id?R-UR8Nke5WimIGIyyzL>_zH~i#?%O}j@ zv_3m?IC;E3d7W(asDe&0_eEi+9bt+)jY&`j-taHyR8LY=bh73#syO-SlGUBE*1=j% zo9{$jC(9I8-zgVFY2?&fn>KNZe%G2g*_1&oovLY>Hcmb$SzD(ry11Rw#P#dolpSw( zbn3u4ot+{|i>^+yIzPrU**d8|%9BLJIA%ivdb`**9NEVy?byCfF?Cu$r(U_Bzmw_J z1K`aa1D$;1u|bGOUmEO`d+rZ$nyaseBHsRWnA0AN8sJocJ|mpcHxb4gyDARG7alPQ z$`i3^T=_5#ssd3)yY{T%P-q6egK}{vj3fHYO~`ZB!1!S!_Cu8}2gVH^JeS6g;SA%2 zoz|7cjay-m^CC1}^jrwluJ2F}YewTl!CmCG_!u8_{PxfW@1poi42%!lry+S{IaEbo zP&^<%#tFN0094WTK^goVvc4r~yoeYC&7tj(zkCVBLXPo5EpGsM^|8<-+CdhxWZ`%i zKkVe9WY>0(ubc{5%-vA#ya&b2m>5^gy1Y=YYz$TUk>rWBXH|^%S!3msG#@EyW8zQoQCHtw2Klz_BJUrl~O~!Gy|3Y9ew^|{Hg!%#vj?N|6w=&m`9OEoZ@PkqfVVC z{&A-q)&8W@HWp``?9cM^sF$NJI>pP#OR!PPt8h}(8>r_GZ^EY^?w~wJYU?zi=O4h8 zGafnBk9JRBvGUKH+&B9Rr)?bfm6JVu`5Kym%grpKN-<4=y&R zUPJZ%#7DHx8u-bnbc@eUeIfN1v`cjs@?71%qCVX($mXhVh}C<@N7ng{<+{y<+ZC_E7sbqoC+i6`HN_AX|6=+tdCN$xFqd8F(N2 zWz+!jr4Q68*3kZ+Dht)5yEs0ZW&#wv2$Z=W)A5&>0eQF|6pioT{OHreAbXYs+Ob=3 z{`hA>=kx1UoL{*yKGX@i;=GGJp|}nfn6tDs`1 z$!n=-yW`eF8LK$g zvO&-2I9E-AHg92yuRg$b)vD>VA6v6R{dP0$_pXYN^*V#&6WxB_bK6%*x{goX8G}Bi2c4Cb;^8IAZt9vpnO>X`dQsL-eDKpy=xD`3Vjct z{e+tPoxFFUeJJnRX|Ge4@P#T_HHt&eL*8%*+VNFou$*aA1nc3sT4B99SLZ`+d9kz} zwr70vVf*IiHz>c=q5XO{7usGSkY#%Z<;a-Wf1Nl9|*ME*bRsL=MqfTB! zzruN9-<1eYl1^NHv;K+QoeLCE=8}d@4B2xc-%#_Hx3ih{xWo?$pum)k3^;VqGV{ShBv8 zWsBVq`oC%9G`U|PFESTca~G>Qd5{;`WxZRwm=Ee8QNCpn@*~mYRy!B#L%zt5Os0Ow zkL50uD)J;9{bM&53)QBF(@wtN?=%@p_i~D@jeEn?3HvzB&C^i-QGH#^ z7nJDdR9inn(`ZY77n{It1DtGFR^(46#UpZ{MjoYuTO*HB$I~N^l2`6R{bm{RDVwz| z@+lLTdAM5-ul)k5Zd(FeY@-Z9ekHOCfRT*_EVU+|jO` z3hNI=;`>m(uSWS*pIy*Q`3L!xDL0++tT{iR9o-dqmPz8hud7l8`IX4Lhw`nh*^pP+ zw+kSD?t{Ea1qMLZoh6Vr@t)hDou8fZrRpkDT!@}T4WD4&V-hRpAWe1tvf1^N7q(AIqcRf??0C+wScP~Tk+ z`RhB7@ifQ-?8qjNCz%V`-OCg|O@#TnELaEXlhdGB83Os)xR{5k;x(X*^yb&k&mm^% z;?n$6)qp$!z4ziLLlDdL@#neY)`x3D9(yJflP*D3G3k6)&r3CeqR)J&9^Zs)ZaTb| z5~JEcwPq#M>?t`p$3nNfD&r4X@@-JZ{6zW`U*zgVssPCTISTb}dJiSWR>k`zHDLP+{+`$S*TbDGNmk5j?A1v$k4o_SzAKj{%RX@O zI%6=eW53T}-ltb5z`WNKZ1B|8+jD`K7u&!~m?w*au`rL8{R(4VEk8EJJll-vjrq6k zGZgc2o^Alm&xhor`Fe@P(4_kX#o&gR*V}Cxn$iy-Tag^&v+Y|Nn$}IB%F>Bk*8}p! z{UQ4qK;`=g+3_xJ>zk2sK{$WoX|&hO)vpiVJ!9+~cg2&-JBzg#B)T*sdM| z#rTDg?KwbJw^Uv|7V;T0G#^y28$;eN0P6QEp>1&*nvE|hej5+@ktvy%@}=#y$q_xF zygUu6XB(mTcAn}hz9OT=Mc&2yb3wbUCNy7rLfvXMmA~Ch@#fnUC;S81S5Em{-Ez=I zm(WBFfULv<$d_y*(^DQRw%?<6_1{zZmuO$z{h}8pg|hHJP@T$6arGk594-x+Zv`m& zRi^T7RiNBh73$bEA-i6W%+#D@9jSg;UnrK2hP>@usI~`Fd6#2UF78nI-7nCbPWBD= zefNT7+PY*)e`se=K5RCxKrEK+fo9HGsCwQc_q>FB=r71NC8oT(ST?9Xl!j_uBPvhS z6UuAjp_sp%%3pbTdYg-g`N$_!euMIP`z7uV?C-F&kj2UlZQTMC|5KD~Se(k=dgUq= zVm3r3{gzIagH>B%bJ{f1Cf9v?p+$dGLv-;_ve+CT5QZtDH{a zRG)^WM4ZGgozw0d$erfbHD9OtRx}GNu@w1`?h-Sni%r}9xt;Rev%HA!Zq4r$Io}mP z%nSQDb)tYmPEp}(VW)hYx+vmHJ&QT*^3%l;2V^dZICxwsSoKwDr|QtCtkZmJD-h2} zTMn+e0eRDT*QrXEfRIB2&(bHCSs&a3k?s&4A zi&>qe)tw^$pc+mSr$J4p&RU=r;&+K_JH^pYQ02W_2l3htb)BrjUGjL-dM-A*Z$Q1e zd3_h#=nu*4JsY@~)&2w3l(`LEY(z2IQhhv&^$We?_x7=Mo*`n*%A4uewU%Qi&dkkklXLjH0svJm9t^DATL;>uZv~7 zgXE_?{akF{FNdstlKw8{x5h$t?+Y{!x({&WqQ(Pgr#2nvVkIv_Q?t$>7n@@jp{&+$ zu#0W&yHJ1aHU#yPenC}W?obztcLjzy)rl)m?jAba#cWH~0H@l11Ii!MMz~lXt2WYU zCsJN(zI0J2Pks@qT}4N^SQ*M|b+JUFU2Hy&g#6t*iu2LuhjQ&5Sgc>a#$wht9tz^$TlRI>FU|F`ku3)T5}o7 zc1dQTK3{#POVQ_N^7LgYKbUm3tCwFILOYN?_YyV25sRVT=UH)E%|W{#%OMw!pt_MY z(3Pu0-Jtot8QNtZAP+7!*VVJ6BcQ&2oJ{I7&y~ylb)mXHABu_hp)uL!yLu7a8?p}j zp^6b>fh$*w>q3!bDb%Z9lD@?kx_UWhA`}n8q5hTw`KSmP237e`Xe#})*tIuD`a`zx z47s2F4#Fhpv&7Y_aVMdUpJu6x|F`kyU*yS zw?h7Clm3RR+X1|1<|}3+pOjNa;5{_EF__*@pBYa1WvVgs{(Ab#i*9{3QQt7Ew_o~8 zPFCOsl!sScb}_H4t~m9b_E()IMXhUS*QVHYr%j*dhErtZ;iylU_@-0k_qm1gJio{$ zH*UMwCJLhW@>l(lx5}So@40dwJ!4icnIX%OFeY4`LYr6 z%_))RvX_IQ$a@aj5lJ3nx!O%3e=r}~SQnxG?DGWm$0|WnMnN0nFk~BkLSDu1scXl6 zwt!~aFer}AqjIwm@+n8C{_1tI_+zTS9zpfJlF~fX)Pr)nhAf^pPtCUi^HqJM8s@S5 zK^)9$)t;v`zioO6^IpB^poBcM$4h+HO+ujq$Up?Yu%nsJYyeE$-P>7G|fRV;$a!#|MCo>TiBAy8%B zL2-B>)#vXD`N<+wpTh_Ko#lgKFTi=o~??d_X3e>BvQ~8Of&~Bv9 z&DGglw7&PvAnP@s;`y|{;$CJtj`97WtaAa1X9aP7tXcN=O#R(@ z>hDzKHS~8T`g-(p_GNeUZ}vzw>eu>zgyKHEC(#?Wp&yegR^d5k%O~KumDfAr`IDwG zo-#mh1WoLuv0SW&1wz~CCp1l}$9Cm>b`NrN7HG%3K)u|38;Us_A?w)=>TM;UNgPh= zuT>DTq06v+TP6j$Ya;ef{*w)w;7{0Z5qSfu+xIB$lo<8=v?LpyhvH;otcM?e3f0Z_ z*p3LlMcd8S5c{EKT!!{#Pwc;0ku8opF4pKK_A2P}nEXT^MrSsdnI@B7``c-`g#v2YK(+x-#%zEPNvwW8RSi~LRR=ame;=yLeWP+dmPCH1luJaaT?XS@RA!AGSys&XdW~ z80y&{as71h^^iB{L!PQe8u*nxhUR@1EvS6tDZH27SK8o|MzK-#=Mi}PRdQmFO zv-!2Lmt47yoifa63ogUFU1p=dE3wTQpT%{ejsOZ#_fxSCeCXy6g}r zXMdx(%skqUs@1Vy_EKBV)h;2GfqoJZ*&aT3RyG#1V?8PUKax z+$ho>h3r!V)FVkd7BQV zax-QZ%4M|G(2Q9M_4g%Ew4<2$ZlU@wSD?~Skmsp(r6F595z4oBpbadBJWsw|4EfSu zP*rY%`Hc+O2+fl}6t}61d5xS9MDv{QU!XWw3G*3ybsAJ}uRv3o@;2F{JmxpLc2An; zn)I-IY;FOZ$lI3A+*UKK@mjCwxrtf6y>`23$n~BDCb0y9lt`BG8*PlEPrY! z>z9DMHqBd2{)rS9KM2i&FOWU=!+cA(>j~AT^)&xl`w-f*X)q7tQyN1(VGfin&yb@( zL3=d`=4bYOcBr;jAUo8hdE436kaz6~^|2Aqte8Qrod<>gB8uNFrMUYF$i}ROyjU>B z^){1rw^RA--Q>6ZP)9S+Rys-X?sMdiFv!=1LssGe*_Hk-*i89AafhE!m5f32%|G#> zyq6rRyXi>3Oi*0U4!O=lR~GLRRs3zoW(}kPG2<`{_-5$B zG_G79SoDw6p52wzX>J7Pc8a~n3OMEdwS}E_S?m%{efD`7!~?UGcd|vPDml4-?W#_h z=5!6Gem}a7Q++b^5TAR{z$x}-YV0&U#y54U@^M-?W$z8Goc3E`=@k1`;e!j4>!0>6 zmWzTrIC(bF3GqeS*~xlM>FTt*%XD`dzi&O9tlPexPIISBZ>P%X+sCP|#pvs_hh9MW z{z5+&v&q~0J4Mj^0Z!XAV4%}nZa>JWi_{qGRMY&1IC)sQp)exmFsHfm4zl5Q@j(C| zel`H*J$K;)0RBSb0|36El5*uD@qVZW(VK?9G!3$gif9kK*pq1E&UbTV%7X;?mgGibLDhAiKF zXzK2SYVSoTeP2K^nN4@giDD_BT$U5sOQp#xb)eoRp;Emmt~Zk6Len6tz6hFaYbc(+ z9oj#Kpv-s{ig#C_8cttqQith_v}VV9l(RNJ$(u3ofr&hy5b{oGAX}6Liq-`vo?n{k zb5$o3Hlg|=9iSZF2dbwdpe;F-;voy630ebL=nklJ9);p-D8>EnQXKXg%G|#os~>Bo zJ8yhNB636;C~swkVog3OzgvRJhg7EWKJ>wl+147d$=Dq#JqYTgV<~Pr6Y_>jpp9Hh zX4yf$JOoY2GmxdE50Ln<+lYDR$JFlLYp7m+q;@lZQhY7iEVuvmfDhE=5>wnMCB+5P zQ@qia;yc+WKI?r!c|-v!k5UARW+k9hWuWR+9@=!3Ayd_$p5uK{tZ^O0{A@jH_oe|f z=Nm!QtqEk8n^Jw;=2Y+7g3Q>GjMECTr=;228nGPL2HM(^>i_%uw^)A<`tSHt|6h(j zw)}+_7H8sXGcKh1K=s<}0s+;P3r?5nZesT$nCgkFxzf{D2qRSOeu(dh0OSI^&v zTyTmXlQ40XaT`&hw4ppE#Cl;ZOnm=-poIypjN6bVvemv|!pfIxngAxKiHV&J`brZ! zz7`WFKA{1|Ly__qCNex*5C&wqrUG6l*&6=zBB{OKJGUSD-aGQw8oWrdsq5nfk~;E% zEHw!)l34M?c#*_rOoFOtB;@Za;Dr(!Jr=5<%}@+J3gzol(2To4#=H($=Lb;9w~(Kw z7w)n^iZ3`%Q}aT5y)x9jTTz_Bdm(>!JYrdC9^@w$L3TEf+U*}r^|9MRk-7j>y?$VO zHqK!v>-8abCx&d_DmuQM`Jf0njN><<4WNzt1n0#b=?}$0dhy2OT%12WGb>c3&(e8q zJOJ`hS)qD#1Lxmt9|!fpLUcVAUBUGc@rsg7=hBNn|IfI7TGfUk=4_hKwGE+(YMYO^ z-fY7kOn_zdH@FYP-9wnj^9w_9f9Pg8aKETMmnfmQt0>X9UlI3}xS9j^8Q;=@5~^%r zlxW>rf_av>bB+?S3}wipUy!J&!uKKDH3f>B7Kxk*dw&D>SK$NKalh9qdCjSEFSz2g zjiX<7$^-YqoMyu@B$jr|ZF)X7em(EXMIXO&PJMY6o*x+=^)%v-3s1sM-SK>}S6z?0 zSbki6%xQfRL0)^#Q5XN6zd#l{n4ZfP1tGiC2Z^+3G7&EhwA}&OhYqM0HM-F9su`{C zANs&l-oJwFiMK7WeS7{YRLAqveg(HC$997DLj@=XWT5iCvB~Yeke6Et*}}1y-}0Wv zah&F7`Lk~SO~H?J9$uXY!SUo@iiBK*X2bcjr=QY!>=Sqi^-)UE`OS6{@~;x-ovk|t z<>N0S@Vsqt-DLOsxNf@M zFzm1GnT_^;+bbN8J%13#r?OAR@ycfPao+g-%yj(@CZX#WKNZfqSzm~*Q_P!mU5bsz zix8fxBVLT?`IQdf{Jj6Z&uJGAqy9Jhf!!|F6VC6%`KWbnyOR|@u@&voOxWa9(@s(U zeZ1=$)MxGyJxKuwOF&L7WeDJ^58vZs#9)s-i#kSCcGe>$VQb$R4T#%Fvt z7t2`Zx;uHN1pZDNw?R**-ZH7eanzw*)~sC@JMx_s2lF^CM*2IwG$UE3Z?2 zHMk1$C{|-HBIzcOJ#kqNIOUXzwhd`0IJ7AN+(eecm~)J@=E4`OhIwpN2BcFN)Xu z1-f=>Lw9K6uZFzqeTu83nTz^IjUbyho8k#!6t7D-&(-S_b)Y&yUoeuBE+aNJ8U8?v zO>6>rzC{!dz5{Lg3=7=yG68+Ti1{z4xYvDX;$*}hYMDH(p?yg|grmCOMyy|@UWDa0 zH6=smL!I{qH2qR6cJ(%QBgoRsfjU(fG-={3arG)|6==(jg1qp4^2R$dMfRnxos7~7 z>a#P++sC0D|CtQUz6|U0Zw|$u$&j_!4^6-4R9`*$a@S5r2*_G@hc+91@koB&kJyCY zCs#z#SntCmP^`;D-u0vMfC?1Pt530L3(bOF(C!F;a^V!nD=nn@4Qrr2yn`HQsQg9< zWRc-i9{QNd`$a<`Pcc+smcw@y7Llm;XtPyUw<;3d1k&- z)<3Wk^@S2`aH@bF7-w~4RE)zmV>yi5rtmb3>#9V#Q&@g}QOplam+qK9s8Ky=elhPb z%|n8+V&15eEeXeZQ>Mi{l-FEAc~Jm;5uFWe^}yBhoIww<-osBY9M&yBVOnzuYVXFUBoZ`Htpomfe+T)Z5sG-zeU!yM~nGjmee65If z%rt{MH|24>oI3$ z6iExbcgH2F3?O&V7a!~~`T~-z(BuQoU#wYBOg#qeh_8@+Dew`?ckqYm$2zD-KB2fa z{UMe;(iZs^8@Z5ta2l%bUY_Zj?lZPiqB7)(yF-zfe$c_}nTOb!XeZMb zi&V5Fh;`mIkbT%f?XK)0ryL~tNoX?Pg0ctw;e_q%gFMoHND57X1W?_jyi!kji1zl_ zSz5l^UZ`iTfV^~XibXysX1~R8%Hqc$-?adms12z6*$vKIU1Vza9^ym~bpIfh zM{Z+zwss?}clRWyx3r)*RUT-Q`9OK-2lhiJiA{0ET-5Gu9kN$P`b3{-zdtV~ zbuq|SUcvE+y>z@fEFK;IifK3>>Jg*s7S@lhPrG+?JxWc7B6d?~BMQ;^4UZ0W$;~+b z=6exnL-yc#(&q|8^K>_!JKIdq^OtHjJ+I9p(Z8@s_0a#A7f;YX+4A&3m3&+c{g&v| z2mP3cF&h1v=)Dl{0rc1~^n3OI{ehMUI*$I(Jnjb7mSogFj@yR*lIJT1b(G-8?z%CR z3hLQ&DbI+R7s~kbfv9~q2>q_ykQu6DFQ`9`dl|C-$bbHR|L5Q4KS|GjEaP@Vea!0i zN3^Y9(W$3?Z3^EN>grSz2MY-%opq{FM=qfJ=!Y;T`4bh-3Svh6g95b?OQtgVT0g!=1{f zrLWVpuawy-Z*NJCwRflu@YdTrq zTD6_}LWa6d@j632m?m3&r)pcYfm7b9)6i*k??z5@Y++-kD0jXI;zlu=IaU3t&7DF8 zws1=JvL#GcwY5`!+SJC$%1o0^-Mn&Jr+pu#ol`A60`;8{?OkjNl89BHu-iV@?jA?rW?v%%kEC&U#W-F?k|A6nAOPI)5ZK*CgjC> zTk_s6Hm8h*W(Cea5tMcRX8`XK{d%*vD; zOq?u?^dETYYYs;&>^y^}^#-n-``lyAF^b?sE``;h%=IL^iT$2lmQ zm!o{Q++N6^2Q0Hr`|SU&o(+o&S_QaKnv1A~4qvC+k%wk?Ut|$6*R-;u4vneov}Fs{bn+Xe>Y@JP`G%-Jdk*86Z5pQ);>cYRE{bU96c-YA zbgFn?JHd~ux;S~OUl{jv{OsLbZ0d#eK>hV>y`1_}u0BpXWk5ftXfqV!BOiTlh>LlX zD*;Y3)^C)Pm0vdo?JngWkMgir6P^6iCXA!(tp9YB=TI}9w%giSPT?0c+bNTEn&aec z-jbX0VBBRdt3bVCEtC;;=el-gbL)9n{&K{8*x~a+r+U{JX!rUOv|*JWp#0euvT%IN+t~h= z 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 z
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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/FORECAST.index deleted file mode 100644 index ea3e7b2759c01d92c69ea4d79356292d4d9bfb77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZXUKP&`M5XPT|geXuD6rw?#i}U|<9Ct3b-JInL#nDM5I+bQ4k?2&SQR!4Vl|-S^ zh)So@sdS={_}+W_y?JZ*vYETR-_CsV&Flte-Ks??^>a14gP_K7cHnF@!ur}`5KiSM z)iw_Gr2kbaZdGa!aSyQ_u@QuIV1)#Wk2GYl0Yr_pA(ksaeT~e%CM?s3s2NidsdPz~ z>&{@Qk|vktC~HX=<}$J%-&cPs7-gA~m479lg=3e#8&29oma}b!5v9cyVJOYkgcZKF zci~bs6Fb}l?z0@6Q)O^;qf?Mxe0A;zo~%V-D9bulihT2L1fyf7S|yA)#~wjg&18b9 zet#E&F_Tx&wRfAvto5ZRwG|)2(JmvbQKB$4BM5~h(~-rg2}2wF>9|S13CD6KmwrBI z`>rs|m3ZYQ(=P}md3)-rod`y+Y^H#j;t4^RNh48pbCr55VICYJy0>M_rI4G>Es*<` zRP4=E!@6+B`Ztakk*RcxTeYS2)n-uLXkysSm1?=1FBFTs=}^B>aMPSpV~FdBb}@p~ zVq6=_?#E^>HK&)u#={4`2(>~{o()s diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/PARAMETER.data_0 deleted file mode 100644 index 914e758e0ab242711e04fcd116f5b971ea453f02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4$U|0Lw{|o?h`!ys0 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_0/PARAMETER.index deleted file mode 100644 index 394a6acddb2c3de6854e86574e69394499efc736..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72 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Π4@RT?xaBtO|C+m?JU<6&Hk*z^^Gi^jEsf=Q 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
_yQ31{W@N2cs&Pl% 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%0D{0_f66`Sv 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 CyZ(m& diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_1/PARAMETER.data_0 deleted file mode 100644 index c729e0adca4ff9be3b92b70b2d9dd13dac9ce0f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 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 S3B02CzY#s=r9u+SJ~;=Q5ei-a diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_10/PARAMETER.data_0 deleted file mode 100644 index 89089d51ff0f5ae635ec3d62787d3d739ade5b2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 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 z 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�NmiU9^1_MvdQy>5Cc}}a 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/FORECAST.index deleted file mode 100644 index fcba30db17c3adcfe04f7a1a0b8aa7f8c48d1402..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmaKsKWG$D5XL8s38+odL{Sg~P0V??{sEKfl9;<3Cb!Gw%oYl#ot2%H%|j5bvl1IC zJ1e_%!a_PbJ1aZ8bXMv7-ptOMw|TC6EOYGs?wfD^yvyG$(i{<;eq1?3pf%j{xcg-> z?q(T1!9_Ry8zOg(Xc_T2;(5ff+@5UY#ofSt@sw~^5REIw;4(bvTqakWP)nn3m=R&AMZ@_;ocNYnLZl!``v7PJ$PO9TSru_65T?4hPa4mzZw;X z-8+iYOmGL}I_?{|qcNMA_jrNJw?NHE3vwHbdts2afP0BPX+pPTjP{b5GGeZ!44aa3 zVV(SJoSI@zcG?fWwA8DhP?<51K^QTC(Lj>m^DSa9D{3-$O+>~f13M$;&~chV-72QhcM zMXWwDVf%VVsTgmc2Sc5krq9XU0a{R15Q`HI)r^n8Q^lrk+ zEUoEfY0vzzzBNvlR+lmB-0M74uhpr5ZOa(CQ~gRoIh%2JMwV9X@fOsBvn}|Ys`)2> E0sZ(2P5=M^ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/PARAMETER.data_0 deleted file mode 100644 index 8901a336c2464fd539993a7f14cb302b728e7637..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|QGM7y7pW#0P02+ij@c;k- diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_11/PARAMETER.index deleted file mode 100644 index a1761eace25f3d933db704dd335e7897f1816d85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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 C_X>po diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_12/PARAMETER.data_0 deleted file mode 100644 index 38f6f229bea0313864bce884aa832af31213ef7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 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

;5{xV>0hgG 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%0A!I)0B@X#alOtataM;h1ahd`B1TpGQ=z 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/FORECAST.index deleted file mode 100644 index 3c5f22a423b36d056129b7879ef74957f9bf91a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZ{kA#4;;5QYZ>B!DRf2qaAqEpS}egC=d&73duo;C6EyT~Tr1P&ic0hJ>W9H3Wmg zkR~KJ9N`ii4u`_waHu-|nb~>s9Ve~2##zESg;Nj9$$DA!jH9=Bh>Oc!#GO5ezOtGIea*Ts z0+~L6hA}kEq0@L&58*U!+5fKK9IYr{ZOzC3fS5rF{>niy3o!0X2g+q; zS)z5Nu|sB-r#c-y+zgB&$uOApVZh7m?r1RR7HezvUyW=OupZG>+};;$)^!}?RBN+F zYcJ`vro-g=zZHyQ)CpHSVNY?_3)+NJt#F@f-PZk~71jC$yDqzpy){3wR4C3;ZT~fP zQ4o~U%UpqQ2q{teJm+-HN*_=2)FI0!nzh@0=bYJ=Vw_`e@XR4AreXiHiu75*ENsM) zSlID`)-@W6N3xf5ZM^=*FFIrKia5N&$@d&vUU5YY=y_FpLN%6z@> o%Kj)273g7?$ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/PARAMETER.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/PARAMETER.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/STATIC.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/STATIC.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/STATIC.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/STATIC.index deleted file mode 100644 index 4377afdcd79e9bcdb445912d8aa2a302b61f9750..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|`rkT_X%g!2tj;Y683f diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/STATIC.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_18/STATIC.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/ANALYZED.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/ANALYZED.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/ANALYZED.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/ANALYZED.index deleted file mode 100644 index 4377afdcd79e9bcdb445912d8aa2a302b61f9750..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|`rkT_X%g!2tj;Y683f diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/ANALYZED.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/ANALYZED.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/FORECAST.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/FORECAST.data_0 deleted file mode 100644 index eb0f34625331bf2122bbd770aa87d58929339138..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 107648 zcmb^4b#PWY8#n6U#oaBqOK~T7ad!*uUfhDaYti6RptuzYu7wsUS{mHlH+IPHUf;~w z@0@@3H|L$%bG>(xrO#SP?$u{KG;Z9uaV*AIqw2M*`R7v_U%V;qWw|mwbN%1?+*`p{fIGPOgETJf# z?0M5O=NKv<;(69H)mSR;>bc+3XB?F`^W5n9&C_o@)i3sZ=2>C_l~4A(>6vpPl@IYe z>zQg2m3Q^r@98s{%A0v^^!(=OH-+jKdp`3lF_p?Ed*1ZSIgQGPc%Jo4HJ!@4dhYl1 znL*{vJU4oN^YoiZ^@}~9d6t+(<&!;cdM2AqG{et*-C0( zhWx|+u)o6(#-FNn>oxk1@-PWueT|ka?$DxPO&S0 z7AH@>Hiy&nJDJxh0_*uY)%B0IRT-yTyIDBR~xl@PFuKIbtmtz zqn1+|-+E4!ra%LyPFlZ_)AU}{1TK%#+$o>UZ0Qs=%C&J?K1n*|mf!8*pYa`>wnS=- zZ)V`Z&L|J>($%Tba*S&{!2^tIYWbF4uH0@Nh4D=H5A5q=5p_vFr))K~KYTfSfYTK3 z?eElw_yO6-hr?a0)}9^V)I&FqbeiLn zM>$#F4j6}IvGf>sw3!G+@i$NoZHRG)FWgIROF7mpXTk=N(XT;Pu>i&yHFPpGGb5qs zTm<8cdOi`FAK^6abj^x!#wP0n&8NL&yq{#xau{#qkCEhwgV2P3f~s6zj5|C_JE&IA zgCg_?GV z9~ew=Q5rAJ&7>F~RrGRDbm|QC^XZVU-a+y7YgE7aGsOXMFizTisiCNz6RJwZpjloC z%C_|=UeOBLsa>I}=nwVP(U8}gMjl-Vjqhrx0=Gh4=m2^6Bork=$vJl*4}L=RTi!$2 z`X{t!V`5yEUlT#|JPqW_vO5BoXtpc{YW?o@}ItX}vL zr)bms7|MgLo`8eHPdjaj*5{r4e7j3dU95MQQ+2z46&9Hs?iAPC+;XzI@-E6tOpSzV zd)$YI`9r5pZ67&h=1otWX2{@YPA+P^aH<~}UZFh0o7YZRclTST-nt*-rnoipy^HzP z79Y?qJpD(fC>{>^sEHUIoc4I%; z^oG!udyV6edq+VvBmo`Q{?#~6Hmn>SukUS~2VG|{WLFYXJa_}nllfhoJaioAPrt4X zW%pThUMmcHgY(k34bHb1T^8qGXU+Z+=ciHvd@ii;Gki|0*Y&4pzxN0}KO3^+G0qd) zkI&T(Ifc)eFSid+{y92%sSvIMQ>(AVdcSSN^s}{3`Y|y5757p!3lw3eJyCm=cOTi6FoI z3iZ}EkUZo^%h?F5PcVO|-lc-9MliN3iWa5wS)2AxEMJM^GwpNGd3<)5?!%5%?%;EH zb|3er@H=o5apAK!aGvix3U~5NFRmm0=fyRrT^|+dSoN;DSRQ|N1?AaRL0zL8RC^jh zwyiG3bs9o`pcAyChC!2h0Ay#XQF-~e6ldRq{zS%Y0!@k+p>8{>)o`c_WP+y0;LEOD zjNXBMh@VRg?XnReuH4N2dC|!`%!TS_1t@FV3s|nzc&Im3f-HARs1ihh#wQMxs|!&1 z$A*yC?nCt-XnCG_9%6fVDb&g{Y$jsysUOuh78Do$N&V;iCFIWZP$gM*&h3|-nhDB| zo6fpe<}3(}|HU)d@5g$4^=*EuzdEdP=8xY@xR8OYX3d|Y1#z+kEk}63AaBL z{bM`D?MaE9rb<`}#GiMigICvOg4>#Bb6Pnz7vhI`@;h1L9llOoZV~bz^XX!77mMUg zN;~DlqUD`@!2SwOu`xzvr#>*Qs#EqXQr)S#rLN^}WHT*SOunX^Y2e?bNJcTPJ%LE}g1#{Ps>8yB6{zS#fSh7xNjBot!dJ;V!WC zw60EF@M$-vs9Uv%ljYdh)2Z{t?d@c*diQ|=-TOLqij4i7w(~V8+Ede)lu9 z$u}c^;>Fug{xmQN@+Y4A&+87iXx9)))9 zAfJ+t8;*4Q!Ph25KE-2QgZAwLqP9fmq?wy|zK#?BxU ze1rUL2g;-3gh9Ef9OY4ATOc2n7WtBTHwB8--yq-71$h#i8%}xCpDM_QKa)okC?iYOqY!Efg&@Z%@%{^;d5yI&o+!j%!VF^=6uvSZok<0N>D5x4|$E#`K3XLxH;;zwdoUEuzCa$Oz;f44Jn95Zt0hpL41uaETY>s)g`m9M0kSF!pZ|C zDBk)E>dwERN||hxTR(e|3yR_8p<2?2;%42TZafm&(z7XEuo{|SyQ%!iDJTovfNa_` ziWhx{CQF>vZab=K8YutdA}f`Ix~3nr4VpsMu`|U320}h&JeB{?`14=$A9JV~7jKmr^D*&c2IgnF!dQ##R=k9HoQg<;c^~W40`o%EVj}Q{UFz+@|Gdy=OOH=!W(}>Y8;pjQ9V2dS~$Lj@iFt2AXdSae0o2JFMD@PBd z@way{c$LoUV}XOPiV8G{NR?iOLIX}qZGvn3PV;g zK2(9xslH!SC=bSiI!Rv0GuD7&KwW6Mwud&;c(UUr$oF2Rdi|d47Xx{a8cunjeqRK! zDOe3!sUXj?6Y9Z~C$eHukWa~RB_aDXfHdczS(_4hm`KqMn#=p49uP@h_)6v9Qy_m+ zc{5QSS3N1TpNl|g3qt)5sYbS=b_v%}d8*gcZu}tRhbHU+WH%V)l{Ml)HZ~?yX9KBz zO&_T9cBVLgX((t37({`xkw zxm%;&t{+L;J@b&(7dZ;+S99;sc2-{{$4A5Q*q(Xm__9QxT=$s^Md$liUViUR+pQjo z?WkM>p~#&Bnu7hvru00)HuIh@lq!Ygcl64?mFA>9V{fTqC=z7i7 z7xL|?yzBQgUGJNG5X)@^sD6HNs1vNFcFjV`p;76&mPzQkKKuyfqVzUspH6~o&pWJF zO>GTr@pt>;Tz4O*>{vY!EY&s{ zY(6-ZlNFhp&S`lw?$oimWp#jpLP5pR4@#>u}W zD2MoU+44?(seC}^vQNxw1_{nQJdDc5nZV0U9V&gZdwo|_B zUB_v!cBtz#I}6u?@-W%DZhaTC$IqdRJEH;W@04f=hrWg^Nnj%v>m&Udqx?aICQkJs zZBwVM&6+ty&$rMXd)^%7P2RR}n#8P?Q@lyr+9_XDYy(gDw{@z(X3}ZO{Dk`b+IBA1 zM;f$unmsW(IOVCsP+S|<5#>9}baJxn(Kh*tvHKy8J`&oG@5qdu`nz&F zkM$QN_zrwUcw*opsmn!&N9%&tiTc|6H(r3TTC0|%4NNngPk`2I4G({9pYmC zcpOx!>}AIhE;i5DNT-gqiX2pBl#BWBH&7>E zHrmB9We(*uRmMWwClZP=<;J*jJ76VQHtJXxvn!pU&Kv?&f}-QZ-(p^Q1++bU#=BV8 z7(kxC2krG56I{70z7LxHSth#JmYhu<_z6Y%ZpdqG#C51PR-EkGsVzZ}KT3zZ*0!7q zRf%sD&*?nXwUeW+LzAq^G#A@edmtO19eFJeS`1ZWT;#PTrGmP{XULEBKz?gVJS4BT zoQ3snybeVR`g<22(s{Nk*ZI~#JL(aX{ps&ZI(er#uAX;T4@JFaP~D@y!|=Gh=el|m zx&x{LU&vym=ect6QbASg3^c70%tv|VCQz@S{FYyMir6ghMILM44TtK*X((nSLH;Ui z8^~=SIqo}@N2)Dy>$TGtLizeJ8BuhxE0--MLecRCv>$T@xN`G*7&$Bi>Q;P-E9VOb zK$-juRHxD)KNYij!~Y$B{%ihYtN9#s;~qO4kMvCjb&m{C_~#)zm4-Y+9Wqx(D6i1p zk3`y~)NV^Kw1*<8-I!RxZvDEOFBIikQ(R~o#rF@80neZsPJf5u+p6L3Q7Y#kDD-BE z+dhJNcLwBXOtge*=n7~XJcQy}wjbNuDPDRC zs*p!etYF9o<*wLJElC7LqpTEPYz0k^-Q=Ep$Qww3|BU ziqp<(ebvb-SHFh(Ockypj#eq$so&SV;gnUo-9)|r)LTy5Y}0MTk*DrB_40>zovP^X z2&Zh6I1=%Z#MUX!E`&BHHS$*7bQx**16R*quY#sI{k>1jS&Y0^9f*s(R&N^uP4at? zbt;8C*EE_5+2fng2BoCD_e)J^{RTtUaw#XuJC$Pv(Bl=802sVO}Y-u7PS( zZp=63ufvd6Y>N4)9{!Q$r)dHxUw>a6^H{q-3i5US>o^oXvuVEjr!eM=yumt}H}Z5e zZ*DvrnmCkCi?uy4|7K4@p#GVk=H~%3p}zPMvYb^hkC)w-LmlS@G+pHYX> zL!rx2e$zohmVFYmRrW&_lk#QNG86JAS)eHtyTpOTw~BA-&j_K`n6 zl8JpO-%HmQiu=1DEAS7MzbpNZyROZ*;n4mGhHBq}_vAzfly&uX7Ed{wT^iIv+pwKsE6Tl_#r(^CcP@I&a&Xqkj?&ze7D>4EiTkDlg8j zI>RW>e*F}x_}B3{m{kYqa~w+FCt!1f(LdP{h0!nRYulk3)|~pKS#i++m_A3y&oj{P z*v@0Ae+ZdH_kCm-?ps|nBkn(yVGQmw-aa+mKQqVS{xGxt;6AVi>*Bh!<5ER&*SnYz z0okG}QC)1l?~dk_@z+Op@Npjy-p%6Ty~Wkh$1$7dtY#eyt+2hM|ym=9U3`*dD< zR;J}jMnE+w80(dLC(wQrjYY@XExs+2j*RQh7dyE&9?sjPk_nvl#`A=T`#(

>B;af|rP$_oka*licZW~uSb9j~TdMo2G^pbvRP$QaYO;R370r52he zg;mP3Qj=`-)^St0wGCA=rj6YV5~0y;qHNoMGAwg*yVFOdk9=M29AF`ViagKz3@}d; z$XAEzd|ZqI5yU9FIKAd)6h|+B%ttn%31UQye%*p*YjIC72~DvMZ)(FB!0Dz9*_EL( zaO8rojDk&-P+VhL33Tn+5Qn$X-r+KoX95k1eLZzhJ{Ix1-|tbw(mXQY(YQXH-k|Bp z{wA-(GC+j>R>ej!$R`tTF9oGXIfSmur}?PM-s>)?zkVjGvMdz?cZq4BZ4RzC@rX;? z{TPhL4l-4nEg99%wDhA7fj$u3TXIR(E(~{-Mc-fk4kmraq+iix4o-_mx|l8|ZzqIP zLGB3K&7M9}of!gj6*e~HAN^ChDZR8)J3e8!g0&od)zlYk>`b;T z5xf4Ku8?dL87teeKKt4p=GQo{n6PGR)zyW9x(k>k|dEyt3Vk4THH6V8eaCehlQ_k7_9)RY8qZ z0Tn8SDR)QGGojP=4da%$wv?mVXBWLLVCj$Vo6%FcoIj3tD#VLC5?St@N^>04gH^x1 zA0c=n9JEVD*NY$ES-Bi@lfVa5g!VhW3D28CrJ1B#M;`VqXO^Q3k9d}FXY@7W0ODmvuV5O*5C8En(*>}3* zcD4)Ov+GOs^D+C0-E#6~xD)?}4!?dcMP<@jmyIL4MRor_(=Ec9ByDBsGAVEr8?4c2 zPW*z^@Nm1fZ&(%0o;w}U1D8ftIe<>rbF2=Ta#1x}n9ixp|KRlNeHOn&=%EU~E#5Z) z-T}d8{-lOUh^-VRw4^PEP$%TmGTxyDSf%px&^0)du<~Y0RGPW2jHIJ0u8nk9F`w(= zX}(jz5g^a`)g3u>%fG_oJp;T+reE>In7!IQm0kt*cwKIQRI2YX+$o1;+ zNi^KE`ttSvUuEYN)CAP*aYc}X4kDt0NN-A2iiU1P2pvN2U5Hdcy7b-y3C$oP(i4gy zAWb?UNRg%p0@AC5(2IPz58vyZd(X_y?Cd!+=k3hw?tjlO#ev*bGiJo}nh|omU$&R{ zpv1E`Yd+?nrFMUJs0yRopnO{9iP-kn4OU5+oyt#w{P#J9(SiWT<7vGuIu zRmY~9l1gG#q=Ir*@W%L1CQo+&nGpoh2rg_daLV*$`Dys5uJ9A9j4yT1IVX3|+_zUJ zFe+gmfp+-NDU^y0tlnIq47KCH2R_Zi`W{Xqp|&9|DR<2+Vz%^+lrgIPULyBRxD^@% z(rqkb?h=C`w{9BY4_u(}DU+<5OGX{D544cnWfVOX$^B$<4i{99N2ovzHFulneB6~O z63AIcGyE2IVa;9LSxkk1ILjIp>4MA(Cse1~t#jsgYiSN}CA>%HWfWJ*{1lCL>;}UI zG&$2=Z32&>#rA_5(-x-(5uJ4}Qld45oyS|1S_7+DpL!|fg6o|JR+I{!ZUPva;*r=Dp2O8Gf?@9_gDkYSRdqo&Kwrx<1@1zGho0wAlx`$AO zc?ZL%ukKk@fIeF!I)MemGzAQ1LPmbK`bM$NYAhe3+&?ysjA4Xd*Rl$h*RhzzJ*j|! zCl|f}DwO%beJz}PSsJxiry09Nap?Ps!KA#(np5{14h*@Tm|=r|Qc`JtW1}rd>zH%; zGb+2IN-r7==qwnD-yDNVaC#KG)naIP%XVMs#YmBSZ@^zyN;uE&Q@g7}iyjND7Y{N1 zIUH!JhV75Wcs%Te7@9T3ImaT!CLVRJDTR|1y^%8=|%AdKHw0M{$ zkVQiXf%9zJ-vbwiX5#!zj)T+Qq9&21=3NNlC`;84j3B?w-yxyN;Pg zuS$(BUol4%w_(>Rk^b^8m<)q2(R6p|zJ!IiAnabQW9lO7oopYCwB=(&)SNd_eUGmV zC_C{_CUkrGu?E&e^#F3$8=QKWB?T-h>VFTisC9;Vq07{xqe_(0!bDi@GI_HXm=^Bv zBkP&%+JMSQ8VfemKX zC{b{HZ!;@0JT7G;3ZmawSOKGvJU`Vu70zIyIr|Ob%HZjqY3rj z_f%6XU{WQ9uVx9Zs0P431wDxFLeA&ayGOs*IZKIAeNf8t$XYd4ec}UVA8Ng9K4zG@*LC*1gqo>p0syY`R-0dwD)=ewAT;+kngMT%oOn?n9;QLUSEm{W&$unwbCwnd#5> zM79Cm&ec%$~?ZYtae33MwUzbLP4LC}^R}^Xz>-E>qG8zm9(Ni!B&GQ(TX^P{e z+5WqyW;Thry~8-?sq9FOPww!-7HfPiX$5W#y>J^dm}&uixp zCMkfY+;X%UkAd^N>Q2WKTYDPCX5Qs9@gg>F^#mL|Os>8(ru$a+lw18ea)BD^fzrQD zCNqgey%yufr#i`n?d%^oUrIGTDc>K~5QeWt5O$Z_T-MW2Qm~mbwC{4XkDkaR;q>yn zJx)FE!WZLn9$N8s#VkZVD5Z+Tm6aJFp)wV6+UH~WfD0mIM&&3~6La%e2Wq7aoST+` zX>{k(9P9gVuz1=hD!n`IL4U;*L2*+M(f6{?YOxo-RD4|x6Rmf7B351(7n<~GE(P8N zQm}be`U!%z+E4h2o>DFbhsMB-odev&tnRV#c1>(8-){vIg-1j0cI(<{Z~v;A`A3wV zO)c{uz5=WW{PU*#i2uhkow=bGz_5JAwP}=41aXq{1cadUm{Wv^?eeXCbPP6QsS?}@ zFlwW`*Mc?4PvVdNI8$UA`H)(Xk%Ug4PaLkP6@aq*m}6R#GlHc1To@OBejceX^$vLg zg3nLmPaFv^?!(*R?YDNUmV;wKvfZ|e@M}x0jb?%c7cZW=I07NSd&A9s^~oV|a^MRD z2v{(DAS(Cl)O*g`Z(IMn_*o!fd=4I#n&SNFAU#a!L5lrsVy1E*#>a_eq44}j^vz$I zOxumW_--dAkw3arIzU+6IK&f$yrNUD^^lW)WB}xe^c0Th`I+Q$?94LGS2$tQ3a0pS zJKHNWe3RSzLS-d5PODKg0um#r(#=Ar#|)MehA@460W23)cIxPBDGLWnZDt2EEQ|%6 z6$^r)U-gSlX67ny?wwjw>F|}|22== zkuFJM(L;W(`hs&|LDeBXp`)Sb1Hk?zI`D8801u` zB?9)b1c&u$UwUm+0s4ONT60>7Qy^%rg(WlNNjW7sEAOTc9#*rqIcF6=jCud%Pto5U z10gQ?y^hy+I{0OHv2IE?T53+B;0CEotEkUC`^UhJMtPy9iSu;XxaYcY8#F|`r)K-| z9OUb?0@__a4A`dc6C2Kw9PBDHPO=3Kf#@$ToSlKJ5Z!asel=)^FbIX&9 zF(p>*cC)0ZGSxMS20)4|xhw#h2SFd2uH6151b%hZEd{pn?u+RaaBs><#U|}Y?sHzP z(kq@qW~L5`G9fQ&+Vj#GvHlZDDlR1Ms8)9p@iBrT@1(|Z#r2*gl3KMQ4UWB3B?oEUAp!r>0dtc2IKGe4;-s0*V=KPbFPOHi9y%Zug{v!@Qz8o2zFC0AX!!26h zhVRJyJALE1m+yV}?D5k3-}0A+1%V7=xRf!E!on!HLMiVf>Sf#UyLl$;CgD?ELR8sT zLV9N=NPPgWe+TIeRy{vW{WifL;w)tD{nV%U3IjEEi;;qnF>j)=&FU_8nOpWcZ1%Tq zx`}8FW^UR`bC=&)lzRxeL6O!)mY3y9H2gUhTz6FUZ(Uh5%(-iDv$gcTt=|^KaH&u0 zvLRr&;qAAAUDkS3i*L$ldPM0&;#-`vlQLq3W-xr`&N|}Pv1K%?vX#HD)HmF?#*JirZqY!}>8gM6s}0(JIW7+Y0?lGp@XO zU47j}@%rG&-oo>TTuF)T5>~#)fX(SWS?P>4$+~DUu3})`aARlRXD)Hs!Z%A@rU!=Y z+tkO6#((!m`*RpAvZYOs=y_gzgnD-rfqU5& z%E*}HL}7H#pVfjMHPNY-`AvEZdjN8Mb>?4%%cR}}o=2=|1`3%gU-dw>pa-J-=hsRt z?=cD*>kTm9OT|vzag`2yUsvyt8F2h0*1%wQo(m+q7V?OZ!N@G8Hwq@-75Kiw)H*Fd z4tEr?Q%Ma9REUc+F&hP29|i8U$TB97a8=)VjSXWA*!OlJNDAA_D*9|OZh!4kd9`ei zVAMi48>%#3kkLil8)1=g_{qvo@gUW7JtYvRv-Fg(itVNsmIaVpsCpAwv6B2eSUh-)bOXwgGm>qv{>Z6db92sC?p_wA>v0&+-jf63p(9h z2`GHl4%Pu*^$tkSPNO5Mxo#}I4Z3Q^wZX2n6k%}NT$t#EYXU#U=8Lu$_V)mio~rA8 zjmh7-;+4TN7VuLkoE9M+bH6dCT^f>xjZ0$Nz?N7h^9$|unTpNW#4)YpU*~fB^6_P( zWi8(QnkapoBgM!g%6zSMPfvJkxuEuEYP7bR@jrDSL_r&+zVP+b$ZKW5o*|Fb^F-|J zph{CvWoN<|$7^&+7La2mpr`%93#1-)@23w(@AICcLpy~x{ePoGElezGGl-whPYZis z91Dso9(uOCrMw{r1sg_>IMD_!&q@bQR7DEhnxubTF9(q1q`n0>ihPjKV*YOPvET1f z_=OTt>dVw)DyiFqPpnN!+7U0IZA%w-*?RHeK-zrAR8&k7by+e$Z8y;RsIXtP?{Gz0 z+6}(oSJf_ZX(`pcqy2XP3YWahejH)0)j!{@BOue*n8L9eb9KE_CS^{A?(@5KP$4#& zc)3G0bVpY>bS?d{Qf}%SF44)mYziuSao(I$x}c0ctl;}`ny>uXbX3b2IXz*ks zU*i*5rCie-fM(B5pbYcV)e}zdQ60(>o-LdF@M6-0=?zc8uTdhhclhSbhf({SN{h^$ z%eQ`h>h01^NHiq^6p3yDSP#&XKaqu=9%*Va{IrnxuD~(gqoH4Ycyb+O;hzj6p>Vc# z?=Gi=v1TVFA=M_B-653p4ZO9w^l zGlHYO)#h}LpG&0gCC`#PIm=brpe1`sOJ5qhf~CTa=OZwW<79b7aGqi@yI`yQRD~ z-|@>-f@h16MQH=LM`t8QnxKwD^f>2LH(w<;hk?txy;)1#-BgxpA^l(QMFdQz+MvWpaCV5wwIkWhC&(TDgc#~UvwBFzyn;Oqozr0%wuR0oTxSbUDeI)p*?d*h;gh8b z_0^Q;>0OK$s;RWr?&6m#Co9qOKP!3{x;*4*e?!WW5?!b+ms5slX|9V7*KGPRlYtS@ zbRLoCeObGEbzg~A%RAfECX^i%xRfwWROHX`gR2LXk(V2UDatX&tD}(na7fxATU7~K zeLs+v72z_w@v=!Q$3N6wKY2dZmIRJ9aY;{8evV<7W!)+n&@*p~gf5oTlwjsRY}pSy z>?mu@EdrA~X@9VNyQ;s8qiQX9mlnrGx)GA}M4WwkS@5_*9e8?9b-B)ZPW2R_hkC4h z-$t-wWP0K56QgV7FzgzYl|UAcnBF|1{*?TZDyxKgzKGX>y;qj7kN-Zjr5r)%s~{I> zBO;MmAx-jn5@CaTUpn4JL`KxnevgQ}ye6V2r0~DYru|>G{yV?MLOyJ$qXGfj=xS)$ z=;#@XNr*{FUI{0MMacGF@EQf#rze~Iqen7wVv=$)vhuQ0SE$Jm6=Sf0iaMC={lC`# G-2Wddyv~*Y diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/FORECAST.index deleted file mode 100644 index 827472ecd2ab0dd428fff62f5f7784c73c35d807..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZ{kF-%lJ5Qc{aNrVO)C6bU(X!N{rsBlmnB6nPrdoSmMD=bbs6BDScY&Ik&c2>s5 z%EH9T&d%f#Iy*ZnJ3BioI{(>uv$J~}9(h^v`1oh$-+#Awvq&>UbpGMy5f-|QcMfm2 zD69SEdW#P6xNZIuk((vDhV>cN%UDOfa=2ZT>&nqPri8nWmAOk;tNy`WU>Lx|T34|u zgM!1rEO;bmP%kh`IWvz>qft5BkDHpD2{=K)W&Fwo8GL}=TaCMowkl4}bI?x-MF_T( zbFYQt33N)SyjvxeJAZRQ?=8j%-qOI-Qg4g2>U-m~D)UbUJCF9pMgQ>_s^f?KZnxRm z+R|P-C%m~tlMSL;}_t651` z`YvGX;vzoTeKRPJnrrF+eU{yEKvwbcWy89B%ieF`CxHL(6;G@y0g3MR8^X9Klr=8ECV*a>)_gbaj_H)nLPZN*dV#s*ZUiR@jjjQcX_fMY^IAcv& o?0)xiYg#YIp5Oo4taSf^p8NY1^}|mW+C8@inM)@4&+wlC0Ld;kW&i*H diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_21/PARAMETER.index deleted file mode 100644 index bbc36c70459af6a5920703fb1a065aeadfbe219a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_22/FORECAST.index deleted file mode 100644 index 93b2a8a40f8b868fb367a9c14da530797523669a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 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

bQH&St0a3Tz{Tb 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 E17QRI1^@s6 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/FORECAST.index deleted file mode 100644 index 457dbed5366b8e661a33ab4d0822b15b0d23b156..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZ{lEo>A)6vrQ?kWfr9KxjgOfRy9Hwe&NHE7#uj0^Dw3=?cWPrm3n!VKyWrI26I4 z5F{uZj${)Y4u`_k)m7E;fAe9-~Q))&SvlC=mHU)eY(2~L-(+*W4#z{ zKG_~;!>8jie?HzC_WSM5`g(hDiC*IAuJJoW)e6x9>?7FAuqEJ)EMN2-y=4mA4AD*4 zJy^#LvY7kqu!y^et$vmlUW+yOVS5dhwHyO2W$rs9VlH8;4`xT9eSI{)khQb z?nxNEA`F+lox^3WsHS(6a+1G^aI4?vIXEHsJ{6S82Gzf6jIX{s6wXCCuD+*-hQ-j{ ztba`hAH%uj7Jk0Gbee+khzzETNPX0d$f}G;2Uh%$GFm#1Q+bZQ7(Uxp7X+Eo*N9%B zkx<-*QRBe9xN-iZC%QJ|4pX(mRLvCy30LNdF}^5H2xF^4)rLW#Tb$=kYpJ#7)#|g< ztvJs(I=PA}cYP7nO`Z>6C73WZuTmdeFlEqTw~UzxCdl!oK|UBaOEM$cT=d#FKXWo8 za>r=(>92s{9TWDoDt3RQU@*lhSba%PmRrFMo$Aqtlxy-9)UGhdhuci1HNg#IeBS1; tWnYj{zT1A_tK9wC%mt9!Sa-0b6g|D_=^-}pa3_1ord)O`zc|70|Nn~q3q$|_ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/PARAMETER.data_0 deleted file mode 100644 index ef0f06cab0637680e7325d80e35560f1544fb72a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|4*&mwvuEA~3f&Ka78@Dvi pe6!zAY-RMxg`f8q*4&P9+W2gL-1(O7nBqVCLFSSP{xke%005S~I?4b5 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_23/PARAMETER.index deleted file mode 100644 index 5cead4c75cf1bcc13ad902dab8ff7830242a817c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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

P{u9|b%RLMt6CQ!+fftp zst>Rp{p&KV@7hXe13OUp!8KG~_(CpT>D*lgpE1o+ozajZHcPMe?JN|GGgQK2G&_EtE~Ey$ITjSZ8Pp z?bbAqcWO$XpMN`ip616X`g}(ugeLpY_-=dZ+GaBNC=_=~LYsOst_$^}9uyCb)AiD; z8Pp%!K%RIF+4&OL{~^^6eF53O#-FB@{`2>*1G{1V%*N(}>imMs7)KY+zT{*ZT822y zpjeoH8@=Ydi}|;*=bWn8gELM$cKm54o0lH*dA;!(=J__?Cd~VFiABf*#JJ_i57gd) zM_qf};qGCltlaq!mYg{DZr&T*?tp=Bf_WgLG8B;@eJFZ}wTJ8eM}j_&gbMj_Ti0tTKdB{OlFg z?<$4$=vKR+xzm#NV|Y&Nm-&+p`)ecoa2!1A1{@dvRN$c7u6PxJ<5rpW;C!&o!8kuW z`gh8wqU6PSvIa!~L*HQ0(Ivnxwr#GA?LyB9laM{~VeWK?b zr}bHR*U9Q$ig5C&zwS9z`=rQ|^ue`IEu!zg3Eu)R0)tT=}W~R z=ar#-Qi}|%N9Cs*leODI@wFqxFPcHStqhdADG!r%Vp6+C&#@i-^)_v<<}GN?-++7x z#X7+qs&5uX8<26r~PBTlEdakMq)gjvh>= zyF~lhG#BzizGngy)hJ(7D@#(ocw{x@i#!G9T~g11tZZzW4;3B-&6Ceiwdsoak96;40W^(kog)YFI%c_7>)ACGnt@_Qx5XJO{n~3cQVd! zst=n6?S>^3uUZGqi)~Pq-$(T`jzG5c6ve$lpvZrf;vP33FLMX}o&Q49;{nC>oO$qQF-A-|z!_Z_nPjQ8C$k*S8vid7>`DbWa{Gzx-G|YDeiv{&)AISdC_~Y~U zCU@`u`2EK(U@J3li0dHqwZWUwVH~pP(AeZo=uq_LNPN(yLwQVuWyyX~#ozX9&L9kc zBI9rj_-0r@8dt7^mt=CKqPW@qQU8nkN>LWgXzoAp?&(g$cdQNQSR25^lbjrSgt)2FJQRx&1 z=noVoPbU09LN3|d(UtQYqOMET`b_KQw0q0-aGJv3dpcS71HGN*Zn?frl{<4k zr@kJeztbLm4&{fC0WM}!cltZUnneShw%N!*PIINhV5crtbBI&TC`^9{2u(N4#r#c7 zJoqSLG@%5w591qBQ-Ptv01YovP-+5&V3AuZ&Axn7$^5NbKN?qs=L-yV)l&cq?sNHOOQR(jk#5r#N zZEzf@D(H1|ZU}7!fHpWC+2Uf(ySqId{gxMtMhY7Nb+Xxe4S^X;}!hEI1gwH0ZMGyYh ze4_~+-+&1lpVScJp-B0QCK5T;U?7(3E8zi@t=S6?o@58_!PC9>c<`iut^eST!=`TV z(W#DpB+E?sJP=Cn2^Z@IDdL}cBsmpqx0Hi zAmn4RL-p_m&cE3?0qR3V=<`@|l^zhrD^50BfCq=R*B6>lsX9=^oQnw;Yj=?*jBP*R z^JalGftJx<<2n!#hiPITG7Q&;Zk`L*i`o~4>xV@sBor#LG9_5oa^X7TK^-X}%Mpr1 z&D>swd6u|)o)WnX<;Y`Sk>IJKk&x|~2E{FV(_IfH^urCOE*c!}6!lAAcdERLuR3j$ z=vSOFI5N~}0*@o{v_W_1{@C*Ef-4vO3ZHlCD|2xF$eU5mApR6^3U=;+`-{EocEZK- z)4JnM8z&Lub>`v00uN0Gna^grFIyIZEUX_AY0-4@5v7?^>|`}>ePGecfsHDm$wpoI56f#Wnk zE1q-vWeRxq4S&L7UbU~&O6(99Lh&u zp=i(0|5*Pkh*hHjP)EMRa-v5~GL6Q1WvpkkokMwPy9Xk%A3T3Md~UKwBtAD?e>nEn z_Rc~3zvCs2$6h#u`Mb(F6~`-^H^6!0ky+`y9!f%=U;I=!?`BgG`kZ3kqR*woL_7fD zc{<^NkX}?J80Y81KL?z4>2T_Qa|Z8qv7U5cH_k_GdN9L^p4^UhX(nxTsu`!L|31-e zy^C4ao@<<@(p`;sFgh{-tho@mJj`GM-bc zIf6V$y~=|;NRD~JUAeU_vN>7H5xJe}X0C#;m49I;YtD-!o>ri=)0A3+FRaOegY9RjlsYvW?^aV_OXp;z0vSig@&`B9MQ=wj1gWG9p-JB&QZr1*n8$+W46JjukF*xl93 zSm%2DAY%J}2x4uk3*ALPO+Dtl$^O8wVhN5*5oLf3k1x zL(^^&@+h@CALUU|uR~dEB=RX$Dm(HimNpdHSi_N5vD!H(ukyPNO}z=otHj3Q$g7zD zD=0(OjCA|OqP9VPB`c;ye#QFVA(Pfcex-WvfHou<@+?thDC7_BQM{?jShpU&bSq>h zQXs!#S;j!I@fFm0nj^nr<4!}qtqAff8?*+>!AU94iW~>!Zu)@*wxbjBE3rBpnj!Q9 z3asXS%C9QqLjJ_N(GMcX6LBeDs!l(6px(ZrI7lKtl1HyVUW4)@SL>IUuIB@}OW z@7k%r9?-;J2YEMovB*?QvjFuE8$-5mF2$2VDc+cHp{v&?>q2#MHk4DYKx30Fa`kL- zQ^*S}p?Jt$Xwzp{?CNELwvhE&NpYV@Xkur?7qCpeHqgGHAHq>R?jY7LQ!l~tTbq%W z7D1i=1~dawEOqrZZ)3>P%!4{rC^Tu}EpzoMdo^gwkAb}CLGs3XGDXhiuAPk18tQYi z$vY>Yo%n^klye2v*Q*5-f2Km#@*p$=o>6^`=t3H+b&=fCGar>iz9@6JoSfI&_>vB6Y0`|Kj8Y!JK} z^+gf|I@QRYI}yK&igDOxtblRb6rF)_U6rbU@!u{gj`@M<+5__kHHQAsAQv8?dB~dV zm^bQV%Wh)5Dbr#e%4@Bnyl7+!>&n@n*7uz}_nHSzd*m_3L)J0NV;766EuJ`K%So6I zvm}%!iSqlOyK*!0;0vezxE1qh9fux}@@sWpyK;W+EBS6R=Hu#DEX>b&sXOYsHIDZ)^qLhO61myv07`4~e3sAd@w4C|oeG%R?M>)?+ zc^t2=sNJ9Ww4Uf&p?H3Z%7@&cxa>P9BV%EnU=L@b`9j57kc$x%=i3dXKjnoYsqY7O zT%y`Qa@R3vk0<=-%59~lP{*1B#q{G;KI$7}UwuDe`HsDy`mqt}(T^#vLq9xWkJ5`n zY;*wfE_R>32&Mk<^32TXzPR=1QdJ>O+yjcl^o1w0Zy{onGJwo5AF2)XMF~4~F2&K7 zL7jg+WFLd5{OUe(+98sAKRl83He%WH6SQ68Adj>klS1R00ICSeEA_Mo)b98>Xu8uE zvGnX!hTXk%zcaFl_ifuzGpEsQR#;*l(&vjp^JFjXJKJ2){g-Ml-LEa)p?_gh>ZAWL&mSZIw-rC5zmkutL(#b( z`Y{n>Ec!LkHvrE8^!QNpdp4N9&?(lOK!0c+b%!b_8TF47=!Z#offDF9b(GDI+~>wr zDyZi!pgbdHekkK#r~dZ+U?>B#LUsH(^~Z6qz<-TDf8YQ4&-qW%3!lol-B6#hyZsUE z8dP@b>ED{c_eHun)#M?AP~WiOSf{P?bsEZJ)R^y-nQAO^@+!&JATE~}c^^xWal4Cc z9{Pj4X;|fei&=w6j9YTo{Nt!k9_O@^_d9*gsm2@)LHV(dp-%QG%T>geM_hO6M)7aL zW-o6$RrBKaQ2!HZ1wx~{{D@J$P&v#0%eLgWv7zGoc2x25>DN3 zO)01Rkf5y7&R$;LsdMJ2;N+ucS9Hn`aVk5_#D!IyJW=6lPTSP_In9t2$XCt0UbS4z z`q!@G)FBz_ImN3C^_sb>&aaJAf8N^G$;!=;PTitvJE#2+rM*)vKMM8TQ5{@te9L!q^0cgzQ`9&{ zt{6x8Zy~=fsE?Yct5bcyL%!XDd{}HAhkRJQl096#=~bnt(;oCiUd(D{@9kp#Gz;=# zy(4*F7n{>7AfJ;Dc`PH||!FsB_^Yq(SI&pEJlVD96_-O%B{lM1*>fS(fyt2P>M!#kYncpruDQDa z+V-iYyXD23rBH3=$aCeM^_1_X%8&e(MeK#@AA$T<^}I-VZb07ISbpOGXxjxtcAEbF zW3JHOW9(S^;W%~KBF|NO^UQV2@#5YOtkpb$Sbj=4&z0*!t)Yw(2w98okQekro~n8; zg6!)PC|f0J(8hZN|7ZO9@A*&p;2UoI5%cr>aI!vi6S@A@b{d|+sTzOC>EwfV z6mp7_SxPzOR{si4c6eM>r!8NomXqHoQy=x0FEm2^x$_vuY_r&{5x?6b;gUD)ogyT0 zC#Q<{tuy?zwyTr3{)KT*$Iscr#io8}Pt=F!=;PF%^YnAtX#)p1McZK*ANkmOLtV_9 zULEN);|q^*vWgqWp>|%)pn(e`R}o-oVHdl z#%&d~*?P3A)*R!vtbBBfi^aF{7{|r2T032AQcc|rD@WVsw25|LT-WOs;kmKNx|yE) zFYbBF)$_C|PM}>GdX6s>tT^pr8P@MCY*Y*Rs#u=;qKn11Uo`#?JbfAQ9D{iPpA``1 zVlBNN@QPj+^8z^{*ELse3P+*&LGK$-{tgOv3u=ihz(vS1&iUK%UHBg+Uuy^*+j<29ZVMW8TIN zwj$4HXbavYzsJQqMHTnveb>A%*u|)ga=D^8Wc|lO8*mPavN>qpxML}_x3ki`GQvQa zv)>c9A9|`U=BGN}Z?fyHXRchVIse?rQiow)%l^E;yvSruiG18ttV8qRCX;ENG>v{J zSRDHN4$HTm{2q2lj`_9CwH%5XnLnbu(;8^*@J}vQeU?JrFyUtx+t@=OI~NXBf!s9j z>gDBcf3_gz`{?hOvQJ#(2{sz#OY8)FA4$Y*jB+!-6V-R`4^{fXke#7CgSYF8n4hH| zst~iOTwNMX?T^hSH)*Kn?}Kc2IF;9p_Kl9CH0d)4ntfZLT<{d~OPRi--9JqsKRW~3 zN@pn!`withU*uyZI^|{d^d`h?aiUdt@*A?Szt`^H z$xaClb_;Vg&|8&gbXVL&3dnXPIkm{cWNkV`cVDa57?gAcn8V`r=WTj2<@K9 zWNQi8%;Hc+CWYeGSM(oZ>;uTQUV)~=IVfwNg53Wk6jMCKal|a`0jOWBCv(n#wjA|K z!nYY>6~8)^L4H(Us6LhFqvwjMP8Y;F^%%&zc|X(|L@zw4S{Z4-U-Tlkoq@`q&YOyN zl+H)J0o32U^?ulOdRcr<*0;nfcR%p_Wzg@bMy;ve8#WXDp3UU-d#}CcdwWNt-{Vny zsK3iT3$kh{slRKq4(hq((BIi-5s(d{A4uVC=s6p^cNG1bSlJ%^iwH}K{zJ5gfa>cW z>L*&PM}MH&(fw~eCZhX0VjtbFIXmM%P`wUD5r2gZB7M%pC|_O(vQ=fEoK=w=T#l?)7}{rfpxR#m@-;Q7{IrE!8C2<7-p+{N;8Q!>YRsKZu4+jlDzZ&pJSJ_hnyiJ+Q)AL|wIcVRpH&MIuz z99)3?&^1=j{*AbV{Z+^JV*lB}%QzlZI}KDz$E9%lp_hNcar29PpzQb?=Y?n7NFEvn z<jH#P(H*FZg`*=MVV&+0KN}R3D1##^g@`ZRA8;w|e3OJUxOwfShznOm{=y6ILEfSheCdJm#v}SUW$2XtPJ1)<0H+$d1oC&u{ZZc5AF?OA zp+0*WnobL;KC(FEDK}y{>63t#PZ^H&>MjWp>&=IuXqjrDTd$6vXfW1)zt~WxiN0^R zldW1l%E>2OS57&s*;v%;Z{wW$;fx7Rwkzc%#Fs`)cJe8Er#R)(qf=2IZR#|XKTJ2> zDROj#Hpvu<8^)S}c84ugQ47sNyKb{)JB>X*$0-w6nCG;Eqc1>tr$US1_`3n9PyJ_^ zQ~aoe@}Na0o#J?`(@xoS=oyq3dU4jNbJsz>B;Rkj zfcmVlLQua@UP3&{Tz0bgb3>iFcf~NoDL#^~)?PuoCrz%RenFyZPCno!6w3myqkY!d z;ZCt>#tqaz*mTor^Sr#})Fm3+LAkhp*U7TXy9bx$wNAM;Ir1P==NDv`?ji5d{Zk{4 zVR?#@Z|H}nWlefvNFAmZiP*j_sOK5RQM)QTp;qra%OU?^m6kxA?GKbqdQv`A-$I_h zG0iLd&O>v$BIXGq|3PST(R@nmSc&<9N*)LE1^clp%^Q9kBFjcczQjKWsLKzcxDve} z!+ozKmieM!ejzI6f&66ysKWdyjyanQ@_ra>+!@5?ZkPLjJ!-gRHg$~(sq|BsLFPN zwogSUvS+1ukPpQz-qP`pxC2?PP^f=}kbZPN*yd-5O>hia&g6#rQe#@*s_~GW+6#H_ z+f;vsUfkjRl3>4W%>0ne^Mkx*2hwj86h8Dr7AoE@DnE9S%<~YkyU)m0Z=jv~5te4#aK7sn1 zt0d-krysr`$4#Ixg<2h-+$Ix%r*zhPg9(Jk+b*0tsQP-NMCA9q>pzF0;20)cM zE@VHeM7r~)r}*Q%@p&t79?cg+U3dFC=*s1Xx3^t8#Teuh;^X|A;c3wIGf@;nf%5N5 zLqm$Q^m+9!0=3T;3?aH>R;WhL$LGqPe#MZZ!)rn1L%$isE8WC(V5ay&wXY(EF7>7n zhB7^5MTpxURw)a##UJ7Nu^;b1mMAL9b>7-gR9ygNp)F8-(vZiRPW6w+L;ZLdWT$IU z{4N1m?>5#eTAYA-QYhr7|A97ZF|;#t`jcO2{bE@JEnmAf?RVxgP)$ya#E z4bd-NkQF1SePAHu{mVf6Y$dIa)4wGkHa4RDNl8P#ZW8?h&ddF>=biFsLEK-$zCPn( zv1jUOCm)#ZlvD3qhx?K3%5vPrEO`*_Q+>@Gaj~f||B%zlMF*WcYd4y*3@AZUnDu3M zyK=Q*1Ex44ReRk3>R_quSZ?s_ZBB95Z>y87I=)Xr z+pB2#z|!Q5$Jnk~5(xQ@04NjeA`gZ^v*9#U^{HNDZ$kAWVo|+qPsbCqfsS*M8?9Kzvkz*4qnt7vBCP=-(DUzpNkGOKtbxs@Hb1f`-XbtMy zrHAU1TJ2(<;>Ic`Yn&eP?hQ5CJ^8T0X@+N|{``?xit_Q*F!kkyDqt$iuUA;$%2koR z=>PeK*K^Qr@Tu8Oc`^o6^#{)?|Nk-m6#9?j4<8(H0PAnI5!ao{77f=SPx9)pD>s)5 z;5t>wwjRUwEA_y2tcQ1@>$>l9T<>~kEZhg8)H=FPs`SPE#ya?hx#d)aBUhX{Nh|bA zW?d}wU#xO4`ZGCk2=#OIO45{e=x_9kqQn{Wm*Puh^rL2cCiJtq$3IY2JBNN)ew_Bu zt)FkGO8xeqFVMtUihkWbDu(`^MWIJ$I@0^iodiJ`Cv>gEn0m679cc>saW&cI3Y2T! zLh+noDk|RikR~d$Dc+-=Pq_|RlPyr69tG_`HKBY!+u>irv0c7#9<s z!sCrcA(lTYK)c`vj)&!?ue7KfUFi7EW`gov7>--L8%9p0uegZ!fjB>Azc=MCxEJTm zwk=HO@4zaYPw5wxY}^LtTMg}naZ85y;&U+7p5k*+@7v;YGAAD3b7MdJXndNt51*@9 zRukiq=>G-dk8F4jpTA0W7}tZHeruNkBXB*6bJegt_TfBj_t{{&J{!M-tVAB{r=3?D znwoyJ-@obKs^O_8BbINzL!Emvj?bhjh3i_3NP^?$i=WYWTvM z3V~$7!;q&9hcd-WD*qlA>tQuYkO{j&{bv!BXOBbs_z^T0|AFfDA1bf*1@fn1w zo=MlmskiR#<`iq^^n`r^`k+32y?##nd{2LrH;EYFR1M+`bn^V6gPeLx@u4UWDm()5 zp3S3CpXSCGr<_)FJUn72LVaY4lNH@D9UfXU%gOUsn*%@Znd=lyGtPJFA`=!k)!Qoz zoh)v|qkKvz7XFov|Ls9<){|^Xj}T3i z?^J)eImQV&@jPVZ>6L8Dk77KrQOjeT(UT2XwAwBAdCG*hp_n$}wu{X}UyS?q=1-`P z(yO#~_u>eA{u`TMo}hmxh;%U@avJK-Wh~-9v!Q-#q5P8nzAM+CM?kak48?zZ9-#f^ z3Q%0@Pi|ih<-n6ruY3kgomdZDdlirlYMu?6@4298UlQ8#^qWaa(sK#sOJD6^dzPbK z4mtpJ^PALu$`A5gmPc;=meqr%&q#{>w?eu6KGf0EVjjk3H-Y@!EGWL6g*tU~%;R{~ zN>Jpa=N;k|{Tqt11I_=qPqC+NduIG#$d(5~VSiB^UJmm~QGGOI_vufqtZkI%ZaJ2| zGE_+>!N1$5@`FAvu-<|6TSGe0G>Wrbf;K3@ODvzI2Gm0*Q_QbJ`!V+`S1&4#gSN&^ zs7L31?aHkh0Y$b8Wc*}rP~Mn+yVI7XSHJb+t0?E?6TNlyrmP>diH1S;YYoM5PC=O~ z0`mN?sQ&Kzx8?tp|IqmJU-KXNcFh4CPlk<9#}0zL)qe8b2`b+h24$Z6knQ~dMah`x z|3u@o(02EQY^EQ@7bKM9hETkC7F6rjLzDb4)i1hA_32(y`OVnqPvy95Oe-wL-2LTJ5D+hhAI6F=n6x5^k5^9Ww^12q1RXuk3E z1I7)#cM--7v6|*Dc2&INZaJoDKE`wD6E5ZvolatXoAaGQeS)84_!W#Nw$`>Yu3XQW zPvc3sap%x(+Gva??9r?XE|$UDF`mfWS23RGvtMc6J30x*4>oKgR9j16{E(f`LN90W0SuJdE^|qGYk4-vQ;oD^!2?6=Y{) z+;+>U?AH#<(EH{UH5!V0_?J zdeZpt()(?^#X~V3sIAW-%g_enfc$)&#)ISa(a)=Rm!U0Azkw(0W%SRcZX@c4kKKgg zTwV0HcGiBVqGdvVtBOpAX44n4d28xdBk3n4)WCS?Pi?OS z0(rWR6fe$;eqE<-2YHKm6u&tIZLJ>^e=UsuT`Z(mX;i%Ji2wc;I5cr`QGb85E9tu# znzHZU->;;hpO;bSH`i3!1BlgL`qK?BQxyHZO4SpxksG1h^A4KVCD7lis^g&U9|p~| z%+${p?E}@IeNgQCK=Jux?{Iznq*n)dpf-0$ex+dVaxLQNJSl-9djL;#^1nAePa;Ma*{2Lw_LOG)8}*5=29P zz+MMHdn_LH149Iq2f9#Pn*OaketH&Sy`26H0vS&uwz;=ZyYB~~=zkIN88qLtrM^SNQ5PnB$^B**-A2I3K`o}WQdGSs+~lsBr>OVq$DX(rs8S8 z&+gyxy`SUz$8%rL_mAiJbsdh^b)IYOwb!1`_uA{T*4k3cYfyaD3~^1^I+}Q6HO0FT z0U-OC28yZFUnuPFfp{nMo&|F5)UPNvJ_}nJkp@Z?rDXT0`Q0sr)+iUVYt|&Uu|~Y) zT{ePZ>;1%KK_KUT9aPrd1_hS~AlpyhOyEB$B6_Wicf3m8&eB$SzN72@%gC^C}+{oQf}2?*lZ2yf}A}S zwsL4L$nUfQx$}0Q@Yb39JvI>SNDpLbE7@^7Kq+=N$d2p*6_dT7{D-K_JV5z04ukx; zW1x6k0$CSYBVJq>Lh0-rDD|Q#E1QZ6>COS*F@A)<~AgYO7jR4U z^SX1PAJS`Ds)#SJj#vGxbHZ)t!e088jnv{pqH0SCSMRA*R_{#)>+gWB@D6*SE27`! zbmV(q(=Su2FLXsHUW)dzST7RCC-iJWx{^8$=S%inhx5pHJcsitt&{0|&(Fa5S4wN) zx=8JeNlyZ2;QH~WX(*J~{4B07r_+q?gC{GA8c85OyA$pg!Fegj9o-EoCoh6x)0#Dq zSABuaI#y7=7A@&M>_|hW6dh04$|xEyz`BOOmiBss{N%2nQ1YF&fBzhmj+0(+lW8qv zX4!!9buXd)ZL47!O<7@`Yo@GBHAOx-n))-Ofiz@G_OXLs{AmyJ-!XN9!b~BlztZ#O`p*9nUV&wU&Wx}K~oN7u|^+U zHsL;1I$gkXqAVDX=UHi8g6CZ*p!Z72t}WSj3qWbxcH|S4GKvG?^jz{iv++DA#ivj% zzq1R~uK|qKcUYgy*`ny+wa|Zr5)^`Et{Vw7;&FAfJ%}Dkig# zPfTSXC(xSga@bImQ{C?cKOeo3XktY9f925ev^j$~#}@Pf#c#G0|6UXz9twRvkbTz` z=~BzHu=zh>lzyl!$RZj*&sZq+@5;V?D6S?R0_9ujAgg=}iX+~?`rq_t`ac=}RxK5H zFZ;ix;Fn3y!G<#2zv7`rxSyon4L~7}`dzDshSGgzS4Gz~`3ER=s~{Sbk^f*Z$UQCu z*(9PISVZaOrIemT+bMs3!xrW>MEPuTE80)TF0}uy{m9-o0#usPx6HUa3-b3^PAs6f z$(o6w1FM>)$I`L^OdTv~3+#IVsK+n&PpP+bn4aI@= zbr2s|>(ih#bT*!QVMsSTw_+bHiZ|Um;ry~26Y0Hu-4?u`OI?@Z`pL~`=^f$vIlLbW zeN4(!oo9DHf&7wVU(gdqB1+7?ejHAsRY?O8#(A=vj~KIEqNyJ%?J*^UO=^m%BJ6_}O+B)hKvPP#htgD{`SURag(=3ELL+yWLQ`x` zj>Xg)ZsOdIxGsKMF-3>Z+Dj}u0&;gx5hsTbSBHW^-z%WB=^Cgkybj8vZ;;(1g3^<3 zf$YF-vJ;X(&h7!ouYE*}cnk{V4?*b@euFuQ~x+`X-)Y( zGeEItS32Hjwjh@i3M%z(g0h_>rLS2>>0y4vz1fuBV zH$kQ6demQFGzF2J%E9?nUaUc!k~(=Ij!7#D5Z7264slNT+V9`up13+4>3lD3ihpyD zkUlDJTXG1lg7k*uUKHEXr3#*T!~SQ7R}+vd3{q8XBbAZ%=@7<`+;} z{to1PV?e(63~}LOIuC^nLAJF5<+1wXDc---rZ`_2gnIDZGC^)zG}R-r9Ql-{4zyjZ zFgnf+lTaR4t`7=(tLV79Jp|d^>)4KSZH00~og9=a4|E2F1;(Hldlczh;04O>y%rQK z+Jj=p)*u_T5BY@2BS1O+3dox7r1S?JP(OL4Ey&&8((K>$r+WVBKbZd`9ed-e#tljN z2685y_oz01!UmMQpM%_tv3pg&a5ff{5?Ah1ZP8%fewB*lMB0J07DrfCp>_@g&~L2jx}cPpN*XK_V#LKYUuXMWfh2l{_07tWq)8IIB_~Gwhs7A@R)xmE4lL zmsN^Ze_v6_icGG-Z@l@2O1@E9xJt=6AWEe?Z+i^Vx6hGbFZvU&QkZ=sL8Vyfm>ms{uu5SCgi zYJSnJ803d6M}GvjD-&dY8=#+o+v7_84iT5A-$AJ9r_7}#bmX=4?Ko~y3es6{6ew`i z56|1sICIW10)9n{{Nk~zu=%mKK&e+MCpmlxE} zvv&~Q^Tok5UyK!1!e*PC@ZK#q{Q~lFZfI}uLOryLc+Y**PFmB6+B>&HsJ*jT5A7Xs z)qYTjDhK5)eTvlU!;LWlr8eV1(P|nfT$n>NSqO4rOF`Dk7F3?B0QpQiQ2Mco{KuWi zpS>Prb!f>HrKuOCyVH0t$<-IOF!UfOy*^I)TL*)pLnx?pzDcyBDXj9^WY}C7eJf6w z{~ETOLQ6mL%V|6T+wc>9!L{y3^*H6=rl7dCH7GcB0;O*>m6i|f51acu9F$*<1KIYe zluvsOC>~l!b~_u8b6-vNp>-f{vI!JlZzX?_FUXl6BKzbCP#F?L)VM(Yu{5QXn{o>_ zzc`WnWoaO5PT!JaTsCZO{X0q@N8gkaEy~E>kj6{MC#qn}A8Mn$$|q`otYH(7JFE!` z3u%h0vY4i-N~dUwD&M|(YU;ne|B(Ltr|&=Vn3~_a#xFr!;N|0p6TZpmfsp zw(1ux3MoEY+JMsFPl($>!%d(vUx(~fUU6!E7D!8?D&ezYRa<$Vk9aTN-3^L!%|OAc z3n+P4-NOE-egnnLJ>ln$`%r$L4k(8+Ndu*YC$Jx>_YCZpHO{Ac+}@7*i4{XoZ%+J5 zTuk!_#A&DLIOiO|aVvfYaUMjc<2Wx|%Tsiobb@i-_@mJ{k5Y@g6dczjny0}otb^{z zN&(Kl^fDUPLzqwVK$RPtalQCCn@N9u?4s)!e-_tO928I2dGI^v5BG`2mC1@1bVuq` zO7};W^=oy%a`IE$M{+Q)sJ0Z90xC=FpfB?M-=I>k1@XCheigC1fH*Atat4)Cr$PQ* zEGYkpApgf(AeVa=6vip!|5^ueTKJ?*w5RdA(np!{&)!A(Ys~{iYx><-zC-=)tn3-; zA*^{oJevuM&N*bCcmlEl(mDCgG1&67wUjdCh+VgU+{vqC8@vFO4c|d=vL^IKGU^VpOwv^`c>-*?-wg6Mm`nN2EdT{8E3*62 zxHx7ugGssOE$>OYV>PS&3M0eKR^C|`qQNP0aw>QnDnm~Ah~{ZM6Le! z@oVL`V|5X2pJ_+)F<*{8RYJlK-om+)KvF-6@l|oM~dZ8$obVRke*}`d+ zvd)tb_+rlH@R)3=`UbSV<&^s!Hf{1%6`R4iek*|JV3WzK3 zA`o(|Hj!Y3jX>ZNTmGcLH!u3La3=_yTck&4hqjL+L>cS_(?X zXaE*_Pix7s1-|eLiMuI%mp90_p@k8YuCyH&Vg^6gpyr1m4@0tBbpb`zl9>Gm`ZYql?Sx8i!@rB?C%fgc;0LSS?FL;?(!JN%M6xMpsFaNz?Qb10^6CI zi5feofzJ)6fT{>xDIor$HP?l!^usOJWCoq*zPg|=rW69hHbjEle){28UO?AHiKdhW~2j$2J9FHK; z#7XhPNyH(c&lQmWAcAsC9gyob2Kl)PQ#$@x0v)%}AM8&YD$)Mm_rh_@HfK;jrA}wm zm*0?p<6xg@fd;Yc0OFyvb}2eG*j%qr)c@$g3o7{wx6i4RzK=lstR4t+2KF5(82MT| z1gR8u*$2XJ;)r<5rL8-q+G0hZ1STB|04+A3P$`7d1Vk~+!e6!JE&C6uWOXC=Bj2<9 zJ+L*-?@+1SGS~{+ppKVH;dhxBWoM{@dx{QDN z_pkS-|Egbjfs+5v^-KBC^l!Dk{Eoh>RZ0!oc&Zd_#zVijKAuNl>zdi{A*u|kF&iL_}>gge3hCN zfUNVbH>zKDr+6(EP{Ul=IECW+k|a>nr;ZZ&lrQ2xS0{rQ_?4L%-8W1F(qk$2E(+T+Hs27ypyaVY}KTA+Z^(Vf546;{E(V*m;jREELw6KFRb{%Zi z-wjm8tR$AvKwKfeJ8aSL3zbt&Yqs)JX26!lyrX(JtpvrCFE}2hVk0Q-uEg<6F~zkYrMU^Ufac1H}$BfRT$kLDxn5EnTNk{XkC7 zpdl!Z zpMv{G__-VPVTBKD{Dj{7Ds^ql~LhmGLGvdBbb#^zl&;1GA z#_)SJoupF9`E8<7%=DYCl1qFt1L@ZsO;s{QZzj@XQ)a7_I(b;A6#hE25a}njSb=9o zS;N2L*b0@3K{mZtc5Lqmd($!}m7Jb%8(h@fwwUAJ4VmSRbPIM);Le1(e^+ z4BIQdT2x*$EeAEfXjEwr&KB)dvi=Kf!2u_hs}y`!!PI;(Z;Ir1q!&|k5YH|g=d1JGx&)y*t5UD@@C^!tdAquP?+97UxVO#KL4r-!+! z&7JUmqf*#T3ph!wYC1fFJ@c^L3!Qh^&gVKP{T!FC+RU2PT;=aiD1e<21xm|kzzAl(mUsJr z^cPD(Wl0by#^w>%cP&!Wl|IygDE8k=_WF2GuKEHBXaD+$a-N%lLh5EvG`c}{ry@$< z*R@#9$2XV{im|&v**pRiCS`-{Uae2qZ*M)2510xvMiURjEE>=z8Q+DUdsGI>dVGnx zoj7(X$iG?#a$(2GzcLDB&mMxZRu0+g^T6s&|MA~{r(gf+`Pa^6cXn8zQd!_(uaZ0M?ErrM2E7ri2SbmfE?-^YU##h&QtU8tvr4|q%M1RIao#GW zfsMDp4)WQdQZ|3S3--YqzOeUa>`^J`8Se$#zX#>F%0AT=8w@z0Qqh0q2iqy>kV?s~ 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_19/PARAMETER.index deleted file mode 100644 index bc3f4758ad69997fb1dc271eb8097f53d83956db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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 C^8OtF diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_2/PARAMETER.data_0 deleted file mode 100644 index 1b78159dc127a5529dfbbeb8af5b003691db6bb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/FORECAST.index deleted file mode 100644 index 62cfffa12c9af9623d156b51a603205958fc3a0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZ{kEo>A)6vrQil0Z#sfY5}b0z!}Du6*=ET{(Kk1-RWDOIIKc6et`DvuQ$tt7>W* z1g;8KN3sbHL+YwOpe%$ogoz-ApN}`5Y)-S$(<$ibqtRf{?yjw=bS3V< zR)}t4J9t1egMBc}C(6)O9AL5iW$bJ(3mjgrN5cG<4oPrV|N)kDLIK!Ds7ha|Qo(hU{ z1Df-<6m+=}XP-mbNu8Ub6+SQX#%R%`XE-k&dTo$4mdlB|f{(2FkwzwtW#2o}Jrj!^ z!!8{gq>e81%=c1t+ZYv!I~j>fJ9&lY2&>~d`R5%XNgg^dtOmVzSlC$2#1)p9!XOPZ z4gvF#hVaIPP+^F8m=>@*>Ap$R+f;fEM>eP9e5>8j64B>I6UZVy*5!m1qi36*!EauC zB~4gxb*th#<8-E6PvjO~H8e=CE)~jhUurhu6&eat2F!IqB8GeGA1?Vc{k_wBas zwpR7N^~o86n5F2tUrrY+(R$JQ(mP58n`-!(q8lcrEfOZ#zb(B#shG>(e`B<5f|@@* F`3Dm43FrU- diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/PARAMETER.data_0 deleted file mode 100644 index f804b9c01baf66c1de609ef7aa47f397394a6c6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|fG6WV8g`Lp?UBfWq7=U!%5xNY&i{Y#V&Jzk~r#(vl8`*+mdz1-g)KQp=e o*Qx!tn)msf0?PlNzEWfHo16Qmom*=#HT;h~$XqhPe}?}I0ANQw2LJ#7 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_20/PARAMETER.index deleted file mode 100644 index bacebc6b31e7af090d89747d14368268d92c752f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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

lRXU^_~LDHn~X@A}6 zN(F;}C5RAPfb!@<2KOCE4%-;$4M)JL;eno{xQ2+~leW~m2|MvFkhVQZZFn%+&A*n+ zO$V0sz3O<{xZl)c_9OEfR*V`|7M?aD*A=d=f!xU_=;~IM81@5#kSUtf>F98J>z?F3 zuQsj{kv5Vr_T*SyJ=t}l<$Si5^kIjs-&uzgb}(LI)7EoF_@1(Blaa)ncNXca=i7Z3 zDEcT}Oo373UPt#MUIJJts9d#=5D4qU5=X%a;!oGdqIKsLiq%}A^Pt;|%&|pw7#QO5phrKqN-ww%%{%eV`(@>XrT%A-$ zMv@8=t=FCDcbr37qo1Tm`q92m6WcY;{iKsi>~WWC8An27Q8-NkJUm9~wXOALqA8Do zyx0k;;V%?_l`=Dndy?fXqtm0XYBCApnbxJw3!KrR3?w1dbUpUFfxDV$3&@dHOA$%uU!h9rTqD{eLH!yrKU^KS#Y}{ZDQeM z@Igz=ehjbC%AOvoy`F3{At|r3VSgartHk2^n&i6A8AW)=`Op3h%HtLS&2PNj@f;6j zV_}E{a1J-Su1q_c z@Tw}XOgvfaYWMOUb9XMeySM_J#hiZQXv1iBAfIus)TV?oAB}g?lX@L?e$;NO%09Y( zmECvwU@+*ibFBi53nUnZGy)_>xv$i?gdp3Yr|c*ZRDor{Jv)+|38z7nIyahjs5Rf4|U z8PndC-!^jSPJH*FJ?97{{IT)F(XUd$cCt}4Z@V^?qzw%kOkEP;HA{W?T19&=6Yi%J z6wl(H(dGi2z36L6uc^p;4#a2uhXa}T!-D6i=ejFDQ$Zux$@w=O*M4NPie@Ln!piftVk>%jWp}>)N<6Y0LJo0D8+ZCw4 z{^LWvp^l7je#jq69hJ_)*hIl-+zOzpv}=-Dr@v5TR==>iux?uvv9C=L*m#$*KewT8 zDRb6L@qhd2f9UD^V*hQ|UUxoYa4_31P&bACqdoF~Y)3ty>+ZXIZXVFzZds&CVKB?} z0DN%XPpaEP(!)u}xG&)km>74&7MwK$y-%;0fZFzG&aEMu|4H+FH2Cf}uB~s@E}jZ- zCU;H?O-r^l*3tKbCA8m)wymJIBjXdg;P7uZO?smaqWVfdi13<}a^$DDi!0ab_n$@eo>fk=C&X^6b_B~1=xsZ^DBTFMxyo< z4M*T>(q*3J2t8(Z*&U^U7<{J|tEo1-+gvGiWIO}hZ)E9955I+H)mv? z@WMT_d!7VI`e*GfA5D3Y@=5${PV`sFQl0k?@s z)vhkO&@(Y1oL9ipo(c)1N3Ejvu}I$Dw>9x_SdM#Em+unQy^hrYks98@+U?~++BNKN ziSHr8f60;f&U%`60KT<~{KR+ynC(6h@&vNF>5r2`g~tcx`h~FX%+Tw6HG&}pG6LIE zdrKmqKf9@>EXDT`@uVP^9rXO|yiorP#%r;SpQkC5W_r-%)|52BU0yNsSEI~TysR%c z2i!dz$Ed7n@Y2s&hy^lkvDsT)Zckcl1NAw;bZcG1#Kt0ab84(}ltMmId!s<&xz!@G!IAu6 zwdeZHMsf+)ltVnf!#`5~(m(M<1~s4akIMA%8E{0QulrbYqw(kMYUwK_@VDTcSv`Lu zC?27;vut#Y^7M5)E?OQ)4yV6aBq2&~D<#1bv72tCkEJqt;?li8H+w=y!gHy?ij~ox zdwDE;eDp6H3CH&|lx}^5TGjLk=c~GMQl7={x1XPXGOo9u+ZQQ&f)jYhGM{c8YNZ~w zsJE@QlLNq&ff>i>8y#DSMOzn&y&v&idt>H-$XCYNK5aI)U$~GwPXc>aq({u^eCyi? z+b`&H8ghq&Cgbx7(=Pj3bLwvj@xNrc^WH#=2s<9HH@Nd@U6DF#z)w#aysV4Zx2<4rHM8=ZCj7~ zo@}_Y*iYf4MeBc?Q7-t1o&0_A+?f(DD7xUeP-e#>&WqbC!5a*#(H#7~!8s_t1ezZA z9XaIP?f6inFE1oD0#CnOZT@Nw7~JcICjV|0M|nHdy~wM@jnLKoVwE+A#C^Eutc`Rq zFz$J%fy_r}EL1O65&R~?Wi3}q`*YcIH(XC@XR|KXan^MYhpSkuFZb|dHucQQaX)S= zB@1OX<$#GRR^HSbYN8jvn;A3hWN3U>o*z2Z*4#MFYO-EGYSWV?Wr|?~SFi}n&Jl*F z-0IC9`Wnq7!|4Wsd$Wc4NSW~Z>6rYsoxN%Ec}KwFu`JDT3PJe7&S_4XjJeJ;9Tdwi z#A}|@Y;<(V7roRTsek2~mGQWg6{{@&_4csZd|*{B7~L2Y+aK(6Ou<0DzUrvns zP2{ds02)cq)-lCgRFhCrmOZ=ib+|T6D9&5H9 z-o$9OApkRQOm-xsm&M@AVBmY`{wB5(j?SWz+kGW9Fc}rEF5ktdz`&(vrJNK_ltQ6@ zt0^t;!Zi7%m(ytf*+%Fkv=r{LF>>m-iusn+HubAhfQQR-_MUX|d|kzShwFj?f6I70 z89yeDBDaqfTHM7#3O+MVX#Cn%i&kR%o77xh&sQW^XrRjXCWP&FdF)z`ysS`O=&9|_ z8mBD5My5Csf+kv~x?s>vZYv7PN!QVMC=-y%rt;&^&IKqlT<@UvmI$5Sf8v(*9ZWp-3WTcUU^t#kc3QL(0(9aA10L0-< zo^qt=a{&Uv?*~UNq~KK0I}_#=E{}L0tdtQz4MC0S6)48tbKc#qBg}}br$B~lLg7>d zopcK|x?Y&W@(sduNujc>+GA>B&;#i1TH9?wd2HSe=}~U8zflIpu{{D+rxg ztg5+r17Sy-u>N6oijm9xVs`xuC`E$v`TmIGHzDGDaYFL9vE@S#(eGhm$|KBwzT|K1 zx(m3Vf=T-Mf}8Xkewq876$jpB_@tgTo+mbl%1wyY`9(8pL~qgW-q}wN8U>Bw2-t0@ z`xfH>ZqT^~CbkMb%1FK!;!F|>C_4w8_dokHL7!TlrR2w5M!GUUFF6d^U{&=VG?v5* zw_?f{V&%43*$$V_UacDOU@l#R#lX;WO@OH!h2wY(!f{rpuq z_oBst72oeXna)kFtoW*Cxbd={E#_%HCR0rTbkr%fz7*iV0{^~%oG+)paBFab7sVrV zT$>0?BU{=}x&1y)4QHDO)w$F@mHuojJiL)I3cpdy?G_M=g($lS|8(tQ%lSs*Ez`<} zSU}6p3-)5m$*5-!YK{nFTFV@iv$kMjz~j?diljK=w_xED6Zsea2pz@FW>UA9VZoIX zmyTeJ9;7hunASP5tt~5Ii_y&N0t0HM-p(q_hn>Oqeu^HA0&zc?)`4JYOeFC3xbYz^ zOP5fdK}T^&^OCi4!OHAmtgL$EL~*TC424ahhNoj=?wJ+IY3ua;=zJ{TEj?_4j}DA& zrdV5o4@Wv17X3QRtb8ZLK7-?WSe6<1b5K)PU%rHu;qPB!5JL)@wHPop@TPdLzfy~h zmGAG;7Yqyf)LT0?&cI?|;QNq0C<1{sbu+ic6ayV?nRY_@!X(rfgsGd6;r&m0e;iVF zTcz=*X4L$!Wv9L;PnzXhiFc11kHV{}->IuP^Y6#kk?ayb#l&el&vF=bG^wo4+bF_2 z?OezXYHSaH1j3IKYWODk=GneBhNnL+P}ih=QDb@lxE-7A0~aBvZ*(cUBYEgv4Jjpt zrC~-34Nv0N_q-YwBVlJEsL^G3^95=m7;wI-Ap>DI!s*A?kThMdC|4iFCzz@=%MQoa zsm(>2%f~76vi?0ahc)kMT(YM(@+W$3NZ(hqOmN4WxiIE;eRLIT`Wmyto7-j|Ko@Qr z%j@DGkXSZCx<}RslZCmMU#iKO64kSt3T$rVwy<)|1<>>FSiPMyoweYzTHn4E5;U$^ zoZmWsAmPN*rNTwjgQ9#Pv90ZGTZ4oXv6wG3j`z3K-8kYB@nuKr-c}64ih{bX9bJL( z&{+`%Isc(M6E^#B3PLf(<~KWmi^->34>wD4+?trLoi7=KrG{b*nC9LS;^xOh-^9JD z%IXv4yY`yzoyJ-;V)27rFMeBk*eV$O53H3*ADKl8x~NCo@ow$IC=Z8w@4+SgM_m(2@Kqz1Hx}KY9-Z z3sUl6kO-fz51fGby&QCFTy&7eBbEFmvOhz0qaq3mfdZlQoInX=K9^8t+ap&ZKVh{! zw;)*8ysYeVZ;;w3v;g88)|}P@K7c-ZR@GYU9r&yoemU&Rugue;qrIm<+TM2ft1(nO z>^{c_Ao2ikiuXCSEwMwYwAclsZcF?oFLOxPB$^X|rP30N+M|q>~1Wd&8P2HMX@p=?1YZu4FukMd%Grnd;y6Ko>3c|P1a@sK==^{ z5vuJPYT7TA#~ePXBDE_#k0KL}uoEQHGIj5Qrul-vD|@K)-8ez6Y`5e<8lavecDM)Q ze6j!m%|-^-(kN@X;E?k6E*Xh}zxq`#5$`Q6;rTSEpEja@_`EmFBnXie+MUiC(W|1D z(A?FX5}9mlPDQXOc^K&UP+kQtOJ`#fZ$4vQw8UaLJ&0;TsCkCB>zfWe*OoBI*qp(2 z+L2r$ESq9ou1BwP7ylyv&6U*7mkw?=uQVQ5O9!`Gz_sU%;4twMpgWASe@_?H0O@3d z)vdAuC0`uN#$6@sFv0!h@L%J)0$+I`1=Zw|t=97&3!F!hUz(^< zkw-)2kt_(_`wpG38q>z+Do=uh60qjZ->B|AI!3o?*e!9h&g7igW2Q<80In&=C=lo@ z!9SW?p9+y$k_NVT5)BU6w5Sqrs7K+T;osj<@U@%IobzSk1BrRn{X<3m5UeWO;beyc zjQy_vp`Q*aOzCxK2@oc8oF}Bv64LK{)b#Y+Cw97z@UnXK(J`DHDgJ|K?ZXD|5DsMo zf=Hg{-h<%XD_f&YQ;W93go?sAN|`SPS;oUMM-&ZK!QT0m79LgziADG&ifVV4K*^ED z{?y%44gG>KbB;Dx?q5G$Xfe`Bp=rTFyr8Gx=TVMP4-EcP6GIo7;i+^pphyoueL%C&o+fvn0=8jWD{ENzf>G zU9@(CzIIm}=m)dkX|t-{}iS?sBLUoow7F~Gbl{PeLWaXbP zM$0m$qUb}D_lGRADNi@rT{#Y9<(Y6r4+pvHVTrNSP_I5!2|KLq{N1)-%F?4Bwu1(r zsT<}jwiSeVk|HGaug%nJhn|jcacK#e2Kjl!f`6A|MgS{CqXwfY;E1|R`NpxhmyPYpnM{E1U z%0L8USJk7rrhJhy)YZbKSh6a&?xhnE(f#JEj$x_cr!T0bW)!hK4F``7cl_gdGGB_< zAqh$WIXHvOET)D>SL9w&M>_5Ub4?GNxEDikLd!C$S?1OdTx8?6A%+~KtPl+Zh2ZqH zUV%o?YPNC*_i!RAz4GO{{YgA{c&CBHFt4_@*F7BAkSV?iMuoiDarIBLJ(+OehRl}; zTl>)%95k>T3=M{kiGNs4d}&t`hw4kZQFqAr&kx7bD4Xe2wH_V}RYh|;+5gPQ@>WN1 zo+pxG_&S>r+NGEJ7tDmvcRiyuj|T`e*68o|g@B|^?g!gRN$`{!@>=aX-M5=uO++W; zKI6;k{%b1At>pG3DAi6QVZLKrY8^ktEPs79BDObW*p?~`qcd;Rwi5+?JoMavDYeph zwneWXjHa&UzHhWwC#cuG)aiipx1BV3PE7olyTXz>1D$ZsvVH72N{NipU&4;~=-3dpDP@nxV65)KI-wR(L5a9}6& z7pcwP?i?Cl0!1zgl@+jSs2mAI?1ikB{h@&(Dli}UX9?}VX`&jwDgGNKHdmXr2E5?E z9Xr_hf7*Va=BqQCtuN4>_Ry;Ki4$T)0=A3%l7yg%;QbZApzM$RbhL>Ex@yCD%{XA^ z%T8ZN9+NcRkgQlh8bY(h- z%e2}>KQisWa5W_!4nLTNU+eLq2kdX2hw7ZYO4x+ts$L!UoL}Rd)rf4wENee9hLd2w zW3m|#Z^@4|xf^2B*N4Y*HWX2cAq3hg!7p`_2g8pZa{5cl-(D#=`^vXcYQnb&V;ik} zdMKLRzea{tDvdn3T>WFOwo&;^)a9^FjV6XUlUBs3lP*keVvh8k6Y;dVnjX0^{|A3S zfWM!{jc*v~!NtiY$;rbST)bFjXzEr{4x{U*Dl6Q|k#5xJ`NpsuKd5q*e7P*|WF+N`sKGXl!LdH)=N^7$oZx7 zmHHDovib-IQX1tp2YWZz5y;7r)onSlIxGho?>bI-z2G3|^x!pnt2hvYBHB1$zDZg; zseywjojne|og64r>A8A220anel#Z6;`?&atH=dM3KWeUOL}fXOo2UXwIg;2Ea3S;7 z)A-FC%Z0U+(B$GCRTkXK#mnqYhP5*}@9MG2>?jxR1cj{g<>H#v`Oz*VTqxbxT3y%2 z#nW|u8GbW(csi$S*%Uh-Vi#3v&5k1ev#X_gWCjm9(m=q2Aw?G);vx9WlryLI@DOsK zePX^o4?}rr=jRcB-9W+3Sv*L~Ck8xZCA8eDG39|`r#08}ppv!diShwA=BMDS%iBOif^Q~{fh9WlwNHTHZo?~Qudwv3Opsd^Wl&E#WD zZ`8R)VsB%%G!L~R-#dNV#&`cbK78j7*Z8Bw$0~Elv(qd27{ID$xLNUGUNvdMXLCM= zCTI9&>GLsf@p+O;^I^Mw9_wKz56LS&`N?PVWd6lNlU~J)L6$s}aR=!HFXo}T{?Ob) zq94-|<+*NCd3ZMT&&yCE|Kl$_6gP99y_X~Rx3>30zvIHez-C?y zD;M$>Y5TkGa*@@j@Ose&F2W|&$vK;F;Zp46KexXe{QjfLqqyae(of8CFjJ^PL^)P# z`YO|WiIf&p%RyDM*4`*b*wfD%zleR=Q|0`p<+!(vV*1N5e}9d`#@=$Q9q2K9wiXxp z*SDqm*>LedJfA=$Vn5c!5ae*NP54wSDy^<+2?mQ}oq}7Ck%5ucJCBF7cCH}E_P{TJe@9zQ2*V7Jh@#nzI zWeP!DP^?Bhor?ytdUwe8uLTUA<3Zxa#ii@~zYgNb@GlQxK_~U@61|_&)tfiAm5Z3S zkBTN1aIs3qt>tnl7gG56i5wr$*sA-Bi&3XvJXI&_#_=C+^5`@VUYDpD@npOZ9|m%h zN6k#*%lHHV%91HyCV<~(%>!O{NPJ8jPY@-E|JHwJgw7P==H)X}jID*};3^d4UKPSP zVTSSKTp@-;IkwFIB*Z1$(Y6^^0d)`4N#mAQfFz9zpX{r^27bVb7r_<1Ui*qlgf+f+7Y**qCHd ztRE`Eqm^Y-mxPFL$|8BDTd)Xsnkt8co)tmuWbZlFArU6m%*}h_DuVJ4jjJt=B8V-Q z(z7;-P)yN$CL&1F080^G4(FYjjKNNpEE<)&OUdvrFuX@YkUwY@s{O&yp3Q88CvSTL+DP-QU zKZ{4niBU+U-|Axc*|&YzWG+SqMYA0cVie%Ud<*?s_L^A+XDN|e2I)3@qzop^ ziHq&kN#4JA__-4!%5eUwEBCo(8KSf)g1iiyKabe9yR8(7O`Sgem8B@0Nf8*OIIza! z{3!WS%>SOZV9DtcbbEW2hL0>k@wM9WY;iHXy3EfrZWTl7ZYzorckjr~neU2_dgRo- zdfy^knvi{Ho^BB+)}(Df5e^bSPh1jH$9dom*00$iW z@39^f;Hmg>O2Uo;86R1I=)L>ri**Y?bs5nr^JV#XJ~pi3=Ra`I2UC@*0OUg@diL#b zdLF3if%$G|* zqjY>;zweatgAAxrZ8)o++mo~y=;>@$K-sdke zae<%*dUhuCjSUtZOvse^eI~B%q5@$iK3YyDTgY=%=g)s}Dmnu*6RbgxSxO zW9b+j*fGQXNjg&V`kwAdB=Wjz*w%yTXtfXJj6Ic(TEYG~q0iDmbyxlorX$xfNZu?j zT^4WBaX5=TO=V67o<`4TTPc@;ZsnJz1^d%c5YxyF<9LW%&qg{L1{g1@FVE<#Pl~B#o@L7@*kPI;!sVc z!;x`FtIV7c{_`R9>fZXD_K3x>-r+0uf4_&M!>hEuyuE|He&I3Jec^Eb?bDd<5`u$& zmn*5x4#cIgXWma669m86ndh$6hhWvkB_|uhLlF>}aLRm62;R4qX!MK@hSvRc1d3e; z_sgQFu52F+i3~Cn)Evf~k3T|-kJuSIxZJ$oImX#I(}Zq%eZWcMjZ%j=Z7inJ<>hCM zm+*`>SA=*OBggu&cG_iQ>0?vIE;cNkf=kzp6Ec|NzrXS~mX=91{EY8k zIlMZo(8u`n&?&7W{>F1%pDQ(7zHaQtKlW*iZ)AKNR!fP_$1s*l z+H|iW0ou>@oVc5mh~|!zM)!wF825e!f008nmio>mnPnod|95JFXP+uu}TVL^D$$NTEW~``CtojTxZNKKwgN+l}+~x z5R{(iFJ51WB7?CjcMmDTv`5RoovbN>G)*in2374fxKV-&t)B(vrlq+5^RHXJZyA0q z*y>yPnS&Q)&0(8obFm$wp3eCMU&I72cq7lp^bIdsx?YexJ*O;j!A$`wPP;EyxU|#5#JHnc{@tQb zjDmH#M}H=heXux>WL9E$+>4u)+b_l{rPukiE-`!x-G9n8iZS?b=g%9pVk8uflm(^7?9e?REi@2$qN_H99BZ>n)NZuV@^k{UeK+I!GtTMg zZO?YsKw4f8s)3Sp0yVOJ&l>38ZjJPRS%ao;1w)%FYLMx$>EPCy8c^EV{h(?PCqc)_?s1AxW zX1u;_9j?nIob9?;hrL~uvy_h4f$CBXT~-IGYNn-Lhul|7w#}SYhd3{a$f|=)e85?6 z%{nlqzqDUzQ-`S^A7(2(s>Au-q5aJt>TpZ{toF?5^$?ny7C*AC$A=vha;t~4-BI6* zPwF9UBYs{FuZn59@dfp;UB~|T^?f~V)!I;y0)}0Zpf^(*p!;i)rtX3UNa-r;23V6U zOZ#kttUtR!){okNp980SbuTE}6*F!UlX_k$c_am|~>{=tjuhc52-fooj zn>AvvZ&g8LKqEYj@}2T-G~%O9K&IN!Mm(n4I>$G{XyO$0XZ!}-SU`0WHK0vl(dZ@1 z8{j4_bT)v>8dr>HfWn8HTA!5~Fe5Yb<9%{o+GaMg0aL^(w>?Z6a8i|PKl4-r^rZ#m z285VX4aE%zolY?x4T#x(XhZvn2Gq7UPXDsK0jyX*g_}AJGF(c|w+=ZIvbq7bBkeV= z-)exO6lgWTVQICV>Dva-a{>ord9=%H^}-a8ZcC0 zS=bWto#~g2`}=>^WBg`OzkVuN7pk3SO+C8C-0L;@T8En~pG5~M>hLRR?xIoUb#PdG zJAFxU9bUatW2t1;;o`PkNwIOnjy^gjbrZX(zSg}aRj&@0S5TF>T4)ip#dNMkoX9`w z!n9hHEvFi#Y9M)W!|BQS8YIOSj7!q1!MVOu6}P&o;a}Z7+`XV0w_<ldoRY13`) zy{oEVy^M+gRS*>#vBSn!q1G-oo-JPmisjlTSB1uocPkAQtDtFVv#DC83h{DV^$w6@ zZ~CX|`yCQk3>rs5qy(PJwT)dPB(ge-1PdQcS4!Yk!b36FO5jr|t5a0U`VPg=+^|~B z<*gXfZR(2{_KG8;?S6`}BX>(r^;a=8rfpgBPO%afjRJ=LRjb4YH_E^&q4&_IU^qD* zBK*>4pj(Mn@7bT~*H=Q?j%#0uBhrS=O8nW^l>5__-0xGoF>Y_AY#*ycjSj`ARbpAh z2)XSIVsr@8RnHK-qn7aO!?D|9SznnL?*5l*L-EP7w5vp^y=|pt zZl$cQTM3CLRhg4u=Ba~QTwEo%9@O%6I?=0?UT&9Q+@BFAs+uI|e6{t!YOVy*Ht^>X zS^tCtLADOPdrc*HHN$pZ-4qFoZ;qPgLZmxE{gd=1h}~jITtNa+>4$NaDBkvH5`;MJ_~J?=)lD*OoCK>^eymODtwd^H$?DTX$#WFFt0IB6N&V5Pi4tgC z<{5fuNHG17ZvE!n68tsZd`B-@f(ojP$d(}LVt_|`zXTb1`Rk*Nt5CrWJErJZg*_p6 zVy~X4lJT-tFxYBwYMyTuI=5b8<`es!BPE)uz#dfl+{=#aPupz9x^Jz5w7qF@6>K&- zuS`>_LX1(~pY{fcET5IYCctxt=(+@9PgYed_m)7KCLNN1>b9D@RD$0z1zw&5Bw)TB zJGG4Hd++6s>!T_wW&JRf5bJ-K*cV!f+0sHyCA_;vOzPFFgtTn%ON^#Ba|3_F6!@oK39yZX%xXr_GhV~6MRo?vpymSj#80A1oxgQ5;;V;dh6RC zTy`y2f{X73fr`XWU5D%!Mv)Gm>1z9JL_QwAx*i<1=LBtq9gs`5$ll2!MvsobeR z)w^)-JH8cIElSw_{aOWX4{4oq(!T=hoX?IFUZ}v2XsW@rLe@uJfiq#M3OkfVkebKe z3W%K=2WP#mfSx0@(^SAy+8A2_x#FJAi3vkl4_0Bhvf0=B|_gn5G0M+ekbX|aXTW;hPyb!>Z?=O1QB#`;L5L+lZ zo#6ie^!*9ZVRHZL$2CGc3qR<8z)lFi*7HhvZbJNB;qh5?RftYM>W?ZyyiIH{)8+}0 z`7-=l(JLX$oKBESLK!XJNJRR;4NZ2XD6P5n@O7NY8SK5b{*}+8rS- zKl@m9>>PPMB1+V|TZr#}C`S{@{9B0Ek1N&RstTd7qB7fItPq^|t4ri23o%C8a3MtU zd8$)e2pcI8OXfM;Q^CMWh#M5mdPE3IDN!bb;?ZB@s{(~!`DY(!OB3S7E$@nVWZo3Z zUf&>u(bUp&N4v?mH43`C23LTJQfj?I+?6Z%`k`L{CP!LJIaORN&{J@A>zK6Z>p) z{}C~y0)@|`Os&ZA_s1`dCn#0m>cE*cY;s?(l8Ta5rw|_u)rcyDP)dsPh{zIRKlL}g zP%`hvHp5mjzhjlAi)dGbh+O*B#4$vOn)?*dCWKnzB<7@8a$UNi3y~AC_ikW>5ChL| zj9+w@*v;El{a4Ajt)-0?LS+59E!V$|=;d;7-gP2Zyc9+ZwHD(2^a~{P2xa|DLK*%S zBGK){#R4-ST3C{0ZiZxiNmMwlE5u}J0Yr$OR6Cin5VMsi210}I%v&^Kx&T(|?|W zcsC@C3ymFXX2tB}VsD-6u1UYjW&g`4$M>yk_Q*{t$5QHV3XeFDwk<5?AY}^GSXzd| z(doY(Zor+l+|Sl zG3~c*b=;srS$u?W)Zb9`Ok&pEUuNw|smX9~-i#i`o z$_FFFvt{Jqe59ww{Kd<9kf6q6UJS!#+RA&8H zxt)n&f&1R}o@K(xib7aSJawcRf0?p+6*>Nv_zSaGkP8$&zOx%J&Flt!Ez@B5Vns+;)z2No2TGH?8R%aYYmSlGTm&f1L} z+kW-1z1YOU+~n4CaqTQTr%6tU`dFy?!~gM72{`2Ya>&dXfPrdTdcHOwnp(&oy9^k` zPYBw+0r1w;-m}92kp7+PJa9}3r~oOwnh8)<1y&9I?|)EIdQ^dpx}YTb^Wki0N4%VM zZ#)~nH))x%XR<;4TOm!8jq=OWj@FZPXnVGEm#Z-w=F)-}Ss!VkmyPRGyVia-yf40n zryCm~cbf-$U1YW<#_$iM6i)=J)v_!0UQ4VzKby$b*Bt$QE-*rM>iVmzfGN?Z$2O_~8}nw!-aP?G>FH!hUjtelB;#YB z0!sNSCSLOdGUw%&t%;-BJKd9|a)8?VkF0;S0$R6(nWiI{IHmI1p?x9~w|TbRzveSh zZPKsXJsWP#6*gt1QZ639Tqlyj@)tJ^HB4@f??;|>d-k{cdP=V>=?qthyuw0hM|9f$ODqU{ zET+d@V4-to)s3I$Sol6d=k9O=7FI)cr0^yLd-~g=HAaf3C)Yl9~sGw;Rc+f!KJO4sJ{C$exiYuW_e@zlID2WD=NVd36khtcQ8uwcAH z_gu~>79LF=J<(K}g;>7#umQtTJeBRGt@jTaI*Dyx|M~oThIQe z*ug^TZ{Mw_srj$?nKwm3lLh8~S1U8A_jEF5m`Ugf79G9jbsBx6BzaNTZ4efL4ebxRKn4idk zNu&HfC$P|dV5~^QWnuKbE#AgyEIfD^zRxa)g`JK1>C1{)7!g&RM5JlUFOg=${p5l${vU%QA0K?Evj+%IvX#C1>N~-!G`h3 z1N*{k*;s6syD7w-4Lt#)t}d93nEGec2jbZ<->!DKjK{`^NaH5^0yflGwhG7V*{JbZ znzQ5^8%2jy%l-}H;Ku3-%k1$S9KUIK=Ji|-@~*FqTBgiF&GNomL7O>PQg&41&mIn3 zhUfj2I?h2s@%Odq=Q-G@xL$kTO%8M!VeAW*9Bg=ego?Zzn8!z{8M$$AE~$xBv6r~mSg7mz^fng@ zZf)*Mv*zNP^i_Xj2QJR8YSq2(#YN%)hE7vB)sLMX6*9SC%s=_=b2=BNi&vD$lyhOF zYLpk)N?orf@$_CV7d9^>70gHT5F@;u>NS&x1AB^UzbNwHaalQI$7UXO=?$A1u#boC z1NlZ$dOVP8iiZr0d3ZQ)+$7%zJcORM2ol-y5SJwNCDnrm?{y*hR$)BI{A-aMoye4J@* zKA^71M+$$rcFI~lV*8m#KdAEI*cRwqyqAyPY{QTUP7Y!5_^4p;`YUqy*z|Vnu%i`xSe_5qqws|f!!#T3 z%Rl%->r{YM*?V=r$_Q|a1kES21lW~dDyms3z@Eel-!j(;P|g(%j8hjt?a&x`r^5m~ zIlJtl?pXmme<}zJuM1FodHj7JO9581%dIEa3lQ1&x;D~FfcLjoWtx2!VBZK5VgTy* zm1>&$*#anJC(piJEkNJaNX@rh0$3mL+|BzZK!mMKW&3y`s?s0cm@;38qnCfFE?X%? zl1pF1QdJ?07mZ?1Jt#yZ6;*5Xg;@Tv?CRrdLNw+qq*9;|_oqGiw(YeLop=AnXnP9r zQkRYlLVSFlzb7tHh_~mW82^MqXtk{i9w-u`Xr6&=M1v5D601f{|3>}4^HcPKe?r`3 z9J^mKMug~&n6(RKMc6s#7^6{6ghjhIjgVU*!qF=R)5u5C*H1qmbg&z=M z+SKctM8`xZunG%0rY}O>7sbj`Mj|xbHN8`GRfM;NW?OS_iLmLU>cy=OL|9R-c~b7N z2)B-UPqVfW!N@&gz|dBN|3V&35ZQ|meB?z`yt4>BB5lj1uGDczj;hjo5fXom{K57V zVfm-8ZtY$ooc0<2F49MY0PpgBGySOR!;U5`_7|bh>Cf(Jsx@1>^XUEn5o%}{K(*Pw zQyE97w&_2U8^5XlS1eyse2Hqu?6%(j`-3uK#gmrP4B4^cM;Bn{`ZRGCIUnCah-q~_r2*| zf({oEKCalec`em?otQ+03=vL>6R>C~uTbOvv46!Xs$DHBH|Z(Wet&(~Y!P+-tLJCG zNmBi6SI|wE?)ty$geN~)7(0sK-ZA=N1T}9nLe44FIsr9p~bt~1C5T`g}?Up|bJ`*~T2_Qvf=aWQ$_Eipf#&ZQQ%@rML z8{p%_^!VIiReW5X%2h2+|Kft*n?IJSMtmIeEF6A+KOdp@{&+54&BvvU zIXg{e@v-Zkc9Q-`K1OMM`MKmP51ggabE~U(sL}9d1!nPZeg2{`u1p@D&6kqTh~Z&n zV)914P#zY)-ZJ5YKM!-ZT3pNbqK-HGv}*9A;;Yu2Q0EUktXPE+#xk|F_9$-BBK*-p?4gxPb?y z^E2v>Pv;HoKQ3e=wTAJ8T%3zDJo@B47rFGdzRZOJJ?ynytTK1~l{vrx=jT$rH*606 zo~2LZ;LHs_q3%u&*nwGob^qA-5as@9Ng^8xEe02F-C*Obr^UhP3T#Y~+t+lQ!W9<% z0qPGOSxA{v8&jiB;pnns(OJKlc=W`8=}7T~d$n0l9ZoYLx=CjY=1{%>{IV)`vU^go zZ(gEz>iJYKUD(zaic@gDDx~e;ffO9yH1C7FFd6;Y1#b5>l5y4ewtsI{5&}EZmdolT z;WqOY#b^?-Fi>q$iftlJh!=b!(l|T9FI6QVfezQs2`G%Hp4@gM0l%cuO#0>~Af(eF z^XPX5)+&swJe|jY$)@3q6UhwVoO!!ZBm={j?s}I&wb$n*tZj*7;IrJgQq@ETJPw^+ z=99!g`+lGAGpW{RQt_%!3-Y(3=eW92dWnbC!YElHJoZ4lKI{#QOWq&RERA1?7?c1LGN} zT{6zQx+fkEh2bBZs^U?1CtrCpHy$r3)ZQE%kDn>eY8bZhL;EuxGTbP)ormJ#xGmh5 ztcgedk5Y-^sqy$OoHuq$PaM7`TClE`#3A4S9eLuwT`)^y`ujK}o0F?}5QiS8RogO7 z$ANyE`rG5sJbTMz_eF6qlUcpygLE9WE=jrepd%I+_OoUh<;TKr&iekViLp3aA>$kC z8;fHKTl4qX#-c+#X3pU|v8c?utWj|;78J>;l|B>;>EVW7O18%$qVa8;$?8~aJ5?E3 zvN#qON2v@~oE;10R;LPs$+1xP?v-*F8;eiNEqvAEY?6-fGGQK3<~@Y4D? zcpb}~=YBU1zB}n190wUH3T+r459tWu=Xq!2A>QT*@fZ`GlXYntwGP@Jv)0~WKy~Hr zH`V0~JV?-bJzOmTbGcblHhoSQ!pn(xzW>jJBX)@h)TfDMBKn8@rz<1XkLN(Xo}Ay-zjjNK=Iz$F*@_cKV)Iz znhTSDKBjobG3n4qipMnG-?eZJb!_seg%)9^c&M{EHe-75~ESkS-=J^fVaw6fuz% zzzAtiVnUo|y_irmjgqObVxrM=CzX&rmtnc78}^8gi*@I*;|D%_0Z!+$?Z#c~Q2p4pfRO9~a7YfHfe7I&VyXA0t@ zKX1{{O2LRRXVRDwDY*18nTlx1xGN5@$-tg`?~8MjaY}oy^s&MuEZbjwMf!CT;!j=t zl&_Hlxr-T#T1O^fS7%G>YhEJ4C%e>7eV&L3chd{s97se&-4P1uB%;q@p-Na?0w!IW z^~g6W0hz6HuG&0HKyCa2{*}`S5I^pw1T@de-P$%Y0Y+kA$v{`FW4&ez1Ag<(AKWiy zVEyXeT+=iL!e-29Sk7jE0*6k$Q4H)96DbCC7A+30J;{Jl;!pRvQy92&e)`x?)Ow!y z@zV7C{qe|^N-xRDj6+1zFxKp?aric>^zN+pvFM*p@6Z^mjo)$HPCf?4*-E1h9*#yz z(2cUgH=;0mv{$&bbtHJytR>h)4CRSW;8)JqT~-zb<`x^=?6=H1{JJYkzULx>5*Pxi?4u%fwJ}LM#M?5{b)~OLg_bh-kBo$`M`|Q4ELt zuzz7h`i@aY+?a3@5`6o7tgufV>>U%Pp{9fz$U+w4^ayD^7C}GEt&mA4_ z8Z2Xpxxy{chFx)F>WD?|suSbM->;`*Rchl&Pln^LwXqDszN}}2QaQ)mAVzNO=raw59oH3WDQaniUvzOQZE@qOF zU0X^sZJC7LE$LlMQu_9t!#yn)=}BL*>{%#_h~dl#HkoB9^L&C1oBUGWaWX4_O;Tui zuZvBdUo?}7T+JbmG`CxF$EcP971F_`TvG9CYwKqnE_t*1K#7G4 zmzX~2aFdsy{vSQ^NfC!bY-T=P6n&3FB-ZS8`76&M4UbpC8b zk@f(E;T}~9M4|ar%5;4OiH=j4JH0TD4CP0X;re)OR$w&o*_%1{;>ajsMu$uN2(sai z@}?7)!%0J;LSyWt5OT6J<3CP9Ad%}ayCpd5N2ZC1qc{2b_<2FhD>u?Z)0;6)WW~Wl zXC(H&AbBD0%$%+7l5sx{mOs;8N!m52NIPXLb2gOsS~p) z49Aik?lz47geMAV0bj>_hQKK5(Fe&0yijmZTj3W04_Qa27bhc;V%p5sSP_LOpQET5 ziN+RXV)}MT%>U>2zcOW^Z*1Z~hJ8HXQ4x>U2)6RPJqgee4={0vM4(V{UWeI8Z7wb-16%g`}7e@}OWoI^j?@ zAHKU5h{CD_Somtq*KyrKn9Pox<~2MGkKn3&Vrn{=_bTFbmtobv^`fdJJ z^(^SsuP!B8*)TnM()_ey4s5hGIh+Z}!JmuQ`74*?qF3=x$tmw#q{ybdxIHxw`A?4z zOnjDyG@k5n!Ph*jRC<)Ed^{g>c^g~5F!E9SB!=%jxd6BBc*^`SD!^boE5MuJgOz&y z1sFcDF0FKP;gIf82wTH92Uq(S!r)cqw$O}1^q%eFP46fi;xR>#GS6e5pIU^I`N{QD z<`kiKhw$#dc||Z26ZazgilPa75e`R7QBa`>@fN+=?$rMe4p?hEn_Yx?EBrY-WvSzS z*_*|aiZJPb_jC2JMQ|8JN1h_|&!`Gx^%WvqGwWc**FxmId3Ly|sSqwaZc}|(A#8%# zUbUIjxTO1Qn^B1Q*~_bYBMM;^?X0xKr*H^27h=WAWm8%#sOQk0802JJ2&2T}Jr7S5 zLMX>@h*B>^?WyH;n^zTL(*m;``Pqd~-ZqkHE?Ee#tu7z;bQj?DJViU#(gIW)-#mAZ zT>!|eI{iJQ025!y-j;PLz=+J|ijI2)*k|_c#FMiHP}BC-YS>c%zyAiF&Rtai?&+mx zHp>=Zg{vS^nkv`?-1hbfY^jA-u8uC6Lf`U_}Bdzmc!^va5 zxttFUEmIw$-rw^xv-LLRqkDR^eCWb_h++Ded{}MI3p)BE4@bggK1ry|11~hp%_tU$gYzdRSymt9^d!^y>-U(#!LhU8-Y*Jad-&&8sGu^)ZSbBA=G zTr6B!QN4E$pnoq(;1n#K!>e& znM1fd6W=AQviuKZB9B7x@ryGt?!x3V$Ny&F+P9NtQ3V+osj~T1)yE9DtegE#(jo)v zuiwBzygw1p{|G-m1w7;BD+p%3Z{=n|Qok1)( zU8f^83!dW)x5oA|L9fPPflQRDCYHn;Vj{7eHlmn#v%zpg%UK|L^m~cr!c>$w9-Vkq zB^4L%XslB8O@Z%&?PEsCrogYI-O$uI89T%RUosjMLR;?nCSis^gIc*1PpQmS5N0P1 z@x?^6Nqo0gn3stAzg4uK6eJ)thPQT`QvwbpywG(&nE=Nx=clAACtxRU!=uTg6Ax@TNTAp_UbcOS~*FffSc7}!O_*9Qz_oR0I1+r@wZ zYrs-Ul7Y%G8Kcz`H45p96X#})VnYi zXNJ}8eDN*@a~59JlphfTvD|wp8XEp4{V&p@FyYob%YwyG@UDpK(tZ?)GRyCecv&a+qi{Qe0Pi7r-hp}@PGk%89cFsMFzJ?BVW2)>=#drIZ?$05HV7}vzY zQQ(li7l3utD$aHA$N0R%4HK^Wp`LAJuXM&2O5fUSO3wJ;x2foQkeN45hy?&IL>{IC zyC)`(ZJv4Iq6a*`KD_>M@B1M>>yDAD1JBq+yCFs3w%C}s4f&vML-EWFvn9Xl2=(0X z$3}Upd#fAVzAXrznc|MM1xpvX6~2e!hUEDR*Lp&MI@(FPuU;7XJ?P!4)yF z^+w~v*_jS+y?_s&Pb{D13Cr(wT%FDCQ2(&#)apO)5VgmG`}w%jP~F381goLl5g}2A#cQ8&Huh!b+1QozmQMF zGWc)-v0K_9le$tse3sLKjezW=*nXIufJ`r3NHISF;S{{vBy1CqbxpUp3uXz))QxHt z9(#pEOYgPL{Ch$&m=}fQn89l1$WkGhoHx^2Q(8oh*n8ROtrwBxboB>IE{F)di{Ckm z$XvcZT-YLVrs4bnrEU=!)XUO{aTaT}&z>~0NGvd?kue^|Bkp*ok@-vZ%Vwsf5h@r= z+VdlgIMcLxb~1E}a}*_11!2noiXB z&=Db>%ohWa46Y8BzB4Dxr(e-bKY8HBZgF4V~&w=x^vn_SHxGiW$| zD1(gpxA0=dq734-MXA8OiMo#=Exf0bf!+n{j&DdOgZer(u6^~>PgCRP{hOohlPDs4 z&(fJ)L~Lfv)cWtbkZko}n(4+1$kx1?xVUaU8Ok$6VbqHlJHjI+bXq;eCF2+K1WOD# zWNzKOxE~kUL~@yC?6eCkA`UltOfud|&PwuqDsfDs0cSEv>ezA9b5|mX-r>;MJcU8- z`?ILb6ib4`0^44EiYA-a4gZ>G5lJL^wmd2e{zPm{Ua8D73?ZYR-IQ6qCU9t8dmj(N>{M&MEfmTf1$tLkhM~SLxI#@i z9JSJi6mGBi1R2>y4|UZ)BhYZ;sDKp_7`-<)Erl6@Kv!#TzoU_`YNG*5B-oIix%x#E zOe5B>TC{}9Q-AivY6+qt4jY$ZFk7xvu3&5|DDs(jE;1H_>md%mENEptZV1oB|9}1* z)R!2@xqnW2*y{wm{m!d;wIUHI>t-!mMdkIS=N`DG7$?CYX4b%X32|9i15jr#S;TEw(R#GY9B`=;l({bEV+><~Ssr`98ZBjA`a(I_kJ~5T}$tCpL`~Z1BjPtFz zoJr=ijI~V;qw)n|>c(DS6H9m9xT5JCVtl&rgmMIj*yT?+`g=8(NcjBhK2ODeLoxB? zlAmS9Vcab|l1R&!Mm%zD99;>(BimGa8Z&P5NRP9}n>N;|R+ycdv_7xo=fX9!6AuK((5@&sh&I=02?-s&pC|}P7KQo^R#17VcClaDN+EeL_L#?IWg)4tl6W#+UPySa`92oY zh2)dvj;#;>6B63psHO5*(z2v8rkMhw&8i(a@uPq!icb`f^?Xh9QJMlW+FHeK@pJ(h z;t3>FzvY4XJ1U=!+oSBfpHEuNGgQy_^T_SzkCmNQP!n9YhClTK#6T1kK|(}|f*_$2 zr1uVj^cs2#y-QVkM?|EA-aFDEl!#PmMtZNIh88-6^58(%hInP@5E3vvYdExip8 zL3U~W_OWNIr(r6lG)wxhPeGYm^<9508%t8tDg1gjJy9|$wO3Z9R)GO>Mfp39oV4q` zjziR_59HD1PiVaOaT zdaXwt0pPFTbSsc`8XTDX(R8uNygFmBX|cbRR&e{`(rb%yEw(J&HU7-uG*}m+@K9V| zEJGlu10lsT_J~uz=1n0u3_~`vbo;LklGal3--UXhn12q_UHbmUo#+ZiirWJfr`a)< z7!G&-^drFsuO|s?;d(geeCAl?5E{#`Qn$1hzvPSwrJg~S5{grQ7W0WYECoxZlhmgoe~sE zeai*pjis5XA^FfF$%dB0Y{mk8b?Sb(8VLK?19aPWV=l?`>8Hkf*Gm6(bib2(s4P#n z!ul;yBsnm~o4Lk6AWCpM&P(-XS&OZ?8~bHKB$IcMo4uE!;q z=@H?BNlcMV!@4PME*MKAw;^Tj;QP=^L(~|Wd1?C*O82oIVBdCrLG6KA^y?)e+Vqzf z5+jnQmIWLUZ2~mjmE(&aK{RUy}kO-pHJ~LK<~!PgB%zM$c2B=_F#egz{pkqMlM^hH_U$&R!dhC(hcV<073_V zi)h};&aTfj3(v+nB=NXK@GAE22gCf6eQA-Yp3dGv-|@~8+4YfxG#^^3ZS_Zmcl4cF ztXc)8J`wLTJG#WvsPU|&m^nM&Bb&AQp;G|OZt}{BcjY;`&9VlHY&wY_EH@{OnA708 zY{H*-ePGm#tJJ&_Xr^e9@;Is^xCrc>;%!2vp509RQ#DkMa-bxqJ}#o+yo}tKmfR;E zw7>;=&clDYMycFP*!@gN8M>)C0{syCIdJT0Aad!@E59328s4g#Qr7E^R5L7iVJ0}E z9xfrQM}mwh+@|(Wo_+e&!+@j z9f@u31vY%ZQA?`mQV9ni3`mFtw=sGYJF@VpjCrJj-k-~8X9M_N-2h3{4|SBtTB8&F zIabt|48-!O9WQA$P;z(9cyfs^7!gkw7+Hwz_Y=5&qE&RhMn0~wk@Gi*IKO#HQvz>ygX`uqS$GLaB5dD!~W(&2v+#;RjtEjT$ASBXD5G)=cR z17xwm^h?+ZF5#``UA^;_;qsz(|4}6!@g+A?!e_C_+cQmGPR-+FwBhRsr zV=-dFq~j+}A4%4e_pfAavZW%KWbNOPL>CKOwUMi_AXk1HgOw~gh^0n*o?Gnq70>US z#*TzXxy;YjuN4fMw9c6d9x@sF`t2pV#7SpC!lO_!BOD_=wM4RFNec(kIQD16-yEM? z@7|+C`u%!E&3}(Bj-*nT8@y%=4vCKf{UlpZbu|<`r zgRc#3VpPjsTJ>IvP87s0I$WOe0r1;r#xXQ96&Jf2isCxK9KIj!?)_fhUh{t?wHW!0 z;j#h{+N4NPoFJ&MD)T(Oi2Y$~ih5kfiB6m=QduJJ?!BJ6BmK_@(NK~8EKRd`>iatM zo^~*wqT&aOVxyrd<7!2r%3Cz8j11N_6NZ16@UIro>)V>FrN_{qQmOva>_%EW%c~#BbXpZ z%K{D?EQeTp8O(WqMwiqIL&f5{)*gVz5q+oe7O<8Ad@r$26Wa~|Y}(bfykVE}Fl67P zfrz=L*|G6^3dXbfj6FzO+f#JtMqUUV^Pkq|b_YQ;Z92&lO{Ul34%9{y=r-nJ^2f*4 zk0>4FNh2pjc-q0gvqm!u6Fkv+J)`;HBIQ?f9rfVKI*|^$a0&nYjBu6RN69XVUQ0&n z_Hy$D;Pc~Ph6p>biDyijWHaAD&&19-^dbj#TX3v4 zd#^^%=5;&f8n(2>p_z~X`o;4S5KZ8pF{UoBU|uAvM=q#rFRst~w2QCbVSxyGWt7;9R)e>(!-4r>}-Q-XS*zQD8Tw@Bz*0P8%= z!Y^1>*P8HgiwTW9+Qlc7FO{Z?taC-q}y2fL9ZB$)l=I+W&$~5(2-nD2SJca=Z z=T5By7lEzWYQIXTz}||Zco29q5hS#dVNBwvUywC0w)r#l{kFO5gh%#(%e|xzg3gYE zr!KyhLTa2=28A}ty(V*CvQJ5qM0f)mJ5LqTd)upaBMh&3v5LMzU6vvhyJ#9cTpOyu z|53OGYE+9&Ykqf$6bx<0+R81UK>f&0!h51~FWD~}xjHRv}*0%_0%QJ0Wkb zmnp~FXJrE^CL=@Za#S-KziLwzW4kV$m6?6mw;qNHQmEk$P7q!h&TM@N!shd&xD8j$ zR_bHD;ur&gWf;&euA04xZsc=(G9Ag8o~O8jNizZO z0}KJbE53HqBZ(`YH$M21=9LV87!PB!k*gJlHNGqc2cPKdrtr%gUJc&cO;Ms+7=+W6 z19luc74w=b#dIAwp-qp^hN{VtnJ+{MDO2d;QhHCVQzIbglyh{JT#jI+!O@n<3pM8XC zr)2+eGvs&e;VL>mvx0v&`diGq;>RPJywMbn43 zLEv?+$!5zTHP7o^D%$xN^5m?Bxkh-HR6_Z5T=dZSCS&I}O*nBD1dzEHv$~8AB)M`3 z3K*N@sbWR^=vY@QS5bU|De%zr7v(j@%}_@^9(WxghUKyk(zQa{1bHLBL+NdlR=R98 z5KD8=jkSZ%vJuxIg|ZlR)Au|@6yznLh)QPO6&)R?9?~k=d{w;qD|{2h(N`zf3N^18 zn!~nB@Y0QJTGj?X4SIpibq=wR%lS0==?9d*MB(X+FQU^o*scrWA6Z0O`6awd6W;*~ ztbtg12$W)MwW4O#0R=tjLwTDgVX7}Xe2(-^yqmYy&(+60bhnODczPOvGFaPnW0L)} z+HLM=?7>Bjbd;?dJ3n-NM&{p1;NGHA{i9iu0lSW>o0G-pI2y9;QaiQ3B zwUS{IEYjgj;2|iAm2=q*l=PhK$D5X}Zf_-`iCK>>pECl>y496wAS3$vsF+r9UW08P z%+mXGKKHX5puajbptYS_I^=Jd_47E?me52GdnfPh^Qyaf154N2sk?jemgiy$rdj#_ zJLB#DQvd7!drUZ_p(>#y1ADKa3{zFphHyf-dH?xDkXZ@!U*q3hLQhVpcid1u0SG6j cz`J*x0{@T@6bWsa4-#@Rgzo>f{^$Px0IOcj)&Kwi diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/FORECAST.index deleted file mode 100644 index fe66f53d31a0c8377fdacd63f3cb7d41b4fa0fd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZvcKWJ1z5XQ$w1+|Hdih^LF=y`Z&V*XS~GfQ_q%WA`(}5GojE#2M2GLLZDFAscu(Q2 zi*mA3l>Kgho*v_&m;5VHI8JmC>r<@fu|68F-QSoNqX*NvoJ{YH27_*Id0GDz7Fiq5 z9ir=4zAq4+z&aR~6J_WE1EPEmD=VMIT0?Ntw=nz47|{&CC9Dj_R_nVJxSk4zy@<71 z74C?o*E#14Cqeompf4;gisT~PG%j-e6gHHng=4x*DSk-M4)ZG&; zV3#GWGsdWe*clk>Y|S9w8E@CN&yRU$lB`!7=W0!|m9`Zw8>4MSi%7N=?5=TY(Q$p% zqc=GhC)GGe;OZv<{iI~1*c-kw{memjQH>sMq^g3%GtqWYw2%3F0R#4!x`>GkOH1Ue zF{;%Js!D?jD+aX&)oe(!`9nZ&lmB2B3xdfHPQ0{$;lS|4@);LQGhWxjP^8(6?}4{* zuXDSzr0L8K1@t}0jS+8_)GHmBpr+$TlEB%oTrjp*m#)3a)U-X>F>xk#c-|VPRpU$w zHxpRohpp;NVrRG;TbJnS9|679IecYtkISv@Elnou%LNsHT*1p(OEO1x|111}hwE#P fVi@&RjGh~$hNBTQnV5NF{%6Ee`7NL~!r%M@RVfQX diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_24/PARAMETER.data_0 deleted file mode 100644 index 41ecb4c3a6138649a9e47c0dd9c53bbe9a0e8f2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 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 qnQgH0P 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

MH!#~H`4W}IH58=obzwSYKLZ0WWxn5lJCRO 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 CmY0nH diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_3/FORECAST.index deleted file mode 100644 index ecdfc3d830e06ebfbc923858947e0a9fd7804f33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/FORECAST.index deleted file mode 100644 index ca341105468001ee48035d6c53e9d78a2c673784..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZ{kKTH%+5XK*kBp3^@z^H|>0r9+edZ1jz-&-!??dCkW!s4{k#?FdnV`5@QMQCWC zqoSj-Frl)eqNB32vNIGUes5;KH~VhGUN*D0_q&<-=FdyNO}R1W+~wZv7L0q0`v&gz zAnVtg?k%qT0lwqP@qQZiJ?uCvklseYxObjV<_@f9)Xgg0xTX-18;`!}F27nIrk%}U zn)QZjop!t4SX^Z6tKv@!&OO3o0(%p7CF`~3Yxt1+TW|<^ACEr1=LSjI+i0a(gWP$Q zlROcdQf?U%$@Q-2=7TYj+|;V(-Qvn&=|&Q4)L>7dX6;vw!i+&Z2kqw)hk;PSgg4P`D2!D*G#mZVHDe_{v| zlyYE`LuXsYupGkRj0{Y_%J@+I&g*s7LW$@^kgPGe(ej;{E2@jzk3WpIKmVkq`}soK zzYVL-^#BYdxu`mq*6P5A)_yjOt@~ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/PARAMETER.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/PARAMETER.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/STATIC.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/STATIC.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/STATIC.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/STATIC.index deleted file mode 100644 index 4377afdcd79e9bcdb445912d8aa2a302b61f9750..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|`rkT_X%g!2tj;Y683f diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/STATIC.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_4/STATIC.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/ANALYZED.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/ANALYZED.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/ANALYZED.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/ANALYZED.index deleted file mode 100644 index 4377afdcd79e9bcdb445912d8aa2a302b61f9750..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|`rkT_X%g!2tj;Y683f diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/ANALYZED.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/ANALYZED.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/FORECAST.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/FORECAST.data_0 deleted file mode 100644 index fbe0a4b97a8e892f1ed9a005cd1751d127ccb7f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103296 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 z zj1-nA*JV+lr20S1?Ai0~8#+Od@oTkNGHgMr*~4!$JK}e6XAyFIn&HNZgZ9rZK*&om z5=7M0RY`GFg5mSRL4iJUv4{wq{T1~fOGO1ZCQ0<(KTt=Yy&K9y{|qkvTQl@#c#vsA z1^aC^o(YMWZ2I<43Sx&m#%8HwHc&Ktwr+72E4_H9`rDEf)q%|Q_&GMiu)Fi=ZkA`IAbj2MuZI4y@;v!gtC47_J8j zr{wdtuy-6PK-Xrk!f-6okG%8|xTM)qLI66lVKcDvda9o8+D7HB|ua&h9(42Y=I#ZC&BFeOY^3(LcOxwA=48F(p` zN=~)IHeE|pPve_ZT#yB|!?g?s59h2-86xo(*HG2LRUxi6sH>$JJ>6kJRu;h_4&wV~ z`7;a!Y9%m)i>zE8Pqj?WuVtpvvr|dzE^uh+w5ASi9?rbgf*pH$Y}3uX>T-FmqOQdD zsKvEk(xEEDPC4y$9#oaI980bllq_v%#X*k#pi%gy9;;`1=TA=Y)O@O@C^4l+ETLF} zbI-cJGt&FAr-CGi>q~n}bc+a2OnYXqgFh~KosA|sHzkPsO&L3Dc2Cse>o(dN&MVqV zsKx#XkNAzt_Vf_`z;y7K3KI_P+wGD_i(fP}rW84X3p))==)T@LKO2^Ko3xQAj=L*( zsq|KTG2>ssgutY@y_n%8G+SNZYIyIXc#3Phx%t(Shl5grzLPcmEadW46fztiJ(L235dV0 z6p+AJw5vtZz*0Sdbn6c!`2i`mdAqmHRC85w(*=yCf<$QSz>dn8UWFB@u3b17a$MfL zr|p70WOijm_pF}|Yyy+Kk-_sa9HVnOXa|U!3K|{qCz~xP%CSXr&D_`D_gI6VcbtG6 zO6Hk-Du3T!0I_3*nQ^@WB;JW$`5P3#Lyt=iAH6aop+Mk&^(<#0AJLC!M~&X9I}j?I znxE+%Z++4+i2 z%InOZoB*mQC8>E+0efp&>z3!Tz3YlQ{&z|MU6Z>_uYhoY(L{uvmOt83Urh%0Vw!N^ ziets+5L)VAeOo)Ph(W(LTtWrBVkAFn{nVi!Fh&c_LZyu1V~T8>61g@#nH$&gLg}8$ zC3CTZ^@!>oV;#z#4jUI=@vw<$*O4Cp9x7MSZcWfer0~IKY-W*rg4-p~kIIecL+b+6 zY>Aslae4R=Rf9&mRh1E?L)p$t{nlyA0;nFp?Eq#)e5#Ggws$8AN3X6#eyyOXAJ_J> z1Z~CdpN?jraBC@q+zOt}#&R-#1l)*)G5EV8dE2~qJl>lUtmKMa%GptNXNrS4!lW_q z`#*=zy=v6hN+g4#1lnV*e!DLB2a&$Z6=PaT?5|?GG@6Odj!>i?*_AnRnDs;kvj8Rw zMpk1cyeW<$2xitrUL=@ILYpW6Z1?A5?#MtrrT2K3<6d`X*+7b<>?Z7)*;NGwicft__K_5YncdFPWLWS} z!nnyeUt%C=x{^;l#WX+^bzMtMH2!u{??gl8Etl{?M^}UxB;6k(kDTaJO2buY8er~F zsYOqIdSR7sbP873)|N$p#apPT=w8s(5ET3wSdgEPAqmC>^ZZ-3apPb&BQ+uULoH#s%%YR}NW5?h z#FT$a(bH_;lZ;jrsz24B61H2I&b)@s;Zex3{Q>^9kDzgqct3A~`%O!{Th^q0=|KFL z+RpS!NDf*T1gx(j0W~V-c!Z7KfwTHUPyq^h`dO7oK*F6JgO}L3+#wa88k{ z;1%RTj*JDebd2YcrtmWL=j*q~4yb9Ael2i|Au*?A527G;LSM#g{9O-FRmzRB;s0c> zas}G5+4-9cM{=kR_e#u2Q> zBBiZ-EMIbhEb-}B$qSybML3~OR-w!cz^{3I_4p{;^VxI9SLDhn^5t{dM>z6p+soS+ zx*@G5$;R{q<)eH94Zsd?%Zow-iH9viR17gfk8=(9G76?s=)v#$OF?LYk!CDu z4IL=3-ll=dbJ*kIVGG;9^V<3?JH7MvnycrvCv*%_OtInXM1=k=?j(U&@Dle|-S6S6 zul=enXY$?@myQgS{J1)+DSnk)bg+QPtpj=}`f9pY@e_+NMo^EBP_*6$bh3qp#m#)2j++;a(<=g%L?`?Ol|d4% zY205ehtY$qs=83iK5dU1Hp~hLLM9caI~}Vky&Xtg(^Qv4U>>wc6rF#z}uG_C|&k9R9wp=nKwh)oaMz z(87Fvg55TeC%eIO8C=zg4lGFCR$f>-gLow5?XVgy>4^JuKi<+ol{B2sbc7BZ)uiO% z@wechr92W&@z(ltJ$-aSu=>osEVic6n&qj(Lzgl#r)6K&CJqjA{lgG9o5d6zBi}!I z?<}@n{}HBwg$2js6TVb?Y>h~qj(z5BP5V-&{bAkG7t38dPZ;qn*S1%4%NPmY?i2@H zQ~RFvb+ZLAj7Zel-fXS;6QK2$zdd&S`||Nfe`j-eX!ylrN<#ha&NS$+l@T%`D|K(m z=+NR~o7N8vFGb%+?XMv&f-t{Kt3$WY@Svw49>hpF=2hd?2S>e(ZN9PWJ+X~zh7%z@ zt<&qD@H>W|Ga>Dg3kw#Mh%7$c2oik^;oq$d2JF045`u{n=Lkkzx!HbZSg8ha9TXgP zJz0uz#GlvM3DL*nS?HA7&c%3nw;wLC9w{b?-}}6_lw&x_EyotIQ}>!C|Du|won38< zP(6=D>orok-r$ z(06l;zF;r86fh@@A0F6z0#<2moQxi7)^3$(F;fdCZjuIcX`^c?SR51o`CT=OkB;=1iQIp5Xt(b27AJ6&v}E)Avq(r3)U(eFJc!^NowU|N6(YB66mWp_(u zDhv?Tj+SR38ZjG!U0!RdamV@&hIAX+dk%BY&O?c!y%q`1OYJY7<5v2KI?90@IMQPZ zs^51@CBOB9{by%?!k(fupSIO(2_2M|DkXiCEKRh_SA67=Nhj?3iG)iQ&h!((falB4r?QG?U14A)`+Pj9<}PT@Eb`d)1i9H4KIY9udpzqkI@- z>=X{z1S7&GRflE_YWz6At_79)<&6rkY ztxJ31gc@yVY3b&fxpHYTar^!?7WlEq_?WY?@29S$kSrQj%Myf-g3+^=(z z-AZ7&BH&1cMk!_kk1;JgX-7jqFcLNzg~PjQ?QleG-JcARGVH*W!72AQN~A2&g6VGsnFg#8 zdC_+coa&(n&p9^cyhN{Y74P zoxHeo98CGnCiF&tAkxmrlMp@Qt+RCh+ z2rjGuM#w|9LJu&6{O-gOHQ9@oi z=CVARaOHZrj;F>*E!xLEXO8Nn6a>d#^1D?nu{J3?6PHSR@&{ylchZs}=Jh;T2X=XJp*j zTgsA`iv}U=*>w>*bCZJYMU^hNb;Wd#B~OAi%SHF5X1$5g^`H2=&N45C+u`u1Xeq&j zS?g;pbozI0xVZd_whG`}O-v_yJ#!Q{wp-a+Ob>CGxbr_6go@%C3#d+U8-Z}RE&4-g z`y`38L*Gq0Bx~cqT7GX&I9#i5Sdi;j)BFPuxAr0XeqNZ6maXNb1vP?6<2}jsUQjYG zdpncP4QAw;;(H1fM^$31g`zyO9q9vAXJuDq_}b$Su+h;kE_)#{Wjwgzkrb|U*Q+X# zN(jiQ;@8zwx&uKTfCV=J9+ZH>nxi3l$8P<+)tNRz81)>s6@qVNl3Gp;S4jJxkQb#y z4~1l(OMnavMxs-ho$%72ESDto`Px?gEcVkXp6%rPgfijOK#>}Mn8r7;v*Y{W;rie| zTIz+X#MA&12FeulnL=K!XLKlY#u*$D!B4gv6R|lWo@~>%Y)rB{k37Yk9Pv5D%pGZF zWJ2GQZDs2!=jy_dYC(FJgBq}|$o?L7TmuyV;s60}JLtp_^}p_ zabma=1?|G%wmOGKE{Sx(@y>iNQiRCboMT9$AkrZ)oD6OMGV1`4m*rjb<1Aq0-d?J zIUK;FGgT&bV^O$gmF;>*EIeytjR$4;GaP4uT#R{t&4Ned5COFXH`jlO((K?;R?Rpm z!}F@jvHKeq)dYRi_A`H6czHC}pehE6e_hT3MJr;xH}L)f1r{MCZBTZN)^+iG)Pr`d z#^Bz2so8kznn5j3?#eQ?Vn?>iWn}H!&VD=Nz}Q#Y$P(|V0c&>)5eDP0amX*F=-16A zWZ-2}Eh-lzqVr6(6B0@n^M6EKYfdfrv$CA^nmuIhdjCNl{yCE-hfITpaeSNjVK@DZ znMOo2YN?c=0j+JDTQO$wXYV+8Z2`Sbnz7j}-F5trGVh&L+Qo)yRJ==C9W$2>3@{B^ z$O%xQh)YS9I=D0?RBsQ5Y2h-H1eF~vf)~GpKKd_;?9_eH2o>`q-sbacV+atgH{rWO zMW33t^y-fxw&MbjU(%y5e>!eZ;MAq3Cp`8#p~5V1w*-3xwkC+u~Gyi7JbgU7V{ z=BNHZd`DZ~16*&7;Dtj!tSPS{2iyuY!XeZSkBf zo9y?a;JcY_iXG?HhSWO6%75yhk;fS7c5@jR18N1p1(t**Nh%qzv^ z@N!HlPUJzP^1yi31NMi=r5~olqXHA|dh_XRM#s80?(4{S-|ptxw!K&~;}`1?dR~w3 zob<}XJCA=8{^HFskUCgGMHc_H@ICF4`~EM>W0DHy_bDv{_V#xc1@(->?8=v*(QzO# zYX7@beM@%3f9`Z1845YS=F0Z{68@V9zvO4WfpXlWF49pa6SPel8eTyB`80o==_I@* z)A#N>D@@F-0l@s_fMz@@Wqsi5Kn&MLLo;lEaZn6@TfEFiY^i#xPc^Kvy6_s_73%11 zwiICG2|n6wd()h!9F$|zN4Usb+keLKQirgqwpW9q7g*O%(P?*J4Zb6w=vSw&8dT}L zk)SGgP;#8piikdk&*++>2*ue#uHA$(mZ6>&mZ4TiVVm{nF(z%xpg_y*T#SNhD^Tl= zt`E(f<;2*7@@&5va{EUkc#@Z|x2psNB@OXO{!=-!*A_jav_Z|%xfHunxObQO!?KB* zx0&FwbWar!QGp;b`>qjGTZ${LZqzxweX^gS7IECe0fV7l&}4`=^^ZjpVHYq{6sUr5 z@?uk$>9+JKSAjnlBM7KmQ5`B!;XWIkv1a7Ur2xIuiN~SqLDh_+!QybKk~)MFUb6Jz zR0OFISP0aKk1;l!yxbmf-HYo*v0-ul_t&~!(=ASZI}^t=%u`IeYb8H|crC}L5<=f0 z3vooRYCs(^1amk`nZbIFBm0K6TxiER7FtF;(s6p`NKBm)oWKv>M&0(=hMQga?_qbv_Bn=)YdiNFurB&#pYndU_(9>f1=h zMgI@)^GA|7Z7Wx$(B;Ge?)5a$H+=;jd*qo{xef2gIjHxwuxLhGq98KiA2|qdXhuYQ zgmi<~3^pxp#-eAuOj2m_H<W}%U{@fb>m|LmZ?r-gGLraqcOfG7lFGi<;_p6qLm3MG39u{GMq|-& zQFG+c0y6OtcL)6qi@pZTx7Uc!)BL7)a1D?n z`X>!?rV*QOC;-aUjoT0ag}D6I5*0?`c>d5F2lZ@V6)tmRwzam(ul6f`@+mQz0?B)P zq|Y}Ss;hL@o}EDEh}YDq9A{nlUbD)+d1@o=c-k- z(p;#SpCdky&tisSx{1#ePq^1B7}1P&`2$j+Nj!&S4A8h2!K7KERA`jm?38w@# z5TY~D!Mer~x$-`G0v}x!P#RGZ_EC*!M)$?($P{*>dlPhA4S&YFi2pjY7}i16nZX>_ zjQ0|dC=CM_Nn!*_^$z5p%ws`sb{w^+-wJ*Ymp!C7)tixy3+(bVO{$@Mt$;>}DzSv< z1l`RQ!6yoJ;=V?`UmqKrF;8u#pCql@8T`n#mvPWuY|R)0?l*d!Mb`IG_Th?^fP>aB z1Nuelf=tg#`@`;y0nU7k#lm-li`rU1v;AUG5qpbeJLiVZNC(DzeDQYKZQV%H*rxI9 z`^q3qlpQ5pIRJirc`iX4t+6&fIl3Akz6Lh*WYgk^?RP5{U`&T19KulBs}s%D=J8=L zULn@z>zu}1g;5q89shb~ow#&)?p@G|u?c}Eah(q;A5lQ8qLI6`*)Qm{28MrYJC@Cd z)gV~abUF` zyr#HKPNVj>?Tu@@1>ul${B_90*A+YONJj}L7DdRhqLla;Skn7cV?Hy_qh6*)EO&{K zF)YYO@Abk7aO*G*<=lbYR2ar+pP4Kc+c->Tl_z?_q~6L!IM6xi3#HFVbG%AxHda%8 zw`GKe{XAZ43A;2Sp2cqKED>{Vk$Dst$)K5Q zxwJ|q^pHb2Fd8Oyz*Kt-iLYBG`jn**T${_+=?Stw7{A9|8&)LbhutudVMA_%CLHQW z=GvmS@!z_L^D8aMm7JlOblDXKjcfK5<6Nw5sYR$kl>b%PS;bTmb=$fdcbCT9*;oS` zx5nMw-QBfuXsmIE#%bIgHtz23?#{+fpNIb@H@P=Cr;?dknJ=rd9;%X>-x#A0{tdmr zJpMtjtK%}U?HgpNUD-Fb2?@2m1-NX7*I}#tZ$`Uq68xjad|50Xr9|;QL8p!D-de0| zzDwy>1OOOT5&B&5Up*)#|FD-}KYL>+hj%Ix*~hCbfij*3DzQy_uoCRmcC1VkXu&Ao z`Sv}iiwE41!B-VBof7rnoH^39_If4|OL^6*Vg;!PT$WG*E`KVA!{LXa<9pop#^>a^ zIc{oz>4L@$I#bjMSt}gcM-EXjgT)h7sQQC%;8tMU_~c6MYQ=vM@7x&>(u9S31pEqW z`1X?OB@Z&|kMOa*cV(RU4n2{5+fgg(-`Ct_OL+#^Y&{)j!P&{?9JHs*v+eh$mydwcfAkJ8&q8#s{nKaDLibp z`0aFdXZ-fafLVT>_A9_muCyz6XEjVe-Ctxs?cjjEgp8gyZ{$;4LZFUM9t<+fO=_6u zqR_35OXyTF{_^1GN`6xz4F3;7gP9CvNV}>1Jlhd`tj#P=x+^=5*%LMoKMwqk-nd%L z1s0|SU4Q!c?Vcj@5%HsP*w-KM#JbM59v_F+h3PF9{)VbCcsF>}DYDh#G(Z;!7WW6s)Z)@F{r)~35hU1aO2H*>sOdU~DSOKlgSbLc6^Sqo^ML z(qCIUvX1QFXmFxj6jAsYxhz?cqlA};fz|cT*HQ@AM)rboh`_O43oUkaA#))z`riWP zomy5#(C1tJjV^MPLbYl3$CW?z&dgVqU9i73ABW$R6<`N@?I7HXoidg?ReY&jpd(-~ zBvYXHK#&y>d?MQ_g;)qod=k)745Z4HjVLMYraie?)1guO!%A!L`;TH^ltF^8j2Zp4 zr?)brk0rDSc~zR=3GOb{M$QsLf9(}TKvQDNK#V*|BRp&8!gZWOJ(^sGE3_&XE%S~c zA&uy5ULqNDi-=;tdnRR0xmN5 zfMZ0vShU?5&qK;jMGR)>`H?bMc-GPTgVcan#GP8V#O(ZPG+`4h;bPbjO-FHyw#Ife zg_p}D9v;LSZk3b}0g)^f`>KmI%KnW)3d#_Qw|(CS23-J@)1|=`Gj7nOeWxj9|4KZJ zaQ#Dw=2-KUw}1iM6tWn6Pkr;i#7yYx>WBor56z!UZJjrPhAhl<-MCY&83pA~#~aeXLPQp8 z^L=WH9K&lqI8v!*F=r^Q)R)IGyp%7PKcck_aNvKRpp)xrk$yXG$2H6`9c5mz{Yt#t zIudS*Kq`>#?C%=(MLZj|w@#`|C`?x;`s6f@n8La z_+6i8gXk+@|Rz2`L z$M*{}21+e*(J8kn3;pV=J6t|N{=2b#10ogtL=!LBNo2@=M&oouPd*2XPdtyHuH}JSU*by__p=m3wNI*|+!h=K<<_QY; z`HLCnP!RqNz!R;HlA6**Oc)`57D47xA6M}CK40#}8+>DX1{aJFtoXL^PQ3)afFIT` zYmFqy5{Z_m@*SC(10VL=emnKVaVVf^GPLG;#0Td1v2sBe1l{v21T$|BB}01sqQISL zlPs| zLRgx_8r!(ov8tP9CI1KabB;~BVOV=Y!j>x(h;`0FY1c&71F!we60Z@k@p>rRmJ_Z` zlLdA(VHyNAgV9*b8`iw!*u$iEQN9eYe6RE2vZv_JYYu)7KUU6_YCVrXNk`-&Dy*E( z7m$rF=;4awXUdi<9$Ic#7LXgIK6`E^BcN4l<~yX#TGyo3WqhCuWEZNy8yjR}I7Utt zi)Td9OMv)Y5Xr8qdb@n;66y{8Zc2@}Fm)Dj6Z4iYFJ{b-PthCkCJwSvr*<3@-M%kys z1sYGHL6oEz-X+}>_l@+JX$QK?RH~IfpkgAXnsMRFDZi}u5$_??qUC!Czw%&n5H{%Nb9%GJBGd4XDKCENis8{}Q8`lh-55%vtt!bq=5st4ETY=xYmld}7eP_%#Y+x@YoxzN{Hz>K?#MPdo`tUz5=_vWdEqHm^Wk_r zWENu##i!?`Z)e21pR+1~5sSOGRJg*F!~Ba?qwRjZX=?y{@49lkoz6USmV6Ks6wF*( z>b31#Kb{Kat9K5#IZ9Pzj%2yZRt@rgiq?p2muB%d>iIU5gz-=B?da}d0*|peu~~$t zoc668fM1ggk=Pn(%Mm)O4^NgzK+D*nma)S2Yw-7BqP|7Rtfo^-Rp)HhU}O$X9`&3R zAIMqw^%@D^V5kc;m@d@^j!&MM)?#;lJwsU)%p6Q@;lF`)v4r|GLFJ3-Ow7lBJDkx3 z?KFBpTT)gj1UQ(9^_ll7G)gS8<6Jw($>~b&y<~0KTXC9p{Hzd-8ep#jUP>me&caQ1 z@$@dm4#rI|pVKfF7&R1Id!0GsqlSa|JZlpMoylV;eee-AZ1BXnr!_|{$2+^i#H-r` z`$%|a6g^uAx?J*V$?{9>-eB0SZc=rA=vigauYT0}V2Agv1he& z-5<9HhgDkiE<)z8n@Ucm^YPF%6H6|$ zkXJMP64vi#L+_wk_MFI*pU*e!ho79<#LiKJGVh7rsu(d;GF$$q>9Tu5H8C#t7$Lj1+_ zAs@A)S@lmu z=y*?D?3)jSqkOyQ&s7~Q+eJSI%Mz|1e9>bhwE6cJjPZq)^dJ1jB693JPuj)AO~%|O zG+ToPrs#VE36J|@Dm~uQLZ-Q-C(X%mY#*WK-laR zuc9A<-)*&=7`z0!>il;+@R9dk2AAFoXIxwtPf7(vESVA;B4^C%NKk| zJk8~5Tbe!^Aq&pjeQhcMV)!|$L7?L24kBLQV)AcPwm$r3nmLQu3H)v|%7^QBFno}F!Va0lBmP4Jn=qp; zRD5V7F~ETb^R+KS(74)~_e38OccvyHvvVk4ONAx{Z&?yS&*#29!%{2X^IY|{8oIDq>}>zYf%VKSkB@E(q>Y?n)iMc@;F z=#anteax`|z4mA?bvX4vO|j+r4E%P1fl!NWRfNxnFeR&=4PY!*blQ)ah(E$2_RP++ ztD{xT9NZvD5I1UhZ8_RVq~p6uGkjr)?TzxGD6t$;{HFEI-%6P>^suKQ_)mAGPrPKP zvL{dBnnaWk0*}&nL~s{Y(xJUzsDwn9dBv)jk=v!m9Mu}FZQA?f>_$v4W!FQNDK5gi z{seq5Azd^_*4k?if^^X*7CCeKgQI~Yng7D5k}&DVNup7UCnvOD^%4V-g(BFwo}l_u z6#+RtW2s%fxMntYK^39VM7k}Dlic6-`N?1pdH98{My_QGw6ph=n{? zh75ZnT=7`jWue0w?fLyOJ?RRPj`B@YaLE5l=upGr>!Lr_hc98FPNkfYkf`+yfx6<=iYI96!&h~XPH>fzD*=Yt#^WLyrMi~ET zsp(S@L56}LV2VIEZz!RqaaRdT8MI+HMRQk4kHlNXnIobjS!LHNiV%ae#NHnrw0L-; z!8Y8+0Ra&nU0dkr8yN|?^-JW#v)lweiZ1$@rCMgx89}Kc-R)1!rwFK7`%DsKHX&>S zR7!jDH*)+13q7($&_mQtXL|nmYMTRu9uSEed3~cBzpUlhc={GvS3v^Rszf^32SQxg z!s*#OCc+)|W@^_*1YB@Ez$ZCYMTzWOFdffd`Q9hd)~fvBUbZby}i^W6kaci z0=K{dp#!f|Q#o??bX~$M=UzO}QDvvcnRr+Ydb#}eqyWLg#6zW7l;Kxy7ue@d>}F&6 zT}bKBlE@F+G}iX`wCyh0TI)8D#-UHm3A#gz4=8PywpZ)%Z zEX~U|-zhfQ;Nj{Ug;8Ai_>!}z??*4I2@k$ijULU^x6Vr-J>h+l=dSzCPgw+lGZ0TE zCcmu}&!egb1~;w>Z$fzD`xw{fOA^t_6gSbF9)^T+n)eh?BJOxYxd@WtWgSQZ$T%L# z+oj=T^`q?&;Mdk%kLuk9*hPik|Jml)&9l$K5B)CZyfQk8!J@J0pS3D{z1}j)(FBtI zjh|TLvLgZCb>h}>{?Z9ml{dJ)W*~hXDCl9^eS{(U+3-8epS~ydvhU!TMCP~JIS$7= zAQRq`28rDqXMzE-|&;65ERH*N&0>?B&y&qH8{7pxz1Wy1a&s# zug!j{123Sn%qSpq=ur6NJ{Mhu#Ut~q)XqM_?R;K(rm*j9EuOmbKKR>(rA2itHS0{I zB$%XRsz}kKCE!A&j^y(h6=BAr_x&Nlk99n)h>ZMEBB0UrmM9+;J0CC@FB)flK)C;^ zVoG8WF6drCDgxX|9%hegePxn+S&662?klQFR&yXPjQ1kz%( zk1`VM*Ei5C>-O5OC;ZzQ?`D@m!3!g(fJ%x&N)CO+H#eqpD)?wy58~Mr_cEe%9 z<>}{79r#A*i+rr)zL8VVTR_N1u}Hd23(LPnOhnc){B@=OmZ_Or^6AyFR)Q1u;?vug zzJz;OoEiUu{%AX#%S>clXO_6J2KjYVm~}<1PaXv&O8JF zruCZl@xOZWK7@8xv|gUQ%Vi+XIJAsa;iy}i{_r_A7i;dj)y3DD<0c7Ipa1GeXV zO?SGO(dnS~IcTWgMuaIp0PZ6NbSUB=3;g^6Y7z2NTvD_nP7$x9rp^kVW0jDg*1kn6 z37|i3gG8-!+!{!tLH(%DWQEcWSuj{LpBgsVhpperbaJ1Xm)O~wG#Dp_t z!jTyT3VGe{rtRROsBzCo8f|7#o9G{%T739z_7ENy0=Xm>h`9lg6S}dB|IoAJL;!;}?;_aVv zU;pS`l1R*rN@o`s>HU4gBa?7)9 zh}Z$Q6^P@4FxhY4@X9z!%HJ5}wz-RG-fyr6i~}ld(;-A+wPkxJ9_(Rmp9u@^;EGrc zu(#=_N2!{^&up}&hefwJ7u|w&MB~~MnkcG9nnX`JW->=xey-Yg* zUxY3|xIg6$gO6Jed{aYv`%9;=4%A2t8=JoVvc!y)amz6aR97zT`1A?ZfDe6s#K!Yr zqsy|4Y)BJ&1353tK+$yILQ{vLe;yRLE2x9@oGtXq0d`0Y{GXo5^qyuWF)~ z_VuUX$6Pfuc%x6<{X6iCcP|&X$A6M{gxoHDi3KDbWd=z1)DHl^84uAy9#iG z?u%UVfO?k+PwZ-fP992Exgg;@%vHiM22EwE`}|8L4>2<9qy7#`Ls`xJ1Onl#x{|~t z7fey2-&Qg{@JtI<1(Iwp$tB8Q457WH8s5Zv$xaQ+p~$_{PDcRV}vLW)R!dCh9$0zgbq^( zgECDbfU#*J!oQ7}*JQ41mxOml-=P9xWk+7!Q?@r&3heRO_(z`hsnUZ^naMR%5E)ZcCmAAoXOLY#jrW^OytfT6D&?iY04CM-Igt6!YRB>O|pXj z5I|b>Hje z^~j%zRw6t`ooVs*$GK_NQ2}yS9d-}0&v;GA?`~O?`i&s(8)}Uzk1{4eRu15v6H_}Y zwn*HVzEPlX7Fo>0;y9|_prhbNCOM=!ZQD-(byWtGo&|6Dy|+!|Az|g9VMTmEJBAtO zxz`eyumJoNmDpzI?pM|@Pe&AI_zdpKo`K@xkI0yQ0lQiPhQpX6@;$xOUUZjMORJne z0HxC7)^fAFdDos&>I>;?XAnzt!k^eg?MEQhvNp-hJ#b3z)Mn4kg86Z_D)d7Ex#*uryV8i~Q~4bchN-;Tu3A`CsRPi0a+$p57}h#8>k zn-4N-R#Np!3>g5KAF=ZCkH+Fa3u2xDbK#m;=(o6Hv76IsP>X9^?g*?(R}5r|Q@by8gc^DiGoEoCU9^fLjug3MKmA zXyL8~T&`50D_)GZTQsZ6^_X+H5g+sb8vPlXcT@EHbJ>@Palli`Zzp|zaMKe#92N@T|y z4qAlxzMfUB*(@Krym$znfi7*Y-iwq&RMGzXwlUy+fgBwDk*0h}De^lF8R}O}y=n1e z#{+psXP)NukQS6W&pV+QSQZ+0fEjbAuZ_a#?;?2zUfQ$WVDx8<;HGKIxROSQ_TX(f zO#EknzbKsFT@QB(8(DAAY^=K3_Ppv z-#f=ACz0{$xopiUCMYr*FC7C!7KLu^_6ngdDG!AkXr;TuP*eP9UQ(^Z8b090B_>0w0BaKdL_miFMaGVpA8EP(}kg??2#Bq8q-lPH~t>wXx-fS zJ^ZM@|3n0BSY*V;*&P~nZ|_BI%6KmC;eDPBekXogujH(5>+5TTwk6FDZU{`5MisYjn#an;>F5wK^)W-aaG-ukdoeNX0aGB!5|ox^295 zh%dNRsoNrRF{rCKDkeXebL0YdS)OH=*CG%SbrM%qD)r%{+L0D~C<nWFTzHhBU9}d7NN?&)pjsw5{7VteB0*=mOg9{0Zpf zKGtr1jIYV=X@FNN$pM+MB=@z@79#PjzL+!9nzP)rI00jZkj$+fRe+!$jvEc@Xkti^ zjV(%1-r_7QA6zbf?x6~P^|2nWZL$um#tAppZobPq^vcYw1JAdnewy_iJ+Z=RPG1j) zH#8&8=a(d;#J~t_jv4as63z1XzO`FU62tr*idzrC4PM!p@*ru-3|z|(U%&_g!ZQ2Y z?6)TNuq<|B3Z^U7(b&hpLYndXx;E$$Sb<$(~+xcAEt?)#0kBj{Q z5eRwTkF&BRM`^$S&YuWy=|7krII}7S<0Own__W@3YYzyf!JaI6m$Jd_yoIBv2mk0k|#wM4H88eTjQT;cF!c zF7$$|r-RbO;$h5SUN0bOvAM>k0rKA8TUown212G*o$eoROev8!XlVNhhOdd&;3$n2 zwfE=k>niRgh3!5{V};TfWRl=RB;E%f3KH+5IZ6%z-+u;bHSc%a0&mXuVJ8^vO-|66 zUPpT|yVoOrz5GM*vDLd&zOo(@db2t)*E`J_xv2NJe{3qXtG^dOmCDEivIXO> z4|FnyFeMs46ZHQ@iB)lU(_M{ z6eq!7KQC-$fefIzbb4W0;E899e|(56qhC23Fp1W&+^8LS?b4Xnri+oCV=~+7y=q0U zx;(ZCvZ0Zgg^C}_?Kbb*E>r&k7yZr*QjLe(uX*M_RYCwv{QkQmUi4eR1QNdJ__*O; zl5+u83Z$$CXAYg(fRfD4^1=G!?5uJjo zkkvTH<6#&Pog!3DgEDG|t+aodx37*JO8{qbvW*1~_8LQH;6U8J)pVm{aVQ>_JS^!gE*ZnM&azZ?rWs-;aPN6INc z^LP$FM|D83kjrIe+Gp2-uA)hwz3f68h9T}^mpgdW@x{8XImQX^c4$PoYZCBdnS9IN zg>dxxa4mg5o_B2fXfS7=jgMhNNVO43*d9jar6~C;iY>GdUdzBDs{3LJSsVXN)$LDDwstSXp zqkD8bZ|v=+4Jy1Oqw7~THKK4N?k+!nnKIKd&p;$MhWn^npV1is7m1gScxPRcIf+B( z^Owc+fBbPQ<05iJVxPxsn$niXn3@v~x9z&1-zE{+P~4Plw{EONx5r6W;`MHFaNr)65Q%>QG(esq(d{&E`HV-2Q{(YcwXBjgaR@DP&f~@?w8xf)}joA z!cDN#$)Hduy+fIhvgVbKKMaD}MhHaFMC;0nIYM%$vSBlZA)Trh%566C5kUEm)56HS zB`F9Y<#%AX6nK4+AV2uT+6$ZyA`iU;r55j@u}iydwV{k*ynh+BWUR~8oW{#GH- zZX8iVrx17SVzh~UT^XlSxM-&DR(Cn}rmblVA31BgKmfyhCJS!-?T+b04A|T%>h8}B zPeka%DwS*ZE;$l_ej)tU@jU(&8s-o@u6t6@&GtI7WABe}{4v@t(&5?Yy@PPiJ_!Fwz*MT)LZ$aJ;Fl=s-~2ElX9Syxr%U-q-2Mc7=C8cfgGR zuCQRR#Nv`An2Oz}n>Igko)szXZg0j5m;}zwH7v zNNs1=ZAiEf3PYq)`9{>X-@=2Tj1s*z4E(^8YS1`bC)F=9i+^i-BDY+sAqY0tWo?|) zyA{)i)r4v`C72g9^UB7QewJxe$U6NrZY-pxv)JQadSV; z!x7%243qI@I+}zh62A6{>F@#$6fOT=EwYfl*w}D>sxxzExO>Q1+9Vsb?@xxuW3%ZR zj-~!GMT=g~^H0c1q~pGt{A{Q1vo7e;!qaF?;FPE#B>9(_MG=-RZtz%fjp7(Z);K$*g6&H|&EEXFIo^_>N~w9?Yzx z&LIUOBF^mj`)Qaupo)a1?}Q-*SRI{UG@f~sjSgwHY+hZ1?vdDIQnc!JwfN6I+o$e8 zQ;b_+Rvh$lluF@jt5EU`e=t04LeXOPQ+xLLczZ+ZDJ(% zZ+CCw<{V6h3=%~cam^yjCcuwD+4|Z&n3SDSvx2o7HRW$1s%xTK3A@+jT4zUBzspXs z3nj@HFGR|rUQzY!rFx6~ zdvPjpq6|%RD8?y#`N{*`utc&NOeqFLd^3y~ml zbpv@fr^Ic<7j((~zNuA#?|(klDQdTa>62JWK6Adry+P--y5EcU@|8`xX!oQ{jnlVH zqsWZw=13&^G`qR6f2Un>oJ|QZq>iG4GY{M*7M=IPs`zP7T$(skaY{3&aZA zqzpA(=Q+vUHHvEI2V3X})15VhuT5_+ zhia1hwl{NhyHnaVbZPx>5rKn}J)WP9ht85fEGH5I7)mjknxEgSeoERAzdZ*M zbDMd7PWaD+F&$WzC%}3!(@S_dEIK9i>EkIf4e2HZ2LB;mvKWiU)2Q>V$Rr%{kE)8{p&mk*aG+>5pz!A> z{P$1M*;4@y;6eR(e;s%r?3+jEK);EBoZR=E-*Scl{j8S`m$K)wTELp^%bjHPoa%g! zZ|?u%m`7-fU1?HFI2CI^#1qUQq47$0nX&JONLBkg*sR`#XJ7OCACW#Wjjv`cmKh>y zxrN;i?~J$9ADrq{EV62b7v^^m4+zln-gmo?)@r1;eOYfe>e!miW@`=AAJ}kq8#g?R zbI;d*9)2;zk7WP!;jk>1{XBGWcDU*z4y{cwL*4Xnw zAyQ*wl*cc^MCM9eA+o2FOD?+S>J`} zN&Ndc5^uw&b?xNM`QBWPg7n5=)|R~2j=$=m2B$3Vd#zIzsf#_b-_s@^EBlm+Aj^NO zK8Q@(V^ft-akS zEl?7FDC5)TxAuN_w4vNuqppoV@Rr4W_~clrA?~=1I4~Hw`y3cKjpv|vQ&~LrzVBG} zS;U;(YD7K?@)e(_ppIDkaIxgy5BBkzz}JlRf(=d;ViG&qIWRIt<^p< z_)_a1BSgw^FntV?MnMbRE~hrtYq$88g6cXoob52pso#L_5f#EC5trVmd^V0*a*0#r zJvomV!5v*3;P$c4i=8s-=$FN0OKT3}JxvIMm~s?r9T?fF!6fFWi{@t4zxR#O$pNK7 zGr5D=&;{iz6z`C=>&cF)_{Gv`9krR|W_po`JtMf(4QkzXx@%3@BiJqS)9wzb2n{W* z=em_zfpqUrgTy|?-9?m~GZo#b1Qiq%;AiFMo>t@5GJly^&VLZXH}W>&7cH;B@3mN|;(|pV57Rgk0@`W+lM>w7p1opn7yB;p8y$wGydsa?=Y- zO*3r7`ck4@EZJ!CBq#fYcT{mA3{*MlC@Lj7)~#Os_DnMn6a|RkaVS*Oz`2x~=~|6b zgrIxN3G?&!GC(MLLGN(3EDO!HslWDDsSdvD_$zqpRW=qVhl{;}VD0EUHPj zMNhb*hE|$w0W~R?)>?r^l#_{)cXRDN^K3wpioGbzzkixF_nN}XmdH+fk(@`NbwYDzRHCFyi}FVPMOvjPDz6@MB~bRk(}VQ5fRs zKC!bhmtxr2qa(}P>xC`Sq2V&pr9+PlOa}8uO!m>3;ZYVZV0{FM=NC0&>vMeA%0YMj zFIe_v>)uQO_QDDsJt333-_bzoHug7(dOS~raJW|^C@e;|@&tSS!rwcIv!5PFq3Bv- zTLxK$-5)P~sUnWeZmm7~N%TzeJ$}6?#xHcqIV#`=$4EPj=TE^+S)(K2nD9dyT3wqP ztqb>1k<}R7!{onMOiwFj&P@?P4*KgXbNC46LBS_VAUfK)p+3uo+QX#;agT!mEd1C_ z1w@VP{CGTF4`)f97!Y)Yp`~pLu=zOzKiI&FJGPmI6}-1}Z`+9oS(GNvVp-!<-}dpB?5~Il2IB>o95iV%+(X_DXcZQgaLa`mmVDW)rrC zOv|@S7uGrP-q6qC)8z_!CY-pP^=doPt2kqipeVl&TQOMNDPRWEmBG|N_p)6ZJOYz; zTfJmt)H(B>Y}i=KF>a%SEY!bK@|_Ta^06xfqKc1%%NNV;lH~wobY<=>UFTZ~XgnRA z%^1FWwrp0mKRvk_+cR=){L& zQKohbrA0PP7wEatTSkyYkA10#TtY@CtD*w2I;ZAka}OP?z@8AD3`d9$IMB;Y@? zaZ`-7mDmSAM|l)m#6Zxm7$x|fk5@aI;zH%($5=m?p}wDPA>ivkSndTSOIhj~3S6?# zb{};T<#J=?a6`;CXA0Hypz^-=COf!I=~o7_tywhI$;Y`I0o^j~$Q2IVV~Uk@0188& z$(Gm|Gc%*g%_rM2Q|C8B&pf0n&9?U%S!@l4K6{HiSw9{tfjFrGJM)H#d;=*%kMiQC@!}hZIj_oFb9U6BbgruaCJF8 z4X+?JE{;&!wGGwcx+k-i-`iDA>D$VevN$)%!clUdkfgjnumoNJNS%Q)D-9S3e-wOK zMwNq$QAM$aCzN=F4YbC+OLDqM3OB8!3=}-H?WSFcR{3ygCdF{Yar4K`Ehhg-fVd-!xz5_|DCoDGh7}xc?UZJ4H}unj zAfy!ptn@NlcCh^!a<&8<9^XPXJLuQM-oEDOJw@a9#|BONk;z{@MSAK^zSrKbfS8r5a&1{qk#>Y z{^YDD-F$lX$M3PsUbg=63n*RMcm0)Y{8 zp@nFDU|vEXTlT#0+t4HNKYat&pXGlBFoZ~H39r73FeoVJc+1W!xsU;4Qp+CckY*Xc z?1D0j{ce9PJKQ@Sl%xaGEp9Hg*D|9j7+eFK&h`j0U9QO&Q$8C)T)D_2=Qi2Bpcsga ztf2u6oF>Ly5q?%@_oV|}S=E2xxA9L=o!f(D{3JSs>z zSS(*k*H@?gCaHu7*L}&6#)d}2E%zrFbdcw#UhHxcQB%-!pi4V8&D)Yz%~(k4eVMjC zVMc|jvc>d|v1LKkOGR#s08IqPUb#%_v!Ze=+L9)OuRt^^_{BV1G8-d0f$0TChm_68 zNJtj#!#_Qvo?GV1t*I6!!|R`J?!)SQT_ZmSTcarGM)Twhs7<8Z zSnqavNR<7pQ+7MFj=rf4Bej I_22vd7fAcE)Bpeg diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/FORECAST.index deleted file mode 100644 index 55f38217c360f73f2a3c0ffc1c97f1a91afe7f8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZ{kF-%iY6o!urCK3i^(1-(ZQA2HLp^5Dz3a>U`-%F`MeSKRsQDx5|uMVcTjgxucBtmRSdmmLYZ5r%v?idtyt=aA;lI@gH&D& zg4CKIvYknZt!_R@Z2fdDwH0Z-bjGx}Zui$VH^zByYuqgcB$reiAD9#`FRKr&s(6MfVe;uL@I4nc*Kq>Dz%S=40pw0u zw-}n#ydyX9D+iu>98G(qrUr1bq#pNCwc$l*csX=o^C%6+nd64Pam*Sn7J*rebB>rr zQ9>ed+J}yr5{L2x`!#ASwMQoR*SR>9Vek2dAxcQ&Y)3g?9-Xh_GRgULphFA3I%cl4 zozW2XoiQnCXEjgZo_%vJcAg;!Yv)5p%(=t~S9UlI6t5ER4Y`iLedPPaPJP+vPul7d z#9ci1@Tj1V&?4Sp#e!lVlat)X@6M(6z16oJF>lp0n0?-b*VJyfsLAE~;hgPO1@AN3 zbtVbE(h9+!IcHirfilaX*B>3TUh8*UiXHq1!>;ko_%Mydv4&kwolDKh^$2J9?3kHT zIsGyZa_7z^a(ZtA_SP|ztL9>0qrHEI_^7_!$$VbQbr{2sJ4HCV$-@Pb#vET7k_8-4KY?S}8 o#C~3a<^N#&|N9lb>|bP^^vixDf9;-kyWj5znM*GC&+wlC0Hwe@NdN!< diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_5/PARAMETER.index deleted file mode 100644 index 2cda545a60841db0b4d629d55b64d91ee1094f97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72 zcmeZo6=GmyU|`rkT_X%gf!V@9I@r(A+cnzc{>U((VdwJ@6d+Pgm>ic@?`;*1|$qOF+2T+`1Ai3RR<3SX^^B6do z;$lO{3m*N4Qk-HKx!q&q;S|5~7&wCBVk5~59{opAoMJS&-DBf16u;c>smgcGQ|mB$Spzk2kUNcD?7KJ!>^5|vN&c*A49 z$y7evW4Ol*Q>eU$$Ne4?PNniz9yfUW>d|K!)i3t=%wxIfR6fhIoAB(Q7`nFXgeF$B7=dc)a5Ar^j3iXu0|x z2YX!VG1TKLk7Cn|_`t5M@-|8D%@C+u$G&k?pgimwSferqt?_@2#8#{I4roK)YJ+&F)a}QfMZ7sjnh%3Zzhd9&O z4o@}s`eo$WFCw=CRQMgKNY`1S+HY(TV8Dp zCHv&VIHQM8r|~BCODN;k#W-UVucz_max9E5YFHbnGwh&va6F7JvQA5A#X8bI8mjn} zFwUq40W{teJViE2gz<&@)gi}EA@`kt>PHO4HOpYUv2*)CS!E?T_zD!aM`B2=i4b>0r4OQ?cD*rhh>NCMq zpKAk^f7wH^-w9}jUVtL+UC1Upr}B-TD4rP$<0dbgl)RGx%79$ZCM*V3pNdedtOd>7 zCXm%_2c_*sRvG|B#Zgp$dm`isXG67hAsM!u>ie#v`h8oW-m)8t{)ebO^>K=W!=d^e z33ctO&^EmdS?2qYuXsY`4_-p?^Bpv|K0!9}JJiv?pz06@^8kB30aP`;DBhU@%FJmY zpPZ3=l!fX`mu9KbewoV-<4#qt_>cT@8s|gz(!^~5jqJC}n=T5n?=1V8=3cQU~iC?Xz07AwhDS1*t#8JGyw&RB>@HK+&cr3WL3`M+)_gp*n6MPx%>-a$B7kLTwzDuF#yB^woiy^Pt9J14YQEZQ0bnQj6Mo{KULaw}g z!Ij%p&7d6Xe;(TjD;EhLtUc%Cvo4--s?t@^52>afPPy22hzN7aF)yf}$~qJZogA{| z|Ab=sd99%EJ%7T*?9Qj-Sgw8!@rnqVts|66 zCO~t0I26CCL2jy395*ktUJ-}f^5T?)Z20DbE;cj&Ie_)99l76W!{_XC$~ZM4J5(Fm z`&FR1=SBMDhO+u_$mInpzx;~gMl+$VnUYL%Y_D6d2ogy~H+8Z{wz*R$y4%vJ`o2MaWTI13 ze$=Wy@*|zQ9_2^%hIex9c@q=yz$}gP8s0U6XxpB%PCUq z=WpZ=q?m3i*`H)Drm=4@pY-RLd~PzANNae0gQ$RlN95DCUJAztYRbBEK@Vy~nui znwbeGzv>wY)xCwtuk6rblvg!c2-&ZnP)_fHyo$%1gSthT0Jk2|PeYk93GykPW+)Ub z?o)mhRv&ql^xIEX&NT_k4GM(1Xbd#VdQl#A<_47eYa@Ts-S$x)bs;bEB>Q|ZKl~qd!wzyXZW3K6L5s zkgr%y_PGk#tR(YMA0r?S8v@18jpVVr&{jyf0PTj?fGl7bv~4#*5&teUBa;WYc6M_$ z$R-UUU#@}X$W^F5#>4Y3^`JDA-?~D(bRoqV!^ywDQ+dH6i`;tEw$6~hTm;RG2r91- zXR)g{r^-Q|svlI}S5bM_>rhut671Sp|0+;_@Q3EeDk?vJ8H!YKmtcLVOG4X9LOp2) z_ASlxWLREST)r)YbSJU$`yDQc*x4d4R4XSZfC@$OqO8>FstL2atKML)Qd*tI7 zD28TUPV1>aj&DU~9t!!$`OpM!r}Ci@RG#<+WHsZ{bF;76q5MkE(NvL^h;5KRG!>>n zUUnswZ`}`7_<1Vd^#uMO0-gcLG2c*Lr)eHi)gSqgjoOU)i)b7|^PLxuuekN}b5VX1*cj^SBWYd{xEk7V=b)Dd<M*(=`Ugq_gz8EL=;k$Nm}6Ru}?Bk4})C zYzTF_isaIqQ2NEAc->vP4$5t!>)=68vOpw{aiy@9}Vdi_PtD->b4e(I3dI-_SoWC8?hnm=y9w;pji? znAw!4r)UfL)cjCB`-pyq4cQM(R)1)3WT5!+cIuBpdqBQ*JjI`1K-+XCEg$Yf>uny3 zwja8PwqNHxWMN;SU8E__ksg}q>#!WVR3D0E@hDbjY5PYOL!Gh*#WhPqzA1+Gr-GsV z7||Q5IIq!oByy& z8?heIcq?8{yUyz;`WLT5vBjT$Mm8Cmz^TTUM;>H82BdJYsQo6DQzz+|)@cV^O%E$K z$>dbyE@gJ|ZmqL9?Tcvc6k{vqaLVM9b2{zpOSurY%bv%{mJQ5{xJ6h#r%0TofYbO7 zE$CFAE*3((tw<54xH6-tQ#Bb}3~^-k;!dq2ARj%f1j=(~E9o>}PC(APmU1z>7OS*V z1O=1J3YBp&&m00xNuRQ)KXL)G3N6aHShu(dS*mt9=97 z%NuLB*u0xo)5+frujN$3hShfJ&`CZp-kLg2ap_`Rr&*f3K5Wwg`K9=Lq@jy-l8lX= ztk4~(yKHRYV%>MVuTzxl+SDnNG;ii)uNyaasy3}!I8FOrEuHr3q*hMxeN$_v8gZkI z)9y{$&M8aRYY%(O?cn59ZAZkuOQq9%ZqUi8-o)+f)LD*^r^oxb*nX+m#VKPa?F!dj zgDiMeHy4W={@tB+cC{W(c`i*)Cok~=szJwkp*;Q)jRpkPMT&%utfx2U>}F4ipn2&c_!p~|*wq>IhDj-ycSm2b3D1$}}h zXZRQw^D-;OI;G#pafmk*Qiz`}gW^yM_i;8k(3s$ZzeWr%+7jJkzb0zq<={nKsC8?ZoR)o^Fo3R;RcMP3PvwYgOB8 zkbf!|h~=~Oh33#dP&|4ERY=LXu3pz12E}}Of5{$W^IW;OUJI(1vmpOP`K*1Cb-t@t zOM5_;c^Ab#zu=$uV;8u3UTYyVsUAYnzgUnf7d^&87B2$ox|tWcawhsf{UQX~ddU`{ zyqSdZ$xbM4##`*lRZJ_W%h2aB_@Lhuuka1Vay!;Swc#t|Q|c|jat)W0vEM_xxjN;C z|2_Wv%lyZzj@s(R8};rj)E5#{J~Y25IkY`lask=@5>!vpZgb0tCGDX(wFdGJ&me1) zVY{nmK9!*C*a7OZBcNC?m%O-z>RX?s`cW^ae7DyQ?AM`^kRNUW<)L2W{y|hfdN9RX zs9bdQL2MIdfFk-4*2llEqxC*+O8&S*`?>Nljz=edOvj%uIg}Uuwz%!R|%o^P8bX-~PB^;r-O zlNC7QwEfLlCqL*L;S>uWMLJb8?+Z>jDaS>WXHI;{sh|CTCe^3QF6McEU4dt_UURae zzSq%CPr~~L`r&@$v%2;*yuV<&-Jrbo*r_|NoxDQtL&yo^=>3?vwekK0Uy=&>uB@w| zDI5)T+9C9QM#0#aA8G&TG~b$#5c4wGW&q94avg&@QGA-WjjjpxgRxNDJ49~y0Zq?} znD5CoeQDlzW)ZYQ_dtF!60$uvplbP;;;D%-Z;uH`vuNlq5$OO=E`WApYKzzUAc;w`^L%BtbB{})~(e$r#bTo%J&1_ zqy8hqd{O?G4_U%|$O}aM{ZRI)f&78DI1S~P>c}@t$WF>bVrM|UrGE~BW?BTatJ5QY zGntw|*?A_#z4t*@>^_x8C;#g9!!9Zb^{IMLR%{JLnKqCOuMcfbdVkcE$%9y*%m#T+ z((d%UZ<@6d%GFSBGOPxav1mQ2KdskR@}u&CL#W;BS>!VfMa&Us`hI}+O73qsZ`oTw z`)M{5MM9t+c#Yy7KOifY^Sf)Wel#a51VMA|4rD!Y{c!bc=SZkKT_N+8rulopWPQK~5e*=KMm^JQ{aC; ze{1wF$DcpDj_dkgdo?HS51#!W+($C;PrA=)_Q8E<=az%2TvEu3QXXoCgwg%mbS2%t zX%*SEGgN=oq55K_q1l&*ESL$}oXN>bajCokgX(h(`U#ok3ltSTLKE|b%E!EfHo-fn zy8MJZds13YZQ70~T8-BCv<2jYD4*757-C&!G}UJw1?@zNWyDl!-*hz;lOmv=9T&%M zn$?6N<5D^wt3FWqpe8tPeDg-?ua?E3ernMmXp_c5f29YlrGD#s9h`4_?jsa=Hc|iO z(+>TYUX~dBmpC5*P2@VfPAX4%dYvOyKy@Mo`Z3vJIXS8%`Y}ED6xpN?`Y{ubh5E6d z-=SLg82y)4XQ}@hauEHI-LW0_xz4r>_pi)81otTqZ;AVomv2P(V~56cA7&a)_nj}@ zNBWEBI&YOHmb;&L*9d5RRME5Jx|sFyisv-@Mw6c^#CNgWnx*fB7RF#d`Qtz+Y+Eu%MX1B$KzlI^$EBMrgRI#oiYw7^ zvyr{2d}<(6U(Qji%h2*a?$Ua*@5FZX&qLS`o9a6Di(Pz)^S~M<#(s;31#tXoUp5>M ztMi);MLAMtnKcm>}>=OOv96gV$2`BOS&mdlVO?vcvHJUU)#r#;gVih%x*ogMng6#W|vJUc|h0Q01u) zdGaWnH=VFOl%Hag8FE0gYb~@r`cwPwZLmJIsT%f!?Tvvtq70qiQ5B)>5ErT!?NBcZ zU!djUOQ_=}fVSfi+MhRLAxq~?+gTJF>NJP3eeL5<`_(EwS)&KN{>Rtjda!;sa2>N{ zUQj)4it9z+IY8G>`C4>+Pl}=Y>(_nwU*k{9>i_cd*Yv=^5GkDdJo7~{5 z72NOCxkvAH^2+h|puBSEE~omjeWz1&+_%HYlHS(g_iQ*3Ou0p+!7u7~9-u5(s+B>$#Mf>=kM+f!%U4MHU?b?Ujfxf%$ zI@zUj_u#E7QBFIh8S*39awk+be~=?9-FNlsSrC+O=<{H#b*Bd?4?PM^v$V*URI=fa z%UjT_E{y!hj_ps59t}lgU&z|jfhNgkYVWfG%6zS%&YueMsgc+YKeq36(f>MgV>s$!nQFO7#bAOy-QA0aExG4D|~>p&Ycn2fgw@{-%3 zNpXR^f0ycK-iG2XY3I=ABF((FRKGSh=1;0<7N}Dcg*>Jzlpi`mk$no4U)~0l?-QuU zuvfSq@+2ZRrG|1<7K*#%hiqm!C}L_s)4UnQw>m*pv@f*LL#V#NNXQe6gSz-6s(&&Q z$}vHZJzPfhQR|`kwS(fnL!b&d1$nQFR6qA7WL@qaDDI5IrJ|yIi@DAE(T8s-9Cv2Q+f3Po@dtGxwW1#r~WvoTks@ zR!-%esI61_Z*K3j-%3lTIIyOZ(-h3^=afq}b#d~%q8sA#w!4${pV8B4_g3lcG$p_F zak5?q`Z>*=D*jGYAjbfwz8Y_!(;j{fWpuyLf=lN1qP^2rc!1BJYkGjcxu$aEBIQA- zhZG)Jk2wI%>*P~hxxCf|+QRe&RP&s^2xPOjnd<7rJ^BKwO7t1AUR`Y(mfJ9c ze0`a$pJ_VUukQf)F%4CH3oXks!`16GEucs=3-SyG+RJaDYL|H?+Wo8vMZ&%mKcO%5 z@T7YXn=jWOOZF97one++P9`Z2b+Oja?i>zT(M8ZS-VN3M^HAn^4#jjf+bu83rGs*L z0cbB)CNDRFdWVEc`BU6v9L1$(K~{GOG&|N&JbNd!zYjy1?KBkcFGDr@9(jbmNNaY{ z7l~NMpD1THN$qhw^;uJ5cO!WoplF3_AeVHy$P96Z&ld;fNoJsMB zU}#pagDi3v)CG<~@img-!FMUX@CwR8F_8Ht2z2|$SEeAxW`gooE-2O&rSiKKsC+~% zDj(nr&5jOaHqRHG^f1Ia^+c#z1w!6zDYWm_leu@1FAhUfF&wh=mmnW?o9zAw+Iz2{ zdhrpmz@HRfjWgHnzde)~>S`$|?v|e75?LtTl7r$qc_}{a`GWG;;#3~13>2*^K&h%g z)!!T1%(Wm>b)cS4AGkCv8X@MVn^3#gO`$p49I9R|A-mLy>XWpg`W$V^Z1hDelc+tl zdqSH19T3Y&9ieR~ss6vlAK!mD{#fsbwitJAy&UV*KA+|~rB5MD?B(>X8(nM;)Wd{a zHNB36MNZ0XP(Hpvs8ck*8}8)M=OPgQn1%`RpEsy6G1i;CF%j0m4KU#~$p&D8E0cI8 zv~|8<;>uTOO#Eyz`kUhv(>-Bx-wlDok zzIW<-@5z{Tc(7zM`r^ToI{JaEGz|}ySoxHAu*Bv}gR1O1$fN0tLM&h+9yqDh|3ESP z7?iKVpqWGu&`tbnh*@{f2cYCz#QZFy@w<3B$Y&OT_F65d{o7NVbr58CCqr42KA6Qr zmr(g>`XH7)7(n$2J3*1LI8^X1_OdMvq&*GG7jC0hmI z0io^tnI>MUAx*U6&%?xzbvlRF*LM7f*PCtrO%wCDuW=oSyN5Bc=Mf`uedyNtkpQTD z7jgZty9$YhimHL@N?gg0M2T%B?Et4>vD@nxrN5%-c)9*Vl)G@FkjfwbFh)BUmK>sePW z29!MG)R*Ss{*gCgBO%ov=?y*ItvBv3_Oj;*tncI6<4&761>_CqA9L}a`3qzTH_?6B zwghAs2OuF9EvFvAcI+<5K6F97sMmv*SFLG%*^AM3qAo-6wjH)_&t8G*M6r`t&!!IK z#BR`js1C)DtW-WQA-OXLC z`orR#$b(VpY7IBJyqxr|P@Cwv+GNQy1}n6A!04^ojQnRLIACz%f3$dgRs$-P{?OmL>RlXpwj*J+b9?dR0n7WH?E-+ld^ z>QnLo@X`**&NfBf#EN}}ym>J4C*fTg`ICKfADT{6kVmQAg(;7UeHF?wV~|g&3VD!E zvA-@rn}B|Bfi=iWd6myqXc|vKUL`hoet2Q zBji`A-wtRa(jdPQHAg`H;2y;rYX-RW@V~c0b|M|}E0%LS6dPVaU9dIsD>fkv@_$Mp zzp~p_Lpdxph!6QKbRvEDZhC98Ol{XX#Sq)7TG#C z=D{LUduYlmfb7f}sD3ic8}$m${B}fd#Ae6}Xt!UYxKq4&?mUWRWy!uhp}n(&;;(0+ zzW)=-EJfzK_PnHotnYmC)F~)4#ZbJl%Iv(=U2g&R2$#nUaxpp#Ed#FzblDAJlJNYvinQuAP*S8H6zo$di_8>Hao>6_> zv@2XY{YF66p*OU77eM*>AT&3k$d$1)*83n86dQ7qcS}s^E#-H>>`I6D!+aXvUfMAJn|8h4|)gr{U1=|NU+lF7q6QN{`dIvuk)X< zTFt7u^Wqge)M+RCPKSZvi=5K;&??lIO0n6g#`M8BtKY@OIBc_3!?VC|Z&Fq6OT)qCV74vDGcosciz0&Bl zE9a-bkng5qKCWUCV1CXk428PhMQ9_EyhHo4IiVU`7|IF7pb@31{u8~?Z;DhxEMirF z_5|etY9zJSSBuhe=V&?ewFY8lT0>rl@;Kf^QM=y@ppCl~isvV(eE4mOE5Cy>DgovR z_Hb^RFL>97T#Tl;@NOsvQ(h=i7ms$wC29{LchMJ$?D6CuT)C~@66yqVp_qA`%E!_d zLD-k#AF+IwzEJ(x0QI=X6gQ+V4B4af1rRolz6iwbpF;knzI*b_9GO46_2>$4qOR&Wq*oAQ7GoU#c|5=$06Ud7@F8ksr=~= zoF~?dzR)8c(HD433OcXya2z_1+iubMueTSz({fd_()N6( zKou_y_RAdK1m(~CI6mEl@@|uNJz_RG-dFc}sAuEI2JD-Q%^rWqE1ZWaL!R#_Ptq5v zfTfWCwGG-j%b{-B6SBUWc0dS7(}m6=l3{| zrqXOE61IZ&O({CRH{wEF@gJOj^SunT=l0=#(q~FT^JFjXJKI{&{g+`c-LGxlp?_i1 znxOwN&mYqpKi;3vU&%-Gfg{mv0QxZzF97|T@DIjw06p;no&(rJrJz`S0{x+R)C;O@ zX{djkv;+MmFIo=jSeqWX*Nv$RP|pjZJR^P)D3e~L{`UPaC^zSV>iBc&kCV_3kg)&A zfBt;`=ilZ(sn33_;&wxQ%;WY)bn>m?)HA=fg6~W9bgHSthoZh|(*UP!_+mug&nT5ufoX%mMz`GBy~PBs2$ z1j>(nxZq?Tb6!S#e)LtRZkF^0Z1wV%Q?)L85A|x0D5)dR65jPPK4bF{e4} zSHdZZRx0I`UCWno+Ba>>IrV_m6`V3US!JgUTvpYo^X0APy+$8JDAz0gHwOn+R@3X%#u#srdB7XjgHmXsg@mu z`p#HC7n|Z$yEyq@tgBPhJw`5{(9OlBgim)TkDa22Q+>NlzTJX+SZtbrd|17by);10DTyrM~+RpTYwc^d+Gu?XBCi($Cxn~{ayBUfgzh!s#LiJrBzg2zC zQJx!ID9|k@HVlHc(;>*h==~paiQbQ~0Sl4Os`HlITX3FRj+Y$KLtfBuAJylFKsEOy#SPLT4;Asd zLV0vIG-Kl;|CDu`L6Lh6WXV558?Qz%_AmYdXuTf6{~mw-b^cTJ&~-Qdhy?|II9dNj zDO^8myN=50RL!IFIr*?1C7dEOX9cI+I=GsX9iC9jX{(l~@8s7jH9`IPv&~R{`V7V~ z+bU6e#P9Yr*go}C0%VV5oV#)DN=DlG8+FdL(8RZvVPIdB6TQQEZ(|u>7JiiKb z+FtADIz`FV^PDnGxA{)q@h!QvFveZ>qBhhk*F*WHagb|g{^_s~%U^o42zL1#>{Rc& zW1Q9*I<9ar{}r&(Y3m=txUFKhT8DPETVwo|HI8m^vG`gQw4`XJU2GEHqmqc#eI&sdj40s6KGe7p5x18%fnnOFAfNY&FUjx{qqBN=Ugnl z#?bgbBsan< zJIovGnu0e`Uh^ANIl?iIFnJdv54LT3-*NT)kw89dCa1&vLN;-!mC zj`YaKjdw$u54V^~^Q0La-eI{A`r!@He(HO~ercnfHvcjx>gM=>@~-rQ7v?tq=wj9X zZ^)Y_|Ah95=!YuU>1&8p(E>E@>g&nhes4j{_tE>9vVRif2{sPpOY8)F9!Vr=j&if0 zE7kWJ2vwG0ke#ADgLm>r%)|Rb5lH1KavZfk7D#TSADqw&JYP84eT~W+#raCdK|j2x z5)MUd_HBhS=qcop*}tLP_m+@{&w{pkIK>x#K{>xT@-P#Z@-iE?5iuL{8p^**;(Z2j zZ3I+3kB|>y(R}n^EhtmXfVTO0$oi#@aog8rTR@&+Aymn(KyxAGFYMo#hEOD%MsY+a z?3&ktUlDnfDJl8_}UMP8&Y_L+5_`nh>fE_Y{y zqFzF1)x}e+ z9=zv9#Ae$)YFD4W_$XiWrTzcs6jX!hyeY4vbUqr>7mC>1y6ErJ%*uG3Y;pR4DlbwA z{hn&pp8CC!v(fL_?4Ew_wdeWX-f`&nc&vof-{qMDS?%=b_e`_3P|vG^{?0zT3)xWm zK^ESDp0lxgN728D6`iR+x|kaMhiG#bsxNz}pJ=lV{ekL4_rLj&g6{9T`{;hn*A4f9 z>U%JjyD!ve|2R%ldR;uHtU5KJQ$;sI{>hVWOyOejE>lV;&ytT^Rsyn>m7tvCO%AI< zHZBS6vw~3VFADkUdQ=}am`pv7$^$n++w&ZiCuOPJ_RQ7FPz)OkW$HChRk%j+w=Ah$ zJ5`pxIKwNRL~Ir&Pvgpkj}O^oAT+DCL;JCKT32uCJcp{VNr$+{g7i-Nxo-xijFcJS z`r4VCqF*88)#lzSD0i>U?8^10f3m;_D=6QVBAbiF!*fth%+6gb&$lG=PK5g6N@)GJ zLh)u5G}p#MUOxp?3+`jRBIzz{hu>a_?V5u@*biNIIql!*NbIjVz8Cw?4xY#Hum+i+ z`g;P7Q!o37lvz^JI zsWSrCjVY3huA`{QxNi022Y7xW&K*tW&c9h3n$&4u#DaY0U|i>Hc|0g?2PZ+hCt0Aa zFgdY{S-=%~KBKcj@nt0L6Eo#o0#~maPlxhNS}3kdf0uSJ$~z8*?8$DZ!^5EIx{&Il%0ixg1D2BslhN|&uVKBqdve5j z(_tvuW*FkutCOY}hV|bsGs0=&?i=M~E0>LR@<~^fQ;uvEfO`FPf>S@7HOa|#rJsU0 za`aRupSE|JQ~rH)I_l$0pMmm+nP)mh-Y(FlnnrQc1hdfYu!Smii8*N3b55Ys*fVpT zGG(>-PCG1a5X!rjSOh2D2}XU!-%Fk1M}6(&_gbz(`DVQa<%9CBciJ`4$d7bX+O00u zOKNU+vV-)+A(gDqZWqh-zI&Y}%ZB}^k1TS?sl09-MtRQ$#%T-fraWnA?h`2AwkXso zjwc9n${r(5p}fS4aHlTN5c!gPzvV3Ib0vsC{X!Xuc#1jiWDDk9aO!^E7ZIoXK)zaY z3GJS=xQzOs6jz*l&hrn7imuO1)np}gn470Ac`D>Hb2d$#Euo1FQ~MMkssL)Jt$B5 zL0`;amE&Umz@r7!RfkeseLY$HDwKs|VSXXJ3qtF#l>?&-Z(E*>GMIenPT0Rv^6uJToJr!OMum?kj?jjyq+KFGZu=3!BBbaqVi+s$bt_c zyF*|6VeLF${Fz5z{4v+*i$6N~FSHY}#z6PU^O#T1LtgX{p^Rk0sMlyoco3C@)uCNv_EMHU1?2v$HK5HTJF0 zsB!Us`4ynfuh-yKy+3-LlZWO(*Cwky*@E(_x6rlOLG+zaeXY3GQYWQ8j3Vd{eWw}t%D7o0a$KM?ZHc_`+ia9(xPW_0Ct{XLv-6(=<`kv@1G zM27L``t{#O@cO8=ap`qx*BnEGFf>$%o1f|R97x|q<%JZ66n*0uUT^a$3BB%ldtvA? z#ctzzFw@#Wm6SdzYo|@akfqO6B=da3^`lGegQ{|0x}NT5r}*Im8u}7#AwLa+b_V_C z5P#=|m~YsRp^``UfF@f>8af|mf!046)IoPKw6d)Wq3uxz@+xtmY8{5_TV0wAZN_>~ zr_KQRu6O5f-TGgEHfAfu_a{P?pfO}El0aSL$XQ(9lLnG;IArfba6hRE-cZ-tcG|TQ zhY~qm# zUIFD31MTNjiIb}A;j&E_+AgP@uBFa*raOEj6HqO)vJ6G z%BL|0Tx{Acgmy(fsDgK6%BJ&HqN&?}a8JMI2l?7$(7Xu46wf}JMhQ}N^tTLT>r{y4p?SNoUt5zwn|9hx#D67(vg5oRE*7=(ka>=6NBx72 zkX4Tbb?Q3XT)8Ya>mMh#XSc$u@uA4qcnj*=9@y*@L6xCAd3_V&#Sl7cn>BNlQzg2-9_8_U=y=#G zoDY7Y6wbev46n0!whq^)PCOphvz`}#>s~C|iTgq}jZgPuuUfe8Wu2VpNBHaH=yz0y zMAxw0n~5;)@LGw{pRo+_?x4K-@4MKKgP+kqih$4PFYU#L)Sup?zp=u5(-c+4%s~Il z{W_r^XS?#DzgL$oL-W-SQ%^N73hM0@G4(XPCeswOAN{5_n?qAk-lxoSw|&*z53&Hy zM^U`zA~x59piDiL9M=Wf_9e)WZ&>=Ij}Fs$&QuSYS~GDz?f98Ezvj(-8vmBJg!+;X#y=Lvi~5xrAsAm& zavDEut^xb7A8mG_|F#Vl?sTylcxJnk$4Z5MSPX51e#;I$g#Ooz%u9Y*iGJ9QsD}Pm z@7=V)Eoa`BUFVcTr>}O3Qjb?+eG>zOXG8a`xzP^slO`*D|!gK8FYMeb5i>i8|gShvqQPZ zpVs%|$#SeW!z#$1%>3hjj6W^^U-BQldej=XUU?t@+B35uH!Gl4dnkT>9Xh zmeb41L6+DL%C&(|#5xA;st;5jCm+48tJ_0%asgCzA}KDMcsoC)&>Q)6i63 z0d3`BwA~rLRA00>WT{g_F)AsQkE%lPuhr0GuR!Z<`;*M@WFwC6!3WGI?2cS?{eK-! z_ruorG`=sdi~C3MGMMMEunM@Zbd{Ev7s&^nc~hw?m{0LJgYf1qpj4B`lh3PwbdvnM^nC}I+aF$uX|5}_6t4AGyQX-|2IW@ zK;CH`jR%$PK(;gi#yvADFJyx%LjKVkiirBq&hJO{bvID?(r;v<&ew5%u3E?w4!PlC zJ2DH#2YclP8MO8m&ReYjjLV`=UyReHeAl}uKimDDlb0SuA+kJJ9C zD>p?9)X{05A->fC^4d$GIC~z-?KGd_y)!;{?bwc@P-U(ROMQnvrspsy>Q1D1`#dsm6|{B_WC7=?eDhnVTBUn|WlAo#ZQ2>$A;we5dQiq&bkIKhqg=)e>+U}D1 zP}li}{o}1GLfa?+$HT9CKGK$NQXuxHTAstX=Bn%a*8skCOFxl&&tVb zcNv5FVzox1{$bl;PCa1U5R|W-hFJEsqg*V%v>1=_M@z9jRci5cwEueuwy*r>(RteQ z0rMG_-e4XiV|rm8qF=pOjrH7KgYnsHShdl`s?mZi@K)VzPF^GnjZ;O{P8XX}uXj0R z_vU+?qMhA~b|WOlCz<%%0kpf7ALEmlyD$Xtq;f~lKI$!vQ{^6FoMNM{W1QkuA7h*{ zi8;n6k#jP}C%fS-#wYcvW4K#hkJxk?mO6O`>pgkwEY^Ge#5t!OKPJM-ij|La>TUcy z%D1u$PPv@&2-PAL#vk?2&^Yw7+aNkUy z&w+B_1=8y`~r%P>e@s6(<^+zO6AHu?5?pxkAsKMT#mI zmsrOBWc8Wk3;HOH2=sgeXF)W|RjE8QPK7pr;$C+s+YEuG#X!jOH;1}#UMTwg!18kH zV_MHM&vWYn6zfZjmS086JD+Jk27ZG4*Dt8QP`Tao9kC3EN81Uddfp%jV&+p5^6sN3 zZnK5rX0M>iNFRmL<hfr@zr-FVk=2+2@-uuCZzK zH=E`9cNo8HohcZfZ0mR!Z|qn4t#k3@E5&WO!4@#t(jL3u3tjWW^i3u2||Z<*U&=fS#&&KfePFBf(6Uvw0 z*y>c}erq(6+~+1k z5xU>2c$2mc)c5L=ml{xcxG%-~TSLCAGgSTiQe0pp)t{OQWp(;ndpww)Z`shJRDb*` zRI^`0n==9W88apaltEP?^Xow6cg9lrXZnaSUl~gEC!bS&^%T@E#Vtp^l+-`nnhw=J z^f#bYjr;$Dxi=5%;rrviN4AeWvaiRMU7IDc49dP`OH{^|y`(IKnj~u?LP|_ZAzQK} zOVg&b*b>q<3ZYWTTH@3T<&#wKL9 zS`P=6Dr->qa|Gl+$sl*67!;G*!Je_DCPdx!WZ&xfg2Me6P|^KF+DH?2gUcTTva$0) zfp-G=2foDnWdCHXm(WT$*+1z(W3ne+JwW-&aFEZQPT@@#6AkS^X_gBp&f8BMc@&g2 z{6Ti+46$7>$XSPwZch{&)Px%ZAzVBhK=IvAfr@ehlplJ7Larys_oktiVwgz!;1-bO z*n(UveP89)(EEqja1N!*nhXkEXs7~fRdaoR^bxMK9RRXgy+OIS8>N5SiQ7RSb$5g%p4P6R{al zPNm;P<%b^-E*O)4;rr6>sN&)m2Q+FJ!1wc4;zDWLt5&EyJ&;wpRecu$|eca ze)86XQm=NPvPMR`lkv;h}8~q4wNC^5B((x+TBX+@z z_~i!rAAC_;P-#NHuZk}|WuR~^1e{j8bZAbaluN^|Tf-e2vX{TKi9FW-OU z>}5w(f55sPJqoTiJpunP@5m{YQpfXW!0XY$Diz}cp(@$>9q>oY;Sl_h>{fJB4d>aR zNR?v44d_p^X(rJK??y{liC?66Rdd@uCa6?0Mx&oBI0vAA%(ra}KO}|Ue}Z(kev&_$ zp+|nm#~OY}4mgH-P}WAF-dJf4>RIeqj{2A0)6^1XT88^3IMH6K^1{owztS2f+;=5x zIGzV#Rxzj?J&5OouiXsKjWlO6sDx}LR(XSRkOZ>Efuy+$Ab0%+C^mfnDvw@+yk|Lu zCp4qyHLu2>jhP88O|mC;^rQIuDWJHq#_xnq!gJ4Bdx2ukYfyUAo!ZIIl^`1*0&*_2 zhO!V-v!`L!5Ndyw0w^8W3knm$sQop{AU>~!_R1gY4=QW{DAnH&$~$SV9AQ{8>C9A0 zXA}+cNf$t_nHMP4+6uCnwxD?4p2E9$fPC6DP??`aI-)-8iX<93Q+1q17h{p3keu+IO|Jq04k}s&-mWVA#b2Hp1 zK8E~+5Y-P_+*OMFc^%pVQ{G1J5BzZ|zkHz<#jnf3^|8BmK(V<<`fNYq!f4b#=QAEu zxLCT6pGSlIak7Ja<7K$-LQ5J~!mTgCbHeRO09jEG$ouaEh0fIfVFg1;|HFZD*>yaR z5|pv_WBl3nD3i z>4nys4{+Sz?Vyx=pJlnJzF;#6ih$C&dHnU{aVPoNd98$RZ#Gwr3l%+SZFDh?4t1K0yI0g z15~&kpg3(c&MU;)kv+X&4*SaO8cp99v__zuO4ef7VcE@z%3muK-!0_%7S;Su|1;x% z82?s%3rb<<|1B>}z)*kPjLd!*XFBLjBrT0^vn&0oA`{2D*dc6)54oo6m=?n5- zH9@6aCEBz6y#VA7zW}Ad383&Rk{B0O6CVn4i_a0iQ9o5EIu9*&zD(guuYR9OkH!m#zU`^pb~FV^X*e93>C6R%)0-)N zVgTvm&p>WdW7H2TnE}fDDXO=tHGA*c3aC#u_5~={UV!&_`3p@^6g%v}`#f)@kN0=3 zq!1KRuhV<`b&nGDeu`Iy;l8rz;ULfHm#N{h=`B!vYw|_aysrX^FLssVIT$ebE7GME zg52WJZ>nbA4&M=8Z{iQ6Gwb;i;g&T^q(qeef?k+Y0ls=tiF8)4eybD@e6K=yc;CM& zm7rl9UrizM4JeLrqbWRhJ8G!mN}J1|WM+sdJ$&3vkTvUGM~xTm?*zri?@6c6#*`mr zdmPA$wJ}9OHl;mz_`c7frHa0o(!h*%&=iNx&xli7VhV(^bPOnsr#(=Z)*@);v6JFA z-XSLZAO;V>6bgBjB~7K+;t2{J?}Ae18<2bUo8t2{F$F_#)&|+HF{Ib61m#tyK<;%m zDBY&18)AetP2q@*1;sg|FvUYTk^zba-k1U+jP`SF7rnY?7q$x!mJwW017t&qE&=jK` z_Mnuzi}-#Ig~#p(IXib^ozA(0`j*PQU3i+LFO_S>>DVj^g_PulR2F)eJ3cGoFU!$GAJ2eq3~4F%xp5W{4)>vur`jM*r5s0?lkH_ z*+o-+ZB>HG2VFSwzoG zNF(CRXgp8+H4&7aO#+2m9YMDI7d?l$x%7PYc>?k#N!9!>{^wu5|5P{S|IPo@9LH?O z!2XHc39_^6lF*+MzXpQJNmo#Evj#b6 zhZ#ME7WciU@cl&bR3 z-<@4R{w|5W^9aS{ms#6$RIgvjze}$g!7qtMx5)2Xu7rP*Vr#=M$-Bru38Q=CzVNjQ z=>D7#$v+*^gnv?uZ;_vBVL^V1Da5HOYH4J_$7IDJMu^RFG1yP2>g=VU=#e3Sm+7ABG%gkR#m>X2W$Rs{0> zf5I>EBkRHch$)XiN&5u(pE~;FZ+y>!^13ki8PTOP`Hf~A+KUi!6YWVpJ(H&Du^_U~ zZD~rWw9pB5fV<=mJ0ZFygZ$DNAQ#>W@$C0|YVS*Hq5bmK^`mSsM1Aom^-zzz%ShC#vPnTb^FEOv z8%#^u@$-8jUf44O={fEbj+Z~TMgCmSWSmzlYfOHAodR-BzErOrOF-GQ3{;NP)8MP0 zOS$m{Pzv0P>*2E#$nrrq%}8eI2UzcBd)a#)#5QDFnHW-ndVKTSwHZ z*scP2m*G>QR5>eiuaXN7sN{hxwr3YXR~*R)g|dnu01_x21GD=7NfTcaYV(g!3s%9Qlz!)L#-? z>EeD0D;`rnt<8SaA2-K|?)%}3)b5nNpm^(7b-n(F|EZpT`ajJ7ktX4NOYSk9-n*X9 z1=&e~xXOmu#RcRKA10kp@)YfHCsRZ8{y-vPstZXJL`Udj9pQ1d%uOyU{Kb42_^UFKq zx`dLQxK6%HYg|8@_ast1Ki4k|^}`*xgZdJeI-&mfqEOVQT=<#lw<(YM7MA+QtH-f} z^%8J=_BPxXUavOpllb~1z7H^m3AlgE_xB^DUtsk_rLffaDHx?o_x&qNQ?(ST`CO$^ zPUED-J@4^8FNP+*P{a9?Aun-U&fZr@ziNF3bmfBA;KhlVD%l%@ES2K8miV3`KKcL( zpo?-X_V{ijcuXRS+ldwQ`l6j{iTzK6T{Sw~a1{D9H-@k+e`khA1qTl<)i+H6_p$gi7Fz0<2Fg+v(NFK#E@YiTRj6*?3a=5wFTr2_JNXxA1H3T zNcuz=aqCTxZ+i#if}@B+9LU-{1cf816n^O`$h)S4(v%F4HOvN;2!-^5w;)%WrlN|^ z3!(XUC7?XK{KeAmvz zaa}<+fX3%ZFSVhCQM6YbZ_y80>{qkLTrllDCnW1oI$zqOjv$8D|Hc3O%l98; z--}qZ|H}8Eys#GRmg3n1`$v?sqOp`U;CG@O69QPgYea7kE!Hd&G&{LlMRCe1}5|*0WqyEmWMsabj*Og2QuLO5X z@>iV(l7DXd2mVSqT>$?rhjk*q9@A1rej^&;KC#VpV^qz{gK__OzrDDxLQzh<8ZP!) z1b@YU`jH5o{5MG@duN)eQZP+>3_aWk{)w&hhkp`h<-(uU9fV&Je_e-PlJfe%4~cgB;D;n(ih}dshyo?UrtmYe z0gVIU0&YW#IV0gOl#CpZ+qx=WJx-kZ7UWjZ9;Zq+jhj$h1Kz3eTp^8%5NmaZ{byEx z5H23}r}#DWKFsQVLq5WjL7+0<2Imp4oWuDQ11*ppxJBjdu?Lh*{Xl*rjjLuRpP-e; zRiIeZ1IKZCQz)N2JCI+RNco-bh4b*G?x1u)1Lv2D!|A$aZ+VM)Tse!%o821MA=L>7 zg#kwJTl|@D;^CU_%2Ou8UrDoeg39w4(l)eLD!bX4{MWlVpxobu=zS98>ZXE9w_Kv~ z0u&w-6{k-WZe9tB+1=ppn5HEto!?Ddei>9Yml7jKlHb{}kNnK*&!Ez-HSDt(Qp1|1 z6?o$|2xr~ef!yV;puCIrL=|@GLi4WVp9GE3q}LObTH~Ol!xKPm3i&U&*8&RnwFZ^T z8z{d24p5j`vvt+YK+*%qf3c)^XleB`N^g?`Dp4Onv2Pi%+YeCM@*Cvu)`Hz<3(4Q` zAx)sA1X{9y-RMAiNq0~gPX0rBNZ;jIr6I!Q86!bB5 z1PmI}e4nI-3-tz~qb;v}@I=*ID|*2au8x4=5?fSIhkDR$7%aKZb~02idFnW?s-2B| zZ0Uzmv1iQ>qRwO|?nCvnuV#~IqfMwcg{J|&LM5%a&R^RLL&!CzffM4u&d~grQW#KS z>ur!b>zMC^LlRoG zB(C3&=Rh_phvQP(%>lX2;q;trZVd`Q4#3d~Tf2f>tz>e57d=2_sTnp5dE(LDC#jZ=DbSj z=LpzO?rK3Wbewb+=~}N3QptO)3q<%7JJ?$;b#s8K#qWU{F@S)!hZHTiZ<~|EIPq!V~I?2rroH0yc34<;=DS zSJrH#_(9h}&NNjV{onl0zkLDv)MTo9KDKY5txD;iHak>`D@@>jxB)v(KzF9K$k@IN zs=vmaP~W1%AlwhdDHQihS>#Cf_4edw%AR;6N_@<1im{l-JE&Gi&;PAodo@^;&& z(4KXu9XC3Kb}eWbqP=r%p29A$q1G8{IwAf$?2Vk`mZfT?R+Ai+EZdXp+gvvV;dzFz zk5bbDQ0VFbyDD!Zdn*>)huy6nNKbZoX(A~08%%aPz!T(ZKP3kKB+ji1yDya10r|@{ z6Z3Cp6f&Ej1In6?0p%^rKxHfqY!LLF zNRL@d{4x#X-}eGVy>iOu8x7Q8lV?IpV`w0(ykRZMAtsmOdX(?mLGi$ET)$*&PaOIQ z^&`j8#1dv3OMb~_EY+hk4b_BU=aZ&zsUs~qVeHx_$a@x+> z>V4wY1mZr*>uExau#g6vDqZX2ek;G7aQ}t!_;jS7T#DyJveI~l`>bDu=ZKwAl2y&z zUnHm$5B|XOCoG^nKcxt3*fF`d3G9iK*$Vc9Jx{!-rkC0thn-+Xeb1>{K2jB;QYf|q zx$$4ls+u3NDiGlg*H5dIB6}TE$%41+QYo%Cu~hm0w|~r7Z>?G`rSYcyD6fkJ?3Q%W zEkM2lRVn0w= zKKZtqFE?yE>R(!IPwluTr3k2K3f8n0p~#3VHwCLy+t~?|4=$Ea~<;G8cN7lvU`H_@Rkig(PT2t z&sWeMXTrxv(Q5vjcRP@MUxadVcH^ROUW)|SKP6}uu1|QELD#!-C9YriU61Nz++C`- zG9P*lD7=xU8N}3fIDOt3bRJ^DZVPxbl-|HJ!_5?^PBx(2CKvg!=hA`P7orczE%xvrAUNsUp-X;wW0 zhabkC4Xll6o~k9sG36>1{Z@6=aM!I5-@m_HNsc> ztyZb%=Fodxr}lQxF3UHl6!}DZl|uL%2ZUcr+o+Na*s%#5yPN2~9pOqq0i~Zc3&$&- zT9jW?t@Ubparp0b;9PNyNkUQYG(c3oR8qLp<{~!*No}7C65UKh#l8C!Ovf zs+1>$?}V;B1ovO`ScK<7c5m;khKo7F@%+fsUY=An3oDgW@|`chF7moN={X$bf#*{8 zenrpeT!X7>I^}k=YbrUb`qy#X+vaEwVuOxoAAIc&WT!7TMLUx8N~m2;kkQVBm{_zs zb}j(zP~5T!_Cl~9i}otpH9`B8FJ}{vg^}H8x&!T9IXwgIpH;u>5#Y43` zLS$4D%DE#f8Cv5)3iQsasVYUA$9R7h?Q1B(6|xP)7A8B04)^6h0T9~e4l8*KXQj+ z$WLndy+S%=cZN!_mHTUzir0}$(l@i9JwB8FJ;CRyTJoN!ApR`9$8%ktyiqmhPaoX) zy|iYk)Jn<6@n?6u#c>%O-{H93*FmYm_`RwHYnouglExQ6Kc#`B((<++pf}P22jaSY z&~iiCD@(pl12^TnXDFQ!Er1~II6&H(`ait;3TWnSO2@w#OU$iV(5g92=w#n$K?TX8 z4CPQpB~f|GY6h;x?1C2SF9G@BF{E>~L1i0FXp+a%Kzf$k8R6VJ8VJwNq3;Ren#Gjf zV<*VYTmt1%8sN(Iw4?H0nhi>wyg`0sHpo5f@e%bhi56rK+Fl{Oi9R4oD|>!Ie8w_R zSsDb2_umq?bT3rnl>wHZsDFs`mS|9}qJ|StyLyts*G7WE%O{|$l}mcd+miq4fBxnBkKC>w{E2MrQ=$41er7{Wlt;gJXO%n) z>5c2!v0NW|Yy2>k+^T+Kpu;|zsFaJ8$tuNy*E3YIv^BF-axY5efXfz}A%688bCt4J zeGBMU9pOK?^QDVaEks2LDkZ1Gi;>R27Jfy1Gh(T#`5$AJAzh}=a-^#(tw4C!^{Z7X zmd@)`a%bGvgJnN9Al`Zi{E5`9txvQK`IH4zk>EP+m+6_;AT%;CDC^dyw7t z0cE>uAg`SON)IzYq2)V}8~+iMe-~2tIr3k8>Ng5c)q19$SN>rPiqrOh>{<@Uy&F${ ztzQ%muZ1s zvEvN*F{$h!s5}`5eM;$@-H-Pj)`cBNY z-K6kT@`IAWXK3+FNAe4yW}qa~L@Q}ZE;Mr+@B!!DLklvpZl9rf9~ubCji(=+qP zOBRPg(Sqzf=hqwdn~Sysh2q=9rL{}c@`z(*fO3@|$OpX#m8We=)p(`P2#|FXK%u~m z!Y`c#c|BT?K(NW8@X``cYC#JbaCfRGojomRz^8nK=3c)9KCEpE3YRoXNB_tBPxbl-|HJ!_U~t@6tq)f3 zo3%<#KiWy9G*)MiO0jbjvZK3p!Cp#p@4-F_SJs|W_c$P4XRv3-R0%w?^? zexPDr^Ib}y{P;r3kE=DE(hXk>N{?yct5ihavy|Oe==jO0pj^KIkCE1|`pF!Dt7wiyUuNmx)c-;Y%<~;;urcZX} zS1>65t@)mqK)-uQ1M*=<6lECfh8VP)>_=J>D4A)XU&-tB0=fAHpmIi!bTcB;8cpe5 z8&h~;7f^~RKt8g32V^BTDPNBiP_WA&Z9@yEu)S}f|UnkoH0lPLt-Rg;99EH*pXxY{s?Ggl3$@;sO`4<1=U>8D&fvH20`xL75MSVYek~S|Ck)LId5{5!zE& ziXgJKG{8;BuNeS$HVVgy`DVnFhvXl!MuW=v9IB_YC#YOOlZnZ{sNDQjko|TbZ8!&% z7ScpJ(bt;d7uyl-mVioWe^BW3gzD9tzH@VpY9=Pfx}v_gi5)?qn-4wb4pn&Wg(Ec! z&BtG)_V7y^)L4)176{hwA>VIP^PCMZ4I{{(jU zPB-F=pvS6Kx(on$9Xr@peqM9*^OV(xV0Za`4oPY{HnauEwP;Da^WmWy&i^A)vmMT;HV-zSuQX5@c-uY*d)Q%VaTge$JJ(1Nu4KD7Mt zF(@2(L%R15P^{mQ{LM>!P|>OxAXZEZSxWEMAY9nC9TdkM0OdwUL9Rb73?#Xprtk$c zpqY!g1I@DUgUZ*t6rV_1(4pUhq^I`U=? zYsQJ}uYeY#wo?9y&8a-*!Ju@r3tgAZ3Q+kQ2=X^;7F4PoN&Ss$>&U;=sd;Y+jD}rT z{Fjrxw<;$V&4vF^W^D(h&)Yyb*@^U;EyOdl&?pO{a3Rr=(nZpDFWy=p{gD=&mz{S& z^Tl^SHlWrg)oySm!$3iQ0w}elg-AKwdq^ifrhbK3(2|ZHCZnAEB`UXIUPafzXn_lH zRvl=*i5IR{{yUiH@(uOCnR@{XVhqF76Nip&O{gT&Mee)fAN7@8bSSUYa0V@doyaeJzFklC;f1&Y_a*Thnk* z7-|M8PARZ|(u1L72j?flE=ox&L9tmG?4?plc2jOH!Hx>MDq&YyrUO_#@gC%c{&+F^ zKi_|<_dop~#=rd^PC%`G0_c6LhSEQ@u&k8x3-?i0Xh8w#Fnxbj=4I3U9Yy^!WiC<5 z&qBB~gD5Pd_i(-*9Vc9*a9&79I!=B_>EGT4W&J>qH=yT;eO(AGyd6yGUekAD#grDf zVwY(=nc_kHcOl#v&zTgsh@Q7l8VASXN06?q2XdQwk$y+x3CpEIp|XnNM~uXEaGU8nx#W;R*R^se z+7nk^^S%C6D{6NZM?q!yD6~t_p1wy&sk7)i!>&{Kp1|!ZqwfZt`{6z+G2cMp+QTxn zeT#udzM!2S8C$MWGFCutDosQcjr)H?x}ndB1>$#AD?eXjjQ z`c{K!;-#4jC~Ms%cK=EfG5L|0ASixur-_1=4?#Ar801=3fkL8z249^&+u;lHXBbV) zjCc$(m(!T2$DQ7SiF?9OYfR*mTkWI;7yMsff}bLe$HYJJ+(k?T z-)}JiQ|a)OCSYC(z{E>Fcoj{QpQD8dm~vDwO^hv?MicD68({)In`ucC^mS?JBKDWttc7yZRvqr9PBCtR2PeC$cet#ZO1r&7K%Q^RGcQCF4xQzMWG3rTCN z2Dy&wLBW8?O4d<2&$W~;!HoF1HK=sCk9?(%D?q+)KVp3j6sP&qUaO-FL2hOi?Ufqg zgK`Q#>^q`dD^Ji~sgC8i9=Vw*sEogl>y)pLqw9T}h6N3jNLP@{p@kP@@f7LUO5%ov zNYC>xh=yy4-;X1nk0_-D5$*?oO6(?(+d2^BwU5#Q5zhB;ANZd+xG&t?pSVxFSA9@8 z*aY`c+W7JUOOab}*Q$fW+ z4-|bHQ2gXaXjlBetAGEi|M{2iKh>xF5C8Fhss*EDyk`pyGhrY3{a?vW4yOtIg02qi zr8sd4^_Tt;K=#cB6c*Nu?=ob|BZAzN^dqXrWFy;0gLu+zy#HGW?gYEgO{F9pJ~L z@6F-ASc_0l5N3T^q-&g7nK3pj4+Ds3g81yOl!zfUTKN_R6;fC_PLhf6#*T^5#b%B47hUmgyu$7^p6p{rB zeTlMj28EZ#A-z1e9Qkk$njwEBg!~2T?Md}zRtM#l&dKCoQ=Y?qOWXQ^OwSK?T)3x2 z?B_!ZC75;vxt6za-zD>HWasbMlP*0>-1-D$l^u~@TDKgO9l}61s4nv5^w)y&?h;UJ zdYHZciGT&%&@RQ7#r?M&;|>iS)-3x~?5J>AF%D(RF2M5Zgpi zJvh69^7$cDAD2Sl4_WI(^oNuc6|@jT^I0Gp^9FuWu5+U?{~zx^>i*mR{{2Vz=6-Wj zb^GO))}e6-yHC7RHT(Yeqe^L)_ycTmx4vp8IEzh9R4N&7TdNdrYW7yiKQtSzQYs%k z9`SiCOcCz!+)Slly2(l<>ojHwXq~!DrR1wvs}!gAT#4|DZ$U9|J*ceRv_cIRCjSEE zzHX~jt<0#qR;6rx%~mDXzwZW>V()tnD*0aLHzWMWBqx>9w%XeeeyR0#m9o|pXO)a^ z>w@?>k)W`S#=$H0p3rRbEu`n0@>|t(T;+!?Dn*yB$X^ieZA3m@jB#ETs87+v!VIazlaw?EH)v0y({wN*GzF$wRpDOE-=m71Mx+_yi~H_jmK1SSG@gH zD&qnrgqLLosuXXm3sET@of)c9sJHS8v{zvm7)bLh__gd7;vdzE1fOc%Q_0=yAgg4~ zm!nlG`NLun?|3gxrMP171H?Buoq+gbUlLWy-v%dv%~sKO80Y%qMX{u%`+tK$`7aD&iwxSJuMAMr2H;2EzP}9ke zXu(ElJ#EA$y}O@*@MEE`RVu4#Az@|O&@5F;T^@t{l}XvE7H-jo2g>W;(44Jd4#MTR zpg6}CWOEZi<=E0(HJ-g}gYO_p^l^||IuPGUl+9@%dr#xlI9+3WXHn8>)AtuS2IN9^ zQa_?4{eG`F{(O(~Ub|3${F7#UP$`e0-><|r3(-&D+sdF|p@n_|cVz+f7jF51;>%Z{ z6r_dzgHkmalsISN^AJ#&Nx$Q;-!%&o%%cUIgqw`sk00@%Jc{0z#U<1a5o~BeCZ9JI z@#2EXAiun3!ltzev}A8g$5)Icj-v^l;-KNA?+yalTOE+^-4Eolds4VIO&sNic7j%{ z{-E4kk6gNr)L2lAxJcnQj)TmH`c3kDcW6N-%@6RQbdFa+(S;UTP|p2?Rtjszqph7+ zbN;oUxYhyWLbj5=MH5a%eOf?4Jmf|31wJ4vJx%Fm1XFlUC@Ay|1Et+GzJWVK3oG!Z zGNm($r+C{WkUe`0%1dZL1v%k0v>2RA@z?Sxep~_RBcDi@7K6NJ87TDq1}e8|_V`{& z6I=x|4&OicX>~x!;2+W%w6FsIt0}bL)Erb6&;kqczM4I}tE&0m{LjC9{}DESYmDc- z^(kGIirm0hCGVX!3%YHLl}c{aXZQ(zd?T`_r_Et^xxIs7Kc!>mMKv9J+LP?)wgPDG z!)c=S1d7*7gk9&_)g~Hua>n_3w1=ISR#hQCA*&79<<|oI2eJ%*ovwterbQhHl@Ql8s}v`Uy^3_T1K?MP-kS6O5yAaS*7%eHcppMPKCeWZBD}9NL#5}{DqK43+qY`W|6kv2J(A?LFLI)3V+YRk4O_}gIw-)&BnS{X&eK$ zI1ceF_zNiJbcSD%7f&RAv)cybpLh`;T?3_kPf6eW42ruN!M=*=y+Gm77*M%G3)^x_ z?4jkW`$0bK45e!xLEMl8R*x416-^pvz#lFpZB+rXDh;xC!yAC&okpN+(U`P7jW^@X zz9YSGiu@l}cmP`5GzaA8wWIu+D=5D*?h;Yl1q!`afjpZAa=-OJHm(cl$eNAl&eZ%4 z^pqi7)~4Tyq(3$On%jwR;VadfVpcPLx>Fk}$IXeL+|7~7V|1Rv=TSXK<@In~Qr*EI zJHHeZ*kQWfhf$=1$REi4T9G~1rG*Q)*0dmw^qdyL5gqy?UcRCS^7^zO0n->x#}(Hs zSa6iSL&(2~LZce3LGg+yEoh(&r{lRoTF^k;Nedb%6|_)-vWOOlRElXq9#%}{;n#Gb z^RMd!vQjFqm`@A(2s}~NsOJCM|BS8P{%3Ii>i_?418%YCH@=@Jv%i3Blmbe(AAn+` zV4{UH@eYkEyuUxl170x4gud+I2j`N?)5tDHo7Y0d97njN6IT@5LGSj~5`8APeHHo}$Sn(!)` zmntmc5H2^Rd8^XO0_yj+qKylrM&YFQ90$2X+Ngk84}+Ha(eIfoQh^<1b*cZXun=hF zoG=+=v1^>;In zb(#Vy$z4EkYZmN07ZD7yh8sznnSt`hsi3fMB849w1hSd*o**vn1uZq8@p@ujDfy3w zaUi#37qO!ys94arLb0+fv|yE+tNI(MsSGN&kAN~a2IMXk(fbM?1hUG}pm6aM-gBfS zvBU;64w8RH8?kUbx+7ft*q#{P8)U36C|v%7_a|}pT~K*V8<`3g3FH@(HHqCFU&Bw< z{+qi0?q-v4y1y{IEDb27XywOdGtiZ^PlQ<)~%wuOC5fs0-5Zqw2&WosS)k7rJjpe*EtYP*^_Z0pe>t0j2M~>AY!& zKH%TRXJvdpV+}n}L`!NjVmp_HzdSt`9ps?pP@j)C>e;iRTKzgp}MjWr0 zkDz?o%|O252^!zUpRa{_kSyMz9K!lgl#fY^s6Ima;d&&!AgYhN4Y+Q3NlW6bDyolJ zrzrkrYt(~strgXS`#P%6ak|J)Txt!n8%;>xC`5WG@eht?ev>Glah}MRuV@T1T~0=Q zT(rHTQiz&~?-z=R^9|^eA?SZf50kE`TI@ER`lZV{URAX+=jkPcH}*dV?Nuv8B^%Hf z;oQ8BNH4?;M1I`+VDw+5??a%Kgm~m5`)|FX9w*HyKt7T*DCGa+fAsnr^f&x>{zv{m z{)h23{ztRM|2UHW;ia?Wcdl*+xuWTya+1FPi;Z(Wqg-J$zlmkdCHLz@;|F*6Q@;@ zzd2Mh&NX;Gw4C1Q!BsR$>KOx@%nU)_Yq|rD{ek3gjsT^L6 za3#wE0zrk^P?t#h(Z%{H_1&U`zfPz_5Q0|ZiKgH4_ zLFwfQP~>-jTtnJWRC;Gd>0XVe@GKgqD2}9Y@lw~Caq}Ov>G;m{-HltO0WEw;fWPCH zYyzcvV>}f9i6nFU_P#CO7erldI{1dYaf`1ab z)ocLMc{JV+rC}lPQ-W(gaVZlS_d|s#vs6&7{0d6b z`k;Kuc2iJ1Y5{V>R!~k_Pw`L8NI$Kh{G5(}EcqrVwjPFfalt>hZo#)X>VdZ(mWb;# zGe!N#2li2Y#U+rxOl=0g$4AaYz49NYpq}MgUqM!DG4%_cBoN>J1ZArZ)PK0u36$(V zBV4pO2eL3rP)dG?e8k@qDgVX$ao!fYv#b7lQlH}zs=4Ll z**iZ*r~mysdV0(AK_(5??el0j$!^N{*?n4_ozr7^%l5uQG739xEwNv3nD*X!c~I|G z=RH>TdbVX=%hL(@rQ4(ah$S-)Cbv7dJu27c<;IYZwN}Pv`*&?RvD9Vlp5n>p<9w~s zSGN87@?~SQy}LTU%vk*Q#e~=|2K!IgwhVM#Ds)&8F{J%K>y4+vt+bj9t-Iro=jA=S zJiDJtSdnbvwt3!(2_6oEwlrR2HQAzVlMIs?-})DfcT3rr6B=>isqWSDjhg;r68mbx z)yMmUFXY;zsV@JsWi_}9prlk%MH)G$dYw0jMs?+I=PIW`foyS}`WgPt=_{gZj z&l94(2AaiQXj%MJ0|aE*6c5?Zw`4E zt-iEbyJJ)T)>*wSwQ9P$&#(QB;$j1KoL_7gIIQu&#LjxhBHGuBw+UQVmK?(>Kl-}H zrv|Jyb9z{7aluTVRg<%gSgVG&Y&Qm9n74~}c`N@p7&49>(%0@_IH1nuEOYHqqer%# zHLYp?@|}WV&u4wNmzrpve5m(Q^Ipd~=Br~LWf-_Ab=O7xV>C=Ncv8flIazK0`5scf z)9sUnvf$V>>w~Mfi$$s39u+l9@8;fXk>Rh{xYd?sS6ns+n58+mTgaA%mkgFg&tKoh zs<6JX?Ue7eyC#lwYv|0bWM6ZxpWMcIRodJiHs9QD7}ZUiG4v-N_D;+8%D7RbxdZy; zHFv5#IL+$*%jgbPw`{lQjC^0WYq(|5qdHE}yYC&(ntN=E>zG5am3ooAJVtjo=M-Gr zz~H#{!pm#Q#NmD>zGHihP*!DKvW(iA)pgju%&0jjopLn)Zpg{2H-5>GE2A@WYrXdB zviWh(+&P?XcO&PdBWLOpWg`Y1 zJGwLFr&H4wgD;=n=exYNQ~8e8ix#eJ5;gemM)v_DYHJPM9`d)vwVinZn;puYE#<3h zADn-+eS+ZpE%wjW8`|p~;yzf`Dbi^6_+4hz*o|_?^*ir8lUM(<<=UNd{q1@-tT>)) z(c_X^pv|UMX1(u}p7;>8{b-wJd5=pn`n4I{F@8nsv8~sn%#f7OZ^sH(oF4O7C!}y= z-N$*FW=r2KX}<8J(esKJ)1;=wMNOW^&F%Q~Q$lDb>wf;FGnb5Cx$>03kcmzYXQmGf zl)@gLtnF^L{>!~ZPya<`rMd(2x6@#dtn(J`rlRqs%h7zxAs>npu>v@ zRtsLV+BN-dRj;wBF=aP@zp8AM{$}Oya(VaZhRq}1p1qf|eqx;k7ym4|UbMB&K&Q+< znJ@ddSQtKeL;d9LWnU9AUj`nZt-CS*r+>Xg4F|T~I?!g&#OPg9mQ3E?boSH2>~{fc zj?S5rd3=ENb?t`3Z2X3t{CY6P+4ZTBR>>LN_le~h)1997)}QhwX3N?^$DWPcJMxU( z&8ENVEm?0cta!X=9(jK4^VKWYBm*b&R7Ik)hQ_n98`0~@0(-&Qv9Dmln!aH{M zY`f6ep)Olz^qrjADJRBz(zw-5&j&nSx+!N*{heJ@w zx>uU#k9Zab+x9rA6B773E5f$l%8%#v&3H8A?$m_b?RW1@i8m-6eQMu>rit>#$jE*- zt&-%#4z}+fO?<@PDDPLtV1fS3iA4nm9it4^zc@epbhArIaoIORa$mJwapwKp+a_9< zPi#s5z0qO5we};Q2~q4@53QFA3vD}VCB>x3f4X<_HBZdh`tw=G-Tg-#?o{aS>*YS; ze8S7`8&?E8&p2jlb~ZdL{>P~Ce#`T3UYJ}tK`+DbX^fH1&u$&MxHuV9o?6@Vl-0oY zr>yB`>}fIwA)*jg}I;GKWX6S4Mi^bn})VA8D+ZJ z=5lKM7xU-t?=>7(X6M}bal@*!@5-a)-+#Rec)KXIqOe)H?&a=&bNie)nAZ5^!jYqo z9Q3PuZ1Tn4i3zq9=H){Uyvt9_acT9{vhmjwE}!GKw5)x)fAylFS&!wX5q{bI(i=Xp zmd0QEJ-ybcs{WRD0?u;77A0!T+EcQsUF}UP8a*{$-6{RnRn4>e9`!l@r%&909V=Vj zKDjq#-JPb!9}L3Mql?^bHPPzSFvQH}`_d)S)sL~i`)hapxus&!ucKx3 z=TAh^D0@%7O63104}hWehf|2F@em0e2Z%jT^=&3ZhvnT4=;pYqs# zhHbcRz{hBZqq?naejA?rHu$Lf>yn%1rx9{wdV$ z(5idmIR+^iz0Ie6YdL&+kxq8OyY(Iiri^_5bBa$`*u3rEuQ>*)g8OM+jj>-H2Vd2|4jrJZHPo$ZB*HatYw|Y z8~ZN_yt)2dX^Z+pHnbek#pd>-@g?`Ybb8&(FpS)EbRYjuhvU6EA4(0p=H+;Fl9P{W@)FaF6iJlCOJpMuTaZoyCc zjlDA5e&$p2O-y%>n_sVnH!Sss{d^F<>a1Pe`lBD1FSz6q6D^u&8eHD?R>^EJdtG^h zrurK^PYu7lXMdNS0=My13Dg*y%?tmD{r&8%{#iV>ZMG%@nraI8%Ci(6_; z>*bw2gDj?A%1Mg-?DxPv{(GtJm;$d?MN3C`EcjvbYj^pGub;nlZ_71Hc0Tv{W`nnj zUEf@sU{W?>MEZRnFR$crE$VJM_T_4c->={U(?(dVORdcRD2KD+WU ze?{jF=L=gsb1u~lE6DLFZ`-Wo>ZQro>+UO^UAW`sq<_7?-9O(kUKamlw$YZhdc6!1=kMKZUvJ=K-PUELABT1g?~t~o?XmKC zK}v@<2TLyeDJ|~Qrr-1n?H?EBFS(jM;*7(3Q=`>4<>vnvTjvy92^Vea?xbVe>e#kA zwryv}c6O4EZQJbFwr$(qv2p*GTXpZLv#M6rdY(^f&N06+_Fs2ut}f}k$A>yX?WUY< z{sZuCI{_!~1#KC=Y)@qcIC3ND1)r96 zI#2QfK2>}kSrFCBEAZR?M3Gv4A>lvd)&Na1SpXH)&a)N!Tk%Bzo6ZKW=xG~ByyPSH zRM)q&b-M18OZct4dZaq$fRO%HhhRktBfU%pR_wV_!t~GP{$I-56}Mi;q4-*E<%jMFCjR!(J6?B|$zmY*>|ET6>e? z7$F8-@@z_g%TR&VRMf}7peDvu3q`WjcX1K%dK%3iN*N~j9`s_?>v>y*rE@Ve&;-$gT-&tp0)aAI8fpUso= zjZv#{-WoIFcos1)CKL>li_je(6eAaB88z~TNjDNi(X`WS(}D48A===V?FAqs&8Ze7 z_Q&*v0g=%6+3w6_|D`6ugHdgfTe4uh;1S=37EoMKb+r4E$PHIR>)=408|LT`mO$d5 z7#(;_FXdR;#PxE5;Xj*q3^^}WPHv|gOaVl_^I;)4VhJuN z&~t2!SAsac#FzV%1R_+=TO_}?M{Hp59aIdCyOUyq0Wz0Gx%wT0%ZJ}%_1hdxA%|Ik zJ`RCKXJcaIsgah`D?C=sW~;8#1146_{qVOu z3M`ymCrg_2;=k@B5$kKLy>0qZNLoLvJ)zuE1IXlvy0nvbfr$$2R|nR7Y_(>1r6Jx3 zrIN>*>{d~jFMdguWmL9nT?ggys$W{65AeAdDZB9+zX)Z4uVm8P;c<21+@@32T@2C$7!AXliF>eA zKH6H<5{LKLNm$ck?e-%!jXWy^pX>8I*u&J&;ABk>1*iB1H}dLke&AWW8M&`Xvi;7L zRyZqxwlznw+P;^KR8QAZD%@O}QU@h+{qLvvVmj4e+NM!yE%v3F zikst|92@L^qBAr8^EExH#vg@Cm6ICDFa5F%tfl3s)(i>Bb*QO#a4zIu7u!}XGd)h{ z{OZ4%&yp9X)%R_PX@$sn?CTyrYCBLxa<-Kx=gJ4)q4<}F?aBsS>E3mYtZA5^Gp8#& zWoSxYY{~6@pA{>T$7B)RoP1XI+V&iV<*WObinhQjz^ncTbElm7wbR@j#68X1+hRxx z92p>BcsQ|9I3IMu%AV7Bkj)E!e2dz3m;xYBv7FgKK11l!)xA*Gh4e8q<%0v-`k~-v zv~@*_r#?69Q8;gCJW50yu>rEjL>?GUN!GaoAc&Q&%;31J6aXQM#wo<=Zgmzuzi zM4DPAH~rYG|5SWbQxtsK+N$<)^6gGA0=bs*LtNCJd*3;XCEA-_nxnFPH4G1rhNSli z2n;Ib7acX>R_BN0=x0~*qC-BjgTVFa)CTJ=3;AwK3=62A@)I!nVS2p8F-?iC* zMACSjo8W}}z8;PpA!luQB<1j{&h|%rmzj!30Xiqq>(T>53%c`4{A3Hd3f^eAO2pEf zIm8f>Ox%x}yG(GIlIogYkzu8jB#Hs-j}!2T(vk7mDK|3<#n|){ZZkRJlkZ8;b8!pc zV%Yp>xy|J0dkK|YXz`(uOdPb~r#E6A)&?bB!leF@`qwR*M?)e4wzEfjv4UiVjj#Gb@H^|~zdIJ#5CyQ+WAR9CE-w;xgUC-{boJN@@>-Lk`H3oBQw5FX z_J|7<&@9fY80Nk!kB}<9%nRmr1FrB^W!Zppal+1q#(R@+Bwnzxjo8~C{cY9Amd|g~ zovXTGAC?&!e=W~)CmT~ScDs&bQ}0pW`AA=lCk8Cx@jb<1>0eb`1(8PV(!|5GPV#4R z(4xsd+eX_Sqb-edBe52ej^~EYsBoFRWl;L8Md%3|r6VXOa{Yujjzm_4M%T zkKv^79Z^Pe9#PYMv7Tas@2s&w31SX@17+0o(i{ZvhF|rG{&Jq zoAG6NR^dUN$`@+-O+WS?mN!=`KaCx;tBL3FU>O;38D+0#$8 zUUh!fLM>vgIk&u(m}FA_Tc2io=i^Sz#)$?~r_KFrQ&NmvN;lPy3u7c#|C_4E|3%*@ zHSl6nbu;O)L9>++BG;y(l5eYqDtIRM(*mZ#}0#|P) zob=c8ixPLrgES6mQS!pOG2E%IW7E!e_rzz=xv8$p(XySj9gAH8qE8PsJI;)nXQ_oJ z*@4QC(x)6$f|A34Y`J~G*o$X){ivKaDlX{S<5P$khQ3U1g1Rpp+l#xe{6+|j=Jg1M zo+v`X%eA2-QIaphbxSjY7%!B1>VPw)Y-s;g@?J!womsO8xI+STXQK&mCwQ+Dgbhqq z6$as{%pHU}e!z>sZc`lH$;G!m`w&QI@)$=@1{qBrcRY1=ketSsxryshL)RqQ&EyHT z+uO8mEbWK>8so$8+<{_Mzt%W?I}Gj{mhRqA<12N@<>k@sNpI5s=HRf#sdJyV+g&=! zJ)4=-y-hd|-i-;=aFhm#0~-31afBHxsuW4G3NM0qcal^lrg?V5-~B2>Kx@W(10noK zT%IB}NL@0td)dwqfd7ax(1wd1Z2dBK7rR~MkjgM4=8F0io2V=Y< z-1FjA55yu&kO^FNz}#c;eO6@o!BMDxyo0QEY`HAkvj$!rpukp#7D3OOB|r>!u0M~= z9&@{h8uXG-GX(Q9HpIj=yqgxuNn8Re1UU&eTtf)`0g?eHkYK>T0fZpCZo9{5hd_uS zWA*Z<>pY(iEz`0{C^j1NwQcyDAadn>0RTjoQQ4GY56J+O?5}HfF}qvvJP7(u18*#_ zkc<1`2k<}dJ~1gCV#JMVqq-Mc$ndUG4eDz1!iFZkexreEMsYax6@@!&_{5sR(@GRz z>Q7RK0t8V%>K2DaI5@=nIo|gZPvEGS%6n9dys^~E3&>%o^%E=EFrxfnQ0_aehwG4C z*R?LZ_3`7*zdMIunAipS6fB17to9De-{t*Zt`2`G1Wyt!&>Jil_X*Z_3Mhb2VP-~6 z*qzPBdpileC%{8D$zw=V$+mvj;4!1KNAs=wB-WJr=_ao(O{~n}OFRkP2!0xgtt$YAn$9ok$`JdnT}i zJ%58N<|q)S^wC{SN+6D5UYr{e+4N#;`#*+f@)CwKL;pwjoJRPx)(`C^B;6hcsvu@_ zBwHmn60$YK>!l=<{@kRVU&bc=;S;=++8(mlh1v}=6lo5k=NH2~q?qtrM5_8YqXCo{ z;BaP{T8g`MA}29Sc!x;5dMm7k14^7{yPiL7H1$yXIBWnS{Lk}>`S?&z*xG(LZo9oj z+tdCf1RA1d=1!&CoLE8k0$r}rCjpyZ3+qv-y2yqfIN|Y!LI4mD>6xF8N&nkb=~<4j zELjaXDi{jR4I&HpngBI8v27;U0Szy?=B9&ksqMnZxKjrmqw_ZB(s3J!8-FfmA?jziKJMUg7fRWGoWw}5~ z?~W-1%I}zw*G_zIxEw8!BcBw{Wpq{il6+>&c-a>7p>(|Xc}f}ee9u% zkG%+c|GZCXIw3{MaWPl|CiVw{0&=R-hxt}HiOt&H@v!tgt$KX$`-2bcd?KJyoQ)O| z1Tj8c5M^(TC71r*KDls|-9XXc4NljPNmIZf!hNkDe+9s>T(K3@v-Y{x$hi6gNgD0_ zy{CQP!@8Kv-Pi<(Ufh~22|rw6Q$2WTv0j{{5fE^rPRdGkr+-e&6Ur@MtQk7&&1>u& z%VK-BTTP3-!>1kMoiW{xwXHBvW9%1B6^qzWg5So`rMQy)T~?UklzMaA?d{O9R3<<` zqKiz3h$`Dna1Q3)#{3BaN4hdR4(U&RstcJu{Gq90=+nQp1|_+49vXocCP3F(%=XQa zMS0Xel=4S?1;QAr^sNHz4j)UQ2B$R`E`i8LU=|deqF*xM_V_DrxzmqPTrk8)Ejp?5 z%mo$}ax`+T z2r{@=mOIp^B+#I^ZwKxEu078Etb+nW4m8f@LVaYYU~arnCVv#9Jbs^O~PBuyUR$~vIZ^Ym99?T@K@sMj@To! zzko_tD@o$D*^b)FDyWzCC1RHX8QoXpANRD$wqnXQnp(4WZmg9q@hJD5-RQ+P_0a@+ zIx!U*vzDao{)r8do&}EETQl3XEM3pnX*Vh=l4!dTWFW{1o^;eB#@+K_*x zga#)majY~VCgW#|tWPiR-ErL(nXd3uTHtwZ66uE84lZzIsfB8mSfHwk0IxHe5AH8` zI!QCERk;cYL4aHjALU{~6HXr69c%U2=Zx=gJg?S!Y5#olgizxm5a+>pZsw0Etp**Rwg>uUQb#z(lB<-`KK52s0%TkCqU*S@D ziQp_(u@0wE_t}PyIBn*vt02I;%@>Uaw&e4}Y9VM&l-=ppzMlZINM$pKMtj@iTnH_p z;o!g!Ey2!Wr_%g`Z|ZLIzG>=ol9Mmvw!}QAI$ezQ4a5MmbG8_Tl>x=@aceU?M=7q+ zG?3|7pUY7=d`_|)+h|_dE(7VAp|nZ+K*iXAgYojG7^ezw77hxx6=&w1m$DijcVroz ziy|6|I3{Rajw+J*(=!{z!rGn5o^2tXoFbpO1C`-eKh1U^94|3ol9_oMS{@Zv?8Hil zXnRd$uoQK9zphhk7IyUkdQFeaV1B*FRyxb5dyd_kRND6)EzO~ykBY`Hy(z)j&_7%G z!nN-wnaet>D3r6%U3#qElR(p7cMjZRT@1q0NeE`&;WWyW22nMXT1qR}_m>o`X?tg8 z-iSI|j6OwBbn<#7oGK1F+C@1dQLyjzmvKKu2+6eu5FJ_w`+DVt8=bNR zX6(AkwQ>S;#;oTk7Gtr!dT!)MzXV)9=L~Ufw_p7$#DU4;U%O&m@EF;gAn7o@O3!ixKwc9{> z(vk$YQ&b4btd$}r0ok_X$K_Y<0cYx&v|*Ry)YNb158HaknFlvoMw>p(c$k)@ z_+a5b;q(mv2cgoxei2|{HEM1(T*s-&fAi!+_SS$I+S&cdvf^$Ph>UxPDOlad-%0w@ z3=-nK4;3zvPMs~D`PIRa+?W@M{T?{dcj1~i>MgjGT#VErR)2>c5Mrg3PKTQW3EXAs zj$R8x4>n}#+WK@}*EL~MI^xH*U@A;H<8F>nKeS6*0xPrwGGD-~nNxPSr5nGD`96tx z1ZT@Vq%|1DFMson?@;@~^h!G>TY}z3qa~#Q?>GAP-o4tR0cRMgAl5tQX6XKJzJ|cf2+I8&PYsUWYwioixN9#LxG=y~$;?s8zvtgT&56Ms zH{R^EmoOVNz-nuNpdE1xiJ{zv<+|HR@_%~oM{86uFjyVxwYS#MK2as`cxdcUiwKx?bNkI{BcnDPghz1i zHkW)avM;-gnA61KCVLW?G|r483Vwb477=5oF%+1PsTYp1PFfxdO7~@IEO1=`n3jWY zb+wJdht~y>bfz}H2{to*!~Oj@)+ZKWb#X*Q*hU4MmaJ~fx7N=c z$kOy^J2VMk5NJfF{9ajjQ-kJvJu+_I%(wf)n`_`$>8HI|zG*KdJRsW(fn)S9!+ptm z#fi>n*^j3 zSmOfKHQKtJ?i-wFj##*7r-K`t5EB}z5ktgYWeH8QNgdrBR`&8SVu;|TD35Z z`)vSfF~V!jP9?G)bfea9l`yP}<%sb|%-tt&VOF9Vk9X2__X$>H*>*j%P^c{a! zc!oBiNgep}`QbRngEX8JGtz6pf|=I;N1uthl9lOUA^E>17CvjTkHsOuot0_Y!8Trl z!!ZjHjd#gqp9?tP?+@2vZIcIO3`K(%_7H5lww zl>&8OdEF}oF$x|XnC7s5f8Vh?`E~N|JRjy)K&JPO4osgHvXX<2_aK$(e;@7v5VD)B z5$QV7=BPW<;X1$b0c%^&~WZwd>-e zu9Y0$CdYWMvs0x;oNCgyo2vB6@l5;n9B#hay12A-Jr3AMg`oE>_7)GZMKRdCW;n%% z@Zwmx!)naN$%-vC9T_$#1{r-k;#Xc7ui7My_4$IyL8O`~95L22n{B+6-h%2CgLZoB z<7Dr%kSF`+-=O1@h0;C7s-}CrjVM?u#>7*Zi)GAq<+ZdL)Q-+1+xHs5&&ukX2=N6< z_V(F{RQ+B`_p)sT+i@-yZla~H`dhBbTQeB*O7=O-93qq@hy0aRctLk6iuYBkwG*A_ zx^+>qHe?D%Y6&+do5}wv3Q|rKqIB=}Jj{t`4iE;= z3cVk;IkF2M9{8VkZC(=<9*weVcWZ2Hh_4)XshX;7_2%oWVPdJ|XU5mQ%pN`3im#?} zY|=pOvxzUHuiIg}i+kEE+F=wsQ9; zlb*Ff)yK}Hs_@_f@8QBD$}lj6RKsC9K`9v38IUD4KB?;stS5eZd#Y|ob7X6-P}%== zXJj}m5Y!2^7_)7!mdHKnqX?8vrFx|_LM6%yBzFxjAKp*>b5?DtaZxjI!@jYf(ev)g zHG{;k2|0(P7On?D*xNGE-jydYJ#z3QYXCj%pw+9=1J~mc`!Zb%`xlv|S_&b+srYU| z9!aFPT+he0Q<94cWJs^95%X6_XSv_JL6T~5Mbr6`0ixgUNPJ3^#-^3nN|AM((lUxWC zz;|p}tMt!J_j!NVQuz(b`&;;cQ2DOAYMtqsMvR+yk>U{S-4fAQ@oX5>r!J07MOI*<{~Ha~lNd9E z-#GWeyzxQ!IQ_Ry{t5^!!FQ-p=9tMA%bdTpQ1prT#mAO5SvYUVVjvXA-%yHD6NRXu z_wgpexj?e>Vb5`oOn`bJB@%-8lT+#_7_k}X?~lm2-DMUNJa5DTkP3ahA4VV=n$LeP zs`~Q4C(u8Jw?Y2h?M^-$^M{y#;?s%e=IX}TWq0C+!X<6eZ`R*lu&Q7nef?e{@_628 z38<`9=)e4NFZdo%HXg`39K)D0An1n-s;vJqoU9f|777kZ#fxS9Q1V&}?G91m$c z#tTg*0v?U`d^Mh68Q13VYGSnC?MfD72HA?bbB|z&OSXKgzo<3;mpEQ~CT5{m{NT`^ zmeR6UL&Vm?f%VYzP0ky)votbQ+MuWpoc14RI))8-wSBE_4-5hKoA>K9G z1ZfrV01*psk;gS_?JXP$>66_7EiMVZ`APQJiI0#lJ|->(ej%E5Mk^g?HX|WVPucwM zWf;EBK(R`i_*T$Id0C~jZ{ycUTy;#Yb*!yBfPlHXMJ~# zjJ=A6a%+88kr8t|)IiHymKBNk&qpDCy) zw<{b>e|7nh-6MYHZsXz6K(g*~vW7LB$T+&I zaYyeRs4Dua^JDN(I}N1!<6mxDJHZ3ZUwCQt5lzXT|9uy&eom&rL;u`~DM0_T7uN<( zUi(9`DO&oY$ERQHwN>J$4N#-@INJT^&4!S}&oZq@R||6VUilM6+p7RD!+&mifNk0z z#aJvLb_1-x&c3t%>4L#G8XOMm*~!5U=M(G8fxK}3cJn^_H6|oXpv1my;TMggudbeM zWNBxp35_p?pqOxaB;%sA+QXHOsrSY78#BUm4**y?MeE6E(2_J)M_(??ezw~$2$TNn zhqSNE3RO%m0uMOtsHppRLA^kGv}t)Oh$gPImo z`U*fuJA?P9o>uMT^L-yGHzu$y;@hIUH(*gPd=T2qKk4dnLO+Af!+9?ju+4#4*7hzC zHgDoT8#7a*1Ftz-yV~g}nhO!wC3wKqPDfQ2hTdM%_g~gq?102_ecmT(n{g0?Gsm+} z4VqaWN`PL|*GP~K)V7oJHdB5;6biqQ@WPq*LyR^BG+a2t#( zHX{08Jxt%OD3HNSXW&@3E6XmI9|;V&?`&1!Iw$jASrV}@mb}S{x}5oJ z!6tbcqQOyYAwvOEda~$IAhF8FPo7uB2k-peAIyx=+SZ9RpVQ!dJtb|BdY-k*RBu23 z{YFAuAL*bdIqAzM(JK%=@psB}=RVOU)Fq@|o@*Enyl*eM%Ymxy`PFX1aU>Km>Eg$D z*7<#}_QF;rh?O%*ij{%9k<+b(?!`doWc8kdmH_up5^s(iYq;8vs)Z{BZuq;2|8{l) zqT~FCD3|KEKN@e{eDSrdmvN-$OtCMAz3?7`0P*x3eNA=2{|Cm*2J5Ne$EK~xfF2Lq zM|*1VsbuJ=kkkIGP-4=C>zU!B^T|HW#hGCrr)HR!Mcw1>$E%Cx1X9NA-lH~4x-8Uo z!fVf@ge5VG*@I!+Dd&zcncp?VTfq}okeLy!-JP@MTM-`ug|f$WF~ zAwy5nTmg#HcQ+W(6N&Op*evYbV+ZTmg5Af8ADaNvg^e$_TpB81Gn>Ce{9$2b!(9q> zL*ZCU@Cjw7XWetIRrb~In-XiHN+VAs^hfz5vdqpgURT&KL% zzp7-;yK--ifx$`m9<5bu-tTSrROfLSXRYK=lFj@Ayimp|)7@5IJa|qgmz=!?Heq+| zWnLs)cmc`5EtUL<2pd=eVUP2pIodsvy9C_=IS>Y)ix}CfT1;mefIeA-&&{S3tv_)^ zw7Kl{hRT!^V7`^_DipHE0M@>DFiUKJ@OymyoqCUK+T7m9%Aqg?*FE@BdaWxkrFM5% zc6U6ZeO=N__)7B{W_<@uEvKspCy!kp~aJr0eQIG_Ojr=OL z`QX38{U&_zp`Jg-{&?XB#ZQD39qa~PmHrc2s+-knqcSYfqbvL8V=^H#++Vaq1g<2F zK_Aj$QZg(7KY0CJDfNzpAVhK)kZnPg;E{NahK2BS74wrat6*>Jr_-Jk+bZEYfNUAUo;qE*t2lxv|ZFO9T{#S|dBi6$I z$eYxFLSljQNZ(i)^qT`%b0w88XLPD3@*crjHdwZoABnKV+=pNaG(o5FF_0LQ`Xz#C zC=w9L*^gcF!Qc=V{T(q%eUB~t8v+pN+lN zun$+#RbzI=z0afJ$J^55->*0JqpilU5CUg$;K5+l699`1sVV!1yt#ND6F^_fU=?m23TFX+mUMd4=k%tau&^?c)D_j|r8u86l|n~vmh znkii?h?Ms{3tFxaVKLTy(-BR{6@^j-9m;1(wrDXDWgr^6s?c351EckUt#-H7 zS7tNe_oYZM!998XZcW)nU4tG@Rnl4o>vCDCy2lG5!HJ?5!07>_K|E9zp?b-w80hVP7J(~_mU()0|K%9OfbB7R@O@PRb` ztk#1ev2AEk{$S*XJZ{yxe4w!HtrLyTS%cqn1I{`IHL6@uptnpJ8~QXjI^kMs#ma-y zW!L9Y=wWpLEQawEA2%EvljZ0zU5HgqADk z>W~0=z;31C{N~9ze3UWhvpuk}c}%!KDbjzxbs3s<9x-aZuCr*YHzjTWO+D`E?Kwn- zZ~;4QvlRc`hz4AuqpF$cx9yfr$QvyJq>*OXN-QVEmdi$zZ=gr(n(oPncU z_Rq+Wl{<{k$VXhtVB03V;?~|^W9p6rKCBE7g1y(;I_qEnFADpbJaveUrMlPx_12snj zG_zG#+t|v!GcqGu^$Z##qgCQvURT;>6IEN2T0(kOvm$cW_Ih5H%fk+*9#-9nF-*|x zyH(ufgJTQYb`}%MsZwdPuCOyAV7i@W2qP4R&bEyw3NKYvyEML3vf?8ip5JN|Qj3f| zL5gh~0A(eY^UeCe6%|JbBS)j&0o4bVJ2o!c^3%z;#P2FfjGBK{DVpC>V)spz|B|I; z;cL}7yLscoEw94c^mt?!T?zk<2vfK{RN5;1KttnK??JIMHLe}`(iw4MnY;3B-#q<+ z7U)Ixb&{Qq4f?R{TBD{gcf*Zo!x|o}7tx=wMNO;q(92mGHrxOENx5>cCY!cFtAm%y zYGhN>V?4@D;oE#xjqjZp-XOpJuZfU3{-9C1r6W1qwA6>xx+8tm?m&R$wNJEaYvCdD zj&9Q`#{>9ofvLZyiO2D;Vb<`VJclflha`SKJ%| zPELc6dYXTx|MXsbiI7w4h9x1*Q;@7D@gn!OJUF=RVBliMtsdE}z0O912u?v?4psMk zD&R5M;e=6S&0_paue!K@xOvrwl#a5_apmZ(VL{vGQ~+P+TR-*#5@Q;(;nw6ldY3BB zkLZcp3g`8TAa@b9y`|o$!Jy;gk&q*5GSnwye{gv9i0DM8qduNPkXq-F4eyO7lASQ5 zL1;JxvPqP~uB2k!>Sk3@@`3OyZfcl$$X>XVh2zc7Q5BG7cF^~pN6`Fe18+6H#e2+v zw>}f6tT@+#pdwdY_{!LC2oy{!wYpnuDs2A8Nx=i zo93Y~;7<;mkeMNm&K>Z-U*=sFOmSlRx}kkc#p5Cd6XuK54RQbeaN>Ykx^^>Of<>&9XXtWx z;d{;Y&-MGT+wF}@v5)%*3hcPuQ@^^x$Cs&dWq%v&+l2AnT>0EHbcOZyJYZt@IOuVY z!J842TeNGQVq;i@5?I(M9T}=7lF5yLZ{s?4rV*J5ip&-$pZgDWe0Xa+PFr(uRP`SZ1_xQ4^k#VY2PWCden(ptIrcdiWLX-KhbGz}_ zS0kXn6Lq(I5cxXsg9RsiJh*Cm8b>%XLL2U(5@ixX!vozFNf34aS%cFt-pBD!%f;Qt zg*KNq-TB&kLjTs7dj#=S+M3$63TDOfJ8>*jExkDC$UbJp?mzuJSxUKQ*3SsLsk@rj zvCZrP;=g8a?hZK$fC0D#8=g-FUXMoKSr1+{xtOa>^5bHM-?I+_rC$_HM&Io_Mn}de z{UGsudPg*`#@F-hUx)=V$lZV^g(HhCF#^hebI%)v{-c8j-x&89n9z44x6hBWrV-q0#IA7=k;XYiRg|t?)(UC;wM>q@;>A7kU;0xZV5S@FNgS zc1=Jem}?VPYfex-jC{N4eKkWEp6JWywBA#=G8HjR5i>W)gL9G9=#haWp(F^DwnrwK zqTvzKP5J5_Iq(aFOv2!+nl8w%6oyymiFmLOg#BGLbEsLTh#5Qjyq$hrutgkNClo0{xH*~@6&(~V=Vvx+|{oaC}H@ziCxbBM_D~=1{JlPaZUZ1Z$ zQP{J!Gr(nwK5jH0FFiP(^uNbYTbRqXVB^)JBrq6fyjEb59JxVBmDZv-GZa{$x2=~Q zQQJ#f5_v8O%#b?~IV)3US@)QtCy<^;DiXO~URJiV;0d_~*x_O&#srUi>vGCSkCYKt z5qrw>9ADzD6p%`fkmRzwUU#}=Ww6vElJZzWLmtMTv5#kT%Vqj7J9pGG&D3{6V( z3_jcuNyl@h6>Al!er-C|LSdW7Uy1FY>+cjm2Og<<42_%hPc9kI)Eqj;BP@O$uEp5F@) zhwTj+lKoaqJnZPi8I4a4`H#BcaMFXBgJ1@xJoC4>{ebbnB#v>CcRM=XG?vLKD-5M| zI5z9Vy`QcgeFzc!lN3i7bJBx=9~^UaR^IP=?C^3(@)Ng++tSL<^RF#qO>tNG)i#N! zF}aQ5&?^j)^QZSgY--@`j`oicK^~I@*y(B1L9Cn>>RJR}dI@alW()&j}3^(y*a&C3_ zUYL?P5{p(yu#W|hh=^AdNSA#bY+WFUC?_Ni88_vxe#wN^nVh&kJ@okQWby{@Nz|o0 zS`;T24pi^$jGYmM?r?qhJcT-J=d#SUoxQR5h0?wExNnmWN{Q`@f1Vg~Wg!u2;mg(K z>~rL$8T?+J@ODC9QWo_<%Xbn&rxo5v#bY%Ojoi)8eha;3?0;P~{S;+HnWvq{)6Ete z-SBarkaXg2XV5EZajSuzH!~#fxBJ}xXFVx;qvOc$^deoa2P>Z6059qg`K6x7p%N5o zgsThZiozDHwX`ASH@n21{plJ9ovqU(z)1Fayyrf}_8H@1y5=DU$tNx0Lw+=RmNz!@ zfTNy>c!4dY;;hc|r0;8nostlv#ZXL|15tbcoRqy-HaWA{c07OCCpcRrhj2Js{ZFGg z8@*re{3=uC(La)?-vLUCq`9q?hm~4l=P8}Iz8K?93n-AWzOf-Uhm6=HEbQK;yi$im z8Mt@;lV0H}&NuT=mcL11qjHsX;%lTs=-y-Clo{h1%^+|hGnK{Fw<}>$CUMc_$$kX| zaiN(ggus)i>LcxRe87 zlzF099S|+S%>@~hQ2L)c`e#xQe7t+!b9nF; z&b!j=c2|2bnvNA(eV2D@X*f&Ij5Gq-bN7KUIS^zyk%PT%Iw6JPT5MfLf?ivn*2(Hwa}DxNtfbun{{PW zSUxV6F9`9%&D0?X6dPbi>@S@ZJjxpG>+70X9)ER+8~x9HV<;<-Gc(7=yLzY(D!7uw zxu=1oT>upLLBLU=j8%0-cHc>vLn(U|xE6=MXZ?6>M!I3C+lAIbc)kk z7ToN0{BAu{{Ear<_^$*bUKaX}5vpMKPSoP6O&{|6DaMjQ{6<*ZL*pu`$}ejMHCcjOuQ~^2X<@$_ckZ zxzWscMR{^xGTpYHOSei;bt(5TAPj*a0M)Sfa5LFTCC1@<5w!#?pA;Y1jbz_LTZ6uf zz@{yo8qToqJCK+$G10YwP-@OXsM~9Boz7f)S^X|{Sn}m)oCNUso(vBw4;*M9O4JL{ z;vKOFcbkKyc|t(aCBp`iEW)4iFlL`biN?r@$Sr2 zWiv;BEBU7%BcXCGGM^U8(;xQ&mSucHA)q4p%P=01kS^1mT&jQwP%5BIL}!aV!}*}Z zj$!zdfQ9C3%BjDRnTIx_>rU}RrQ+454955bzO(;EJAK9W!W^q~f!N0y_^bg?`|_Kn zej9vZxnJX(8Vq{%#I6{5QyZ7GOqyvO}= zHl{;IY{%B|gn*}0UPtkoy(8PXBlM@SFVI}hBrhX>ex7e5e2C^!|9OagkwZB)-Cp;J z3Mv3w-Az>iPv2oUPfS}shP%mZI&ZvE`-vKofO ze~MW+406iDOI|Omm#|oB2LL@cklK-7|0j%bpe#ru%mchC4p1UYRysA_X-yLJHMJzu zFbaG=Pu+^{h6<|9KE5{e)D5#-xy#h)3}W#^>30z=(eo=(44D|?^3KRE8b{qmP-Gib8M`Fv4lJh(P14(Op2jXZt8PzCf* z50iI=t%Wi3r5CMX8$cWX(5H$77yeLH!*;oeMz-B!93>DATXD0Li);^O$zmMr9uX0a z@qKas^ar?=xKXCNw~#ew^k4+kpr^Jrh(O2QZJwRi1gG)Z-IbCbdfU%<-gdQWg>eqf z7IY~DVdKQ36bW5(BB>i#clgObLs|a7G=559gy*d9f}hwwbO=Ef5;;oN zAWQTVgrFRCtY_mgtG%m5Zf};MOo}`3ZUh|vrG*QA@leeSqB-Q7JT1q$&&lfX&g^Cw zL;17$)T{ZG_rq@fCmOMRarZ}=H<0Y%v;+u$WU>(cmpc*jrtZP%n&w!AP~6u!0R*!z zWc~5+eDC5xHNAC`>lz(-ixqRaMsQ*r_j$@~OQRd)WNfZid2Cn+Wuj5W4|UfC@`jWA z){-xPAG){cq_nd=Zmmb*Z;PN#lYL89%KL^3fXFCWU9%Lt@ar7g`C`tWA~1M1=Ro_Y zC&`z?QrX)&)ZJ*M#DFhZcnI)?1Pd%2!C}JTDm;EP{$hbF>B0MLVK3wVKHO#6 zeRk>su!N;rG<;&fxlm9Y5j3GZFw9rJhQ2oiD&l`WwCS>}2b{BWu8`;ZIcc~?x}(w+ z|Kx#5jbLOE^pgwn9Se}!IY+%+bo#2o$`7ACz_!-Vr0BO9y!{zjN-=(y@T)SBM;{D` zSXtjNDfz-}If+JE4DK_{Pq&xG7=v5QtQO-^IVryRW1A&{Zb3rrP&=z0JX9nW zu56B~h`?s_n?WJkY%R`NW<)$h#+V)pJSd{zWx5qKN5ji(jV(f~P$*hK9PgFkJto^f zDeemRgw$=76^oH0ZhJ3rVFS0VML5;IV)#f9oD*=FIl}`UQ>@kLd;|y`<$uJXlB2&g zg+r4{wuDBSX$P;Yuy~T(W7lg$3JZN!Le>Bar?r~C&t_)i1X(+vmAUgXP1fs{`EUvz zj$a7rCpQT(-a&5TlWshthnI4Umb9M9)=-HDbwmP_mmtA(ZF76;jwb@gO3UO`$+uCysu-1)dg%68^qgPl;c ziirtdblpXry&aWU9W%8_Wc4jR86QJbxmn9yla!8CW z+eTRrce5WUqVTZ#dy+`eU6ELM2LVbtLKL7U%9>#h+DqLS7T7Y~As zm@KImt0=MC;4?86PqOjQKVf?Uoc<1Bu5HtLpQBTu>~9X^sqmV>cHVricoKS$&V`|Q z!Yod@{j<%N@ z7=7!E7P*7STMBr3IEzlh%JJodCf&HhO}^bxeZ|&JDoS5?yehGXTo4Mn!U9?r`XByuZXUCzy7~=wKcqRP7StqLxGzG zJ2FwfJGAy~eAjTzifZ0wYPNYj9)D};wgqop%%tMlwC-ixMNKcz>o6Z>$9;txs7v{7 zzP%LhBdz-zBGT|w6Ldp^rz%CC_-iuw^H*<9BUN-9ry;822|Xsy^({ssQ56}A07y}} z=pV|yk%a@dAa$$b3}3UyyA{<(nZCZig1bhu6I_quKVGI8h;rh@PHHtdG9Mf{!znlI zl*gUJK7-6IH>~-Y9G=kHxYPKVJKW_B7P%Sa$UJ5*_#AWtoFrVymn26h^Md!F*yqYj zyUQ4h|9cf$y(zZV+3emxpS$|J1(iSj_-En&HEQWB(M}tM(ZA-HV2}*95X01X`47(0qjN6E(F%UUL1r8&^5FgseQEP)O{We% zT>S^DT{JjgWP9M9^2mxe?Tju=2+EW+$B`or z!;3o~;!M7<4UmQfqg42FPt}>0qK1uW-m&~D$7i_Ra!Pya#>+~ZE!IW}Biz!lD1u>l zem-Bb6L`zE#rvh(^UwF@=3v(bk71$S3pl5C`C!Q+5E7WI(FG=EQ< zo+t*Tuo;ySTc=!KN=#eg<)%NnWqGlQJq7W0>J=KLr*J7rMU9A@k`6d*S-N(oKMu0e zegpt@Ib1#Fn!7EPECKAKICWbVd~kc>lMl0&S8ll;y9{(VS2N-sZMo4SO`ocLu_J&E z8cI*l`MaMCql+{w#8v8(R#~{h2Ij!dsbPAEy1-a@pMIk);|{EH#g4gvH*D@19Ra&r`iK#S z&xxQ-(IV!%JHn2y>-qGoo#EuE*wFbk3=YvSiNlYQe|xYFmY#a8wo73;YB*=ttw#_wqvM?&;e=z7L_~Y9Lz3uD`~> zQK|U2=O&fZdE0Bk7!5Zo(8Yy}hQU_=4akBTBqAxlyNw&+Kok58qsEf!^VxE$BW7gb zRINx&2?rqixctF^r2cmO3suRLwk;?6ioTD`IcmvvwI*5GJ-@b*Gx(i|M>>ex@b;1{ z*mC4W2N7hO77{$#?|Q;^dF^t@Jo+a3Fjne`m#)moWdn(?5#+wJ*Kjt+*3DJ;Ly3)D()^+^-Uhd^&3q}__0 z8yRb>e3=kb5x+n$MpKQxAyJn#Fa%-OyIl$@XW28>E(l18@EFE?V&|y8Q(w1yDlq;H z_k45ZtZGy=rJA zJQ|uw_@9gEtJIaV@n17(48G;gcVw6h>U3V`SWs5-*q-n`9?Mjsml7@o6%6eD{>^Q{ zikCj$Q_Mp4nR_%ewV(fAXd5e|aA;?=oTc6n%E>6tHUB01FEkSZRhw`3dh-WEDtfZ} zyUMeTVgWM(yda$yUDX3(;B3BHU@;h7UQjM#sE`Dsk7$Num0EVi>z97uu<=U8$Fc#_U?2p=U=9&rqpUgp}GWu2GcM0 zRk17^*rss)Z;d|`Telml?$uBVA9E4{d|YSD{dX6>%o$054xI~5ZJ%h9hIUNHZ{+nP zH^I!hz5T-CQ&9jra@%THExr4((FC{rfM8-+#?-rLth1M+w&0Dkz5ue$stOzyK`Pk} zjHcoplUkYCbMhl!_KP1?wohpHPw0ahtQR0yM%HG`Njrv502;YY()q#xY2QR=@;WY-bj(e>#Bahk`li>D*ASgBf&GBA zCDNDdrt8P(R7e2H`@}80_koB$tmo&{A?Tld1gGGhur{zqVTN_K*=MsO;QEzd`OHFh zB&awKE}n0RHdaeVePXa;QvE)v@<)pmztUN<)_@vxdhqsvzB>Wh%M)w9t<{hK`Du^t z<4S;mZE9lEd!i$K@6qU;fRkb76wuQW5l#9jVxd2Kwx9pEP*4gl=ZV!hK$;60+WZ@i zzG?sO7TxRIGk2qJNQ`Jq3|Bx#31_{Pw2jMxcY8*N>-GpXV1ustEcYoIS87E3g?+GWHod(|DviH6eP~zJ zYalJ60qze4NCGs~zcg6yj~WXK%s);Cd&v&O!WEiiuwFyjIdHSb9(+2Xr6TN_^j5BckL@f5ZEo3VAP#>e5!`^kDW#G8yM-EJ?fq~NstRiA${y!T+C@$16 z_}6bo9x`wOjD=uS5r?NU{B6e4a2&xY!SeW-VBahule{=dM%qndz2xNBi4CfKvZ3he z3i6?$JD_NTgwpv-Am;eejozB5>Jq+}_)h|`s!Nx^BnSp^9XW-O;M&|}*;MjF)ybOr zV88LZB#QWPO%C_5SN1Q{CkwkMni`oA?va^+%1~3^GQ-(X(_}^NE~~3%bX7*|yGlm` zIGkI^+Rm($f5)#JBV4|U?|D0x>u+TTPpD7}ZasMl>e3;F`$O0JwH2Ns-W?m)s@-qc z1muEA5t*>gITAoQzD`aSLl-o(0%D88QtYOBsXhJWjQ$V8fW~8(6zm4#6v%QXrVj0y z$IkE|yCZA5xl?1gSCFXfWnJ4&7D10Ed<&}AJ zFxSfQ6oLOvytSePo835+LbLRnZ=cKHbb|!u#@FOua1JxhgqU#sIRPs7(pkU4HU;Jz zON;w0n}oK_9B>}e{@}}rE|06Wr7q&!SZ~|6il4`LU!_M>iq3Z% z`qaHGg3$KpSF2-?9UY0JIZHsc654Jr2N5RCnI)Yq{YwmZJTzbN+Spoar2W~Ou4456pZEB((&ZKH`Ngi{BW3uUVH)Z$iMzm77-p zU|QX@eM4_Gk-r__>Ye@1``cF`*8~KI^R}$>#mB#D(f7i-V~Oc|K~!CH& zAP0hV9%;x_AaDx}XDR{;-j?Un-YLj2PrMgt_6gqvBGmkk4R;X3`6opHA(jVWX8|_) zfRJkB*->p?wMFH!N2A2FX2)s|f!{s~*so#D>Z;f~oP;Ay)NvD|9Gs7@R{rn52#aVM z-aQKobe6^S+w8EgY<+16Nk0Q-bgq-)cw~^yQsP7~WQbCb;osd>|H}f;dt06U!Lf?7 z1)^Js1Npg&&L!!*45T~10A5F*jJ2@XU37GW0JxbW$_FD3KdlW>VS%M_%hwVrLf;UL z$@bHS`|6K}S&NwWJEQf82ZN)-?Plp&4Z!SZ@IHlI-sc!_SNHtxQL+bt@O02X+mfM= zqiD~L?HNpJ5=e2x1=Z3Oa7XhuaHfP`hj#3}V8T%lo=MdsxW67T#BrAmSOrz}Yq!e& zO)x+QM&V02X;MNQ>+AEd43k)V?s}O*)H@-%jYh(0v-*B$%Gk3$j8A!2J9-*<^h)iS zQR3Kgd_?1YI37YJ*pvC@5pDZgGDXN#<;i`y5)~r7?!n+n{a-5b`z&BV<`=7ZK-x_W zs*?2>t%0o4jRK$^T`*t>fv~evb%ZokB-hxkNM@etcrO0#>rXf5>&fR9&2T{>hDuKW z)$o!Z@~Hrha_G2$@3mLcL_ODVa`rik(z00xz|7Hq$FSr^J+z{*qcn5Hu+ZK>T8|pC(CltDK#Toa2AkoJV|Oh=uDJBB?BwJx$@%VKQ$bY=iZF~6 z;*!RXNVN4IeB#GSUz>?~dzs>$ZP_DFA`*H6qvcK!D}9 z>a%mX=|!o2h7J-E!0O-Vh4a^!IOwgj)MRwngc(o;iCppWw}daZbC?QkC!VCpH|wif z!eJxj3t&CQS;|af`k0ArD!X7+1!=jG7d#VMtxtrey5euGs*+~l)92?3UyeZ_{eFiW ztEvzVkTdaheB9yJRe9flCjK&bE5@4Vx0mEk0o+-hZYgpaTn4ZKjJ7xX!+W_6OwvN( z8V;tquhhVe`*M(mC2Io1poof0xlUm57DEnj3XV(8*Q`ccEzpv5r@tE) zL(}8&y9~CDR!K+8EQv}3wjx`n3{{$8@xY+A1_IVQ!UvibrHzfWm@yxfl9z7$w+6{$ zGZ^*;jguD$xoK_kHD}7)ABGE6KLglrPKy&{0wu_*0?IVjQT6@(uL0{KEj20Mw&XcI zwUGGtOdX`_N|EH3iiouBN+P${H5ywahwsv4d40jw%d6}tH7Pf*BEgalxW!$;?fTMQ zI8`^lRvGpae?Tj_QX9@JReDc14(G`qhia(rIU*JQPwVPLup(=&SU`cnFZ~$BdkfAj zH1$FA={2%Jm*rpE#ec=v{j0A4DW$4G=K>T-BiPG^_Ajt2{9!oRj$d@v(zSt4_pd4jOKBBZ-byonlU)POf@v~%>Lkb=qmUM-P%MZ<3jDR zlihZM{Vf~PgL=l^LG~s?HU~%hy{17d9BdYPSndp4P6Me-(+@d;7)3^uM96k3t;80C zS}%RKxo?xDmkANX@q6Rdk&J7D?LNf1Qmphcb#EFBeAv7bVu49$143VI{15{6;`mm7 zMlPW*z7TpHHCdCu%*TbC>Sap#eI~Kb$3I9C<=s~toqQ;MFV;QcEh7)&!JEB#l9EiS z(m>h3nijMKc(+Ruc<&0wEgjzrP?xkNO2{dT-`ljb22UNE!Ixq>o{irFMH~0pNUCu0 zZxkzSOC$PH%iibogI%I}Yt;n{5rDQEB*~XuDL~D`Cv75B{JLMC6OM5xLY^^%@eL?DN>Iqo2O$=cP?wG(=_Qro9bWX zuoK$YOXsffTPlH;_6375!f|Mss-LAmYJEp7yE|;WvwdAATxY01*hyR1N5B4KW&Bho zE$?2Kx^3}1Q5iH?+SQ6Cc|YCPcwE#|0k-OYMDTT2e5VDq^(m_aSB<>?n~32z$Nyt+ zoa(-KvFEe^@D6jp-$_vhd*h+oW=;wQbE_{hBHadt{<+)F{LC#B>WTO zQ)Cf^YOi4=k8XmUrwl15G5UULnq6g~{5LAvg7T|cajR~~XZdx1w1{@U>uyY|2_prj zaACd{Zp)E}`xrYe`qTat&W(=7)Uz23dFS{Tv65;Ouc|nW6e-Q5Th&t|wk(0wTFYa? zansggHoTsN3jt5%+DbFD*^SvZi?f8v)I%&+fj&ecrhjvSy@bkYh9GTS@83UC+!btA z+4?$#BI}<>R7ZCN_>IR(EToZ0Y!}g}gtdFWkWBZ6t1S_fM0a<&{5)z17nl6)HbqF! z3eN8lsBJLxmGH6X)Tz%@bAyNI@ud6gj`#_^os&J^)-~VbbiD3&cZZtOL|ZwehjrOC z^Zi$t$oZ*YRSbh{P>1tC3TAU8_oxLNa*4TXW$l7XF)GIHLyBmr(NHaQP7U_b0*me6 zWyp&QLV{)cKbsoi5AC`+QV}2&kYQPRR=!KyO#J+V31Q%WK#?&QnrGvKpm|ORyWQ5Y z6jQb-8caV0(Lx*aFb3)nqL(+;?6Z!4kGJ_{CD823YP>JbDujN3x zjOo7N&##Ti7}+BfKZWxk;?E#+Y9q!%43`GnA`AxAzBWm2BMPtNBU1*XK^xsh zg~uyxgJ2{3!BO|mxFC;uj$hc>pFI%1Hn#3lNeCWFp>}b?;pD|}XQ`N>b z6nP6pe5c_Y&TP-GG+`GrRs5=Pz$c+{6LVT|BH4-j!`Jz1rcxDhC0pc+IyU{2#5NGj0;C%Fb3GHabbbpDJx5iIqac%XE>}eJrJwof6f%0yroUBT!Vu%deUP)Uh`=~E0nWdf zgTskjV|O@VQ(8!qsn*0`)kI-;3UU_pXJJUcwy8@QqSq7)yVEO~{t<|v5Eu!Yh+34cwKl7!O_Ic7B`!yGtl#SmSjGOYE#qY2w) zT9Qqr<4gNaV8;0vVM~AU-=a#(`Lpb;P0UFh)a6nnIv&XNaE78tN5>N!MUX8>s9?*I zIkm-rwI_)E+ipjLE)zou^j9TjkJJ<&7n_klG4bI1=3$DF_&Uz946dG$3&z@-Sb~eD zFm=N}sGFe~3Yt*t3Md+aZynfRaHLB1el{07sx6>ikIg0$8ZP ztaGy;%;L@zqOd^~D3s*vVu>-eY_}Jq&SF1{W($;}LXU43?*vH?y(c?U0F6=MP%pkYu$RB;{6T&r;~3w-UZLCW@wa?*y2mw63kb%VPJ_?gj5v9XvI*T4r5hS;NJ98k750aOhhJ#fVI=O@L72y3$EPfUEfszUW zW{AKlScbCYjFaXgo(alhJ zX(V&H?}?(~s}PjmnYpqoV*nKxOpICWezicTO`fcFV}%^NNs1T0bFu_u4rZmyJySGv z9Z`n~3Ugb!H=YjKtoE|bkCiyVb%=Rhw~q5MyuyYPtKIDe?jiTGNEelnqp=lfBw?s1 zSlZ7f*j7fhz-fx7r%HB#+)0YDqw@()1&;frEeYB+_N@F$%|~?$w6vE$a9g&r_H4P-;Miof?|##JcIP{OER{oxL?l5u1U}NIDHiLKR-X`3V1S;>BT9??1+=(vAofV$3P^4fpGuHq1fkc=7tyZQLPL zSqeD_@)XX57sxz&X=0jxoDn2Qn2#4~8e}6;!~f$P@F=&K$1201D6XNgN|9m7it$i0 zV6oALzGVe0gjf9eiy@8hmc(Z>ndW%F$bdkqD`!lwavb_gTr^3)B^H)KZ1S}xE*yqT z!HlrCylPMJ>loQLg7OJO(hQMM#D8(J^mLLh!aa}poE2{iW)N0&_!h#50rFQ^MA$yt z>Mjp-M6Y)uAXsCm>tFuA8iqINs3I2aiuL?}Gu&3y4(C6(u(C zZ!%*^z5qd*bxcO%HSvgh|N7?)|LJW;p;7~cR^aCd(F`BFkqV=@mTZ!ZYf)<#_IQ*jbEX}?o1 zCopd_lT3$n&>g26(_vohzV-n90;^R!e;mnQE0!J#9MaK` zsb6vtBR}AavlQU}J81U*tpD%)ndJYRk7+3=~`)NgBk%~kNRx|LUt{9{h+f2#ZX`Rz;C3-l6Hc-?WC@d4=1 zu0Fo|Qi@4AQ-&|Z-~F_#{Hq!g0OqM*pRX=<4O#x$T&cDD3fK^r#&+j6&C2s{)AZ&< z%sqhPR~%EP)p)bPUaw{FXY>`x4vi3HAJrS@(4CoaekZ^|KSDl*jK8j4$b;_9?%#rCar1pzIo|E@ z{zTgDLP4s^NiF6xQuXlsfFRC#lya#O6bnmPU%sY_vT;p{Z{t89-lll+N}5^j5q6dl zy9Gl<&EKCCHL{rs^0}`Y#D+FNqTKG_l?eCUhRx?5vR!%845+yL3*9`3Wv)81YG-`C zQXQbiu~qHyOI6SBzkG?^qY%d-A=u%nu8OUqUDhz%{zA+@M0pWD-X z$?|EVLG(~ne_~KA64uOP4;VDVNuAYtefz|~$yBHBYJS2&wCB|-ZnatP8kTwAgXfyunHzd1fYE-^hR5? zU$S9TTZ@PWAn+f4isC3F=Ttp&78#u_q()M^;3)84-8?svoldV>Ij12aW-XTd=GaU) ztWl***_RS+%gtzPghzB%7|_n!8oS@rMqj#+?y+d`6-`A(T&N2G@Lc|9M90v+?g-(~ zKzb@xBNYVJ(9PRYL_>+kd{ciX9C3Zs_$Z^wi)Qu-B&;^D`O??Sm&@b}%ZM&>GGv5O z2JEVFm(44o01dSnldf)w)s2Sna5${CI00#jK{LDWM+-!s*f+dn@6n-*(3}hgIub!g zhNV}xa5z)baeP>nr3KM#^gYe7P%9+U{@&n-ubmpc0$Xw~x1fHDr5ud`J*UOAJeGIT zCfq)NtgF1jyc}J^4*i|o)@Z!^f;cloL`F+42BkDUHn~9|BdIMQCmU8yuWT8BRFFm2 zpxz@nJK$wjYlqMhYX?=2kwtttBk<`V=}3`aLMNd(XjC0*jEDq3%Igr!$lT) z_zpA5W(9?5zqQz$M1^S~%ze2{gFLu&$T|D=4ZKUI)HrG7|HYsEU1cu~abOYNn3Q5m z)I&Dv*sFvjRwDPxO8YGI=2342e*ta0yq$seU>=xHkGE}qg&rOetz9MP4?(Lmu4F9ft~9+U0hhJgWpXC_fVqm-D1uIv4(i2x3L_2SkW%fL3F(|5Tc`Z566-h{q@l& zNnd`PSmdWCKrTbl&g?vsiK zFJ7_>>)n^3^hD>ewCl)@u8T)%<6sje67lS*w*XLTpNjC|dJg{DR$QS^WGMK>;y#h~ zfE+SPwOIk4Q1Dj0&*Mo&jjpIFHuEzM3)$ss<0oxJWf^uu*y>3TsdE0G&B!BquVMJo zH9o0i`k9*Z&i5ORF^h|F-=U!0qD(ShoS{e~Xa0)9}PoIS+8mg$OWfywp=K4?wd zZa1>VDE^LpjQ$t=AmU>ms^2-2WpA9P*S95>Wlam|mWe+1JJ zri&2bA*P!BMro|lPVUoQ)dQSntiF{y>eYz&i05_BzeC2buHMBnl%R*?Dj7rPn7U8PQD80;zTFz=z)%R-@lLBq^V2@pPaX6iPG~eb4D7@I zj+jkZvrF_9T$ijc_GU*~fNCC$ZhBYpe zBoRw6j*rU#aXE++@y@#wNQpidx6S&$IuNM>UhJo3;t&k_FfUESySr&|s~_{rFj!A; zU-Ntzf#B{c*YAlamT^lbj2O{S%s{oN2sy|5m(E&qN7S)Ch3WPta z0;zI~gF-PZM#8nD_`;lWYJ+!aW-ax#R2_sfv%x-$aDzoe(`QGR1?_W#MxI=p==f2{ z>?<9i2Tl#Ei6xl@<#S73UcL@gwNovepB+@_zF)_SJm98$MxQF2qb{Y!PwW=>OuQ7(?KDA&WW<1Zo<1uxy|^)kB~mf=bOj^fY;~bhnKw-ar5C zdjW^1lv@qy>|J;_c5s7j>}>uNq6Nh-|89B!9ugr`&>_0=;RkD^Rs6*XPUK9@BlL$G zy7%GSg-V7b>9@aJ&FcxID%=~n7RoMDng9v~_aH>r>7&9JXf(LSt&$ON`Fehq`~#7j zaeg89g4*+4e$TVj{yFy15Zz^MTY)fCY*Uz8oMo%Fg=t>j6dOED;%wwcwc1m5VoG%V zK$dKUFr!3Id~*+ZxGQYhw3^fPbFJWpj);3cmGH}Y3iJA0-Ral{zRh!OzJFv09x&>5 zP2k@mZ(T;}oL82sU$WY zkDo;aCX1x&Ex_=|MzVxbK>+|i*>KMkq3D;p`iU)YPjGU-gnyPWKz=nc_w5{-oxsE8 znOYDgYKKi4=Uz0}bv+Lm+~3j1yy;Y;im>$IP=mhiK{P7nUj`xW@Bkgx0YacD+8{YaRQx-;RTVPIUmi!dTg& z;rZnlE>5oP)D@HC9_az|Q$-?R6{J29bu6~*e^k1TrL6L0xnJ;m7(d@mM& zp7F`A;8kt4QhpsXL|h)Jci7M9Gl{~@EroH!qlbO=Z9nKF7vvk9U*H!orSnWN7a8~g zoAa*l2x_t>=UZ=_wh%t4MQA&F^=D=KIB5SGUFg2wITv1KbjPb`%sDLEq=M5~p8(*_ zwT8P1N7H)Ma~hLk+t6=a)?MHmE0VZF6ofU;aR})ozWz8ktv}Y>lUMM#1ixZ++x0Zn ztrXBhCm=BozuJq0r;PC=($^XG059nI4<(k5U)enn3@g{O+;6_7eiHl=8)O)K!&LRN zc?8@ALlBTT?J*j-jVS`G>@=A+UgtFE?db2NEHj-OMO-C)t{uN}7QIa2a?l3QcDJ{- zZ}%KWj$4RSg#bH=E=n6})$`#Cwal;Ihjs7hyY(e2X0QVfzPAL~v-h+(I8xlzyku%jayPf)gPi|n3^7u+LQhZJau6@h_ z)1V5S{BI}td85=u$lUlr(w{uMckVd`W&z7cd2v^iqWScmsCDqu8|%i-%dp40Hnt5P z5&OhRrnqv^6gZeNCu<-}KR{rVV#f07wQ2 zC33!pV$2+pOAtlk9EZ5*17C* zp^isdRYS(bQeW0eQA`4Ufp3_zb*PfmID0Q{BrT^K;N-wfh{?+|J7ZEFv7&M9oZtiA zp#&TA-kTO2R6TUL8cvGB+c^Elie5#sKZ9!zf3Xm2ldcFo#ilG=v;s^9qTBmC^C26k z$yFFnkUZF%Ry;-H6W4J+eXym0 zJH6ms2iAs@7Pzbm_+3*|9)v6gYqzzs_9xc=@vbR?pWl2s+`25Qg*e4a3H+kr9ME~& zj1_m-j+mgeaDmd|i;#C_<)~8kWX`)3pNf}02`T4n2$LBM=0suAu<6PyL`GpLJ9w1p zMOL<9K%=fbl${$f3ybc3M+MK3Zn>@b3ZIxFT5pQ_hK1x+C}9%}ASpE0ak=NgQ8on@ z4A5mth>2HS;cfpGqQalk?xrIDtLgGKlFHfz7GZ!*nWtI`i8?)LA(k5nfier_w^Bk0 ziBd(aZ6wRIpV*1@N%9X?YROB%CG6KKhgmP+097QK-#WhInK#&zxQE2L!=I{P`8V&# zF0Ra4w#U9p8X_r{nb03BWe%H`csDJsd;6r_CbN-!F|`M4t%?=LeJJDos-B)zQIiwNDY7>#`(g_f#J#hlo z;bebG@h4gY#87>jPG21PG8SDAc6$oZHh{u*f{cq1cB^R`bREK!#jTut zNXrFi{U&a`MTloZy`J)v$+e#4_Dn@+u1FZnKa{Qqmbu+Y!9L0K-^mATJZwU6PZx)2ZzDl~g2qY_8qRFUICT-4GJpa~vTiW~x`Dp* zM&o=4z5#ru&0Q~K`yflpEJ-I)FC$Ouw6YMH^#9F?F{75q;!YW}Oh#%tYhohwPn z;xLWw{1rpujaga4^UWK1MqCwDnn6XfjY8(kPMyZbooBg9k&L%JEpDJ)uUU?RuQLQT_x|4@b-&D8v|EbRvt+tR{lz|8?E_ z39Nc8fNblBYDSDw<7mnU64Y z)8`b3|3<&#X_;{a=ic4VFg=!~1Re)C3veIe;E_kxjGj?NH=qc<}&^%uS=q$hCbi>c^o@ETNHk(8&zC|S`@y$WB2hDt332TmKgJ283{iG8$%t{(QyMd^(z}f&J;gc8>W7ae4YP~i4m`3aBX%0|c$v(VGWNa` zfCZ3*@46V1MMsmuB(-Tlrz!-aZS7=kL2(X7c&*4Y!{r!3y!Pm?z-BNR!v{$rkf*=p zg3Mk<#*PVAX?XZ}2IvyVVI?j<3r`ank2M8oh&dA_++9UoM%ICf`7X;& z3yg#O8&5*DF{nn8ntGu``r5-x$h;$sjXveicX%LWskrl=Ps1{u_L@Jv65T>O$Vf`R zmCsIf6{x;niQ-BIX2xrsh>t}upzL>@3gg|Z`v*2{#ndlxqurZF&@!LK;OjJJvKmzz zZqJE%kl`hsIHY4WQ5OHunP+ru#-^+4zvoUag?i!uYK>$oFpSuKer=`l6Zscpa+?gtDc{`HJTU`_j{`@Q)emt} z2z~`9mo_Vmpn13I)>u*J#wX&!q*y%v8(7V-!xiuTwT!RKEpo83q|>#^ZsTQSGNo5z zQ>y=V=_0@}w*pTNOL@h5_0y%#*Kqf@JOy)&s`Ih|^MHVh?27GvpeLPmrN^VYj|$V? zoA~rAK5W0_=caC>e$4P3h0*o)6AiDnb+wP*Y8`}zo$HJ}Cc_kB3i zX5a46;6D!6iCYT^pBk(07UX&*1{lNPJR_S8jcMx~h|p!{W2g-;D)Hs@9>UO8j~bsl z`xnNUL=G(N$bSt_yN=vsa4gXT*T=+r<4JEUTF&Um%`V7(^0zt!wU}zs>3mqumfbe$IGL!}^E`TG(qH2cJEw{&fz%*XHRe2_hxoFhw9pb_%|``Nm!I=Qd1P z=xcCLue#B4>)@p>URQ0Hz)v=I@po+6?z{4S zO>`i(?j=tkVrsq`&{hPj*QI?4g7?_Ag*3_}Ka0ca1lJZqFzamT3OPnrY>K#5t+Yl+ zwys&4m~!D*!u!2sA*-jX4IFy;|9j@uc|yyuW2U`!v_G0kK6c_AA}GT$Zxb{xF3;qobEabcg#F(W0PnTrJp*_i)edJp&Ar(97XwpMqGlFjbqOaoH&)J-iHZ1 ze3!njR=sxd;lM={Rw{1xfP+SJ&kOjwJZfVYSAn7zlz8~!{P{u}c}vPqLgX<9`TNdqfe0z#1!y^RYU3tJVtwrz^^MlUWBmQ*0Bxnhm z_fP9Je#g9Nr?cgHUhDPtSTnQEL#a#9sv^ZLX5W}fgspp0dav0R$eT62NABh7CB#PQ zo&#FK&i*Trtf+nt&Na?+Ki&CrIBQHGvxj)lFY==f5)blW%PvEe%SXHBNe0cL27&6k z$AC}KT$9}TLmG>#%@WI8wCiA55vbAEYuAB4t(d)@P5AeW$lQg8shT5lJ>V+0u6-8M zw;6})FZogjXoWB3djB=9@hV-3tU&Q@nZqErS~^?fdUvGj#wBzbxYgL+(PW^K)a>W7 zcb*;F*>G8O9m>^VT)7MpBdaWW=L}Uz} z=9JCkw8Rlhjk{NyPkDaB@Qaw$A?)%8d%xBa%mAV1#vC2-Eja_lC#YXjPd*J#D5EFV z$+m7-ph&Ngard>|rw`_(MUy%BvX8Va!wDB?F~5?#q8y{z!lrefm`Oj{Uxo7+kf1Fr zZ_`%#9ag27cRd@C^gRC3dM?`i;w11}nrM&6O!^O+4{qKYW_&M;rh&1Zt#D%V_YbQB zV^^p-?r}lp3T-}g_Ig5^U&MHmo|wE*5AWp>-|K9-YmFymr{I~GV1T!??ZmoqpaTC;h2i}{{%srDZlc_ z$&)K}6}+^)cMpP&hFX?gQSgAQp5D{1f(Tgy{o4(0cW^g$v_}rc_84`b9y3PcMtc69 zb0Gs;l?DZ_^j09y^3tos1Im#HcyWD(L0WGu4|Kd{mzZ=SDC*dF6|MmW!4vkW6_yGS z{}4|dEATq7unr%Kk4zkw5wgC6z^{$i_c+=XkvqeSYS2Bl3;+oKgfWC@7mc`|1{sWV zjCH=$-^r49>|8OnVD`2S{-;_kg4-f-X?cFS6a|xZ%C_gMyXNG#Ykt#uM6;rUSJLbP z+=b&#&hz5hy1pIo&SZgJ#|ju7ihdrHVou(H0tA{=x?(50`zsg6-aBjW`-&qh0)%wO zYlb~F%h1~;=<`QWRrV_smwV8;9&{ejW#39m1g-3RlZ5_c7yHb`-*o~s&-d6J&R~5L z+>>tP+`n267JDn7g7)qvM4inon2N#l$<6)YB+M2kzOAr{*Dku>uZI9iT$3`M5mLcM z$0pa$1B*t6eOCjHbL`jyI7z4BL;uOPCl0?8U?N?a=J28+MD=-og`8tCw65(@mA_)^ z>+<4BsQE=tr_k4(qcKUQPrfHK zm5EqG7on8ZLGEp z=-8}~P-9fVZ3e;#m#N`&p%>@wt0_^WKxt=yA4MU*MYU-&OGAOy(eUh(9GQyaiwA{2 ztd#DS2MfHl59T&4+}OYZSZ-Gdsn(wCJinJN4X%y$Z$WgYNePAbRn)Mw_5Z2ttfJar z!fsuP7MG$8q!f38yB27H;$GZ~Tk)X93c(!;1wI^#dvJdD3O{Ov5}x*AsXuswHM)_DoZ2C({HO7fnCz}7V1xO8U}6bl+Nlpp?mK__~RI{ zyNq2@ar45Mb5!4ShYcD^vz*A4WSxTfZqYg833Rf7e2rfO<;is2Up z<>51VS1k*Hd|X`L;y<`8CJiJ_0W7i%i~B+(D{lT}`Dhz%e6hGOS^LR!z;a<9u@O*R z!M{f4azG;PMirnOV5cBCnk;)a`jb=yN-E?iB+#kS`r7iMQ|#FdeYk;Zi<7@nDrwT_ z&zom#Lyy($qa5|%L%Fz0#vI)>prjs3Lg-smEtJkFFH6SqALC!YLvR*ZU5i$Om(Ej^ zvo+t~Q~q49`1m`zjU`u|VFRtDT=$>WM%Y%}DV{`%kk)Cv9%C!Z_E1i~J2JX2 ztA5D-U3XW*nqB3cpX~n!JNZDtR%<^2l4DxxsW2%qe%f8Nmp|DxwNN=8mVDBH+|>cC<38(dPI@M_f(Ob#gviI* zs|-74(LlWd-$E**s_`+`=`#6Bxx^v1O*_3e>U}c&PaOpRdiOOTpLVa-)t~K_OerMG zKy6EAC#7&Z3JhRkfW96ig<$*zd?@XAO?ot56)8(FlwB^NV%5qJ)Q9w*6SMB01dsE?pClF9-1atk3q18a*-HIU`xa-MaT-hC+*M6!>3GZ5C ze2%I7j>l^Z@3MRf$!l$<0=x_Cd8{qLI3amQ)7J<$)#!QevE4=`W=4^1$6f!F^pjhc z!$V0hrV(c*zgSAaP`#0?-`CMAy9zGzq^Id~8)`5r_|B;o@#n8{+GdjlOM|y~mgIfQ zA2NrZWbc#}?9MG$-xR}e4%TX8%hC_t7a+C}(*@su!*hlfzn`6^26Al}Mu47`@e8&@ zpn+rySqn18I14r^0p-0cxe2)uvoo@Co$H}V4&u{+I&o=i73|xOhj~aD_3G@Bfi^E_ zC8i|2m-SY|Y3^WG893#BWQw&6>z>D-gt=}O7zw^%re_@=p z#|>}CI0X%6ZKE>zzH`w$`*s@40GWrq3V@_1tX3ntf5~T?QixI2WJp5=dzh9@4=>i` zBXip1 zH~|N+-5Hax+c@b^W$Vqxjahk-B7>bRb`ZKaW)>sHEQu6x^s2)}9yO0b@Y0*8CbI5ca4aDZ`vm zRUDy@%kWB+m^ty)AX<_rK_W3cW$Jt3D@wF&cfF<#M?l9F;B^jH+)R}(KEt!B*f_^E zVOh=_bfLJ5m#GX2=?P#l|&GF~@ToNIJH{r5!%@ zw7BZ%Z88jhqcrLJ+}|<=ff*vbB*h4vW(P zx+T!6p!69I9_=g!o@sKru^u+8`VYx9l(z?+!wlbcYQ8zlPQx57togx9z{Z>r$wVNh zWaZJ)xU+uBa2-M$CALI>Z4DAi7}zSfsIEU=%CeI8sU|)d(^Kg%L1f-5tSIczo_s(z zy&ybot?ht{62Oa>S1%^E{J9sCM1dybqWCVKc6#U1SpgU4kKB$ZX;u=`acOavtPAgK zAxP7Ir)+r_bU;8(ov3XH`urfFC(fDbDvQ*NFiafDg6=)?G~|tpeyw)k@_Zrlav>dE z^sFE>R8lNsr6CWw4hOV{^|8_KS*{}U2v>Y`t^EW@&AzVOZpPZn#Yg#^JAAe!LW{V0 z22Ut$kcTVlQ)5;Z) zw5e&WZF0ZDMmil1KzAf1-*iSLBVbtrAenq)JKFXZm#Xsj+Y^OFzeD3x9xx|;j?Y@Y zIh#RvpqK}x;tc;AyO>U}nqFVU)d0dau;&62#V@2hW4P|y}nnIg1yTaC~^ta{d zZDmOpVSF_!FK=N*t5nDMN|pgz+rDye()Q@JT5y`Dg5E53X_s(DN2mK0Yy9R#abb7U z>rB5N_teoZn19`CQKup|dN&>O#0VZT?GU#^fL0Y+ieobM;Nc+Y%LjPMJj^9qYh#v+ z%T1oO+xwx2)!(II1W#N$%z|nNgQ{PYU*Zc`@i(}yw8NTZmp%=8ceYkh{${nvjgu#(6 zS}hC4RA4*7jkY%i>_R~zO(QkCH8|D}0-m2m|n+85M-GJ+3y$#eU)IuWdR z?MO9cF9IS4J{lmbnHmo?uzi_g{_3^G1bA(nfhg}GOs(-9Ppy^h&g5k0>bQpF^=^vD zmPRiNeyf7!If!`iDg8W|7q3qO%@UR3!|#fT&~>^8tCIln62%(*%Z{pup{ARV91dZl zfI9L^%Kjh5SnO)VYSf2+&*AZP2R-1?yB2~p)LD5s`YW@E=Q7);HVOYv#xw4+)j-J9 z&&n0uyYt1C6|<^9NydorC84Q_xNCu^%FphY6O#g6e_Fg=;kMP!zM`iT*hA@a$|V=k z;_upO!E|YxOZ#{e8Y!ww6csuT+vu*<2_!VRafK>fQuT>so3N$wM`mj`74$4%)_ASw zdz}_zm^F`yc?~7fvMY+E_P07>9Zx2k`C}pCoXDF?czz_#hvDSd5zw~Ft4NG^U}-K3 zE{|o0yWD8X?0I$4jy|qrz6XGQP#BN#j%rk5l*Ll2{?TU2`H|V)l;2Rw-0x5s2hT=$!%R~0nwXP z2sRXIjc-~Jp`R9IC`~ZW>5*1BQrGY4Io0rYr44~=|Lsm-p2ySH;hJMM9CKjQAU9fz zR$D`r4MCB+jV8K^LwG#k^w2e>CF7=CfLHjK|N8rn_(vN%k32zT(KT~u5g4WjWc)ze z0t(uf?Z$m8JX68m6Oo`mU&Jd3;xE{=@~A>x^Pf<$(l74~^Os&dITWKMp-`0m6CBqU zeR^kv^!uwOOt-O2M#0P3^ea8NqcCBsGP2@v~tv3a6e%-%O2f=-h^7a-@GF)ZXhs5NcZ)8rVg?VHV=D|-r zkkx;_>N=|E`7{(x&}}N-`A}{m-QE678vnJz$b1@T)Srz~tmEJ_M3A(}0L@vurz=F@ z1m*kP_WcY^WV+h0H-Yl*x5SCyhsU2*9pSIHIy^g~X;X<|{)O?cwT|>Y6?XFoaO^&CT%6wRYc#z(Njpf& zk6}OXzz^hA2@kxr+MD_DFB02*y5)=M;EufI@@038f<-e*q1^?a$u>q`Be~lFF)YC- z(7?uX*WCpxX4D{jHdILB9s+h151-n}*v*&?CK_Lv3vtV;gzDj#XPi&0W>RtY%y&># z{8Sl3Ca8^7=$4=Na0rbJ)L~yPDQESvJ_!B@ee$&_32tjmu(|u8e7exAW7dPc|FDS=EsWU<{F}CDP-G(XJNsNs0SiYpFZOaz9^xk$`x8 znQL>ACnVVv=<$*`gJt^c7l#{U;e>DJNy#b)Q|a%1rdnlOvBo+xD8eg4inXJ{nYX!- zn>3kq3BiO8XX)msW2t7>`64X-E5!K<6Ybs-`)z&6umrk)gLUhwh~~s_8OWrXCrqEK z(A0I%Fu}k88_L8Is*GJvAq7HzcX8N4_PN+Ji*UP3IhYjvk}0)y5p&}Dy2|^VgNA;u z({h{!c6C0G7tc+Xrw33unR-m%W5V~N42SBem5kkdWY=hNwEj%xH(X(on_ns)lE z8FMsZajyg=~4izN=ge^F({Ikzx~+cs@g+ z9WSw#h(P^ISlwM4C z{E4{qrOWWFlMCMB2&fwUA&*yB2>FSK3CObH3Jq0a&qrzrJaX`k>Lh)WvP#VRFJ1~T zfRlO3!zw4j%`B(aE&N}ml3AX*ik_%gfVX-j-Bjsj;3~CCklCK6>D}D1Ya%VhLh!Ds zarE;CQRqB1;^FT5SG9u|UoYMZtVYF5*bs~_i`9gonsQ!Bk77@OVdwX+Pd`|slBs15 zdoo}okpz{!X6Im{6+X^1>dvkDzTy+D6pj!Wls)&y0_A)Py**=x%=Tw4QRaS4m$Fut zX8d0gG!dNsrI}jG6L+?^B5D{0_HbRm=Sj-i{(8mW3*{y}O9F%HhYb4F(-TGhcE=mj z!9y~9J?EJkIoBSdN5z@x{J39}Ow_+VaP46~%9ds?RV}9rEut2P){Dz2vN*8a%pMsSogAan~pGiXRX1TD|u&^=Q`AI>GQvae3%gV5-u$_ zx$qra(v9eL`YKz{kA|$#*bdypMR3WOLaehi96DOh1Fo~786Q|BMJ8ooj(%3dq8{u8 z^qWY$RoQbrA|F&x@2V19w7kf;X9Ge%^edJTToSRUP;U(loTlwqkmv67CWqi4k+$jP zX_{p)n>*Z#yz3uj9v2BY!z->}9^lvuJnC3{>00wsa8D=$vBNc6!u9KG&@(2sR2|O$ z!)o_`mH*d&NA$9*sUoc;XQKL9*+fN6hm)IA;8oCz%JfqI8~pbAWsUbzAZ{TcVQx;4 ZFt@NU=oQ+FqM)k!@n!n|9{=b3{{aT3*VX_4 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/FORECAST.index deleted file mode 100644 index 4fb2f8d61da5c83c6c92df25665f406846e1e463..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZXUKTH%s6voF!5{!jdV8FuIfN{Ba$RD{11a`TAx0~~13yOn|#Kg{uWb-n^Ney=)%0{O-MPzxUphM`P-qQtIye^frQeiTgh8 zysY}I1@!@!dPx6JO5^!B;x6JSVqKK|PFc+|c1)1PCJ_l6LCovb!3Hz?L|EntA~6pT zYhuD&e~Gf(Q$)`dRX^f>8q7$GxzccLS6BZ^Ih3Zi956!PacM+;OCt?NL?zFKi%QlF z?keR>$y!Q26NF0|W8ntO@ZwJdi;OKQZ>%naiH)_Ye69=OLiKN}erGFT1>zK9*j+E;kHMm@#mV7$Gr9g}e{|`R zQ;}c_eeQ3Po6Rz|L$8ymCIlJBpEO*A47%^u8L>n(47M123P%2`Wa47BfiZTNVr~?? zrYS*KlUW`NC@+uh2*W+L3x*!E@ST(iM#}H%nP4p3bP6jS4f}85cwDTTB`eo6f<($G zl~bkngkj~jTw^+~h2wJJ4*DklNV!LNB-7cewp*`U_2pAHmLQ(vCaaydUZGmSLtM1| ztkAY-l@ACtCrI?7SZM#E17SFgu^$5+&dq1R*!}?XulXs(tow3=JQjpS1rz8q9SFt+ zNuL;o)2q30%k$2+1-s4}qREX_3Xi8RX>Mv79VzYXb@qlw^Hw-+u4x0E>CE(mVgKmK Ee^RplUH||9 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/PARAMETER.data_0 deleted file mode 100644 index 3023b7b1cacdaf9fa527c9d63bf6cc8652396652..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4$U|M(G&jF* muO1_KFR)~4nQDf|9`+FLH>dmr0><5`kF8I&zp8)`aurl5N diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_6/PARAMETER.index deleted file mode 100644 index 28ddb9559c2315c7f3d5fc32007b529a24122e8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72 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 z zPp6=2y$kB_Igq#R0d0pWR9`VG)z?Tw^&b*Y{Eo`m9zVoZ)PSmW87M}jCqKNW<50~& zwP6aBx7tA6w=y(-rKo;d0rG1+sy}cA$Dg;E1jVajkVSor^Ca`nrStZ?0W`I}^BESK z;&^nPnO{ko{^10uXS{}NRRESJSM8bbs>^AM6B-B zfwG1_)klyrW;Mk6R~~4Ze#d%k+Ko^|lprrH!F8!iTU@^?Mhv=+^Hj$5Z~BeGeZ$^_ z)BU-wC$&2lYoR^jF-M_&k_!)_y|NQVqaEY9-{E{%}kzh?0miW)V)-<4#$pF14z>Q??)C2bZ?0Ry&|g zU#^#n`L8f2Teazpxbqjt7LV`aVmT;9U)X;&6y+#iW;ssvbLHY$qyA2A-$Ai|;sBHn z&OXqolbnWZVcS72w$o!GKenT`LfyCd5La%t$3uQBuJ46vb4%pM{HBjW{e%Fhd^SKE zHxlw;F`yx|S+_vhEA|LCJ^$Dq%AcnxPMB+?D>qN3LFWGr@`QoNi$$g|C}#=e!{+7| zC>~}+J}d%eLRL5m@?kT%2NdJ)LAksh@?kUfBw6S$GMK9_y@|T1nxg(%0IRN>vUj7ZL=tGbPs}7Nn|LWaipq&s6d9J=v6`Du%c@$fC zg<{_{)7<{6>aC%PwjQ!dAE10t0(mW4HVT^F=b){b40$Zi)dK#%`k#Mu{_|&-{`>D= zc?1TeAL9BG);arVr_Pdf8XUh0&xP%a=1W{`I;U9elv#^xfde}2aEjT9_oBXQ=7UcA zHaq2~`D@_$xj2{!&(nFFmB?2`oHeK1bZqVTV5c7ZHUx2K^m9)2ay0T-8Poy&pv@Z- z<0(~r62@7qvb&e*>cKvt7gRK6e46gWGAZQ^ABCT zFq8?tLcT2t@?t)Qluw!?7Q_Fd@?y6zooPFs=6hL_;sdXa=#d55kwFxH7)$wX-gg*}t7K0ppB++w^4U3~p^bP&<*Bn|o0x z-~GB1n(K=(&Sxu|4nTfpIbsW?_L>3B-7b)Ad5U`Rd=FHu zFF^KjE|kA0zmSuYV0v+GG}KQiFIM;aA|ElopOVGoz6G| ziYSco&$&6txZ9zcaTfA9BdNS)G%|TQC?9Wztnx#sZoZ=OF>9c$wv);?rTv2S7hM3E zW)UtHZ`we%`WTcgGkwKznYsY7F^?$j^APHSmA|=qws`@xakf!hG|_j=$3{T&cqhfa zv3|I66R9EOK0%O8It6WpUsQiE@lPzbdm5+~XM(nWW{NLop?da@pa0bQ`~44{PsaX_ zDl#0S>vq@=$}=C;qx4nv4X%>kvZ0;_wW0en%`j-{?}7HmeW+@E zfILSG+_$_-7Si^Hto3TTpT}%~GV&>C=HI6J8`mjbbQ!7w39x-?%Q(o>Z-R2vPAWfh zgvuWjKs%t<20*r?9r^J(xKC}54^Ulig!`5MzD2&vjQf>$>_hjh$$yjyt&yF& z)k@570w!X4?EaNs?tW1t^5Fi_Epp>NEO%r}koa8tkv!xgP74iECqfbbCYl8)*g33%24FpCfc>6Zn^gG zOT;Y8R;W%+A;%Y^{_FC+}>m!HnyxXbz%=)9e1jq@vG2gY^FS5dm){ODJY={)v-6~mQ_)9a%- z<&pZhKh)AzkzFkMG4lBmTu1s=S*S`pq3g_N8d+38w*CdKL$x&!@@8-8K58);vO=XP zPUJ)Jqj22EvP{^2*8emt|1bXj^`Bk-@4tWJ5l~gf4MTg@I(UpzuD&zfDW1Gu=;T}T zEkk_r{aVDQGj4P0TZ?x(WxJ94P~YM7A(USmhwmZjK{<}Q*qlm!(rKTaMc$(uwhKnN z-_{VPxc&VMJbd(=Q~y;e)M*bLy69AoS|IrOj*A7o|Q z+;B1Pbe-IH7)lWcO`g$^i9ArpAbB>6`DOa2SgzhumX?382-c@#SG?kuYvOgrcJQF9 z*e>~GGi~36m5}>KBRjMUbJOc+fzXT(fx=Ir-t4=J<;cWKuw1>%59={cR${$�c8X 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�lA)ShE!hxi(?g05T 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 Jcm1FD{|^NSh))0j diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/FORECAST.index deleted file mode 100644 index 78b322106ea469d42e5887967a480f214fcfef23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZ{kFKiS+6vkf-BqazylmLQY_|xmrD_o#W5arstUfSMn%F+!%9JneR3bP?0L4hI| z6b?l&C|nf|g+t-0>KX(|zj-s?yxkqxyScfW`|W%0dw({2byj9Xl9Ww z%62wZvV5s~M;_vmU+!O#>V(K8>`$;OSLVv~0#|)gtihec(J;%44KgdnoDa6#{$R4Y zxjxOtTT>XFu8oJoZf|*+0W7*O5x{j3yyYf7)UXSH%wt8=ISp%&Su4oT#x=x@THN=P zo5fKH4!Mb%UmJE2UtMnSmLV`kcEOOj29gn}7E&Y#w9FO8P@pm{aJrhLj7C%DML?>{ zhAb(*5|1_?i&ik;|@8CtZhbgCSQJ%WnXNJ*j5Wrl?RYNGicjKUN zT^l3&Z5$)3360JD(lC0gn~U6maWtptcm2imuNu=Tk(F_jGR*;i!S(=Df5S~negN)a zZ{CC^NN#%Mr$+kzrZ2ZeGyxdzdY;}{Kukali~2wO57Poh>}`tq0uI=Lf;ime9w&_g zhDnX4z8c4j`^xx9jog09sQ}+v5qoY}LuWZCkdBCbN-;lXcqp=&pBlqDtH_a!**QZf zQq8~{&B&fHG~;KiCGdxFOoR&bk;jJrXcz^a!I3>$C;4u7ks99k?x;Xq!McIvoV&s8 tb#8U;vZs%5h|5)r&Q&WO>NMqk2ZUM!vO_DU|BV#m?R6raXtaepItG%u{(%4h diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_7/PARAMETER.data_0 deleted file mode 100644 index 05dee2ddd2e6277e223aa354a8b8cde59228e025..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_8/PARAMETER.data_0 deleted file mode 100644 index 7664ed432b0474517a45295fc50d38b6f915e5d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 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

7(2R&id1#GBP-I&LSwecD$VRUc;o*z!u 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 Dzx9eW diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/FORECAST.index deleted file mode 100644 index c661372176bb7a873d6890155bcfcb704e12c4d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZXUF>Dh-5JiUuq#z2Q00Bir6C#X-A%Qp*!HJCp_)g)73kpL=f#|4cPDn^}R8bll z=&0zZQXr*DM@2_PhlE6jD3JKGbAM;oclK%R^YfqiGqYQ~J|#y)2y%3j~=ytI7c5L+_YrrWXTbR z%dLW)xB6v8`zAuG3$Sdu1KN<4wr)sKtC6O7=vZgTsqDPuon|?3mp*=Q5utEu~I4LZ3mZIrF2`C+8@o GPyPdb7ykJG diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_9/PARAMETER.data_0 deleted file mode 100644 index 3ec5272b40da5bd552a6ebaf07a52a7dcab7f712..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4$U|I?h#kG;g~WLXZp)akL6PCC86=njwh5`TsR mSGpp$PO!UcpK+ff@#d-5_ItLhT32}W>3)#80wPR&iqN!8EIPl;De(GPG8a`bf#aShVT%`0JG zf~u6lqB1zdF~rjutc(?^Oa_ZGH~%14XUE_WutGLG3LX6%eIlb=UBC)ifC@p*Tb2RVj#`nf9@Di|=Z1Gzvc1p@^`1_0Ov B2qgdj diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/files/state-map b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/files/state-map deleted file mode 100644 index 847546ba7af7be9a63c27554da04aad841dc1dfa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108 Qcmb1SU|?VbVir1J03Wabe*gdg diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/files/summary-key-set b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/files/summary-key-set deleted file mode 100644 index 374e2509371fbe557a278ab04427c55512dbd6bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 463 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/FORECAST.index deleted file mode 100644 index 2ec82d5de21ca557ea081c90a7c5a45a3a5db1f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZXVJ!}&}5QUc_K_W^KC_sTCO2ePA?ASphRf5Sm7T`OX!&gu^>7b#bqB((((xr-& z0ttzZijIoH5)~a49aXwibV-B6+nswmyFNRoQBL2@ym>QwPCr~W7mP98<6C0{a~Ib& zT+fEvk9Q{N;K`()jV6xkp`-m}H_l>!Yc)o7TJYte&IT8CmJ|*H+ z#684Ih((%>Hq&ga!ps{B33eUPVhe~xKOOCc+#gE`cLULK_%lggD_*fcTv3p8L{azZ zNLZ~+?zeKR=EN7V_;-p?{6*YKfbFuu7s^;)eS`2JYVezKEE&%M57g%HPafhN<}eQ@ z0IpC#+1JDrAPgL4zx#DY`t9Z65WXnJex1XG4q-)+Xzb#gH~6h$%;XAU*}{T{b*wU2 z`^%MKf08PVQhij66`gk2%26#ULhVbqrAJ|yjhn5Co_>-uP=Z*+bqAN-rHANXy@4;i z{fnFUl&HqR+QRwZ=?)7!Al_W2YBxHK2jtEKoK1y8;ConBggpdqc>j+SqZ{rZ6ums! z%2VY+@pi*0>ZT&BD5+)^{D*Q(;_H1? zj`cz(JomHC+1h#pF!0G&-bxc~qF diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_0/PARAMETER.index deleted file mode 100644 index 124fd1529273c681fa1f3aa832a7cc76c5fa0dc8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72 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

<)?IWMkjss0)_0{M_m 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/FORECAST.index deleted file mode 100644 index afa1d3eb1330985a13c679ae0e01e3fbed9a7f95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZ{kKWG#|6vm&8f?{DT6ip#EMm!HsFTtcrJhPWWyRu+L&b|FQ&RCe0fSqXk`X1{rFv$)AJWb&K$=X>8y{%TH+iAewb!X_5EhW8}i zvMeSmdC}|kl3V}u-*Z+*uf9E-%3Sp9;gr8$RXtfQ6I{bsk#}$7}c2XZh&<3SGTkok<~?!t5|>aMVg25 z_Mz%;I3qht@z5KrPJ^3uY8WBahomNC%C4|L+W= zajJ2Ak_|zERTL#71+Z96?#uc7CzHJx_kJ$z(n>;gy*`nIc z1H(3R23uy_ak1IGK~+CS$5tRNG^YK{IL3<89?)NcZ&e@fFK?XG;#cDup@wFh zvxacuQLR{23bkw8kxI543Gv zeEn!6sqe6TT!5iWT$0`%Z!I>%@O_fjAJ)Z=jh55@5g_*TAifgVVl#P Ee^Gb-D*ylh diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/PARAMETER.data_0 deleted file mode 100644 index 69a76c69ef3b7daefcca11c7799e440147a3e8f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4$U|8SxORv7=co4XCbKbV*K-`0TOXKIE%AK+IbMrHzV83` nXN6r|pY;CU{ufibV!w-R+W%nQE;X4=clLwKB^Uf>_|E_U?1?tp diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_1/PARAMETER.index deleted file mode 100644 index b3d275e53fb21080abd3b5054a675e2cff979095..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_12/PARAMETER.data_0 deleted file mode 100644 index 06192b663d4536616975996b99caae320288a891..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 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℞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

$R?DT-$PT$%R%JaP|6s^KF*Dp)% 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%0Db}Ip8=k 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/FORECAST.index deleted file mode 100644 index aca2e32260e74292b6a49ecd1af8300201da11e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmaKsKWI}?6vmH>3hL4>Di#C>#l~Q4T5PA(*rY+td&bxdf@!x--JD!5g3zsl2o6qe zPHt|(12;D}C%10hoZS5GIrrRiZ!h?o*Bf4beCIp=UiEf?&Ja=e!>t`0w2b>4?!mC0 zwmWO|9G6@4zYw{zM3-^y;uNNuMCJ}78FLZ}h;ugUPq#O!x}%^w z7O+92r2w)TTtziE6v*3BwO~EkqN~QJb&fcMtt{e?GNOQ04$`j@WNTGwZNtKk<8vF6TF76z6HY76L9ymaP+3+q;N<>A-89cx??dEB@;U`PJ>FjPGv#g z1WeoIg`bT#A8pO6(c?L$VE%A47_>X<>uQ6#e(;Ez+eG-#9{#Zn6e-L7fH58|wUOAh zp*bwM+y(M0Tr@Amh3kror#O9*4`5=og}-R`kI1J^EvDya>zHja@UPfR~#`cjz#<`U>Z?|qRMCZqX}ligCb``_PXRauz!E0 zOVND)Z(y6o_oW~kl+BKb(C3nq8q13(g3a$TaA=s74<+?i+Eng?f5FDC?i-|i5GZ|v zO-sl}n~t7rMIk}5XbX5|Yd@}c+IJQ2y$hQLHAaltC{~7)>005e_JnR4f diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_16/PARAMETER.index deleted file mode 100644 index 25fdec4685758d0a4affa4ded42921a5eb40b0b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/PARAMETER.data_0 deleted file mode 100644 index 6e82c5c2dbb6dcd687ab610f435408ee4a865de8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|! z|Iz&%FE(89tjyleCAYX``-kuQ4@bUN;pN(8U(o(4sy_Gg{ypip%x2tvXm4#K`%~}y oGyCrfTmSA>-?u-G_r34LlfUe5{n;wIBlgFBkhx@n{|x^b03uE~vH$=8 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/PARAMETER.index deleted file mode 100644 index 4dc7149bcf5ef872dfaa7de853b48c004875ec96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmeZo6=GmyU|{$;T_X%gf!QKJI@r(A+cn3mE_a diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/PARAMETER.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/PARAMETER.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/STATIC.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/STATIC.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/STATIC.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/STATIC.index deleted file mode 100644 index 6ae8e9353567cdf4a6efd75f0a4663a55ba1dbe1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|{$;T_X%g!2tj?3Ig^3 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/STATIC.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_17/STATIC.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/ANALYZED.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/ANALYZED.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/ANALYZED.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/ANALYZED.index deleted file mode 100644 index 6ae8e9353567cdf4a6efd75f0a4663a55ba1dbe1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|{$;T_X%g!2tj?3Ig^3 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/ANALYZED.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/ANALYZED.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/FORECAST.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/FORECAST.data_0 deleted file mode 100644 index 7c069ba06900fe45f01c9b37e230644525c8274b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103680 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

oFZG1>w?g&byAKyX9JlME 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/FORECAST.index deleted file mode 100644 index 1e38fe0e2b1646e40a21709a7136e3648a75349a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZ{lD@HP?ZcWzadQ(~!Eo8Fq%=2%)pDukY`jN>sd&VVU~8|j zx?O2S^_><1w>Ik4YQC_%Ou@hOj~*69tk5B!oy0wJ zZRrw9mnF&;`1?RnVD+Y#oo%|89d=-3h1B6cA>+ulP593kRp%af%iS?Y&GH8ZU$!6Qm691)Ne^rb zt1=8~p;G2Ju4|YS^Y;$u6LXYb=`;u49*38ZQ)MHb>yb0YsBEn)rURG_F+$1)u*HwA zM!cV&H+8IBn^Hkc;GV&4&V~&*jy+r%_9>t&L7t6L4lioShr+yPrYb?(+)m_#F)G2S s)MDo$W_)S=BpS?+FHJXSPGXc160ftV{}0>#3&uQA`b=5uI>hA8H=Gpx`v3p{ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/PARAMETER.data_0 deleted file mode 100644 index 96b186a46617a332764bb446287d7e5527137e6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4$U|J%-s17# zm_6T_vw<61p4mt6cAe1u`ELJS<`d6Sw?DC8VElE~L7s{B$HSP`G$}r|=a%eJIPv<{ n{(8H{-(EQn_J7WsaeL+WTlN#A{=Gf@?A3mdx#WWX4F4Gb3RO9> diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_2/PARAMETER.index deleted file mode 100644 index cfc51a05e81593170866afee82de72a558b862e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72 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 z 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

3r-vAR-ti0alP(w~2qZ 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 OYmfWNi=)cm?|%T_RtfL` diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/PARAMETER.data_0 deleted file mode 100644 index 86829b22705850ccffff9245763e41b49337823e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|I3@}bJipOW_{kDxHNFrk;#AehyF?XyFX^Cz0$YYtWF2t@Bir8yvzUSt^F%fj4RT& p&)R<=xcsPsM4El=_5&Y(`+c(CcjS)cPv#T*LFSSP{xke%001wDJEs5u diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_20/PARAMETER.index deleted file mode 100644 index c33aed0d8a1da3daee0ee9244f1c24cc873bd7e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_21/FORECAST.index deleted file mode 100644 index fe0f0d7c2f0b0df3de2fea29e03e7841d29d1439..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 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 z

TuDqpu5f(j}l_SV_|KHbESpP-bNwHGNu$1qTBMgKB8L^rl91+3xXZE_>5EgV&$ zOODEkeq3%6^~}&;T17K>;4;DV%m4r%L&G!~tSKiT(#|E0^+y+9_h6 zd1GjXyP?=mi*OqA_{)dSUn?jvKNf!~g76Wj6~)?SclrRySkIt$z9`tYt)2w zLH1bb2WvaK78Z-}g!t%hVjz|M#@(EMZ2m+xs2h|d|Hk1;&5?pw$c+CD#G znTJ9-d5lDInTFt4m3iE?2E{kXkFNzyD#}nvOOxnyk-Z97PhCm_8w(zWfTN#6dHHKR zd2JiDboS`mTO;ZSOBGbL1jEBmi#sW~*?ZB)!;lWqZTWuvAgfJ=oyb=hLg>;1iMYqZ zZoM7ttHm9T&)0SVFxch|j%Gz00j$BhI}gofjJVsatk19^?lhcm=Dq!cz8<^k=TWdz z`WQrpb7D44DI3m-8GJ_cH|%-p@m| zqeXs>kCHM`2l--fTJoJjrjmI>aff@nbZx|U(mhmEby33qA?fB#Xk9t!%-{I>WI^Ja z$&w3^m=jZmffB@G==4-m0=UU~n!#B`^`r`Heciqb$zN3M!5-+>s_1yV9-@$;DNWH+ zs040jEAw|cjn9LyF7he4&dmdBc7c*l2Dw#z!qxM+pq0@zkwq%%iR_F0dtF#^&t33G z=iiTP;~ahx1s>dayy`|ZjPM^=bRAma@C#m1ZB3mU|4S|9J48(xEUMPJ4 zAq4YGkdCB1E9{!rw?L%Gi7jM~_GgwncK@t|LeNXJ zEc;3W-?uCIf&a;y+_$2MVmmj*VjGqMDTl>ax6A-bwl8lt2EAsv*r4F6c~u|$=|90m znwHuB(LvckR7CPv>cpf#qQHk#=rweE@;wLe==a7!=jPz`xu`rJtAdh*AOYvvk?@`E zpi!is?nwGRkt4JK`Chi|?_vpc3{fzWOa2LK@i{X$>yp*CU|9WXa(xj}f0{HOx8>~0Yx zLg~_UyT|xafaG_Z3A$ R6@5iDmHX`fbpHSS{}12w?xz3% diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/FORECAST.index deleted file mode 100644 index 432db22d865c78025d3d6e3a39bbe90558b47a2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZ{kA#4;;5QYZ>B!DRf2qYv32pkvgDA22F3%%6eE50dMBkBeG z%2f);R)h-tS?Kz24mJk6Cl{4TXH=p#p2Vo(V=ks!fwo%2@XXb0It9X3IJBHY$sk2T z=(Tg^E{pp5;JV4K0$S27qUI|2d|NL%cIQ?HKb9-~QTcR1#2r)~nNyyEHBWbAZsvEL RvsAStxmvuW4>`wA{sC4V3IYHC diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/PARAMETER.data_0 deleted file mode 100644 index ae315352bacf03f774bb07607a59d4169418a3d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|uI7XGBWA+WX1>b#j(| oxBq(m1x5S%BlevC*k80J2gxU;qFB diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_22/PARAMETER.index deleted file mode 100644 index e4ae83c833bb9f601061b566273ca9e21479c30b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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 P{J%lD*Z_XK5&Zo>eH938 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/PARAMETER.data_0 deleted file mode 100644 index 8e6f6150a09f370e32973795e9dad27fe56f6708..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|4F4GbjzKj= diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_23/PARAMETER.index deleted file mode 100644 index 81a864974b5c6af5cb698f3bd70dcb971cdf90ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/FORECAST.index deleted file mode 100644 index 635db16f6fe78559ddc2b7c0d182966aae06c2c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZ{kFKiS+6viJ0NB~m|5J*T6v~XOwawW8COX*!N!0l#Px&m?Fz~E4r2?+_ophyr^ zI1~;?atR6?4u!+vP&mGMZ{NI`8*cBWlkENaz3=^*DPOM8AtD;STiwS-m$8mujmA~e zUmwzaJnp3bg~%NyI)(iq_T$*wva0vC%4%J~;*-aS<^axN_h2VhD??`(NyLug)u^nR zJ%!wsL8m*RW7ykvr-=j72jk9m9E-KFSYuEsR@D$2grLujQ!x%YUf^EkoY%cK-M+m$ zD<^kmZB@^1O-7^sU~@C5ulX{gHkXL-r6>3!DY1H}A-!OX>!U8XhA6gb(FtRch9Gd# zkogw@7aP({?(POLL6U}WcTwv^toWUarFp|*o;Qyd{&P+8{<_-b4LGU(Q&D%A8O=MY zzSZYV&avHbxsdzM-0liqS(~QSe*dbLp?EF*aX>C$UBu$LW0aI}=kXGc_ZZjxCQ{kx z;iDk^5iqWMd}3_oKIUN8ZHtO%{`p_jLGN1chDM$L6)=vHq$BT5ep(o-dUkQuZTzb$cvVO3XLZD6shbhK~=v(YLVX&GIY(K^^5VxRtA3eww4 ze0Jk)K7Zvtc>rZlZ2+H{U^=L!A86waa*o~kK~;C|kwIETf#MXVOCXQHHz=Knp}T;qlc*Oy$L4vy5k){`jHFz GH~#>4x(Vq3 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/PARAMETER.data_0 deleted file mode 100644 index dc0a0e1631883fc3e5de688be8b9b9c1ee47527c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|b!uPi`TjngyCmo8evr9jg8vNv830%yJh}h? diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_24/PARAMETER.index deleted file mode 100644 index 105c02c7b8f7dea570ebf5d67e35834fcfffbb64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmeZo6=GmyU|{$;T_X%gf!QKJI@r(A+cnWPpa0@4 z$l2siDeL*?zfQ`;uEc>-D2J z(laoC;)4Cj2+!UFC{8?(+~Qep5XF(6frBY7IE0Mw>^+p?#KXufp7n-P9O)T2g5rWB z$q3JqisFf$*FAHNqVhqWCp}Y-rt&VHyF6o$p>jXZ5YI23zGJC=f#*}tlH;g+qUUwb zoa3o{kmpIy)Dx(@i{~!S*b}MT&ojjHi>L1-s$byw)U)JdDxc_i-81JDDj(!|(lhl` zD(~XC%QN;gD);jY@%-ZHJDutmcs}(kIfKe4dS3TT9!TY7Jv(?#^$hjA?HPS0EuYu3 zk>@bam7ZrkKX|5}Me9}e?BO}bbD!rU&-k-x`J$dJJ;!=(@VxB#!!zp~TCbL8fahY* zqnUrBU`XX9BuV*9A zVV)~J&w76FOuv}ctL)jsbB^ae&qto|m(cP>JzIK?_1xfj+4F~I)}^#wEzbbY#hyn! zUwS5AM$4D={LOx|Kf@2kpQ?51HTq}cj|s3BE3iMq)rYYUo#xi_*G?9Z{gYE|$@2^4 zDJw@8e_|80Ydl!6TT&-q(IvH$4ZD=dsk3&<>g4rz=W?3IZwol(!s$hvYEp0sr@m6Q ztdrN-ES&c1xJs~Ja8)NO8@q;6whgWAG@mckgMM!tICb>GjS=^s+tkV4q-~CPz@e5- zb!9>ur>$AMt&_#x+0Lm7RO#T<2k&9rlPkwzyi;Mty1H_)`*k;`Y`Yoboaj2Br;D}t ztGCl;i_^!+3cZ7R=dHdj=CzOYbIJvq0$`Q-{b8Ju1DtkQ$AM09w8kJT-+Iq@5c9i1^QschkpXDov8NQ|EcRn;$0 z*7Y0h*5fn7p!%8=;}7rc5ACI66h}>u@kd_l1x4yZkOe2g_@gSdfaXpxT`JFr% zhg8GvP(E2h@y`1cKd14D@2HJ&iMLSD#NSHsxO)`0jfZhbR4WSYlV(uHA4V=*2-%b! z6hAu))p<*?d<%K_FQ}Ww!Fa|+67oVyGJQHIvSxzjYi26nm>t?WxuK5CNA+t8Q9P*_ z#UZ7jNM0VYYd%!|sT#BqwIRRR2&!K#sXj|5sxQ`?>QfJ;cU^ zLpg9cmG{{J)#p=G|K=_fNAchmergj_+a^4}*LyrBAQA0Rva9r9LDG4J3RV$=MiPy+Hu5@>&?fFgNXC^Kb* zDp_W#zm^U1rn#V2d8ypD0F-+QQ5?4@S++P?yCh^~OH&-PEL5AyK~uN_Az3jj@FZxNxQciy>7hf(1g~Y*I!eM$}iM` zEOUJ-AK#GTKcmmTj6V(j+4#fz9$V_h7v1}@cJjN!gE8L3$g#$$zT908`@+6Q4(Un%WrGc)AK#P`|a=b=2GWx19Rb`@2rFxyXH|IQ#Jd z;`jR=Ir*V+kKv*^Pf_om>bX;&yYs?nzb}2|G*$fGAZ|A%(#f|re2enQ>E1bYj~kGE zobukqGC|=FSnk4UXl3J%DBl_Zbyyi1cT3EJyn}_ZYnsp4o)P5p#?W+cN#1D&?dUpC z7AOO`;ZTkEjqT{5Yqb4w>nP4Yn6{s+3bdmWK^Ff8_D7Ul4q3_0Uc*oFg`RFI}*~w^6@iZDVIi6r% zqT`35-9_i&FVP+yedu_^jEm!Ao7}?jQVVxKarI)=N*qV&zx;0(v(8~SzV^Wr%y;;* zv}9mb9Dl20<9uMlXWzr}jqcutr()fNow8nYn%WgFJ8ik17Z7*tcn(;8y|rK z&g^%pSx0v``GO%EVeyc4PT48x9|MBjy)80LR z{ni<39>sDi=0KHcF=QdFpg= znuU15*+4kx?`cl`HT7h~-3pC&ip2RxBd(um7@Sfuz$t6;?x>%>vyIa(DqP+9@BOEn z-c~gcf7)Hg$(JXo?_}%mATLtcOd}VYBDs#J@x*BDoOX4I_D-I;H}WKNcYQ|}%RA3HIYpgZU7U7c*RD=}aBVlI`u425lV!^7 z4>NZ|-elvh>*Zn@y+86NT|5QyCLXqf3~EC8)05BS*dWTIW|cu6rAyz1cGf85Q(|*A zmtA6D>qY~r4x^K+cCxZLfQ2))IKFB zzdE!Kng_q2+|VBR6;E&q+BgM}Pw91Y$)`UcJJSJq6zhDB@~U&ikuTX8%PD_KA0PRS z;e(+3`3Ume4Ja?@bO`FN1u;+OlIHVjK~l_{P4}@-E&K#o)UGto3%CX4F+|;Bi$@l&wQIfv1C3}ovxBYQ_Obt=0GFJi_f9>!6nExB%6c!Sq;fkv&klxq0W*5 z_sLAACXi*APw~BLP}NI4&#f;8`axcI0n|sXK@*vBzN_aC8$&UR?vJSimk_IdNfx+z z8C(~N@zbFGbQ&rX3-`55L?vh+jG*|{E+`Vbqqte_g>E}GT06)x29XQSL)|k5?pvv) zrAgKcii0aC{(gnxjjgwd9<|h;8w+RDSszWQ}t!am$-sjUc-;5{kgJ zRG#=Em5=#KM(0c2@^)htC`NRHyvKBkCvK(q{UxYRejK}PR@twb^zoNpQcF^x)V*FS670n9{@51~+bdH1h zg*mkZ^Ey@d<^e3f?FQy=>MG5zbn~&8$Eg0hXnvDrCgwjX$-PT%dE-;*D%M-E6M2!& zTLO8J-DK{dd}0pkw1azMK5PeWf8b(q?LCc?;d%ddF`v{5^J{T&%oD_V$y2Avz44h- z_uTj#<%btxo-VTtdg)@3z2Ym>pL+|{`iV5|4v&d^N^I{6S@0HUMq4O<{GfO}RCuGy8T>8dFJ=>U=mcNmX;)2=83HhK*QU;oknouNY4eiyw zP?eQR)jzmcophrF_90k^rfL`)*Z@H zOQ3Cemf{Sbpcs@E`IHSP31ywekeBZVP5oI=&E7_F{>xA-{Xp@@6d&AvsUF3lc+e2q zivf@ynM3teL!r5LmCCRDgxV(u&5sV%ht^k-n>Rsz`a0C9Vk4jAaY{n@sXf#_)1eC6 z0Zr0#kcZud^5{dd4#|!@LacMVh9dP3$QmX4?B0i&Qy2>0x{!bEMCDUPLY99K*?BwF zuRl(4-A7RR#Q5U2!?)&zDpz~5$O>ozFG0~L##g*vru12hG4Q~OVSgX1fj ztcS9#KQv7;Q@rLPoj02nLUFtkwEOdr%m1eH(9DC}ry`WW_i=u6zrIi>i9)uUMAuKx zU%0MxaDTeK>M@E77sYkX!-u0EVWC&huZXIDL6g51`W;#NBKjc}UKg?fkI+A#7`eW2Q%4eHZ$-+={GK!0eOZb1L2mSv=V@`pyh zX@}&7!km2Mj=Nql6!O0-LOGE`)+!YgZAg723zfggOa5#A)AXO_KdR}Li#YFxhoXO1 zzfz-})a0Xd9F~s3dBD2XKpvz=Ol89DZ>P^uou)y@7*5sn3i2Z5TQ#nWbwpTvr&ZY! zIYr--iJj`q_ashRAa63KDbXysQ<>2zobpphN~h^`HkDJ~e3cpwPmmTC%9GA1&s0qh zW6BIp)^9*Y#Oo(zLcF*Zcj{6XA@gng7s^{+fg(YJ%&3ol2HIRAi;Gpwt&p|PnAOF+ z`~;|0zJRP#&1|k*v|bH$SSAT zxtOgUo7*Was60+tZAV_G`kF1jlXbjOz{w9kDCjf~zZY^^RlJCk-J4a^Y4av2?$rIa zmOvaUpp;W)Y*7YrtFGk`=UiUFsjEk==rlWP_&CL$b(Ng@cjhWi`DS}nCtusj7jXez z!>RuMUejrFzO4=8v3gEbA$fhLd0Mmq;+bt5I_12eMowMoc4H^skh7^%Wgp?^)PA>{ zIeD^5Eu1X-ww6xWDpzYbB&3Z~1kRUE-KTY1xFTmer@HkKiVMfuyI2=r(7`G8_vq*} zsVa4H+HYw)J9UN+(3A}C;$j|qZC59&J+_w_*1Oyeia1*-p7tB+rge~4nl?+ITKW>Qgk_OO zvXCiIb-V>_g*?a~S>d5jlsE%T&2)?0>+tT~$ys}$-5(EmA%EEd{+s-#X}y1#|LBnC zOECUK`32Re49JJ<=Bktz)f@oTq!1{2-+=O4^kr^6`8+$cJ<33HsRHC93Pa|fl7!76%TU~hHLF@d zmf|b!TdJT@kfr+=NkDyovJ51#ZKt-R?N$o_TkjT5P@NQPmY-|G0GWKoWJ zkbXD`vb&KqFG|}8d9NtGjq=|maWVhWWm=L$SCjl1AM=*s7D~* zaUH7gCs03+q`1WgD7OBBCRt|8ANiWr(8y4zbQa3HudS!~=AoLHhw`scF>h6sBA{-& zjpn(tLon~vueMSie*Fy1k86CuyjdPkhWWG@u@##24c?+X&wqsM#{$d?Md32<(Y`0| zKo&9@^LlY1C+7dA>UlDC0ObuoQ+#&Iv!GBYy46A6A$=b}RBB(n)fxKDPAFf@sMq&SpS?$@!2)dPBc(Ax6q`Ih1X$&3X&6> zKskOey}noo^{ZV_thfSA`$&qP#{TKvx1N-VG)2in)uCk)$_oRb@taBU=M9h@J_Bvw z8_0{L`Q^4}n)yO`Wf-)>wn3HcA;rrR{&vgRvc({;))WfSpUTY)Do?+L%J1(btA|4w z?=EB?o;!yk?0_m=L>_T`bH|h77W$vg;ZX97L;`-K$~<3#mRb*{acbz zYCyBHB;0pN z!nN2=J59uM>g_oaI$8J2iJfNA$D~f4a$9nzI=C^V)Al`(#;JeQNe44bhBDr9Xy5;U z;!>gXuAXOY4`ovY^~2dv?N|(1X41T0LiJnMLYZ+d)#tiSmi`Sz+AJB|cI8e1P0uz^ zeH{g@&}8FXRNw9nWV2&Z{(h$fwC{&fY)(VgKXxX!U9q+*G;0P!o?sqiYCTkEPEmb} zyHx-7DU^p9ck8S2zKCtgYj|B1HW&MCuM9`Ku-+=ITh10;jCNGJ?xedCg>2Y)s;`|K>$7e{$waZSeLim|88Z~GFSf>` zzXI~^hpGPD@V#z%)3WX^ zr%EqnF;xeJ@N#33-5SjHtLseLf*ozte)v&zJGln zmVZ5BhEtq6KFz7$7M$voi+4@02~N{()_5l?P-~pi`nMg6*vFS_lMv;q z$385__cX`)YRwO9*YI0-UETR0_Dk>1hW$2vQ5L!F=#=a5e(j*8Xb&B98to*$<=lw+ zRJXP``QGAaU(Hvcy;a>D)c(y6>~Zxne>WT-8u0kADOm4jv_vE@wijO zJ9g4(S6w>olofxSb*ep;kRREY7b9HE!xJMvVv|~5Lj8ta$d6=5x~r)FYxFgz9sT6G z(~R}KiSpUYZaLY8$G4q&VCuV0b)wom#Mx_F#80E%cgl8Wp&7ph`HyZti}IfFlOMTy zdv-eICBHg9cCn~jlE&{|DKTD)3cbi2BOu!}8S*c4s5~2ePH5`}Q@nT$v_;m@a{1On zb9W=f@peKs={S`~xeaBC&roDag?Rz1QwH)6?I^A^4XS~=q5k}s>WihI`9r@-G=Ip_ z2b$m|P)|Pz)tv zBp=>}eAqpx$~}Ol!r#ztcnaCPmr%Tor23s7seHmWiZA`5`lV4ZpHz`CpuQX%O22rJ zO-VowNCZWWBvijDDV4uWMt(_7^;c3rH6vmBc_fCkh| zLuue25`+nd-n;NGS8q@4$nG@P*5QK;vFmUl7t1|siaG7l*rlEN)YI~a2W0bcvW2Ou zIJtivU#CoaqNY>78(r6_KAQT7Pv39o6uYuCahe|E{hZ1tP79~(y}p&xek~@QV)x3n zPLt;^d_W)q?<$F6-?#z9h z`bvzxPP_jZl<&^R$6=jAl9^o{E&vKmW7sOnBvyc zE1N(OXBy5Fw>VnOn z-8Kla0`sA%7Yfy`^H64f2E}AH-R++!nG(vSxuLy4A5hp!brI{W5-Qc3;`$>gE;N?){N)3+hEzxP9#=@b-iFF`fzE_r|+q&3^$A!coUkT+uBgAjQp5#*idi+gNg zHpHTJA;{*Jqxw8G$V5%4zIX>H$M=Ei@d#+kOr>~m5H!K7Aq(FQb?!q@dBLO%2s+4&K)cV9yF`~zfxKPbKuZKm6QyEiV>6_Zfh zDHX+qGf=!CGsU-aP<+aJKzT$VDvweeie{yuROO-S ze>nbFpK~oR?%aGa!l`{fB0-S8c`*@}lRK_;BDz+L#cVgnjN%eIrbKW%bXP@bYCE6J49I7ACkh z_zNbulG6m0PiTnoP^9{a2^7x}jDcCMu7n#)wx)k1w%fkQTc^JJmi)OIH9t&0QCMX6Sg7W2YXvWbOs7%bOh*{_R zP{}utpJ6n97fK2F)cnw1tqOJTRupIK2icwRP*#}-|9lWb<)`LAyJs}j$8HNnnnFHUQkfa2@{ynhq!eE}^VeKE)$3_$yceK8@EbJ2b}FgsM` zPEory=@0p+>`*@W5mvDSU{1T)e-4L|?pJ>9R>Oc{57ES!xp2hLC zZ9d?5v-Q7`ILPR)DB-xXpAw#PbmLSv%Z2kr?Yw~Vhuu;1!O^|SIIqOzTsY78<_?s2 z<%mEcW^OLVJWJd@jq_4xEKeT#Odo6&y9e2hDNx+7l-NbQyN2_t*xsv7QNPR;oL6}l zTyokb(JwmX-g^;Fv;Ht8lACYQ^|9g08CNd)6glnG7iZ%7k=LW1K>Q)-80^#?*B5)y z6^X0-u*mtJ@GJ?sb1-xkMBcE5+? zrt1&I{@R{7X#cmq!27Xh_Tl}hoRjf>WwQooH-0ZGwd=m5bo>&eM!TD}Md>)jyg|pM z(Sw(E(NOAtbM6gu<$A)IP_#$w)7zY^*wHOcn|8uRr%bXy}1S+&H;zbshjlxgXMYFjaMo{RO}Npn%&S~J1uH4Q)_|PfxW}^P3NvZEH=AY_D7k|_p z@5OhD-~-5m)XO|{<8{*_h}?g0&){7|z-h=Us-FS4a2@*>`HRC8C( zc80b@z3-RSPVs&v07$`$OK(@6b@+-08Dl~(t zA&+7;cTs*-F&FYD-gP16QAgrYzEpiURBv8WyjdbYk_RtBUW4)@Sh5}$CzJB zp-z<)`GYwy7OKBLLAjy}&EMnPB%5W!JXoY{1x@iekexma)enYwqh99CZwGfrZ2B*Q zcFRSI+s2sX+EFYiLHc)v_Vz-Gznp>k{tqZKK^`aPxk8Yz~!<@9R-S?li5=9mNJr#;YIzeg^QqOsiv zNudbILf$Dt<-_TL9x<;0#iA`V3wlAjeK?dsQy{MrMD^=eLw#U7Ilxf)wX={#UZ?W# zM^xS~67u`sp~xI-x!W&ZBPsm1B$TqKnD=m!k!{%kZ~@Tmp47)EivP$&Z^FBHiNy>stN zRO?S}KLqXJMDJa>t<)6iSTmuRdYH;be1Yt9p$}NUgFjT?L!ch{H^p_bBG0l1+d?)n zh`fISs&8JNnK}I@w;f%&D&$GJLy=?xG&|`BDNL#$iZjlEYRwF2C(oid+G42luZHaX zW-7n5lbo`T7^x%{Qt2YlcC2jvidm zY%U##78js8QyR zlc3(*g5uQqpiLeZ%KhK5A3AAliYw=#<=)gKtG9&Kr!3Vc{z&`%X%VSQLcZb>-k;b- z?^j3AgGPG!G_;F)$mqC5^rPd`?kydUveTi6?Fa4aqEKCr4t1GLXn*sqIJ9SX;yTi& zi$U`^4A-4)Cg}Q09Y)t{^GNhBY*PK#Xvb&X2SYv|(O=0&)uHG_9}tQdqtUO4-a)tz zpvOj_-?Mv*LJ@of{h@i(4XVw_sec@|^>4R*UZ5n@QPw?jF;l6bo;8>9jF|bMOmKzz z+qVOuTu(nxq7FZ!{y5%6$o?h&`SbkGKh1xVo%vAS?S}f0-R+NP+n};jPyONt-xlra zR1*gcKz+l8qn)7}Gc)5PK?Fyb1 zU*yv5(?=11V(Ygls?%tn=uZ3bRty+6GL}=mE*i(lmPU`~RI$ENp4cmGA{Wb~yAwN2 z#h6K*Rt!t#ISt%5DVE$WmVOBHw8*DXpqb)VqUPWdijIj0R=Qo*Tn z=BVi8BLjV$@?G4@PBVU96(>(zq?*$XlV^N+rO5R^{rjUsn2Ds=M*n9)`w|x zG;pf6B^o;A&AN@8R`+h~G>3zlI7P)XO%XSa(afnD_%?S6HK&DBvga*fdf(Pg{c&R( zCo4ZqI(74^ZJqXAly*+F%O~1y$iy{akE6)(>#%rqTO5MY?@thQR||%*vM;=;V!}4stS|a42sq9qeMU zuip@-9bRjwQ}4<-%xRv)8t&xFpFuYD+z7a!!nI_ zv4}Pos(NuL@0~P~^4^^vpnTJHtXodixd++LM&n$pzn_M(c}2>1EAE2)Nde@$YDNfT zEizAZ%X6P4P*h1n`EHMSP_IvpJXe334Oxri$aBr@xzM&tJ=Lu*UN3@b9Y>xkcdVv- zH+6pGx9mD1QLtg$W#j&#^ zAJymkLpAdl#kEr)4;3*xLU}M0ni0{Ff65w-pvblovP2)CjZrxW`xkQ#wDBLoe>?vC z-fM3B5p(iEr{q7IuoGSxP(Q#(;`Wwtq}jr>#)9 zmXlvATOal3&on~)snZz8tY4f~h$DAMxbSs5r#P3Sqf^EI(g}W8*~Q6Q{lvJZ6Xfjf zVpBh&2kNip=;hQO^Yn4rDgFC7MVlcQANlCJgI&y(UYtgZcCyoF8kDo_8(_kLJX9Qhvv6lTVI$89(m>0-lxh}id6p2Ff zgP!!jko>jzDwdl*=^EDi(h~CqyE4xWlvnu*RpyhJN0=N7kO$l5-EX^k{zxDnHse!b zejyvbh9c=(Rzo5Q}m-Xx_MW5wth6(!BDHfih>G$8JCLU_V*E;pXK zauIy`nUkftfc%{OevWyO$xL53GCp-^KHOv?&6B3k4`7IWA0x4TtBG%6`xNh-HW&R+ zg{YDFJ<2-)03(DDrkcXM* zl$Y7#YZ0^Iub^C11fMgAtAnBHdVqWoh32DsszRA`3bc*SL)J6dPxrdI1U-PjQ_n-J z5?+QTBFQhjkKuKoNH~e&b4MYs$uQ5grX*w~dXoK@Q2EJ$F^4CMes*Y#5M~Hb0TFxALMfDHfL$Ty5+1YzQ=)#|K*R^ZUD3JY2{`2Sg zpMRMD{Mi)F=l?J>kHB@L0-ob~W5pxsx_kVEtP~U1pFEPBERczONk1T=uH>TlM1H9J zi$IpJD0!hUG^@S(nb{G`&@@ogj7{|`-{JK{$So)v9E0j5Jt$~*Ohjy3Nyw&`pylo* zgW|?#^dDk0J-Ea+UPNr#pMtXXF~|ds(sGkL#bLxO-EOF#uO@R&gSI^NOQMh;VwIpe zl$(92zHogi&qwzaRUP_*u}(7z<-F@!Xg1%a4>ud2OMRFL9mbFN^z-s!=QI_l8VIzi0pQ`n^}){k^b}==XS(*y#5}_8E{> zOGW)%qg7DPDv$ooKD`6kfFbDTcx$@P#_k?O|0b5TL;oT!Bt!opn%{xy^A74Kny*HG zpxV;)Z{8=S>-)}5x?Xd3!gZkh_e62mg&Nj7n$r|p9m6RrOpNVR@9M^P@&s!WJ4IyL zB#1NQB$pJ1YIWgRJ#g59$b^^j|Y&+W>Ie+E@P zlM->4IjNlXlYeTb43}x(nrdmCqGw*@)#mO?C_{tOyK?<;QwI288RgqjWOA{1coxdB ze{mPf^G(SdW1+sV9NOL+p?JLlnyaHAuay|8Irp($kzhMshu>O`*EM_QVn1|^rL=#; z!m+>Va2WQV?KzM4!)m96YS9?HPrc*=-Zwwn3(5|^&@Mbv2)SxGN@u0|-ho(8 zEq#dBS0z8;`09`EaQxY}M9@?pjPu6iPe|v{z4172_4o(4eKK3 z{=$pwK;EJgenNi28V~E^>Se^FzD|2RPCus_yb$up6agr269C!cP^eEHho<8^s=rqP z@>C&MPsUD2>!-Sk?dr~n5bJgOp=go1zuT@(ka!@rf4}%(r-{CEsFN*UGQ!EnT~SUs z#BVg}^_MYD{czeiC)=KC0^;yt6PSB?j1GGseQQR=r zG%UB@LKU^}3@q1mMxfK!(=(kiNyXVtJ23iOly@vVACA2pg!(kU7dyrGTH49)HeG@8 z^?D`B`_T`R+m-K-AL)B3Ho9`Xu*w!E+mmCPQzgtB>Xd65ggH%ykX@(`&%YP-@o(-& zdDq&;Y4e6so-`oa5tMJ9f7B@s$2#tmT?U^(dEw_LojP|NV(qkRsDH5b zy3^))al@%gHn@dyasRfHWtn{!F3xM6a$^eQL8i`6$inX;@6mnJAdg{rijl8=tCXBB1_xj`XGWVC$YDHhW{xdL}p2;f-l~%f~`?EDZ9V^Z=DU@rmL-N%4Mc z%>0ne_JzD=d(w9V6tRP#ioc!857C3*JkLYK?6&v7Ps`Vc?X36ET>AobBJV+;sL@`z z^H*()1@%pOz{g~u2YXl(day^W@gD4{Ne}jj<)nH<>bTy6J{d__I+sJ>vAmn{Ih~jBeHFq@V7%*hKGj&naVd zLl>kwBth4shHoIpm8LG}^&V)x=S5dyq6AWx(&Zt!Av?Mf+ol;*dFeO$*tIFt#Z)9s zj1h>%t!}jZsrpc#C`|E*1W+D$fbFssTcPYTgkGn3IjG`&!~UotTgiGIpuClo;*R^V z|F&2MXaZwVylV~KCwp5Ns&5DA{nvPduGrK}3&peYXdkwz6}oCsVIaD0)^sY`ksVq> z?b>7mx_JF%7uwrSJ&GZ~emsxkpbp=}aZ%47V(4HaUgCJ!h>sXrR5$Op_9GMHc$&<$ zFeK@Sv1f6-&W7W-+ktsc;W)*Zhx36)`+W@Yj;=?YY6bnKttjc8KQF=#x^ff$4bCgO z#&3^{ZN(or-;}gFT+E03+V0eis^fgr3lC#x7MHGVLVfdT8{mKP-(X-nQsMQ*xB}Q8 zel2IHdtLD{8urtsIsrxZZkQtQSC7fl#qoY*U}I?O3&?hVM7@eP0O|}!u)fOr9ov;% zs*zLH;`MBYEYuF)!>}JLQzvSVXoaDSOiM=P&?c@xF6a(Tqq$J@*hBH_8x#k=hjMr< zY+vL}Nv~6o)9WVBPL|0@HqHoDwI8(J_QR0f=u7rX2+jKWTV4CGL`k3-FdWCtK0CPC zmFs>3ar|t{d>e86R=h^PBRU*d=VFy{=~}1!JS_zENvEwr`O~1)PP1g&DyOY_WhG3{ zpvYb#81c}NE1bOf<>jzgK`5F`(=Imq&n|=iMg9iEpSScM@bACpKmW`4Q}~~aKmVtH z14zDz!1-VTis3xh>(XFKEs_pKe_-yfHtzVyjMa}g?MsfSGas89{S2Ga7X1%9M^j^U z(EG~$S^rB|zFVa$PSq{LH8}n=`au45Za>_29p;*0> z;&mUPoy{?&vKLB2VSS+~Qxo#}^lZD_RRpmvpPtHR{>1t^=q8zc2NdZ7A)n$; z)E>ikQ9J!C0r})rXg{0xH`-IKr&NLUoq~2Y+3B|mWX41|4thC#BqJ-g!#F5PWx?^1 zeHq3--8lx1qn%U=je5?{r)NB<9*Oi>&n$2Fa3l1X>}6X z3)x$^`dK2)U%k`N1^^x?Ea|ll*!Ne zU*+F_%-;a|m+|M%?~nfHsfmVx9Y^F*ZW;;mc~LqW#Xkp|6q>NZ=SNem8qXhkSFa{Rne7;~%|Amk^)HNL>`EmlTDOMQuMZhHjLNHwA`ecc z^2Y0-iv5t{S%olfk~8N)u994KuWNQLhrD}L%%|+iUr<**brt(HcNNB09cMP?SNi)5 zjJvk)LK=s2Y{9r}riNpjHuv6P+_vS@VmxOLIObiV-gYRL(<8Pf(bfBS{ZpMVFA#6( zZ#rr{`k^bgFXKJJ>puyEVtHcBFI2wCcoqqFMy`fDym->3e{oy%_F{w z{-$2rBzai$g=vJo4(&~j1pj>9292S&|g8v1zD0NhXR9W~TalS^xOI8Grs^ z{`3ES1N;B3-@vv%JFIi(0Y6rFlT*q>Tb=A(0-D#RO@#5ngvO)s;^9xs3zgp^%xl@X zeV8w5pRot9UU+Vd8+u|sj2k+MFY*K-2V&gdS$ARF5SLc0bSlFtXCpH=~}sDHja0g7)w z$lw0xr&ZQlkYA{b{#sX94{eSF)NcoMAuI2PEIbbSadD(JWL+mg^J5>ym!Cq}Bmw1D z(dnyqrl1eS@f$*3xiyrJIzZE>GsVGup}w$yta6j;^OwMQVK#4pJbzV;8}`gc$R`}c z_`x2~BW-%bBIJQ;=6Z}Hwo4ZpKW;|DxFM3PfoyPHj2|rQJJe6s)A%v6HO38_A_>L` zk^Bga8*c_+oDiY_#sz(yzWO5V%Z9s~Xp-e=RbV`pfpE(Lbug_o<(p zF%tcsn2;F#5>Gz|YC-*yc+r>op@CF=5j_H@;?N^->|7yQ zZXrEF$JQl6Y$9IJcA{)12lt@uXUYa;;yZYK)oDI7Uz$KUE)%r%KTyA2hyLb{?skOw z?~ePSO?`+w8cx=G40-ifSYHgw4SD0Lko9Q+^`h=j4IW5#9SP;iF_7;fRab>ruNeaE z#eQTje=4um1+o_%$N*9YbVY1p4onm@2?KF9=t%iqkZ*p=Oh5E~OxzJCV8{;vb*1hAPKeXA} zQ$Kj^Ec!pS!w3DIzH3go^=11?XR*E7$HSfK(uxSDJ#ZKOoBos>{h1A{ME%*8F6g)H zxY6jZSmPP!pH%;8=zn;Vq3Ac%$fnd^%;V@MbjvH`jsWx*deu*;8ug-iXTnpESBs1O zL(D4-&Ay7{rb>`~t`7OmMo>R#Pvs*9LfK;mw9D5+6Zb5Y2S!4cCJp)}F|i8Ga}V~X zc+pyDzF3N{CqTbt&eBKhymD>CI!7-k+svZ)Vi;syZj&*npHtIwqn|TR8$kVeDD`_w zSCI$LQ+?TQ(d-&R{o;sKP{oUYvLbzcrK4s=f5{8eSD4MV{)lClCD0T< z3R$%0RK6`C&Byc5=ViK4Bg8soe<+*Jp*YSqXcC1(-s~w9ml*nC+aneA%PHw^6IxRq zv2Ifrn#Zjmuhk8*2?0G#u9v52c@Svc2iL6vKbfbsVE1 zIcg313*Gex`VmpQ0W_`GqMuRCqEdges1^DlyI?Q+C3`qMWRpgrzY>1WX`Z#PDHJ=s z{5eTQ^lviG0qXC*37WT+JB@zOW^E4D?@08IEY%Dsw-lxRGVTM+2eq6}dHmmvXnuH# z?r-ZN&uIQw%|MlzJ|_`3Cn6Rjhd`6A{~!N1^i ziu2X>IC-s@2T;E*+94-9n&pU7-k_h1Qrki?&Zst7Ft27kS74mc!FkTR<#Yv$aYnbv zhjuY%2UGi{KZ<=(=f;1B%jg zUq;=f?X%ABQ}Mz7nQ#6{72}SQm1zcYO|^M`YOG6u6Gr1MhR6(R~oxJ~N=W zOF!ACT5LhA2Ooy2&o#&c-q3O%XMD&Q9}s5k%vSs6Q9=s#hp9g)c+4 z`a6{`%t!rJ-cFEjUI9(kXHZoy^cd&crM}RdH&EwEiu^$7R*?T%1NH6KkR3^de1Y|& zudeIjg7SxI6(BF<1Le0yP~YlJ861AfbMkzI{OP>VDL#w3b3Fq(}<+ z7XlB_^Xt|SI&t7To-;GzG(G>@6X>~zHzx*t!27|s3)TJ09eEU!?wR zqv>Rqmb3%8r?s$G+`#W-w@fa8?4GG0|7bj=Z(L6DS`ScabrBRM>>>T;o+N)fLUz#S z3GAZi*%A~=OsPNaP2&gB*{QIj@~&*yRpHcGP<||seA*M_3IaiI|_gQpOU+=0Pmd~8G!eMdv%?j`|Ki697sz;NGm4e{a~_;K&dH($OzBfNx!4v zed4b`X8%TlTm&sO!M;u<`6BHJRNrr)e1j;2M;O@@*Ow1<0)@5>Av5|TAhQOOL8<#} z;#C8X>1;~r>#RWjmLth+-6-Ad80onSq+b;S3cWsnTuNuO8}98tWTzrekzD?n+SBj_ z)Xv&PgYtq&WOw>L1X<(NXqUqI7N|$&lmrUx4pRGX_@3v+8{qp}avg@}CoGBpIraJF z%5#+O2|^!)4UH%S=58K^OzfhiA^6Yh5E{a^)J3QWJJ$r1dpnYB=LrfE z13;dSBz^8fP`;W*=@D6^ulYc-V=*WW{seNv{|}Yt_utk7TTq00lw0Ley`G_ZXZ-F% zX8TuwD~(ia>Sip6q@sW9EIxiN<)Z_ILVrLvKfW!Z1uzY$Mzdf?_tpsyq8>i zQ;^U9fzTcK=6(w0d7w&M8;=+QWS-Kzrc# zj0BlMP6+9dm!(li&!LgjZYCc`NRRyN584xZV>5;H=#(I&N6y{?3fYZ7@yJ=UKWUOS zh4!d@M!OVuT_6f(puA!XwO93)pw#gTLh4wxOi)_;vY!9O|NMvFKlQKH|B~O~tRInG z+{D3-N-sW=y}fl76!i^3!KMeu<>iyz-b8zq%TZn=+t`!+E;1(jJ#hiZw$vtl;&4#> zO(CMpUGgtd=3Dq1dG#IgLy0FrW`YCh*BgRje@#$GRRP%rzsL_RNGHG8{st&J(|CdO zb_HbN{7{hf`Hg-Ndp`~2Drh{2U+D{3aHRRzLg;SDOsnmr|Fw;HY7ZzgXNX>rp!9~u z7vy$7A#*2MQ#tO_b%mvRkom&R#QA=pXz`NRy*=)Sw>F^r><|cYHRN}>DR!tg{$nY~ zP4vKXkY^7ezZaASijTa=@3nV?-{W4|;kim>C*kjydD+xo{?L#7oPkX5&6+^?H{Q?%a{!LiW2>y+6e*sEouEWoXAM)YnxbU+z%6a5LpWxrb zxi0W)@{dD}IYl3_fZD;?w$$F{&PIEcHUCn3f7*=f)cy_>(%8ff6mGvEx#a{^OE~3!Op86mkYXCBnH-bXvBa}WQ36$n_qtMLOCZI6W2js%j zNnY0up_fvyI#HTIOtA#z+T$QUH-Yr4Tl7=P$*UWJa_&ix?fMcFJ2&gEq_f-mf%0cf zkk?!WiisOQ#@L?Z(!-P<^a{sId)Cr*r%$K*+0z;IBS&_Jy%%-#$)3-C3A-%0QRtY-Hr%BdhTFae>g0>2+*maZcCsTwF> zN+!Q%(ctgKmEwBL-?ik=0&d~{g&wu!ubOCq@{c*F4{@w9%FExofbuiO?Lg_67w(HO z9ZB~$;WpjBnl8vJE+jw11%b@c{UCqd1r!Y(LE+s@P)cn^=`{>-dUs0q8xOLxXOSE~ z2IPuL;m`P6w5J_cr%L`VY(D&({LvBZMX0_Gzb3@D0p+tN;osP)x*$`-g1q)vq6vj? zGxG(=(s#dl{)_*qk3aoC^WT{NpZ{?eRP1!>??Eg}-ltILIpw56{`BK>3fap27m+@u zA-=)k`*p~Fjc}e#>2qbI2c$VBABL%;1-qfwXj@e6I!h+5G23UzYkM zLv%pKbR{TF-9r90V;|`k`Vb#n21VmAP}Yqm{mFQc-AGGi@NW|#bHAQ|(xulV2NZ#_ za~DGZ_MnCi$M0*O=l)J2fT)z}D^(U73fK1IzVo*cK>AGyl z!g$(?PSB#g>EsI?s9$NJ3i7VQK=$)EQ1YA#%4Rbt-Go9iMLRvpcb3LKxCo-ud?EDW zDWYug59Qmf4+?pUK+cQijY;R0Lgs4>K{HVunF8odM z(Hc;W{{yoAwIDN>LRp0jBEPl{da;zq?qSfclvNvnTq04nr}11-tsw;VE|Hzkl=AN* zN|zP>8~^hke*e_(f%;6b8})mjg7tf#rYLg#9;jgb9;jgb9;jgb9;jgb9;lR_;+(AH zuipdpvBLU2P+`w_n~|_@d^c6tyZSv)VgI-)57@){Jy4^R{PlaF-Uc~m*v&mcX#=(NK6Jy1_6tltCG zTVeeks9un#&n23+hrWIfROGAQ0~N>D?}3W**6)Fe>xvd}C|CU+s3>>+9;m@M&kBuD zg;MoHy8l--;fl<^)fA4ytQ1Tg$=gHOmr1!z;J?4Kfd+bt`bY`YI`62fp_#xi) z-77^e{Ot@s#9W&H2Im>D3;u}jeS!SZgNRH;FFJ(4F9~6;@Jp<^VK(%8R*`>-rQheI zEE-Q|7Jh-B;sd_IKQRXF@|FDT?SJ5xWInV|k!8Liu4(s6vh%vuWX~NPK&FE;$)j9J z{^kM7CWk;Fuwk##TAHsb?Kw*M9~}opyEBx3(`CxW85>Wof3KY8TCCauS(~|PZbDB`T=c#nPffwn#6X-jbDO&`Y9XlEndv^wf zois0*dEBtH!0K$=51;cIWXI9(Si;~8x=(G&$8Ky+=P?}%GM}u7v%*033YCZPH$k~1 z=Z1O9TC_v}Z~2|{OG=0apFrN4?6w$NK=KHpNujv^)gFc1ur9|G%EfbGK$&G647k)M9R^?gI}(mT_B4m%5Jq>ntK{e1Sn6nN zKY;<1_J%yf`HG`p=-7@$Pm!S=$I*|-px7}pWZccrzqzj#^VbFx}cVWn+Va_mM zTn0ymYeN$lEZ+7(4)PDuhM{7Ib%CK0?D9eW-8FQm#joZtTwLcKFkD>Y`=EGy2@Dup zkwJ#+-uxn*Z$>b2`freJG^tq8GndwZ;yDUj$z>GCkDpMxo=FJ{U%Q04}Je9cSLCl_`AWZEvG zdLGr6^txr_D0bZinG-ue$%LMZe6J~`H$8+8AZ|+yo|_c83FJ@x#`BcV9R($GO^`X? zu(r+$H#jQ3TUX-dLwFCQDL>%QvnlZ@_JZQuNeF$k*PZ zgCrPVLdTK2SB#F6;CzYb7z8q^)u88-ZuxR_v?O6W zuFqN7p*+kbW0X$_&_ucUm%l*iZWQi^6ZOgdd_E6yBX5E1X91LAn}Ez9UF2sf7t{SO z<>To?_l1SJ8I2`vaSzJc>glX^ zutGNYL6Ac6*HqX~=4SC_$PdLpyvpqH&2D1Cec$Sh6~bpD&~v>zKOX1x`jengwtbeUkQos91neI1 z3|yMj z%(7;%`+Qkbkh{^Ap`sljM%Q$A9S9dwB{;1e-UI+w~)%Q#Tpcnf8f64 zN@q|w@(1@X&fH3zNE4-{heoI;);0n4CvTcg_2@ziATaU9RL^>qsCWL=aZu<@6UCW0 zKYA`*^XWNF8x1mpUEV9tiLna6bCfoFWhpYhYAv3x+^+?mxBO=(oc%heoX6JUJz_7)$%@Rnze!Rk9Ie9p$FHP4KgB3>*fFW39qfsi)eZK8ef{{ll3(m` z8g_!6GW@C{ODAiuDCA4*KxX#$Kt<*>Hv~X$AK|Z1yf@^OLiY0ZeF}xmvrH8J@Ak*e z)UZ~{CAZyn2<6>v47(-zx?WIZ{`i5*3b`F^U^ki3^FpD&cMtU>THc4>;LiwTk5`wH zzc`c+JI#$*Ms~o$npkoUvWzKk9)Qc?|s$5tK(>1tt4+AosKY`J@pO>9{N# zoQG*G;=H0=Dz3wsv;u`$^KpHyn)W#3KRu`NdG!R@N>h}Zv6~Tx>l!D){>hgNaDRMZ zCf%>4CGMa9)12yMMhw+kxevXE)gswZyBDZm&V2;P-Z}t3CsbWU{Yyb!u)A_VBnE`U z@Gf|7<#-G7Z$skn{OSiXE-B>^GoInOO0G1}BYcX3zv4Hu$rY*%miD^c77 zyU*2LIfCQ!s^Pa7n^p%DnF~z!P{@~?dg%O%|EXX9;J^6(ksmePJFWhFV(Es93i;qU zw-ie0&mt7EOH&>wWIEQq1hr0J&jz;p;tz@}?$G_AP#)W@8SZ03WmhV9U4Mm)PsS*P z(kp*Wg?xJaG;n6{4Cr0k%~dGp{?$_`y!O&p$UI74g!FK`#R_?O@DiloPhO@_RC8IO zkQ;bvHPZdu)`FL(nM1$v+(w1+m>l}9Q|)C3dH4D)3I*=*R)u_co;~y-uN)MzBlm6t zr+X0HouQX66jOc!0~{}VcA@jN@3L9RFKGR-0hb9@3i+`n8^CdXmI^sfTgYPZOQf@2 zMmSFF+8Nj9A5Gk$>@YDjo!m)hw)xYUT^6=T{iBfl25+d0q-@lx5(vA1TQ@6-&wBL*NF8k}F z{j)WyWFP)kg3PctPn7cT_u`(SoO^F2LvDQS8DzJcDGG&6FYx^=Y;BZ^^lg_w@r_=Z zB1;Fpg5q^r$bfI$;uZ83J3-bb2NZJ0zEds&=WYQ#>$RBj zzoCihQtlLzJ84k*&u*Y-T#jH$i#yMt_U zUyvzO2f3v*o*-DQfh-?(qkI=bK&dQ`WK@K+ilG_zCqij|Oo0 z9yD>D-}V`L(Q?pdq-U-JWwT45aKC`KeZUtbT^>mbB?x1Wk-R+~lxlx~+?9b}ah|t} zLGIZeP|%7bS&aq=`QtQz#(&?{ePi?rh0^gB#*p9kf&XBF%1jlRkBj3KiaSrNLB4Ue@GC;zR5L~9 zs&v;OUzX2$)~&MSIusTcf**lY1cl!Q7hP3kN$2o2 zh3tdM>&W-vY^Xv$YSJx*!l?)FD`H#A2u0>Pb%9@DzQ&<{Di3hDtLUY*Bcj2X+3+vI z!+rM^nfK`fzanlc1BJeE@rqtNZ~*>=t2TgtVe0zBuQ2={kQ1^WDfyU+IQSRQ>OvCa zfA&7cdEM8*ugD*0Z(QbDi)5r9eGPK6&pboE!7Eb~ay2T?A&UgVGvWfQL!eh2LRjZ3Wr;KA>b526BUwK=DZ?$agISnb{P0C;jxD;Ag zRZ8jdQn{{FH4_vT?g!bh9FQrTO@2*14&=4xkiVLc1&XsA;jaW8HTWx5gU0pPz;N%HNxgg$#RmFoyv4)9lk?PmBZ?)xVAD>26k{z{&=CP&G~>n?)dVt1;_ip;h<2FfpJ zFGg;$V;;)gwG5PBo57Ek3RgESWbHz$*D66aD6Tc6mPMGxK6-MkaK?sifZ)z z&mEr*KgW6R0NJ_=B(I`zV%F(4=~KuLisQaP7V`R#UkEk=Md>V2FBfE8M}EY0_wNJQ z{@*~(#}s~mnVmxZ;Na-bNIT{UUIie(gCa!Ix4K<-iz zD5rHVQ}psMS|Eb$&qL;mT}dAj2yz+;q~DZH`m$0`>|6sf(X}AAwTk%c6Y1Y&fYOGB z6uD>u+4v(D`dvT?^GyGAH83p(6=4g(S7@1FU4iCu#bGG^;IRE+n9Jm zAur^FDP)dZfW4F3TtWX?p8gqjjZvdD{)G)4V6TK5)DISnn!_$hEl`lmelC5um?54J`J6vPhTbH|50GZJf?wi;Vw_i!qCvLwHYgr`2J&{9ByY;4^aFXI6#4;V z8dp&I_`x_Y+r|PEfB4aLKGVXm%m-$AI$5ShBnQ=7NG%Db?$&2#|FUh%1ah@yrxZ(i=^@yATw9P+*)~Js;=c z%yY<&SLot8OwkFt-gFfz=LqW8v(v}JUJEOClO5N;Ms{4c9Auu)B76Pu1Spz60)C{I+_NV*FPp7H*9pp@dJ3co9{i>GRKDcjRBrAj z$o{b>c~V0F@Tz5yg|p_AzQ&Gdw-%JkMu5C(L%`|^8s}!(6r;Y_1lm)JncD|4-`|Jc zb9-8Nfj?=8_n&!mo!Z0i!627hOn!UABT)3Fg?RZd4GSr(r+{ycrvP>?`UmU>vv&*Z z3$yzJ><@Ec5bTm*F$ngGnKBIaOK!Z6zOR`*uye9y!$Jn}8>nAXObZxrI~G&_r`t`~ zM|N>XP<(kP6?QnfKT-b@`fak>NRS(C2m8tyc0xZ--gqoo$6 zK0$ibRgg`$1BLr5p8Q+?^B;cy@GC24;JRJ3%@s;n`8#mE+%+Bw`F$HsfFI7Bg+8$N zMTN}RGglM}>Cqty*)LPzf8=6X2%j1F_^zUtJipSoP5!`mV)UVduyT}DaIJ!xpDzK z{1DrG6`nWiH;wv{$6Ley@WJ;%wrUmL55AgypODp!$p4&;0OhVV+hlkrl{0IfKHCBcRmA8)QbD z0mVK3q+c0A`UlY<`~E&CSHw{IW0LvN^m~w)M!&bQG40V#`K&3_UWd~{3;f0-kmUs0 z2!s3D6zyAhxsuv>mq22N7a;51u)xa9&SV#MapWI8%|K!BCXnB01^%bo^uq z<>W%B-294K_-UDS1qFkqAlL3V?pLatK-~Qk^}x+~OtilQ^1WTCehxJR>K$tZS(qG4 z@5>!}kHo{{A+z=!K%UQ}`oB#5KH*CYo)7o2KPW$lpyz#aF(|pm;Q5NjJA$l59_$rc zK?^L1gIB_7=T*;2GI9d1I3ma=;w$zzwsO;`3oqX zpz&AP@I5`>Y1BWHml4JMY|5uk7wn3*+cL zVk=f5A73zm&ijtWjpfDFc%RrCG@nd9O#OF0+y#0uz?9y%V44TVKAK8$6Ah5rHiYCt znrFak^nff}qQF*eJIPEi^{b@O{ph%FgXp+6V<`Vwj`WY0gIs_kC~DI@1$H!zSMW8p zls;9P?%R>Z$wm82x-ZL#Xivqix*pqUleG366zoVU>oc=?hI8z3h1+EoHpE=?uIPo>HSg2HF`Qz9s z=$GYyoVoBzk;O-Ye)wmzWn`xo*1%0JLgz6i=KNRLt5q__I3Q1~c=^02Tv|Lq8nBS908uphMfqQ74uzKMK6hM z`YGhnrhqKJisZ%{L8i}UkRL~6OKm8hr#0nEG9rFc0cExOIIsB00_28MKrYvUfh;Wa zqrly1lR#!sHp<0C`JkM9)z&^Jm*p9hU)=En_ak*!49c_b<36Q`8Faq|uPBiA-X4(2 z*$7I)d6E-qh+9@6KgYcxPO>Ieo<=$sRfYgm_WlJ5L`~R6fvLMjf!ttk)I0AIi|4@o z%Avs2Wxw#8xZ^EA{%AW2z;&ylK+*V3c;3>1A9xQ$*J8XMEO&tdtX;q2z2P-xg4~63 zc%Q_KLcCu>uRg@}OYz=uNjLBwN*mNc{#GL1PiDLmEl3jE9F)_CH%2{9*J`AYJ-44x z$gkA{xkC#;*KEGfO6u--+%?@=zLAm()K~zv@CN z$W+m|JG<%`WchPG$c>?ZOgWFv!?^9hdHBQRUzr>oD$l5Bknc!=lJbdc+_#+RLjFpv zKl~Io-~}ijJ3!+l9Q{7Z9GwP#B`lf-f5lnT!t7kf`rjezUmDSn7T9GUJi+_KPo)Kb zc&GR9W1_n~{FqqT3I2=i91QZj0sI)hm4pA{zu3cn@w;EaZ?Vx!;HQMte(*z5$Zq%> zX$42^VUlWNuKxN$nJwCz=(d^Kr{Pvwpd`Wu?OdAO5%z%ZSV8vZc{J<`d-fJl_agD6 z7tz@hl-Id{Ld*hCI@TIw*cW7%Hj;hkQqGW^VF8Lw`-Af1H)OY-kw0LqmXp0Y+Zhy} zJSKlJg!Yo=?dL(}mh=SKq>mJ6?-5CMZK^XUf6ylViY_4YV+hGJ96(n6D=3cKL3S~e z_N->Ls62e>Q7Z2xTEK>%zlZL(?itrmKvUab}EKHEGW6x)W8KWMfa{z23n z1AoC<27}_2Y>*#Llw2}NU-l6BrDZ>G9wxB^El6;M`~^GIlj_T;DatKgmB_z7dky<7 zI;n%K#yQw=KDG-{-3NY}U)&F5y57Ze7gsouosZp0a@h&uu2hh%>4W^D&3aI>zXh`6 zo8i37SZh%7C}vAk*hEo%hNY@@KcZf`YsNr1}WC0)NP=Jf?+3EUIaNgiZz^tD8p)AT*6^%l*su zkFx*vfByZ$|8&1St-k$oW=&}xg2$OcMP@7OJ}DIU2~}Xbm==niVT`x6Qz&N^s3;U} zcO0sadt#)eQ2e1Y8|fc9FNXf`Ya@mH;%%!HvZ}gkLGzS#3dOUsxkBNeL6*>8F93yr z&7f?(%|g-h^M8ZVaMulrEbBM3Rw$W=*(zj44Bw(q7#eG@kQ)-@2>r=Tin_GrLKK|tv7(j6roHcs~>Ccvgd1s;%=IMCUm0( z&V|Jd@i!+b-YDtP^S2quxA_T;yB6Nhg#J|UJB9K_T9{E@I58Xf)LwvG=)Cue%-^{Q z%J2SwjP0Zx=%r;~{X*ypc@wDNC6f+(&TQC~r zhN^?i`$421+>i7VRY7_6UzDF2m`nGOk^l-(*GV6F8f1N_-y|(}hs;YPb0ZrTfY@=9 zj@z9E%2$68zckE8vo>tFJ}saiSldHpuIvJZI}L%nV`;$z;n;CXFZQA1%KRyxJ}s2M z(Z}1b`>^5Xi{a3*5 zG6yEWeu}4p1SKDvHi+z~Q!!-bqd#%*97@-C47<+sY(ku=>VoSH?B%Rb+)#`2@!8$U zF2Cd9KbQldJ5UZS6Oaqp4zjLBNM}obQvP!{aUSl&L!4j8*pBir3xZrxzVm}%-^Dx0 z`*GbXM-Sn;Qw%(D{vJDyLI3q7?7kSg_@p8Wb$7iK@|Qk%gGuM$59F|(ry=WA5)W&g zfoxlJR-sr>=BrTn$@wdky61@sv?;Ds z+@g`CR4vL8eByV*Bx&4*+ zMGX9iIA<)#yrbVan42_@fm!nqdiL^nP{`>E|01oSjdo>^O^~_N-|lvvw;e-8=+xuV?`TzEc!re#=v^e!d_mccgg++=()hS672< zEiJ^rYqf&C6QbLIl5ty-x6*tw&ZrXk`Saxem@h{l3)_~0oMBHoUnd#mmuG|!g?%7D zbOXq-3qj_O2FT7(Bl#Zv{=;8v_#G&Xg25v9iU{J;C3>Gj+HOc+uB??2msTQ2y6 z@e^+3cTmWp`Q38!M96IVB}(7#M4V0Y#JSboDgF05jK}bXKA>Q+2$W5mfb6APD7W;O z=CAYlw9t?=Fp!>;&TLR(3+XxM?WO0Qr3MPaV(2|-w}RfIg;mrpfBJyj+-aaxP>6Od z^`?0~Yz>VwN$-EbKJdk4H@G4iCli}ag`QJu4@z?jssHI54>Hp(5?dYt*=NqgGWwl{ ze@Y9SviFG6)&_ak7UbiCHiFW#wV=>?CCT6aq4dBxAXCyXf3+3;&cwZ)NclDCcTYZ+ z<~cF529UnE3mx~A0a+E=ctC#mitMZQeNbphzmLk!2O#q*)}RzLlhPU5Fo*T|fd05J zGZ17uS`wd*0_Cs2VaM4u3837<6BK@~0Hw2iiF;`t9lQN1em~`}TY*yDFp{s(0y?ra z{jMs$6yPV=;$@)NY#b<$Z%=gl27ki(Cy`&-bb;iMLmKpjrXov; zeL->NMfhVrb1*1#k?_;Zazpah&1>Pm`RX80-nbDIk2TEuUY`y>&po&a3g^8++3_U# ze^rvX5?bGZEiiyy3~dXtnlI_Qbi@r}=0)m1EEPfN)E$uV$pvMr98j3{7~~6LC_O9~ zoozsA`_m-k3p$&qP)y$a2y#(F9BpITc#;>k#VdNIkqyXc8G+JR z+JK$?WdWJ*ktyMLwRo_;T~R;v%EknoKQb=i|K)!)MvNOV=|A&7?C%EubAbGh94*7I zNI^-Uy!8qw%n?9-5iR)77pX!P&GX@B#7+Sq*WCo#p<~9Gf+;yO8rb-8oyv{ ztI5wWG_D~xY^)#*>qUOY=pF1h-4EGh zny)05{e<0TdZ!WfY2z)P*-!FaQ;?fW@rs;wSJLK`Yd97kW?$s00FG~cO_fa5w=sYNKJ3;Os`9JQ#G?KGB6L)1& z`3BQ^L(J~UkfrzO@@=IN;WuP!H zg1!&gO7cU_6F~0rA=p>0`WxBP`%6HkYa;9_>oN`$yM@DUGS>6RjxPTUyD8qc0;QI9 zu%B{odr%7R0WwFbU_bfbWU{AMuY;m>B*xTOk_avcSga^M~DD8#oMH>inS4P3_NQ>ELuxD!P;eVt?LGVB9uov(z{KMn$JM5Dt z@H6buo{yCL!rDm*IIdz`yh1Uq-F<~zhanjEkiPoeR%F&bC>-gzmv1VRtqQJzW0*jN z%$0NJ6>>Q`UeI@Kw@;xs$Z9>(l|28?zyJCE=~17s&L0&~5YN)X>iBP5ZljjqVwJtDRYH@$J%tXA$bd7SBJ}Kk#*xZ(jM|-!(0qidqzF zvPq_wGJ=MfI|?C@(*uda&)1V+KVfza38O)u~pz15dd%j$1uGYvYi937Tf{GwnNnOI==FDn}1Ac62Ho@hRlV)vVfiVf|J!CBUH_y<&TuHo@A@YxZuxVkRm0z1H4nMfe!;A}C4R$q z4hXt>cR-RlqNR)hN^VNS@ITy}C|wlB;x&danvQetbu!`|LjLdL$p3c*i^- zfBVV&E*~bnD%m(Ba%AtMe_Yo5x^0nvCfq!D!1Bzf;RnLQ?hokwV$;c#W4uNFi`{P` z&-+@(1a_NnqikqzohxG|w$px|=-S@lxwC$Fx#OZIkDe4~_83tk$9zk+Zrf?mt{)Lo zde?=V`Lm{GaBu%;gSC!v$+JyeyLGR+|01#3&&t-{)WR3bE6rXey~woOveW!}%4W^h z`p+iwlg=Kg@N(Dgr4z2PVC`JZLVZn_tLn1p(>Zg>?fhEZW>m-B=rGyhV5(jDGFR_~ zYwfL%&mTYe)-g{{6Wgt;PNk)-w4F4}ae``x)t{g5`m3f|I`CAGp6%s;qnS1rVpQ!T zp8D53bsnvH=kCr(5B0QLck>H>ycqKF>aj`wFIKsF-q5*pwAZK9bNq;4H_HN{-1;N z&2)e9#i^06e=SU^QX9ST+Oy~J=UXLysc@ehwKv7YvY(%8*2Jk}qa(FjI3FF@%W+2g z8>@D6UN_FW{t4O8J$Lm}-7~78FD5T9;)VF=15=()j+ztvYo-y`{)WHv-$nf=w9rxA zdCkxJoNM)s59Ku*w`{(ZbnvFl(JjXY4?MQ6nNj7Do|YP^WA!p#&-33i*t;Ta zRGa3b?v;OWJJ_U&PMJ-$=EoGNyQ61&vq??5-M%)Z+n_Eb){|7y&L?rR5>i?;yVkSE z*YCSRm$hhe;B?)TUkCT-RlVErtNqwA|JpE{A%lC&tq`qpnVj%wle_fh zspNuw6*kj4ME_Xybm9r~t>Zg{zVB1Haq>wIcMJVqA!DB=Tr^61P-XKyb#Gk8wwD7s zm_~#?DQo>C!7R^cb;`p2&+B^s96xe&huVdi)>og*F#EDQUM+LS_Eft=+diI~YFywj z@4K|QuZ#1?x`Nucsn(v?_P6YuoTPidRJXTLp;@hO)hpClXuMXe%y1!bf%F2u{lMBsE7Fcyo7_IgwJMeuovmfQj)y(spXHLc= zYV=FDte95a>}_borsqk=j9o@1Sp0r_XJl*d+~R<&y?%o~nEn2x_tk9Px9g3shb>r= zGkUdfsBd=jcb^+C4UQ|jV4>IOM8I%+kttL;KY3h`fne@$U3<-;^`f*v&Q~tXYt-Ia z^=IDOuJYxkM_vVIw;3~5%+E;lc(}OyW&ZQ?_XZ8av$7xmVKm4hQyzFY*da-Wy;p6489rZ*1 zjyN-Dxm&>5q*2e88@kn%H+D?3?=x)r>B4>9r7u+0e9!StX8PI2wq;cq0_!)-)y$j7`vUDk(;AEDY(b1+rGQ3Z(i?l z=338dN3sst&1NR1|6HdLHfK`oU!#L|;Z1Ccy4S2V{_cO9+cH<9`4R2EUf#r*qoV1Cclf6r&G`Lc>qgw;Wbq;r{t+U5tKd$b(%u89P^hGRo7s^R~H8 z=y0ddIhDrUR=cd!S>nIM{pp3D{q7_Nm$^B;@q6jLpdhYLedIQ`1L-?1`z01F=yNQ0 z&>yY+2iCfe>)@}x=0obq%L&@=7uX;D?rZkq=+GUypN>cMv3srdF7?8J?LnHi3ci`l z?7w~5w9ZH0PA$$a`!oBY>e=&0J*EvXPpr;6wt0f#vt6CdBf@&sy*juiHp}qHjKtBQ zCOQU3npLVdjq?vp9CCVf%k1dYM|8aUHyvmkoK`f)V};?|2`(vJH|qEr9#N_GxP5r~(m%K3 zBAVYh6OyO5DL6hU&2xy${TuOGnHecHaq05!`0BsWjU#(hY_W2xJh9U2m|pvDUcrwh zj=pp)r|AiU5>c7q7hJSngA#{n6fp*{5{cW`jHZERzZ+PsK zJ1W}wiLDBj9Exvx@bfO?Lrc><`W5TEzNo9St0dVpa%hUz(5MkBJ#OuKJ?p++dfr0E zzx$*Thq)L1{N{XKROI5nxb&`;Z@_r{L7!KuUc24h&3Egy1eY^IS{OBdbKy&@nt#rq zH+f;_A00pA?yx+{sQjkG5>@lFQ`5CxFY_qxr@3$K42P?~23hC4+U@Y`*E+i$zT35P z<~o~iad6gtd1rF*jm1}!j>SjZv>5)=@^s?u4pB>wj@#bqM&CQ@G)~B4} zyq{4A@7>?AZKrnSyEC7Doz5`({ONil4MXko>UN79KL#ab1}|-0GyC)6I3EM2!*Pu) zQgDK+F4djrma17AtAVVpLa8xhc$og zyJ&F#?M(*zA6h$Yz+lU`6A7-}ta{to6$;r0RFC}H__}L^=lBm|osmv@_>msJp0Aqq z?oy{v+o3C;-Lje)tRKFza>v9EFHF}pwtRTF=Hyb>G*wHfQP;^qEOoj>ElH(Add ztF`3(_=`O{X@9Gl&_DGgUtBdiyUwa&M^n=-hWjeKH6EQ!^|_OJZp`*g2Xlwr9X!>| zbl321XK!vS%z7|!&biHY&*Xn@sFd$A`FbO|df}wGH{BdF&TambJ7?>lQq48z-ac|! z^J4IVz}5o|n``E+AGB zPFm|beoFozyEw-a>Z_{H-K?x={h`y@vb_n z6w9Yg`ltL7KUp4svCn*|=QNeicVc@s(fk|}{x<8d)#;qDNt>g3zUqHE;>b14fDoIL zYrdW_ck(F>Gph+SZ|fN3tUGb=jRDbh&C~vNi5)sR+C2N-!hgO8=#3j?Tx1rL5Z!b4 zi_fFCwYN^JQSZHEOjytEUoW_q4H_R{dbD72W`%hllYy1Xj;9^Yoq2lUV=qnp{2S&m zI}SVC4?Ga1pBZX)XUaK^@cz3!<#6*Dt%~&iWe(#G7I_V-`(is=`&z2%s|)5+A32rZ zxAWTW-^6`So4WC4OA2Q+3s^Doaa`TIET`ithX*8_-rnY$)7{Mv_zi9D-7#4|A#{`O zin^3P2Yatfb^O@I^!FQ;KkhHXEGi?!u1DoaHb3F#{@Z3FuTH3{+B5a%sZYON?bTft zI%LkMJEE#h?x)(zBZrPsTi0txc(XI-9L5%B+r(QGt@S*xY2@RiCWl8(`X2LYv)SA> z=Ra$`8mXGK*JfFIX0Kr*x7VI;I^=ZD-agvTce$TX>8c)P+<(!ly%Xo`3krX?@>pW3 zfmZdUW}~m0^f7w%YHyQ6PanP4iR9lEp2+-bHu7z7c$C|?fNtSm|M80&_3q%tL+z40 zM{jtPzIBq-^*50hYu?Su(y_IAZ^k<=PmYj8XPjI zYnKZ9Cnbh`oN{-)N(<<=W5dv>ZaSxS6!w{C`G`|LF*I_m-$Cg?_}hcMcevf_c3@tM zVcH?vA8z@r5twIqsmJd_`&v9nUSV@p zZ=d%an;shWzkY_?(wv&IiYs}$!sU93$u-p#-E*B@Wu|%R{-`Pb=x6EgxwT|y$fzG5 zUWIJSzLOMIepY|V2k(J{I&GYCaFO@czTG48`}FN+ofMsBbRvA$yYi%chxSC8mAuVM zaIQ6P-)8jhzP-AvN`8>PGi>5f^_z=^Jzv#-zMp%IX_a@|9=FQ2PUxAseA1=?-$Pg* z_waSA4MP`L>DvhFK6vBE1c6V%yt{!t!MKXt+FF4UKt-Qk@R$|T(qBmk=|>y z9uhavfzN9(HqVil%G>InNo(JA$0=(E?ot=$1y{RA8ab|gQ|(>bJbKFU^zK$WW`uN^ zm;T}2njzOVY-*Jnmv!LE?eT`C&TkJaE*gBUnSqvFxY(o9&M6wUS)CkepZ{a8?&$wJ zGIVP%Bgg)`z6EtxbAM}T8&~DzGpTp)LE#~eq3Z(benqR8_|NQ&btZhk=WE}aUe@SsVr`r>-!|;H!Z@hj|JIzXm4c4U}`#t~RkXTz71D&lYn$tj(Ua5v9B*<*6Q#b@q%=5XjZ&7)w!gq z^z_zpf6o_F9XE_RrEM8CtbdYUQI)ap{!cH8hi*xGe}D3V1qTk<9eOYEsl9S>zjW`#S){tQF~js-QAu%*7=FYIb)}YK_jaV{a=KgQ+pj; zxUSo8-h{X#qJggX{}o|idBD+4O6Y^;eb+1W zQgob8$|cb~@Ey>5pQa>w!FtB*XMU_fKgAk72IK5z0%uIg=2VSoHq;KLEdPy7}V z?O)5jK^Xb`h52?C1vLu@GLRLQJXWj)Ff|C(0CyE0iqCQ_nS=D&D_jhEe8KvAymm31 z3^ftQXTN}sBQc)amEO4=eoTBQOS}{q`&9epfVO>193*>6?sKA}z3U~P;-mr3cws#% zPO4h?KP8QM+1r<4in6(`utyJ4NnZfRlf7jL9X z8DW=s&xzbP_jhz>K}_q+j*iCpe;*pv2od#{IQ#cdVWT%!kcAIWj>5C&nxslXJ zN@?}C(^qeu)eKyDcO9KqY^kxJq+L!{wR5GyT}<`)4TcL}wI9JJy%BAz?cOV@-l;cA+V)c0 zu7uhWp4#tpfV1)9(qHg$poeOfJyzUSI83HzITCn^F&F9LDPD=;b(d*Pz2&p|3#=a< zv8*mKn-HAKlhAaOTV_Xncd}cgm@mwP1FL3Aa3&7!r?)(nIs-U z^dkCJZzZV;OLqg6hzuOfo*}}mSa}tgD}sFXSjS*5gG?88Z)Yl=3-p_y_Nl?*XUW+s zs`oU7wXbiOHt1-Aln70^-wfe*Oy0exx4{t4TcC)eN#i>B9~+eI1T`w`Tw6smvS~dWGYYZHeZ^N!4&Q-VGkOrp{lH;i-4Lsu|QI z-Y`)Z#whY@#LB~X<%utw73me8+b;z%ym(!zZuYl9nINi*l0LAkg4xy zxDZw)Z9t0v*9iXNwG~FlPfvo&3QZEds0BUO%~;#VKC15VfO7BceYp`1DfHO(BComj z=-wJ5@AoD~B7%-tjU%CdIWC3QzZ(|_V)hq_R&T8G$M*Ld=$?wQQ;`~YJ*qvHvmtgAc zB$~BR(Y)%m#83+Obi-azXqVdfI2UbCGwZU#3p0MYRPieTt`#ADSgT=+;INqT=F19e zQb$?NPNL0FsAB-4tyI#ZD$!cG+noEu!$!fhhP~8bA$n(t+oh*XA!v;H)BSz9`;BB@ zpWstafR#gQGt8J-Bm8Z+c{ghOKG^i)hrp2aXWfk}fx&@84(fX?k}m%B?-uZ8l%U+m zm&zklcv zU&`yvvQ4t<-dv;YcVsMC0Cj!eEogh`*CgW7hHbg`wQq4mJD_Tb7h4AP z<84IO7faB^Z|c}|mbxVrDm*Uc18<~aX;zw(wBQD!k~Xrl%hw{X6FW7joKy~);bwa3}pCeVpaTLZV65!Xok_79~4-QxQu*iyfecERA} ze6$y}V~NcnbJ-nEvxQWLN<4($!?%;?9g1E*17899@+_;%MU-n9vLL+R}eDTAJs&vGdp}tfzwV>E?BC9cpa)qF>n`sP)3+?UBxBd&q zIA&+|njIU)k5apqyMN#u>EtvT_SWmI=3 zt1yZL9TyL9N1j9yZ<~8qU;MQBY6bd72BTF%C_>}~9z#lGw0|s7 zi&052AM?+77I{_6uoffyyiE01WzB@3x&2l+$*dUcZ~{y{%A^D-2Lg7>znr!HHBx?g) z7WEXCt&_0S#^!$Y?aj=k0LB}a=gL~k!zNaDbC~kQwUP*gThUn65?Uf-8 z(qV^{eB-raB|X^ZLeEFdf0bLrL?8MaIA&%DlZzu}|9p!@YQj6Mi=i$lgUn1d6dM1t z821ab{mZ=XwBXpV1ij&B=z#( z9$rTZbSXq-i?43uAN9h|$&ny-?RH+Wcy?07{^3hUZz_TQUZS$8Orx&WL%kArs)SWO zLoSS|$$Yod=Lvb#(kc%t;MgCN$Vc0tX!f5iqa$yIjxh4xGQU0A62H6M|8w?HXWv1r zg=E`#?Mfym@58&vU)(`DD|co2aF7}P_vG5v#VYmWp~&}eVf<-@A`=dI@22K^T@rlz zPp;g-P&S-4myL*+Qs~X!RE>|})zfvv+?Y@ODp?o@91nv_)Li(xsg#3sWb?Rg1ECJ+tAXqF#CQ^L=gV$c8Dih~K&7TFe^v^JV1 zm*>b(sD9eCw7%JwO)bm8N6LF`iH#sE3>-E*?4g8>0JmMlByWoa(-JB`u5PW9J}`1r z*i^XWv_`^&|E3v!FtbLrc(vHtj~#gVaO5aK-In2cig^hbn_4NOU$-LZrH`2y(ZFY+i1^);op=+_Ij8j`P`9T&Ieij)Hu%EJ9Ui5rr?%**vFh! z45t<)^*F*S50?CSfOP9~idx9*`6#W*7opkcO<)uGnU1k<^IRI-Zmpi4rVK+k9l6-S zkp7*RT{@5gQgYjO^r~h2&zpPFH}vgu3(z44`j>;cT!%o;cWywm0KQ=w9G2La__SG2 zvvh8$A2^KEC(RBN1wl^cBwe|Ey z_XZ@0(s1f%<E|$pdW;XA!>o(kLfJc<(JO|l1#(fvA z(W$m>#VasTdVWXm`xeEYS%J%PVVixrF#4yTwBwhX7~;vRo4TioA~6TbQpx-K=pW5e zqyU3@yo4viNoRXL$ZAh$ioK4KjYS3`82Qr|L@SMML7z|-$Oa)k3Z$i@Am5$*ESqe- zjCUFAK4;SI?X9z^dBOrY@owFdWXLb5k;L)9*f_Jp2;>H?ZAh33*S7Y@tS>bMzL;Z+ z>kXQp;rGx)!kMM3EW14%w2dP$oiJa!fU3qqN^#b`sbmH#cEuJauLNiWs!l2)QS5;; zU?M$WJY?8h#`wOGU8GnlZ^ylCL%-ppSSW?=q$v+8d0Pi7f`+hQuaQ2?91 z`Q^3iiGEj^o0Bo$i*mo>RI@y6@5{5F)R$cNE;rjfy0_Jh$z`)3h6+c-$4_LA`n;Np z2&VGhcfU2r)L84888+VQ3Lkv+#0UQXeB4zFKWRLr&?qTPJR1=@yOwPbUbSkVX4-ZR zeEw3xPey2+Eq(A|UMhsB7eA2iU->sVmbD58HTal}Ek@M$EW}oTOSQ)#bua=7E@eMB zO&{V8oJ4vYxqxEcZI%I))PP9dnf>6icQZn7`_lBucNc<#QX0zNua*s(s-d&{2o(2} z=mP`AEAqPR!fVCIcv5rydG4jjZpQjtFhtHl`k}tl7=M_ZVvOM7jC#mD;Yh&$h98PV zAxaXOOf(>T-)ICchyW;RJlw?i4LAUe1LZ(&#O1#%sSbZ{etMjL=*nQ8ke*U18;#YX z!O~)z{fP)Jq}Qdyqu(dlxOw46ih<5fL=Wm6hWLx!hA`BJ=@1pzMC!L`tHZj(7*Mu5 zAN|+zjrYrb*bt`%~0YaCkw5b4inN*M+)mSyO|;91&s~ zO5c2qD+N)D2%UzuAS+OyRF4+KMAnq!GxsP73zp)# z%=s*J^lW*2-AIq_D|9p*OIplf!CiX8G`R%8pp2Nik|8p^YjW>V;KKNKS>|8a{|HS~ zkR3+$3hl$pLkWciq&9v{A%~73bjUzolHMG<;lCpz2l9*)*p$18{xtu07_(U=W;EXI zUH5{ENL>ykvQvt%Y@{6d-YF!;h}**7U3ad7jd&(jw1y)DEi$L9-mWKsYUl1;Rs{pq zTO?6CaD@-`T_kLa%^fE2PiVpeit(ODtgDWZ8%djBWg7xF1nFjjeZSq`pBa6tD8`$~ z{7hNID7&DCRvgzS0jO&*(&=(Igwa;n{$zN?camC<_v(SfZ^~KZz=Jv4fP#u29iv+} z;r_E>sobE~UbdQI@`mLP5(~ln_Sa}w<%@2m;FhoN8yt8F{scz|YLD6g8apq!|J({? zzIv-{Ftme~_fz*HaX$FwX8t#XlTUBSz~IFLz7oxEm($M`Clvb|cv51PQrpgc=Y1KB zerN6*-(C;}gkE7}O0PdpV0ZDTOe-#IMkT>^uKhIjl|n+OHNlE&65q@E7`*2p+4?z2 z^3J#?coz5HnEKs3GJa1r#NiGzVCviUKQe?j4RchVH>G+(RhX`HCjLo>nm81cUq>hG zOa)&`kM7}@lG1+`8mG}GRo+(r#>6PRJZHkh`TnFLx+$CF$d>CRZCXN!iTKDGoKt-1wYNTzRP7O}FZN9wfekrAW840Jbpk2WPTcVk((LIf~hYK>x zN@(XLk|7mKXKkf~HFrZ!=jD|ZQrM;`ZnNXd-a{R`F7T@e-dy_eJrM)la&0pM4|Nry z4<*^_g7!9Q4-z8b9svt@Uu-JcLoNpGme>Xd_s$s^xv@B&1MEIotusy$eY~wg8F9gu zvGxG;>0SVoZ5{k*ua^ZtA`0ig8d3B@R|JMlDKU-_=IL)42=B>g2LioY zot;IK*;~skDKH!K=Y6cpizig-F5!ob3lru+;a}Uns=ZpTl{suNvkKn@WM-z{9FtOk zn%iG`a#O?Hw>sy#hR3E&KIhZ7rO+eAc$V-iy0zP@%oPRiOGz(3a9WBg}HmkWn9rk#Z$prT&r_DXu+^c6?r=6iq~lW>M@k50ex_ zV;jAjy(V*g@Xz!#_hBV|_Z%SaFTu400dSpS7>CHUF4$(ZW48ENEU*LMuAT|K)H}+d zT#oWP>3qAOzSMACu8UKQ#>8P0wPlsl7{HSZgJeivgGEH8BgwllvWe}CI_@%_v{$-G z9^R5-v`ICqF=>0Y{Bty#Vdf|`1o#}|b42fdW;lpVi({Uu*jBd_~6iUf|;jm5t711U1; zIC8;nz945T#lu)SJL>UJkII|Zh|jZCkzX`;r9y4|UGRfANmCJYArtg8_f7Do)9ZQJ z_wDfGGW@UrjL<7*+gKbnr_r6e3QdBH7cXkfaen}Ym*X8KhGAtQLUJT8)>CG<153G| zr~HM-7{T?UsmZNxgJmY}(xGJwb8IBg;x3b>&ZYP2fD$@a=!dgNL=&I>{0xt#%9yiy!%V#dbT zTQ^(zIla8EYmIJQML4g%l%+|i?!nwXZU=ivRz^FEV~wrj_l>@8eI-MHt6 zbz61LKd`1rk3iDuuRZJDeMap8V0-(aL;Xagtb7vd5+4wVo{RVC(kZNIbjum77g!l} z+93{YaY(q;Y|si(d%4-_I`{_v-cdf@ab?R3@tc!@nO;htn1pWFA+A0^7{ENt?!X_e zaFn)xY-skq6w$H39wT6S+y=_;y%oKq1eUF<=w7V8_F-K+veTN*{}lsddrmdctG^my zj+Ypme>@~3^m?l*nJoPwjKR?5=7ZLfyRic-t3`!N(&GdjIiPwSUl~EG#ol4=} zk#l+`^%>Mg@Ts+8R|5?h&`lZ04=MAj_{pEC#g7`&5jjtlG8pDN=$wd&s`C1t z7$lTuwii1{)&2_06*jbU-e{t-Wiy*`wn$}5iW?e^C2tU-A+=KoK;Bn~+vQO&b00HR z!u@=RL>K18587K!>!dn_E#A(g#Ie|h7iGGfs+E2H?(3IW6VcC&vP`hFwBwOn3}M^ z&~;ZlsXz6dg9US>^JwoI*6^H(4hJZSJA2iEcYj>$4L!DF?nAD<`!>&Ou7e5Lon8hF z02zteHkZ%iI5z1}4m1-_!8V@+n+%uVUQA`^)KJQA^--a0wheGznSXeer$dYFwu=rT zkE4#P0t3$b4hvD8ey$W1Q(QcqvumV`6UrNl)1Tzmu<3B zcQp;yHG;b{`kKtzBP0orUvJc%Dt=ebGM@lsLoPD->S~*(L2g=pGZ0F{fh~&p`6vh4 zD_GLaDM-T1n9HP{VPJ5oCdr5B7r&P7F8{--#8c2WG(Pm-4DN5w`cZ*WXtEOmCuPpx znM@jQcOM=sLVJoaM(J`WGr2N_+BK z&GyRv{PS>Ly5z^CY4SOJ^k;^CJ8;OLM!jZN7C|rKsnAU*dR%2dR+nAcuGGedwI;9} z>ar(!3w{Bw^I>;9C5j7TL%p|dF!#-PJ8l#R$VKt;PHz9Hq4Nj zC_%&$J(ojBRb29BOXMzP@00F6GbY0ydhVjryPH&{K;=+4TN~sM5u9KF8PBR|DwDz zs4P;o#tAQ=N)3k#J+dh|MNi{6GF-vyz<>;o=na|7x7TAYbywNm#Ir(gmEtqZiM#;F zgx41Uz@lit5aw;5!y1B#^}9%LVHF9Uvsc}Q`<{AXkRJQAc2*aO2l~DnKtzSklyVQjniYoXl>lBt`D^1?ISLABGgsQ}hCg;05Gs3k>jT9xl#!V?oH7&4DtDAD0HlVNhC z3sM5+OW`F%nT|DrJT#%i_5X_*OQe35!D=f<{E4zs-0{2oA-yVs4^3X66+J0Jpgy*LQB0A#tgyDa`fH_z?8EGwU0>jBBXj2$!N zsYQ%;2>)W8Dh-$h9W0JqBL^EJe!cs;<#_1OFDAC0h@T zsGjm}RQM#7*>(lXLiW5sw{rVk`W9*#wxDkl%e!#}Cu`&`v4vUw^~$$wKNrQ0$YIuX zeTQ8ibOVDh9Q7Clv-R^2w~5)6*aVI)<3|LzAe*nU#SQGIGk-?}v z^*x0K)Dr7W#yy4L?t-~oJUoMJn5tAtKZq-Gmrf7ayJ61^eW>NA1^-ZkLVS9-t<%HI zbp=R(DHI`B1wa45RLNbDJfG=0u2c|ga6DZmJi9>l&uWexFL!*O9#Lm@aPn z_I^l3Wakw2*H2%Or5Q8~xARe*nUWkwve7C0Um^mTU=?5-C1_Q-HsU4Jj0m`2!mk@-Uq`8Tg0O;G{Qz1=< zS!LvG7MEE>4TI_W#$p+6k~-?9M^)+ddfCNSb`Y~Cz3m5EXc~Se)4Sa3U&w0WjFt0| zSQ_OO{*7RVdGga8>^hC=JDaMy6mB#Ar)+i24~If1jfXNK=!i1Sux>EpwTPj{@b%KN z_1t%?u74ZS1b#{N7gZ>pB6vohy||zUaLluFY`sq6tPg#}XWW8!vE%~A>e__uD_QDH zY7l$=J;xU3odb$!rcp5?dSNnWC6YvVekmb~($1xkW5*~o{4GQ7?)7|J(I0+g7rRL~ z^OEe@Ot3aI|1lK86z4vVGB`NxU-@x@I7ry53j?iU^WVUcnWRyj&;r6#4m&aYJWXC zc-yK22ch~{(XnX47G+(`Cxe;Qdv9|Ny1%|x-hSlx<*)ErLRC5^^n}5iaixBxYpf#( z<@KyI4nAA|jua3zJkoS(3~-_yjt%(lhiI_lFLacCzH90A&;y6}IO2v2p^u)Yt%g37 zH1qC$5A0UGUb`RqM~MmL!-t2;(c+rvse#UDpg%?$j*;N~7pV~bVv3Wqv8W~Zt$KY~ zaYO%p&ZZdoDlI6_PQK~GQqMUeTIq}zH&CaL;+#l{3NEob7nfjlUY`}CAYt?`e53-;yXn111`6)Skzc?-BUz{p}cd;=j{_Ot5f^6uYe6-jQ9 zT2bP%C%v@kp9uCZ`LMYdQ}&q_UvTa!Pb|s(r6UC1fu#ZxXNBe3SnmBM*Zfq4#jq7- zxN8F^!ku^T>m>7Kw)s_Y+^$$siT1-VeEAyh75$4ko3E88?74U=v8O6qP?|t{WSQOI zuxfA8LCh zJ{tEHp)ouNt$Y2xromQ!iyG9FY$TZ`Y;4jG4K*x#dahZ}rs4Otyy}6%ZX25pLb0je zQJygY`r#wE7{>2>%~}*rNiE(sA|sT?HivPY*59mJLTP>JmoVUOnIOv9ktU=myTUS=!z>EjF>S?QswEY3j@ZFU^jRT7qMkT~Bs-xfn)% zQLc2gSc(KVj<-ZWGT>T7<_4iO8o9cH@xJ!W1Y(5Jk?a{Rw%u>{@KLaH!ccB?odThc ziwIPrYa1LF^aC4bqC-tx{KW6Ov{_u?x4p?uVd9}pGaW+HLk~Wp zMcHG#=YtP zyvz<^u?>EE{my!f3=M@up*r)Wyl0`_2~|Kr5Hq|Qt2{T|P3og-B@JefpWLWeS}b`{Z|UQOF6cMHwA4fe)#$JH;gsmF&^6^W@xe#I z7RB>^f}R4FzdW|T^1z0|U+2#O*RR_?U)*tDu~n}dtHFQGa@0^ZZs6IX`T`k0;qnlQ zl*e~V<*Bw0af@)B%?&U+rZ2nRZR{~um@8Y}Gl`&e@-}x|*o5U%Sw+grKDYxWEq3eO z&4khuHr-SO;Ykf0`1DjFgDhCd*YtSd59uDwr=`RLXKik*&gy8|O5Zq$Nzaeo#0t*_ z9I)eRyE6mcU=c#OmplB)&jo?17E81ZpPeb<3Wi&We(j|LPh#{4B3tInx{;d<71ecK zpCO^2*|`GSI@oKkVa{S>+PHhf|7w|yjNdmvK1A?ZE58HQ&Drbc>;BB<4bd{Z>+3rf zrLHu7jb>X|Aesmx%GF?+JmaNib(#8V7x>MSidhI{kyy&ajh@R&FBqH=E8b3~y;PV&{2UQf_eQD(CTA?K}ec30*x_x6wgj>(xrS zc4bY99;T>_2Pj$?!!T{DkbNE`^|zL@r)X6GT(er#<3a_q{FY<~49&6I>MT$}7V2N+ zSFpFy{+1h5bX_Jz`j?lxcu4Zqqg$z6C2^5S;ehQpI&+gdTAzMA0V)Q_RWzK&3~9EU zCn1*1$nYjFr!ksnx_>aD2i;WoJ3f zyiC+TK-_vj2q{5zR6|I`L#;G)*?HGhjfipTL*8wVXV$~?TJJ3efF$>){l_!Y|5GmW zKJ0)A#&@AuiQ#Ra=d;DolDW(Br*$Ek?F#|S+UFak4ktURk+#b6OHQCzvIQ{XHYKo> zD19w15)U^Q{O+QG1?f=Bd;!)U`x#i8Kfy-|`I*coxw+5kIQ=?v{YPN#TC}$gClis! zKxb<{M{-Cd@9Ri`4AN(q$@_scE^xDj(6s?~1y4BsgE8p)^!}n|V-Q}1fi$lfj8^(q zrnfiy3@vbb*(3RTYNu@_LM@At$zzn)Z1Q*TZMss8K>yFE%cxafO_;Z0n5^`6mbzU= z?zS5eNK!tW76vDZZ5Q9a^4&;Y*YA-N*XwwmE062q+d+YkIc3941bCjyizb&%VS(BA zhQdwyQ#}tDzti|*@J?n532`9t9F8kZks(!dQVJ8UH&R`M?a?9AKLY&l%N4gwTLOTq zRxo+F=NaZaIe|`p?J0s-9Y^i=HX8i-wqofPoiEG!a{`>Jhp73ogqcX$Wrk&9jr&?8 z`93oQ5w{;w;()b4qG8(;$5QIpTjs+4N*?BYig@IHrBV&-Raa#d9|JlfjC=EG^}$)z zd4FRNdv4q-n_{|I@QLHXl)vS%0_^V(mgo&zS6^=ru7)E*qH~~7cfh_Zteo!MH!iHd zc0gMtsmJjU7kB;>Bmd5Ww5H6sSRn)lM%Gf(OH9G?W-8a}i8+JcLh*5w1Wiru(*^zZ z@iNg%P<+HdVLx)o%$Qy2$9i>qs!_oyIx zG^3<{zAq0tz2*Ti`ieN2tA?-Zewwsz+0Iy$G~sjGSCyhLx{VL55-QwQ)UFu#7g-|v zt!iwL9>v@nDD>~MWP$x~E|SBRgwZ>2F_!5Ot6w7g7$?^hSIQM_k?1NgW-!;1r=r|P` z!ou4!R(_vw>^?#Z;|)A@UPlfwE{>#e?~uTKxAV8MWPlSp%ikT;v<%w?FJM`WnfBM2 z)#&p2kzi_~3_4`Z6Gt&SgXX`y(4!<8A8`;RXqfDr$DZVnLr=6aZcApA5udB3lsd5C zA&|=+2vH;w52rG0eg4B}-mYS1&qeDgGXT>wC=$J*iz)yPvBLX<5o@tm<&az^Z~tB0 zA4g#3ET>{xs8ZU$)WC7EpAtmT6R3o(;Bjnr(E>1eHSdZ0k2J5Z`-eo`A1(4N)x^JX zAl4_^$?hLXd0Gs*dxlA%IF*{GYZeg$H^A2Gnq#3m1z?+0Kz^_a-Tn(r4Jj`6n99|B zXzvRFpP7-5GmHK3zqraD@I&aEE7~9?7_mV|3nOr$kuRGfVRb9XG~=?MjtzPYTg1JR z0+Qq){_}3KBvf&wx~bA@E6GDj%gYG}vG1S(`~w5pSS)k=88j*qq1UP4WTA}82Q6n| z*NqBgd4=CFAEaF8`7iP@jf5fP9lB6x)!?z-0=0TSSITl6Y8OnQv)mFN_yg%E3M2?W z@YxC9djuUg(+TubQgtO6=t{?S0AfUp#HT_!{R_NlWRE<)gb#^*j4j5ehb-(e5SaF} zAQ?Jlt_5+^p*pBui?;-n7y94DbBYmIS0Fl)NhibPO%xYE%Wz~McHd|g&!Qg9TdM5K z1p61+4kU|llw9FSkE}?3*3#DH+Q|0zPxS#$!#K2l*Z%wB%neJU!#W~$!xw0sm*k_J zW7*+z$*f02f-R3aZvBMs8DBnyqJ=VQf~tVp0Yd$OAqjgGzury%Ca}CXo`1*rP4Fo3 z&SD$#M$Nrp=&bu2kZt;$@Sgjdo&IsQ7d!`{(bRAK3eo=m_9GQ6o8eRJO2ot1TSDHC zJL4Ouu#6^!#rGTX2Jrvvm-A>>(>}IpyLXu*27SY)qH{>pPn8#w?#|b>rbXgB9*;t9 zNd%v(4>FrU-11J7Yv}T$UI2CWSRv|N#^>mEZ+~JwNh)d}AP=w<*AI=q1}b;>h+M1s zkicyCgAnj>Ld3b3#|O`Y3Y^OeHD}3x$T?%9n<*`AlYh>9U^{P$&K6qgv7C&fFgCOz z!i3K00)ub2x}VQpql^U9*#c$@Q6a`REgzk^LrI2d943jkQO!!!?YAE(pvnYVOos-P zUs^Y}1p0X~vn{La^i!~+_H4gW?r3$B;6o=LJS9QaW_@Sw?_qo6_DZ&^jjBt57_WRyIk4pii@!~b^3g~Y_Y388GK${G*sZ~90YnLfkF)y|z z9t=3vbw8nT$8Dwd-pL9sN4$&)IbH)!u8Z^9RMPO=B7XnbY2cp8lKyJH8meNb|9%pE zeNk#})^pr@;;zV(C1yQlDOT=}`OtPL6*YQ^FT?kgM}_RSZ<{SwnM#5HlDS5&4v`N? zAkqHQ^afny%2~_(pmw9Uyh^Sbc#9Eja}_cuw^|%G%ybf5DW22e*fp?kNk%0}Aho#@EnF*O`rH#Gbztf|&vpeVTsFl|COpA~2V9EaKRV#ar%|i4X=^_( zZoFinyv+axZai*owGleJ{3OlkWI%4vb82)LqgEP3JnT3_IzTaTFBsEPvBZ`VtJLWF znd`#~pmw9S#p-+BrVeG@P3Y|FM)y?Wnc*Oi2Hyx#JYFlNYTT*FI3k_^&nwJ3xeriN z0f}vn8!#fldR*&&IZ5E#+m_^Sd+{Jm?Z=p3Ld-e#fesf^f;ezx`K0?xTzD1G$X8fW zc-*;uv>m2j823A9zsGLT+X+~%R)|yA)xSn{r;9QY6hGNxHhDDOCcAV!rb+T)D_5II zbZ`ij7O$pZ6Z_EIWLLI5s3Db`CgI`6 zdji+Pi1csqZmc-jOI@$1oHKWRC@#TYy+pEq=Sgl$?aB^iC zPL3wSklF-t$Op9~zIjNnSdDMPd*5IoN8KYKhj~_#-@M9y$-Rouq{FfOn@OtYFA4Ud!UOJswq|{y^yeC>9=R;parE{NdgtAewNM zC!ro|2^keEmB(3E>^Lt^PnYAP94Bl*6&LJppOL`Wx25mr<%AP@UQcgEkg(RQN<>SX z&IvDTX(Xb^LmzmDI$u%2oxFZFVrx7j>NXuM4@9u5mlKJv03M_Bi4?h4={Jza$71U= zVMf)Fhie2C}Q@gPMFZq<=zg`oSk*Sap2`@H}l46u|1#0%`C95Y#mG48Z{>NQfNAYPlF6W-s;1mzQ@2?f_41sE}WE8G+Zi zaJ8Jy$x9(-dvonGf7y%JOMNpQ)bk6@+uvE zv2$fAK$l#-0TEoh`#EvBN2v?Ka+{la-FxkkHX1)QFwot4a=~+$2{U%*AXQN|`uc+{ zO<$bp?$creI>%ugGNRTh8|)62UCqLTr-%N#v*FhA8xoL z;))cI0>1DWAd9nl9ZyBN++=h4iJWB4J_@qfs36B4MXP z>wFEZRRvF#5}maUybgouo&68{q`%znS5>?URt9oLy*wKpkLM^p1ak1Z=MRU^1P1h& zHFCNcQ9LqSHi&ZWW>x}LLyz;qN9y*N$L$Yyw;glCL$f}B+%gCLpS3QR8v?lhes}UW zGokz*&D7tjy{qFrf2Vl8_VOIdnH=2|29}Rohr#)|+Y_B-EdyQW*uhepYxpN2SjYcj82U%b^!V+Y@*f=d zlyKTV1B64^L9%pi6AS~r>ieKmIfPr&h4UM+v`|lV3|G4Ykvnkmp!QO`sJtqnmua8_ zX4g2z5JkkhtFx^*v9#m z_v>+$`o8U@xXQMBH6>chr*@};NN+;^ypxh|V(_;D^Cg24)7ai|p5y)DUX8?XcP|ao zQO;jIpinYGGz8l6zYzMt?|Lyz8IGzqfzj&!%@|7knKtJ9&0+wfVo5Y-ZZ%XW=$3M;Z9i|$c(^AF{`E3#}-n7 zja)I^a=>u^-cXsN1`G<9RBJ55!97Xg_%DI#2Zrv4mOR+Kl%?_J+mg1daL_R)64&S6 z?osmjJ~PsO@q5IQ;ytS`u7T(7t!i?-VCtcvnZ?~LNt>|?*jFfy0if&b&uZAw?aR?r zsn^wz8Bd7=*iK!a3U_AaHcey%bW*@M2uT_eHb?LFg=-E&Qx*~csBz+a#Q2B9ZF;Lz z0+{YuJ;*`{UtW@hSM*OO!wq+?Q1HL|&Tw%({SCW8!xQ z*F+w?F9qkuZ{Ib_1Jy=(Fqu*5M7D(E$7XIw0|(oE5t~oE*)yhx$1%UwCG>>2)T=F4 zac=8b6)oJ0|HP*qPM2k3-WQU5|1{eOxy)xiCO1zVF*2kCV2-O*9Tl5izLa}$`da5D z#J~QAyGt|?ngh_O3kQs(@0kmgZNK`<9>D?jTlBY{GMgsSG0>g!ldf@YaoU9T_pg4W z3q5)Zb(bi8W=gIF+{gQRGB9oUrZquvOjc1{f}Bz(hOv%W)$)>^l-#Uls4q!G;;X*4 zuZPl-vr}Zw$AF?0$N=LkRu!2NtdK~19`5($FF*RnBC@;gfO|q;t6!cS4@tMc6a@^Z zgeR=?;6w2_e=W8y&b*lAfs>hF+LA7@`tNr{({4hU6-iI|=R;wS10#o#N+n4?}f^P;S-I&JdibRN?)-} z96muFesrYgEzfeXgxc{Jt=m6TkM=DucN)1G47eA5A;Nq44p?U*<}grPgS;Fo=(Lyj z6cVe@onLT&Jy+TaXnSBweGRrFnhcYsOEAy9ko3AQ-(U(Y^fCVUbu6}_nF0!4K^Y{g zF?k(9s1axuh>G`6%CS4d8`v5gd%bWJg1OSz)Dgc(Ks!E87v10Ag|58omkJpx%Yz;; z@Ik3vYq`P(Jjl@VFX{jN@V0~ClgNyd z5MOl8lpFDp*om6!X2b=CzKluk%C54;6D@&|MX9_4Ut2Kqpr4t6*LY@!S$_ML=jodl z5uip!letdgR>b^JlZkR)%?DI86%l{p53_8Lzp@D5Ij`XI()Qs!6gau&D}VcDmMffj z5zMbQ?S%1?@yuFb4Wg@eks*zZ*S&C?1!2C75EfH5iiDx$4hP4aLkfsPH)mje?DVpB z>ecVlqp0PZH&yzR`BSGHS--}G>wD#4=hX@WhvC4F@|H zzme|4?-}9>e|1E9vXFn7-+1mAVCVVfjYEcxE%FFZAa^-!vxSC_4k}jp?s=^UxOmBn zVWRXsC#O|Oq6@dwr=Q|Z1bfO^<4woI#z{yohja=+X#?hXe1c&GD;c~a!;^0E^4B8* z)UBsXg!v|eJ4PfNzTk*C0P=F5-WlQL>Rh|uQ2aB~aq!pfN#N2uy*%qXZoHnjh@H_H zmA1K#NsSP(dc8ai99;_sb?!FRUyUhIbgY@Oxfn=4K71V-79)I@AAg6)B;3+s;fYTi ziae;AuAXNKgb2S3+f8xIIUs|09nsrC;=QIu0w^uBrSN|1?^K5el*@51K!ltqL=6EPY*Ig{aU^#3zzVFfA4Ix1^Cy^ee zVT=6cXI!-RGgkZ*@W@1}@@O*1f{D2GgM-+&H&mdOsy}O>uvQXn+Zo`3W@NlwOMN7o zr1IscAEl(slO?OBZFs9jyiiWdJ5h=;!&hJ`#cI;dj1Sz|Z(5BU3=xV0P zgmd;x{X${p#QM*g&8l!AZaQzXS?@1RK}`7uO$dO)O%kJ;Kxo6TLGTywc$Q}XjCt*fy1gRTX>i9D14nVUay4}TIft=NR&L8hBu2ItjDdsl z{QJvD;o|?$bxuK+Fu}H-X;0g>ZQHhO+s3rL+qP}nnzn6gx2^l%#}jeRbG=q&WUXA^ z%G2nt*uq=_-6;bhGl-7c9~Aei1XzX4I#PF@AnLXI{Pd@KU^(}?M2))NSc~V`gPcJ^ ziQF>*x7Os-xPJh%xy7z9zJHABXJLIdWYR+GTF<3teR9FigBwkUzo5nQWDak89l|%! z&A5n}^`uQ439sZH&U#+>sO-923vba9~6@KT&-Bxzu2c`}Kr;so|7z799X6ZEFqk>6~jrfsa2fpjn zZNJ=Cmg@+M$;{-pHR^k9e?MY^f|ewZmy6p3g|*@_;vj;`K2`L(eUU`>#sd?d+tk*( zVFH5lEo0t{SDTgUP`WPOH%Yt8XfNOJxPGiDn`TCSS~9_ixCc}_^1HFcSnPp-JN;Fg zC*QU{itog<2>d`M3uwHJZc|gJ?q=pBbZCCnSL1PZqC<2-41~r)SNU zN(h;YH9aE$J8!T2-F4A0YsZ1#(+okm){>etwvizwZb^<6e!0z95J7TU#`Agf%VYIAml4q3r`xSx~`3Tl7IADbGn>`#t>r0y?eq|F3Q!GWv7A#_# z{Tu}kHQy%cpvbBW?6p)UAj)0nFMd)wlZXRM{QJuJRg2(n_yzL>MXG+TW0A-mDUjFK z;T-j8q`z#R)6QXne}|e_FVL5v>d7TM+j@llHYJ7tenBoBed=|AIp*(uI{bcCK86J+ zLJcq5UeQ1kJ~Rol+(9j1HJ}vj0#7+ZAwE|6H#cn)s@PG1V`oMMM)XGGu?c-w>Sy2d zWkl3jd1ABnMKXM|1ityAk7T@=mU4{a8zQ-|+i0tlj+jNj-5M8*Vmv<-?KW*oB>iKp zHHHd(H)(WD)x}Iyn*M_S`4G`P8(OIgg~azAog*HO$WDeevdY&hA z2!)fC4TXxfFS^{G>ai%6f1D=J%V!W`g0uCRN{_bR7XEKdz?>NI6qmFaeSlW$z%uUdd4Nam*{`FK@SxtDaX&x{5MLSOH*okBl^Mb$f-L|AuZr$x#a z>0})yc2_kjpE&9vM~NZmX|@1Ip&QA_@7jJ4Ra6r{t<~$@0f}Gs74NJ{F(&^P^f-n| ziSSuWuuAlPnmCp-lXe@!8?S{FQ|?RwD(HygvVeEpPA4V_dX3zQ6Q%f;GIU1bsrrwv z#-UP-jD@>+)h=b&DEL<)$@j>3w=^15bVB>&yuYq7Q@S@7UG4hF>*uTboyl)6;Aifz zSj))SS=0~qSD|KQ9CcWWn7g!~2NPgCpsVz$4HNmLQWHcc?SI#n+^P137UOi2ybqv?p zeTNEE8`=n)boeR|;MZR@=!=tce!Z?;eM(sDu{rgZoA1o${B%RgQU`6Yx!*9;c?R?% zDYNQA+%>QWZdU=J+YG_Oc1J0JmE2{jDMXHI>IdHc9O;sK91hx;Re!qMfDyV}x~IOk z`*956nKkDqXnOZP`g4~qG?OLIitx){BMPnvDI@}lHU}*($7`K>_Ds8FxOJ)m*JlpF{;mUL}Z8awuLU+qh#_#j!vvD z-&p->Ri)8}9tMlG1=|*X1p7soDoH0*+vK}68$Q1@ycERi=zIJD5Mi0o`}^?|5NLe`Q?2}AAq%IgtAFLTR6C#$P`Rf9T1Jso25w8# z7YwVh!nq{K#ZJ+>QUj4#c`=QRTa`D*&0h_X9r(TFC&hNl>(=^Bnx?y3_w6iY2bY>t z+4ay~B3@}z_4@-$t-o4qqaP#|i@JqS=v8~XGdi=nUk_t-rSLGbZ_dYu zZbN>UgOg|3_*1;7F-TRQF6X+oE-Y;DMyI(@^NY&t+k)M9K0Ilcb_d z>y{SBS#2}7#s+k%Jc|THEtvG_oy6xRbcu0$Xk7L1=?|Ta*2)zl;~UIf29--kw;{lA z(!(X=8(`-!(af#Bmk((AGs-P#I8e*Iv>=RooO3}KcwOrj0lUpI@M4T7E{E0S_rA@2 z6wW#4Cvs8ztQBqpU}29nS`7rtK)48XQ~r{}Bkx{k;lEMB1D;i7+S%3)EsnovBWzqc z27CZhmUl1XpQAwv-JnK8;d)8_W11u037JS6t0#<)$|n8W%Sgfo!IxXgFe02fJh$Om zj*TmJ(Mf97NlN>LX_uKI8-~=*J;(W(%+nuC(+JRl!D^0tIhaPrH-1v@P(}LY2i-^A zn1I8)RoQ!V5XWjei^J_zER#>xA)4H?#;A(>v`R4($=&pNuoI8RQ3FXn^~`@MMmNLe zaSJ44XcB|EH8U*`Wv=CEM}~~Ecj$FK3Z!6h{xG44RG4uH%^CYXz9JRQ5kZ(8d+?0R zWn$xN?2v^)9G7;D+;+Y)PL^uKu-s5op?;y7?C1Y$d-rG7&y;t+aA2y35FD`F%D}EC^zfN{3@^MgjPAN58_UEHH1(mCC*Jj9-Cr*3z8EL}Qyx@fB6TcD z_}r1B!XN+S-+j^UO4X%sXrV?kku34?LC9$9k>JOqGLJ5CBVg*aR3Nw|df>BwVGexKjTh*x$k1US;S||tNZe4Gi%N?a~^ZmA#=5# zT+B$8dZ9bKHp3*FS0Fo@@x0AuTMw^ov32dsb7=^ilDYKK3J<7N<5^Z;+BYd*$)f6T z+aoo-a2;JKU>@2u4Gh4$*qxC&zpV~NBKvWy4aWD2bO)&6u}+_+{YhOJDE&cn(sR?i zZOgGQR)vhbDr!Stv;}jf$g(lYE+tn{RE~b}X$sGltN=&TI~eCLT|%&#SvhFbSuoe> z(w>suur4>$j`qlzlISu|{HkLe2-u9!zS3zF@9k=Wu%NS0%HZQ0E_BS9an6)dL3o39&Mp-c2>Y*+0dD>1EIUz6&%E=3t% zC6c{>`(>e4`j$euzYe+W2srJbR-1ewMQy0Y{FSP%1@5nY=guDg+NMrSTKTt6>ZiMe z9j*OeF;3fmHAl|yp zRror>;+#?CF=el^r(9_j>?R+|AZz6$p~Tw8H>8;*W}D)YXA$gl69;VUwg$w1S?~r| zQOuHiUFKL2^2)-K%2xPIsEX#aG1K&7((dPlDMBT4y}FfLKdb|6Q9@FyH8Ksp{*CM0 zL&~g`Zy)V3bYe)d6UnK2*S-lGU1MaD+KzEHnR-D(iNcb9N)^raT*y2nUv>(NbU=d3 zK6-35Qv1iQXK7o`$&~$kB30WoVzNzap1JvG!)7$1Q)rx{=TnAXk)|j|>(<|VsvSPV zEyyODYA`LPIq-2>nlYJ9lKaasC3Y=)Hi|W2rQS*;Lc9;~(pn;Js~^Bg43p`0W<)g||Vij^*C zh5lG2TPO$B#fF5#sTC}I^6k(AoNvY(d0)cG)!aLGmXKD#nKm07P)67jT#c?7h`YUQ zJC^AT!(5S!k`WMJr_!+(!loHBnf0Oxj|{tWk7sqi>Zms6N&e*8l)Y8j2b_jea7wKt_vR6~zX>K4(%FL89^i_FrWvgu<XJtiWVbBT>M8xjfXhcqf#UxeFU=B%md|&w{F{aBw|TigUn!sPuWLt)|HKclvuuYJ zJA(aXt5j7XG)LFZW;=0&Vy9nwaAoM|4?Am3~-YY^qM-p>zL{1e|h*hx&hJtPDL4m z+$uV2LCR+vw)1#*HFU8j5;21{{H)L3#|rAGRn?H(_?C#J2(5j>z&=r2f}S;=6@Dr@qU0TI907 zFQXRbOWBfxo5T)?J4>1mGW+87)g#sLFOLkL!f1}0><a_t5_Jn@#BS#JCAXN5QK9@}h%Kg0_J7tGk4N;^Sf3}e!%lQ}z8$u1{5Wx-Td zYMxAi`>iubv|?cxZ4LsttXzotb_#k$!=mv}ue{Zu{$SHkgNzDl^k@o`JP&4!oBF}s#If2LH(sbw&*5IHTZuLwP z9LJ0Yd8iCdfw0nNrkbzi#!)3_D@bkt=aQ)&eHC{sGJW`Wpp|!)?WWW2cYMKGltQO? z*K{24doQ){iO*^;{Yy^cG3Ks7B5REm3;6w>@ZjnlHo`PNZ%D)z0eDdBd_nTdk}$K)B{o_(AHcYL;zR|~(s zW|nG@(N2hiH!Q=OJUe>Y@d63#n;N7O&TwyPV)X1PYuMLD51XWeW8TRKb(p%{0p-?O za6!&!uXMGT0(Qz~YqQ9SbCIJ=JQ4R?1u#1ScZ29bu%C*Q*_a!AFK=D~_?;c^ghiV9 z|BLQT=q8j2fH%KBdCa&um3#w-EG=@8w}d^+mq;Sk#nOBRCOC*2L)4bEtr9#;{f#QF z&-pF&rbGi8e4z?Kf~N%r-eMp#HeWJHE}NMFpwj92qN7>!H2*PPi#4(RoWc~i?_kEU zB0jB(%CJI=i|*@iu)yv%fBA&IkO?i$?w1UmKl5W9Q>#e-0TQ2{W}%)rlHkAXO8-{# z+hyettCWxm3j$lCD55ZWZ)bioRc!K%%K{S$3$Y~9R_W8y;s5i#lk~x=jDqBxa4#9T z!2Jv=>fV!CgZuT1ybP5e!ol-bWK12+Z);PI@-PZPjhe&8P%9AQ&c)qO->7iXsnC%_ znejK&=M7IxMnLG8Z&w_ep4qC{{EO3dfyFM!PY(WXds_?+G2!> zQ@bIf#qmEYr!_JzK}4Eq$Wh~|w+oB!lZMv=Nwr>+27X~HAu};pdv1=~vF+G_d!6I7 z<+kC!@nZievP|X3N+EpMMWue2-GdS0kAPj^WKPk(SzYTvl~FTln#6$B51u#@4K&KP zmEt*jEC}DS_hXSeI(M@Ff^D$o!i|ZM?YRzF@QtkRLU!3+#yD7sxXbn|nA+1Ce@5gV ze*$#zHpW{YOpgE)T2QGw@Iz7hpB#$UGzwa zMlOo9f>aYb4NOZoq+0xfYC@vI?VhejcymV~So3BI-q@KmIos zOAqMm3roCw3YOK+xya-gY=-MTBxuw}C78%5)1CX_zMlgElarH)fs75SN+pSjvD{k4 zvsaQ9Vs8{_ZVLFbw>0NukX*xh8X)fIoxYM7H55T4BuQNtAe^G8EIDXCQlB#`AtoYq z#y()G#9F>+27sT3Qp-m+p09^{xvw9O8U=+n=qV%9u2cXdT;LkdC6>O7k8(l8B5c5# zi5TDZ_`$6rYo6&mV3=LSj8w!mrcBz8NxQ8zEW824t`2#S z(#XdK3d%hMcDdnqA7xkTo}+@dO{F98DQZqfq#ll6lzKD%DQ<<6cE4_ghsPNzRPFKG zj+p#sdE5#YKdV%C>+$4m;*rX?;{BF1{k%(eBYuOaVb}MDXZd|f-=ol?EBs90);+`a zdz)lcOMP1*{$dW<&}_SE^1nB+9inGi>+?(hdU##`l;E$iz_t~Fp}?!I&vF*z!UI@j zeM=jrlZ6VgGHUsF?tgk1MlN?L#leLor2X@ysOXt8Rw5~DswzBn7TNxA?lrqLzSIJ@ zRHEuld`M~lWmrng1k6rNi*|C%V_e0>Y)+z($%&KxT;g3tHZmuP+`(z9YOgIA#_GZGq+mhhr)x&$*!3eKR#mm%y5s=B?NjfWL7zkbjMe=RAeoTMYlGlnE&CTaZWu zM+w@x29!d3+S1j|JY?Qy{Y~G+ayrmsS@Sks6uUr?eUH1a^UO z6&%uIDA4c>6fbG;_L7=e06#PWk4TOZ5~FEnG`~q#T;@XN-gC_PcOTK7E5lx6|ID;#`n%!?0Eu>4j<@9}7Q*GelA@3?EJ6EtMU z(0b3_9hez@a&62^oq;dFd2Q(>atOo4RAkhZj= z{>DPKie)NvX6v5LzRc&`a7f&$2jp-j{PHjVJ~P9pS0z$5`AZ7A`*{OiK3HMvpqh|- zv3yX1FW;Cbm{L zt5*U0^i1IYfZG0deof+k@@xNpf11Gm&9C`*=*s{6_%oA~pfXESr63hD3sX13Pzg&) zY9TdZV<$`d-1GpIUe18_y4O8Gs1#B2WP!>{e0J}IbG>5ypyN3ot`GgG8 zYn14^LYM$57h|Sooiqza^9#@ z2ajQ0r1_OvrKACrFd0E-hekGXld?M-8Bp0flaCTsmn1c z&u9NTx~?SDsa>}l#T_eX<3;@%bbbk;J)sfBOPJv=oS9euF44fd!f^_C4NA>Q4XW0` z)F6`#J!pX|%G;FOIohT&Li2?e7zTXB{IoX@@d}i??;1a}U0o_m${XCQ1EJqGA^;$h z1N4gaFqGH3QvF{Kp8yF&@Sj!!SUnthAp*6EF|y2{cd~$$?x-@s-U3zA0BCTQR&m_e ziTpj8(b)DnR_JP-X?YrED$Z^lzC-x%_V1NJ8LKzZ4^k+aHVh@j71lKpZTW$RPx}h8 zWmHV~6?TH^vi?uAj9V*waJwWbv0geCAMW@T zZ)UWzS@a*LOnI@^;UtY+3niwOBg51uT{)Pq*0P}Ml{`}?fG1F-DF>jg z`e}B&OW7_gc4@J`w#!lOnd$Gn7s!XE3`ra^71&P%8CP;3mpZA!V7 z2JHZt3+o|Lbv^e2vyo6?`nauMiY2ASr>3?;D?!}#@+f-vl@tXOq3INbE^oJHsd6&l zLOZ3|cv-lp;H1jaB6>@V8bZK7+wqqHw+Vdy-t`;)h=X$<^COz+gX-%0pg@yp@|gW1 z79C2n5LgHnwWMrMtgfPy8d6~JtD=gwEU(A^O6!dY%iq2u3Rj=MEjqQ`nuKFb=bE(0 zUXvaw;2@c7NDAB5CcA@%wDPo1-m|e19{Mlm*hs?#o1LrJzP?=$G~>F}pk&`Pplstt zhc&xFqq6rcKFo!f{gl6B;r2uGj*X82+g2SA>Iya&e@%KHh9fle_ExyG1%@5A3NQ9K zlmF+Q3=Vp@js{~+kvpB37idF zu3KwB(SR>q+3YC;+_Cp?lXK!`j{(b>WEO?e4oeo`S|Q0DLwcbhIZyB`y}7q( z&5;SOioX3sHm!^Vc*<=IJ)h8PvF0}f&5gOQYF3MlCw`8=Fx}Z|PmXqVtxbzbYL^|u-LI1#U5$K@>wYxk;fDS`(pFnv zY_Kx>yf;8Nd(ArRGfiN@Gmcb1sCF$Pxip-^z(U{#+@p};c_%f|zq~Cd>3{HY@W;dV z&G(6h<&zxezV{&@x#CiH$`vDWYp3-f%0-u%*p>k!!$`Tqwku`d`-dtWGC_C%8x`*-LimNSCYGKXXcNuyw{)EpPyZ;B6hht zvcl*oByaG$t%=19ca_cac+FcUr8As^9>4e1vEGtk@tDd;4^f_u3?!;lfW)z$TQmOw z_xEtw(Ec{`P)Xj|9Pc`c+?TAxwTJuK6q2#7|8tc9w{-Zj>dREs?sjvf<_WSS)RmDmIYFAN8eswDR==BFIn{ zE=onWY&~vjIGlcPXbNm*RK7pHNK{ZhIZ$@HfI176~yNS13;pd4yE}NuoA-U;Ew_I;Y-)$-?h0mc234$R*BVk3u!!DNK zAI!Pk&+EE)I)HsnaChg#;SqPcPUJ1FDIG>T>yA}qRKC=0}BED14LP$6c zXJF<^&0 zx`Nm)%{CV+zK71NvyS39meR#zj~1AeyzIceip+V5_?7`C-^IPJbSS^q^EciS>K&Vn^09{2Zg(CpQv^x@iMnlF=^DPQ!vi!5@n!keB`6 zhQCFX?jh!eZW)c%H6E13rCcjomkF>Qii7b_s;V%oGs~b)8 z!ly;xjZztllgGxDfQth1Y+tulx(hE#a+_XT4Ztjj#ti#$junL=+nu!xcY0V%X15zl zf|+T1pnYk85yklc;ih^kEwcKJ#UT3nUkK7VA9u#9-r>ERwF-IaN%oGruO7L#NEF6v zg{iR9tJ9Rgx@3Xbk9xC7dRXnJt?*H|R%8p14Dxh#Z#Iwdk9CFl^&p!nJ} z)@?ezCt({YXhOJnod5JcLHxS=KzUmTe%@3{soR;q95698FU<9NrCpDUZ?J2=P43q0 z{{#nBt5BY@SPZXJzP@i7VQp)vdTD7hf3sb)Ekuhi7OarmnS0o9wZ@(~( zw(h77yeCHOEiTTSkChGnxDPft1$pSEle~Bzxl*?lhcn=9r9$)5l6X$oPU|!-{3tt~ zDxa^*+$h)cJyod6NkticmgQ%R8x!YJMd(_#)cjaOhuupZqy!yKl%eg|%MWy=;cd{} zQ>6>&gr!SUwI5L>J6n)q{mw)0Z_-8XSXeq|k_`||{LX{0AVxF}M$;g3Txu&`viy0=1#nDh!raz_5t1cu+pkP_L) zjpT0aMvh;sRX!APAc5v_FuZT1NAw`XwUr!`A829yAw+iSC;P6QTNE|5{w}iXO^8TE zNm8K1lNpYr^^IDQ9~L`NB1Rz--uKIE=u{-;<=92VIG63OxKoRz_xckNp8_3&ApI-P zTu-V$wI~z=%?+hqe&T1ys{#xcmWtu>5+G5xSOGe}emDN^wP(9f74sbB0EJ%g&wO6XXdVg~UU z)^B?(7thz6*}wVPcZ^^OeUfz^oZl>-;|C(b2a&4kGD3~*9xFrNoFI-_jQ@lPsqWvp zv>Y)`^)mfbpT;tR0b5o}>=1_hT1bB1n1>q?c57FC$x%j-K9-V^pemUJCb-;$2g&5m z_xBX!=U8|7+Zs{gH!rp4;=>N)f|9zx2fBKRpPN_R2JzxYXg46;p}c?~75M2NCL87d z+JzjnX-i(86!`6#;^=od^&f+RbldA=@BXWHxY_}7b0Mo83KCOv62}uO5zhB_*p#n$HovqvTcVmPD z);RDVLx}=`pYs{rUu}6o0;0;LwQp>T1eYq-bhP4Mj?^Oz?WNlYCp4@d_9<`s6H$LM z+A{oai-+~^q3(y!<@S+kg9#RNWaY}VKL#A{oB5c?{m0oQQ@FYp5&Dj26gOBu=T0P` zmHZ>%?;d-*h7sgUn+e@3p76}AeF)|t=+!>D*Yy*5teU@^3PviRj0R()}Aq2-Q zXt<6T-+QNAqb+`&Srt_XApIS45N+9sh3Nn0pNNR?M>|(+Wcw3>^5;em)afZP?BKLo zaEmI2DBd{#7XgG&u!vSo4>?pY1;TZX5pswO2g#=14dnh*@fS0WNid-RRRMb;t7N_k zm{1dic&V*7qon$SC>f?r;*u$~2PBNAKVvmq6^9ugeAwKZ0&Es>UVYPWr z&*&BWC@+Xxt1Qew8%cCoRvo<1n{W$GSSb-hU(;EDna{=R8)zs%n0bZD4r}>D`2cv7fE&(gk zAYw)B^4pOMrgkd9r>_JV?hlmv+kq_SqKSj-4k1#> z7O8V{QeOzsXR9&s!XA^x?ej3nZhtXoQ_)`U5_hx1N=jT7dK^Vwq|hSBn;W}Z!ut$h zO%@54(wXwc>vjhPba5q%ojj{(OTc)gT~wG|-nm>E%ls`45qPMjF25M_KTBLCUb;k0 z^w_ErY8KPTZtePxh4V!Z;yQT&D{T%E2(d|ZOq=OAp|>VC5B15h{`!Hl>G6Bai06yb zY1P<)ikUI`T52ZE{D(zKeJTiF?><(DRn?C?bi|iP^E`snsL{RipiLN%Z}Fm__9t(npVV{2M>3h(WbF^N|;o>+ihlSKlia0gB^4@=SPd_SaEx5 zDn`-$h26Qd2`!}v{oe1Ii5|-0#L2f-N=r8fLS|i3`_E1dPa+OvikWZb)h_(V{WsVW z*igxC1M>!r1dKqF!AdRm7n1r3!wKX?Gtu0a#M?QtcPE2uU{Es7KI1cco?SB|F7|Zz zjXl+$Azo*#X82%{*~ww|2}V>~!q8L2_8InK@LUA3hh>M$qmz)q2ESTj9tN;$$S?%n zKFpxK4ZSZErg#B#emQe6)DI&|QIDq9Dgr3yCimff z1T8&Kq4h$4#?D+cf$I(i_!-=k9!wz3oPsaXmzEEya|^@HhWGoUuV0uY8WKY33(L~y z4rZ_IF-vj`c=e|GX|RTi!n8*_5EO~H%47B=kjh16C^nel?Zjj^4r|DZRl(%j5utJ;?Z$PvhCw;}-jSt6qgo zQv4|4kZjk#*FIlduWlPQ+Gxd8wBo$WNChs#8HA*i&d@lcoypg7>f}B*nx@dO=k{q+ z&hHbS8DI=!KVMm`I0~`)tR@3J;t(51YaAcXNzz3>S@asuk#Jc{XU{(NU_%8=+IGaa zNuFoz|6rk5#8-XrT3KK&aZhTu@ffjPAGJiVQaDOX+BfE8Bcl18ZULI)9ZhPw^crXX z+;5(3&p8Q4c9!CqbfN5EQ>1pUxDBqbG+y+0|KQCY2gIZB@)Jrp}f=dc2G}n?~mZKb0{zTK~B*Hys#c{A(VaM;kymrO_CaW3_rjm04vA_ zS@Gvk`+H_AG6o_?EGKsRVAbt>m)V7UU@IvvE~fQXMH+0R zJ=}(&IrHoNR5z+_Q!<{1ll(xbLg?w0K*=8W<(?G5qAI5>b^DG%B6J-n&9>_jR4$(Q zcZm>>(}40$va764%B7Y+9p3%Yc+ivG`Kwh@k4=?7L@MjxYd#^!W8{qU^PrcK!!c7WdMADg$L3Eu(B=woZJ@C1YoenlAoA>XV;z{4L8xYN zVnqJxdV!1r^ZGY25{)C*ksX|=;nvRl?#7jTiKb8a293$dr6mKUD>U*lwuovcSavN^ zJtN?4QZz;1LL!zFM#J7tS-UeE9MAWBYIhtYZyRW41kqt{-yX_Pg zIt9#gnpTLooVYhcgi)dyhX#f5?Mxp)-jhNX{m1{EnK>5Zd{=m~M2s%U#@QAVD)HqI znM(2<@U`>FAR43WbD^Xl3Q|nZDL#Bc?^Tx$jm~`cGee9_%lm}9si!Q1^fIrGVkP_FBY;uP1B@ z70ssQ^rQjqK{W}SIKcQEUXPOKXi{>8*H-eI{<*3~z> zK7PUYWUqM!kQk(6^p7$z04Lk1Y;D&9$fn8iVm*pVSUNpzmy(t6>0bLsrHC4h$Hjq3 z3}zV*E^}_u*I%h_T;r(ZG%j44j$}_d8{ArkN!UG4149}^^{yc-A;y7?-*_UE8z87 z(zX*{nHe`>q{P#Qc{(&WLT4Ck!jCP5#luG6z!Runb7KDg#GGg}`({};eFG}cSzx2HeF&&3zh_F#UzhRzwsWLNRD)Ky{zL;=JvyXi;wt{d{tK}Xu<>p!avM)J+B zS$f&Kz&h~F_bHBK9Gfj|Ok&LcNV3-i8T6=BV*8O&y%h%Jnd**b;M?*3$$# zT*!9w)WLjvd?aDke&0K`@8p~Dw=KC~_9fKbO#$m)OL1#Xx;~)p*&O~xJ=tXa{hLk##XHvDI}=X(Jlqwz|QWYXCSod1N%b zpW^RUQjgt_DQKadS`ghQ)#+H|l=|Y~9>&$W;RFTsXviDYAZIP0jiWf(C{PEnq6N8> zNFs!ew8~L)X;s?O0__BMbGW)wFZ8lNy*Ey|^488M_xmMHEna84KHou_ZL6mVZ>6pZ z{piNp5^ux9rNoA9VP)dwtxUtD@04YzGR(R=f-v;mIt1ye(NG`Gdq`MXz@cJ*>U`v;uXWDX!?@*(K~JfUCExNm6jJ5j4hf`)@${J2;sCIMWJlP3!i*j>jJquvuPz z@_-HIwgGYU5fz!2V<}jUWHoF(+>)wOF%cE}>KOm+(4GJ|cOF~_+R5p;B} zl2nb&RM%{_kj)dT*~vov(qKcfQ_XBZcCiXoAm#!kxeTS}-Ps``P4azIcI`fCje2w^ zF8Nv;>7%+4ks4oIe!C%lrqh<<;JE|!pS9pW?UHRU&tFcfFxqp+%eVE?0W6?{z;lea8GBb{6v?!y)(Sb#@$wgZM5{p^9%Uvw*lw{|y_neRv{KgYH|eN;+dC=SAE zD<1Q;bL7?MpJD-78(=|OalEIjL=PJoIDgdS2&;Zi>T?7VCQM(xXXQT(C$^XT0s8~z znmZM|LtM75aB|CNkX_CCkdL#We=D8=S=DPDTXDe~GaL`Di(iX7uP(DYA+i#rlMEt) zUyA)N3m*T}s49K(RayrBKXm+T0q3-KC&T~(}g#kbLZ8$32>(2Ye zeeB+l!JU7ZB{qEFY!hthnCN1D_!ysFq5r`PBo73^bVYIh&au~dRrx`KcZ+cG2nRoV zc={n-k5@DPwk$0iq*0f@KiFJ7p<-Ji_pit8t;$#YB@FSuMF-6{qz3DccZ!2N&$TQ% zb300UzA>p2 z!Kn?aT^xm41(|n5{~Mi9KOD6kvD^B)87>!uO_h)7yRK-ord}+8PjzMT2Q1fS8sC! ztaP&%Zt&Q%{@Ij^$U8r)HCqgU12-E>RN&Zupje<>582jxDK3YQ)2!;W%lb?ur#*&= zksF`D=`I}lvVIe zcpwNn4uX@*^`O=cw7Rbi*NxrguWs$=FP*;Mpwx?4#5Oqfvwc6Sts`(j-gF5X=t+EP zaW8naPI-D1 z;MbkTLqvO{s)o_^b@$-wEq=tQ)|N}O9$A_fy7KkLR?(`URF0wMQNb`EtPmY-44JIz zFAXF*#8irC`DKL{^C%w4A_E@3-uw-341W2-q3?zsjyNnhl5RmsE|ksZgU5ikMZiYOhdR zQG3;_y+;w0KmJO@o~gZBqeYil5-YZ*C>2}m*rOFyyxw!(_rvq?x##@OT_5g;`{kZ{ z&%GBXcWK4r_0G0z(;QV^F}!SzN~~Zq_iFbPe=A?zPNoGbukI@ECy*7-&p8rLJm9U~ zx9Wd7_ADiLH#-ZFr-Q^EKX?&OdLi^1yG@=m(Kplt-eL&%xLiubz%wV98?zw93+X8n6XRaeDKcBz4z$$rDu#w<;) zg?I%s*=7X988Er*10792OkHkaYJ!<0NR)QL3^KfU1)Ea05{AAvKKK5ZnIN+?#6gd~ zFiajK-;ij`Mvtcv1A}~dwN3^BIGvuHUyMRFR3Mx`^0jGnt7t`O3FVg7OoaiJr0U$) z97_}Xb>KPLmBi#HOYdxWQ4b9yYcvN~K)mUdm(5dnkCR9+zEv579*R|BRSacg&Oc^$ zW31tj^Zm_Y5f^RK{G25*OH7VP_lRa*K8IwkBl)&qPcCtTsn)R;@FvtsN`1NWz0vID zQv~+S+sB5Qf)vOU*Lx45nHD-sV;t}yDMHq$ryhpP&GHylYVRxr|fi?re^-E zl%;H{A8(ixq|Av>HB2~*V+jzQVRGEt7E;aA1%6a_`N&XPdW~X0K6F~2>H|~>lfy*>`eI^%FRBOP*uI-b}}Vel447$oqrw)GcAsM)ZU7pmk0 zX5svFK5S`|=EJ{i*P=CGc6#TM%e(}zMt5i~vJF-EijoL$c+hmV^R~k#S}7f95ZCjL z#bCWm?Bcq&y`~7%JL`mWe}yi>vBi+iXvg|bbnGrn)s`h+#<0B|z8%g%T|vi@@eNGA zD=UWZcPTx42qFq|a}j%^eZiJA>na4b>XV}A+Xs zTPm*$?QR2*n$Mg4TISyMN@fqx88o#YkcmCm;;>$nc7a_uAw$*ZAi0*Qz@)?}L&A|q zl!Fi?+-7=4M}t5aUuW zr`Dw$ykzBB??BFFv|z-j1F^eqZQnBh1fGG7x2dvKb5Wakk~Z`K>y+#Y=LmRX4;n4f z+xh05&vD$D47qRPoq~67XF`o3E=&j%Y0LkRi<)0~yD($7zY`~FyUoM_l@yNhY9^${ z(icBTu2+-kw=Sv@7fy_=wY$%e-4pO(MGYDrOiAs+z}6PYeYm6ZSdXT4FG3*&K>9HK z7fk%4<2pWFB?jWY?b397BfuUn)!fU~n|#-q-iC%tET4scRq~!R> zC!Nx!1TlVZh_a=H5FuEtwjgf0ty8-kbGe!DoJqm}85hIRS092A14r^pL|Td%FUC3% zvnySkcPaS7)}|P;ijb56`6{A-7k?Py16gm<+iQB41JxEY9T(pWR6ars-ZZfl)4G&M zPv$PmHf!(iEiV#Ke0}V-A(Bgw+=`U4^(KGvuY^kp#P_EcB!^ch%op&6VjpBB7JBZ^ zo)i}cl4eL*I#TSD{yEa`MaMoacd5@ayUX!i;@yz1&y0P9!{9jLTbIqDp{f|UdsJhO zcdaWI$$pdgkIF^j=2y%p zouG_#Y>)^K48bdy##1U7ghyGb`=u4PNSwjvj}Lw3(mt5 zo-)#6=9YqaB>Q)Gbkak2N^B3BA5j{0{+6qa28S|+1kaUNUQao=g#`D9u_?ct`9h=M z!+!}*skZg_*<%}5K3!j0RU-w}Id}f#oxOy9fvrWEv8P-$IhU;SyWll^QPW*ia_%yB zT6g7Jlj4@=ixsbzC3h%csdX?JV6k<`SML1}qT_z!hcroeUiLsRC-ZB!zzLe?EOO@I zLXZFP-AYU8!1jKQJ5>ey8FLHqE-l{P%kYbMd=+oYHEp0!qA)a$dp63y&w6$`4KZC`yTc$1pv zWFqJ|o{rQ|N*U!KV2i60Bxgbr72=8S>ItQxdV{c8!w8F$nZ?lE!>Y*L35QF2OJJjeLux635a zR|PeyHw4ToM)?7{cH0FAj1b`4?@B)nA;!Y%*1N$&J%md383~dE+y!=EdB@B7oK5d% zsY=(ErP^U8y8ioTsjhb(KVYBb%hKp`~*V%inrbAjH+(OoS_6a{E>AAz7_U4 z-Q1|ZN_5A}I=)_o8tR}HXk96BePT3G(X~235320S497KXRfr=KSK}xD&X(wPS7$Us z!^7E>?r1a`<-2`fWwev?;lJ>(_?(+EGXB6l1bR7RH(L2}H|RHwzgIcdOividaf@V- zEaJMP(^UG=#U-bMC6DU-K=X*_r_1s{({J-{(x17wjd4{Y1HF8TGlMkTdxzec@~nRK z=&!Italq5Mk)sz7R!+jyLw7!!jFXjFLB8j@cyLl0E$L|PEG!;P-qq2UWM;!^7Xbt9 z9S%~MR+X3@>^mdGrJyIY=cbB-y-S5KAusMJO66-1IVuUZ%Itu}!4~mJ`)mN<;#K*j zUsqE3q?4SG?8e<+dg<*w@W#*2Cg1Ql&OOsJYnDM{y!3d2;dLtb5hk)~0Q~d4~=GV)Xjis93pLkj*qu5!LwZ6v7nwPi+I#m9h7QY_@#CRtS;7G=}yuEiV3H01l zoFWA;`q{Z`(!5CDSy{T{gx2cGed=5-bG{xNLF8AH3j0IF505zgmv^u_#3?Vmbc}l# zhlxo)dmbX;u3?Sg<<%V$KqH#oZLxipb$rDYaRGKhVoLkWY>nn2o}@?Y7Qc zxM5Qw-``{-QyU8>pF;V9dXIM7Xq>rUP7Et#hwG))owQ}@ecil;Bw z1$CQd(PCy#k}0@1n|wbL<~(zjSS`}+WE8m~%3Iy(ef=0a%!o+na;7o45f7Bpm%DKPDM z=wii+kswKHF^t+R$FMT#_zG)#CKIe|O!5k5QJv1q#*lE!3_WyHL2KbNP zC4Q|vQ66~mg|CkBzHQq?bhI$UPV>ROD^0}l%^-dQpzpA=J%?pvmFqw6|46nu*@G8k zdQ{r?)6gVIz6ZG@r7sKckNI16G_#S^5ft&X;e8RtgOPm9t|KV0Qg@FJWOU>(STFk9 z@V}>1eX${BuNV2!AO+~}R+p%d_E)s0f{JHG3*zGY4SRCVNl3FJ%ab}J!|8Tg!*h%R z@UD(-7@q!A*nad|F7V`2#{x%i2G!WJkWEq)!uPiF=%?#v-j;qqm^Al?jwT_7^xI z=gNBj3bbeevnzIu@(Q=EAR{R*AuS>+D=r};DRGVZ$^ti2H-c-bUrGNR{crsL0VG$? A$^ZZW diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/FORECAST.index deleted file mode 100644 index e3a507872de7f8fe84670d3cf679788e78f4a54e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmaKsD~uCS6owB55(oki5I}4&%cE^5TL@djKIkhzXHte8fhahFz@acVn?P_Vk`-%q z-6|Xku?Y%?!l7^|9EybhKK^^|?GUD&oOb5B=lt`ZbEkNHT8@ZFZ|CwBf?UIS0%u)s zR^xtAb~`Kb2#5J$?~0hCA{P;#AmS^-qMQXpPFlbtXAv!8Q*D&9{>>IXO!doBc`9GB zoY|5$nD29wb0r~-NKX-#JdR6sjhc!0SBhQ0Ppj-0q7^@8s&!?~SV{cx(n6hu`YmCICN?xLzn8LCR%iaq$E9CO(#e*s2({qq0- diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_3/PARAMETER.data_0 deleted file mode 100644 index b1f41588e5211dcb50ac510a3d1f8aa9564a5c46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4$U|qhFKaw= zc7OZVrt@mmANL(vRu7k|K?WS8M9{} n>>u7f%-Pv<++HhAY>)TOYxakjFZKNtdb%HEF1g@8!+!<+b{Uw?(V_e-Ge(6ZSfR$C{SF2I}|8VG-z>mO-pfWaVN;erMSa1|Lgf? z&il?ev(`Rq&sj6)`&etQ-@cOE_j7BK>+U1Xn>TMBn=#g`PJocnkBi zh$>}$qW(MW{wM06nsm(kw=$MZxR|lx0S7@x-k?aa)p0 zQu>m*18F;wyfZ1gkh-gz@@^jYd5k-Q%6&Yp^Z3=RAJ&m~jp*SKVVTkAWT!d3@|K;aqB8!ebkc<2`Qjc*WySk2wNq zx%wUldR*c$%;PJMDd$o93LZOoobGX#$2%Tl&ZqVTJT~(=RAJ&m~jCuSKVVT zkAWT!d3@|K;X-O(!ebkc<2`Qjc*WySk2!*9x%wUldR*c$%;PJMDHl=u3LZOoobGX# z$2%TlE~fScJT~(=RAJ&m~ja$SKVVTkAWT!d3@|K;ZkZ}!ebkc<2`Qjc*WyS zk2#jna`in9^ti-hn8#NhQ!c0W6+Hf7e^}J;gYlt=;(e&>QOHx_i7N}G#0#p1Z7 zo$Szy@=p6`gK&yHYpOY=_mi4VySGz_G8Y8~bps7>Jh0Rg^IJ%G1^q<}e z@%!R!ojm2&_Hc7gUnk4(tONAx*U4$O$LNCi0*!xaR?Y4%785@7aGI=ZG4AP8ZTh&F zzmDI}DL+1iyzFs57wd&9`#Z&_(F2^aMB9O|KskS>UYdH4(-e6R)%bIRUCc|b8RFD$ zhYxj%@m|B6_I|eEPWJ6RG^fo77pt<dfcn|qM&XoT^KH{3$wR=NZj zr{t~9kheTS`lcM~mS<@~`jE?n{SpQ|>7P`Dbsa0tQ1Cya1ZE`zYRUlj;ZjfO=gf8eaV=+FQB{_ALFmhnGfo9ASo}?$U z7a==Why0p1)N^}4xpxG`O=nX5nB`E&ZP2C)f$T^GH02*cE#E^PD>}x1o;n#cQ?fwq zRS+_ta#TL2CKSIKL%FC8RNcBzxqn~Ct`Da26{E>l6Csb70Zp4gDqpY&$|;)ai>{^e zsT;`|+n~7j{kefqDG&8 z8GoAmv*VAhwQ+TgYj@Vb8b;{=p!kzZP z%F8IveD0c4ycALU-TF1yLmrFyfx`_r|fp@1>$YJ zUm@O-=nZ_Z;w{`980q98Uhm+g81J1T*Jfx_*8hNZk@uiAoj$tQcDw_1#cH3h+@$%? zoVW^gCiWTamZpMYdnU-sW`nv{cF5vVEap+Yh)hB49!7_@=QFI2y*Wm&^Liewf4zie zR~{&ezQy*KV!O%jL&@{yp&a_1_M`hQvUCr~FQ=#diW7$YRd;;J2_JDh?1ABsE&hh% zWb^i;pUME>+Y@fb-iMGFEQS6_H zIU35o?%K+aI3!=r!zDt)Ew& zta2GB(sa0j^8SM_JI(yTmz?VL&+pe8)<)+#;sGkNxak~)YS=DJ*FKX#iSWo{=C(*v*x)V+=CZPWivNq2WBLHli;(a(r96^|gU^ZB6D{CKq=ak9MooP5K+J@DJq-H;F7_mKE$quJY zxp6zn*RS1%@-4BpqCBkTCX^pYupaT2E^C}RZ|4u`B!E;@`iFKehhp{D)oGS=t>h>*u%5DRVE!^}n|DP-y|&}{FF`K?TI6^c$Z@ElJq-9v84gXec<@M0*�kK0*j5E{ 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 W`@9#`lvEX!mi)~Af3N?3{(k|){bwZr diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_4/FORECAST.index deleted file mode 100644 index e7bdf52f5a6665292707dba48f7b8c836ddebb4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmaKsF-Tic6o#*h1xtt4L1{Zk7gJ0^(k9Skki;~34Qk#aea#zMh;B{=2Pc<@AapAT zf`e1HPTe|n2z2V!$<3*olbe&^f9`$fo_q65pInYSzxSVe&VP>K@e?(tl&YN-MhI#R z=K)SHjE3*ZHT40HYSUkoO6QeYM%+QvOb}Wo-PMT403)3^lcCS)p}2%dG7E@F(utd4 zRAuZNK?ZwG^PF)q zirMWn5XN(xw7A5NdB)9Wz5FGdcQ16yyZ_%ATvn&m`;q7L2pP|CE3!DOuz8ChBT}_*KiO0Q{ z-xJt2-ILZQBRr{_p6nxPOHhovhMz^7Epe9LI`@4BhRp7~fBi3J$K^{N(_@;ApXL4t z=Z~rRA7QzRJg1w8jkQgTh4IV{WUChiVRQXHV@{|0JSk-cmQA165l!xn&8_xC*v}pE rV5KENIJfb^x9dB7 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 BRZ{=} diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/FORECAST.index deleted file mode 100644 index 3fb65418a0905bdb4274d1e600a1d5c444da9635..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZ{lAxs=W6owxL5*kFQC@F{r1Ekjr2ONP@(83)T+S?5roIo515)=-F*^o5Bp-7sh zs;;W83PDnZtHLx@xT?CUCj2vR|9Nw_u&|lS^6mTo`QMu(`7kO2BC_ytdKZhl!usGX-Ktee^Q9$j z^q+CufDgmvPiD^;hT&a-Au?qMT{(2SwYs_9O`7kz2)Db|tk=tx|*Cd0wH5FAbq*9ebUdaAyA)$M)m{5u$%#2upcWNIW)mY#2?&2Ph2A zjd4ASiH)FhfGZ9>iXnKvFpP@%XodD>ZDZJ8%|VZKaCK!IUHMv#)M_=1VJ&6wJ;;$e zC^9@2)e?Tl{WXqyPw~j+xs~pgXGwq3xyV3F;-13o1HlZ%EjYzzp%p4*cG~*`%+0;-L-u7wkTC=d(KF0Y(k=%sBh2`zLhY^Uv;{ oxPRTlplTk?5BsGKoBsG5!|E{o<@um*YXA0w%q186XZX(m0A!vyZ~y=R diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_5/PARAMETER.index deleted file mode 100644 index 0018eecf4c9bba8ff114f3f62819df82a3d1cade..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72 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 PQ_)nvM*mOyPyYV_kOlBe diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_6/FORECAST.index deleted file mode 100644 index 2ac26beb0974400ec1e4cbccb9b02a2586903bdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_7/PARAMETER.index deleted file mode 100644 index d2054df4c932fceebcd65429bed3c17d301b8001..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72 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 z 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 I@&Eh(4>y8gsQ>@~ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/FORECAST.index deleted file mode 100644 index 6803d231776b786988afd4b17bae2c869d5eaabb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZ{kA#4;;5QYZ>2?PNM2p|Xs3de<`EorMLZSS}Mw;Ncx35Wv+28Y6INJwxfl8PoI zI1~<5aY+q06t1ccg+meeXWskYyzS+#*}U}n^`Dvlf3wBglX6Hz7Pc;L;*hI&j^U|` z^1+>zqP)>vl1KQ+SN*Flv;J>Ok_-IU{b01_l{A@ng^ysrjp;C}n<8^KzAcJaeXx0(uMIK-SzkTw z1EVpQ9BFwxut}0J+m2C5jk%3_iyiz#x#qWXG{z=Y16gw93?~jI7j2V&I!CQ+$kf^! z$MV+dm|5a}I7hh?_{xnQm7Cq`9OPqgxB+ny&lNmoT~Ss<^mlyp-qAWkU>%WbGZ0(= zy0I{gwDZR`KA3;=H~iDBnEyZIpD$UOdDq1`b6kyd0h<+P7)OlEnZYz;QG`uQ&$nSIPxFoSkBVY7gWBkUuJOny2!cxX)d!cy`(-lMhio**fU2!)d(Lr$aMyhuPB}t1B9aU{I|G65Z0N!?VzVLc+=6$GaW?(tKW_5?KmY&$ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_8/PARAMETER.data_0 deleted file mode 100644 index b2a3976b54c29b275a2c07d8a8babb62c5a915ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 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 YsZ7Uu&S=}}S!o;Sok#zh{a^im14YGa{Qv*} diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/FORECAST.index deleted file mode 100644 index 1f1df9fac4237c7583530b530467aff48005b432..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1702 zcmZ{kEo>A~6ooGa5(oki5I_(Nf6IoYTf$cLht75b>`a!SBM=LYAnH(<2?+@f3<-i% z)K%e7kdUBoC>#oh!XXF==f3yOyKnknn#oP4U+>Sk=e_dTQQ0RV!`J6G5#$oy{dkLU zIqQ$)E}r(X{z0V0_v4875f33Y&04*&R9065CqI<(+-XGR4j>jyHQOL_PYKVQKvYKK zo$1QW^?5nDH7~2#{Kljx`h(Gk4gAr65&3vcUE^~_CF3aQwhK1Trz1K;i+L9 z;RrsNiqmSde}zqM>w=*R-m`cw;&lUSlVl#?Bc3+wL$wRLt0PnAjQ4>bBJSb6aTLYp zf?q;Cd1wp;MoFnBx7UeyBDbCHDb?(qrDD0RrLh0KmRf$~HCY~dOZ{F5wnuW-KWuqv zdu>teOypdSxOE{*+TmlvxGtAzT-6~{d(03PbDEV^)T~`HCe^IKd~E2XAxz_sK-oDd zuMA^D>4}b;{B9hjb&aDdHm<+pQR8$gcF*Q>!&uQ9d#z5D+Rd@_JjKSo8pp;`E5?KJ zDd(K5P@Yz7$Hq|BWQnolmSO*xAYwZ?<~j?mjoe$~I6<{kI9H;er-E(z( I&N=<^7eGz_f&c&j diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_9/PARAMETER.data_0 deleted file mode 100644 index 9c68873c7a10b0ad267022cac6d1da3b4ab143ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4$U|kCTn3;v2?7#c%#P8{+f7sjE#QyLV`?eosF1g@8!+!<0wPR&iqN!8EIPl;De(GPG8a`bf#aShVT%`0JG zf~u6lqB1zdF~rjutc(?^Oa_ZGH~%14XUE_WutGLG3LX6%eIlb=UBC)ifC@p*Tb2RVj#`nf9@Di|=Z1Gzvc1p@^`1_0Ov B2qgdj diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/files/state-map b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/files/state-map deleted file mode 100644 index 847546ba7af7be9a63c27554da04aad841dc1dfa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108 Qcmb1SU|?VbVir1J03Wabe*gdg diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/files/summary-key-set b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/files/summary-key-set deleted file mode 100644 index 374e2509371fbe557a278ab04427c55512dbd6bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 463 zcmY*V%L>9U5Zr@;euskAq4XOf8u0k0}Z9n>F(@2ZX$BRyT{Vxf{&g{ zedXfiIzY@d0R^I74C!LDMFkk?9w+$#`quQGs^BvCL%9}mD_tT-NsdsV91|f!=N#Q4RG3I9kut~7 zofKJEQcCGi6CL}#pY?t6+P+Ud?*@@b^yj~eR#$kY?8(tE#7WQ6DL`g-|S4VF>JYj-0cKCHOs`#RPC`QL&(NXL; zi_!(S;wJjmVdhh8=)|A>IByu&j$0%2#mQmm9PHM{DTcVx3Ikp6tQX!7!jUM{Ova6w zcqkXkOR={a}Mvb=>`U(~Bl^RZ1jLVI2#~RGofc4w(M+nZ1LFZJA zJ%uIt*j0uyHE8?@13K_bA2$EQVF^2-OJgc-P{zcCcw-s9wLm#%G~0?H0eE3QK2Aij zG}O+8m6&|z2yPI&p2bK4tZ7fC} z!Gbf`ei_G? \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil/templates/snake_oil_template.txt b/ThirdParty/Ert/test-data/local/snake_oil/templates/snake_oil_template.txt deleted file mode 100644 index ad2c648a0b..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil/templates/snake_oil_template.txt +++ /dev/null @@ -1,10 +0,0 @@ -OP1_PERSISTENCE: -OP1_OCTAVES: -OP1_DIVERGENCE_SCALE: -OP1_OFFSET: -OP2_PERSISTENCE: -OP2_OCTAVES: -OP2_DIVERGENCE_SCALE: -OP2_OFFSET: -BPR_555_PERSISTENCE: -BPR_138_PERSISTENCE: diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/SEED b/ThirdParty/Ert/test-data/local/snake_oil_field/SEED deleted file mode 100644 index 314cda88f6..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/SEED +++ /dev/null @@ -1 +0,0 @@ -67 -110 42 -42 106 34 96 0 18 42 76 -69 44 -40 -78 -61 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx0.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx0.grdecl deleted file mode 100644 index 481f9d8b83..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx0.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PERMX - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 - 0.92063643E-01 0.92063643E-01 0.92063643E-01 0.92063643E-01 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx1.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx1.grdecl deleted file mode 100644 index 03959ed75a..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx1.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PERMX - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 - 0.53819609E+00 0.53819609E+00 0.53819609E+00 0.53819609E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx2.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx2.grdecl deleted file mode 100644 index 7d8e9bb96a..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx2.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PERMX - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 - 0.84981030E+00 0.84981030E+00 0.84981030E+00 0.84981030E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx3.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx3.grdecl deleted file mode 100644 index 5b733e38b2..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx3.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PERMX - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 - 0.24182262E+00 0.24182262E+00 0.24182262E+00 0.24182262E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx4.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx4.grdecl deleted file mode 100644 index 39a483cea1..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx4.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PERMX - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 - 0.59172921E-01 0.59172921E-01 0.59172921E-01 0.59172921E-01 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx5.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx5.grdecl deleted file mode 100644 index 9286ac8ec9..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx5.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PERMX - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 - 0.76347315E+00 0.76347315E+00 0.76347315E+00 0.76347315E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx6.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx6.grdecl deleted file mode 100644 index 8e33d568fe..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx6.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PERMX - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 - 0.37705892E+00 0.37705892E+00 0.37705892E+00 0.37705892E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx7.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx7.grdecl deleted file mode 100644 index 399a9fc9d0..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx7.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PERMX - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 - 0.84188782E-01 0.84188782E-01 0.84188782E-01 0.84188782E-01 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx8.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx8.grdecl deleted file mode 100644 index ec1f83277b..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx8.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PERMX - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 - 0.52828066E-01 0.52828066E-01 0.52828066E-01 0.52828066E-01 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx9.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx9.grdecl deleted file mode 100644 index 02dd5a1a0e..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/permx9.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PERMX - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 - 0.67972553E+00 0.67972553E+00 0.67972553E+00 0.67972553E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro0.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro0.grdecl deleted file mode 100644 index b6075fa61d..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro0.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PORO - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 - 0.94346166E+00 0.94346166E+00 0.94346166E+00 0.94346166E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro1.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro1.grdecl deleted file mode 100644 index e814818eb8..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro1.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PORO - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 - 0.68036640E+00 0.68036640E+00 0.68036640E+00 0.68036640E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro2.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro2.grdecl deleted file mode 100644 index ba3eb9d6e8..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro2.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PORO - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 - 0.21387884E+00 0.21387884E+00 0.21387884E+00 0.21387884E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro3.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro3.grdecl deleted file mode 100644 index f276fb55a3..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro3.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PORO - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 - 0.72398102E+00 0.72398102E+00 0.72398102E+00 0.72398102E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro4.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro4.grdecl deleted file mode 100644 index 934fecb3ed..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro4.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PORO - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 - 0.68414760E+00 0.68414760E+00 0.68414760E+00 0.68414760E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro5.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro5.grdecl deleted file mode 100644 index b0448eb974..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro5.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PORO - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 - 0.81912923E+00 0.81912923E+00 0.81912923E+00 0.81912923E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro6.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro6.grdecl deleted file mode 100644 index 919c438a61..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro6.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PORO - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 - 0.43541095E+00 0.43541095E+00 0.43541095E+00 0.43541095E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro7.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro7.grdecl deleted file mode 100644 index f8a6beed8d..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro7.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PORO - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 - 0.48421845E+00 0.48421845E+00 0.48421845E+00 0.48421845E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro8.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro8.grdecl deleted file mode 100644 index 285e34c970..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro8.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PORO - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 - 0.98167807E+00 0.98167807E+00 0.98167807E+00 0.98167807E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro9.grdecl b/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro9.grdecl deleted file mode 100644 index 1b0faeefd0..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/fields/poro9.grdecl +++ /dev/null @@ -1,127 +0,0 @@ -PORO - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 - 0.82837886E+00 0.82837886E+00 0.82837886E+00 0.82837886E+00 -/ diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/grid/CASE.EGRID b/ThirdParty/Ert/test-data/local/snake_oil_field/grid/CASE.EGRID deleted file mode 100644 index 33da9f7a70ee0800280622f32e6ac3737cf2615e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22000 zcmeI4QBD+55JevvgV7IW32!I94vazqgBc((e!Gxff=hTy=_UB3zr6?-VBOoddMX4z zFa)EiN_zUd!<%8M`ohd4gi^}p{l(?>d^?<#Qoda5Znt*clydad&M!+j{$c0)b#!0k z`Z*@RYqGf-KHlvvZg1>69-W>Kdpq0pDzC4$xBKl)tzfth`-?MdG=35GZG2x3i^E`YCuZ{T#d)emLlr>5)>^Af~Tw?Y?4ol=tZj59i()zLkS_rniOf z#~i@)c3!=hz6UR+pMn?D&%uk~F$aHqXL{>>^a3|>s%gBR0J!HenV;KlIhz1e|srnlZ3t$8th4PFe7!t?fG4_$L;i{(s= zu^-C!JJZ`@^20xkG5r|4n7#)urk{cr)6c<+;o19GSkCn5-MyH;1}}z3`Pmt3&cV(oXZU7o z-|tLsi`9$i$Kb{EJ$Nzw6ug*z4qgn;-tCNXrbq9cdil99rmw+^eP5f(T3~qgZj5q< zZ?^XR&h)ley_kLsUQFME7t>F{i|Oa!#qjLi_Mx2VF^7qInS(KX4PFe7YBNu~0mHL* zW0W&|v$gMcrnklF#q?wFV)`Dun0^XgOg{%NhG*}#Mmf`C4m0&K2V?pgyciyZ`+M=R z`qI05%)x!LjqaWCIL#KT7t@cyi|KptV)`j~G5s987#`o#zppdB&0+Oo`Wn0#9_8;d zoZ;EK-5=!)-)!yso#}0{dNKVNyqLZRFQ%V@7t_zdi{aV3o~JWCdUr3TufdDqQA5S; zQbS$x!`_Wi&e-21u%s^%!Gmsg0WCoVc>18vV-tO+MYPEkG_Ve(6-j2T& k6M5teG6R``%s^%!Gw`oxfUoJB?d}Z!0<_xoEdF}`3t>$U6951J diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_DIFF b/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_DIFF deleted file mode 100644 index 98a867d959..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_DIFF +++ /dev/null @@ -1,4 +0,0 @@ -STDOUT snake_oil_diff.stdout -STDERR snake_oil_diff.stderr - -EXECUTABLE snake_oil_diff.py \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_NPV b/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_NPV deleted file mode 100644 index 887830c756..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_NPV +++ /dev/null @@ -1,4 +0,0 @@ -STDOUT snake_oil_npv.stdout -STDERR snake_oil_npv.stderr - -EXECUTABLE snake_oil_npv.py \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_SIMULATOR b/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_SIMULATOR deleted file mode 100644 index b4b7f9928f..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/SNAKE_OIL_SIMULATOR +++ /dev/null @@ -1,4 +0,0 @@ -STDOUT snake_oil.stdout -STDERR snake_oil.stderr - -EXECUTABLE snake_oil_simulator.py \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_diff.py b/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_diff.py deleted file mode 100644 index afabb261f9..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_diff.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -from ert.ecl import EclSum - -def writeDiff(filename, vector1, vector2): - with open(filename, "w") as f: - for index in range(len(vector1)): - node1 = vector1[index] - node2 = vector2[index] - - diff = node1.value - node2.value - f.write("%f\n" % diff) - - -if __name__ == '__main__': - ecl_sum = EclSum("SNAKE_OIL_FIELD") - - report_step = 199 - writeDiff("snake_oil_opr_diff_%d.txt" % report_step, ecl_sum["WOPR:OP1"], ecl_sum["WOPR:OP2"]) - writeDiff("snake_oil_wpr_diff_%d.txt" % report_step, ecl_sum["WWPR:OP1"], ecl_sum["WWPR:OP2"]) - writeDiff("snake_oil_gpr_diff_%d.txt" % report_step, ecl_sum["WGPR:OP1"], ecl_sum["WGPR:OP2"]) - - - - diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_npv.py b/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_npv.py deleted file mode 100644 index 4ff61251bc..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_npv.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python -from ert.ecl import EclSum - -OIL_PRICES = {"2010-01-01": 78.33, - "2010-02-01": 76.39, - "2010-03-01": 81.20, - "2010-04-01": 84.29, - "2010-05-01": 73.74, - "2010-06-01": 75.34, - "2010-07-01": 76.32, - "2010-08-01": 76.60, - "2010-09-01": 75.24, - "2010-10-01": 81.89, - "2010-11-01": 84.25, - "2010-12-01": 89.15, - "2011-01-01": 89.17, - "2011-02-01": 88.58, - "2011-03-01": 102.86, - "2011-04-01": 109.53, - "2011-05-01": 100.90, - "2011-06-01": 96.26, - "2011-07-01": 97.30, - "2011-08-01": 86.33, - "2011-09-01": 85.52, - "2011-10-01": 86.32, - "2011-11-01": 97.16, - "2011-12-01": 98.56, - "2012-01-01": 100.27, - "2012-02-01": 102.20, - "2012-03-01": 106.16, - "2012-04-01": 103.32, - "2012-05-01": 94.65, - "2012-06-01": 82.30, - "2012-07-01": 87.90, - "2012-08-01": 94.13, - "2012-09-01": 94.51, - "2012-10-01": 89.49, - "2012-11-01": 86.53, - "2012-12-01": 87.86, - "2013-01-01": 94.76, - "2013-02-01": 95.31, - "2013-03-01": 92.94, - "2013-04-01": 92.02, - "2013-05-01": 94.51, - "2013-06-01": 95.77, - "2013-07-01": 104.67, - "2013-08-01": 106.57, - "2013-09-01": 106.29, - "2013-10-01": 100.54, - "2013-11-01": 93.86, - "2013-12-01": 97.63, - "2014-01-01": 94.62, - "2014-02-01": 100.82, - "2014-03-01": 100.80, - "2014-04-01": 102.07, - "2014-05-01": 102.18, - "2014-06-01": 105.79, - "2014-07-01": 103.59, - "2014-08-01": 96.54, - "2014-09-01": 93.21, - "2014-10-01": 84.40, - "2014-11-01": 75.79, - "2014-12-01": 59.29, - "2015-01-01": 47.22, - "2015-02-01": 50.58, - "2015-03-01": 47.82, - "2015-04-01": 54.45, - "2015-05-01": 59.27, - "2015-06-01": 59.82, - "2015-07-01": 50.90, - "2015-08-01": 42.87, - "2015-09-01": 45.48} - -if __name__ == '__main__': - ecl_sum = EclSum("SNAKE_OIL_FIELD") - start_time = ecl_sum.getStartTime() - date_ranges = ecl_sum.timeRange(start_time, interval="1M") - production_sums = ecl_sum.blockedProduction("FOPT", date_ranges) - - npv = 0.0 - for index in range(0, len(date_ranges) - 1): - date = date_ranges[index + 1] # end of period - production_sum = production_sums[index] - - oil_price = OIL_PRICES[date.date().strftime("%Y-%m-%d")] - - production_value = oil_price * production_sum - npv += production_value - - with open("snake_oil_npv.txt", "w") as output_file: - output_file.write("NPV %s\n" % npv) - - if npv < 80000: - rating = "POOR" - elif 80000 <= npv < 100000: - rating = "AVERAGE" - elif 100000 <= npv < 120000: - rating = "GOOD" - else: - rating = "EXCELLENT" - - output_file.write("RATING %s\n" % rating) - diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_simulator.py b/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_simulator.py deleted file mode 100644 index 1724cea874..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/jobs/snake_oil_simulator.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env python -from datetime import datetime -import os -import sys - -from ert.ecl import EclSum, EclSumTStep -from ert.test import ExtendedTestCase - -try: - from synthesizer import OilSimulator -except ImportError as e: - share_lib_path = os.path.join(ExtendedTestCase.findShareRoot(), "lib") - - sys.path.insert(0, share_lib_path) - synthesizer_module = __import__("synthesizer") - OilSimulator = synthesizer_module.OilSimulator - sys.path.pop(0) - - -def globalIndex(i, j, k, nx=10, ny=10, nz=10): - return i + nx * (j - 1) + nx * ny * (k - 1) - - -def readParameters(filename): - params = {} - with open(filename, "r") as f: - for line in f: - key, value = line.split(":", 1) - params[key] = value.strip() - - return params - - -def runSimulator(simulator, history_simulator, time_step_count): - """ @rtype: EclSum """ - ecl_sum = EclSum.writer("SNAKE_OIL_FIELD", datetime(2010, 1, 1), 10, 10, 10) - - ecl_sum.addVariable("FOPT") - ecl_sum.addVariable("FOPR") - ecl_sum.addVariable("FGPT") - ecl_sum.addVariable("FGPR") - ecl_sum.addVariable("FWPT") - ecl_sum.addVariable("FWPR") - ecl_sum.addVariable("FGOR") - ecl_sum.addVariable("FWCT") - - ecl_sum.addVariable("FOPTH") - ecl_sum.addVariable("FOPRH") - ecl_sum.addVariable("FGPTH") - ecl_sum.addVariable("FGPRH") - ecl_sum.addVariable("FWPTH") - ecl_sum.addVariable("FWPRH") - ecl_sum.addVariable("FGORH") - ecl_sum.addVariable("FWCTH") - - ecl_sum.addVariable("WOPR", wgname="OP1") - ecl_sum.addVariable("WOPR", wgname="OP2") - ecl_sum.addVariable("WWPR", wgname="OP1") - ecl_sum.addVariable("WWPR", wgname="OP2") - ecl_sum.addVariable("WGPR", wgname="OP1") - ecl_sum.addVariable("WGPR", wgname="OP2") - ecl_sum.addVariable("WGOR", wgname="OP1") - ecl_sum.addVariable("WGOR", wgname="OP2") - ecl_sum.addVariable("WWCT", wgname="OP1") - ecl_sum.addVariable("WWCT", wgname="OP2") - - ecl_sum.addVariable("WOPRH", wgname="OP1") - ecl_sum.addVariable("WOPRH", wgname="OP2") - ecl_sum.addVariable("WWPRH", wgname="OP1") - ecl_sum.addVariable("WWPRH", wgname="OP2") - ecl_sum.addVariable("WGPRH", wgname="OP1") - ecl_sum.addVariable("WGPRH", wgname="OP2") - ecl_sum.addVariable("WGORH", wgname="OP1") - ecl_sum.addVariable("WGORH", wgname="OP2") - ecl_sum.addVariable("WWCTH", wgname="OP1") - ecl_sum.addVariable("WWCTH", wgname="OP2") - - ecl_sum.addVariable("BPR", num=globalIndex(5, 5, 5)) - ecl_sum.addVariable("BPR", num=globalIndex(1, 3, 8)) - - time_map = [] - mini_step_count = 10 - total_step_count = time_step_count * mini_step_count - - for report_step in range(time_step_count): - for mini_step in range(mini_step_count): - t_step = ecl_sum.addTStep(report_step + 1, sim_days=report_step * mini_step_count + mini_step) - - time_map.append(t_step.getSimTime().datetime().strftime("%d/%m/%Y")) - - simulator.step(scale=1.0 / total_step_count) - history_simulator.step(scale=1.0 / total_step_count) - - t_step["FOPR"] = simulator.fopr() - t_step["FOPT"] = simulator.fopt() - t_step["FGPR"] = simulator.fgpr() - t_step["FGPT"] = simulator.fgpt() - t_step["FWPR"] = simulator.fwpr() - t_step["FWPT"] = simulator.fwpt() - t_step["FGOR"] = simulator.fgor() - t_step["FWCT"] = simulator.fwct() - - t_step["WOPR:OP1"] = simulator.opr("OP1") - t_step["WOPR:OP2"] = simulator.opr("OP2") - - t_step["WGPR:OP1"] = simulator.gpr("OP1") - t_step["WGPR:OP2"] = simulator.gpr("OP2") - - t_step["WWPR:OP1"] = simulator.wpr("OP1") - t_step["WWPR:OP2"] = simulator.wpr("OP2") - - t_step["WGOR:OP1"] = simulator.gor("OP1") - t_step["WGOR:OP2"] = simulator.gor("OP2") - - t_step["WWCT:OP1"] = simulator.wct("OP1") - t_step["WWCT:OP2"] = simulator.wct("OP2") - - t_step["BPR:5,5,5"] = simulator.bpr("5,5,5") - t_step["BPR:1,3,8"] = simulator.bpr("1,3,8") - - t_step["FOPRH"] = history_simulator.fopr() - t_step["FOPTH"] = history_simulator.fopt() - t_step["FGPRH"] = history_simulator.fgpr() - t_step["FGPTH"] = history_simulator.fgpt() - t_step["FWPRH"] = history_simulator.fwpr() - t_step["FWPTH"] = history_simulator.fwpt() - t_step["FGORH"] = history_simulator.fgor() - t_step["FWCTH"] = history_simulator.fwct() - - t_step["WOPRH:OP1"] = history_simulator.opr("OP1") - t_step["WOPRH:OP2"] = history_simulator.opr("OP2") - - t_step["WGPRH:OP1"] = history_simulator.gpr("OP1") - t_step["WGPRH:OP2"] = history_simulator.gpr("OP2") - - t_step["WWPRH:OP1"] = history_simulator.wpr("OP1") - t_step["WWPRH:OP2"] = history_simulator.wpr("OP2") - - t_step["WGORH:OP1"] = history_simulator.gor("OP1") - t_step["WGORH:OP2"] = history_simulator.gor("OP2") - - t_step["WWCTH:OP1"] = history_simulator.wct("OP1") - t_step["WWCTH:OP2"] = history_simulator.wct("OP2") - - return ecl_sum, time_map - - -def roundedInt(value): - return int(round(float(value))) - - -if __name__ == '__main__': - seed = int(readParameters("seed.txt")["SEED"]) - parameters = readParameters("snake_oil_params.txt") - - op1_divergence_scale = float(parameters["OP1_DIVERGENCE_SCALE"]) - op2_divergence_scale = float(parameters["OP2_DIVERGENCE_SCALE"]) - op1_persistence = float(parameters["OP1_PERSISTENCE"]) - op2_persistence = float(parameters["OP2_PERSISTENCE"]) - op1_offset = float(parameters["OP1_OFFSET"]) - op2_offset = float(parameters["OP2_OFFSET"]) - bpr_138_persistence = float(parameters["BPR_138_PERSISTENCE"]) - bpr_555_persistence = float(parameters["BPR_555_PERSISTENCE"]) - - op1_octaves = roundedInt(parameters["OP1_OCTAVES"]) - op2_octaves = roundedInt(parameters["OP2_OCTAVES"]) - - simulator = OilSimulator() - simulator.addWell("OP1", seed * 997, persistence=op1_persistence, octaves=op1_octaves, divergence_scale=op1_divergence_scale, offset=op1_offset) - simulator.addWell("OP2", seed * 13, persistence=op2_persistence, octaves=op2_octaves, divergence_scale=op2_divergence_scale, offset=op2_offset) - simulator.addBlock("5,5,5", seed * 37, persistence=bpr_555_persistence) - simulator.addBlock("1,3,8", seed * 31, persistence=bpr_138_persistence) - - history_simulator = OilSimulator() - history_simulator.addWell("OP1", 222118781) - history_simulator.addWell("OP2", 118116362) - - report_step_count = 200 - ecl_sum, time_map = runSimulator(simulator, history_simulator, report_step_count) - - ecl_sum.fwrite() - - with open("time_map.txt", "w") as f: - for t in time_map: - f.write("%s\n" % t) diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/make_data.py b/ThirdParty/Ert/test-data/local/snake_oil_field/make_data.py deleted file mode 100644 index 069716e345..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/make_data.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -import os -import os.path - -from ert.ecl import EclGrid, EclKW, EclTypeEnum -from ert.util import RandomNumberGenerator - -# This little script is used as a one-shot operation to generate the -# grid and the corresponding PERMX and PORO fields used for this test -# case. The script itself is not used bye the test. - -nx = 10 -ny = 10 -nz = 5 -ens_size = 10 - - -def make_grid( ): - grid = EclGrid.createRectangular( (nx,ny,nz) , (1,1,1) ) - if not os.path.isdir("grid"): - os.makedirs("grid") - grid.save_EGRID("grid/CASE.EGRID") - - return grid - - - -def make_field(rng , grid , iens): - permx = EclKW.create( "PERMX" , grid.getGlobalSize( ) , EclTypeEnum.ECL_FLOAT_TYPE) - permx.assign( rng.getDouble( ) ) - - poro = EclKW.create( "PORO" , grid.getGlobalSize( ) , EclTypeEnum.ECL_FLOAT_TYPE) - poro.assign( rng.getDouble( ) ) - - if not os.path.isdir("fields"): - os.makedirs("fields") - - with open("fields/permx%d.grdecl" % iens,"w") as f: - permx.write_grdecl( f ) - - with open("fields/poro%d.grdecl" % iens ,"w") as f: - poro.write_grdecl( f ) - - -rng = RandomNumberGenerator( ) -rng.setState("ABCD6375ejascEFGHIJ") - - -grid = make_grid( ) -for iens in range(ens_size): - make_field(rng , grid , iens) diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/observations/observations.txt b/ThirdParty/Ert/test-data/local/snake_oil_field/observations/observations.txt deleted file mode 100644 index de28837efb..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/observations/observations.txt +++ /dev/null @@ -1,56 +0,0 @@ -HISTORY_OBSERVATION FOPR; - -SUMMARY_OBSERVATION WOPR_OP1_9 -{ - VALUE = 0.1; - ERROR = 0.05; - RESTART = 9; - KEY = WOPR:OP1; -}; - -SUMMARY_OBSERVATION WOPR_OP1_36 -{ - VALUE = 0.7; - ERROR = 0.07; - RESTART = 36; - KEY = WOPR:OP1; -}; - -SUMMARY_OBSERVATION WOPR_OP1_72 -{ - VALUE = 0.5; - ERROR = 0.05; - RESTART = 72; - KEY = WOPR:OP1; -}; - -SUMMARY_OBSERVATION WOPR_OP1_108 -{ - VALUE = 0.3; - ERROR = 0.075; - RESTART = 108; - KEY = WOPR:OP1; -}; - -SUMMARY_OBSERVATION WOPR_OP1_144 -{ - VALUE = 0.2; - ERROR = 0.035; - RESTART = 144; - KEY = WOPR:OP1; -}; - -SUMMARY_OBSERVATION WOPR_OP1_190 -{ - VALUE = 0.015; - ERROR = 0.01; - RESTART = 190; - KEY = WOPR:OP1; -}; - -GENERAL_OBSERVATION WPR_DIFF_1 { - DATA = SNAKE_OIL_WPR_DIFF; - INDEX_LIST = 400,800,1200,1800; - RESTART = 199; - OBS_FILE = observations/wpr_diff_obs.txt; -}; \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/observations/wpr_diff_obs.txt b/ThirdParty/Ert/test-data/local/snake_oil_field/observations/wpr_diff_obs.txt deleted file mode 100644 index 4aee6d7ef7..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/observations/wpr_diff_obs.txt +++ /dev/null @@ -1,4 +0,0 @@ -0.0 0.1 -0.1 0.2 -0.2 0.15 -0.0 0.05 diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/parameters/snake_oil_parameters.txt b/ThirdParty/Ert/test-data/local/snake_oil_field/parameters/snake_oil_parameters.txt deleted file mode 100644 index 64573d0058..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/parameters/snake_oil_parameters.txt +++ /dev/null @@ -1,11 +0,0 @@ -OP1_PERSISTENCE UNIFORM 0.01 0.4 -OP1_OCTAVES UNIFORM 3 5 -OP1_DIVERGENCE_SCALE UNIFORM 0.25 1.25 -OP1_OFFSET UNIFORM -0.1 0.1 -OP2_PERSISTENCE UNIFORM 0.1 0.6 -OP2_OCTAVES UNIFORM 5 12 -OP2_DIVERGENCE_SCALE UNIFORM 0.5 1.5 -OP2_OFFSET UNIFORM -0.2 0.2 -BPR_555_PERSISTENCE UNIFORM 0.1 0.5 -BPR_138_PERSISTENCE UNIFORM 0.2 0.7 - diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/SNAKE_OIL_FIELD.SMSPEC b/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/SNAKE_OIL_FIELD.SMSPEC deleted file mode 100644 index 5a29e043b2d3740b3774a9deda10d6ead8937467..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1416 zcmeHHF;2uV5ZrJQAaq4aN>g1y1=WcPlbBqDVn>co);-`__|ScYN6=F71b%SrdN(1Y zLZV55qt#?K-tlC!3IOEZbV2)|0N}jXXpfj<+^at>(jcv}Zj9}e!u!+O217ZFONSK7U=mE z;N%Tw;6O96wRIr#)0rssF1?d|dEV2z{p0WY(9cBrvz9twUl*g9SR&6j&fXE1Uwh7I Ao&W#< diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/SNAKE_OIL_FIELD.UNSMRY b/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/SNAKE_OIL_FIELD.UNSMRY deleted file mode 100644 index dfa04f80027b57788211c785cd6a5203769ee63b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 455200 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¨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 z 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 WJ%7nEk$S+7J3C!R$^J5S{Cbw? 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

IDEVE%a% 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/refcase_readme.txt b/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/refcase_readme.txt deleted file mode 100644 index a3d0fe6058..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/refcase_readme.txt +++ /dev/null @@ -1 +0,0 @@ -To create a refcase run the snake_oil_simulator.py job with the this as working directory. \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/seed.txt b/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/seed.txt deleted file mode 100644 index 0009f6e89a..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/seed.txt +++ /dev/null @@ -1 +0,0 @@ -SEED:268776 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/snake_oil_params.txt b/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/snake_oil_params.txt deleted file mode 100644 index 3868522924..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/snake_oil_params.txt +++ /dev/null @@ -1,10 +0,0 @@ -OP1_PERSISTENCE:0.15 -OP1_OCTAVES:4 -OP1_DIVERGENCE_SCALE:0.5 -OP1_OFFSET:0.0 -OP2_PERSISTENCE:0.25 -OP2_OCTAVES:7.0 -OP2_DIVERGENCE_SCALE:1.0 -OP2_OFFSET:0.0 -BPR_555_PERSISTENCE:0.25 -BPR_138_PERSISTENCE:0.35 diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/time_map.txt b/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/time_map.txt deleted file mode 100644 index d54b4293ae..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/refcase/time_map.txt +++ /dev/null @@ -1,2000 +0,0 @@ -01/01/2010 -02/01/2010 -03/01/2010 -04/01/2010 -05/01/2010 -06/01/2010 -07/01/2010 -08/01/2010 -09/01/2010 -10/01/2010 -11/01/2010 -12/01/2010 -13/01/2010 -14/01/2010 -15/01/2010 -16/01/2010 -17/01/2010 -18/01/2010 -19/01/2010 -20/01/2010 -21/01/2010 -22/01/2010 -23/01/2010 -24/01/2010 -25/01/2010 -26/01/2010 -27/01/2010 -28/01/2010 -29/01/2010 -30/01/2010 -31/01/2010 -01/02/2010 -02/02/2010 -03/02/2010 -04/02/2010 -05/02/2010 -06/02/2010 -07/02/2010 -08/02/2010 -09/02/2010 -10/02/2010 -11/02/2010 -12/02/2010 -13/02/2010 -14/02/2010 -15/02/2010 -16/02/2010 -17/02/2010 -18/02/2010 -19/02/2010 -20/02/2010 -21/02/2010 -22/02/2010 -23/02/2010 -24/02/2010 -25/02/2010 -26/02/2010 -27/02/2010 -28/02/2010 -01/03/2010 -02/03/2010 -03/03/2010 -04/03/2010 -05/03/2010 -06/03/2010 -07/03/2010 -08/03/2010 -09/03/2010 -10/03/2010 -11/03/2010 -12/03/2010 -13/03/2010 -14/03/2010 -15/03/2010 -16/03/2010 -17/03/2010 -18/03/2010 -19/03/2010 -20/03/2010 -21/03/2010 -22/03/2010 -23/03/2010 -24/03/2010 -25/03/2010 -26/03/2010 -27/03/2010 -28/03/2010 -29/03/2010 -30/03/2010 -31/03/2010 -01/04/2010 -02/04/2010 -03/04/2010 -04/04/2010 -05/04/2010 -06/04/2010 -07/04/2010 -08/04/2010 -09/04/2010 -10/04/2010 -11/04/2010 -12/04/2010 -13/04/2010 -14/04/2010 -15/04/2010 -16/04/2010 -17/04/2010 -18/04/2010 -19/04/2010 -20/04/2010 -21/04/2010 -22/04/2010 -23/04/2010 -24/04/2010 -25/04/2010 -26/04/2010 -27/04/2010 -28/04/2010 -29/04/2010 -30/04/2010 -01/05/2010 -02/05/2010 -03/05/2010 -04/05/2010 -05/05/2010 -06/05/2010 -07/05/2010 -08/05/2010 -09/05/2010 -10/05/2010 -11/05/2010 -12/05/2010 -13/05/2010 -14/05/2010 -15/05/2010 -16/05/2010 -17/05/2010 -18/05/2010 -19/05/2010 -20/05/2010 -21/05/2010 -22/05/2010 -23/05/2010 -24/05/2010 -25/05/2010 -26/05/2010 -27/05/2010 -28/05/2010 -29/05/2010 -30/05/2010 -31/05/2010 -01/06/2010 -02/06/2010 -03/06/2010 -04/06/2010 -05/06/2010 -06/06/2010 -07/06/2010 -08/06/2010 -09/06/2010 -10/06/2010 -11/06/2010 -12/06/2010 -13/06/2010 -14/06/2010 -15/06/2010 -16/06/2010 -17/06/2010 -18/06/2010 -19/06/2010 -20/06/2010 -21/06/2010 -22/06/2010 -23/06/2010 -24/06/2010 -25/06/2010 -26/06/2010 -27/06/2010 -28/06/2010 -29/06/2010 -30/06/2010 -01/07/2010 -02/07/2010 -03/07/2010 -04/07/2010 -05/07/2010 -06/07/2010 -07/07/2010 -08/07/2010 -09/07/2010 -10/07/2010 -11/07/2010 -12/07/2010 -13/07/2010 -14/07/2010 -15/07/2010 -16/07/2010 -17/07/2010 -18/07/2010 -19/07/2010 -20/07/2010 -21/07/2010 -22/07/2010 -23/07/2010 -24/07/2010 -25/07/2010 -26/07/2010 -27/07/2010 -28/07/2010 -29/07/2010 -30/07/2010 -31/07/2010 -01/08/2010 -02/08/2010 -03/08/2010 -04/08/2010 -05/08/2010 -06/08/2010 -07/08/2010 -08/08/2010 -09/08/2010 -10/08/2010 -11/08/2010 -12/08/2010 -13/08/2010 -14/08/2010 -15/08/2010 -16/08/2010 -17/08/2010 -18/08/2010 -19/08/2010 -20/08/2010 -21/08/2010 -22/08/2010 -23/08/2010 -24/08/2010 -25/08/2010 -26/08/2010 -27/08/2010 -28/08/2010 -29/08/2010 -30/08/2010 -31/08/2010 -01/09/2010 -02/09/2010 -03/09/2010 -04/09/2010 -05/09/2010 -06/09/2010 -07/09/2010 -08/09/2010 -09/09/2010 -10/09/2010 -11/09/2010 -12/09/2010 -13/09/2010 -14/09/2010 -15/09/2010 -16/09/2010 -17/09/2010 -18/09/2010 -19/09/2010 -20/09/2010 -21/09/2010 -22/09/2010 -23/09/2010 -24/09/2010 -25/09/2010 -26/09/2010 -27/09/2010 -28/09/2010 -29/09/2010 -30/09/2010 -01/10/2010 -02/10/2010 -03/10/2010 -04/10/2010 -05/10/2010 -06/10/2010 -07/10/2010 -08/10/2010 -09/10/2010 -10/10/2010 -11/10/2010 -12/10/2010 -13/10/2010 -14/10/2010 -15/10/2010 -16/10/2010 -17/10/2010 -18/10/2010 -19/10/2010 -20/10/2010 -21/10/2010 -22/10/2010 -23/10/2010 -24/10/2010 -25/10/2010 -26/10/2010 -27/10/2010 -28/10/2010 -29/10/2010 -30/10/2010 -31/10/2010 -01/11/2010 -02/11/2010 -03/11/2010 -04/11/2010 -05/11/2010 -06/11/2010 -07/11/2010 -08/11/2010 -09/11/2010 -10/11/2010 -11/11/2010 -12/11/2010 -13/11/2010 -14/11/2010 -15/11/2010 -16/11/2010 -17/11/2010 -18/11/2010 -19/11/2010 -20/11/2010 -21/11/2010 -22/11/2010 -23/11/2010 -24/11/2010 -25/11/2010 -26/11/2010 -27/11/2010 -28/11/2010 -29/11/2010 -30/11/2010 -01/12/2010 -02/12/2010 -03/12/2010 -04/12/2010 -05/12/2010 -06/12/2010 -07/12/2010 -08/12/2010 -09/12/2010 -10/12/2010 -11/12/2010 -12/12/2010 -13/12/2010 -14/12/2010 -15/12/2010 -16/12/2010 -17/12/2010 -18/12/2010 -19/12/2010 -20/12/2010 -21/12/2010 -22/12/2010 -23/12/2010 -24/12/2010 -25/12/2010 -26/12/2010 -27/12/2010 -28/12/2010 -29/12/2010 -30/12/2010 -31/12/2010 -01/01/2011 -02/01/2011 -03/01/2011 -04/01/2011 -05/01/2011 -06/01/2011 -07/01/2011 -08/01/2011 -09/01/2011 -10/01/2011 -11/01/2011 -12/01/2011 -13/01/2011 -14/01/2011 -15/01/2011 -16/01/2011 -17/01/2011 -18/01/2011 -19/01/2011 -20/01/2011 -21/01/2011 -22/01/2011 -23/01/2011 -24/01/2011 -25/01/2011 -26/01/2011 -27/01/2011 -28/01/2011 -29/01/2011 -30/01/2011 -31/01/2011 -01/02/2011 -02/02/2011 -03/02/2011 -04/02/2011 -05/02/2011 -06/02/2011 -07/02/2011 -08/02/2011 -09/02/2011 -10/02/2011 -11/02/2011 -12/02/2011 -13/02/2011 -14/02/2011 -15/02/2011 -16/02/2011 -17/02/2011 -18/02/2011 -19/02/2011 -20/02/2011 -21/02/2011 -22/02/2011 -23/02/2011 -24/02/2011 -25/02/2011 -26/02/2011 -27/02/2011 -28/02/2011 -01/03/2011 -02/03/2011 -03/03/2011 -04/03/2011 -05/03/2011 -06/03/2011 -07/03/2011 -08/03/2011 -09/03/2011 -10/03/2011 -11/03/2011 -12/03/2011 -13/03/2011 -14/03/2011 -15/03/2011 -16/03/2011 -17/03/2011 -18/03/2011 -19/03/2011 -20/03/2011 -21/03/2011 -22/03/2011 -23/03/2011 -24/03/2011 -25/03/2011 -26/03/2011 -27/03/2011 -28/03/2011 -29/03/2011 -30/03/2011 -31/03/2011 -01/04/2011 -02/04/2011 -03/04/2011 -04/04/2011 -05/04/2011 -06/04/2011 -07/04/2011 -08/04/2011 -09/04/2011 -10/04/2011 -11/04/2011 -12/04/2011 -13/04/2011 -14/04/2011 -15/04/2011 -16/04/2011 -17/04/2011 -18/04/2011 -19/04/2011 -20/04/2011 -21/04/2011 -22/04/2011 -23/04/2011 -24/04/2011 -25/04/2011 -26/04/2011 -27/04/2011 -28/04/2011 -29/04/2011 -30/04/2011 -01/05/2011 -02/05/2011 -03/05/2011 -04/05/2011 -05/05/2011 -06/05/2011 -07/05/2011 -08/05/2011 -09/05/2011 -10/05/2011 -11/05/2011 -12/05/2011 -13/05/2011 -14/05/2011 -15/05/2011 -16/05/2011 -17/05/2011 -18/05/2011 -19/05/2011 -20/05/2011 -21/05/2011 -22/05/2011 -23/05/2011 -24/05/2011 -25/05/2011 -26/05/2011 -27/05/2011 -28/05/2011 -29/05/2011 -30/05/2011 -31/05/2011 -01/06/2011 -02/06/2011 -03/06/2011 -04/06/2011 -05/06/2011 -06/06/2011 -07/06/2011 -08/06/2011 -09/06/2011 -10/06/2011 -11/06/2011 -12/06/2011 -13/06/2011 -14/06/2011 -15/06/2011 -16/06/2011 -17/06/2011 -18/06/2011 -19/06/2011 -20/06/2011 -21/06/2011 -22/06/2011 -23/06/2011 -24/06/2011 -25/06/2011 -26/06/2011 -27/06/2011 -28/06/2011 -29/06/2011 -30/06/2011 -01/07/2011 -02/07/2011 -03/07/2011 -04/07/2011 -05/07/2011 -06/07/2011 -07/07/2011 -08/07/2011 -09/07/2011 -10/07/2011 -11/07/2011 -12/07/2011 -13/07/2011 -14/07/2011 -15/07/2011 -16/07/2011 -17/07/2011 -18/07/2011 -19/07/2011 -20/07/2011 -21/07/2011 -22/07/2011 -23/07/2011 -24/07/2011 -25/07/2011 -26/07/2011 -27/07/2011 -28/07/2011 -29/07/2011 -30/07/2011 -31/07/2011 -01/08/2011 -02/08/2011 -03/08/2011 -04/08/2011 -05/08/2011 -06/08/2011 -07/08/2011 -08/08/2011 -09/08/2011 -10/08/2011 -11/08/2011 -12/08/2011 -13/08/2011 -14/08/2011 -15/08/2011 -16/08/2011 -17/08/2011 -18/08/2011 -19/08/2011 -20/08/2011 -21/08/2011 -22/08/2011 -23/08/2011 -24/08/2011 -25/08/2011 -26/08/2011 -27/08/2011 -28/08/2011 -29/08/2011 -30/08/2011 -31/08/2011 -01/09/2011 -02/09/2011 -03/09/2011 -04/09/2011 -05/09/2011 -06/09/2011 -07/09/2011 -08/09/2011 -09/09/2011 -10/09/2011 -11/09/2011 -12/09/2011 -13/09/2011 -14/09/2011 -15/09/2011 -16/09/2011 -17/09/2011 -18/09/2011 -19/09/2011 -20/09/2011 -21/09/2011 -22/09/2011 -23/09/2011 -24/09/2011 -25/09/2011 -26/09/2011 -27/09/2011 -28/09/2011 -29/09/2011 -30/09/2011 -01/10/2011 -02/10/2011 -03/10/2011 -04/10/2011 -05/10/2011 -06/10/2011 -07/10/2011 -08/10/2011 -09/10/2011 -10/10/2011 -11/10/2011 -12/10/2011 -13/10/2011 -14/10/2011 -15/10/2011 -16/10/2011 -17/10/2011 -18/10/2011 -19/10/2011 -20/10/2011 -21/10/2011 -22/10/2011 -23/10/2011 -24/10/2011 -25/10/2011 -26/10/2011 -27/10/2011 -28/10/2011 -29/10/2011 -30/10/2011 -31/10/2011 -01/11/2011 -02/11/2011 -03/11/2011 -04/11/2011 -05/11/2011 -06/11/2011 -07/11/2011 -08/11/2011 -09/11/2011 -10/11/2011 -11/11/2011 -12/11/2011 -13/11/2011 -14/11/2011 -15/11/2011 -16/11/2011 -17/11/2011 -18/11/2011 -19/11/2011 -20/11/2011 -21/11/2011 -22/11/2011 -23/11/2011 -24/11/2011 -25/11/2011 -26/11/2011 -27/11/2011 -28/11/2011 -29/11/2011 -30/11/2011 -01/12/2011 -02/12/2011 -03/12/2011 -04/12/2011 -05/12/2011 -06/12/2011 -07/12/2011 -08/12/2011 -09/12/2011 -10/12/2011 -11/12/2011 -12/12/2011 -13/12/2011 -14/12/2011 -15/12/2011 -16/12/2011 -17/12/2011 -18/12/2011 -19/12/2011 -20/12/2011 -21/12/2011 -22/12/2011 -23/12/2011 -24/12/2011 -25/12/2011 -26/12/2011 -27/12/2011 -28/12/2011 -29/12/2011 -30/12/2011 -31/12/2011 -01/01/2012 -02/01/2012 -03/01/2012 -04/01/2012 -05/01/2012 -06/01/2012 -07/01/2012 -08/01/2012 -09/01/2012 -10/01/2012 -11/01/2012 -12/01/2012 -13/01/2012 -14/01/2012 -15/01/2012 -16/01/2012 -17/01/2012 -18/01/2012 -19/01/2012 -20/01/2012 -21/01/2012 -22/01/2012 -23/01/2012 -24/01/2012 -25/01/2012 -26/01/2012 -27/01/2012 -28/01/2012 -29/01/2012 -30/01/2012 -31/01/2012 -01/02/2012 -02/02/2012 -03/02/2012 -04/02/2012 -05/02/2012 -06/02/2012 -07/02/2012 -08/02/2012 -09/02/2012 -10/02/2012 -11/02/2012 -12/02/2012 -13/02/2012 -14/02/2012 -15/02/2012 -16/02/2012 -17/02/2012 -18/02/2012 -19/02/2012 -20/02/2012 -21/02/2012 -22/02/2012 -23/02/2012 -24/02/2012 -25/02/2012 -26/02/2012 -27/02/2012 -28/02/2012 -29/02/2012 -01/03/2012 -02/03/2012 -03/03/2012 -04/03/2012 -05/03/2012 -06/03/2012 -07/03/2012 -08/03/2012 -09/03/2012 -10/03/2012 -11/03/2012 -12/03/2012 -13/03/2012 -14/03/2012 -15/03/2012 -16/03/2012 -17/03/2012 -18/03/2012 -19/03/2012 -20/03/2012 -21/03/2012 -22/03/2012 -23/03/2012 -24/03/2012 -25/03/2012 -26/03/2012 -27/03/2012 -28/03/2012 -29/03/2012 -30/03/2012 -31/03/2012 -01/04/2012 -02/04/2012 -03/04/2012 -04/04/2012 -05/04/2012 -06/04/2012 -07/04/2012 -08/04/2012 -09/04/2012 -10/04/2012 -11/04/2012 -12/04/2012 -13/04/2012 -14/04/2012 -15/04/2012 -16/04/2012 -17/04/2012 -18/04/2012 -19/04/2012 -20/04/2012 -21/04/2012 -22/04/2012 -23/04/2012 -24/04/2012 -25/04/2012 -26/04/2012 -27/04/2012 -28/04/2012 -29/04/2012 -30/04/2012 -01/05/2012 -02/05/2012 -03/05/2012 -04/05/2012 -05/05/2012 -06/05/2012 -07/05/2012 -08/05/2012 -09/05/2012 -10/05/2012 -11/05/2012 -12/05/2012 -13/05/2012 -14/05/2012 -15/05/2012 -16/05/2012 -17/05/2012 -18/05/2012 -19/05/2012 -20/05/2012 -21/05/2012 -22/05/2012 -23/05/2012 -24/05/2012 -25/05/2012 -26/05/2012 -27/05/2012 -28/05/2012 -29/05/2012 -30/05/2012 -31/05/2012 -01/06/2012 -02/06/2012 -03/06/2012 -04/06/2012 -05/06/2012 -06/06/2012 -07/06/2012 -08/06/2012 -09/06/2012 -10/06/2012 -11/06/2012 -12/06/2012 -13/06/2012 -14/06/2012 -15/06/2012 -16/06/2012 -17/06/2012 -18/06/2012 -19/06/2012 -20/06/2012 -21/06/2012 -22/06/2012 -23/06/2012 -24/06/2012 -25/06/2012 -26/06/2012 -27/06/2012 -28/06/2012 -29/06/2012 -30/06/2012 -01/07/2012 -02/07/2012 -03/07/2012 -04/07/2012 -05/07/2012 -06/07/2012 -07/07/2012 -08/07/2012 -09/07/2012 -10/07/2012 -11/07/2012 -12/07/2012 -13/07/2012 -14/07/2012 -15/07/2012 -16/07/2012 -17/07/2012 -18/07/2012 -19/07/2012 -20/07/2012 -21/07/2012 -22/07/2012 -23/07/2012 -24/07/2012 -25/07/2012 -26/07/2012 -27/07/2012 -28/07/2012 -29/07/2012 -30/07/2012 -31/07/2012 -01/08/2012 -02/08/2012 -03/08/2012 -04/08/2012 -05/08/2012 -06/08/2012 -07/08/2012 -08/08/2012 -09/08/2012 -10/08/2012 -11/08/2012 -12/08/2012 -13/08/2012 -14/08/2012 -15/08/2012 -16/08/2012 -17/08/2012 -18/08/2012 -19/08/2012 -20/08/2012 -21/08/2012 -22/08/2012 -23/08/2012 -24/08/2012 -25/08/2012 -26/08/2012 -27/08/2012 -28/08/2012 -29/08/2012 -30/08/2012 -31/08/2012 -01/09/2012 -02/09/2012 -03/09/2012 -04/09/2012 -05/09/2012 -06/09/2012 -07/09/2012 -08/09/2012 -09/09/2012 -10/09/2012 -11/09/2012 -12/09/2012 -13/09/2012 -14/09/2012 -15/09/2012 -16/09/2012 -17/09/2012 -18/09/2012 -19/09/2012 -20/09/2012 -21/09/2012 -22/09/2012 -23/09/2012 -24/09/2012 -25/09/2012 -26/09/2012 -27/09/2012 -28/09/2012 -29/09/2012 -30/09/2012 -01/10/2012 -02/10/2012 -03/10/2012 -04/10/2012 -05/10/2012 -06/10/2012 -07/10/2012 -08/10/2012 -09/10/2012 -10/10/2012 -11/10/2012 -12/10/2012 -13/10/2012 -14/10/2012 -15/10/2012 -16/10/2012 -17/10/2012 -18/10/2012 -19/10/2012 -20/10/2012 -21/10/2012 -22/10/2012 -23/10/2012 -24/10/2012 -25/10/2012 -26/10/2012 -27/10/2012 -28/10/2012 -29/10/2012 -30/10/2012 -31/10/2012 -01/11/2012 -02/11/2012 -03/11/2012 -04/11/2012 -05/11/2012 -06/11/2012 -07/11/2012 -08/11/2012 -09/11/2012 -10/11/2012 -11/11/2012 -12/11/2012 -13/11/2012 -14/11/2012 -15/11/2012 -16/11/2012 -17/11/2012 -18/11/2012 -19/11/2012 -20/11/2012 -21/11/2012 -22/11/2012 -23/11/2012 -24/11/2012 -25/11/2012 -26/11/2012 -27/11/2012 -28/11/2012 -29/11/2012 -30/11/2012 -01/12/2012 -02/12/2012 -03/12/2012 -04/12/2012 -05/12/2012 -06/12/2012 -07/12/2012 -08/12/2012 -09/12/2012 -10/12/2012 -11/12/2012 -12/12/2012 -13/12/2012 -14/12/2012 -15/12/2012 -16/12/2012 -17/12/2012 -18/12/2012 -19/12/2012 -20/12/2012 -21/12/2012 -22/12/2012 -23/12/2012 -24/12/2012 -25/12/2012 -26/12/2012 -27/12/2012 -28/12/2012 -29/12/2012 -30/12/2012 -31/12/2012 -01/01/2013 -02/01/2013 -03/01/2013 -04/01/2013 -05/01/2013 -06/01/2013 -07/01/2013 -08/01/2013 -09/01/2013 -10/01/2013 -11/01/2013 -12/01/2013 -13/01/2013 -14/01/2013 -15/01/2013 -16/01/2013 -17/01/2013 -18/01/2013 -19/01/2013 -20/01/2013 -21/01/2013 -22/01/2013 -23/01/2013 -24/01/2013 -25/01/2013 -26/01/2013 -27/01/2013 -28/01/2013 -29/01/2013 -30/01/2013 -31/01/2013 -01/02/2013 -02/02/2013 -03/02/2013 -04/02/2013 -05/02/2013 -06/02/2013 -07/02/2013 -08/02/2013 -09/02/2013 -10/02/2013 -11/02/2013 -12/02/2013 -13/02/2013 -14/02/2013 -15/02/2013 -16/02/2013 -17/02/2013 -18/02/2013 -19/02/2013 -20/02/2013 -21/02/2013 -22/02/2013 -23/02/2013 -24/02/2013 -25/02/2013 -26/02/2013 -27/02/2013 -28/02/2013 -01/03/2013 -02/03/2013 -03/03/2013 -04/03/2013 -05/03/2013 -06/03/2013 -07/03/2013 -08/03/2013 -09/03/2013 -10/03/2013 -11/03/2013 -12/03/2013 -13/03/2013 -14/03/2013 -15/03/2013 -16/03/2013 -17/03/2013 -18/03/2013 -19/03/2013 -20/03/2013 -21/03/2013 -22/03/2013 -23/03/2013 -24/03/2013 -25/03/2013 -26/03/2013 -27/03/2013 -28/03/2013 -29/03/2013 -30/03/2013 -31/03/2013 -01/04/2013 -02/04/2013 -03/04/2013 -04/04/2013 -05/04/2013 -06/04/2013 -07/04/2013 -08/04/2013 -09/04/2013 -10/04/2013 -11/04/2013 -12/04/2013 -13/04/2013 -14/04/2013 -15/04/2013 -16/04/2013 -17/04/2013 -18/04/2013 -19/04/2013 -20/04/2013 -21/04/2013 -22/04/2013 -23/04/2013 -24/04/2013 -25/04/2013 -26/04/2013 -27/04/2013 -28/04/2013 -29/04/2013 -30/04/2013 -01/05/2013 -02/05/2013 -03/05/2013 -04/05/2013 -05/05/2013 -06/05/2013 -07/05/2013 -08/05/2013 -09/05/2013 -10/05/2013 -11/05/2013 -12/05/2013 -13/05/2013 -14/05/2013 -15/05/2013 -16/05/2013 -17/05/2013 -18/05/2013 -19/05/2013 -20/05/2013 -21/05/2013 -22/05/2013 -23/05/2013 -24/05/2013 -25/05/2013 -26/05/2013 -27/05/2013 -28/05/2013 -29/05/2013 -30/05/2013 -31/05/2013 -01/06/2013 -02/06/2013 -03/06/2013 -04/06/2013 -05/06/2013 -06/06/2013 -07/06/2013 -08/06/2013 -09/06/2013 -10/06/2013 -11/06/2013 -12/06/2013 -13/06/2013 -14/06/2013 -15/06/2013 -16/06/2013 -17/06/2013 -18/06/2013 -19/06/2013 -20/06/2013 -21/06/2013 -22/06/2013 -23/06/2013 -24/06/2013 -25/06/2013 -26/06/2013 -27/06/2013 -28/06/2013 -29/06/2013 -30/06/2013 -01/07/2013 -02/07/2013 -03/07/2013 -04/07/2013 -05/07/2013 -06/07/2013 -07/07/2013 -08/07/2013 -09/07/2013 -10/07/2013 -11/07/2013 -12/07/2013 -13/07/2013 -14/07/2013 -15/07/2013 -16/07/2013 -17/07/2013 -18/07/2013 -19/07/2013 -20/07/2013 -21/07/2013 -22/07/2013 -23/07/2013 -24/07/2013 -25/07/2013 -26/07/2013 -27/07/2013 -28/07/2013 -29/07/2013 -30/07/2013 -31/07/2013 -01/08/2013 -02/08/2013 -03/08/2013 -04/08/2013 -05/08/2013 -06/08/2013 -07/08/2013 -08/08/2013 -09/08/2013 -10/08/2013 -11/08/2013 -12/08/2013 -13/08/2013 -14/08/2013 -15/08/2013 -16/08/2013 -17/08/2013 -18/08/2013 -19/08/2013 -20/08/2013 -21/08/2013 -22/08/2013 -23/08/2013 -24/08/2013 -25/08/2013 -26/08/2013 -27/08/2013 -28/08/2013 -29/08/2013 -30/08/2013 -31/08/2013 -01/09/2013 -02/09/2013 -03/09/2013 -04/09/2013 -05/09/2013 -06/09/2013 -07/09/2013 -08/09/2013 -09/09/2013 -10/09/2013 -11/09/2013 -12/09/2013 -13/09/2013 -14/09/2013 -15/09/2013 -16/09/2013 -17/09/2013 -18/09/2013 -19/09/2013 -20/09/2013 -21/09/2013 -22/09/2013 -23/09/2013 -24/09/2013 -25/09/2013 -26/09/2013 -27/09/2013 -28/09/2013 -29/09/2013 -30/09/2013 -01/10/2013 -02/10/2013 -03/10/2013 -04/10/2013 -05/10/2013 -06/10/2013 -07/10/2013 -08/10/2013 -09/10/2013 -10/10/2013 -11/10/2013 -12/10/2013 -13/10/2013 -14/10/2013 -15/10/2013 -16/10/2013 -17/10/2013 -18/10/2013 -19/10/2013 -20/10/2013 -21/10/2013 -22/10/2013 -23/10/2013 -24/10/2013 -25/10/2013 -26/10/2013 -27/10/2013 -28/10/2013 -29/10/2013 -30/10/2013 -31/10/2013 -01/11/2013 -02/11/2013 -03/11/2013 -04/11/2013 -05/11/2013 -06/11/2013 -07/11/2013 -08/11/2013 -09/11/2013 -10/11/2013 -11/11/2013 -12/11/2013 -13/11/2013 -14/11/2013 -15/11/2013 -16/11/2013 -17/11/2013 -18/11/2013 -19/11/2013 -20/11/2013 -21/11/2013 -22/11/2013 -23/11/2013 -24/11/2013 -25/11/2013 -26/11/2013 -27/11/2013 -28/11/2013 -29/11/2013 -30/11/2013 -01/12/2013 -02/12/2013 -03/12/2013 -04/12/2013 -05/12/2013 -06/12/2013 -07/12/2013 -08/12/2013 -09/12/2013 -10/12/2013 -11/12/2013 -12/12/2013 -13/12/2013 -14/12/2013 -15/12/2013 -16/12/2013 -17/12/2013 -18/12/2013 -19/12/2013 -20/12/2013 -21/12/2013 -22/12/2013 -23/12/2013 -24/12/2013 -25/12/2013 -26/12/2013 -27/12/2013 -28/12/2013 -29/12/2013 -30/12/2013 -31/12/2013 -01/01/2014 -02/01/2014 -03/01/2014 -04/01/2014 -05/01/2014 -06/01/2014 -07/01/2014 -08/01/2014 -09/01/2014 -10/01/2014 -11/01/2014 -12/01/2014 -13/01/2014 -14/01/2014 -15/01/2014 -16/01/2014 -17/01/2014 -18/01/2014 -19/01/2014 -20/01/2014 -21/01/2014 -22/01/2014 -23/01/2014 -24/01/2014 -25/01/2014 -26/01/2014 -27/01/2014 -28/01/2014 -29/01/2014 -30/01/2014 -31/01/2014 -01/02/2014 -02/02/2014 -03/02/2014 -04/02/2014 -05/02/2014 -06/02/2014 -07/02/2014 -08/02/2014 -09/02/2014 -10/02/2014 -11/02/2014 -12/02/2014 -13/02/2014 -14/02/2014 -15/02/2014 -16/02/2014 -17/02/2014 -18/02/2014 -19/02/2014 -20/02/2014 -21/02/2014 -22/02/2014 -23/02/2014 -24/02/2014 -25/02/2014 -26/02/2014 -27/02/2014 -28/02/2014 -01/03/2014 -02/03/2014 -03/03/2014 -04/03/2014 -05/03/2014 -06/03/2014 -07/03/2014 -08/03/2014 -09/03/2014 -10/03/2014 -11/03/2014 -12/03/2014 -13/03/2014 -14/03/2014 -15/03/2014 -16/03/2014 -17/03/2014 -18/03/2014 -19/03/2014 -20/03/2014 -21/03/2014 -22/03/2014 -23/03/2014 -24/03/2014 -25/03/2014 -26/03/2014 -27/03/2014 -28/03/2014 -29/03/2014 -30/03/2014 -31/03/2014 -01/04/2014 -02/04/2014 -03/04/2014 -04/04/2014 -05/04/2014 -06/04/2014 -07/04/2014 -08/04/2014 -09/04/2014 -10/04/2014 -11/04/2014 -12/04/2014 -13/04/2014 -14/04/2014 -15/04/2014 -16/04/2014 -17/04/2014 -18/04/2014 -19/04/2014 -20/04/2014 -21/04/2014 -22/04/2014 -23/04/2014 -24/04/2014 -25/04/2014 -26/04/2014 -27/04/2014 -28/04/2014 -29/04/2014 -30/04/2014 -01/05/2014 -02/05/2014 -03/05/2014 -04/05/2014 -05/05/2014 -06/05/2014 -07/05/2014 -08/05/2014 -09/05/2014 -10/05/2014 -11/05/2014 -12/05/2014 -13/05/2014 -14/05/2014 -15/05/2014 -16/05/2014 -17/05/2014 -18/05/2014 -19/05/2014 -20/05/2014 -21/05/2014 -22/05/2014 -23/05/2014 -24/05/2014 -25/05/2014 -26/05/2014 -27/05/2014 -28/05/2014 -29/05/2014 -30/05/2014 -31/05/2014 -01/06/2014 -02/06/2014 -03/06/2014 -04/06/2014 -05/06/2014 -06/06/2014 -07/06/2014 -08/06/2014 -09/06/2014 -10/06/2014 -11/06/2014 -12/06/2014 -13/06/2014 -14/06/2014 -15/06/2014 -16/06/2014 -17/06/2014 -18/06/2014 -19/06/2014 -20/06/2014 -21/06/2014 -22/06/2014 -23/06/2014 -24/06/2014 -25/06/2014 -26/06/2014 -27/06/2014 -28/06/2014 -29/06/2014 -30/06/2014 -01/07/2014 -02/07/2014 -03/07/2014 -04/07/2014 -05/07/2014 -06/07/2014 -07/07/2014 -08/07/2014 -09/07/2014 -10/07/2014 -11/07/2014 -12/07/2014 -13/07/2014 -14/07/2014 -15/07/2014 -16/07/2014 -17/07/2014 -18/07/2014 -19/07/2014 -20/07/2014 -21/07/2014 -22/07/2014 -23/07/2014 -24/07/2014 -25/07/2014 -26/07/2014 -27/07/2014 -28/07/2014 -29/07/2014 -30/07/2014 -31/07/2014 -01/08/2014 -02/08/2014 -03/08/2014 -04/08/2014 -05/08/2014 -06/08/2014 -07/08/2014 -08/08/2014 -09/08/2014 -10/08/2014 -11/08/2014 -12/08/2014 -13/08/2014 -14/08/2014 -15/08/2014 -16/08/2014 -17/08/2014 -18/08/2014 -19/08/2014 -20/08/2014 -21/08/2014 -22/08/2014 -23/08/2014 -24/08/2014 -25/08/2014 -26/08/2014 -27/08/2014 -28/08/2014 -29/08/2014 -30/08/2014 -31/08/2014 -01/09/2014 -02/09/2014 -03/09/2014 -04/09/2014 -05/09/2014 -06/09/2014 -07/09/2014 -08/09/2014 -09/09/2014 -10/09/2014 -11/09/2014 -12/09/2014 -13/09/2014 -14/09/2014 -15/09/2014 -16/09/2014 -17/09/2014 -18/09/2014 -19/09/2014 -20/09/2014 -21/09/2014 -22/09/2014 -23/09/2014 -24/09/2014 -25/09/2014 -26/09/2014 -27/09/2014 -28/09/2014 -29/09/2014 -30/09/2014 -01/10/2014 -02/10/2014 -03/10/2014 -04/10/2014 -05/10/2014 -06/10/2014 -07/10/2014 -08/10/2014 -09/10/2014 -10/10/2014 -11/10/2014 -12/10/2014 -13/10/2014 -14/10/2014 -15/10/2014 -16/10/2014 -17/10/2014 -18/10/2014 -19/10/2014 -20/10/2014 -21/10/2014 -22/10/2014 -23/10/2014 -24/10/2014 -25/10/2014 -26/10/2014 -27/10/2014 -28/10/2014 -29/10/2014 -30/10/2014 -31/10/2014 -01/11/2014 -02/11/2014 -03/11/2014 -04/11/2014 -05/11/2014 -06/11/2014 -07/11/2014 -08/11/2014 -09/11/2014 -10/11/2014 -11/11/2014 -12/11/2014 -13/11/2014 -14/11/2014 -15/11/2014 -16/11/2014 -17/11/2014 -18/11/2014 -19/11/2014 -20/11/2014 -21/11/2014 -22/11/2014 -23/11/2014 -24/11/2014 -25/11/2014 -26/11/2014 -27/11/2014 -28/11/2014 -29/11/2014 -30/11/2014 -01/12/2014 -02/12/2014 -03/12/2014 -04/12/2014 -05/12/2014 -06/12/2014 -07/12/2014 -08/12/2014 -09/12/2014 -10/12/2014 -11/12/2014 -12/12/2014 -13/12/2014 -14/12/2014 -15/12/2014 -16/12/2014 -17/12/2014 -18/12/2014 -19/12/2014 -20/12/2014 -21/12/2014 -22/12/2014 -23/12/2014 -24/12/2014 -25/12/2014 -26/12/2014 -27/12/2014 -28/12/2014 -29/12/2014 -30/12/2014 -31/12/2014 -01/01/2015 -02/01/2015 -03/01/2015 -04/01/2015 -05/01/2015 -06/01/2015 -07/01/2015 -08/01/2015 -09/01/2015 -10/01/2015 -11/01/2015 -12/01/2015 -13/01/2015 -14/01/2015 -15/01/2015 -16/01/2015 -17/01/2015 -18/01/2015 -19/01/2015 -20/01/2015 -21/01/2015 -22/01/2015 -23/01/2015 -24/01/2015 -25/01/2015 -26/01/2015 -27/01/2015 -28/01/2015 -29/01/2015 -30/01/2015 -31/01/2015 -01/02/2015 -02/02/2015 -03/02/2015 -04/02/2015 -05/02/2015 -06/02/2015 -07/02/2015 -08/02/2015 -09/02/2015 -10/02/2015 -11/02/2015 -12/02/2015 -13/02/2015 -14/02/2015 -15/02/2015 -16/02/2015 -17/02/2015 -18/02/2015 -19/02/2015 -20/02/2015 -21/02/2015 -22/02/2015 -23/02/2015 -24/02/2015 -25/02/2015 -26/02/2015 -27/02/2015 -28/02/2015 -01/03/2015 -02/03/2015 -03/03/2015 -04/03/2015 -05/03/2015 -06/03/2015 -07/03/2015 -08/03/2015 -09/03/2015 -10/03/2015 -11/03/2015 -12/03/2015 -13/03/2015 -14/03/2015 -15/03/2015 -16/03/2015 -17/03/2015 -18/03/2015 -19/03/2015 -20/03/2015 -21/03/2015 -22/03/2015 -23/03/2015 -24/03/2015 -25/03/2015 -26/03/2015 -27/03/2015 -28/03/2015 -29/03/2015 -30/03/2015 -31/03/2015 -01/04/2015 -02/04/2015 -03/04/2015 -04/04/2015 -05/04/2015 -06/04/2015 -07/04/2015 -08/04/2015 -09/04/2015 -10/04/2015 -11/04/2015 -12/04/2015 -13/04/2015 -14/04/2015 -15/04/2015 -16/04/2015 -17/04/2015 -18/04/2015 -19/04/2015 -20/04/2015 -21/04/2015 -22/04/2015 -23/04/2015 -24/04/2015 -25/04/2015 -26/04/2015 -27/04/2015 -28/04/2015 -29/04/2015 -30/04/2015 -01/05/2015 -02/05/2015 -03/05/2015 -04/05/2015 -05/05/2015 -06/05/2015 -07/05/2015 -08/05/2015 -09/05/2015 -10/05/2015 -11/05/2015 -12/05/2015 -13/05/2015 -14/05/2015 -15/05/2015 -16/05/2015 -17/05/2015 -18/05/2015 -19/05/2015 -20/05/2015 -21/05/2015 -22/05/2015 -23/05/2015 -24/05/2015 -25/05/2015 -26/05/2015 -27/05/2015 -28/05/2015 -29/05/2015 -30/05/2015 -31/05/2015 -01/06/2015 -02/06/2015 -03/06/2015 -04/06/2015 -05/06/2015 -06/06/2015 -07/06/2015 -08/06/2015 -09/06/2015 -10/06/2015 -11/06/2015 -12/06/2015 -13/06/2015 -14/06/2015 -15/06/2015 -16/06/2015 -17/06/2015 -18/06/2015 -19/06/2015 -20/06/2015 -21/06/2015 -22/06/2015 -23/06/2015 diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/snake_oil.ert b/ThirdParty/Ert/test-data/local/snake_oil_field/snake_oil.ert deleted file mode 100644 index 693ab1715c..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/snake_oil.ert +++ /dev/null @@ -1,50 +0,0 @@ -QUEUE_SYSTEM LOCAL - -JOBNAME SNAKE_OIL_%d -NUM_REALIZATIONS 10 -GRID grid/CASE.EGRID - -DEFINE storage/ - -STORE_SEED SEED -LOAD_SEED SEED - -RUNPATH /runpath/realisation-%d/iter-%d -ENSPATH /ensemble -ECLBASE SNAKE_OIL_FIELD -SUMMARY * - -HISTORY_SOURCE REFCASE_HISTORY -REFCASE refcase/SNAKE_OIL_FIELD - -TIME_MAP refcase/time_map.txt -OBS_CONFIG observations/observations.txt - -INSTALL_JOB SNAKE_OIL_SIMULATOR jobs/SNAKE_OIL_SIMULATOR -INSTALL_JOB SNAKE_OIL_NPV jobs/SNAKE_OIL_NPV -INSTALL_JOB SNAKE_OIL_DIFF jobs/SNAKE_OIL_DIFF - -FORWARD_MODEL SNAKE_OIL_SIMULATOR -FORWARD_MODEL SNAKE_OIL_NPV -FORWARD_MODEL SNAKE_OIL_DIFF - -RUN_TEMPLATE templates/seed_template.txt seed.txt - -GEN_KW SNAKE_OIL_PARAM templates/snake_oil_template.txt snake_oil_params.txt parameters/snake_oil_parameters.txt -CUSTOM_KW SNAKE_OIL_NPV snake_oil_npv.txt -GEN_DATA SNAKE_OIL_OPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_opr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_WPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_wpr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_GPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_gpr_diff_%d.txt REPORT_STEPS:199 - - --- Observe that the snake_oil simulator does not really take these --- field parameters into account, they are mainly here to create a --- test case with field parameters. - -FIELD PERMX PARAMETER permx.grdcel INIT_FILES:fields/permx%d.grdecl -FIELD PORO PARAMETER poro.grdcel INIT_FILES:fields/poro%d.grdecl - - -LOG_LEVEL 3 -LOG_FILE log/log.txt -UPDATE_LOG_PATH log/update diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/templates/seed_template.txt b/ThirdParty/Ert/test-data/local/snake_oil_field/templates/seed_template.txt deleted file mode 100644 index a0bca49fbd..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/templates/seed_template.txt +++ /dev/null @@ -1 +0,0 @@ -SEED: \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_field/templates/snake_oil_template.txt b/ThirdParty/Ert/test-data/local/snake_oil_field/templates/snake_oil_template.txt deleted file mode 100644 index ad2c648a0b..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_field/templates/snake_oil_template.txt +++ /dev/null @@ -1,10 +0,0 @@ -OP1_PERSISTENCE: -OP1_OCTAVES: -OP1_DIVERGENCE_SCALE: -OP1_OFFSET: -OP2_PERSISTENCE: -OP2_OCTAVES: -OP2_DIVERGENCE_SCALE: -OP2_OFFSET: -BPR_555_PERSISTENCE: -BPR_138_PERSISTENCE: diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/SEED b/ThirdParty/Ert/test-data/local/snake_oil_no_data/SEED deleted file mode 100644 index 314cda88f6..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/SEED +++ /dev/null @@ -1 +0,0 @@ -67 -110 42 -42 106 34 96 0 18 42 76 -69 44 -40 -78 -61 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_DIFF b/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_DIFF deleted file mode 100644 index 98a867d959..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_DIFF +++ /dev/null @@ -1,4 +0,0 @@ -STDOUT snake_oil_diff.stdout -STDERR snake_oil_diff.stderr - -EXECUTABLE snake_oil_diff.py \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_NPV b/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_NPV deleted file mode 100644 index 887830c756..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_NPV +++ /dev/null @@ -1,4 +0,0 @@ -STDOUT snake_oil_npv.stdout -STDERR snake_oil_npv.stderr - -EXECUTABLE snake_oil_npv.py \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_SIMULATOR b/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_SIMULATOR deleted file mode 100644 index b4b7f9928f..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/SNAKE_OIL_SIMULATOR +++ /dev/null @@ -1,4 +0,0 @@ -STDOUT snake_oil.stdout -STDERR snake_oil.stderr - -EXECUTABLE snake_oil_simulator.py \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_diff.py b/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_diff.py deleted file mode 100644 index afabb261f9..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_diff.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -from ert.ecl import EclSum - -def writeDiff(filename, vector1, vector2): - with open(filename, "w") as f: - for index in range(len(vector1)): - node1 = vector1[index] - node2 = vector2[index] - - diff = node1.value - node2.value - f.write("%f\n" % diff) - - -if __name__ == '__main__': - ecl_sum = EclSum("SNAKE_OIL_FIELD") - - report_step = 199 - writeDiff("snake_oil_opr_diff_%d.txt" % report_step, ecl_sum["WOPR:OP1"], ecl_sum["WOPR:OP2"]) - writeDiff("snake_oil_wpr_diff_%d.txt" % report_step, ecl_sum["WWPR:OP1"], ecl_sum["WWPR:OP2"]) - writeDiff("snake_oil_gpr_diff_%d.txt" % report_step, ecl_sum["WGPR:OP1"], ecl_sum["WGPR:OP2"]) - - - - diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_npv.py b/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_npv.py deleted file mode 100644 index 4ff61251bc..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_npv.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python -from ert.ecl import EclSum - -OIL_PRICES = {"2010-01-01": 78.33, - "2010-02-01": 76.39, - "2010-03-01": 81.20, - "2010-04-01": 84.29, - "2010-05-01": 73.74, - "2010-06-01": 75.34, - "2010-07-01": 76.32, - "2010-08-01": 76.60, - "2010-09-01": 75.24, - "2010-10-01": 81.89, - "2010-11-01": 84.25, - "2010-12-01": 89.15, - "2011-01-01": 89.17, - "2011-02-01": 88.58, - "2011-03-01": 102.86, - "2011-04-01": 109.53, - "2011-05-01": 100.90, - "2011-06-01": 96.26, - "2011-07-01": 97.30, - "2011-08-01": 86.33, - "2011-09-01": 85.52, - "2011-10-01": 86.32, - "2011-11-01": 97.16, - "2011-12-01": 98.56, - "2012-01-01": 100.27, - "2012-02-01": 102.20, - "2012-03-01": 106.16, - "2012-04-01": 103.32, - "2012-05-01": 94.65, - "2012-06-01": 82.30, - "2012-07-01": 87.90, - "2012-08-01": 94.13, - "2012-09-01": 94.51, - "2012-10-01": 89.49, - "2012-11-01": 86.53, - "2012-12-01": 87.86, - "2013-01-01": 94.76, - "2013-02-01": 95.31, - "2013-03-01": 92.94, - "2013-04-01": 92.02, - "2013-05-01": 94.51, - "2013-06-01": 95.77, - "2013-07-01": 104.67, - "2013-08-01": 106.57, - "2013-09-01": 106.29, - "2013-10-01": 100.54, - "2013-11-01": 93.86, - "2013-12-01": 97.63, - "2014-01-01": 94.62, - "2014-02-01": 100.82, - "2014-03-01": 100.80, - "2014-04-01": 102.07, - "2014-05-01": 102.18, - "2014-06-01": 105.79, - "2014-07-01": 103.59, - "2014-08-01": 96.54, - "2014-09-01": 93.21, - "2014-10-01": 84.40, - "2014-11-01": 75.79, - "2014-12-01": 59.29, - "2015-01-01": 47.22, - "2015-02-01": 50.58, - "2015-03-01": 47.82, - "2015-04-01": 54.45, - "2015-05-01": 59.27, - "2015-06-01": 59.82, - "2015-07-01": 50.90, - "2015-08-01": 42.87, - "2015-09-01": 45.48} - -if __name__ == '__main__': - ecl_sum = EclSum("SNAKE_OIL_FIELD") - start_time = ecl_sum.getStartTime() - date_ranges = ecl_sum.timeRange(start_time, interval="1M") - production_sums = ecl_sum.blockedProduction("FOPT", date_ranges) - - npv = 0.0 - for index in range(0, len(date_ranges) - 1): - date = date_ranges[index + 1] # end of period - production_sum = production_sums[index] - - oil_price = OIL_PRICES[date.date().strftime("%Y-%m-%d")] - - production_value = oil_price * production_sum - npv += production_value - - with open("snake_oil_npv.txt", "w") as output_file: - output_file.write("NPV %s\n" % npv) - - if npv < 80000: - rating = "POOR" - elif 80000 <= npv < 100000: - rating = "AVERAGE" - elif 100000 <= npv < 120000: - rating = "GOOD" - else: - rating = "EXCELLENT" - - output_file.write("RATING %s\n" % rating) - diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_simulator.py b/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_simulator.py deleted file mode 100644 index 1724cea874..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/jobs/snake_oil_simulator.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env python -from datetime import datetime -import os -import sys - -from ert.ecl import EclSum, EclSumTStep -from ert.test import ExtendedTestCase - -try: - from synthesizer import OilSimulator -except ImportError as e: - share_lib_path = os.path.join(ExtendedTestCase.findShareRoot(), "lib") - - sys.path.insert(0, share_lib_path) - synthesizer_module = __import__("synthesizer") - OilSimulator = synthesizer_module.OilSimulator - sys.path.pop(0) - - -def globalIndex(i, j, k, nx=10, ny=10, nz=10): - return i + nx * (j - 1) + nx * ny * (k - 1) - - -def readParameters(filename): - params = {} - with open(filename, "r") as f: - for line in f: - key, value = line.split(":", 1) - params[key] = value.strip() - - return params - - -def runSimulator(simulator, history_simulator, time_step_count): - """ @rtype: EclSum """ - ecl_sum = EclSum.writer("SNAKE_OIL_FIELD", datetime(2010, 1, 1), 10, 10, 10) - - ecl_sum.addVariable("FOPT") - ecl_sum.addVariable("FOPR") - ecl_sum.addVariable("FGPT") - ecl_sum.addVariable("FGPR") - ecl_sum.addVariable("FWPT") - ecl_sum.addVariable("FWPR") - ecl_sum.addVariable("FGOR") - ecl_sum.addVariable("FWCT") - - ecl_sum.addVariable("FOPTH") - ecl_sum.addVariable("FOPRH") - ecl_sum.addVariable("FGPTH") - ecl_sum.addVariable("FGPRH") - ecl_sum.addVariable("FWPTH") - ecl_sum.addVariable("FWPRH") - ecl_sum.addVariable("FGORH") - ecl_sum.addVariable("FWCTH") - - ecl_sum.addVariable("WOPR", wgname="OP1") - ecl_sum.addVariable("WOPR", wgname="OP2") - ecl_sum.addVariable("WWPR", wgname="OP1") - ecl_sum.addVariable("WWPR", wgname="OP2") - ecl_sum.addVariable("WGPR", wgname="OP1") - ecl_sum.addVariable("WGPR", wgname="OP2") - ecl_sum.addVariable("WGOR", wgname="OP1") - ecl_sum.addVariable("WGOR", wgname="OP2") - ecl_sum.addVariable("WWCT", wgname="OP1") - ecl_sum.addVariable("WWCT", wgname="OP2") - - ecl_sum.addVariable("WOPRH", wgname="OP1") - ecl_sum.addVariable("WOPRH", wgname="OP2") - ecl_sum.addVariable("WWPRH", wgname="OP1") - ecl_sum.addVariable("WWPRH", wgname="OP2") - ecl_sum.addVariable("WGPRH", wgname="OP1") - ecl_sum.addVariable("WGPRH", wgname="OP2") - ecl_sum.addVariable("WGORH", wgname="OP1") - ecl_sum.addVariable("WGORH", wgname="OP2") - ecl_sum.addVariable("WWCTH", wgname="OP1") - ecl_sum.addVariable("WWCTH", wgname="OP2") - - ecl_sum.addVariable("BPR", num=globalIndex(5, 5, 5)) - ecl_sum.addVariable("BPR", num=globalIndex(1, 3, 8)) - - time_map = [] - mini_step_count = 10 - total_step_count = time_step_count * mini_step_count - - for report_step in range(time_step_count): - for mini_step in range(mini_step_count): - t_step = ecl_sum.addTStep(report_step + 1, sim_days=report_step * mini_step_count + mini_step) - - time_map.append(t_step.getSimTime().datetime().strftime("%d/%m/%Y")) - - simulator.step(scale=1.0 / total_step_count) - history_simulator.step(scale=1.0 / total_step_count) - - t_step["FOPR"] = simulator.fopr() - t_step["FOPT"] = simulator.fopt() - t_step["FGPR"] = simulator.fgpr() - t_step["FGPT"] = simulator.fgpt() - t_step["FWPR"] = simulator.fwpr() - t_step["FWPT"] = simulator.fwpt() - t_step["FGOR"] = simulator.fgor() - t_step["FWCT"] = simulator.fwct() - - t_step["WOPR:OP1"] = simulator.opr("OP1") - t_step["WOPR:OP2"] = simulator.opr("OP2") - - t_step["WGPR:OP1"] = simulator.gpr("OP1") - t_step["WGPR:OP2"] = simulator.gpr("OP2") - - t_step["WWPR:OP1"] = simulator.wpr("OP1") - t_step["WWPR:OP2"] = simulator.wpr("OP2") - - t_step["WGOR:OP1"] = simulator.gor("OP1") - t_step["WGOR:OP2"] = simulator.gor("OP2") - - t_step["WWCT:OP1"] = simulator.wct("OP1") - t_step["WWCT:OP2"] = simulator.wct("OP2") - - t_step["BPR:5,5,5"] = simulator.bpr("5,5,5") - t_step["BPR:1,3,8"] = simulator.bpr("1,3,8") - - t_step["FOPRH"] = history_simulator.fopr() - t_step["FOPTH"] = history_simulator.fopt() - t_step["FGPRH"] = history_simulator.fgpr() - t_step["FGPTH"] = history_simulator.fgpt() - t_step["FWPRH"] = history_simulator.fwpr() - t_step["FWPTH"] = history_simulator.fwpt() - t_step["FGORH"] = history_simulator.fgor() - t_step["FWCTH"] = history_simulator.fwct() - - t_step["WOPRH:OP1"] = history_simulator.opr("OP1") - t_step["WOPRH:OP2"] = history_simulator.opr("OP2") - - t_step["WGPRH:OP1"] = history_simulator.gpr("OP1") - t_step["WGPRH:OP2"] = history_simulator.gpr("OP2") - - t_step["WWPRH:OP1"] = history_simulator.wpr("OP1") - t_step["WWPRH:OP2"] = history_simulator.wpr("OP2") - - t_step["WGORH:OP1"] = history_simulator.gor("OP1") - t_step["WGORH:OP2"] = history_simulator.gor("OP2") - - t_step["WWCTH:OP1"] = history_simulator.wct("OP1") - t_step["WWCTH:OP2"] = history_simulator.wct("OP2") - - return ecl_sum, time_map - - -def roundedInt(value): - return int(round(float(value))) - - -if __name__ == '__main__': - seed = int(readParameters("seed.txt")["SEED"]) - parameters = readParameters("snake_oil_params.txt") - - op1_divergence_scale = float(parameters["OP1_DIVERGENCE_SCALE"]) - op2_divergence_scale = float(parameters["OP2_DIVERGENCE_SCALE"]) - op1_persistence = float(parameters["OP1_PERSISTENCE"]) - op2_persistence = float(parameters["OP2_PERSISTENCE"]) - op1_offset = float(parameters["OP1_OFFSET"]) - op2_offset = float(parameters["OP2_OFFSET"]) - bpr_138_persistence = float(parameters["BPR_138_PERSISTENCE"]) - bpr_555_persistence = float(parameters["BPR_555_PERSISTENCE"]) - - op1_octaves = roundedInt(parameters["OP1_OCTAVES"]) - op2_octaves = roundedInt(parameters["OP2_OCTAVES"]) - - simulator = OilSimulator() - simulator.addWell("OP1", seed * 997, persistence=op1_persistence, octaves=op1_octaves, divergence_scale=op1_divergence_scale, offset=op1_offset) - simulator.addWell("OP2", seed * 13, persistence=op2_persistence, octaves=op2_octaves, divergence_scale=op2_divergence_scale, offset=op2_offset) - simulator.addBlock("5,5,5", seed * 37, persistence=bpr_555_persistence) - simulator.addBlock("1,3,8", seed * 31, persistence=bpr_138_persistence) - - history_simulator = OilSimulator() - history_simulator.addWell("OP1", 222118781) - history_simulator.addWell("OP2", 118116362) - - report_step_count = 200 - ecl_sum, time_map = runSimulator(simulator, history_simulator, report_step_count) - - ecl_sum.fwrite() - - with open("time_map.txt", "w") as f: - for t in time_map: - f.write("%s\n" % t) diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/observations/observations.txt b/ThirdParty/Ert/test-data/local/snake_oil_no_data/observations/observations.txt deleted file mode 100644 index de28837efb..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/observations/observations.txt +++ /dev/null @@ -1,56 +0,0 @@ -HISTORY_OBSERVATION FOPR; - -SUMMARY_OBSERVATION WOPR_OP1_9 -{ - VALUE = 0.1; - ERROR = 0.05; - RESTART = 9; - KEY = WOPR:OP1; -}; - -SUMMARY_OBSERVATION WOPR_OP1_36 -{ - VALUE = 0.7; - ERROR = 0.07; - RESTART = 36; - KEY = WOPR:OP1; -}; - -SUMMARY_OBSERVATION WOPR_OP1_72 -{ - VALUE = 0.5; - ERROR = 0.05; - RESTART = 72; - KEY = WOPR:OP1; -}; - -SUMMARY_OBSERVATION WOPR_OP1_108 -{ - VALUE = 0.3; - ERROR = 0.075; - RESTART = 108; - KEY = WOPR:OP1; -}; - -SUMMARY_OBSERVATION WOPR_OP1_144 -{ - VALUE = 0.2; - ERROR = 0.035; - RESTART = 144; - KEY = WOPR:OP1; -}; - -SUMMARY_OBSERVATION WOPR_OP1_190 -{ - VALUE = 0.015; - ERROR = 0.01; - RESTART = 190; - KEY = WOPR:OP1; -}; - -GENERAL_OBSERVATION WPR_DIFF_1 { - DATA = SNAKE_OIL_WPR_DIFF; - INDEX_LIST = 400,800,1200,1800; - RESTART = 199; - OBS_FILE = observations/wpr_diff_obs.txt; -}; \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/observations/wpr_diff_obs.txt b/ThirdParty/Ert/test-data/local/snake_oil_no_data/observations/wpr_diff_obs.txt deleted file mode 100644 index 4aee6d7ef7..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/observations/wpr_diff_obs.txt +++ /dev/null @@ -1,4 +0,0 @@ -0.0 0.1 -0.1 0.2 -0.2 0.15 -0.0 0.05 diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/parameters/snake_oil_parameters.txt b/ThirdParty/Ert/test-data/local/snake_oil_no_data/parameters/snake_oil_parameters.txt deleted file mode 100644 index 64573d0058..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/parameters/snake_oil_parameters.txt +++ /dev/null @@ -1,11 +0,0 @@ -OP1_PERSISTENCE UNIFORM 0.01 0.4 -OP1_OCTAVES UNIFORM 3 5 -OP1_DIVERGENCE_SCALE UNIFORM 0.25 1.25 -OP1_OFFSET UNIFORM -0.1 0.1 -OP2_PERSISTENCE UNIFORM 0.1 0.6 -OP2_OCTAVES UNIFORM 5 12 -OP2_DIVERGENCE_SCALE UNIFORM 0.5 1.5 -OP2_OFFSET UNIFORM -0.2 0.2 -BPR_555_PERSISTENCE UNIFORM 0.1 0.5 -BPR_138_PERSISTENCE UNIFORM 0.2 0.7 - diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/SNAKE_OIL_FIELD.SMSPEC b/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/SNAKE_OIL_FIELD.SMSPEC deleted file mode 100644 index 5a29e043b2d3740b3774a9deda10d6ead8937467..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1416 zcmeHHF;2uV5ZrJQAaq4aN>g1y1=WcPlbBqDVn>co);-`__|ScYN6=F71b%SrdN(1Y zLZV55qt#?K-tlC!3IOEZbV2)|0N}jXXpfj<+^at>(jcv}Zj9}e!u!+O217ZFONSK7U=mE z;N%Tw;6O96wRIr#)0rssF1?d|dEV2z{p0WY(9cBrvz9twUl*g9SR&6j&fXE1Uwh7I Ao&W#< diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/SNAKE_OIL_FIELD.UNSMRY b/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/SNAKE_OIL_FIELD.UNSMRY deleted file mode 100644 index dfa04f80027b57788211c785cd6a5203769ee63b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 455200 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¨i=5346pcw`9ot-~8K1DbVyUlok-8Bc(txM9urh>0n z`%FKqz5l;`P>M+l0!A0GYL&S=Ts!j$33KTn zVKX*LV(^c3oJmso(pf&E*RJ?}=?L;+#1x$Wtq2=56o8wva>V|T>@^pme&h;#W57J} zUbY42zfeW`cH8NPB$4A&bw7${Po0V9D7>ei9z6rLllugJFFSv;ft3!ZW57XMOG5&h)CGi>nl z93C2WS9~3gFM3ZFTpw>s!g{%rFoktJ;Ios;m&x++Mh4=S*9?TcsMC1&_I7NZpbs84 zayceaxjs)gc8n>0P;-PGOKG+~AC0{>ntpq0JjbU|{|9?T^ugYS6y3fn2NXWMiVgSa zVZ&^0t(Mc|XrD)R18?DZcYoq}TUPO#DFeD~?Ls^%U?d*i)P3HFTD$Wj%qR~dp?6M` z(3Z13;Io&?$7Z@hl;(%u{hcCIjQN50DSp9%eXqdt+^1r1sP6(RA#aiwepX~5RQPxt z?^B^?s_Y(=QMd^MGtWIw?fi`S|tTBf{SE5Z=GxH)42Y^pEHN*~=Onl!5~~ zH{sQ3)99{tWl$>2#Ab<3*erm1e>uKwt~$td$``!!c?MqUbD!UKI+^||^2X-tyz!Xq ztZu%I!7?z0nKWb0`>^-`rQqIz=kq7M9Po!w~=dvstKZ;f|{|Y_yioIzXm8waR7&|e#QJeP0UaH?>fhx^H zP}LK-)@(4IK4>}UTF>RiXo%u=p=-f8+|}PwI3%hQ*DkO@Gh~JXrI(HzpRr;Vj@L8B z@pGmE<%<(R^{Am3^4Yz+5%(nR0!s#MLyKfq;)u1^aQL@`bKd`~p2 z@vLyp;bf+lsfo}a`XH{?PCy>VfkItv_6_Q2#Zn=oBz z?B**E)j>WkT{zaS6UVf93N(^yfXbZ7*k(yMMi(+9I_jv=RakQA4+*(>m4w{x9v}Y4 z9A~Q380=(Yu+nTXqjK|v(Aew;KD!|wdj$a~znWWzK_fE92^anB&&bc*ARN7S9X{J4 zKt2a^LBD|ioEfy7r-)OIRpOL)=Rv==b)f!B9=6S0fNc|RN!VcJD-l|G-~?W~_bFbh z3I&6I$$`GI+ITWE7mGsvyOwpjQy*4Lvm_yVPm_>+;(aJ-^T=sZ`3hOSAQ_73Yeoyl zg>1za+yby~dl6LH#Jz)P)RJ4m6#?%UrL;rBv0vWf3uPj->g6P$Y5!5|9}0%8#A(_? zahi=A&`fy(&iT}0ySZPmodZ|TX^t+|L#qenhU=;8Ns2?=MQw%TSiB{d` zTBvKPf$-2HTM`mVk&y77oXK^O%D0>4i&mi+^$kCSyw_Lo6(fv;^Up!mQ!Qd|$YlI| zVc@VmjA~Pgkmn=9S5i|@_^hcw+njs$ApA4|XGFB&j9tBfwqPN+&?b+a#s*<0J+6H@ zzS{OfC?xGZUT3})r+NhmEXTYDTHepGi%to)@A4LF#D#iTkq@hbl1PYy6$zQroAoZO z{ls(4fA>LqS-!P~;f&_5&q5U2iEqlc;TW6-`*u#{_{JG;6Gq9LW7ITcg-Grbz8Uxp z#UQr^kEXw4Hkd zWW6`g8C8I140?v0Z}jfwYxjwRCv-AM$dDr>L{Gd=BaP2ZDqk_nm;6|s(O#u3v=N2i zJ0Csq+D0AN-(oSxXQk^Zj9<5$>Azs0aD3wueAjmsN{TiE!^Sjmd=swN;mwPe_=e}K)KTo^4S3_D1vukrlfbE_9t>`Oj^~b^f!z*w&&TLq z<_hrC*$X82{RtBM;aLy(+@9ei#^}XoEY&?6C-Y<-+x!zB4*HFN9MYdH8AKNVKup z9E@79f@?qLj&{7=|32Oxu?HA=uLiAd*?2+6RJ`D&e|P&`Ik*xf`KsgG%FlRn)LlWq zf~R1_=I7XJMG~IBqr07H?cglfL|c*I^m%M~)C0a5Qu)eRzRk71jDgY^;Y@!${PNF9 zoYm_b96XrY<3wZ(E!=oTo*5jQB%CQfAHUjTj5eE}045u`eh<12KZ6V9n{c5@Dj4IU z4xaQ~guNA9vDbH#ZoZp|^(b|63f?-#6K}a&E{G?}U{vr)yu45aFDkZ^=x9S_8eZ!a zOM>TpBf;~<=P;zbe>0`>v8zGCt!=BBkvrE5J+8~*cSAPg&7C`-UbwaRzR1SbPPpk@ z9;5d;Pw27i1%7w!8roWcz__d290bnx@WXowZs0vTCV{b&zknClKj0MxO?bt?MH1ie z?y|cm%{UA1D0zUl19w5XLOC$;ID-A3&%iz>>?JzdBH9Nw-&{k2&2-q(lXcWtQu!)b zzCz1n#&~?S(0dMzKTW)Wx5@8^!=GH__$DnmE6l(9lQCGKCiMDchCeI+MTJvMf%VWf zaXs`n5Qz6pdW!eqbYSVI2i|N;#H$<&@hTBFN9HsS<{d#9YBTUI>tI~4Yqwxa@5^A^ zlvEsK<$_l}EbHbICLD(M$|jSbU#Hl@?xOvt{r<-sXSUQB9A;xsl-J3azTYbJ>t~3+ zM$X2C<3_-dPFx>~9Mb)T1viNBe&n0rWghTo0EeF2o1Q+wg&`L;!-PgATiT9DZ&P4zC>|@eN=3 z9Y;A&KjV^x_i=HWf}l$OAP`tZ;F$20IAo%kL`N^$DuBfFZ2Bt_%0J0{SS5pjI3-#Ub)$HN#iRe><7WEms#`x-i|@C}G& z>vMemN;&wj-#L8P!45Dxe83OWD>x>l5yvESpVNTv(qEw5W{As`!f{!jFM@NAoB=c$ ziQ{?MIC8yqH(&5%YuGl$jRYIMn2 zXdpr6i+jK)o{RmP?>Ng>w=kB0A1#DQXKEOQHXnSny%t(I@8S67CMyW5p50}vCk+!O z?KNiQWJ2(8wMx5>|VcsUw?$5?H7vh zk>#WDp%L1Gwg4?)GprLQAJ@lghdz+Rf!>Jz!q2+fNZ=oR64;f{13nL_e040}S^U5_n#G7EIb0=_!@3p5?n3d7H7>y;7L5=o-^|fjT}D&Oned zMSNehWTLL{bW9=xcaITfI3uR_mlx>rRvF-$p2G3PGxzbCi(U9k?Ks(l8x6b zT#46tbg$1KnX9pA_rqEE_$OCRX6F#DD)qh@4|FRbW*4F4p@x3t<=cs@LwA@er~v(F($ ztzH{7&r1h0Eh;&_MBSIT@n|q^oYw{1^fyD5v3WRsloL)L*7S{JT5Q9?+y`4YzT_?nH9pQp!N$KF-@2#8_-aWXeAPM*%v1jg)%+81*6F1< z>(p2h5yGBrSDJ#9Mkt}O$;0sZ&zRh5Uk{908A;-?Ey3YjAH|p$>g5wdg zrgJD+^ZAm5?|;m3#QpHU``Ghr44#|bXIxh<6c$#@W(MY(68z&X@_T$z z*fRVmV}E=MTkpbXPwYgm<5Pf_Gk2y8re8UaZyr#=H^pb>+q!o-|&Tj^C;_A=3q{*IXLeD#MuYR#jz9@`l+%KQmRWLYw9kM zHOG7MjxLePcai0L(-zFkSiM776xPKIT7&S@1tK`b1CiA;b&+42zwpVX1&mV;BP@z3 zV04Y2p^vTZVELe65_#np+_*&p->LJ(cSc_WUX}!E-YCO)Yi6=VpRAVKN>-QUA*F!6 zsBGL)e9h%5zI10lC2A`H^MAg_TQ3>l%}KjSc~9V73FPj^0DoB=;q263(#R zrM;tGQu){?MfmA#3Nt5eg0O5}DKo_VA#QtX45wiw;(M2UhTql++s3FfE`iU5WlMR? zP>mS$ea=(h_vr`;H4wm!FR$R1TjOxcxH({1^8z?9sU2^1Kh2gO#5XFG_*uR|N_kbN zOz#u!Mv!o)&-BkoMWm|nlB}8fn5=PPXYf+_ zyruH7J9@(Jr(7A2JVtnMMiw&+tKjzR;n00pKe8-rCh~i8U-;pH3^RS+AK}5JkkOZ^ z$1=TUgEjYQvL<&t%;a6ek2)}Z#1P;Y`yCEqHsT%VB;JAD$THoxWZAuQNa>U(DpNJV zcb#N#^UB}U{K_f7t9<}2td+srCdQJ0h0Y}CiZzfsIuohnGw}gLjdoJFwzp5|tj=g`cneh#&nu zLnZ&t1p!Z9;?kyZc(0m2S+cU2EK_?726?`X<}TV_7v zKT$>4Fs6kuQ6J7IRBwTcuRbQTt@DxJ>C+;GfOf`fQogWZ24PG-4aVw&`hvCjYGhI6 zJ(!i5gg>5k$L$yDKrH(kTZSV;acRFmT&jMV%sO+7%-$1$ls(E(Y35tpR>bbfzPe6j z9t;IRkKW_*mUZmjZ5dfG>k;wl-3*3LU4c|0W5{a$U$UAf{-#!1|0!N8`1kmCm*rEt z5x}fj`%&1GzmgfNA!1bKR6?HybuxWfCGtD)S)?+AFw5Ljg-urnFk^ov^?sm$0)0)DR|0lyCRfN!N#zWXen#*v*& zNK>-#x*=dJ2JK|}svU$YP97sJwVudttE#Batp|*+_eSA$kHw6oN;B3eGzKXzYsj2W z>M+|W9{-qCg1=)gkSH{Q#yg7e!9jBPpe`mZ=Fe&Y7Js)Pm9Z%#;7lY5IK@W(KkfHF<~Y7mW6;XRU|@+7 z6FI0#c>COP#@fi7QNLaY{f`eK&LeA(Uwo!WeaA~CAa0QGj_{v;s9kOU;LJHb+)VLz#S4_Q9linC12 z(Q;vH^cY4Uc)@7xUI*74vnLM4t;o+?Mx+(Ch6&o0A#A;<$xwn*czA3f*x(*V+_tE~ z91S7UOL-zA4$WU40!hTmdqrVrhIj(|~Z^w`TrzIr7@o5kE{H5|eX8H6QzA|wyErm~~ z?PP${0Y)duABNPdB9m?2A-@SXMLJ7%Ght1w!l%0%88|&18)*cCOx+wZO$)-DV0%Um zHZ!sr86fS#Q)tl~gO52Su%(qus((!;H?$*_5r(Mbun7OYFb#jZ;zKn#rGbPcWw$Icz#Ik(0tRl94xnx2_JW{bMMkV1%Os~GZ*iX~0QFkZhf~3U`_|*PDTstYB zI1GPDrjB_Drq5_W$|2{-syo$W)$L(D;0ut-_nhS$HO7QVaz{XBhvSEVPbP#gdg_QFrr<%@VMZ^U~^qNv3IV7nItK-)mGd-j0!@zT>~`v#1y62Z9uKt>7#>N2^=BjZ8Xc zOC0a(1CP&a`%OGWR^>O7Ra;08_{8US|2>AhWcf^jmN6+wZ-gE5?=m(AhcJd2fiP|{ zJ0RviLB2OVM271XnfR($VaKIOj4eA3SUYY4TejMgN&TGRrv1wpmG>cxioslv6F(3F zB?Els-~)W-z#PK#GazJi0aD3%f=ZPA7zLj=MpizW`f~aOSm!wapC8hJPbD59w$Y1; z-3|bjmNp_~jdHTeBb%(6Kd=XU;xjG(=4)g5#x-X%>&{sTf96y%6I)I*qYpK~waXq7 zm_8W!miUQAA8TL|?tB;i>f_H$R?x&Wl?S%PI1-!Z!Em#dJJZJ;GQDS;fL#5>5S?3x z8(Q0O!~JXm{)7`Wv=*t|qgA2-c)#%K56B_ii=GBGp& ztPb=*O09p%DuYh4YWTJu@C8ccd&BZs+n!_66}3e&tCbo1-k33cHHZD(?e~PrW}nZ< zJ0jDcrA$&+rAX$G8RLMbV+Q^NJ6D(xQBeil9A3w$1s!Gj=7fMPrw>9B7mF|Ud4(^k zWD%;@2SOW_B9+HC(7rTZM&-s>MsbvYR*uUC8|K`_S9Vt5#(Q0ayqZdEeENaNX|Isd z-W|mMMHlgZ-jj9kAgO%sSU#$85R+k_Dv~Q!WZ2a=#==AoCWkB~e9d&^>+nZp;c$&f zH7pUyz1Lx!!ZNYV3>mP?vyuo6>fq+*ix~C#r%b88ypWG;me{bd>PvlUd%Yc z-}?cnDjY-m?1nRa`q(kbSd~_1zoFka=M}#GrY~;ltxZUa4iPR}4C1%lLrVU|#J_kC z@h|Ghc_Z;Uz`vi*4=f*^v!BV#Tq{z1-NsA}iDG!sDlj$DoAA}PBVWw|5wF~tS?_#b zq-5QjnRfgno}BUp?42J@i0f{c>(t0-svTi82D*Wr13I8>do#WkJ`GVBTq{@WL1&CkQPC=Yx^q)*6|PQu)E1<9MWkrI4P{Fk+}MOE^A z{*O6Mh}0N-WMeR1b~}^(aG*$)s%KoQj2ZfwCR`s&2wx=#t-KW~0tO-`J<3$1nykyX z%iY3LZjA){yvzuh@f_yXMll0CjTo)DilDHe4o=!J4BxCN!8a@S5#CB)!rv2#RGmbq zxO^s~zOFaZXO$DJKhzfFEL@B4{y)<0GODWQdmO){q>Y3K76ytU+>3H%?%te3h+@$V zl2VGO*ny~kfl4=0A{bzxqGF>WilAbmSQwbtt-ta6U+?vQ=4GwVgZuoxX3m+jXV0FQ z4SA9)%hV80ze9L+gG($rN4s`4z&WE@aL&k||FywC)~Xgu^}T04n;Ip^FtXv*Q;Wdm z>wI?Z<5;q3buF67E6`ayaUB1I+qH;2dtMTfWmo~42S!2P zZ8NxS%f^sN6Qd+IepX3td=#TN;5V9;s8W@v23qE}4th1_K)21Q=EK)N;WC1cNLn7B zk~AN^ig>6eqD&Z~{PS|Pb@Am7uq1w0GVC2j{2xXM%)#2G~-E0=(d`bp4w@5hyyjV6;{ zCrj>F`AhC_Jc>Qmpji>~r8d*;KYc+%GYfj`DK{TG=?|9`_E~b@;*8{0moUVg4u~4> zxJ;#1s+gmXk(GHESy9%B{#z>5_nG;o2iHK(jX8XudG+AEz6vHp&LqjP_9*@;p%EV+ z^AnyOgS39Ne4lGo;KOp>K6Z1seaB=GgSwIIo|i#4^cM89ROWVkEF{y`J4o(rDU;k= za}ve&GHAASF;zKaN4IAIXa>kYujT}EZsv9_XHGZCqoQ0%%ft(aTlXUxhH`n~Q>bEK zAV$uK#>mJSo$xJ_>if!k&Ta_##y-5}7ctDZvk4~mo=#Gi8>9H$QyP(D$xkkdf((}! zUd!t<_)pJ}1h9Ix1MjCGhOQ*p8(cu|LKyVVaNu?yiX;wtWs(OE7fK#nD?#yu1!$J* zN>y%;q}xYVfcD;t(C3H9-16ZVE^omw$y4PClGco;h^gZd;Vf75MwKcWrD3G;M~obE zuoJ%JQhnc<&%*~+`ftZ^dsZwZPUUryHnTI5wxRb?EP0G(ncJz#_b^&o zGY@p-UV`S3qvlg~Rd8FEc}Uvl*GL||ID(k)3en*;R~8pe6+S(~+3yD8?6-$H;aefq z$3`jMcm6;qdb5z%AKDFO#z%tldOMOC){Nq|DjMGWo_CqTp5N zvwz1Ay0R6*+PuNT+n;3n-$ZfiMj9UVgZG43$k#f?51#lDB9@JiM3*{oCr&OxTxd&j zKFWJ_M$(MPf24m3-iMOC?nbX)TV7_j#U^jmq--0y`U zSG?L((&7F=@;rYA;=IX-ORc#5Rkl=NCF{RAb8+_U(oXndr1}1CEaOA(&V%jMlpnhO z0L->t555-GB-hIq#kWq;@E-H{8T?Wx@Ey(%Q_hCS_8`g9SeDEN5}sVh>6_ zT-zae`DY+|k7W=yAL0&+Us45Lm*pH;-qC1dCw!}<`ec|d(r7vC80gI#+WSG&ju#MU z@{8oV>Y@0W6%DIw=7U_0Ls6M0Z+NpS%=5I7#C+YuopZ58T(yVfUb_T_cLQqbaXp!IT3c;2MzQCJkK2D5EdNzv5z zD6VUzp>H+$$m+$gUHHkHD5kbnn6 zC0~;oC12-GM6uj=G)p{9RrejFB^otgXz~VzII5V(_1(?w40o6O_Lh}=rqzgcUsx<_ z&0UybOy%b;!CB#oI4eY}6TUT4eJqOSSEg~WceX4q{<0pHe%J@|!a_)iT_%dpT&AI$ zI6hjTAC#v$@Mg(Xu>4Y-WPNHMuE{12F~y4H%Nl?Qd;sITURRDc7+4wV2#a!elTzD*C_a9ch8oH8O9Fjh z=W|b<%lHB@Wj>O`M;Y9;g7b)3B_uy^0ElW#!Bm-Y=lN<9(y>|cXPJ}akBdEuI<}zM z#_v?MJ%JXFm%tdsaWK4orFoLM0$1s<7G#f2lKdL_7}5L>;x}8ax#v(S_wWZsJPpT) zM=W}lnrDoY>QiLCweynTpocFHU5>!2s3=(8`jC{_tVHqQeKh1^IluCT3sk@l9(H;| zY{XGX5^Uve$~;3Xa3=ZZM!-0_8N`dmaP=dyN%$gTkXd>KWM=k6(bGH3x1OrWZK6dN z9>Li8J}^=_%RK#62DjJd6v!tGhc5P05y!4Wi|zxs+uoT}E_(q+6qjMd)^DBg{f*QA z-G5z~FTv#rR9~0j1sw{jjfb{Sb!D=E?jH*6e{OrhY>TdYq#-H>{MyByu;s$<#l|-Md?hSW!o| zCe8$E69t^lb*@QPOy;cH2lBrZLB4H0imuH=bT$6t0(xo&eYqQ4j;wEwPS%Wmjs;pcT;$p%OR4PnpBR379fn`u-wEG(sXmrX;FIWWIO)>HPd%y)2@AKw zx-<95o{8sBT>OyEv~%V+7)8LLeT(>M@zt;{b+csacoElDzX9=hIVqT?3cQyspnVK? z{mD)eU2q7L*1iU%P(Ku%?22abN2!`$1ufKB4rJ0&5a~plSDcOK4r?2NYJD+u{hKf8 zO;{dBlY2A2E0v8|kKt*XF+6E|CwzbRCjI;UV>>_iRNEL1>UTbORCNHT7kmZfVfu(_X=t&E z-5I!V1C?cG!-U&U!|*9~|M~vM80T*+`0qAQV{MS(-3DiaPV=s_#=%B~>#*5JgH&0~ zLviL)8oXi*pVW01)GW#5-6qFDqPSX8no!8SYzjea8bS)Y8-UI76JRyvEZ1`N8d#`5=b~Gsry9^V19Rr(2o@>3dn=J4B0Ms86 zP(St+Ma9Z!w#I;}<#nZ7&nSU#K@GScV1BCZ9e2EK0rYg51!~7x4xq~xwAkm#{WktW zWlAbBtWF-o&TQ+1Z$ zv(=-iTE#lL)vgY#r__UFlDv7HwF7tZq8IcYyAHY~W+VKVj~4a6h|G?+RL0d2!(zW; z*ou%&_%=)Rb!WbUmIu(#eHtJ5xDk>mxCJcJ%Ti3nem(ceoGEq zE#khlzeW6Vj}!&z!}Lc4rurY^o}G;+u_k8FdvYH19{3zZaXgyElvB0KGBn>e947g! z1^)E`^Xow-TdL4#-)xgjXMxF2_N%i$)zU={a zaCQ7xezrj!q;6rHQJ{4Lp^xHfgpN_jYxojneRNd@IeH69Cf|m4i*zVDm@uJGi*!s|20kDfD|I1?LhI0MX(?6v*qi2lwgCs_L16ptf_ZzdCa!*vF6frb0?mUFEXS{i z{Diec{b)S-vuX#18r;Fq0rxuLOO@*D!+d*}dBGi})%>yrgCKkLG}tZ^N6x&fLvh3_ z>i=DbFaJ0I8b9jt%XdG5+#afuv%dxrxpxm)+{}F8!QdG+6x_Bx;65}pkhouIpp!oe zbV8y~G{XwbS>fXnoNt_s;u%M&zw&8*Pf`># zKa1m6UmgovTi6;~ung%M;f)sTyu9KYr(wqV67ark$$h)Ko2+xQ1ik5bpx5Umil(qQ zecmyu-t7j>iFE<@^CFnu^``mH=)PRz(fKea^dt12T#xXQLq2&D>7ynhzqW^Ch|tdBQ=0i%Y2{%ao;Sw*4Q95t%0 z(S_zHj|MN_SKtt`fRmYP!ClF{3PU`WgT9eGdq+ngzoU%w?P^SZ^-#bNl~4>(u;_#@ zQ>u?;gZLA16QM2RHJ@Ol4TaCmVgIIqvw@BY%1U(NeY{KNtDp%+nn>^H_N&d|6U`+RS%m zume03Z29#yqoMfhAUIh2lr-!eh~mlNbVl_p{z#n`-1UFYZ&>0E+cFC!EfJ1HZJ!ES z1iU6C^JYOvOCki7%M+PJ+GOLWJ}~%MH4H9FMA2B5=Lr5q)pf0Dw&4Nr%h&;~qd87V zV<&gr9bmYH8w~1riSVX7^0zM%ogOR5kJfCQxpWN9jBe|M?{7`nzvmb_%y;f$cW8gB z#wR+|z_#KAa73<@G*qZ7UyslI;9SHCS@-Di4c7AHh6w3<+`!E6mBc;g;Ap%Vd!BE zgtrwaDBdM{Mn}o_QacQOaTkN1Tr@KRWpa3VcfLyCe zMX}jw>YJ#>pLJJ)$8SV@O89Zu>6a#X{=S;@>fVSJam&cIKK2kLp8&J6T8YA+=VVJ& z0gTwt3M1$?6lr`#GuMq&T_>Jq{;7k|rE1{g=gIY2{g%6PuM|cPSqsDSOIZx(f`V=# z8Ne%(?@IkKxX2NM^Zu>_OB+A`*6jS-*Pr>W$~M4z*+@Rkaz5;|*#&1h49NAvw^2MM zf%+P?^L6jQMV~Zj= z_I;RqgR1vr_Zrxl!|d~R5Fl#ev=1)jS{LpF6K#DM6~X2h@8+RkGn)+YKS92p`i{Xp z)?u*P-(@su{r5Ky@bCW9XTIC}Bj8J9F`r%K36k52KyVFyDI=Jgmsj@Ui5pRviYNpN2ta zCjIC8A7h*XsckTTwZXmIp74Fd6h3c}3GDf_9WD>;Mp_A22@m7ERf`duF^d zRqyhWX6%>;^L1`Qi28SKV3$Vj;SXgn>#YUGl17C0Q7FucCd0$b$d|Aq7_|Hm1}$M( zM5%pTDAhNR`5taAfuC)s`2x#Q*mrLbT*-S*?tRWfanB~|efutd^F$ML6kg{GEx*G7 z-7C;#svYSk*B>noFDKjHKZO++w!o4W7&_ZU>2ZG!81J;(#)CKRjeqTcH^@GTot;Dhl&zGQ#^hkA_y*;Bqm zxAs0-oUSINJqX0qIl%J$T}gMDW|Eok3`Ac!5Tyj8Y3ormGs~lDFCysQ+Q`MxvJmkq zj2rF%+>;qwf$KFCM7>N{9v}gQq;@jO)`Wce>5YLeW?omRo3oIM59wNPCxsjhbxMwQi zKzlC-@vlV)AJtGO9!EwGC?ubd*$SL7Fwe9T{Z}H@H-!0K?;4A;Tjua(*PcOjb{X6q zXGz+OwNUi)KJ{w$zDO%jMBc;M_So3uq#J<=}dN0Z(xe5Bf z9e>Db>&wyf%po)zPN>>3J(|wy(PL^i!F)>%&Qw;yz3`j>7TR0E{Dv~~1))%DLdHgK zBOmJHF;KM<1C`m6CH4LLTl4X6-%#fJ^w}L19OL+k%BxT_?<+ixsv*zWosOcneW};f zMf}U5!SHLzZNBn>A{_5%1huPiWN;pvL$%4XHP>*6^R0$86P!t(59K89fho`mS)k@` z(DVo!Uj{o;wVmB*+Sd+<)mMcDhjQ6v90#~p3h5x|xdS<4!+hgWxYk5WKD{L$G+Hs> zlqLoo|Ii8F-}R7x`-U;!_fcx7c+iF4TkZ+R{Ruql7fW75%}3F5LcQdi`L{!NU>Bt* ze&6FgaPma~be~yH3~U?F;^lni^JD8*Ctz*KE7Et?VX~FW0LUK)Fci^rUw1Uq3!!Qm zX*BK7dRV>06BZkF=gjL;xYxUNFonF?&hkumj#JP1Gx;wzQ&6_RlRqq52el8jL7#0o zWca2qwD`7^l$u$?`t0$L;O|bfefE;VuUa6issTaf6`B^DLbE7{>K<+htxJOWNjc9 z{}ELloAXC%qoLMR7v9@>l8!TZC~BTYJx5pbKY|XS+-t(u=n*(~w*fS#S`$OVb;x(= zPD%}~!AAKUSa<3c(Yc;LirsF5)%;&z`HrG#Cd-xg@S$qXax_hT9K-m>WsmJp+{?Fz_WEB|v3BCyGZtnr@UsK7*(=5NO=*MD!U62@A z4I2jTAi8#xlpMAIn@|y0KU|Kcn_JOLErF_0c2sM9EhN012CL$_b2cBtxsNIXVY2mT zu%2zod;`$3UokPCJDa=>8HD~5E7|YHe|`LqwYXhUeWRGK>)R`+Ua_A)`6~kIv|{1g zi{s?uw`VA-^QIofs|1;c?WmY=fIl7a2kLK51l@i4#K^H7d9^uY+oxjK)UpmXuDVD1 zpEyTKb>zX;#~mhI-HE30*{tq-096}gLsOG|VEt4Zh&^M#O&b1@`;_7aQ>UGQ2|i71 zo<-1d_%_0Au_kYd2czHbVeEIO6TaP2eQd=2{Gn=H2hvo}df33$=+<;8<)%1Qa$ht!nC>ZpiPPS*Jb*D;iYF1W zHIBT#(+mCf#j<_Nhdbe`km?)Fd}_0`u*b4_{CVdRxFoX@yIg-qzL^G~=om*m`i~bB z4IZHK&@jHPh0Q;j6JXGoL&TWfOUP?pCfh0}LDGT2u-Wo78L-Wglsz~NlkKK}-J!i` zx{&!~e^FI-MqcW$3y|2&4%WhYZu;VK?&}s=aG1Fi?D#a6hx>(={8mDXmXg=%uILwh z9{oZ(lLx4j>Kns+-42vv&oMwJDM{3X4w z(9}E_hJ0})W1o*hzP}0CwstzC47vwfwrwSY`WlfPwka^xvKvgri5 zM^ipOhE0(ZAa2=N&M|X4_g%gpIL+S-Q%tK_9(4~|PN^c2Y)W29Sl{VI3^P+4&WRnHmojbRhvYO@~< zt9?UEgEk{SXfoO6>cG|?M?$ia85z9xCfT`P9;TCgm{y>TrZd}7{PP}FtsF*E>Ox?1 zQ!B(DjpbbSTXR36mV--d2uvI5!SdjCXz4zgK*ARCGRzZaH1@+8SN_Il(qe$WHFN*| zMvi5^-p>26&w)n%N}tPc<%t9p&mAIvvZk_HgbwN+;4P@_H$wHkKlrQ1@}c=U1;fml zMASM7`JsQvHiLeU-bDdY!n4Vck4Sdwj{yhK7qCx@MbjBGQ2Z^1s&2kaQ*stSlBql- ze1FfmUrgkF-e?53Ex*BDdkI4OEwl_AMldpoyhxsfGgceojJ2JaL+z95GhsfBim}*N zKb3C|w1jK-W}s5NDecnA)_S+kr|!d=gl?}cW4915{)W~!xN&1I7)4bOGy6*9N4k@e zH$xyJ(jQVA&y%5k{-h#NADqVY0LKmN{c~qEFQ1-K)kyYy&QXWtv?5qf`f^^6fcwp+ zh8_iW;Ha*N@H`SNXIl}A>ElRyl@Ytw%>ZX`_MPaz{Zf5wCMIa9xufQ~AN7y?=OA5F zLxwd-NafG>;4YHqe=4gjyee@hv(naI^6` zs^hplP+O{!RO>NaQSor z;Yll6#`qKddntML+8=%M+t9bD<-a!gM+|U4s!z;(y0`bB&Wu#PHC7&O*K1+7Hw&q} z_6-!J-=J>Gt_m85L$Q}{E&ssN67IIH0We9h*=sbFf+zKXDfl|Lo?1&hxkq>e#<_qP0d3^HRrecQ*_@6r+e;X5s8IV+1j=nGAuS!@=uD9Kxd-v`l9=S81&wPxvk9b3_q+ zPAu$%uUe{aJo611AAowLCH(Ve>TtiN5;e?^(XL+aSv^fR>iS^3pnKpH_VrxMzj)dk z9=)Uhf7oPtS3L4qPl~HD+T_3-jgPqsdA2 zko~#`BwcvS&A!)*$bJ%Frm_$CG_dvZhab=~uaH=sI!f9+{-DpST=bbYw-dg7OSFr(Ip`MlAxM2=W{){@5yrlZfmLFhAVVkdk@r207K8v!*qFm@pS z_Gbe;KDZ6FSKXz`Nt;l#bP{!4yGR(gC>^yGRQdNB74Y=4C0NU!BfPU6^41BY==5PI z`uY+IR9Re?vx6LQo&bTGeh}c?j;02KQG6wes@Pl5WG`07bnq#pI*#S$r~M%EV=h6s z@fq+x%GLrNDxu{LC1U-oh&)OvMDONg^ls_Q`*&2Tk1*fJ`sFyN!<_$+vK5|Gg<`*5 z*;J)61w{)cP*sN*5#KOHWB=Ra40ZTHDUD4c`5Z4@brY=V;Tc~Ch24>9>A zLykTuh2Xv~AjqEi^h;5Esh#aTE}+R1O<`-lhme-Jo?GZyOyuk1VV1Q41n$4fd_B>! z@(QsD3?mPBhoN`;EA-xM)rtPAk?Nz&H`?g zQeo)y8thjY!+#6f4KL-!ft}tBJCj9);bD`T5E{NTZSB)YXl*EpTo?l zv(Qv$CfnC?j;hG5q{-ZJD2O=;>8;2u=@v#50>?n4`v(Z##bUUJThQ{rVq()YmOQB6 zhu&lidJCUA;X5YPCt*J04~A%P=?ee-_84g2>yHDvmr=D3qfj)k3z=ZxNAACzf?jWY(ChQb z|9t;rjB{LS8vttq(=D1fj7;Hw$G?M@d)DC~TP4~}^9rj8>q%W@nuU=-P|qV@=n~!? z-uCg{yKa4Qh#E=5v_0<{*S^wPfGO3ut*#olFSYLGJgsjb4Q-(QC)w81Mh$ zynn_$lm*ni#eA}x{8}2Iy(m7UTt|4vEu@ytioS>VX{ z6@vUDZFsk5I*w3lpgj{Wp~$Bfbzx~!llnLu_P-CGMmmDWL0>Yl<2v$Q3rT@F z54-!%gYtLl2^pS6&c@rpT-|brviyRk^6DtAW#{vpm3K zv}`UR6Ffpm%d2PTIV&GM7yn)Bm)3u0r1~tG&*F0>jt;UHl&V<&>}^J)?IyJMBUaDm z`iQz@q4#oRUQKhE>O&-Gb$6Bx*XH8?cHPt~x`D`vM|M&*x$NRH-BliB?Q6V;; zHj|cdKIl0h6FrSwJK?L9>SJG8!ScW#9CPiPpi*KDU-rx3m>=`0Mvo;Za-Kt7HY5q` zqD>s?vs_U91l?}H^nBVn;H6HUIbeIJz-R4M5O zO*U_V-Ab>aXvP?B?YC(}b>LB0)w2v1t(wc$;zpq56Lz0*?j3Ub$w>5wi$Ran&a73P zlj^f!zKPZs(PU4p&~390{5Yt_@^2EV8P$Ly`wHr^^oD>Jp5X|UM4|he{qV=@3xw6o zAk$O;`6wTf*VGrPyf(sK`JaSux=k8>jD}?+++eA20@*#eD6XibN;AjNWLpj@BCbPm znKc&|c!sFnya%!U-C+rmI{X|gMY%BEB(>G0&@Duxra zlj)`J8bd2pi8`)er599{-ds70oqeuMl{dy>0* z7aZbCVgIc%Vioy^T$vLMF`8#!rPW|G>6nA!-7Be5Pxg)mv3e$v29%Cp!NuK9A?hv$ zutsznRxG0kzc--eS4|>NKXOYl4BfYyqI(6K0ZQ%T3sQY-wkFuuvGbgMh=e|g(b(nQ z2PDspX+H%ARulc4y3G72Ot>)*jnqtqzH&h*dtw00U%Q0ZXXYXw<3@7(8AElI0vr$m zi1o3T>I? z$||De?;XUV<0QFxybHQJbVGMPmIapTtC#AV#C%RW)Ny>Mme4o#9m?F7L2y^6y5m^? zO;MvR{%yjf&A)K8f2g3#)#$uY1>(i>6!GFmCHBBL|L zsf*8RVan8p zIHvlOpkq*k^7Zp!sqP%&I5`1X2|vk^DTAY#_n^AZMPlndliVn+g4Mc_5L;Y{CNJ1G zWOozon$${@(|*GNKNHx|<1iP$MuBu+9|!Sn0T4^s9(%?6Xr;Q9z=5yiMwt`39lD5a z=UKI))c(69)i;^>JXS10VihXrRDMRehyBoU;!vuW%l0MOU863ZvBLD;18{8j20@oT zMujF_STSo9aT@&s`9vL(y?iPhQ=J5dm&cQdr9a56APKDL{|r`_OhuFDzu6d6M!SY= zp~>4hIC$~uTB#lP?-J<&<`U*ukRDGgVci@PSVJZvDo;Qwt*%6(9Z9Y)4nVj5Md)Uf)Cu2ZsXmr15oUxQ zN6;T3=(VVz!ebq@og6?1c8Os=RqEn+S8(3BA5D+<5e6*Wj$PS)li0*A#6@#A@+oa3 zD>(*Ebf`kj)CpuV|Ae$W=mv2Ew!+$NX=w6<`Sy0BT{REWvaLP>B{rohyu6GFO znfMLXFY60yxg_RmM63Sa2;KODG`Gg0Yf~Y*K9uc*uTiRR8uJCrWM>s^bQT7D&OyaC zMVxfqkPaGKgQ7_%smrt}f?Etb3q~Ve7?fj(N)K9Co0}6?-Av@uFR=5)O5l{gBOE*E zMy71GA@_1_K>WZP5Lar3CXd+jxi6L~c5pQL=2$rL-3}^^nXk!>^b$qDhWHN|)N))bOiZwsfJW8s9}7&7&43Ayi<0||rP zLVRfxnml0ROVt3Xc)^z@Km7_deg|RCq66Iel98m>trXapQVa3p?=hbfT8*$KSHTjLTL1C6oN+y2Igl`=}9q8`=myPr0FxCCv~wE3qIqo z;kdK_Q3bJ(sm+{cZZEHCTKOfl#u;1$u-5R=+fSb zE1Pj3#%>P<-eS zRa{<0Qxvq|go!%rSBl~`t}i8hG(%w1P7_#Xc8GmLR-%>ZO+t#J$FRc5gWgu%F|ouJnRb{%I?DvO|qpflIucXS3TsS<15a3A#^TsJOHh2IFI9AVM^k!w z!^!MNP&M6*z9l9=Zf}W**rr)#t=~ zbF2K(W~ZJovL+o>p9$z%w~P)S=*fJc)J5D|2>$GXq~VibwC)G0{}=!p&-5o=JJ>vA zYYE9%od9(?*P-@E2yyCll{__{3L6cs!iKWFXmZO6#WjgkQN(;YIdEEjI2_10#cetu zA{x_5V9RLySsZ%IDyJjtESax}x{OE{LSJ;CWN4f)=Ijq-D}e00$~(lnbtdu!J|u%b0rl!* z;M{=u#CgUA^6cqANF1sO8_PbT$qhvmp8%@ZvxcS&sD?AMuED|k;@ z#vv0{ll$8Yt%Nv2KHMZt>r&A9P%1h%1a!jpH`nv;wHz1bTlD=LPK@;sjE7xA^=Ad> zt+|A$f z+Sx@pn}!-dVtGF_xptc6QEyU(w_Y^GAO&h~Zh-2cJGms&AEfX42uQwl1`>_S*gWe9 zTG@OhbaFard|!pm;cn<0tI-MHO{qTilncv-F2_l)D+H5(DD3uZBl@0wO-JUQWxiL` zrN?O@vds?h<~Bhz$rO7k10?;{BQus)BVRa}q_?HQrMJVN?v;qR{wgIexr4CT;45q@ zABZMb7P4IV464x3LQ_UG!#REe9G)%5B^Qn*nnnX4LR~gnA@(3 zys?g8mdw_~)zcy6)H~wWzLNO_l73+_T=qQ#_4a#+`(#$@+Q!b@HDG5zl*^$>BirA5 z?gv%aZADW?E5P}knsDSme=c?SAfkDFHl)5OfX$;evYOSQXf@57NJ9FP%dP9s=~_>8 zdg;{(-)*TrcjjBg&XSyRX0l-Rv>bapZD9K)j!>i5-pt12YTs&ArJaWy+o5Y)tG=$Yxl^sKqOIJ~R;RaPmET$^I_%cY$yBwDfWA?=$bY%v_o@^Ej^$}xz5ej2&#AB0Zvs_0bEnHcVGP2j)Z zKM&@MeR2h-8MzDQqXq2wR2yf$)}muH!^b?)dZESBAimJgZ*GNvo`(I|!tha3|4 zR-e6p_euKRbhv`|p+V;w@qFb@I>v8@l($dIdqq+uCsZ?z{{xdsw=6+jwZ{Xi$u2c4Wclc)My&+%`cC-bd|`-9Wd zPYY!64ea$~7=~5oQ)B)(nex?SQ z>h~deNG)5(2tX^(Wd!RTNy9Q*bbPCaPXB++|Nj`{+?Cn}>`f5j41c5jpL9WTAsBl< z{)n^YU8G~fey}`1Fm-;gN?1AeHrj0YDqzcf?5leMvfn-APAm?qkcK|F=vZuyj>jIe|1NC|x+m4=&3y4!E~DejYl4Mt2ljci6z4!+ zYLd)yky95?=bH(_s^Q0R!ty_PK{xLFn=CuJUEQ=)c#P@BP>rft(rPF zb`xTc0#3Bh5Ues^pw^&Eke^*n!Z+<@Fd&|qkm8%6vRo|3Ptq9H@aAJU6h9^iNqiXY#h z@=rI?6z8>YWy@|jledd2Xw@RR&wE0y=>tgb`wXFpZwB*iyx9v~bNz$~W7zX|*A^F5pP^>m`k=_+6Lmi4Ev$WRi*~PH2or<#P-oaK zC~~YMks~iM-*A#K(h_dpI0V=IRY*YVV)A{|E6CK0fQ-T+Xi_tp)r%da@|RhR>eB{S zzqLW_!*^WKtC^(#fegr_*^tqT`_+)ur#ED7?S>|YS)Q?DB$cnOq$v^Xj2i#TY)`>u zZkyr?qPKno2!Bsg&m`IT$|**zQ~D|a`V9GZpVFT<&P@im&VlsT*LuO5Q^MIF{u zkS)*F`VXt4)smlNqMRJLIC?tTCoe_&{p{;4_4#a*>I-DPl*$J59)-g6<}&QpXo0aq z7E(2^;KV;}@{clPp*CA<%nT=)1}<eL>8Z7SWDAn=}Q-3C*Z`Q5jd~x>3@x6h*$< zm~W}Dsp~Fu$Tb(7cPF8~(HGeHbR}5~RV)veKr)v~;6cY@xI1zZ3EMiK%Gl;Zp6qhS zO-X0#d%^5Jh&C!edoWGO3xzw1N8sYv!(4^;M>44U5h(I6Vzmu+2s>rbDps9L)^;KF z?M*oS=XJCnAou@Bd+)fOzyJSVv{Pv)ZAxThqlJRWGY>|_c zJeX~Kl+DYA?&2k@(%IDCoEjSk^UXiM@Xc|>a5!iJXX6>9JZcmrZI9zmW*p#!bH2G} zRc~U}KL_!Q$v^p~kB;COv*8uSS)cP6?Aq;Q_#YVw{|7n$t-(L?ab7Frn-y0dH9*Whp27XDrhiFN$7^ZtFtP7!>YmOjIHZD;ZO^UyNq86p!m zl5Acc9H)Jxz!SAn@^Lo|szbb`%L4t3KcQz&jt(8XQFGQ%sAB4sB>N=l69FZ8?eJBxhXPigtFHuW}q_p$`O^`ZFwLQlghej5wy zGL2okR1LowVU+4y}Bu_R-s%6*83gPFO z2EQrl4bZPzA>TB?x2-%3ldTP<@lUqEW?K`iwVp!qoIp4(a;3ni_EO4&`xy4Fqcmxa zH`>@<<#}4OSy-#(@LZ|R(n_;<)uq$CeEBpscbpTcZi?U;cUtp|nPqU;rUd7JnWA^N z@Ken_#b3TO=Xbx6dw%C3tX&5`zISyN-(FA#9!&6BcaIGT+RCnL>Z0%0X!u#xH-N83 zA>VYtmyx>+Q?pM;3 zS%-*2JTr0`-*L23%zGW2<9i9Wwm{#%28*f@0x`DO{eOe>Dy$KlefXKi3N zXD-%N%pjkKsiN+viUQS@r0we}F?OwyH22gnbkG~jFJAt|V&=So=hQ(gJ&JhUk%7Fr zQ7&7u+mkeEuJJvaKJYy~zrbO`WYH^s8Yw$$q{MeQysC0JFLpTSUQ|DZb)LSJAB+|` z>Fcw=T|D8HKAlZ4N@0bO9nmLlBl;XW-2lE13i)OWzWskvFw;I%n!D;M+D%TvhQ)T& z^XYInZn#7P-cOZwjM$5D&-+UYrbVKoRw}>Ts6SiVJQAK0s@T>UA`e;bJFn@f&X(DT z8i%B@d~f_FzE>6nhjp27PI*Sk?pC6%Y8bEf`^2BjJna5pdll>Qcnd!i9m@AaXNzIO zE8(>@fK58$%xrz!L*$mz@qKI0Q(GTc*Qa#hYKn0v2~g*Z`x=*tQApdHu{3{w}UFTb_|lTCQ98 zzEzv}KIb)XNEUa<9x-1-o<)f#7_T|jnm;|b+`V|7Epr&;!n2|R_}&l?k!vwp@ZD!Y z(}uAd>$1^DX#x7!$s54;_n!H;4L4WtWnFQ{?Az(mqT&#A@UKFu7@pIsA`Xr_-qL`} z3#8qjj4*MvnY8rLM%e!rJ#)iOu!Q(jcn&EQbt}L5r<)yk?Og*FV&G0%Pe1U?c{Mz< zLj@cX#r`}VOv-+JDKY&vuQfO3CDoSh&t_G#Zf`h091+C#%@yw~ec{L1TF0jMI>Bzb zTcLN}L-c;pvjKdc6!Ogzd`GetV{S_|X=!u&PGU(@MO{vRIm?JK>RrJp2bGhCbl$Lqm9JyA$qZNk^GetO`F8R=_hS6@#m)3ceL=rms1>`OyTu=Pp6- z)Q0#0J}cxCFBR!%+Ca<;c9B-dro!Gi4Vz24Q=ifzIA*t`0ZGnM<_29%X>(r+ZEuXu z?{@Orc7<%+klyg@Ef>8g?(nZ`n(_|=$Fa~<(JxM4M)~!2FX2QpnFW=wvqy>5Jb`-#emiEN>AFnAt%(F!c|D78FSF#g4zhQ2M)A-TlF8n~BneceK=Kt=8`Pa$n2Nd!jZWDR^-BoOr-3QWXE8fVihWy}naX-Xdhx3>5q?|aO5`HJ}`a|P+*^3A6 zwJ$m`_aAR~<NK2*Fp9AZ!4Cwzx?lyR+>udS#46uY%|X@O@Lrw@C2iO zyc_7EQI72=x0C{wy8!X|kEI+%~AGT&5jqLfc zIV(hdRXIFv*}^NOo-IpqW<_GwcdwB{(QCzDAMpR#aQ~x?^IhQ@EEa2UYVotX9|Ian2E58*Ev~o)UKVQwDmOWTBUvh*BuLBY!C56COY5%;3pb@+?DI6Ow?g zZ^mI)lR?yP*e^If=|=reoRf|gYhcESO;SXg9&kJ<{4oQ1vaO>(iT)MiSZ4We{>Nh# z|GMHL3yV@C-Syx35v4+Y_~v&wM9zRq$IqnvIG+-Fm-4U0r+CH2CGNi;PGX(|oq6sA z;WN?qghy5!ypmnn%C$S#eUHH+XDxc%J_)e&mA_Jl6h%*V-p+ zjeIkEc-0!deH`FBsUc_3Z-soz1>eQKx3OYxkQ8-X)Kh11?EBe{0yTu6>az*;@984t zMHpbtP9-TOSQ{>hpZF`iDz;nr1U!{*u&i}~P)hUTKh0fO_{a97*UXk5z1Wu@-P8#V zYck+6VJ)e298B@qTKwl9UtZ;#%hYsdGVfoO{G=D-*)I;lW0~-C#EfPUEkfC2{r2$H zm;qmFk&UVF`}-S@{I?CaLhu#%??A{rbt%SrB%IP-VgDXI3al4>wEqmD{vD4=r)GV@ z+`3{Zw$u==t0wV^6WiI|nh%hDAJ2~16r-^`j{oYT#3J&oNiV4j&pBwrb0T-bA*={4 z3rk6*=N*a(HsgTDyL6UT4 zD1Ou;{^ztYuRfE`n%d7{y(2`9XB#t~b9OB}25p2__&pY#ThE>xIw5kq4x;DA|L>jr z|Nll*`V07P{X#+-N!Ny5L}>PKY3=XcaGALcSt_$=&@D?i=?751-;JeneZsIHQca34 zI0g4H?!3B9A9nE8F45!gG|Tb1izbPN{Lfw=7B%J)>2G2D_zEX}e5{Byt{x4StrDq( zFQs^QFEom^=QUrBFr9)J*7wm_e#S7IA3N|49`eh=&wrG~#ze6a6?62&0rVWuLi~0G zeh#I-IXnO63l;hmPSC{4fFV-+j7D%Bau|n?eWbzXMW1+cRq9tWRLVz3EWEowO7s{4 z);Ed2dmG9Q_x=poHH7k__5@{ey+-5aY3r=+0ZHQ`S}q&b^rQk6!HCy z_bA{K`rVv)5i8$CN(nDk!_Bi8*+C;{NRG%8w=JW7rN5+$-6mqOMK>ua=N8EQ39rj5 zWZ6aEA-j>mazmy=x#T4p{prkNn#?AH>;QhE_X&Q&S;QJw*~8_^dQuU8aX*egsj?$~ zKUtRKfX~F#e72JqPR$` zZWAOWU;hNAI~B(sJf~qPhH!E>rG5o=(iNLHEIqhLTEAb^@invOUlw|^+@BGU9j#<1 zZ>B)CO&J>7*0I=K&&lx84t~-oiJw&W5_}$TsryW-O`lNQ**r9n%lL-}vzW>0FKjR~ z;pb1c;nT>e0eotT`GkHCj(=pGNFO2xF(Z=jdzz@h$7qPRhbD%cu2b%coV{yICQS*xt z{M6GO{M7w(f-ecK=JBLDK$YU=KY?HlhQh@fb8;9G;*+H=QXB47PFU~t5<=#P8FIwTEyZl)5!=Q_~|ol{Pamx z!8aJL4uPb)Fpc8;FG8iqbpCna7iJx+!$yT&^Wt z4EWdQKbYM{Q#O8n94}}may-9hfr5p8vo^ByNEKGue-C=pwMLJR!b7N#PfIbM(67{X zJi>F&NSlv|8DgW0ao)R#Mt}GUrzNAPUqFU*uWNU#w9}W;^C}^qHyFx~2ePYuJ3=X$F_#g?*d+e27YZb$SutR?<>G=Q(ELcTRZzZX5y5Ygw3li*QPTFC8tCpC4|UxI>}I_lWYSP}^|&syI(~ra`a+hB1Zoj7fae=) z@qF7Cg3lAKJGPUWYg1ag$_nZ!J^9c1m8|QhZfxp@T7Ko!e186DCdedJdSExYsZn3&l$k6jnAL0Qz! zh0cZRsV}59>N2hE-xC^=3IDabH*>OAX2B~b@vF)2cz#+H*w0q*ntYY*F*?fLeJV!x z54Gt2&iB7H_=k=2H)r7AcSyL<_;s!xqExe_jBBEwWcRL#@7daw-57NqO(%v!ZC5c{SFw{!dNt)23QPHgvaNzI z53curl3Ms{T5J6U8ddZ7?*}E!b#^VA)v67@HnoUfSUCagnGw7u4rTj#d$9L&x}*Ei zzUY2Xth~ZAsF^~(2%%qPSumnDjF)!yzXz`)CvmO4IZeDfvng!!gP zyBFMn_r1-~ZW_oQ7K(W!dYjoTuUcp~)`xn><7|DN7Mbkt%`fiiz%L40#bKp5gKCeG zTGnWat$PQ}#Hnc1_&Q_PQrVnaYW%uqJAQGpKG@k=BB%N)+aIgV>V6iX`+N&@4}RGI zK0U>JLceNVO+>eOFYS6(gYGfwaQ)L6ns8g>Ll^i_!2W5{^OVyFt9&8t)#wJFtUBoA zH)qAq+d|eTh23$=gZ8EiP(Lheuvi~5)ePX5mXG9@QVRv&3b<)nk=o<-6npj|wA{X< zQOXsO$h3&fkG{_f4S(=Uy@34K`zd*Sd6C|SksJ9dZ8tvG1pEM+O( znv&^B2Y$K3bbh(7@L8@(5bx3^q~0NnVh1ra4ZjAZf;Fs%>>gWcYr${iI`Yc~FTh5R zhu6?;EPH(m_PI#p{+$uA<0F614MjGNp+deWq2Gt?Hi)^oTFQ(X3?GATxHCq~i*NQs zglh~^{V}R?a?4k4vx|4Q7(`hVARhds_IxYDX z(K6{u8(ZP$aDm&1a8eh2;$vHuK->N)8V`46Jxc@F3bon%X81vV`O|waS#xpsTCrn| zFS4(zL=9l*4Pn#yHGuDLyyxHNXOz&d{$T`Shjf;9@;ww&`2yN^JE3viD%K}#A`5M@mfs4z#;-j11!g7kaYWoQcUCa_-bd`s z?n&@+YCt}fl956_;f7MTFcUyhPZwOoX#NTi4|GvNf(Z>1f z&-?ctju9IFSRH}2AKFNVpM;{<=mb28L|5^j-G@ zW-|}752pFR$_K3U<0$Bz`GuyUcfn@gJ!CG~^6TF9{Q4r{D-RcE(1T~B{?meDy5~dp z%r+<=oW};Q)?#6gPV+mtefae`d*OcenAo?U+1dSFsF8&?2i(&|?W61|%NM>rrEaqzAG85-UfBRXQ-yr7jT*@tDcK|LXPlIy zE%^Ri#M99}G|gAUg8dW7Kde&vSQ3EfsavGuvl8L&J`GlVXR&YYj=+dw_G)QkQBP*kUQ*+M%^)}b2D#GX2Jo3F<_l>gSF*N8{E8jYvAxUC=f*5Nb9bd_ zUwz;_)`B8;WyI+KOD zJ->0-j^C)v6S346aChrP8jHdydY>!wGUh{d;x#r-%r=a6UBvG-Yr=1;h&32vCeG9? ztRQR%HCZEOtCbyqbjh*-eC7)I#A`<0*sC)Vlsu)}9$Dy{avRT^ub}A}qv1T)mHd4| zrLQPK%;st-@Az;86q~?C^v`J|D*{|ASf!b$6;zumdIIRMtzji(FUSEf^36XTuXg^KUK_g&nbhuji`-pXV0!(7CtTAb&zJrA@%9n0KUH( z|NH!m6Z$DfJ0P)qG+B@S^O~UT zm{HWE{*nMQWi^HS(A>5PI>l?)cFPrHQ8ky})^+5!`+OGpD$n7*lat1$`xI^b83v)s zVy@C2HhtkPmSFG9AB=3tZ%0?aU8MkC*1@dsO04LGG!BxpsO8qX*#JH(#e70Pm8?!k zT((a--S!gvKYv8|p;0trPYj$7Y$CtkY0__@>)LTu(%JpS7$7@@b_@5BO3^LRQ=*8y zZ(EP%*_qJw-p96A4kycQ&-m>Jhxi?1VFSbugZs4-(zJX?QMFxQXt@OHdk3?b*)=Sw z*B<_`+Pp44wXgXgapcs_XB0KS$A`Qn9sst;Nr@!M7D%ymx$ zoUX^~cte^wbTORIhm&8emAp~>VXXajNjg8U69Tn5pu>j6q;}L!%y>y;AJ#a)Nc57? z&2G&yvfGnoNIAc=={dhsst$*QD!A9RCQa`Iin=}sh9@nd;W~}Yd91?LExExTmR;jT z-D2T(eG)O=s7U|)vIU_9_Gnyo&m>2U5E^gPqNvsBXkM2B&A>ry(a(h})wm6RJYI|6y>A4!q-+jH2-?JCB zof|a4CW~I(XOC0VnD;P>o-5{lnX;u{G})%mB3^8>oZl1orrW|pqQ~I~cK@IT>3kQt zuvX7REM8cb3h$8C3i%R+ep(BHko?qJx->Zq0}3@z+j0)g(JF;Y^F`!$w7p!#&;$v- zqopf4?J&5VgQyv-B;ENg;Ja+uPv2y;m=XXzKM%I+<~p+4k<9PyS;gfi^n3g`lnkam z7xhp_sZqKEOcumK-=GWIGhhg{bb8GnwDI8&g3pS&j(cDgPNd~1zCV?jXwiQOnnt{2 zE6=*I9W5gG(-G19q4HX|brg2@gD!59Dz*Za7vt4;Vc!??T zhlN&fGfWqKxbLth8E(}4$A^ z1oAWO*wZ&H$vFEIWQOAXa<@+d`2Ob1{d<2V3;py0W3j;`Sh{gDAA^^<;OmhZnm;}d zE@2krm-Je$S)`0)i%HV$^_wy5W06?fH)Jxj2Y7E$Q|sFoX3F(2u&-qM5)M!+vzPqQ z;B@|IoABdgbO%kWC#{S$ip)2Kss0Y=*tKJ8613TVadtjSxXK>~K7s4&E07;HV$bxy zlS#A{@LUH-Ti*b__6qsd3H|g}Z^4ELC+SvbCk%1AhVR=9X@P++TsCP4{qp5nKZYSW zvzt`p-x$M>41l!Aj?DaOz?mk$jjjbR60_vNL%5A$MSySf$?K`sJSr8eKmY_dpZ-Y@L?@xnu> zaDR4C%qR3SI2wr!pLR-joYX{*;m7zHpGpfZbc9Q`Bl)H7kZaps!#bB5>7M2bj1V*6 zyxw&o3#l1+`y^7`-wx*L%V1D;gY8$_MXk(C9CJ)6s_KoQ+ehJd=qg$`cOqP_?I6GHsdAlw0Ia*PRJwoJ6(c(wgm=&f zvg$Gk+;lvtJyeBx#AX<}-)8&I{v>O|$-H=ZUtU}=6At@^f~ww8Q|;9hnf3@~S2Tn# z=N*eI4q!*uEalJ7J>*Z;uZC;p7ctN24txG%viN@o13g6l=Wh*pXW1*}6B-*Cm1AS! z4C&t1Zx}XktgMk+6)m!x2bZ!zuKUQJM8067MsFh|1EeJmr~Qte<*VOU6>DgfM#BqEUNe`J3e+J zf3c`Jf7A?^! z3|Fs^DRsL>i=M~B<+~U8opX^l%S^}mM_Z)FUY=qWm;-t*$tD}U#qjuQMw%TxVG))E z!-^*CU?+33zPge>DNo{0JG#N)5a7|>mzwr_F8D6P{B;*JyQa;ei<`1MpEta$Q!X#j zJ^6HXF~^pg&bJo(QwbLHm7&-7GmCkAk)3ue7c~%hyrduouEFAt9QJ^{ z6m_7sO6K5)&x?9b;pJ9%2L1I#{`>peDD*SQT8~uao6_SO0T?l5vaCtFbF^g00Jye4 zA>NS#NwtRv$oxWW)$YUNPA_U2lLgD=DQF(um>o(@BbyjiUgF(| zmqd#@K%$MTX-;{J0JH6X{P zi<*ruV($1ZirlXT%Y+-yA2gV)edWY1xDMy9aE+Hb6v7o^Ca&8GR&KD6?0!814=993 zZFK|q92D}U2>r~>G?04ps8r&uhLINvWh&PDY3Y3vxDLBQ{%tqPn@_jI#-E3!=YE8- zlNXB~uNlW=dtEyYPw4ya!ZP!EIwj(S5becLSp9Z(S3XhYu4dCmhm`~_u z5ikvDUGGSxD&-gzykDl;60|JI6s~h;lYb9;xzX0PNLg(ml{KG)am~jFJA5+PcO3wa zxI}7(1+c2tfYE}D?C^;h)cV+1UfSm;FO3@xhm*$O_BTjdRYs8)n!;*dAq+;$UxRIiejGd^N*ciDsE{vJ=w}&`jI^YD>3KnO zj5huyQ?pE_$ z(S;lA$aG_}wd}%6zkKG;U4;#PdJOpRV$yE^m?G~Mprx}J3`!$eqOl1pT-uITxL)Tk zyq(}uOOQ88Vy~~fq0Z)M@F+-y$G}Ss;QM=r{QLV$75Z77TZXjy2&pVQ8Kcjhl&M=B zpcO5C!FA_#@{hYCH_;f0)c9Lc`OaL7pDgOg9otdYiBa$vHJA`Hi9v7`=v*sX1%U%->|{6&2wT#Di# zRlBk`IYHF5V;wwFroh9t>3@9xqmARNa1GLg#x1|uV$*<@(ko$OjhXODreP6HE1n5g z_?boIpL zMUP5P(oX3}QO(QHs;B_X#~QG8BeK{7(U10x$qxR~Hw7;1*FZYIiB*X@Y^R~~;UPN@ z%J*pipQ}PX5lxWWOxuUex@V-A1e_)ekBk8T$ zb4=`?j7ho4nfJh&4t=rf6B|^*YL7y1K>~qz$BEkPghfv zeS26BorvZy(%AZ?eb{5Kz5LD5_59_BB)BZ-2PtzXdz)N9E(>?Sqq#RIp&|JyZi@MY zeyw+hV)N8%Qf2CNjO%+@*0fa~g&GWoo2Xk1aMqApydiAbdR?l%e+d&mTtLv)I&wD_ zZ^Tcl8zw6Wx&RmFGDu5vSj`q!VyAb5&RK)H{=MH7#j2QMKA~S*D}QWhSt`|Z7?1HWn`An6 zV<`0LO}M!^Qb1~wyyb|i*qo6ry`SfX$?XF$Go~N$h;E?Moyc_k8`wluqs6g1>^S+7 zo!LVEYPRT?v+JPflN$@{d`dbU?1Z2A4{WN$IW%14hF9%lFKtiqs(E|GxZkhBpDCJr zjgMyUwuO*KNi)#;`5>iT4d5e%d|QNmcEi1}Wl@>*?$a?$Xs0LB?O01Iy$#?N(1ijX zE|#}SZH6s2`=k#&&SG+YF6PAflI*nbL2XqcvsW&#`F0B}zSXniuU*M5HHw!vQ|IN9 zuyJlC3x7-@>Gb_ZQHOq`_4Ge5ejLcsG_JCW*=qc)YG+=tLI&r0FG#)4vf9nU7#1_G zX!=O7qWlK%c_`)+`n5}WgDrP%OYhHnV8Vq`Su=;Bv@$0XZd002Kl3=b^}~VKvi*`& zZ!!~82EW4mv=$_NOa`s=CyOpU(0Wo5Oh||2#wSrb8*N^mS#PQ|mXZGGE5uCfkdV)oE}p60t>x5$wI_izOM$Kwj6ucKr3>E83r2 zAz!-Cul*x8q}y$kKE!^-#1SeoJ=guT%I+)NLh`6z&?0&3<{OdT@|EHJ-YFVIU?t{C=9YrwWPDoouaLt!gl6y zw78?sHoJahH756XwN)m6ou>)sLv@f^1hYCZ55UXiEy(;V*u0Ak;Dcg5p8t^svFL{^tn zVT)rhIaS6^Jkz4~{Ri-hXT|)rrVSkK&46sU7wH^dM$r?l!1ld9OnOzYEt0ZmF{sX~ z_lP@iKrEbNMGfz-8unrE7V0tLG}tFkFz<8!@%@iBj!fYiY!w>Y4}6OBq8jOQ`%jn@ z)k|jJ)1Fpah+LCH=cs?n$?`Vq)UnmnR{FMaJf`Y!toXQ^dM4R`+T>6x?Uu0JX8@BQ z1uQT06}A8F!C%iS<*&CK7j?{iA&cxrI*)ZJTI5Z(3AThuK}VL}-I#rR(S_G^9>m|& zw1#s~9z4qqvyUBg$Y*sf*iA2p;-vr9;2$=Qr(!;#aiAF_TI+_ z8}*EikYN=wi7L2dP0kBbIV}g&lmD{PVu~|MGBl-|Agnh=B)mB zI`uBz3>JC}?q^gQ!1p&EqJU56*VW`Owq943exw^?if4q(Xi_5z+jkjm^{O;ra<;tv zuyNQHaY_2q$`{kJMqu@gBjoSU7wqyPYW;j5+LU?2H2WMoHJZrYb_TEPD(shjjp6V_ z%$#XDfpo>07E?F^ZA;5x)^!KlZo8lT=I{Bt98X@ADe}@9yNG^*dF)e=68UNE2OHi2 z?(tt5z~`lqZ@bXXVOS-$nUzStX6Itc?Qog#oEfynB?Ru8$~2%{N!}rS0=74*mN!~f zg6S@)STlPG^&1~1_K_{MvA%$|KI$;7&1R>*7m|Hl8m~M*msggi!J%XrJe?1a?!Yw^ z>vjfqgWJPw??INKQbCPgB=K6&KmRSwhf`?^JcAFj&sri!78}4^^x-~UWC|&~L%J*G z6Z&=Aavs~J-k1J(&q2_Lo3a+6jcCo47`R&{QsCq=dB<0Q*uLPWTxn`5rk}ct2(z6u zAX(%>uh~s)$BF!v{pm34pvg`r?x#+d^LdqjCtfvm1{_M2L=Plu(w*Z-v4?zMck>&} zTQy=C#p={}_XA#g(1^diF6s+Ui@y8*o!RG2uc-fmbzu5|aCZ%90ACMKMN$1-PZ z%X=e?wb9hyWE3f(_>KdPKf@j2I(p|fW*4phuJFnp|-;l<3?20Aj z*{}Hfwu5=~;OlToy#mj!PV9@#eF{9f1@7+*;NG;f0es$y`GkJXZG5m@{i9rIu@R=u z=^!&rkE8JFB)IpCp@H+2+evZHI$bX+NJA{5NLG{=^P*>h~q8_IHAemWK zBtsj zQ`f*p{Ot!PUac&L!^{2fd^Cb|&pT6`=}olnU~$eQtn$Jr(l_{amx$uzh4~+~Gik((y0AtEJ1k z`DS6q$pX2m@jc9R`+@k(OEhXmx28*YO`~DFMymu4 z6;Y6E$C7SMIK_)PgAPsOVHxz3?S3MW)~P~X_cfotTjD7CEF6U_>m>W;w}?ibv4{J( zo^Tu65Ien>Vm_fUqm{^TSt3`lx5o5{3YldUqo_`U;GQy@2FHiU9oK1KXUBDNHT4M0 z%zlZ)8PPQ6rN|XNx0pKBPeZ%fSukG_#?C#zN!_ZwdCh9EH)BMv?$;HNe1B0hB_oQD zt4D_=9bsAWhwa&&LfUb&`G?7o{M{ch-?eTqWO19>x2OIz`uky#g4`|=(EX;Ef*!eLLCk-sE@BgZ7b$YatL6#+j0rWfUQG!J_t0^`SXiBx z*gjrNdfj^Sk8*wfUa1O>hc-ag`#t;qC5}Wpd$=o!IMN%f2JrP&$hTYQ2Los95UJW~ zUr%9%YMRWtlaa{rz6AF>2{g3BXSwSlAM9G#O|DTAjM>6Jwc-9^nj9tW=@FC3;fMh` zG&%Sq4& zz$gAbBpHrz5@cfL^^cXYG->;DaethF>$$(V8j9Y@ev0{oezIXNv14GmT>TBljFobk zO^+`WGn3%{axo3fEtb1o*2At>Gv%7MzGAkBSEcOxPC;jL;7+;JP0S4MFk}`i`rlyr z*Ef*M;!Iu}Hk#M2Xd`CE-hfnWN6px2N=*F$dy&u6a%(cnytaT0MQ@6FRYF`2ScyF}QInVZo=abQa2fThoKVG*m1CD-QfH!gM=c>Cj zO?xTaGQPld*82wV1t{hd`bqDeV#o8*a?LBEW8K^iGTWuz6ua#=n5r)gt3D#92{zb$ zVxGL|vC)__^(QuuGp89=li~JLnVd&Bp`%(ySe!^^7j};$x0${8`z40_{d7spG_HZ% zVh=UztwBiz2VnpC5n3(PX9qBvTCB+B_2t#P?t?ZQyV?Q;FWJxUttnXa7jqN!O0K=s z8^G63A>Ur1pO;%}?6f&A*E%73sa8#vwb^)+*2-^#8F!)K>%Pi8awcJqb$7Y;K888P zOOf9F0L}6dd6rKbk;~c~bR6yki?@B*MV)cv9umyofAr$-U&O$n_O+-jSwzkJ(dI#6m!o#cZ`|Gcm zPw3Zu)qCumI91+s-xtgpc~92%STe0Gy9w5I0*zoUa;PrBp2#b5oh>Ud*Ec?OwVCGby&eEEmc6X^CS4OrEK{VLi?vlB|-=DQ9qe}4YQ_dnV=0~D^oKA~}s zTb|gtXN+8X(^bs6GhJqPKc3>2-2!v2pb^De&Ohth^N$0R(CyJ@V9X2l+sTLK=Kg`3y@+3xG~^BmRLmzd_AxWW&dMaYPMj8I zOI>B{KAoia=1Jn6ae+q8TPpX=RL0%`dGclv{V?zUvG!h3Q8rDq@C;_fjEYKDFw4L& zL+IkE2U`$O0dp1wF$YXU34@@BSrkzb1Vy3*C8(%i0?hd}=ZyNAP(jiu|Fhn6>9E%K zU(6LZ?B4x!S6A)YrR#vnEn0zZHbd)R3Q9X`;h-^}Q7^=joj0)t+t^mZw^3TcH@OR% ze+xpst2K0RRYJ^2ntdI%8he?1VcBoGf&K}Z@N@Zh;d|*Wl%G@}ipN;}wkq&>L^ zbPrdq>52z`$AkYxE3}^R3BWoC2OVgQdf8XmdH)$8>`D~AogsYt2BP_QhCJ^lbZ}Y< zG4I}^>GK=dYtu!R6BYo5ku}24+o?jOWjM-{%n|idS$%~$_|-i_s~?Nea(D25d-yLg z+@Dzf?=emW@#mb!@Zh}hyu*qIxLnUt9B922wj$+oJtW|s+?@{{osQ`}4)IRQOL66= zt(f|41_VBrqcwK}+o_ju(6@J}_w*b)UuF-u=aKN;j0@k}{J~d&{CZdDAXdQ6@B=8r zE74t=IUY^fv4e(k~D#Y@=XfvI3p(N_5N z<*V=`bTrDx-9_Q#5!P@*7edB#Ay1F>Xvuao0^c8w|GqyD5q~awV=={W4e#uhiz_D2 z7EM#TLUfbG$kt`R%z#YpIOZ~DSU=)jCVWO;9S6+%HW5@!Nk{Xq6vSL94!+kE^%t~Y zrCS!mkWHJ_-$Lk-GPH_Xik7;6;%jv=>J;_(h(FhlqcCOaMXqJP6jzjV5oOoLKy-Wz zvX}|rVGzlk(tl${%uU|abrJdo=U~onZwPBvOL9o8eGp8g$U;1H1KCpjlcJ8i#jhM+TgN{yv?As`Pfk&oRUwT$ zpgKXGR^CPUN2Q=1-&D2uvWP$G#K)AF2fT~T4qVymjcE4kGHeGMWJ&M9$SMWI7tZ8qJO*NnxP1OsH-)U-)@^Cdxa~`QknlB>j>h>@3CK6PBa$ zrA{O8O;eAL_#3@m4^yt~<6UJvab?7PQEnIx+aKv6%k~A&z$`vuiXUc<@Z;LJ5&iHZ z=68*PaH$Jg#n%9Tvl2~n|3Upv3s_m7X5i5KxbP$So$$l!65-1s&liOD*MGvEXzJsn z@63dEXL%jx!Jz7QLiG&t2G*yVWSuSw;ysYC1+coj1g(SwRF)3>58wY7<4jk(2HC{% zn1=%~wM9GL%|wbTUw;z+%p=_q+yvQ)t}sisijT}YgPF;rcy}xEdyFr`!u~!GUPIm~ z5mhkst0|iPsz8ITW~^*vDhwNECj4w^Df~FQpVr_bc{SKU`y*E%ZhQ=BkoC}HUpUJP zxD2L8i-qcAZ-if~sV4HiGwI}>fW+xIgkK(wRwe=})BfKY{N;{xSC5Z49ycHbQ*HZj zZ5?~`8EPOZ{LVp);X7pI#W3sr7w+2b1ZLJ=<2}s!qF=2u9vgxX@y!XX7KMR*RW8aP z7Y%IpvNG>J;JE&z@N;ge@KZk)&3}=v&u+>^ZodP2^~tlVwgydV53syDm%+?GL-^h4 zwD9XSaeU_z3eBuR;_?_GZVW-IcI3UVA>cob|AKFZT6{Ug-}qHgn7Z^k@80P(`s`aK zDi4l@n6iJ6-I)VkDV5x9o(CQpeUIwR$Yl$|>j}Uv7a^W>GFz5GbJ~jw2Yj`o&(@w$w&%SuN ztPAy_aJ1@Z2TqlQZ-_k_T%F3woF|&kUcXNbatNhWtio8-9dO-Wmfw0fJ6fLYo z?CWmJ@?DRE)$vrJX6{d+dfH?(-&~Kj+rn8x)OCpJ=#7@Sk5H-Cm^{ubwfGJbe^buU z8_Du8*ZJ}oee3UvY~Ce`NzxHo`oP@sPJA4F6IpxKasAFyFyNRrp8e_%QM-DfWlcFa zR}4q9P{Q|FkCjy^z~!ZlP&K$n_;vL=;TwbY+Pk3L*HTDyHARcnow0A8gyow)0Gr(t zg_k(%FN-tISig4Hn0dVi7|w3~;4ZNsrte+jG)nuV5cDq;AenP_(69p#@^ zvvSSu;HK;dKxlKJR?|xO-R?S? zFP(B|jUUBJK@i?H17J#3i1fV8xUFoNdUnpF)(!+{4_x$bHhwOvoB zx@#y@EtV6$hiE_iA841E4*LxPQPH^y`%V1C^7gL+VL^AHcFHT^_bjRhc(z5`Axc&^ zXEto~u0+eF=TLF&M3U- zSNNnKg_x~6!Ht>)VqoqKycqEhY-AJA^3+8bnMYom=H1ZHDUy{BTm++QTM5;D{e`OI z)o5O=kM>@RpxrtK2fE5oFZ?igWDSDFFX@PJ{02k83Zteg+tHtDdSu)`_e|< zOB#f$q}h1+lre1TOg_~a3&ACp?zs6$Xy|3i%B`-$*abR5wJ*hR%}8@qJqzuFYoMK% zDI|BI8OZS^*sp35J95k!hB)69YJa&2HJWYF+|dDT+ihbt9t!dcrWoDn1}fr;8o}{A z_4tTm4=)c)?@+)EuWUg7C|%Jmh(laM4uVr>SY&R&r{?=$PUkngSKSp{<<<V)vSV{@T;#}mT$4()TRpktKDWypYFwboesc&9*;%- z;~>PZypG^;1D3ScNM)^kcDdT6%c>3J$GRGYAxQo=m7@Im?qj=G=~IP zUxXzeU`c}!pK)J~IWI48lgiZ?WOf$sl(d7bqbL{X*%?MlDE7quXjod$%H3RHvQp2j<8EF4{CA7Ud0@AwGqH@201A32RInT#~v)NanUe8vjwWl*oI~U>5O7^qk zV%Q$|4K1Y|P+>Ko5%~VpBmaKJ77%}Pjy}iqgLd4wAQ%Joe-j;+--iV9CxRdmyuY;P z9`ugRHLm7;zSd!o{|mg=as}<9@n|`EJdD2iFUq}NqT$1MR_?kKreqWezu%D`u6qLE z+m7}PAE52Q6OgWxi^^vgalnFpEW2(CjF7(+>S;E2?PgOnZ(C0~<1AJgVM6)j1E~Dc z9~F9Kjlj29ExtnHZ(h5lm|pgSo8->IfY*D(Vfi|+FVPtxsuY$!eaAiHM_}&k?Y!^j zQy5gT5Fd>B4BMWRqU8`17_(o2@G28rW>5Mmd@vdde!moyf0lXH2$PiHZ>*%W+~v;v|N z$DyV99GYjf6Xn-A8c7ta+@8Vo$Z0~&Vr}8~qg{mWJvu19L)&pZA=9WST28o!1HMPG zthOt`jeQpCKlKpmboZiJ^&x}>hU}|tJBT$Li^^*+(Be~L@*Li3@f{`p794lOj269l zU+RSp^z1J>vm21qjAFQhePMZCJ3iaX9dln!=KVivVzA>OeDb{#w!7D(WiL$_XPt`j zx(YPvFpZTn^6&mA3N=~ULX9><^O_duFv^Mgs=mV^J-Sb}M&Lk&j2&uH0;2^TfyN^U zbsh$2_W23IcpLUPJPUSBT!qRKZ?w2GxDosTKYLzdPR>ciH;fh*gwjF0_btgV62u;jf^ci;w^z3GQw z_nUnxItIHpenMq#C|aB(CENc!KmW%(&N8)YaEv%!Jf|mSh>v)G(l!R(Zz_%`y8-)0 zbwxOR5mqiZz~>DfjfW@O@`3MXVDQD+_%dNT?6^7;Et`?%?06blj2nPP12?jA{Zrtv zZKP03_DD7BsBfjl2puAqf#$6o$d*zMr_>(@9+9&23u9rtmA253tuNHQK16fQwjm6T zU>{yTfjy_q=q%Pji-RHmt-)XN9Lv??BaWAxyoni8w(|jdd~j9AcA`uB6xjcv6T-FY z;A7>==STbF;ppjn(7SmU(()|6uHFDKL9b|@njcJ9whk?V%h1TmgO#^!1D@C7g<6l< zLQQc2;nPKj1FJ#vpdVzvrdd0d#W?WaI+nJ_1SSqv3Jo7`3-!Ho(d?EcLeH11LgNd> zeZ7Lp9W<+F^SMUgTcH*oDVO|=?__vc_@FEg}AX@f>Xp0l!Fy5J=V5o&ku6l%T~5x$n_ zP;vw`{d6IRW{O!YtinP4+OSmjy)aoX0VP^tLjBD9Xm%kKp>+%Pu0s!q*B^k&wWMM3 z_iY5emFn>kf6Er!#f*(Qe9(3)TopK8bW19N`c0wM_yL`REsEe(GWzAGP=> zlIP3M>SM+MeLi^08(ej0hdAofYe?Qfy=m3kz;D?vzW96)9#NEW*_-zmax4x%b^Q#n zb7*GzwIwiV@prWNz737WX0Wo;Rxrout5Dahn@~HxGvUibhbmvt>~<0k&!ODkiDD9UbTyZeG5jQa>*dHa68=ye1ACpdyG>={H^Q} zjTy%~aMO+FaMk12;usq}IH*It#VwkEf4{BVd!Q>Gnfslay?KBkUpwRHfHx3Zmx#(U z$6<0S5f$C2H*TskD_G4y za4)K)8A2U|hIY--Eb|$%dpp>R=Eab>b_*&!Y0XGAsGdJRwfIgDe?H4(m~pk3%c8Dh zkfwt;cI`|!n0ORzwdR2T(=fg?IvkJe4&>%mmaM<9>(B`lvs{~C7OtGHQYD-5zaDvrC81t}&< zv^A`TfEahatVSD;Tr}l!+Ebx}Mq#DX9@wp0jmq@*|;j0pXe>r z#nAqINcpwu^*GFV4zvks33+!PqP15g4jw$8B|a0Pk=Skwv-|!J;e80`jBNk$iCleYCJ2 z9;XI}%_i-sLm=d5EGHkh(>QplJKMMZBzS2CqvR;v5vl*8*_IE;vhvu&nuBoQ>;qKV ztI$I8&-+2$`4XreAMqF9{~9x!dUJVL6$Y)pCQe-G4yl7FH*ISMt6ItV%1dsT*SiB( zyi3N==}WMh`Z@Q=_R~Ez7pA&t(~P-OXtbyoE3LT*3!nBC>OQ^_>iQoid~P@_tP`|p zHwFsATA_7GD;ylD%@SNu{NbdSoZsI!D2((n#(r|A=`mx?K5w3(eNs zi8Y)5fjxN?kFC#wsSimrd~7)yEuKsD*6XlXd%w8B+@*(6^0pQwP2^}6l89_)5xdtq1`giaj7ke#lz;q_XH>^=ka~Q? zaS-*RW*T{MMX(Bk?)DX@bhm*t>wKDJw*i9IJm-FK_c71MmRnY&VCeeGSTD(jIOR%I zhQ+|NSuv=%^O*4c%SyMF!;=1Mg?d&d)KTnX{__A1JGzoQ4qw7ine8Fn*6%&8KVY!%TTE>;D zXf9RtCvob+B1kK_fwr@pA=ufO2Q=@5d2zwq>O%#FCblAfpc077qi-}o6Q)(1B+vO; z!nc)`j^72|#Glfd-(JC#qxzZ1ZeaeQ`I>vBZV;A`uYoV#ZdA7TgHY^%>6{US|pv3M1n$4*q z?MMrDlV5|h`yHvyaRcS&?l%Hos9Jm_#9!#HhnVRQ#jX6VW3Y9a=-#yg(yvz0tjsqM zayN*tx<3W;UWRa+e_vy0d9w1*v76;uY~kV zTT$7)3CfTEsk5p3{#5Gm5q~O&0hsCfi(C7eVDR{T;*3R`AY(Ln;YA&V(2<9DF!#j# zrV7r!?7`3n55y)PJRrU$`2>3|0QU(tsI^@Cyglf6Ry=~F`8hcMFnokGW6 zhoRNZFeti4{H6M$se2{c8GawUUFuNkIvgdl=c3ufH^>%!WmiKcKt`b#Dmx!VdCv7l z;0sfWk0L>?`nDP~C-&wxD`PQuX{tE${2<7<7KXMv10ghX6c0I+j`_VzIec4=p&xa{ zW|X3fUravMQ;&iBIf}X5a?r>YHhz`IkQEC|rkDquauX>^SNt zlA!4-cNSx}7nT-%L+Q*8DDmx2I-PmsMcSHOPHqL6duTtjt3i2cmqy@QtsWoo7Z(2l zGu?GLThWW&`6Z&K?or6J?~b+ydV#8Wdmg%>3+9WHxh?f)gw{?Gn|nQg_$$p9R52O9Vb17R;}m4$u%F)=6wU2#^kXb8gpTJ z_j;5ry@Qf9&(X}eDQWNSvWqvD!yzB)b8LMW<@*d8fiGMwzB9z%>fyu4cJBj+W#=$B z@tru!R}V6ew4hna2S7Eso~!JZV*Zrv3D-$8k7WAR)s}%-hRtm#)I#LL<@Zh6fxn{6YRx zpFownovVJn!Tgmv9IFaY)%}>*@}({$1W=4RTn}cvC4B4UXyn+OodaF)Gkz#E^m!)K zJItbYISecoM(k(71+20GzSPrtu>si^bdyw6w z7b+?5DBrsIKmPv57-x;zH8@Kghab?x%taPl@OGd)%|da`zz8_BmHem5Yapyu5f95; zj`iatZ4+iL$>O-g2!kJ%i*q9hU&C>q3wrnr2X5#!>??|{BkEgRAVKoh8+{zzB&c_cD5l+2?vi}2T@se z4UKwavorA@VbzeuLc`*2Lj7u2>dm!7$6x!QMgN;{W@R?A$WWBE?8r8Cw}b%00F;&_ zqU0*&TJ_1(Ve~~-a;E`u|D{=y^@#FShK=Cwk5}p6_a}A0^0nihVW#&uK4f8Q3~9>6 zg^9+Ht+y6!e=%4+@*Iy?y%6*7&EWRUx}wT0LTqm`5%yh?p;A!_9y6U$dFvG#X_m4x z{ck}~AKIS*DMJ0mXVg2+(5WLp^P5fKtT}0z_xhu(vjf}MeJBLBEk^0ZCMdbv63w(p zzdia2E1okC4zKkle6A?>Gj9aG_3H5ve~}uln7KHR5{lXw()P8usG%0J7aT)DLmO6a zna|f)kHP#mk=&t0DXJz~iyh{UhJCg7P-%VyJYqdj`J@C5>y_+ut}g`D7YGdzmO_2Z zb~Jw=L8tyQXzmjMXJ2namU9JVIz!lo-W?(EEuFD9N1)`137U1J{)sWM>{P2EaHMM| z`u>`te8t;F;M<@UUn%hynROg97nJa!^9Nx_m)+tL_vw(GLq3t3KCt@A9=_(YJ?4Kq z!-usFN7eM3V#oA&NHqR}N?CL8D8GivcV1}txhFeqUIxMCdP2j-GRhw=B=3za=rm+1 zG}m^7b2Mj&omq&oUfpTV$aYwj9fQ*Q{wR4h0L@zert_r}J8|3uj_kHa<)8ZHvbK%D zw^2Pl;&0s)Bg~wu#qH-gVMxyzqIaXypBgsam0dV%ehkrJygxj6}3!1LZW*CDhFHx z&-QeFR<%XLt9h)%SP7w>e1wMBcS3#gdNjYLiB3zqLbEX*aQ=idvS&dk>pzdJ^Xm%1 zO*~NgDgY%P-=eH;KiwU*>^RmyUI@hiOcrP|9E$~Q&T!{WKT)-yQtYyfYLScPp|bx1@HC`1MtvtV zJlU2N$5=z?B&xCP@fYe3Ql9bRPjrgx0!=?AK`A3o^^cDUUn+}?^M&9Iv_Id`8{=~v z^#Tk=HZ7GMYf}q(PZ%m&v_|>7S^wetA7h*?YS*BgI9@-)1~bQR<&Lw{X$_3U70umseFX?VN@+C6T4NdBYaO#+4lo@_9u_D=Eu-*rye^MNcb*f630}-I6#`?GbQMh zp9oERYd~3NnvW|rMw#(8wx+TMLgol4{bYcWZ;Me@k%4SZe^zkv8{`KLL#1Xt;hWe9 zeB0FGyFmPHIC>p3hZ%9_Srzn+juL&70wHHZdlc;BA^g}@zFxiw3%cp^kv(^yYH6C- zo%uncFTEf8_6AR7N3}Kf9u&QUhhLwjf(j$np=Ihy2UWP}x2h<#QUNr;1jOkNDf@)gCiZ ziw~dG5<~R-MgJz%kaLQ>@Lfkj_=g0({(Tx2^ptTIy&zOAKOy!A4uQngbocie4W7de zqopQ&qszLmlXt^G<@ky4Q4Fwe1e%}HL8oWI&?MUe${Lapv}T~pNXjBSY9O@#29$nX zi;^E-QTBv-@Vq;*yiK-H(Ax-=9aD(Eo{ivdyIOp7lJQL)9WYb5osaM|!4Ta{F~F-1 za;4wMOL+xE^gGTsBwWA({UGjYI1g1m8e-4W^!;t0g-VmP;5owzE!*xuL-+0M6Ig6>t684hIOl!yymv=OD>%TZDVD7$x_@;Hv{ zh~GxaIcrg#!=KKeKRFC_-`@`P_=vwvCzoU9pk;id2geYd_hMjqI^>QgkJMSCAYvu) zJMI$}^p#8Gs8f^7#x@!t9q4X!^IetG!*)6&w{YJ9Go_C<&ofMT?Ur;{3 zF)>bzT6~v?zs>V@VrH)}?lRMz@R^E115F_Jexp(;>M z)N|YdiRJXhFm4Z?scwXi^f*>$*vVI4AZ+M9p&_xmP`{IOfW=+W*{~-xDR>SSPP>st z^giL+#8$V+r2Gl-S2YbKbx%=tRg?0Jomj3TLg9EjRCc92>cT(wyE^`Ms>etCZRwJY zncC&tbw(h?IKg5tdHEeyzC>Zwd03-x<(tlMEEu$rkM2JLRYBiG{SC7qv4YmQ_d@Wz z^M>~4d^GHB!cGm&gRl&$&+K0!)YGgZ^V3o2Y$bsv6#y4kst~M(()V|lg(>!fYHBP> ze`ldoO83Ks;mATZvK-@cP)j?&jPtw^_+r)KyG;CTIeii{+lF&D_Z=A0ZJwD=Z>!M=Jl&11g({l))g&3OU4oAkHL}BMQSZnOU zw+udn1(u$CtZY20!h4EFU7AA@x)HuanB};W?gtMvsQ%1~`^#bV2KxTeyoCDoP0{>9 zGR@FMXu7*UT&i1(FpN`-x|)T?`a)QDbCfoWM`=sipQqO&izsA=J~n})S9TJ{6<5%?-5lVv<3~jG|wmo)@JAOEwA2V0gU0} zQxeYXSG1*m^RQXqXe!Tb3qtG`*rY9 z7WBI%gnfE~8clwnwBu!z71bakulH{`~##ar#x_FM6pD zX59bC$4;ri5ba~cKhuNjL%=@f|k^n!02wG;~+EcgWLov7O6D;mG<1xf#|Abdx` z%baupbxYBpU^Y9QG8Q6qLWG9=%|do-_jAUiJ8hzwNqqm~p8OA2+2lhIFeD zSFdgg1+$G&xVwpF6h!jq7ALS^xP(uH6R6rYKil zDXE2s{5L|w@c^NICFPReWTSKWLTI7i60YTwZhG1;lv%Z80cYpI>L;^NqoprOdp^TI z9$;+qNtPCV2#U;t2p{FjBN}su#H+=3jriMMUW*w;xqSTO{)8_?47ZsCg=0Ai?;|0~ zqXUmVrHKV@&G{sJhpHXF#lFjS!2U2>!nXmuex{)E>sB;~xWUfW4TUvhzX=V+w}kp7 z{i)Wm7oA@$gBEqJaQ(bLX|(B`Y+K0u+YN{C87oku^+A*xx}vO*a*$hhu++)dq3G#% z!l#Y$$Uj;lb^9|xJwD=Z$BIfGbjHovgi{mx#BsT978(0u5D4iu`#udMD_THznDu`Fe9od zpEO}H;jkU15Emfa;-}^+{^>o^gjW&mDD4#Xe`Rcc(djE?!cN>-%z8& zIh30JCVaF%w;Qqp=_lY+*AEnh8HNS3`|@cc-l8h`i#TY90uDSlP5824&hcbaUJpkDgE#D=<2YE? z{esYNf0Ix@x(~{YYH;{)ebAhL3hwxuBY4}OY-$&_^h`TglN5p)o#IhyO=oJp8{yMr z`zc;H^}GuzJAFrabYt{Je{{QlzaMT8f3Ze~Fk_Ah^$zVOd~3wDPxax%*G!sOEWoC_ z)qLm3&seZL z5>xUYfB$2Qb3pAH+$4@;uWDe%I9)zpEl+khG^A@>!uk%alt0UmBV0b(4+bMZw9h0$t=OY08THWTyon{D37O=S9^yXREv)~nECGB zD=@>x4cli!yChbLKn@IA^X-o`|q8=adxBJ=_%+R48$WfmN-ySjQ zxe1)P=7^ZM5~96Z^WA-(U_rz^?lJ8Vs*anA7M(i4!J5UWG}r_4S5aOfrVHvPeqeV@ zC9rXIBub>kLcQ@Zilg&!_yr|sb)N{2Zp}gPr~SEYIh%9C2%@CUsL}m0N+)llJCbUR zQL!v8s}jz-O+aOyr<{xe%Jochm^B zmmK7~pDe(F4g0v~%!#Nvr6nq6wuKbZmMQg{!h+uSQ5iV^^&_p=-E%8p)22x%X&x)o z_q>AgO)?x#{qa zXU!u1PCpZsxqTp2lVSi}IV^Zsic0?o)L)#<9;|YL&FTG7(uOo09XFwTKk@fF6uRAQ z3(uxe4DL4%Wm!JV^U_{eA3Yp3dM-fe-0>(oMlnw4Rko|9Eu5d$g!B$2D9>o$2z=>k z@!cW*;;t{m^rtJhhbzUXgm0roS131mj`*escJ4Ieal?0E!S3nYYwjFWo!=x{X)J=& z{ko{^sR;|?GDuftg8F06u*c(Y4Oiu4=-_AK^LC6q2Don5nTC_nW7Y5{+FBW9?_NBr##RATyt zD(>lmgfB$gSl<^ec4~pxFavgJ74y9sHdv4t!e=k2M%9IGqV?GKkS17Atn34eJV>`W zxdZB3KV{EGSHRY~ktpd(y5m|Ml;606BL;qeoX-{=f*~J$Y%Ot3DvZq;MhV13iWQZPg z5hXgL%l+~h7=|y?er6*AK^g5gN`3r0^)FXU)C|z{}WhJBom~X^l z+H)w+q#CqjEy|BHrWSrkJwD$bQ#)()<=qq(&5We_)bD34zf zjRiSMK6kkps;;GptgaB!*OF$WlLjnl_70VnrKm5>Vs8$|!FCT*lo)AKuMl~^Hf@6= zJnn;m?=|S;?AZ3wj&R|&Co1aBp}b)2 zfBgNAF;14+HMmP0Cj_>^^av9^dw4L#IJ)ANxijIqeh7*#>9F^LBTq0Hjs=Bp`8=Py zsJfXV+K%lD8CJB{+E&7nH&k0P-hq0r3Rp##^RQ!gJCyVlg}VDiXrY&hBZ5=G=y5Zs z=-m!s-bFNP-i%Gw4S~&-*Juqylt#5fSy>nItGmsj!=A#WW;0OnyBOuiJpWsRzkH+F z>hTfB`;7fCeNh`e$2pqt1&Ld2_QFljMsa>5BrFQz36I-gLGc$pKOhWMcNU65rY2;3 zBduI33-G?~NL=TmUfE3cX-^l3xkFmw!3jd$6~brZf+KdH2II-6;Nu{gV>Ig$n)TFT z6UBb8rJ^IZMMyRGLXA7D#)u$UNpTC_;S?ZyGQ)(yLJWB$Ij++ zoze(jrMRtq6S(d58O60)kl6DR-xqxw3(8&jf?(RicPmA)*$T+aqdIGoB3OFPpY#cR zP%rHu`#K~XV!Mz|OkpY1QJ=QO_^&vkPzim$yoZ0$3&9=H%xnf5zfcKV-yESBz!ar1 zbnadqfXv#NZEY6>S3)14qH-F_Pc$Y^MeZJjY^sM}~{rUhjv0 z6275$AOw=`w&RJ;2e9D!JHAjwdZP!{qTLMACWiRZx3mwIoee`p#V6ETZ_R#aHiunP zzn}z~3w3#QXt5$1N8Fwd{S(%}m+6xzPt_F79Ivpk2SwOckxemb21?_~Pusib;(j;@CE_E1M zM9Xo+Hyao0 ztH@7vXvF?Jq8=admvmKz>CIF50*B9puUg!`>oz=esH8a|32<;l4Np2sZ>Sg4Kelc% zsvcK}Lwg25Hr*YH&(5&o*?v@%1fkxDTdb~`9>g^}gc9fBLfxLJXmR*Dj_j})WDdGe zS^5rP_*66t*v3ZLPJ$hz@6@0<_0m);l-;Mf0?pjm#)L$;;dh+8RfZFP?;C+HPc6O& z#NU3uo|yLGG+*dIwN&jF;tt<+@Hj6C?W8)8I?4cdGi!8SzH!_5bGQ1N;l@u$-WeEI6}5q}2^KVsVTReX`X zA?3k8iZK&T!ZQmUv@`5R+W#Vcz+@;E{0!mVTOOe5*>ut2@jl3DAl=&IH1IVvMn$v_ z>a`66jkC=l{^l-}OrjVkvc5BAvklPB<1A#28p4ye zyJ2A)E50n&o$&dHPASXb@DG~tQhpEow`ifl^BwA5*$6F$*+Sx(FqF(&A=G)1R|;#2 zBcoIRNAEzrLwAIMUT9X)nmNCZhF!5kQKLlV7Ynp^n^ zsv!N}H`MLzkjxCi3MbR7^o z9kG?nqCAJuDKu}H!<_b>f!)`vsg^_a$l^~Zd-nisw&}6RT^rzDp%b0inY0Eb|EUh4kD=nx7_>{d35Pdt=P4R%u+U&SUy<;N@bwT! z_~$@=&%LOi`MImCDDE_Sj=JmRpxM4H9JqZ2B>}XDo#_q@e}^M4o&X-v-d37L^>XbV zXx=xGIr_AOIL${WrM@cZ*=&@3EJhoj4s7lH40vEyg^HUO8`-yVTrIxG#9zwNv6vr0CSMAmezFWl9QpAm3~OIu+oVY47X2TAAIX=XY zUh~8~Hvqn*E=RksK~UJ~1yA*Ui-k0s(EQCEwkonefwddT`TUJL7K!G5I(K~BwBk)n@ts4HG5PxY4$7AZ#?|h}u4@3I47WWpFz|R|QI7A!+Mb9Vj zw5KbvaD>49vi?EU!xC|{jT0REJQo!KBB;9DLyOY=s8c-@y3V}~8F6n=5}zm3bvi`3 z^ls=fbqkE+t7N~u3hRvU@dzp7cp<2mpwZvrZ4 zz2$j-a)@#C>+qNJ<&;`{Pl>i$A;OimdTp&csbCxGhJWVA@1jygBzLic`-aA;u#6OK zT`ocM>H;?OTs|DoScKAt2BaIeL$fBqXq~IYBDQ>jSM5Ke;sn(ibN*mchp$8}zGuW= z#_ax>>fed`vBMZ5OBVMX*=Z}G`O!m8dBfS&>v(3f1T0)!&jXJ=M%Aq?;`oCaaEiSB z6;29R9rFz>y!BBhtQqJ%S_!!(T~Km@%CPS)qB40ry4+m{)5lubw)r;@*{QoI*EeQE z$>Sk;KAkVO?$B=pz5CP9di@y|5xWRpmt8=`(Rh?+*);;+Y4!Mszsz_qTb2 zA@T+>v2cs6wDuSdsrUq?18?xmlRdC7uqj`4lJtz%TZW#4+2jPLvXfe7k z>P#E}hS&PQk&aJLQo2^CeejiLr8=Q&lWpJ;^~JVr6y+&$C^v5J!iK)z0|)QB)7fG| z_^9u;74hdakVTvT1)S?Zb5iP3VeN=ylvkd{p0|I(fYzs|N8AY|Zw?BzhdZF< z^e5=L#Tk~IF|qBmXCdjvR#EKf!W@iSK*k7qW97A@Jxm_+9T%e2`-I$1~^98G91Vv@+4^)C#t?!y@>%gzm^x(n{<#ZN&a8 zRg3Q>@s~aBC#J*>;=z`rId=Rarbv6(wrPJA`MnEpdr1qPGe*S1qOUyk?N(G3xr**r zEqdj>TDv+#a!avH@rbw)z%&OK;(It5)nSAc(;@wQzDno)mo zJX*9L%7zUpgRBX31|>H|>5bjgSJfA-wpOsU0TTGKvnMK&Nt3&4L?iH(smDkBW!KHY zl%<6{M7aV(T-u1KJvD7Lt6gzus~2#0$y=V=rZpB`Y{yme98p!+Qk>}?2IY^)x46U* zqLjy}&omo*jw%6*`y-(^;uq-{4-2(Xq$RJ6MmK$P2)eDZ?e@Ej`cuj4$@(K3cH=i> zzgSCso9`(G=!<4LG{0fiAhz~2LXY60jmp{75zsKOOh`*czM=)jh z7#`Z=6^4viC8k+Dux zypG#eY(-IQEbI=XORyv&1Gw$!Z$HN$(_c%Oruf6uQVy?Nu z22>%7{Dn|;z5~|)KUIf>#$xxBTF^=1Jo#cEoEr9pr&|vm3w$HK`f!f1wmF{}|1zyH z08cDv!^ig9-MJ8(n!b^tE0!Rne_LgX-y*7ZI|XgVWs3Vz{p23z<{W&nOoor!!d!+h zWyFH-;=G$LT$8ND0>L%iE@7}N?JHFK28$Dgf1uNFn!052T6p@;LHD_ZBBIce>ZUTU zm^Q(6X^^Vp6t&oERF!MsJlAl344j(sei(x(s`-uQi0{0Qz-={aH!LdS+iHt(%4U=P zZNF!1zulj2V&flY8D^;!7qE2_r%ky(YP(5Y5)cE=glXu$rK^Y@I+m;^a;@88 z7F-XjRGr3Vihb*t$H2SUbP8I)$@(@tuJ2aOztL9wtn-KUZ&&eL@%M7zE6XFb;A8vk zN!^Z(w=85>>KB9rd{DM!KBSu0Sp)q_k$7?{NbY@o23dyvWyHka2;0~|8Ff~OOM4r` zbxd2a$kz}q`nO@3=_guWo+i#}#xRGds=A~n;FXYibDyq9OX zH||^^!!5YiG47_a{Z=xW-wi-pgZ<+9*LHH>y8Fm7H^P+a2nXu07zTI|n_CKZ^L}AE;4_i@fhQ5pEW9Rb95U z76)Iwg-%FKj&pv)$!!-rCLLA9Pbv|`#VWWhp9Pl)zyHqQA8$}uz3bmLe$F=D`}`?3 z#%z`0slyR6t%qZ6$@%8X(y_+GI6_AQjyI9SRE3$7*4 zy{+s*C$jun5p5^c7w-bz$^$jLk>&0vBfnlp*or2~xV(#xH(@eC}j zj|iWyBg94C1E@1NUR~mu1~1k^>M?eMSgLcInm((*I|h%!ZAQAP+vJ5Jw++udOmD?? zxO#Ase1}cB7cjl?Sxo%HXF_p++p!2Mf5lqDXuiJ zht9YHb&36Occ= zRg2_Z}zw(L~`0FYPo7Tyl?Z|^o=p9o_8vW!`u7tIUI*h7WY?s@vPW7UDe`C zy-4TBAh<0)&T}2z%Yly>o7(WP{SJf#V#8A-8M&NeoTO#S-d~TXk^LXEt5qU?cnpzQ zLP6H(kurMrLWC{uuT17#>8?&=xIFa`Ne!yNxj{!*Y(6FWZwVDQVh=$l=B2u%Zf|&7 ze?U)N6OkG;lv>SpfcH5g=AxWZ^}bgijt0a+XG~M*>|Y3{0nA+*_fECc;{fUYtPQt? zw>hquQx1G(oVkD7k24i{uvs%~$muAf>a;<~n##(4WhOQ0^Z@O;z7oIVTgt4jImnu0 zA)|}ASGB-OnYtiF+}C5i)P>C=x#uJ}eSZgwc^icPoajY%rmpZ{M?f}old6okov)#1V z?={;mYmy~4j5sNyYkx+_-l@vLJM*YTvVwLek5Gjz88Ro}8M0RIlQDlqj`v2!mU}cvW(XMr5elfa|kkcrLY!3#QF}%m&kjkL{OT zs~0wSZj{j}R}gY|gpzGvnXJ#eLVMj7q&w<~%&nh{tljZ4He?&ZBCad5uFVloumCRe ze~1;v@!bFIg*x9^ztLuacrb_iqeoY(i;EXP)$$~I-i;RzGG}!=?&n#-W$Gfa zvfENPbxTK`GdW_yv=C8rY5{aEbyF9AtHJZcmC&m;*KC%bBUcmFu!>b!C%%np=(J-Z z--G)&{w~njXaJ`;?oAI2V@}{IGOlI?w`i^{4Bh_U8T=#0VK$LAd~D;K!2;{=7s{BF zwFtR!P04*6OZJq7_F?zQ;L9eNx5Ncmg(^8ed^^HI_A5c-r;8UU+%xnaA=1){IFIO$ zIw}3clnaN&lbTDR^T1VI{6Wpyl>X?|$6stcIi1`MYQlT&Xn43)R*hIXjCn=vp)-(U zxC~!7C3S{dvtU(PlZ#|hXC&OB%;7S~xg7YIZKDO>Tee@W-W#mnSyjf?UWSmzzRDrF zfE>f?qWwuf}1J9n)>3^_4{yXzgMjK6vVxXVAKg%D`t9h z63<32f+a2d;Gi~y^?;49VL&*({Me!CoF)+=wj8V_r~JnFtH|q=Z)5Dc&|X!My(%v8F3?+RvMz4(rO#WiIQB6Q0m1 zNmUm=Tg8cUZS=Z5UhHXIm%OVMvIbx*JXSSU1uhH|7k5-=e2t*9`WWlvZh&jnSXKJ3 zII8GS18!jr;o@7KI@}$t_};Po^15VWeb-KMe(m`PDK%1#))+@_jqalZuK}w#!%`m3 zbwYOaFEZY!8RKi9gci3H@0myMV)as_?|sTV;_9ef8X-chwu#rxEAu=NYso)ieR$?2 z_ij)s_9xntXlw=V-ksrbWrb?ulxgB}+;_&;mH9^e#%4#rHQYy)u~m;Mso8$PTpQ|B zs~q=}*$i6j_m1tC_wfeS*RzxJQx+lAV3l$#d<=O6FGPow*Hn3+i99l`AF`V#%lO!I zo~=HpguOKtA0Ib>i^)^5uJIi>P7X)y(}f~@>__o-Su5u8omUq>V0@>(q4$^vBI`?2 zQmez@-R?R(4g0C4uI?zVPT)S{0FD7xhQaBKJ6yXYs5UONp~^kn;1)C(E zkg=cNkCa^qt+_`zIpHLgai2Qc6_c5FD|z&J5wd+&$OZAs`F^UDh#Oww+pXGge%e%Q zsKxXAHTR%)-y0&v>W}y|D;v71bL!%|F08>?j6QnB;>fMn)H-%Byls-;IdP3Ds86D} z*(HF#kwMT&gM%z-?w0TsoI=!L-Ey+zHl#?*rTK@ZImo2sB7AO3#P@CPg;cfMb_rcavg^uwTh3#EA z#^HWk>MuBb<@)%p5vrX#1XasmeX;30&(dL5Iq-3(R2x3F-;ofBj4oege9C8pHvOxd znGj1F>$&Kde~xNdr_1C0_al4SP`PkXB7YyYD^X_?#P6S{%4Yk;<|aqruzxempF+fc zDiGg?+Cq0=660fy+4nZ+vmsEN{#Zcm?%aiUHQwi27_JJ>TPyB#WG>vWOME~1ob<1A zP7l?dXDTu~!#T!Oo)>8I@jrb3V~kUz^$hrbl1Cf+@hw_9*GAd@A6Cs*UDEV!MR1*_h_an`)n4~tQQKm zNzQN)9m|2Qtk(1IJn|FU@7SnkSeLm*F07M`P+V2cS1+axaVh9@^cB@@Me<~HG_rR% z%EdJra2_&TiOtU-orN#Cexob4mBzuLaS6;FrAQd}MU-y#hVEig7Z+XN+3a@cyJexc z@^caS^y59=FQVWzjk$57_KBjfCtL?e=NP92oVf?+{Cd~CntrhTz)@-ew^`9p+u3{);;no;M9gwE!h$;xe_Jf(C%_OT4PIFVzVxJJtS zOG%{r%Nown!^MsrrLg~`i&~$pHWRYN2~W@pye%9p@~^sB_@l`5v5)zE&L@m__Ch9HWk}2p1Qwa%+8KpK8VTneBIc z+Y+qv>Ms|urbKA3{>r5`UgVRIjLzd9P=ofF^3-oDWZ!5hmzaC-?0>KlS2&*Z12@BY z_A0S!OkLO?4neJbu44JJL!{Hm1G>A5)y1zS0W)90cldR2JIRfDoXmpP`S0+$@26VQ z@RWFZiF4%X!=ST?^{fXy<-5>Vb!ymas-4GqR^W2DI8Zt8m7T%A@8@T>--)h_uflk_ zD3x{6{nsd$p9WL+#u?~*I*u9*X(dnZGeGvsgK|mAIfNyID)CP}$lw|4G><nkAg}xz`t~ zZu^m5K?HPf1aXd70;S$j^lQ3YJQ`(9eLL`;`8{Vjjx$yzcN5~3=W4ElzvP<16u#&D z9Z^44U3k@>EWMboGMam-&2!3OKdu66!^ieJx%4U4E;N&iR|Fz-s+)4%bs_cX?usr! z?WtM%40*O?b>vhtWepBJgsq8F7U@4C6`rP1Yb;NvQ(7JOgXey3bKu(oHMTw=*O@WC<4ji;l@_Z`p6+>W3Y%x66N z*bO;NrpRUWxEHr^rLx%K0htCbf^)Y&;$Y@%*nMb$n)~013?-ioeL6t**HLweVH%WE z1?cyVZ8hN_`Q2hZ#_~(>-eIm&)z$1E&vRs$0!hP`#5I;WnZ_ zTNioU2f!+MnRuVVuZLu!miaK59-qEH+lSKt{_Pp;xJux};htGQ(qA&1%6r@UDvO#>Tm<^qT3ed?v$2xfmoC=n!?p2JY`ev-FKdcR0YPJ5) ze*a^P!<9HKXYh?}e0q9Iq~EC~m)0{yXtJW*?p=xeF%~{6eaY7Dl`QCc0685m$%KYg zdG`2&veYMnD(9Sqb8B;v8=DWiNPpCHI4L&g>yh!Dm(Z(!l55E`p_y6<{ZC|wPupy0 za8w?=Lb^d!vzux?-iglv-1AwXWPkbC*lgwj*@iX60^;uQd3}Q~3P7L-yla$#Z7xqXRd|1m3+Fc2uP- z8`qtxj#R^$%*3Jj9bnhh1vOrKiLI$)$g~C9*lCfvq(w9|=QQwhohH6LbfBTU6TxfB zQ>faFRc)^HR(#D@ptJTp*L-4GQ=jK`V(P1&`&m-M!v=60)Cw*Jjmv?Lt2A2hao1L! zInW5{{y}n?)j)*qoT%Kp-HV3pOh?y|;pDjYjXZZQ961y1Wnz;R2rKBSBrFOiGm8Nn zn@kr+5_-U{b}VXSOcXmNmvY@;E%e$%t4myWqjl3L_-zgmzZ;yS5x!sHHF6$QGasn7 zGRNbGdoJrZS79ATj>%2k;52%l>doHE)VSU)xDEKryLQUrPi=V?S248VWBc(MY^2vW zW*@XbXkN1NV7&(gOmRlnOLfRaXPZ19t%sbj2{LiRM4pSYRTB5L;(q#4ID2@DV;d{N zwrCJ)4A?7n_dGFDNOUQ{!Ya|8G8;>58Qu-&{5HEMW? zeX5OA#VQbbf%@u_o`Gn6#~lNfpCFwP4{1z$XL$K+g6g)fYVT)9QDV#ScP{6ghSlKW z9Rw%mrmF8b^{DBqr*P~0nl-Ln%Yl!xU~Tx=e)&l`ShLDVCalRtXrY1fxYKb8H2H#V z8*7lqt^#?XSRiMEzf8&`guU}sQcNq8`9R+J=YB|>dU_4ElNO+Qez-VjyPv8~O@&_Y ze09li9Z2^L7+5Qu^ioqO@JuPZG<_jVhO4s7nu`s4px)NHl7Iky-iu}J(}v+@h%w8U~#tkM%a41K=t52k<;uMRXf)eOyg9SOgjOY z*a!oYZjix^CN!bzCwTGyBfLyhc^&ns!g}UKT>K5)=G^xl_m_FOr9#KD3bi=j7;Zf{ zzR%Aq2R_b_wBcj>6>1Nu4m8ERB8Otcn!{U5a4y=Par_HxY+gxKj0IEupv3N?j7O2lDea_*;aNaqVcD zbnha(THb^hJxg^oBbs!+@XW^T9?vp@~*3}r!dF6@WID^oF z?-$$e+*CcRzF{Pj8uR<8Z>qfb(3GaGXpio{B&lERl$ULik#nb+OmXOs@Y+Snij6&~ z?%SXMb$(57cw_@^smI^;M_ow5pE^|nH! ztX7?B*oE{u@Vv&;deH66J&Uzmi@kqE7};N-R%a~X)@di4cP=Z3{W!wbhL7!c-YgNT zm;91R89NYGW1jNro-NIYSce`H{7Eykp}hP&3^{M2WD4)f3~zB-S^3zAtnQ40bKAM% z;?w4^iLVQ@)KS4wVd=Wj#QWIZizN~-eHjSMXI!`kY<>Tfmb!2OF2DEm4DcV z^w+Wfeei?s5GS4yvxMV?`@9p#k8FLqGoOR=;&opC;rkzB9F9`8oWXCl@%f!aSlz{6 zCO5r;uqM5gHttUjT&6#eKB1oh%2qF zVbgsX%sR9brw6Ph^Y&@bdwfY(VQrv%IDMQ# zMrWYstvu@RF<)M*y$!jnlbh=4k8rgla2jJi(7XSioj!ymfq^x$g7{e<;x zMa>9Fj^B8$L-4MhS-s1FkH7HR@Ui_a&ToNLK__I&W}cny(@*(yZW)ESyhg8H2GlvY zSYEq&AGwZyWNJ=6!ULBm=|4|Xv&Vj%C+mvB`RQo2${p1Pb{ChfJSNNF$Ix$7U0qs3 zg?1XkkP#Qi+}VmkncLu56bcHPtGa(4WZIH7tQr(S_aM(LIat9l@ujHK_&GU;a-E9L z(RoanZM4O3`~}p4uY~P)iN8~;Jj~_tR(wB4-dDcd98KZ-Q_<_v5$bAoT3%n&0J*I1 zw1V0qJjh2`*I_HQ_>4y3v-^`Y->qb_x5h<2N6V91Yg zRA=pW3Oo7%p4ZJlyLD7gG+9(JZXI-OImS8ni~Bgw;TXAI)P0;ouBJS1=en2gM)Pvu z<1d6Zd~ClI7YcT5=Usk@o=t_}ZA?V$;0(H-vB5!n@irn57a>bFW2w(70 z$w)g!txWlTP8=xiN86!Q;|{2Ln?g`x4MsBY~Z6k$~W z&okqBf5|D;%lAH1>76BXz1Bdt$PuoADmYFJ77fmNky|439h^+LHdi(irpgJ z%J#cF_&3tFq{8~iHB_B^MBENPMD-7yhyIX<>e4_1w4Z$d!y4BhtAvUa8I%CeoUKq- z3sSwmUX!Zyu!C;9yU_je46bn|a2%Q|nq1EzkNSadv*Y`zx>62&{Ca4^$M(BiG6-qI z*}rydVhzJT%I~^kD5iZi^y!vLeV*@~VtZ`vk%{C{R4! zW&rE;`%$$?dvUK|1vPAW4f-=?t4rfe(Ee#OhUILfhBY5k)IGp+J8SPMMyju$s!>&* zuhs3{2YN=e;hH%Bj@^PpOT!oBxrO`w*1WUaW=c8mv3F^~_lNCwW%(SW)mtT3II_<6 zZf~VTy^dlpYS8CeZ|WC&OWvAWh}@VzGOhhxgdcjNY}#{$9HZ~UIYLJ~^EnLb5uZ@y zdPh-I=Lt1hQVseGNL{*Z0y=cxis5}qsc~8%#drt8GkrGH6C+i{>V;(1pdxgKRfV3# z8Mx*Tf}_|VZ2kI?w?|9nHEe*hW!cP|w)@GqPa8hA-&NOcSb3e_k3CihJNZQUGwM6V z_5O{%{X5bC+bCJ+F&Vkbf5^0gOoU&opk&tRLC!~O!g+p*c=7WbteeK5N@TovGCr9a zf3b%CI(}a+xuL`1<{18UJT+_ejbc+wnPaUF_3GE6!o5Hf^OI*kcy`)a z5snvZNp*_*7>yX8X^a2x{f{vYTTsgx{AC+oy>u5V<2TBcF5eMW_)Alv^B#)7+Yfyo zZ6W`w^=09gy2#DEDp&c$ApHJ!WlMN(a?=Te^O6?g_4XZT`D7NVxLgy@&+ewCWp7ZH zRF{77M@QQq7?C`PS{zZ+{LdlqjG6)UMSG#|m`ydl_2Qn7270s=Zl+)0SZjcA8&rX) zFVFm1@h_W|UREGY=DD|H@FVS&T z0|W?rYSll7;(Z3gb0+TqDQzQ+R(MmbfHaP8a-i4sG2Cnu;izLMyep-V`t=g#UGpBq z*NwE})8#+;H@-If2lBdM4XpT4Ri=47N4V}djc#OHTJ+)re1DIj;mzjAJ7d$4Tku1! z?llGBrSZ!45w_&D<}RF9%@H3x=c47{si?eYn|Qa(l3EyEhW^tJ>OZ)SPF2<*;JFLg z{+>h&Hn)c7n9YD~J5jMtJel9-nlslv^#-ryyy`3*-r5TFtxQtFm%^>qI5^#@S`K_V z+VLrjFZ~EsY*op$>_41GxcMMfw{K>3!q=j`_e}@M5nM>7@4@59M+DeMSA=O4VVcG z=pd?W=}&cf%!clkNzj|fG23L`WqI?kkcawE>oWZqGv-<6Z!QPEG6ViIMr~7p@8=Db z6;=%5`zLG>ZnsRMpI?!dem#f&^~ccYs4nvE<59?c6D!yBPeVk#EM-@}XQUot3Fj?8 z#J4xi(W3A@Dm|?rzD}=4);o=0P+hJ5v-CVVeapnC_SWRwbqg(K4QJ0TZ-BUFqPkBv zvN(Sly4l;I7jhhKNhWYO`b>1lSxYi67;csBz$quP9QgFK<2%auZrEc*wVQI)VgAO; z(;9=1I+QTC4*KsKM}b~`^4{uU$Sv+G*W5dc2wOX4H*-Ff^IVJAQ(64HdIBvHkD}6o zcjCuKFKYFt1`MnlssH5NMCU+Pj4ItgZn_FB$?}FL{bb$5eZpL?3Dxa96uS9#&|7Q= zH`X9`*m7R@TzN-r2epTraU`6!md*5Od0%wPZ1->b@eP(YCwxTe@tJb9QouPxfX2wu zfRc2L;Me5^jsIjW@B58Mp6Py>K13f8s>RCQA%93Jli-{kEQ(LgMT>6VQOWhED4u+r zY&+Y*K(ST-dBwfh$8|9J-~sZ;bEak0OW|ps#=3$Rg~f%3RPX#x=oWs2-fDg?9}I#+ z;wsV0P@mfC{)U_0S2(4$D+fLU?fBULZW)h2>eOJl`h*JMlP7A7+gnm{TtE1|SVxn# zPnQqOV~}UDSEfJdhKNp&lzne!Qroeb=dL& zu76cL-C6hp3+fhs(@jpiqlQ86NzblOxWd*t`a_ zlM*i+gJ+d5P&D^Mqttk6aC<%XwD|j%%X{@&rNUvsE5j*#Ly6AJ&*|iJ{cB1sK?*C(ZCUD<3X;jy(65a_#Hth!`_e$*LYt zoeBh;uZ&|(@*Ok}HbBKzZlqU*`vPueFoWFh;lDHZ|6j+^HPMcbee`xv>(S`&0uFF{hMVA5ZG`t2>+@pCg0F zc4)@^R#Sd|47b-O=Ue;@*}qx+_wFEc?NEqui%h8P;r+Dy&l`9!4^lauFYIo3QqxFX zj$sc$@5u$Yr$@n|nVFan8bIAfPlfC2&CJs-vyHYl)>Jz__R%}KZ;^6uzFgb=4#HpO zX{z|vq1Ao5VNk7F6rA^2K05ILc|)eljA>gCk^D```#g<$uDS{5H#f-0Qli<$2QaPf zLdId;$fNm+?-)^RWNbP0VT8 zg?c`G4A%!2c+YBiV$@1n@o|(O?>cQjij%io*S8cA^-VR^Zhxk=;lUU@C5*y5gv%%5 z4D#lZTpwhBi2VV|Q6EF{{lnjoKM`cwdnB6G+yE1wOH|1vj@++Ig+b|SRA4QdZuy@u zv91|)oxYe>^%d~gnGH?54l`hB<-hO?HX zO*!mWSvx-Vzq@BckbI}9TzAI}5uR-|)f?JUM!i)S((D#RoTx9Ku&?FC`pWfx3lMQ~ zn{r%tF8SrKMwYRlia+O|X+buOUoD|3X3NR5#X1<8v%Z0!!gJO7nD}Qa^%$ERwT;i1Wf{lz09!u&Dy4Tyy6l~-^w8Cwo~RkY({|GPI> z2g%`0Wrlw&B6>d3)EKjx)@KjLkb5eM(j1UaIk(D7+$=XltVYCjUFF1~+2kL57B1B< zQ{}bS&@{9Sj3f1^>gVs|6>=Gd_UBPy#y51oG6|Dj7*Ow#<0-wnJ3N+Lfo3_A@7Lsz zZSo!HMGb_0<4kx2TEjkPriiv(K>h57!nNQt9KR=(17BGl^6wZ{fH1m%y-wA z8@8uS#cB-eIg?^L2gv6R_Q=beDL2MXL&WEI%9%D@Xn6fgaIw`PGlNcO^6Dat_MN91 zNA{3#KL^7hRHgxh9uN9r%IOsHo3e^B{2AW_)?|CSLUeiULk>>`^tN(M#G7Y|kB@?V z(n_&l{wEs1dxuQLG+A{SMx7O^wY3&eVipW%Tcg6| zo#;98BBmbNOa2knX#MMacno-k*2a@Xk6l*ew1~eAhvz}RT{1jA+=YEq6|wlzNb*m1 zfa_k~0ho3DKYagVj8k3v8L*E&*dK$WIv?bQz-Nd!TB@nDt0rx2SAgL+s#E-k4f4h2 zRODr!mzxsiBeHs1rQlI9jlR!%;hpMH&3RwZq(^TU7R{&Hskcb|B@c$nJbB;farFGS z8q>04Xvm7$v@xg(JUZl~b*oFF@4{B(;&lOfSL;B(=VXrG$H9L31(DFqfCi5Vfa}&n zaLgF_-x>TP#;KtlAN%OTP7;ZEiE;z~rilBaG?pe`Y1@ZS7_s6iE%;t2Uk3Og?`VMB z%(}Lbjhiaxv*WnG-;Za5zLI%sGc?inhvBqyWD)ITwnBn-m_BZ59$KXt_@&6Dqkeee@{bU16Ss;IxdPV2fmtG z@o_XPA3n%H;@~}Uj66*o-)q^+4D=3ng4I3h|^&sW)oc=U<=MuPtyd;Z4 zV>BM44}-KJWHo0Z$wrT0_<;49yZ1uxWOK|s*_p=!d8c|N3>+s= zgBfS3P2wgP{x|`h$;s%`j4J)3zTy;r{&_T5rq{V=oqv*DneECPSeg-VmOT zgJIt`Myxe$LL)B{_dcrg-k?q8z*nY$^zUz^0sG&h)I=n7s4F*D7{I?jP}3k`0PQ`| z0He;hQ^M3h`KDhy@~)hdTbPd#Iowyd-m4bP;0wWvdqwdc@ z-}X_M^HPtd<_@G?tV`>DE(5La^%2v@e<2#&4En5vqrYMyygH`C-fg+q+^c}b#<3>d ztPyau8(0o}7TWQ#|2;lpf@SfWWu}QAA{SlPG#+n22fG}`a^SPn zj*tECNe_1{vmGxp7a1XP`&>rjC}60nk610zzYX#U`4T zov+d1RDp3fa%j~VOHzWUnnv5!7WZj2?HFUhTIzagsCQ;qfcEIP`$)%Yx; zHQV~ikKr7{UG|mR^QR#4K_}&L{BzE~PVikTpjJhv(17Qabh3_;!;N6-Q8f-mXK!+! z?GyT6$VTXup%n4qJ>`x*1ozfIA^i`C_!VB%K5q>4uO&nOWhuOuB*5NUM;r-Bq!~JV zFT`#*>^oHsd=0eYJ6b_LZ$27J+TM`cS}2I>^h{&ZqcSPUv^b_U4 z*H9}yuI9<-2RdQ#qc3vXwrz+CY^Jfjy@gKNjKIX0SCr8!TYf5jkGwM%NkJ7K8 zJin1haYoZQmeg=BC`R*<84`Jh`lv_3s$R zSg9aiv^|5x^L*rXXAeZhr)%s3j?igSA55Bdmp0gG#MgPY|`OkH+C!BAt1ig2^L}&?Zwm`GvWSd3pA7=lx7X*%&Hsyf)K9UuUidhLdw~ z9O`##t^RxL9(nrSB;R?yFm`PPy`~`;sGLMZn}HPf(TGkoWnHbJb&x5%18dnB>iWz9 z2F`)cR3VX!4s|(FTx?9S2^%C(T(r_W2+f@fs zI}fET7gouy?=K^7M;*EAr3z8K#wj1NB5BFq4sdH;g*+OY!)kN7x|F$WV*57o+Y<@n zv2(eG*arS#M-dqpMvI~w(wSNoaNCvuxpTExbugZK#udO|_&^vi_f+*Q4fcIQMB(7Z z6vlqx^64t~HAa`ie$BMwWB+>v$ExP?`{4GulZvQo-)LE@ zM|7_0Sh&sV0ePa0$oO@V`jR0Gl7_<|fOpMJ=?42rKSj}xdlXTRYq+e<|j%jbc9=KO`_1MsJHE)y13qKlI@q#-~}ULoX0&V{ouY-MPjCkg2Pm!&7ZmysT?EiKx2fmhC@o_gx zzG+b(3l1jBUH3L4dfHx%*LsDn4e-ZI+l#a(^oIQL$QgO_8_7L?{1CONzVges8>OU# z!0lKlVe4Gh>F%KZZFh#+hR&v;?h1?xxdv`#iXqjV5YuEoCEY8bOHH@KO{0Olq9e8p zHlzN3r^DckCk$c?AU=JB{ZcdW>O^IV@;(TcyqU0nSJsEpW&!ZGT)c=28pPtjd%S!bQUnRi~7179oc_}Ks6qCetaWy;;JejqyQibj-1(yeYc zFxz1s9SFZ7fB9J3o zB`~S_4EjU!Fm&i>#0KY6>dM-5ZR`TL=@+neGVe-y7Q;NdD=_%676zL(gQkbWe&2iX z`Pc=D8NvH1)44Zyc2YU;mG!g!?SH21e{T!!B0g-J+%xGaqVLwwsCU`Y?Ot0k$L%#` zEvY1bn+G9p@I1M1aXzA+jMh|Wp-X8WhQeJLN$q-jp>F>h>L1K6@8b1|Mvf1FiOogm zGaqD_=>g1lTudv2Q|ZRq5blxYLf(Pc=l+-mpXdq0s-0kPFbb5ljPZDjAANUGEbH>P zEMtG%-@Y99Y_;O!TQ1-A`HFap%5u+-%ZM(Wrcp+|q`QMEVJ>!1&V~f}`|3I5b^R;% z*E))*?}Zwj5#hADY?tx4k<=k|4(jUfP=EI;q^?0}G@AdFNqgqR?X|$L{f#jHnH8-H zs7$w>TX2tNHRBsB4lbEPL$fSk*gTni&;nG_6ZZFJi{hU|^H&DKC9)yx*Ul^lK0EFB z*#F)Ytw-F>A98Q-2gEe^q-ovg6y2XN2ti#YaxQ#87B4nI9tpXBWdWj1zH4+hY^U@j zKe(rQQKx5~u-rLR{cWfvbw9R^#@4M06W)KMfA=?rv$l9#niZ|-I+58^&P864$!1|jVV876_9Qf?D<75AOKlU}^+8vVn z44o0vIz}Ul&e6k&9+)>^4jq2>N|tnXL0&66d7#k?MAtj5(R;m+)=l!{ecW%!$BXrE z`+rq`9aWKfnbf7g(ioV8)`5XOb5Sc3;(OntwcfdOZ)qL426u$KX(kR2ZbkvS?!&Nm zJ?@)NhC1p#9E^%dcTXb4Kja?R$kwo*T~=e$_I{S}IsWZ`71{sZe?5!&_xrI{Yzkrm zTs3Xi>(Qf?FAzMgh>leWl%+-;kyq=MJh0gu(GHz71}q%0zB}*2{T58!l3Ku0e~kLe zxW&|`=QA4r^d(Hv2E)MK1S4{uV?ovNlwtjb9(;ZSS3gVsJ|u`^H^0)T17kEUg z1ogQMaA@F529^zIp>ZA77Bhx@K>C09{>K={QR^90Vjukwtit@Md)NmXASULkrhVXK zdUCKbLPGD*3015tJ;7&C!B!r$_eHcON@Ez3MjPF;;L%Kvdi<&liybG`pC_}V(;5Ss zc&R2#vN-~G%Pq@i8jCeT9Q~l@An4^1O7^;Gy?j@kQ3JxCU z$Y}mWTIA};+H^}{-}BsmXYh|Yhm&@E?4uuz+G4)R4!J+A05MxmX*zmX(6eiY5!(3{ zof@}V{t0nL?#mK+aNkx$_nNCQy7Z7XH;RTwpM%tU#3)$wH&uU{wt@P;n?;jz^k8y> zbEr^1jI{8>!gw9pRP8lAIok`am0v-gtj7Bgo zWR|KLq63^XCQWr|i&-mp#LS|;H{ZZQPp$qqV>As^d(+hQm0|KJ3kI2sF|xpl^P6bO zG~Pkay)t;u!9vJfUvWN2m+v}%L$;d0uz??t(Gw1VYp7D_Pg;^Z5iTuCU~f~_XVd1R zF52<2kAA9SfmqkR^1!xO#C%++>2lYSURPyJ+)?c)|Mn#L_j@*S51f%%$6^pYW2?qA zs4{Ic;68VbIrZ-zgF4$ss6WhDOoNtopy>;*!L&*r7+gJxQF9+)akW*nRj(br+{rV> zd3un$oI}DHff}x#1@NNPeq7PA3Jm{K+*cu_4u6x7it;=47{isOiEo!%^(BB5RX(Y2dR7G^mJ59yHinRUDEqJ`^ zK?5$IM;+f#_50~xX~^@{G&A%pOl^!|Q2ZUE?N?y&%>vq9VH>@1ieP>J-H;pe#kI2z zG{qtXhS%4?P^E(6Sr-oLV##cIEG6j2G7rWI_7ymK)@naD?fBULK6CvoW{|Nwn0FPi z?lUyqmk_=8XYN?cAG$ciyG?}yZ;%^$OJ-l>7=8I4O=V9#+F8Q;2^zW5AYXsf(MeXn zoA!-{tG#IUyty!Ke-Vbw>SOfdE?BbqChe?nkKP?g=~H<2xlco$d`9i9nd-MwuTsGB+B7%3 z224j}!mz6c#w35h($Onux84={*smq?Bm5y3trK@Kg=X-6C&SXlFzlNF7=f5%7#3OT%a6qIRD{>Nis^)2OfRG;cvSn1=D)n@Jek zg?oH1?`f||G=2V67cP}mkYRe_p~)AT6<&#ZlKj4m@MezO4mkX7P8PG)Q*zE2INvgW zUEY{-;46!R{v87_<4S(Xxy7-|T$$asJ-?$vHGP$n^!0mdL~1J0js8vA=v?BNl$O(F z?lAtlbBe}nQbRgWSqGlSThhp?M`8Z=miqM+HI41Lj6zaB!*um>7^b&Epzc>BR9H>> z&3@3g^lor|a0qgWop^lz8O_;R4Mt6KU^w|SG=Wv&XrWNOmKsXo9+&g!^|0Hps2upp z=C8HjWB>cA#3E{Uy3BrPirC}5H2oYJ(hvKlh`e!#56#YClfqjQW7sXF}uG=mY&4)fiD@_t71*du?>%E+FUmeVI3D4Wi$AYijo1N;x() z;pK9U0(<+y{QqO^EZegBp0`hTBdH=tmx>*%Io<5b21UgV>{b*JTfv}1x|BAsKoJWS z6%Y#p#l*l)OcX`nUOxE#A9`^dzxy5R&)(}?d)BO(bG+>7&5Eha$DoM?)>uOA-YqD7 z*@;EIfr#I3%T74_X1^QwJkIs55Ir}zzDpm$HY&^TIwrmrA|Ap`VFdLGwI%y>>oZwpN90dcF>7Kh&XY>VUpzaVQJU7pIrQ0I8WZ$ z3O-ko$_sX3Nu~jkP0Qh>8Qz<+2I0|Mi}wFS&}Y%f`al@pUWsNIDaZjTVCU&SD1Jv;yZ$!UkIinez5aNtI^kH zHS>3xg*HtE^dkK|TXk#^+xkZq>ciVXIW_@4lY)?R?GHP*uAbx`ZsRkZo#58M=L@V% zW1D})LOH1!N~JuvGm+PaeO<|%Zltq}G6Qt=4u-Q{Lo4_oosaA9=R{*{?yn}EHe8O- z*w4bOj!h)zUW|~@G3=H6Ac?}{CY*E%6HD53Loh88+TLHr%1)0)-#IVYs_#9~X3sc! zp1+2zwI0HPm2N_vdlV|49D=1rCy<;rfR!dSkwUM*a9I-%x5t65%>e~$YkONL?`?$A z%^L6oCtTWnWStKrv8?tB(A8reoPG~(1z&%ue7vev{8{q_o9^EbPiNX8v}ma?r^`{2 zU$Pt_Z%48>KIsyL6D>F?e?lxt+l1f|+Cuxe0=w{r&qmqf&DNH3zR~9N>}(5LpD><< z==Ftqs1=lJPh;ur-AI`?f|VDgkYaolTqJ9Gy-@>`9a6}GM9z1bug|9zkf;|K{_ATUxPRA$61~up5c2y=-p~zo?8PcYzsi>#$W8+<6{y< z!w)#|;12ha<*~YVwP5yZ8M|cM4SnA+wjo6V{bn7ity;hWO_T8brs{|@4@3Aa) z7*cy)V-?lsN$J}iKG)9!Zo9pi{P=4ucwr@!Z>mA5E&~$pXt?;jV?8#!U^(}zxTop` zI9+OP1>fI#fPe2VI$VDZwac+dlk2PSH$s1#2@58alVYI_!i)mgN6%)7;_`BwIP_dR zyLS|VmtGLew`sB~ycVjT(`FV>tP1@+2YULviUpE93$q&n^|A#}>3kEuo*76}I>atD zEF%@Ka&)<84Y%+trnu-f@3kHYB zNn*-dLs@8fDU^RMfU?Fy4A4%7%XMwmZ}EP%E1S;_lCgkO+W(z_|Hl|dBJ~~c(~S7* z#bgBX`u~!PV-QBeg(V5vq}+H7;e(slS0P-Y)LTA4WnDg&U+>R-BPOzI14fWK?+fg*@Fd(uJ2TZB zXBPHT7bS1F>U$BfH_Vj5I>s(WS=%xb=)>>gD5DgyUqWm`&vM zgBvj5ToSrE^CyFhBg zED^CjkNq6*Qlj)~5>9B$5zk*NMexxFg00b7c6+=TT>BklL5b6#H*O6*ayY|+TuNEg ztS!*!w;L)KdtimKVcFA*O;|Sp~bZ^Cnya=d+MD0nn3ArkZ}bEO^;G7QNaD8WWPC z@^KOTbuS{r;Rw5Z`4?#~_=(OHyloX3UE|L#El>6LKl*Pz-W4D=zMPMZV|s|^zGfh-?1QjU>_8fsEr>j3#Qsd1 zCQ;6?!|~(RV(C4uzlTQz2mc~=@5dv!UbJJO3G&d*|4t8wZek&ac~5=xLujl_f~uYX z|6Avfso=rx{24_$&w8Qrw!sjd$}v4rjYU`U?>BK8l&7d-;H?hmdfJ5zJyy*QT;qN5 z$pLU`|2Mvt#y3PdAJ^ZXSqHHpG+sQvJ_up2?1j~9#*^l?ZipJwl{MGvNR%6Wa6EFJ zST=1Og6j$dC+A`8;V>gG?Isp(^c=dAW9Y#|1s3}4GmF{d4~>LusP-(t%0vN~Pu$r3 zE()YKMGKwBuYquWENkOu%wlxap~8E*m6t5Tpf3FE|7jcZxEI6n#SL)TJOxhjNv+@; zDxHt(@6YontUq%>ELDj_xN(og;x@lahW(i!&EGLGXWuT27>dO zZR}C@G_VPJEMkW>bXAwr{RO*Oc+VRw_WUzw6rO!`+1}c6cyUHdjG8U;+k3ZAUlDQ0Cbb$qI@$^Z8C6;rRCN`A^#S8z!BP>#u2s z3f9%Ti=}Zz2)An^tpCwMI!+%D9Sf3c^GBjmSj^|)$&2MneGp>sR_MGZj6G>m0?XOM zqO8rKb2N?at)Ian)|9fiCkD{qai{7AcdTxA2HA<`>{0qeGMLEkN8fls*nF57Kgwot zQ9YoNqQztNat!)dfo>DRn3qimJKXaRT*gb_cs;WfeC|^Dc-M;9^t1!kIVXr^X3hMc zS0V(MG18s75!7qK5>@RI99LBm%NtS<;?P}iS=^sJn=}yY(+d_|z`dzvY0}*| z9Tr(q!Qz{GLF2PJRI`?2_0xRhEKOoh?tLV~nnUQ6{|mwleb(0C9gDv)5-JDxL3!tC z4EFfObF9^D+~`nNc$CLGZX4iu>~SmjJf!n+{WVXyg|+j%#j?F~5k9|%5GYO~y_nnB zR#{F8MN1^A3lHGf!*$|?fO`m`Mxk5JV)o*+Gl=oLHM;>F-79qGfDMaQe8>{pUxTLB z0H~JPV9ic#AIc{NV(>v;e}2`RP26&T z74;bk7pD|BW?cG@?|+POhD(13T%*ko|32?wvAoA;gomyWHZ7+DrP-?Yf>UCZP*Up4$nUL+?XPr6bmLR>aP4@$6N? zduqFIAv!64MF0AI%;H)(OWxHRDqmHg{LC6deEraUU=5r0HH#e|b`&l$OW?TVZ>^2A zJ;+lkACHE`mfQQW+UBcx!DA-EFS!d_&P^c0UZW73=}jsHDK5OZjF4Rn<8>R^N&t)x2LdIG@exbd;TVI00SW$-{B%-!q~#zLC=T z`pZaU?3Q8Gg3jWF`|b#T^F-MCnaIdD9C3ZGlbUkAMD4*E9P1DuUd%p-kfeD+--wT_ zZV@+u4{T&fu}7eFJ~WwF;?Ex0a~)_==--AH++JQxJ0Sv*5bqAp87uHE`z_OX)NQ zT5G3L)tp+E;HSaTJ}5$Smn_s4EW(C>o!B$~H2XNG9hqyp!g=}{^j|lX*`+D5?Xf?g z+9w+-R)nED;?P598e70~C8rg*Usv&JINB7p;`{xrYyEc&*XAte%Qc06eT-P~Wi29X zM+hNf0?6cZ2;!H_Cyi6TCF(IFarE?F@zN11gjBQ zy3l-954F6h2vGWoy-Ekzmquf<H(936jFyjd>s8!MfU>rZyF0Ke+B;w9cI8nL;p5FxXK+F!WBbJ!-NQ@cr`kzI|WR)54R zBXkj}F9;G_clP_na|ld>WgPzwP1o&o-Q_e(-Iu{KYkxw^TpenB=5xR`Gwe%m!+s<^ zBb$}_a0;{mE>;2S5M zkLyo1WhneQE)*|Y4nss%7a@|8se^$8iIv5qH>5(M(R2+(pGSyS?g63BpM-%Hb*yQm z4TQ8@mNm@}8Xuq1wfSvW+8=e6-Dy3vC=2THB?xq>!T$NFtl@22vg;rNr$M?vN(Ad} zv5DpM=XG<%e1FMwh5OzY=ovASt?l29m78Bf7fCuC_AUC4?|+PO#!Gz%yt`E*d&dUL zeIAOJ3)B!%A}d5~oJ;0&8Iop~kbY5>M05N;6rDUEUY#C-&>;ha!4|QsrHVoLvw-EO z20*Q*$*zIv>}loL)72PyH0HxV}b2&2J(4 z{3Eg`?uew8F=SwMUZPpJ7)6_Rh*#fzMCk0%!cd!jBb#LI949*<2^d*k4}m#pP|9Xa>lXQvneP%viwoSoQiw-r#+KM$49aTu;V5WRw4uua9? z*=6-V{O&vm4im~+!8b`dAJ?c{_ zEBGc$<>QgOM6TjCmZn#WS6}o(WZ#iO+>Y*KeLMvz4|kBsy8RNZQUx5jHCDV9T#3*# zy#&uuL8MTB2V%x*mUp!d>hp*$FYe5;cQvp*m-|BN-Ug^|x5j3>J}8KmBe^ko)FtO2 z9CdDi67DfHs<6B|d#Ful2UW|F7@>L!y?gXxLH)k7$|-Nqx%@mFEL(HeI7K=i*Pp!n zHTb-FBvvkqMdZYIA^yE5*=lY_>c*aA`ZY_U-F`TZB*==_b@%bw$c4hFg{w%(H2@Nw zDz-1!1nQ<$bZNUW%a!}c_8Jd^*3TfQpU%eS$O;@c>J9V%c@oEba%m4h|}(Tk-w={%8Ij!x?e?$s-LuT_eQG z7EMI1T_7a78j{_Nk4Uptqjn2ANVHe3#u2Yq;`OvW2yNo^ETQ~twPhP5TXWfg0lfaE zavNQ|)WCL5Z_D=0IsPI`mz1Vub{Sj z4pc`khG$1Ui}Z~j3$41rZX6qn&Qa%K|DmN7eBRRexc=nV_QjI5#p1Pyy@=d?OGt_i zCi~-Okybg7+CTS`Xy4p~Bl_Cn4eJXCGjkEf?k^>kYi%HDdd>2c-a{>5HC6oB!gih8 z%=YIuLA%ETzUN%UmI;4Q*gu*SdA_U1t!{9TECj19WP>LCWC!Y;pmwtsstW?(dF&DT zh+kRwu6R~8S3qaqMA%>d+6umDQu&Oz{^XDD!{X8p;&s#ch&*#$NPfAC9JNL7L z!F#Mk$8iA)ucwMP3X~9r5@CF`4XGJdV!-Nktl+9U)Vf7bg?S0vV`a$>{JsF~G1kzq zTa7JevvH)06)8LQpHvOfXd_ILJ3;ER&SOBsEOt1dAJ11@rVE3gu)L5)mOsD`+J3xyZg>xDwcUjxYgJO2 zlS_TZw1<5W|9;;4nEUh}tROiI>drn;O+0~-U+$t$^Jf-4Ig(XZ^8KZEci6{Y{*Ui} zjB);Yc>G(V#$2Nc&T?2Z^1gVZ=Lke8tQXQ!>dE=6Gj`l*qK@AB5}n64Q7C>DZyXahQ9>uSsG@ray&hYBwtP@nCyDtFnS^qo5tv2o1j$Y>igIQL}HPnq5!* z+IEHg!aA_FKiKg1pV*-~es4K-6;$^<$EYNJH$Alzi=j+*cdG?Dn`*<}Kjy!8@Q)Z^ zrgT28QH8m0urOI!yur_ZQFfh$?F|mp*>n}s!)(d&S*=93_Xr$r{4G|ENJLnkn&7=S zn6zXEVPMNwcC>3e_g5>YviL1*{{#{5&t3eopW7ZztTjNPY4=+w9x_T!UV!8c1PACCkj3fY-h z@Tgh5IjWS`2rm=TCm2!}{~pM|ZnB>5D$$L}!{Ng(#Ht6g5LUTMn7;QqX^%3+ppdTY zxY9SM$_7&D@!#w~Svf1T-3jemHqa<9M$pt(IBw3*+7?7~s1NLJ*T8k#d*-F%&yJ)u zK>Y%bQ*Y0}=r7mNkIx!Q&}(21e)B%hni$ykRci&`Z0USlqY97gvB0uUyjj~FQOn$f zj8mt{~RSDCM(SRIGuEIeKA;HWG5bmNaMlA>eDX0==KIolStnMI?ZJx5wV|Vz z3r*831b1=6NtXwtwOg6o#=L-CZ-2PTu4WU48nR=<_CcdpE>wSqV$6)W=vV8(lK=Ry z$E!WiDcuZq4biRmesiVsas4Td%*VWfbz)U>2%=8K2-y)Mse9rmWG%`j2hA#p-u7EK zbUj?Wy|w`1cp=Q&w3_ric4J7l*X(qfHusO)Mdz&dv%_sBvSY?Wq0@B}GzVrNI3*Cp zI8WLij*+BO9c*9M^FHH_Y|@tw?0EJWXe{UXER72oYsq^XCGjlv_b>LepA9-~h=W~q zYwjB7N#)}XEE2`=1DN}Bqj)QFA)=nE3povgsYjy=vh8chG2^O4uRb1!0!qbdWg~>o zog*x$R--n#wtVih4J+AD1LZ0iIyNWiuvfm__Y?HkyN zihLhA!lru;Va1*z*XS0gbv}S`N9w^e53vkYbM~Cqk9DGO*hTDZ1>XYce1G-V(gAZq z)l(C~L<5_XrGU&v{LGwl)Lhi=n%<5FqzxafPT-pGex>M+TqlwK@v0$fm zhe5Louix!I1LL>u09)RVWf^Z}FT<_T$*ddf<{W4R-$LnpTz^Wv<1qW?A?~LxgXjrI zggqV#)VHfYa_2v!F5dYP{pRN=h%6NE>=k(ZhODscqXEw&-^Z}jAXeVL4oaV1(CN}N zcI@kDcFH#eI)~3fONPhmZnIGmGm;DpKGU$gC9p{`MBhy#*_^Un>~zaCzJ_N&jn^bi zn6w@2{!*6X+@8JmDuHuT0_=q2|MC5gG0xw7(7)GkTdq;1We+gB?Pjt1@+L%Y@)YvQ z81>u!4m+KDl1oE|q|G=P6!e`f-t9RY5gN{d-xzl?)qD!~ezB~g`w}SSUZhhWSF#g6 zygv1E8gy>SK+7c)p$9T?c7G)q&bmV$5p!YVHV1vX&Svw2F0qpFlc33c57hX4`H4N( z^ZvlyZ0Dds?5#xtoNF$?uD!~C@8BOX&SL3&T%$^RzhTyFC-Kh2PKe&ORM#{MZGqB+D|E{69QREc$V#k? zq4UiPS~DXMW+K74tB1&_D4Iqr?*Z#~_2^S;z!nYvz|J1df@ZT7)O>DWl0g+HPmk@M ztHR!Wm4S0{6>NXrX$2pzc$W74xJH$pKf%m{x5YdBjwrfXSJ+?7V-o+j*i|e?J-P-< z43vtIziqd8Z#d6m&6pvq?%9XhU2}m)kSe=k_YF!~@2MC!*(o1?c6P&L=<1(@R^ogf z&wAnf=X^3zF`f@nfbK4#?EX0f!2U;P}^`5lYR~7y>VqMFG7!fDCa#Z zsfS^E^I0qS{?_bBS)W{^%G?uoM#Cxb?ix8nw{#T__EROiJcQj_wWw#+28qGc3CQp3 zA>Mnq0ufQ(!rFt)Wagrd;hnu$CBJi1EVHGP^X=K`uNCavy;SIS?+UHUT@m)>7RrnV zlj&qX8a+4!)_sSePhU^A?9(b%x?lpdqK7~&as~JCs0Y>`Vf%_6vbybG;Jn%sw)^v2 z!M9W@UpuZpF7;l1SYl9g83&)6iTCGqLBz?A z!UktA>W~nH;Sa6Yb>{<6T)m!7#EoMmt9rB2u6oe*Is>id7YLtv9_4QQ9`$fKjp=>? zR<$nZ{ZgIzU5H|371hvsU8)YG2d^VXkzQu@8 z6LzylDeqH#N5{`xWoKK;Sy@;0H$MlAC4|mwkZfXUeuXH}HKjrd^nD!t~yzeNB zZ2{|q!&i2br2A3ieV9l6j>Sm~XW8RmHy!c8rcQ`7*d+w+m`@#NmcX-5Pj*Y_3xyX; z=op`Wa6WV~D}U0$=O3y;d%;IU^l3yzdNrBNnnV-SuE46(d-U$rldak0$0~v(&|Y2v zwPRc0z5f%RalMWmc3;H4_f+Ne;>ECaTi*)4<aVE^)9k{;`^5*bZU1KB$kJewTPoW|mYp=%244ha+ z*GJGjdIj3q{SdKd2rgb5NF7Sv(Znywu&f@zz2eK+`q>-U#aD6AJ|7IVas^Dw9tEL? z3_B7e$9|Y>fYWC)*tUPv3O+xneC@gZRC*M^d*ws%fqO8v-D?txUK-FK{qEQoR!Q_L zL}H|S7Y72|#E08oAkx=c*wT3^S@$f#$V@+WcX}ukMjWK0o)cMlb_=_>c^-7{?tu1# zDTp-E!KLPKvS=^TpFIMP&7Y_EQ4B=2d1Zffw1!@J6dYWezyFA zQ)MV@8md~sw?aA}*PqJbnV5QUh4|o6Bw`d_3&;H1(%?-;v42u~>YqAWVl;0)4p?6l zYaD_QnYBpRy6yP!kZ+1O;53!o`n`}Cow<(vmk*0I$HyY_##J75fyo=E~iR@vN8lSn*g^rwVU>D2ovnv)Z&@>bVpr;FS!Ibf^d`kX=lm%|-8ILxtB1)ZcQMWK)G>3m$HszcZC`O~7iG+2B*;~k==7YSk4T*=8R1!IP2vD)X~Ay;#S4*MFh%Ah)S zT|)zU>yAOEc^{$&FUAeI+hnJfMRRBuERH`zk3;z^c&3@|{1MysnQ+dymPU5g#-ZV3Xz2VY5|c&x z*!!zmd=elas`RT68PbtDcS*$9%3JJ}T@vI5AE1Jt8SKVs6?QYr5PBs%&RG?MZB9E; zwN!~5YKGGMA4_2&$31XAUuIz|OxUdt`g|RKggT!IIPZufB(K-83m3YOT=_;g-aZ8D zdhJ&5{e1`j=HpI+64kmWOlV>C}bS1&xavz}^gh3EAeIR6q+^)g&!e_4YpWo`&)`U^TX7#N*cPHsmy@ zm=<1_z?`4`yGLDN;oo`Af9M40@t#Qa-g`0sd}j=pHIZFvzmw$8>ccUA0IYBRjjyHc zpMT>ZDSTXiYF6CAY1KyY$s&f>wJU_OIitzTa48NqTqchL2PCG38?e_^M|_$-1<|&n zg>4=isjIdk#!p29QE=J{&_6VSUiP6?_|{^Kt#D zO|roF+os}^=C_F5cT%{ZJCDY2kG{g|8Z^RFMq;{fG4g6|h_%kgcphY$5OZWbb=x=! z6FNR&A9BUkn2o)u>Xl&Cn9NGPnJin$%OwT$YZ+)&|DQu)FAte+2@ux$lM8`19Q5v zd#~cz-G+hCpR*czg?ACVOa=E66{)Mz5n66#g$~5$T(&%Cv5EuOgR^RAqs{x27rA4J zQZxq5F=kb%dr0{(;Ar>})`MGfP7ajL_gABTE@JHSJhAq;F5+m2aK%cFCOlb#qtkQA zt2ZQV=eNV2bH3s;-UAx_`LK}i`vV~I%t3hY~#evpY+NBa*>WDlYk@8LKK{SZ^= zeP4yxS5I)iW&w3uQ%HXGmtppj_Z9CjVR6xktfpN)+RVKN_0 zduCk~pD#ARHcMY2Y4L38GjuT~4+&=V(_cZxZ4vGJ;mc}zm9q!4f_N|FMdpvlEKIBvO)#;v<2X{S3HdsLOh=S>T- zZR~I%`PmEVTau0`dQaHT_+o1Lyr1@AFnjdejy;SwgZ`DR&|j&JxZB>S@lBzgb5GK$ zn4d7~Jr*wakFi8vJNWq44j33ULOnhU%lcJd@Y^5k{)4`xwwu?>&#a0ZIQ}n z!S$!U{WrY6sfy2i>k)UWgK)!h4o$Ul!3iZ7nqX!lX*b&eyARrmFCxEVTd13mI?0n< zdo*Io!v^;2k}S1M_NTp}JJ^$L(^<_~S?GWCuE8q;c;vG=Uw5l zx-Cm)wd`ppLl`VofO>WSeBDzqWZ^hgGpskM=kQvi4O3uM!T;V;*XLI0d|ZF(Ra)>G z(N27!^c(St_Cl3*Bzec(!HKt$W4G5B@uk@zY&$hbNV~I_*a3G;&E3Qr zn|o68#cq^$N0HTHA$#=3jqe+F&~J1=eAz@i(b`XaCVA63izR3u9RU}U_AI695~~fq z0fUOqP%lWw^2x>+^5Fw}eC8Nwq(6iMpB-VfyEQ!xe`}Kd9RpZ!{b?xu!sz|8#TR^r zNqnza!mXR(G_AQ7Co3&z@{}Et_8OzGt8tb1GCvdBK8+W4c-0fE2XPP45Z2tiEj4$0 zMtN3m*t5?9d!iYLHZEFd!%iT94Z+jNzo_rsTw4D;5$)L=bm4Pm(iX_DXHTPH*r5RG zB{J|^V2YtjesCX!E~J?%2Zyd@unPWr#+SCg1WV`R`qSul3ZvEK#Fw4Z5I_HtP@U*a zGv?n#alt*B@<(6N-a7}oa>j|T`kzNkM;{^mP8aIGBM;NM4=0%(p461FnfCYxvKQHp z*wZdmyjNZZZ31GEaI^-sd#lNH%vRdS@7vpb;Pv1W`>`GJ{n?A&`Y>GC1L~D~vBJL| zL%-}|&-ZO7t@xX8(BLz$<{WGVUx-w`j$D5lOUGi=fTlWQ=fksw&N_mT+I# z2=Y#Kl(av58N1y3iLdzVp_nnjLgvIN~C zg7cN`L!yfwo;4^EyWLCy`TNmsdpSBc9%AX~!`RCxJs4i|;j>CJ;J;}RhWRaFudKF^ zc2qg+U+saFq&0Vqq0;%d{xotgW8~G5;;RWth`+8N+_#IQ*+M2xuj)k8dk>PBDVAgB zj~U|YnVE+DT>IOznBf&E!^SeXy` z@B96aF;1BDckoxE_YE+zQD0HyVq5p;y)w+2z;GacHs_C0%B&hJZ8rlHLVD;Nx2ha_7cyo~-s{qOCh zP2BUaoorupb{o#J?rX9)-9Er*?RBX0+LTrCN8rBd2zzgmO}ZQU!ak)hEdNCP_YVGX zR~0Uuk84y@voAd3mWr=8GbD5`5^65k(!BQXP(leb%a8NzbHz@NZQ`5YVTk!;Cge73 zp@AEAVW#^9QpnV#MvpSudA}Wdzaf+N)OACfhl61dWr3ue`FM5z9Jx(Sqs;>+qwSGY zbb7Uw<*agNZ@0?A=+**gsNKTq3_ZC2Uc){nT9Mug71;Yuh2_0Jt>BB0%4f+nswwor zh~FK=H^w`WF!!MFIK_?TM-InX^R6^UH$Y<6bON~zKg72tK8Us4D(njJqd|P8(JX@_ zq*#2LexH=1oqZYm*yjd&`SdFHTUiZ*o6nKlAs=tdkCIq>lD3%VpzYjRbP7{vJB^pJ zciiL2*m*ZJOlD%u!FqVC^JSmgWRw2l@vt8j0?VW7t>BB4&c`*Xxk48sX0{XG90U?l zj|oqG7%gZD!8w^JH1|M9Ne54LX9X zz!_F=yps%O41rzK1z4`)l_paEkkdj2*VCd^PbKC9 zWss9SS$sdMEn=I#2>V~&B9GSs=8n}PwcfeZu+)#T-z?_$Oh4E=-%uC??T2CQD5UDA z;-kql8Y*i;!K;SDv|AyZbrspZ><8?#<8GMb|AfY{57=n!juAok*l#OMGV*qVU49=} z(%)JlX)(^ThJmR`DnGM|mKL`Pm?p0o=&!=8%o ze~v_4&vfD7mUJ31dpqViRgwC{AN2Fda>}0S%j$pkWbaev!yvB>|NogHHD&8Oj2IM z$upWAd_RVLt!aYk#%a))#=U4u`2Q&~hP8AnC6gJlu$$TfOZmU&2Wj6gPC6ggpH^Nc zxT`_@&|Qc3QrQXb3)E@(@d3EdE`^r48b~bq`XD>qU;Jpc5OI6^3Wu&Z(x@3Zm|we$ zG_&T?j}kM=8Z({!+B$@NeBU1ib@DLUKOAY1^YD4!Wg4F2PNDC7VB*mej-QUPg6NKX zEnC6#-FRp$XotY@-!M|=56L`wL#DG{!LDZxI==Y7yT<=9#)+5u4y^xbv_>1lHZ2i9 zT+v06jEV3ubqTF-DZ+&>KID7zn8YGH4%vgE#E*yh8h&XY6#CZD=vqxIIP-(F$|uo} z&X*{&TAwv~XtGa+Q(>qR3ZqYX*v|W?zT9ah&o03fc49e9WJNeeK46Etda(NFYiK)e zA~bw&An^MHj7;c9au%bh?fe);Ztx0 z`R`9dMfq{^o0}-Hs0l~b=jCGEz-5Rxj~9yCAK>k)&#^E)nzY|pQ+<{!W%8LEO@<=- z?Dh?Y-T42ZYbCaarQ(~+9U6Hii^4+&!1$;w934tnVfAMA%!*d+VGRS7(XN*~G&Xr*bLYhvm35aCcDqpfRn@RP z^$Hy~j&B8Dl5{?GX9sOMO7wlJ31v*FCYiCz+1JeJFkCej#>d^UBji5nM;#}x zM_v?ZGXlmPPr<>vKRecT3;UJR747nPj2g;kWnZhoXh(BWd^?rQwj6|Q+z)h|l-mlv zWT|{MTz}fTBpBjjC4REkK+@$aLjCl^wAMxgm-+Pe)eaSsj@K3=^G%reS%DCL$5%Mn z`7O^w4#tw9&q#mjb^7-62c^FnMY60T`*!m-4AbOb{5u}$DpT;oUy;TxeoT?y?!oAO zIP8Chu;XX?u|^p$v~SP#7ahjuNOr*Jq99UsJVYI0c3o0ncW)yG ze=-$6ol`|pQ#;}3BpF(_TNzihY-ml%LW!l>5oAWEh@VqNA)$?uQ2c5)O`7@wKHUnb zO|XQ%Eu2j0zV}GZY7MJbG=<^mV=!?IM0$ude#YCTzs6t^u#gm84n_K^6rvu;o2i79Vf6VtuAb=i~a*aZSOXZ+!iINk#JX&O+nZ{j_m^ zDz5HPqV=!MC6;H-Afslg_@%5n61EKzN~W}>sgsScO#M9>-d{^!N1vh{apOt8-jMzD zQHGIxADEO_AtNLZzbe9MlI2s{Hl_;8`F=moH zseRo<9nY?S&4<^pxOlM@e1Btve}6w)u0Ne6{utzcQv4F;jO5tYLem6I3P>J|O20?6 zajm<=N^2uBHcb(~PLxN&wL8MOc9rCPUk%HC7m%@B9(}o3NIR^~k;3DVtRZ(DjBJ!( z(sBuzsz&(zG>0Z1>rXKqc-(q~^LgsC61Pqy)9V||erC|Taz z4x97)V3AYO3celE`MCacGJ9a)uczYIj$e>mHd|ADY2TWj|@9+ z@#|+E18JrT=bx;k>0a;P`!1JE_@3~EoM?MdJSkqZX20$y!f5bAn4%7uq2JNiIG?5t zlTggNTo^7I1=|;k*x9G%#`StEudyQ2F>>_zh$U?w=tWA0BUz)iI*b+`=P@de8`O=^WF$l0PhL{&QB4?H zt$^*yz3lw@vm_g1fDRwdLu0>ykg<&zr#70j3ip!rkBP8Zd>3m$Hy7FEa zD04^rHbxUEHmPp1CwkJRCqHrh$y3^7)>UHl=Lpi5&lkV9dxOOA^}>b4`)StD-tfC_ zMQu0a(PxJwO1o=7$~(5QKav|Tib{j&nPg-|Y({f8M$=ccrMSR5FsS(qTh(W*%ruAO zTwlR_t_d{qYY{3Fig7!7k@h!LvQ--j8?iGiI{mFDmKLXHO6B8`phUNO5e94t6~EQZ zM#{J$ZgOYW(dHa|+{m9vo8BIjSPwgkbmIc?dto6GFRv3W_UT5mOB1o8v=g=4Glf27 zZKbrik)#r;!kX5&!st*COq(>2t4SYt(M|F`1v`Z5;kdZto&#h$-U_g^V(mVFIMa*!S)W3Z>LTH?@;;i|?<@R|WmEf`m+6!7J4*c-OsXsN zSo6Vn7~NipwtXKXdt0CWGQBcrR+bATm|DPK#2nZ-E3=AGrX(Nx5*Cx)p>Z@4VP4xY z{(=VS`Me|hZhK+L{xeZ=}_3P>8vge&)TXx`x}tlY0bX21QYZrgcE4XP!z=^3o0wlj==`k?J9 z73Amz_m`oa-m;s-NQa4m(!oy*WTQGl@K#k}`{NPquPav0nd z)}`t&FH~*?UygLXzxumq28s3%vA#GQDX;zA6rcFg*7qlI%W@cPb#Io~^ty{3YPZB6 ztHY5L^jN4o;7to`L$E5-mCP;fQk|+gr5Xg0`tUrG3Aqeo)5Sbzx)C`E9sA3UKS6V^ zkEF!IUT9O61M89U?DFP1Qg|7Ij-CzBI8}=9J+_$e*^%13ZY0M^g|JS(0rSwwt>F6` z$Nu{t$*V#ny1)1gkk|zA$CzxS8s2qN`f#0s4sOS-A1M@MGDTt&)CJoQ?Gu0Mjzm&< zKjHe81X`GS0;}V>ug~C2`WSegQgY^zhO0BlTByO8EkoPS47tWy{bk?9()_swl(ex6 z+H5=otLM4ws;M<8M(#q#%R8Y_auX3FpJ3wFm1Nj)EIBQC59=ilVD9}lhaqi$*(sfm z>rc=AB1D5i@yDk(NFDIdO}X(11^as8_T{e>^r}>1b9*wjk6$4E%=1FB`~czR)O=d3 zIS^|?H&RERbo%i7Ii+;jLYfXXBztlbjHmG#d5(RNo95nMZoNA#Xc?5fVCTTl4W8R zeehdI$)}!@mNCEE@%jzp&EaS_dkJ=$J?by7^OzPTy`>bhuF(H65LPNW?7CzgDb?J7 zW${^PT+l~kZaF3uo+aZ%RqB+~2i9!|!d%&)6@0s;^Kt#@h1J8Yt-sh{)q>RQ6K-l| zCKS?GiaY-C6tcxyV!N~x(ss6p4G;8@yunDQZW~EHpUz|5@;hX8dIP<$8%xQ9xfhc1 zOp^O-3FBQEXqR4vo!Mpm<#%?aC0*($<F%zNE(w*E zddFh1RP63<#cnYX=?(=!IwceoMO5qn5gQa^V|RD!nVj?N|J~Ui&-1(B?z>>jImcY@ zd}9ooN3Qg8ZUJRnyG80>a!ERFCk)OVgvpI5D7BN}WPJ2!aq}?BVm*@D3lm`FG{FCA z@I_K^FopHbT&T3%W_@^#nD}HM8OzsG&*N3FZn^`ra-DzI;6G|r<>K*ma`a^h0xWEp zx8X%({rhXZ8r#2|3uu4%oR(c|#KuVlEGBtJ zFCGR_#uQ1?c;ZVkc7VaF8xX0hqO>xHley$iOJ}Onj%}l$-7N!_N7wpa`}LRPkrlWq@F&ec=7QFMI|mwQW#xK=TIy4`F-Pe6&0IK%W&59TvR@Ku#r81D@d<=hQ93Lhj`F`@8b?YdUa*y5F+h6I@RWc<@!cLu1=4gBfUiXB^4@#;y&6o2z3ZWW)V_|%Dl{fB+X zeEBT!XS)(IOZNtJl)R?Z28R%u)j|#%66yJ)*bcy@^lM!*=lvsQeR;l$dx-8LLlb4^7BJ|1YfVe!%p3 zS9<Wqx=}L&e>QEwj%s;cqhb;zLH;UHX(CsX5g=- zFOYe+F5q7JH(C>shRxd2!Z8-^~v(tv;G7rHpWGzIGwz3|&I!<2a0j<7h zO1VrILCfqJEEN0u-}1L1a^ydSAt4JYB|7yU4*gF*R z{yR3uz96S_o9Wr0b+paxDd}d;B6-jAFwCxkseUZVgFHC-`~V7>H-z%a>Y>>&4CdLc z{$I+??izw9P78E*6L75@K>Pa>6? zQ?RRMweU9r(&lWyG~XDq3M;2xlZs)rzZ9lZ=XU{LjaYn6jDI?8p3?tDRN(LIWMp?g z#_Pzgp`8j6sq%Reg0%B@RNe(1ZkKZ5B2YO?oXy($7$DT*-l?Arx=d&J{o{L`6N4FBn$0{`@S&SKI2ysqtgN^VF% zM`;Kpr#uiGmVCf=j|WT(I2l=o%mSXRPNR)()d+j9PCZGBo}9WxTcy;=V9^0mRGJPW zxlu5!04h41IYqA-w9(Iv3S}#yX(SJ`VMqM$tz1Q_-#)>9jVn}ssbXu638u%&kj=~U z2Gg7J zsGL2KQ#?+zsojGLFFk?A%||eO;L0={>Pam-4E9WpOjY_8wz-|d43B)WGx%;XNB^388fsh=^0 z9_mR&S^Cgmv$3X2i~S!)7?3*lp_|75sHzOcw#G!vcvMaH11^wX<3U(iCquNiD|gU7 zvG|-jIr`-<{ABzD3Hjy7zEZ;*Y%QfUwePsEQbwttUkZ*ReUaguAxMl~gB`=i1iaah zLz~@_5I%eixmB;H$9_{NwZ(vpd;cM&8y{h`L3j}>i5{XsmsCHX;BcNx;hKEuq6cm;GVI}DgQRK^i&+vc5IQzxpV;t4B zc?jPWPeEeTTV#J%<_#N$QCizj+`sNlX~$m+jx3*@-WtsGbbYWRtRUcBgd1&s9E9-3 z0&;IlrALPbQR-YXGU;`Ol$lO~QQBCTO+JQQlDVAnsM!=YI*Cdg2SUTR1ETn^{!ikF zG{Qfi+vCqrWphXA&kQhY@Cb4!c|?#6fMv%Lh$eO=PgN%#ALF0y$V&K{TeAOu6LQS1 z^G1(jXzPwoc#!Q#TVt;XjxQb{eQk&!@j)9q_7ntsNQ$Sh^g)R5>mZL`7WAms0!o#? zK_Zq{R#EYSQC$wqV$`uKu8>o{KAyH%w^7Nv7O3CRg~*`8|Cw?gY1%f!!JFwfbbEq~ zl^&R_s7{Vom5H7fB(S}O*^@n=4B20=V`9F_cMVd`(;Se(hsvZKiODJPD>sxmEeUJkB z4TNQu9z;rRUBFi_79Wdr1>HSQ;S=B_NCvbcXMPPY^2?!gdtE%T)S-0aaKS0G728fL z2$G2ktbSh*@TF=CZTa#Ck#>Ek*MK|p(8G;V2HB9A<`Yt--Ykde0JB@3*j-@Gsay%C z@Drg_wlW6l6KY`MG{yg={2S5=mV-lED^vp(VtaHl=EQxY?%i~WUsMRoH7rl^@c;T9 z{)2x9#pCPb-@S?OzIIoTOwLD6aszJ~975@@Gw|qMGo|0ZCpevtW_^GQ1WD#qnC+Pw z@Qw9vgqP+bGCQ2SS6b17+BQo5_>9bDZAtaIJdDkk!dy}g)lRvbYX5ZJkGjF8KuhvXFb*@r`RY+IgCK|RMUVTtt%;l>ElFc z-X)*BRC?f=N6C3^Wd1FL)E4HzIPeh6ZA(#IpTnshjit!RLA3MD4yfHMgR%Eh|JQ$~ zl6K{DIL=gr>O@y$rry9jiwo3qQymG%7Q)iw3{19nxJs3yz=9{8dHZMqRn2nrY19^+z zgD8^@;>j-;%Iu~mI9D*;^#Lk^)LHh8+5INqul#U|+*^&P-(KYR&5Z8%WP2?Cge>p& zA@y8G7{~U9`JzFnxoXd;rHLr&r!iHG(SX{hu`uFJ_`mz$LprZ`I6jPm>e^Ar+6n}> zOd;3nZPeE=7#1Jz!(_;!f7jqYIC?}pKE_eKOegg6E)=9%RwCC-mA7&kOIfnZ@U+C6 zGN1JnoIh0WgKC7miFtE+cNqn84VccsES zIU0MWbZ}~)`&0C}8mg45ftq$P3{U0wf0%cPbmMj5WWElnG5fJYs}%D~)L9Oo2L%Q7 zgvGT8ma9G61$>=6{_hyBM<+)cE#Y-zz94O!j@*D?-g@>&%DN!Jvq3y%mE{ZF*}a*T zI8l(EaRb>uOL@t{NQzb)faoU=2}3gJUiayg6uN?}&o+?8wT&>od=ut-eqzs?U`~Cs zD#dKyPL*{#q1s9?3|i~|@!lEIb8?5%lwnZK_=O$GyRcxbJ9*guq<*VigR$cFr}bnllip z>91jM$<+Vz=!>M+!hHYo<)K>Qh-|euEF5S+o`ZdS+|E*4); z#y@?_)9}(JLHdvqa>Kv!w%6}a_7pEX&+bjx_Fh8wD+7>vbE_aDsfL_>?|A96S1D%R zImEPFr-1x-bl1_C5`Ru7+v*_FQn!JL{w$b(h(@iN2B)FxPjOz8X_uh}RM~8m!I*Ua zFXwAXf8jwmJ=g)&Jp!`hCt;CM4tXtkOam_eg2jqste31SJ;x`+<752OAG!pdHD!W~ z;w0pj+VJ+8Jt>F1gI)+>l>Pj&(8DMmsbLm^%#gFlSz5u%+?J$R{eH|lZzl0)|58V} zCMDMUkzLU%(yI1>iBAPAGz(Ch*PYW?@si@1!SSw^xlpxab-D*S{%l&D4Akzz*^Yff z8v3(3m^KzY4yIno4`|?T6IhH2gmF>l-6*b>b5cA$#y|ayGVmNUPLLUU0=Z}3@ZAO( zQqHHtc=1Mpa;n0G9y1D&>XahLE|y|X=QB@4ISPC^jyh~lQ{wWsWWT+M zw1@73$)s1X=~u%&)8V{BY!>An55vpt8!2~* zp3tKz2`TM4g3Rj`$T=zS^74x)Zs}dbnSQ3;YQyQDVmFr0I!4_R+DZGPGfXx+!(z~C z>^rT%X?liGLRkw{_nHQk{pQg7W$gdcN|OwSd%$`BSg2ldL9Q&YWa((~X}U~9MqGo1 z&UhG4=t_)wS}Z=7PX4vugGWT6AoH~zdGbSf$8)um7oU$;{87qtyCn4ZJRB(z4+UAj zVC1~C<`vAUDBjEjafyl4r{`Sy$6_iaJby$ETl7gM-5w^z^I;L}j{RdAInDH2l(=Ry zRlhZbO6XDO#VPv#N;4qCPgQXK+YPEWOp(hpb(Xp@Ev5URG<4HYn176iu~%2}RGqny z|Gqz682=39?BQW?Sdi^I0C~30cxRtjyst-up8l_p;vT`YELR{`XF9Lw z-J9ZDnEur7TIxG2o$llgqJ$C$a$FNiy53u1(zp{Ak=?NW)m%>V%SlS=w}xs;rJyn> z6?(=Y{(q!EMj2Ppz5jlwc4#0^$_7h6gtJ&-9u2EF#qQqGFxFvJ-v5t(|6`2P`5hIr z28^QyZe!qnBtwu*e}lX}CVcmSd#J#s5w9~MDZfEU=ovW~$&dC5vbWNZOA@@&NN-9A z`HT1ky(nmD1>G_F$#Tx@owP`ebpHv3$&352C>V{p%`Z5u(J7Q{w43%!ngtc(0_g5K z<^Oj{AsPEtp?k(Vs6JwAuz4Dm?G_QKCeiS=voNn&0;6|p|6POs_=Yr!$HzEoFm(~! z$H@t@PYRGX^9A1{IfDv5Jj5IR8Wn^-6?$GQM{@dFL9SaPa_9Wum6t?QqTLq6-;$+% z$>ZsE#zIOk$|L6)heANnB9i-^5adEMkefP$S4niG#5QFl^!29xyH3+>?GlP_ zwWaRk!b#t5C`2v;VbL}T2ddLJZT)GKa-@m&Ug{3z!vvjnfh4Uzkx7IVdU&xs-0Nw` zXZkKHjC_c5`9q_+#lk%JG>nRub^+fx@%TD9dT21*64wZFk#5K4rzkib=LcL^bhYg>m3zOI)Hb*cTmyQd4fx68Io#W z3-ZjLGWVGbuXZ7ml6#gS(L9L;vij*Qu4TqaZv7D?_A-AI4_!*ZzRH#akGSS;Mo~BJ}1bJIY)|*Pad(A*9>28U4FN3H!BUEsC!*o@GNsynj5P8~DdG)tr zD7oV=5)-UxFuN~rMu{k1@fx}K_8~*_-w zSdXOpj3Lw2W$5X$5UQU?pin*>t88K^aO!#*TPz8)U#wryr85U5F2-pQi;sP21w-b| z<2vWJAiwfA^1h3Bk6#0*`29SgcRuE?k7!4M!NMcBP;3f_Qw4e})U5!d2nEAb(Z?`MO!W zSHHJZdZh&)oK{n*S-s%8VH^_MR|pDnCy_T_o!9bwNvVEmNSgf*4fTm&ew?o%p?W84lGv;&fVNnY~CE)y-~(()D_1-EtwBy=%$r>@M`|cm~z49w^cf zVf8v+>b?FRjsM1STzmXs_|mQm`*%@1KE^*o*6Z$4aZymvvp~MfLB3aJFDfhEfe+_; zQ0aqTg6ru*Bqmo23ZoN{mobUgo_LZ{UzQ{3T0RXM?M64gTT|S`5ONpwBx5I8n98`o zatepTgZgp0mT{C`=|%^PPD80u0a~j@lkD7aWWMM-T)f!%{5pvBmAPV#wJG&s{Yw)q zpTaE81%^$XXH(qyyd)l9C;!frz-7>EL1A_f@&~Qqy0;!a`pWBU`A%s&WRc7%((t9D=*9}x`(PVK9@_e3d}jqr?Sf#rd?yaS2<3Da zizs8m6*_R?IrHpb{?6K~NzPQ8EcCy@B}I;%&*vyMnu;~&r&Hgp2WS%WA2pjb42C8D zm#6w4W1P!k*TB7#qwnvd=R0FTp>93$=icId{f<#NoB#dz*M)Y@lN8*BHz85_nxODy zF7n>p;&rPMX>0#vrg^!9M#MYQ^|u2l_T3BeRCq}yi8e50`c#%t1FV5bPUyM+k-wh#47g11dF-;CR05j;paPxvL>~SZL z|2qb7XB;&$l|#?eXhBi#DDt=5aO3sSK}o zJ&d;ga6yW}bsAZkOV@+@QS6~c^88aqBJL$j7tUt+?(sNcH;mJhdrX;D&UDbz0ZL9u z&>ZSZ@=*uLazQy<`!avhPw!D;yA5mgdQiWzZZxG-3uXpWVK|9JCt}a=Rq^;3M~(Vx zqo?~4L2-;K@^j;O|0hqW;*$eDd;X&GcjpARd$W)ba$8VL&qn@$CA@*;b=p?`4^qN^ z(Wv8tsqHaQ?3N<(`V>f_PZ}^yUI5Fg3LH86h|?PpOPQZL=-|tJP?BcahwuDI!FM@X z83e(#i0O5I+>DZ4BeC{i5cS_JPgAdMgX#M@F!buYKgDtMns|JSqeiO~(4(zNP%H~Z ze*Hf@Xf;(f3HaQ4mn!zV3GQ|hNbocj6rbEgeu#)S>>fku<4Tb7?lXiPFqxKKfN3qmcXSYr&hg^(3IZvsDT)pi+=b$;H_%8KObTy$lhqknxJfX4?{A~j zJs9i8|D^%7_B8EpB}|(QVW@e!3;0^a;`3nqGb(t39;++_#jn?pfAt2>WmHqujs|>L zv7RbJjtlM!LlFPrwV>qXjQlcr-e_VrWhib$D$`CG^TCl?Z#z(|rapP!l_#^YOJRC_ z4lFPA#W97xoZh=}v}1=A9UeOoihGYi!_9;g^9{***+aNZ`psfEEvAS44(oo&(ZITF zn&Es1riCFecsaET_}awd>*U{sO7zfe5R`)YA^+7nKHx(f?OHSxU-cBJibe?TwXAQp zMoUnN%0PabBX1n9P8kRNSf7bE)Auc**3msErY(qkTCK=jVI!MInE=bXJ8-N*ozoAH zqU?p0)S&hQim}(B-Zq4khJGa*i%_^Vm_qeUFO&to!1^2w8dM)oGbbKny%Gmta5|t1 z_&RkS|NDON=;Yt`ap=D9t)R5M1qHI_`M@Enw3}x%d{T`Msxb9BPoZ|r-rl4 zS7gQ_sIRdkWr;sz!#p9~jmn|=Y8uMU|G)Q^zD-b}T}?592WN_Sr@n%+{azHfYVo4CT9j$9pJ`dm zpb6f8>Ds{66f;qQ{Ek$S1nF?VLmKQnOrZ8fL=(1UWdrqPj&d!Xpo2zBGLq+BzM zY&RRiJtPvUFY>T+L>)GCnA4C0!)SH`>s9L30D~2sGpFM2mv*uEJQ@Ftht7xd$4i2; z_g55nt>XKr%2D;RiTL*0hIS`<3LcRk731Pwv%3OID@c6%Bx#ON8hi20{c^&@r6`X1IX^71U$T&q58B8<FgN$rmx^n_{* z!vs&wT*L)W5mbzoP;j)Fw@7$MJM6At>*LWhd83G~9KBD`AMHTLDwxlBOEASLjgia9fC~ z@}U2xE8mdY;_-EI^y+XpwapS#oU~D}shaQaxq|l2IgKA3!>OjDQScn&jyQ)tf(o0B zE_frsTb@Z}b5uEO&hsEm*?NSo_#B|+hlZ{O^>2})Dgejm~8g8!(9C{tOnl0=}S8}!vjaD@aG9S(LNFili4ip*N3Ejd>}bg z#lf?-gyH*$$_)_+ZSO{-(t6Xv*S8>YDujMYXP#f&{&m(1#NcE6GZ`@hj{83fs-~GJ zI5V9eyyyw-dlrLVr<17G#ai&Pb4Tm~X+d?$3KXuNz}v34K{=1Lk)E-hrne2COVt$= z)!;{gv!;>l{5>#tErQip3!GW?gfmh!rlOY7baLAVDEOE_CFeP51ecNHluhu`e8~8B z6;;x#zt?d#jgFo`i!J>il1zgB0;MkCyDJ_aST2Ngag@QYV{E%DIY5!4G z{9bsTYQOInycP^Vth1k>TGNce%D=qbo zOG`!{hRJmc=nJE}fbX7Ie7zX|Om=>R!hVw%d`RJk^^Kvrv?Tm7F{OQ{bp@|I zJYwFQ7SyDAq40JcZ~rcg@&ekBv9v$U{JoPdme)~~TRrs-+D3LAF)&~K1Xc_EarW#l z&Zs`0N){}j)5b?3|9%XVU%8Ox5jk=?TMVz3Yb*xH#4hy;Y`*$}#xAj^rE#oQQt=%6 z#+_$V-1)pO9$zQ_u5E)u)MY_UGaQ8q7y03J6Y0P_9sIf6oAxKC2wq=|5mU2GP#bXs zMat`Vhn~|Z@9ihn!#RiPa}A@5cHR{EY!3DDUd`%pH89T#fz@g&G%h~E85=N#ao_uN z`f&i{TUwds=4jHIC6M#l67=den&pWLuxr~agxSrbaWiCT8PoPO+4LQH9~8QP?}2!H zo&5VFf`jQLL2de06q;V;N7~+`dgh7sH|7o1P5vhI@@YlPvS>lAWCDtO2k?$db16UP z7Pb#)ra9JU=t7AuMQ)FwzTMiX+X$AfKOzOI&_XmBeBg{XtfVrfXLP1k9`ZY#q3rjF zv{l-ud-r?j6~W%X??bWMr~_f^>uCHa4_f|d6ih}rL$7gr7w|n4kB{+BWY07s_OtU> zyBme>`TVF%2|B19%1Kyy(g9~Pq1UEGh;dgG)V^w>Xuc)yw9k_Y1~7fJL%nFOw-sHm z8cdNvJ``kF!~Erj!2E6)tYVI!>0~-*{LqrhZf>Nrp(h|8ro{Z#6-c}GGqbmu&euNLeNH9+3g%mx;=zm_W$*w{EsotBe84X%{VF=-hpld_Y3MW*HGBs zhaaPInGQaa;3PJ6(1D-oLa$TL5&c;Z)Pp)ul=X{u{??5OzF$RVw@ox}&}(Wbct#Ol z!>FIa4{~UfhlS)B2Gw5@ zsP0yaE#3OlM88qAYDzea{{VVRCv;(tAB)GwI4atp2m6QGg8FD_6izAP$A$&bp@yNH zM8^)QKNli+D+q|Lixt$fPNAr|jql;Vh6>BZA~VyQf~U`-7V{?*QNmHbuQkkH{2eT; zr?VNkM`+eJ;Y{}Ir1F(M)Fi5hyz3+=v3N-5PYv}PDgp0Q=HV@M2-SPFuqAXFP3rLv z({p(Z&tFOv3JlD@%R`=MP(kWhuuR^XWo&8EAH~+z6aCc7)QtK+ZXqY%y|CzW5>|yj(R|_y zClalr3Vt*-z0-!gq7L(*^&s8C+vFm*4c;%VK}{(PHNFPe(%zFMTRo;V&0}C(dKr46 zJzc=}R6M>;j$UDYnaZmK^>1M)jCspXSmr?uv(h=q!UQ@rUrX>#&PH^v!-57~N3p{i z-lfHciY0#_Yi$NCh)yv`E3pJKXz@0nP9KArsg z$^3V+CkYz;t}-pIc7EckN;={z#Yri4r^6@_yjwF7^+Qw8NRdYIcpu(PcMBC)OC#&$ zIa-)Mk(%>|Q~36|H1N0?Iq!c0i#T>Z_YOvjK?`Rp`;{theWvE((U7a%07b5p^qx19 z>k2>kWUwAN(G2FPa17zm*J!F5N9$ZeU_7LV>6k@z0pD}+_!$38t)Iiragd;~!wH48 z+5F_WEp$|)mXlg`i21-x6MPI-BkFL7pz$yW#WAmV_o+Ut#uI@Zlcv(5eIuyZ{40ff z6w;uo0n~k^F)Vf!!0KQIT27zhOt)xLRp}x+A2|wgQNd7n8$BgoC69zLwUQO!OH zd)mJt{C*=%lTo4dGqYf99Rb~fuHbti9v|bM>EI05){hi4UL~Wj$)BI{B$JLlS;I-) z?LiH1MS{;n4@9lsCun+2fwJdlHx$*s>kY`E;-3OD~y(Y$PN2s~K!QL4ai11CPX+Lsl z!?s2keSZzzRh@M;DIZcaHPZW^2*020u=E@IQ2Q{t3wFTf{B=PyX*CMp+ws$%deZTfr=0XjEjn7}A^1ETfyh4-1h6x1?b_lWn0X~wH++VqLl`AfZ^YtfZF)obzi zI{DZ9j%h0V5H#<7N0IDGerB)?otQJ3lkwK1W098yU)x$l9y1ZNocp7s?;YNI`)1my zn2Q{TQd%xkM@@DYC~UnQ4IA}egZDHhHw_&cG8|HhIGaI0%Ye@LSF9x8IPV%Ud+4R zuW=OABIaYi#YjXc-J#j{e$eKltXA&m1)bc^JioX*=$%-6evG4LeOzI6OC)Hu9Ys;V zOMdRJ#dPYa9Vc5ohfenN7JT1nBH|D8m$f;ClIse*fAS%!U}rctVI8gNtw?99qiM6u z9vZ0{LT<;I{#&*bte#%OmGF_AWp)YewG-&7H#@`bzaiH&m5jfQpyHhD_)HoPPyD&ZTPhG(GUOYa=QM1L0u$p*W(6*b0qETP?;D~2*x?wIS z=NwO`w95rQ*LR3Gk|$`dIg3&`S)QI)QN_M!bUB$g|p(u(B8L8=$h99$Vy2-F2tWqvKCUWi$(CCyZ~yua#82s15uX*n%l97 z!d_2=;q4&k3{33;z7OK@G5(oloPgy$dqF$I6h-sC@e4GS=uGloPOfq^o%;Mo@LRbX z5$o;<+UFmj)N=&S`8}Y@DLarCx{21TETA)c6DU;mH1qAyB#*wYSRJPVR-gLf>N6$I z>OmRR9>}Iv_oFhUrz}9b6rSuJXzuYJ!*_O_@4Wdm>b7=Ij8RV(R;y1~;u==qX*LJ+;ti#sPzD?(- z&Dnr?KR$$PyE=*3+r`Ig6#PHFVY4i6abSW6qH|m+xML^N>%I!ZxPj3AC3FE_=NbNQ zeEyyMd)5Yv7gq%x6Q=i@@|Iuh1ZwoO=H!bm)0us91-~C>5&oq?&{;MOr5RUw{>?0^ zVzY1gAriE<@*m&oGJ?*c z5EPZX;FmNEq$aufoPuc#olPDs`1_k9ytYZuIdcZ3P2YK;pCj#>o`C!>2Wef?LOSh6 zv|(C0jg9(7Uf~_E5)Q*!-Vkl_pE;X@22`hEOE)wkAmf$|S+~z*W_6o<3jm7R33a9? zRv)qsG0VTvf_qIAF;)?VKC_@*`LzrC_eDHD#y@lK#W4TgOVBw!8bt@6^UDT(qo(UR zoI++hHO_w`_-`7^bTTsqUBf_>{+Pn|E(xODYBx}@av`mMVnnC*&ZqUEN;Gc1EA`^O zz-smoSgUS9+i?+RJEDN<+Q-n1zpEhq_ZejF_b0Q)apX686zDRWb+meqg9;UhdEi0| zADU6br&v}8FM@V>V;Assu7Q~I$@phJEg9yalLcKZe-vGK%P+sr)438!PEogwn)>Pq z{wEeA+&Nv)U2qd+j=%Z7Qpafb;gu-(w2d~(_|hpC4O*8sj>Zq#MZJEFgjG~4taX%e zJ>)QF`=*5sk>$}Bts@~2bs@LB!A^efZ;-@QvwcV^hNBjhqUPN6N*d;V*2V9 z(4HLeFTVdV#`z|84Ty2nJSK%{4s8*1XEIIo2NL|sRrb`p><6cqx`NJG>=#IS7Ph=p z5_FG8p={CxK4@ApRnHxR!sSi0iRn(AtahNa$LeT8kJ;p1mk6u!{;)Qx!wvUV&MtN% z)z7V`o458tI!ggEe#&H_v4#AZ4;ZF}Lw&p+4q3BW%E_m+_*o=Hb=QW$30-LS>Pjy8 zyLfz^9Nn`LW{LX+-MVfl`eMqjR@q7Cah6k3FQIck69nq*jV(Ld1wEZ1C`)SQ`<*yU zHM&z#_)(ui&3)*k(_sp^KZz!4j3J-J9$`5&s_rP z=Nwto^&ncoG(pPMpw9FT4%KW&oJTq>d2xcG&g;M+vj?;_JA2~A#W+923mh4Kuw#l#imKnYhb=kpB(vtks{i&*cwIex6@|-V|2pSht}A!ez!|a zfB_T>uu%8c8%e{hL)fg1JzTns0ET#)N6`XPc!x<4G zK=A{@9(@q>H3&Ox!}vijM$=xC{wQAZfHt>Gq~nDSw7SnKn!KCHFF}v_Q%AtsYY1-j zoX0sxWz*r9+4Rrmcu2LMhtzvRvMQG*E-4kXB~?BPUbhPT1XdXp5jzA@6d%Q&H@Gq2rG^h^k)WR z=h$cbkRdNtj#Op~8Y1hDA}w zf>ubC+dwMsDOnGBMgf5_;7$ZU{aq3oTIV7`#er75{zrA6_H67a?Oe>f5q^WZw$^X?MST8vN>%Jn~J`m42j#)-W3=8P)_yv$+-+HMbbIAJ3 zMGE*@g8B#-Pbg%zzNcGzW$-m3VCRc*^%GC(y7Y+@V zKREKJ5eZCFc-8yC6t{W+(D^v*t%cpQU|Q15moSmcr%c($V-RS{}jb#%5N8 zz6W5vm&I^nd*GkmI-JvKH9A^;kna0;K+5nQB&*+%ZSNEcocs;}Y<5dy#7-Ptump+A zKGW)tiA?uP0s8Ulp{3TDV-s_KN=u5z*U7(EelRW$5e)h+MRC>=e)F$&bY)c?r`EeS zUB3E4;D!vw=90&PL7f50Em!a(Kc1!in?9oSZC?uCnomb%n`v3(Fq-~dn(%2Jtgq$5 zdRhQF)cSJHTjtQQrM2|H-2##?-avBd9kPABiUh4C2)HBwoe6Z!wOvl=wAZ9JSPzfw9?X!65S-imTK3u#5ZHyIq4*yS16F)I#8r zrLcKUu3)Hi66GUVvk~M8Kv-}(d3~+>vZckXR*oM0$8C(x-8#*Bw zLXYevAeqSgNzd#id$OY5AxhwfRY2qLMI8Hi3rYXv)7r0W9_^74^i8v%S=9M|i^JFX zoBzhgIwu9osoi0u`Cc%j?I^xAl@DJzkFFiI<}}of)3w#HLV%_kLSHWv4EIe(d3^yt z&hHf+h-t&l;6)Va_n8_NZKTD)%`_{tkODrJ!p5Tm)*Bz<-tq>n$HPK8aV~%!+gyX> zH0DnlQcm_y1?uB88+=L!H15vA@r^r~7p6O{`zA$+8(u)~M+!7IyL16x=WLP~e2k-( zktr~YZWatvG}w1fgOBL`d*W< z^JySOo-3lmj}OqIF^6dO=tacmo4{st2&`jDaX&DQ>v^a*uh-S^%YyRBz+y|v7R~2$z8dFH#~z=LNVoa@?BI&H2-&)mWwaodpo_Bu%pk0mLnPXhu6wLx>hADomt#{B9R z(8eFrD7h~Wy~J$s*L5mR}A1TSuvC+o5N(5E^Ihb^)KVczle1 zR>2a`vjm8yUF84Gf$Vc-%} zUaO&4?UhttrcZMYU7+~^E!2n2eAyaogLUg)Jn8+J^E8N{M!)OyDqs>MY;Mr6*WbuF zzK#Z{I70Ae``2+Br=?wyR_sihLoZWmDf42H)`dppn1Av8k1>vl*fj`b9JNYX1lDTxv)ZJq}4LGa~ zVbxt|Nyp)Igdw(?9j7pwUVt<(3dQR2my9yakhe3s5=#6+e4g8yzVcjjAgrD9&jS9Y`#p zSt)O5!5u5=+q4R{V|T&&!(Kf7>&SV%bEc-|3G~K)Ed5Q0qn~G=QulvO(7?H`AXFcL zmc0?q$hTqZj@=X%9z$uZ!=Zc34jLhy-w$!$5H<1mIyrjtK6LW_3ML_eC^-_($3GlF zx8;gCy`7*tv*!zeNkg!q$6-OFagv!Rl{Je>i>FAeM?7G^A;(M>Ax)ljDV}>RzTDq3{v3iv4_7$+v zdW+}B#&F*4@zgw~2fg##On=UW(~sOp>go7{2A$ZA-ln&q#l9hD)wQr~+dA43qet5$ zZ$fu{F*JnE9EQ04(-4bKVEnVTYJ_%#ryw%3LCG6SK5<6~-I@P|Gtf4nj_&$`pc;$y zUM_-&y|XGmo#KOU=g_gdJ=i@Wo#L;~qWw>v)AYXbwAjas`sM6ny&=6|W37xAh3cG7 zn+u&64P%}&9rR~bA^lJ|PCc*M)8K{P=sk+%Yql=I*|a%G*FHnx$_2D7(*e2@c0^*~C6Xo7-}@$PZ#-jh_zk>_jOBdWj??*v9DU#u z=#NAKeP0IFGr-XhgURR}J0DsHUZT;!8R@AF6rNZ_={;MZ>+=vAs!d(kKP~b282_vn znn7#sM?rL^7fQ`u^2wuF-t1BoXBf4Z?tXnO2yuO}&Zk;1ojwFr17GnAJJjj;yCtX| z^N?525$bc4*y}Kx58rWN5yk2rZ^p-qaVmMk}EHc4imwX^Y3l_-CDx4$a$}1yh4j zDE02kr?@|(j?JZdrSY3+z$)g~r!Nni3DI~x@*3xV`zc*mw3a>%2%_IT-RWCzfm~0Uu-=wk=>1_l zw0`HK$;Jp7DRvZ*p~Cd$YoYVQ0_s=HyMRweEWX~I{M-K=nuE6srt>$VboduORmX(x zy4!O`e=pGe6L*B(3gKAm9U+*h-9c61IDX0F<8+dngqkTmC`m~~wN*tl>AoQ?8*-lp z8Z3gH=W5t2UWqqU%+bAmbkXf3eID|Kew~(~uS^rkjm_x}(_4l<*6*Qhb{tK+C9z#& z5=DyCDC4U$bZ#Dl`o6j@;L{b4uakebjG%Fx;XAq?r3=3Dsh_0i?h{SU__!NA*l8~G z?(+d5_0t8jSv;!Ff8&?UPo|Sk&!FbPdrI0~L$z!seq!TaTCU0Tr4Dhh8+92r;bwU2 z5WwMOZ@T#HB7GUNlzxr1qOS&ptqPP;)rUyYzIVZP*Ew}OVx&PJc85zwAK66cPzAX8n9qU>K&rj0vvvLv9sxwF^i z{~_(YMug{-7T`upx{Ofwoxji4}+|T{oZoIxBBYE>NjcTd0JEPMZ*c>`w`srWX z@vAM+VwX*nXZpZ9A3|+P+|lRi8#+#I23}Hn&w1?~0rw{4VfKesIC^z0WDm@M#fQYf z^VkKLHE1in!``D~d+wQQg@WcqkMsI=V&eS2R*zwBG+cFu=M{5xQN?nbn2Wg0!R4$CXbFzNbEnIo21}=`@z?&KT%(1pdohruH2r9y;5$*x{sQmEKclw3=D5qOo~n)5gqMy^ z88KK2rRpBIL{!gTn4W)DpM zst*g(UZdTXD=0rO5g%_}jS2ojaPYA;B+5KS1-=s~Gw$UO_>_3^*$wKidJjrftfXop z7xA3oK`u`FAiT@IK-89ufe+%ds4Y9!dmBHXYWK|WQr%O|cS~a4DgxU0P_s?p{_B@h10je?kAUt-IG`Fe4#1~+};Cy4r1_KAq1vGdx5j#UbKt7 zfC{6(68EzIj*3CAV=!sQq?XnP_TepLY|JDO-(q%+rOci|m zkW1}$s-c&`9LlaN@Urqt&fiD|%5He$Ro^H$9=8ZC3;qG8;B&A$RTG?iwxI6je$-yk zj=lHi6Gx|CP}A@N{{B1)KNpRLZ+}C;q9GC%#VkX+k2$C?PXwPRA||%JgF~C@AgQz# z<&QOyX2vKcn%IL^ZSqQ zf867Y<2eTQOrzS%o}t8cZK}SI-OrqU%q89#4e!@)Aeudr@VRC$wfo|Xp89@NW87i9 zyxfrsxU&_?`Q!1L-$yucbqZW;x&w0sN5WpQr7-`2C+eOrNA370*jJKCW=RmJUG9VY zT1C*iG#Wa4x4<+Nb#Q5wLwk#IR0uA|r<3|IsjMC%0&*a^y$I#E&cR_9tN$B=f7Ef* zc=IuhY6sY$`15O2J!2Q1D_Y7Woi~Jb`8`DIlLmZwGMU=zTjS2m8B}9e1zz@>$^{-$ zfbz5Tc%5GaVy2IVi!=FP_RSjDn;!`am^Y4YDa*pSegl8qcO!n5qe(t zL8oUDOe@j?*NDStzntyYP9Z)mHOJ(s^>A34gHt|VQQm1K4vQRoSIlbULHTyxwgDPsjUJ7^WJ5i0NN_hE{I~U}<3?4a-#Or~+ z5L2lP7xE9oEYEh>x2XpfDzG)&DvsLhexbkgGnw;B4C>x~LxBYi(6defzIGe|%a!Y3 z@%S>d4_t@}w+`Slr+t{5vmXwh91STF>L@?yG!EOYI|M!r-h6`^y?=|nCkdk(^OzS% z?^*8D9vAqqMULpyD#6#HI%=PK4Lvd|siyWmyj;}E1*^}3M;+_&hLAct_f3EcI_qJk z$$aotih+d%k*Fuo!m^7u;qOOB$UOV)P@nFJ0-sMocc&WvFW9U&7Ocs7AJ-M9t~8`V)T#231K&q7DNFIZ)`!jgTKXn*%ED*WA#m9DSwRE`@& zUa*1FCg)I|Pm#UX8Oj+$i#H$BpN@Deif%YTHTwMVyx}4%Y!@e+4(yy=dR0fQnkkN+ycDJSme&a90qDu*=x5N>3jAQWc%e`b_E(eVr zeJFH07=EN}gD=-!0(2LE+ubW@|I-*1XZc{&%v?-)cpQ%0tcNp;r=eVVHcJ0$7y_RT zZ$73!otZT#Vz`iMp0336ZWUar_FecqHklaI7Qy$c(bVCDCT`DqO0|MdV-~gNLS1&k z6aQs+Q~CtN#Yw>VmiJ)$B^dl#$AF8I2I~2&V%hH&gwI2oEVA-|mpRHP?8f-4zQPx^ zEWo4;Sh`vs9fprWMW0<*RVa+7mukaN>#=aA^B2lp*^kn%R}X=2@Hgn+^T)b+sLs|Y zC>(j8vhN+9-+6;elMjQ>r6Y)8Q#$;(8c7{0O>w(f7u9;X0JGNq;KFoH!c(nDc=PC0 zh}Wru^Ya#h4eP1$pV0s=J-blvgahh0=@P!4CB)^yH+bc>8ijwogzxnl@HxB~h^-4O z6H-72ttM1Vm&9s=-*~!vD;zBy1F2y#C>L`ZrAt;0flrS&-=O}Ec%e|24%Kp;i{}sK zaA)~`!55EcV$^yXy06MnM`>l;mb;B=PZ)(+q0hOn-c|6lTo(%zenI?ob2xW*Bv9LJ z;C~jtH9iydvRNHtCbmIN}ntGkMDonEZN^v-e+Lrm7Qi_(Q{Z|8!2i#6SPb`3 z?@18qZ2dt5_}s~ohBMIg+W|!9P%-=Ib-ccb7uruu__mSvJEN~HsCFFJxHiq4(X>)gY{Vs0$eC8ep88hA77x(o?0Ss zz?3ZAZ~NSU$3C)9_*Q}`H9Sz)S(nfWr zm19=Ne(unw6sXMaz*`rtLE@%MkS@0ch*Km4WWR$Y2WnAYbe<80E~mn2%235cmdr z2LAmUG=phWmwBBC_~%mXgi<_TXV0C#?E{_Tevt8s3DB1xO&$9WqkHB}s>Ax9uM8jH zA}s$x)$;3jd-5en{Idqm21Nn%pMyZj6X2#_i2Ca9QRnb^A{ebkR-9C1HNE*LuJ{qY zeQksfYvW*gGKH0Ddg$O8f+H?@V~xHYp0$yO=yisW9+QA_qcT|z(%_p#UhC7CHy_iV zuDL7nHy2XvPD?!h;WU?VnL_8|sl?n=0e;=(=!{7(&|Pyk)%o-pub9VhhldM8weW1b zeSZ`rMU_BW_Xw~$Sq_0~oxzRO)b!yjt2HJQp)s?`Dw_s)!}2)A3$o$c(PhwnBO2(8 zW>{HRfDZffa76nqtU0&<)A<@9`tyA_H{~wM{?$k6QM-r0XTqD0=}(vSRq}%()uH)# z{+A+`dFmE?+hs&1%x{GL3PNY>_=8)L9H}lHiC3Hncld1wbZy z{xS$;XNRTRWl?{zDeA=a5uwwaWR38Bc=MzmCDs(DnE^nRF!% z20B*K8SmS0^Pyu@_s1E$l5mAP643+CyZ>U5*IhWZUz zQ0G(+5zdJs>o2FkJLg*{St1CX`{bc5VK~^jIKk@Z3+NDi6-TCC#1|)+PoA?coY-#& z8TyRx$}E;Ae`*MP<9YK9>M!>c{7I6dy4+IC(AMBCF`vcnySm8aR(bf#KbFo^XIVUa zu~cssKVB(Z#~odD3~Cbg;T>@+IQ6Lm&J?ouVz(wh5X)9s?mPwcFQlSQN*WQFc9?98 zjEB}S2`IJm33O_BLhGxWU?(~NYm9%RLu><%eAk69+RtDH^VW$G_zW4(J6R9XB9uC{ zX9#@ey!i(8SM3M`3xud{OfP1bkLE6Kv4tNR+la-OQsfhVLuW3Xj+;D%sovQgc%?;_ zJ2s^XURW#Oo#b#x3BCkp#&3s7>|Qch`!Ou!~`(Au;Ur8N)1 z*T=cgI@Sg3uJ^#2^6}^pe+NhDtioE0-Iytu05PEgkQwNTvb#T^Q~;}h{{Q;>ANM$e zXU%`F;aP(k?Ro^ir7WrLr&!FuDO}b{1^DsgB$?{ufqc;hbY|==+}IjM^#;CUw%~a# zN+us(wB5nG6Mw^Ll`J@&?gSH9pIxwj8LUV+jry#gMki@M5uN>%xI2%4wlf5!YbL{2 z?^bxXz!2;=0IXd*9UT&baMY#>tPR_PnQ#3dR^mBa7$1(ZOP`_Cs+9l6;2(9IiM;uk zM)l-0;nxEtsz)p_!!d}v;v5OxyJwJThgkhZ$&${jlEaM)ep7wt1DMU$c+`7asEzQz zyHD@J>3qgG<_wrS|A62I=CNTVhWh<8*>CJkB3ds?wt*hJUpv6wi0^@~YIg88EC(D$ z)x$bI33N!Z#!*?qSo?zYZ#|TQ*vQ*(q16&)t#wgq`i>#+P2$bRG^%H|0Qv$;sowE6 z))W4h%buA7JsQo#^4@*qPkTUTNpZNLcm>tZGQezmA1=Dc2kOSFWAWyE?)%(EwB9~=xIn({2 z=gC82^?Mr%7>3YUwzF}A(NSt3+KkzoQn=$M=R#ebES5<4!kHhJAw?(}OnuiwNaO=p z#rzKpOxCkK&QBuN@s#Y8kb(9u<|y-K2XuICg_hQAaNN5D)=zlA)~6PZwittT+aKYj zG*dXqJohfmYerd-9+cvLGz7jWJo(s-0@d3F&@1Lm^}zu%*2i(VQ~RNJ&o+W)4k(a2 zozC(%$MrGusKJVK%#Jw5o!IdN>i4^0$%PU~J-!c4?Xdt8r9BYRUJR=>7NdcK4(c3` zB;tE0@ob+BAFiCi;gJ)eL)8IVq+MW!(F$1q)P?;99m3K3W3cY_a=aX`193{Oa9QdU z4*#$lC0ia3fzN_B-=O{u|Ag+UZmJ*6j~UzUaCzqH@KZ;VkX805IHiWp%J0H;zc*8Z zd|%AI%yBU@zC(lNJG?jN8>CH=faFdWFuFe#4siLfx~vurR^_73z9&RNWDM~x^oEZ+ zKcnpAJor*(3C*VQFynP9Y}llQ4ktI_=zC+aUV_z!PIyAx=|Z?%?u^49OQ7Wa;34o$ z<;^#!zl(?A$7y$}&+2g*yY#uM2EFjJW-+loriOyIpU_#~58=9%i>RU8TFicWfs55H zf`&(_c(3~bq}8QE^15$e=-CSg63@e$9c$2FpA_nNI1q`bImGA4clb0}8fBXm;meK| zcs=(q%#1n+8-;G8!->~8M%)|goloJF;~lJ~paWUqtnc7*AWCKo)<}8jZyImDLH(8Y z!*>rOYGBE-!hIXLYg)e07ve^^JEkbaHPG3Hzj5t@J=AdXGR*EQ=1vNjL8Hehyq_om zXZK!#q$Y7N(6xsHJ&~|hIS~y`us!O!P$H@Fn(SE_0H6B)qFmTj_@W{QOdbjOp=k|*DsLH&K04qddI8XRML z)S!Cqx@sQ$nk-MIcS@sB*+@EjogJ<<@S=wI)?tpUFL$zO2D}{o93M;sFD+KPo}a9Is?T#pgS3#DY=g!%CKRsqVJJ%!JY55ueQr7)}C3pPzLM~9<| zI3}tU>)Xd-PSOuZVEsth!*<|s4|9~G2QQM-b|v$E;zQ=4(k(eczs*$;EfYPh%pDR_Ao@WIC_NH2+l#ERRXd!hnD zGbg}0e}V=NnowtkCy}xcB>N?n!WTa)ly5AC&--4(%hUrfJKG*MRWiQABXP`&T9imuV02!!>JE3Zy_UdCZx2hl@Yy1+O-+UcP7tIJaRZB-*Y3omnd&Ot1si zv-?tm*X$c&Ih9B~I7a+hOQ6Hr4;2n{z-QyD(0FqI=4==Tn>SuXhw$+@b~JnAx^pq+ z_FgvQSPgemE((4xNGEoY z^O&#JIXXucakVR=Pe|GTm9m1P_#njeKvZ(O0_nJ&y7XAN8U8DD59j$Pb}4c86v>fN`HSfCEM zE4p#GBD)_QUONOn!jo?<)2RLmR^yFf`Nr?qIpl;TS0IxF1Co1*{lgb1@Jw41hYRn}rB+!(<9n0F-xi9ZHBv{yk=1m_6yRHWt&ZnZGOe4DsV41mZj*)=6 z!|?UK0V=lafKRcvp#IGom|K4ew!~SZL&!uNo1l#ieV_1Jbv`7)GRV_^gfiWCQKEbM z5ct@uFdiD6JE+n9zVO*yj2cm?w0gQ7$`|0jv`$sx-pc_3G~KQs&&*j&>wRy zpW>1xoPpP?bn#(S1Z22Pg!tSOpux_N2Zx`9jca?+P^T1i#O9M>+kcb5C!WxGAPh$w zDThz9ouKa9a+nug1n#EC&>?6Ej;()#jh0jKdV3Qj-CYHFy`n5H;4@0ROc(+mdv(K$ zZ%}^;t?+-*tLAH1)M%&<{G(at_P=jIDs8SsG`H@0EU;{YyM;Sw}U z8elnYW%oFbA>P;<)QyM1!A&BtN$VsUq91B^k0HbUW{{x!j_}RyFpdO6_$1;6wFA4r zX?8fcmsX%d;3!lY@evz+e_=k~TS%rtaP>axRk>P&68DY_fp0o*zCr!v>%qrylp4Lc zhZ%_iT%n`_{GF6fW(Jj@n2$1@^IZm4yxmSsCN9C84;5T;_eyBa+l}R4=0N6UTZqf( zgmItG!NHQ5u&J#94HpTZc8dU!iHst_xAs7n7^`Qn%(#zt#GzKC7UoOv!PaG6=n%lN zVVz{Lu}B4Pj`fG+2YPTVW;M#3h-KM9e}=$EdGgI0)ZYsSXdft{#*?ElBgvdAk`#u& zodaZ6G4p(5zEpD!#^DO8Kusc>Fjr&`cj`qEw6NUGM~Qpkf=e;PX^Vhr)@}$_+6kL8 z6wq+%Jk)-yNQNutk&xUa&{gKi{3bNv<6b3rAuY}N0rX&N_hrV%JYx?TV&mTdEST~O zPT75D{=-oy<7J8x(TzjkV;#3V*5|xI{e8EA_f4y)al}f-_nx~WnT>o4Gs*0~w^2NJ z2c5fG9G9ngQj_-Wn5!PdrQ9fmH=>*I@yzvbQLqJ0o?#g(yI9_j*KXLdIS&n)XPEZ2 z)$CoQ1UZl~1-^$l;AmP1AKCAJjqGGt5LgS_4*g~8vm2F)W$`76#ak{@;MBt@%zro> zWfnxD#NN9@;A7p2y!e>@42CO1TM5g)Z85`)WKHg_^a$k3X&`f_x}${HH##@|5iS=h zp{AS+=32exPAB-ln=3!?@$YwVF)IX4j#C6>+vyPg#0}hyv(PY+&EKhBB5Qe+geGdi z54%e^xuj^L8YEpd>JqaZ~H_+io;*XSCnGCaG5BvdczR- z25TYzu3^k$`ZF-BhSn=Z)MOGLo4;>dvCL%TAMQuyZL&j&@Kbbd)oNU}T8x?|6kx8) zLGBF8m3X_j7AvxD!6mmh5Su&#l(goemZs^uDC;XpNPzutfjVLr@LAs%0r_+nu~KcqaehWrlZ7bBO85;OkquK0i4C z4&Dh3;FGmF?A*tC!Ig?(tm0-k1au6HfJj49=gb-*@eQpEDoP4 z{esK4njj`o1;!|jf!pg+-DIIZtBGPs6XS_vitDC@G4XauVkL_ zGO*)~7dk{$qjK;8d^LLl-uZL~PCq>k1(~`y?CEus809krK6YEoi*Hb)fvi9Nk|Q-` zxk?!ceBAvpVywQgku1o2hLV2*={%oF=(aXHk4$=@9q^&tm`9sMDZElQ%)jO#^Cra584ZE#Mxg zjzfV%KghxYdzA8OqVuwJaLI#SI$q!-<`$H2>8#JAZM zJ7I^)Cp410h1%MmiGq|lIds(odIw}s>B~fDPa6wQK2(Ft00%oIzoEmKTvUEujjvix zVTr9FoOz)Lw|6+>utQcT-aM4~V>cN*_~sAl?`AMGKjx@u6FX3t`lEz1!r=PSdN`txu?WfzQGasncn7r~B>N;Fbi zkJ{2sL?LkniEy6+Kl80nne}P6FL#5A7c;@N@EGh&5kd#{K3VyvD>fPX;=Nskkm~vn z3SC2S*oM_8e#dnP^T(>dy!Zz7_rf1uxAIZ5@fB1OiOjKd_icP+g@%}|SNPTq_ifn{%7~4CF zC*2%g-#2OS21P!WYuxq}JU6mD_?0H8Rai(y%p4$*tMuX5hYzSK(F^aR)OF&3 zvn}a(Gc9(;AI&|Q{uYI{=90x*&*HGl8Put09=f=QQuBLnF;A<8%S_;d4@*+<`TFaS zTYLnf4b4D-j)X|7X7EBuH1ZZltu#F{;*}aX!lwxRsqQRiGXdVuafXL0u7g|IOz`UX zg$}H)qO$fJzV`To58bxI*$r_}tQ3OM^)4uGHk3LX+hOzKWBN0+Sq3k?n7%?jVn((a+qo>UKKKMg?1i0LSucLv2JUi~+J|KlEq?O=F~0n@1AiYjPKa-icIE-``Z`2SZUedUdl30) z0eH9NpwTI&(XIE$$N^n))Or*QC|KaQh`G>Kz8y-Xx5BcyO|VN*2py$@B<4`?3Fx!9VIa>{#%huI+>=#*QTT{H zS!#R?W%}yr{1t)dJpMSHQ0;_yOD1xcmW+l^%c}52;|a+;7ZMdO)$fM8~1c8^OWxBAj{O*8`+H` z=zLbwUg#Z5CmMxf-lqH9WjogUCb1Z6)0e=tvOjQ))!}4qy5LA`E%-!8pi${Y)Uxnq zSzHUrvEvr-hxOj59qocPj=;UlFR;9^8GNQxqoau$s-$nk=7$^cNzhCuObjPgcl zdJx4pa zD)&%b(E(cfCqT*0>#*W<82CK2M@NevsB*&sTgJ5G)3=^*?r$-ajvIy2Dqm4-f9DYR zoO$yN>aXG`)S2z16O1lk#_kHPGK|&VE}M`QV=7VB{wH0)?mg#si_nR0L^1Dx5qCvx z3VdPj|oeffTLg9U~lbuG*&!>nw8>Y?DA#gxaTG0yC{bm=T1WFh+-(ZwjWmg_zio!)}o{J zS5)cs#WzAT@VU(=$cQh2@|llO>f&w`Q+hoFzQKL$zt0%XOn*kozo906IGt!vhZ);- zx#w3`q3EL&vYPD)4}qKaUP9!L=OFFq z1IM@$*mu4Ujdi0@^ZG3^wo{s%uuwsM;lIq2b0@rekOhU?L}B%>R^-#=|$20!MWo#e~WqZG5r}$iH7Gly6Hs!NX&58jd89^QG4fZLkQuqNah>^HyUY2<_iqVrKBhmT`NN>P<~E&JGaWNF*>W#l+(WTYQ?hmw^TYPb zp$kRCan67XoqRSG^R5}Y)M9khu0mCsfp2P$WBssTxIivKMO-^d zP1%B?*KYndfB)ki$BpM0uwN-^@z_%k$V#BR^xbV~hp4?PJDcKV! zdSc3dWAKkT9;_AoTce8z;|tA#s^R5y(*8`$SgXv{^-Htdo|9z#b&3jW?$d?tn{c*^ zGM%z`73SUf#9hnY4_)Gk__}Q>6sknSVQpm)uUP_7(VpPfxEqZ#ya3Z_XWb_{8{h1K0SGb4ps$mn8TnHYB?HX6RKn29Z4ETE`? zd23Ez2VzFr5It29{I5r#am*3aG(e*2)Jo!+2e07htE@-<61;hO53U96gAE7xVE@#U z=unw~s)g(EZFvYb%XGk{KzXPd&-fB;ST@=JokRYyK3DMMV_#8fRPzj;2FlaP`wB2) z`Bd)Zq!yG|uz+kHBaVtWKGa#{1I~Ezo?2`?jCtjTT>haH_`!Y%->@8!I|aRPsCo{F zE)9d|h#wFzHV=)@k4McB)P=8<3;mHLzI=Pb78JE81 zUd<#Zk>y0TSgpnp;+qj$luJ9vY8Q+OtfV(No!)c8Yh(!89 z^y>o<;HQGd`KhQWphU)b%qNLL7ARPHh~>3?gf~j}A@@NWY|S!N>GxEWVP}$M(`G+M_YU?KRiL{4gZN z9}@SKpK-+D@zi;XK03;U(5Wh}jIW6+@G64tb*b1o&JBvgbRfL@ISAjK1;@=ELO@Fy z8ke`QtdW;QjX#_uw&q zMh7!VI@PC$@g3l9ZGH|t3b(P%vKC4_HbHn;00{N2gX2Mk5I8*>jT<{q~$0xWy& zVeAn2*6`$GyF6;ldJ-N_bf;6EdNDpRuKDN*l)SA%ww;^Fdb(Fr=V#$)KkEpcTFuV* z<-54st4=~s$y$8B+#K#LU(W6r4M1po5FD>r1A%F^X#BYhH6Ga!b(O0mIkt=S^u(gx z9}{R15P+;WCD@Yb4gOp8(Lv`Xj&nE1cQ4Q3hn6C^;%xwR_R;Jf+#f}u~|wLzChD99cMcr4aK7x(sVyZatULkr_ZUKR$_2P= zk^t_(I^cihB-;OV!EsTV*eY9rp9Z!$Ggsuq{9x3N;fL#T z@WA>59AtYqfwJjvV%IGQTC)dDq(7j>h0jF8;u%RXJ%qwL2+QT&0L_-IaIs_|Y+cSg zE4wbCea&(lcYPPO+C9Y%?S+t?JrWwK3Q*!$1&a8${5J;w_=c?K%{Qpgu!Hchdlj{) z@Mk@%^4!}-wpYIIPdx61=* zs0s*H4MG!RiW2Pon&Fxqa_HoE4_sPFE6zBJ&S4r<=A?o z8@tZvK~DEZc(v6SCG0+-$fA!!;M>TXZ&0H*%b+Y{5}oSZf*C8na&5zHP})P8c)E+? zXqH*IsMH^)U)x44W2G?f)-J9X^5NIS_4viJ3mzIbK-jPd;GgIOF&pY3c<)Ly0bSGx zxkfZ!MUm5g07W*IprPUcc+I~6&Tl>h+y4qez|~f?pSvE_bVITAdlLR&9^AR{J@ju~sNaPJMCqjc#y;-!BEM@Oxti+-9RS7J{s zziq(08_T#7i_`Gy{c-HLcL2&w>{+bO8{n%5ftVXdA^3$Qn#_8M8hb;C*7{Cz#yb;5 z3g)BXMsH|3t_|s3n_$P=FA&h3jP~j$P;It0wwYYRURP(xV;PFgWACH*Us;xGH82Fe z!TSOp>vK?lpYx$~UlW}+&K@&1h;Z%pQaDUWl6W;%;OI9>)J69!T32{cs~N?tFYh;Z zZ{jrQk9WpSr8IbCt^}df6Zp2*KrHiV4l&h0lcmd1!{Z{+`sPl~yd8m}QtW>G20t`u z>cUy?V(@sh2?8gipxuw1sJ1f%+qRy>zVd9y`!XL|eBPmW!xI#d?j8c)7M^_UBu!0( zW8uN)D|DLY0A_6N=02?X%)Apsi1#5?9AkQly0|nTc|oXE`e@9{TFu=zI|#pL72vnM zKjE=O3>;t?Mtmb4LF^(v2stQ?CR=h)W3vU(-rY-5XKSLU+XgfedI7I;(jm340d`)M zhrpfV(e8l_s+|nLwk*Wo_E+F4^9X!XzZb=?1+Y5qP|i^9y!n{^OjK6EgC#5Jw1?MN z9VeLk80f)r&SsNc+(aDXcbK|_RUtNYQ{dZ%d6{Y41LH$5!2b!mT9lx|`VSoN+h+B5 zTPehzy$&JG@6cp#4Qi~NKy>)`lhnK3D0<-y8qJ>qudJ2f%)ScnOxXj0*_YAoV;nZ@cF=p(IB&9IG;l zy0nX;RmVpPSLHA-rH3oizYKr2lw)_{7kKKr972ljSq(HY7ky3@4n({{lej~uu{4e7 zN?Vh(!WI;>Peh~d$KmCYAUG8`7rgg+LXe3J+JPdf3)bO#A0z?-PvCl5EW974gW?W* zQ8*&vKfeEQkF%ZU7_dqYHQBHT?xhJ*%hIoy5vav|X=*~58`H_|BjGsKeJXVwX@i#C z6Di89V6|3#?x9{4{MDF=y%xUkY@;BAtP-{w5bcGNN1nlf=4)tjUX^7i8WP=OOUPN< zmne3k5{+pZG`{DDWWi0aYf~!(xi_GloC~UJ_2c`ZULxok05=v=Xx~?i;#zA_cthxa zWAKkX&fwdmfB(k14QkZC9`4DxQ!AxB)>pos>-f`w!^ITH9=8G++D^x5eHSTi zyoh_tKZ{a!O2(5$IqM(O|Atoz8OSM!GxTxN<*S4ME5kwTBO#H&C2^846RyA@F(d z<{Q*#oCA~u{H0bqd|6NRDy~yC5r;2QCVLIfqmpg?Avm+is-O8&#OZ56Xs{xh+{;IeWs*ei#08SRvKqyWo}qDTEj0Y{hxk7N zuzNOvpij+cTlfyu*Nb7hOCAwXIS2VSPr#>5Q&H@dD+;T64uNkcZ@xi|W}k=RE)Rjj^VzMb{u~83E9W@4V4yMqpqoeXfd#f5)~`Vi_GF48yrHuv(K^rjW|?a$b;Z{ zAy&Tvk3yXHLkMO4H6~SeQDfy!qOW+Dr1uO*aUZsCozw^ofrSv~GZOY#S3h(`Q|n_D~KbGr|U<>2pm?n`g|SMQks8f) zt$K#Tf5?)3&-qX(Z9jFbyo*zQAEv}75c9(GxC*1A$j|)k2ZEa5dD%V)>dUd}yW|dW zC9)8vC5I->aV!@wg6JP#M$R3qMDb#8G&yhp8YK83_UjnfJLw$+Z(M-39y?L}Ob@pI zokqlktf4?N3_4hLj@Sv-Z&BGW1U@g`e1rOXV+wa)t){T;J7!#}u78Vga^Eycsvclos3P~obT+H+BmOlz2{j+so7~hbRzKgrg7{&7Ak1?&nsl%| zxcf3)+s> zP3~veOm7Ll%ND4cBnpB3XRLa!Iz#-~J8)2D8k&j^M-6{_VkmN-obOwL67e-?x?nZb z#msuIoGwE#lcTTNS8Ayofni66&y66rI|aC?pbd{>r4G3|9IwBp(j_y%hs|JEO? zlv7jvgK%g6PKsOOF{5%W*TX!h<+SDzzk{`?ocEM24l}_CE%&H(3#)VNZ{;d2Kcc`c z4z&sL$SL-{`J=FP|SXUZLdJ0nYc&002eo7UAkyb6_=o#L$V+Rqc{md_Oce0b zsyZT<5D7&=7VuN}5Q^q~M!_!^{~LpU>~Z$;<{Q+g$7U#+WkHGie$4niiTkyJWf1%g zBmOaSSpUu9L&Oy^p!)b5&6ASP~IteGf1DA|Rlsz^Z3rA0#|^3gM<4 znp%dlTHPCB^l}Z!gsmufc?Oy(*)hLI0ufD`5Fp+U2Sx+hT<=2-JcXa?&JqP@Ww=9j zL0`@p6g^zV>gz+f>)6MWkKOiA({KkU{1!n;aWG~|P2l=N9Z}wP1Mz<@k17fK>5{2C z(KOqLPIvTY^EZa8S@Z`5J4K0z+G=PrQ-T1`UaRh|g^)N(6~aBU(bS&(-%qy@<5{Cf zW2@uG1y!+|VSgnNCk*wQ^q# z?!}5k6qrL+nJte0L?aX zP;>en96Z;^d~~$oK-4s}Nzp=$#cKGuGKP$N*8q2KIm5tc4-~b^Lc!gFL*U!bn{QBm z`R!2X97ClmoU8t&6OqbkVhen5zDRo8mjST1NJY`W>TA7G*%uBzG1OHRP zR^1I_A@SRFI5f=;P2CYS6$6P$v?|GLT!vCP{Ad;z2+z~T!-1U=5G0cfp%RH`6Pw8D zAwKw}rGbn+&b-+z!;sJJ4~l$JMM0A_L*Vo0$+u!qe;?Mt?S^d1jp)YA1r5{ri2&}VRu;~vE&H6)jJLTOH8f0+1VkT}08N8g-qEZV z#B}8^l35dt(njp}<(dyvr^-Ok7&glGt}6L_*F`psO|`Zd&Q$sK&A*q zV%Yup$H6-aUh6ZEHy_iV*{E{3y{D0KcQ<0@e$VOrmR+dOY(fH#PDj<~&D71R7xmq| zsm%syc7|HSHO9O}5#xD8Dm4#U3(~rzeVRW`7^{4S_F+ zHy_iVnW-1tUKB&8kI2Q$<1y3utC%;Y`biRSTpd-jm8shXN7Qqypf<%Wn0I^;_cBcY zMUJc_($!nwJv$fqP4Kho>2`tSVMY)!SpZEFtWopuM`EU{NHUL4Md`DY@%2De%2V+B z5X<(bxe(evjD7!hqsER2*g5+=(eMj~2QxxY@Exn069W{uFj#;2fAjZ0?s0;7jsd$- zr)KubaN8=HPTwMqnHLhK3#{Lbiff*bfJie`Egzt6Q7))EqoK ziHt-wv@eN+{Wm{b_4<25@&bSeucc_3?t+?Enuu9wDamy4W1f^d*%}UoDpg(Bms$!T znRO60X)oL3{6>u}Uf9{Uk7%8I52doFP^ju5iYRoWKxFrSWAKkXP6%(lL5(gihT8@c z==8grF|+v9bb*0!%wIB(1o*8&)s}ebc1s;~w56!6cMs;BIl(ote09-zDP*{#6ntRs z=k`zEZS_;@6(q;iK}7BmwqLMenPlF?tj(BYN?yWYqu#UMpqWsa)CIfUX2F5+b0KVd zC)>wbvGep7{FYuqbnaY((ppx7ENMdF4+AK$LtqGe2YB-hYIGO-ja6Ak>4;j)tpER5 zd#kW0zc20^P+D4Q5J4DV5J?q8nYFguTSin26btDV3{1elR#3nWLXZ#@MllEjJ3v7c zyBiA?v1s2t&vX6WLx=17KL?(9z-RCI-h1t}*ZQssuE#bd)cqhJE29XS{3@X{-t9+A zofXvM_Gp$%?&xnyTcol{oJtJ5?s}P&JI>`WP0M$WVs3;CX`5gf$XD8_illG0> zAeE0*d{D>zMNp}oN$G_v=8%^`ctHN*f8_ZIB(21Sv5Q=x|#XErv}XPJdaRZIA zK5j5)$wF9vbt@$4FGdf&325&70e=)_6T6%#aNY7DDisu=eDqC}Q|r!Khs0;@-}@IV z(cf7wsMN}%BlLr?$f%x^pX`Bpht`ml3Snq!xtsb0?nbjmBdF+Q5PM6#>i$M<6)M$? zCc0V7b4r)_Z^zsdw#U4I>>^c2IoOE~EUvMb;Xww@*h~)iuR`^<3Uu_2hq??ch_U+t z8^**#(img(uv*AsR6YDT)sHx;UxDkNqfj|#5X!rkpzIfiZtP#ObUumx?lt|N{TmU} zibal!octH|`~1{SR=i;K2!l>hza(YscO{;V9D0S-JFIkn+neP^1<6ETc|7w)uVAxm zn}i)xH$(PUc}RKx9Ua~!qQ%n9WZ=o^r0{hQ)NmSrjxHmi&hQIFzE*_|x9cG((H%Wp z?xOiLJN(u2HyOCu0&X0chboz@pMs~u`bJZ_!M9O5pG1FOwle+oV`pF{7LBOq6xPf@ zeVbsiqBI6ghd-fyN1f61=vz8+haH}{HP-!|)e}@+T}%vEo&WcH!(hqUbHYw9MaXej z0I8Pa(BWGgT4W9&gLH3^!hj~!h;l_o-cq=^M;5|%Y=Wf8dsqz!%cF|s{9nGK1Bo*~ zA8O{+qiRMy^X!#l^SeE|!6$hS`SFNoS~khRPe;hKJM??{6-b$^~7lPTll%h0221a3;#woLC*1`kec5I9p!$qzCT|w zsP+umKWsi~+&4yt`_)jpy9om1wIJEQ6q41aqDN>L`@Y=4KZ=wLTVnyWY!;VV7VGKC z%SG9__5bnxk1>wqE-hsZm`0rjt%k}W_o>IF3s|)B7^gHkkoir7k`+el&@^BR^%wL* z<7HQ=XZ~_L@qy?5AhJSw{gRR+H zPVPd~RBc9w;|@^En+d)bDI~vo1<6AXqetvzc81KsKP6Mx5WQ7!vz*NU$Z^D;%e+x` z+~xn);2$xL#KS`hAJeGQm;q4f;YdY>8?k76J*V_01r2PyNaD>!Xd2~A{l~dspV{Tq zvx~(zO&0DS6F#BJI~mefd>sA+8bkbf6_BZ!3i}3CK$^uXbkx1eVum_0c+E&s(90V& zhX>kMAfvP#7wps z+H8vxi>!7|Hv2kNwT;-1ONAH};+fZ)Hc=6!9LC zD`e4QM;6Ni^ug95AraY)fLpAmUhCLd?AhxL%6#Fv!M9a9pG1G#?4UBzosKjz!=f7{ zoQgOb4Vo*-@}e{}O-`cz7u(Q~Yonvp*^C^eweF4QN22OmPhws4OJMWzTy%72{xN%g5f={! zlFPG1Ee{dee|ClId?gqepbIGy;pfhUH7iGS@CN&Dul*22DdfV<$SMZyzk} zXW-tXx&eE!zG-XW75MwA0v6j&g`N(hA@|TE*nBx39Y?)K%VU+qWp4}FH**#9y>&$U z3-6(N{|^{p`3h1aUc*N3K=e4n-a6JHgi~9je*w zCpHecD03(fSP2;Pe8Buh8!}*vN-H`}1hl+{%^WgRq6U5*`1K4i-Kzi_vp2kOfq_Lx2dW&CWqv44`f>wlkrVN8Dml`EmL z@d)*-?u*5JA8~4j2O-b(4_PYELDT$P8n8SYdnoJ_a%AFA>sbZbM{k0vlSVLOqSlE~@ zK#v=&Zf92jc5WF*eA7$e-i$IdFbc&UF7HsrU2-=3zsTcAYM1}L2H{Mj1N$w9v%Lc7 zD3ifhY&V=!A9)0MOZa3-PCqm~U`zw@0#LilnR?kaV5#dK_a8G>qT0z@D${VC-6&4DeuAE9Fi^T%nGBSZG@C)s1_P+MaX+LH#Ta$5q!5??~vD+kzkhSjUo zFF^C0bJ*o*Ndh7X+}BY+L*`S|L-#YvSas(fxkox5)964~3TJJu(NPO0VX=^K>TJ#e z?+izl@XFA%=s69z_6)WDT&7+d)??}L6Yf9b*i1Cz_r%fnBFa5J1q;_c0EOG-khiM? zw!BP6$LMIZ($FPCI`@#h86Q!bEJu5Nglkt_VTgAYZ1z)tjnAvlaLTJ zaeLuD^9kThNI|)uy-`MO>3@6tj~FgpIv>;MzzJ$_c8nVxbt3_bM?c~;mPaA4(}E;y zFGkZNo;0A5&7J+xNWI=LFG9}??!R{IK=tTqGH^`^_SkU-7WUNy#e_)6yZsBc3MQlD z{DEl2Pb99B)JWE+{iq%5jCNmUz%}m#7~H=SHb2-48~^@5kLM+5e&RO%jUGiJCZ2`| z@$b=S_8OF{r||bfemD3ecNHnWPl-k&pRk_NwRCj9LM)!H%4r(zMznycwp;ax19Q0e~rxIC&?%q4?QM`O?NnXsT-07_PGAYXMlY@Kr*9TOg*l`9a} zgY6`1&=1t!$9m;1?1QVXY{5yX3bu^D2b)Y)(Bmzu8#p(U$jCk=(F@w)p|v~q*|ZDg zN;bpaa(*}XBpUuVAFG$O?(6K+9urz3~ zd&{>2sNq#YhE9w@`76mVzfm2O_YQ>orD3qOLmeHH&Y)G`H8OP4K$3CTl+D-Li+27m z;i~)_uz6^}`a3z;G@~zie3^&l_m&Zv9b&RT%LX1L-ebM;{ZTIFJ^b~q>IR=A7b#`` zB>F1}hqJ#t=@|ZGEMDcoX*E7Uqqch_&iMqI7N4ep30qN3Mo7nby~olhd-pc=d#JH< zI&mx8feMKiVgCAepb}gR`6pCaJxVq@Zf--X`CG}*1M^7w>m{gTzYOiHTj5G(0tndr z=dCBwU{jnWdVF7r<}aTSnWyha+~yJR*zzozH1bhy)NS}{cDoyV+0ywW`l}iR=lEW9 zOu}9)PW{MfC-ufYuE)vZbap-*N~D2V+p(95Jso!-8%yU_ySGa`Ii5XZjV9ix==vSz z^N)e5`3K1V+y}O8VDI|7_1UbLQ)Fm|K1uJRi#mR9(Do1W-5C4`EGkuCn_v%Y+SU&} ze%Z48Wf+k)n?ja3jfKb8uVO#-6(}dT2VK8!c7rcRDqo~Te=i5axrqvN%&pH@oY9}t zu}Hx_aVN=Q8Fq&{P)GyMPe)aKTROgnFP6r+yLXIzgqnPBGFRm`erK> z^xFm7>K>zGwhmhD8cv3d>qGWTZAG1pH_`UW3b@R?NX$+Sgl!pHVUt(~JzAEcd5aQ} z4YwgH+G^lQj2oIcu0uJ6XV6tEIotkE4DgThVV`t9iT+wF;M}T%)XNI7xKM@Dxi|v* zlvk2P5zN44KWbsH>B@KXXkUo@9;b-x0Wn!U zD<7V!PC;`Y8nsVL!@3Bv)+4P8b=6*mG)0+^x?<1%?4upaWYhe3mDrA!RN+;{<4tql~gS z9ncjN+6}&ZseG(6i4G#H*2gT6j_vP@#Z~h;-92y6c-{lDU~LGRrsvThPv(~!5=SS@ zo{Od1_i-{a51^LQ8!~1t>rsB30OW(wIjEFGRbd4!hN>`*q5gDxTa%cN?w zKsq1O=%A_AaNhq79lPQR7S})H^q8Nl@sXos{$rMB+$N?$Gb>SHX&aqTEyU6c5hv5p z2esy3C*vlvKIrW#Ft_0$Xx#q_`>mZ|hqFC8o@d{ncl(Lko4;g7cLc@ddEfV}~145LAt_$a?elX~;jv2@>QPBx_uwT^Ei-lNB3 zFRyr*o7@7LN3X;F8J4hv_4hhn^+Ky38;Q{A3fazlD0^>zivw1^hl@G&pk|ixl zj`g7^P|G61+K*)GhauSeqd5*xa)t{n2SIf~KiDN-1u4F6C{pf$eD7bR$CUYG=bex6 zvfpI1nX?mR+K)izk?y<|AC%4~(O<TM5BR^s?>2bM?WZ7xLtAXFpwt5rFoS6=t36dO}v>2yI zI-f*;AC2I`=N@$Y`h6%?G2#rr&O;N0!DLR|HZ+~~g9h8bL)o#pbmFIRSb8>->lxL= z=GNXK!HL^Z_dUWP68zy*}OOwbwie*&G=}zp!x)Q znB9ThLs%|#TPlirc_M%AH`1f+49QvL%zRwupxvM2D3diBI)f!|6#s|se~fX8rLI9V z)97H?V7Tb~kdA-eAH~|%953ZCnz(Hwa}1BM_sBRJ%--i@;+yEC5sp}TsetR*sfju! zjU-&z3^j9~!|bIYp!?km3Recg&Ohbo_>qr-VfF-CKa;e~GpM`K8g10B!TGZjK_;5@ zprtoLN`51X)SOvNqf2@^%q4kE%-;gl(7|#r$}G=?PSKkG*5Ds8j#xS$)97Hs<8X0Z ze>!1MIf@P6b4IrPSgo9p%no!!Q(+kmp7RC%jvqoN<>+E*RWv8RISO^AHjt>IE2uSn z6U-KT1-&<6P*`FCy9Tj5$JZnjj2J=CJ)fkWeZf3TJh6W@AI{H{6}HDch20%SkWyNL zB6U6FuR2G1hRq{|@x9>ng*oUrDG+4>W1&;fo!-a8()pN12Ro_5#rqHFgpDIn+;1{x zR8xf}h2~^dp$nSY&7r|*dC++*l1^%C$I_ZloPv29>TG^YW`!4{w$@mfb^j9R-)Fz! z=VM{loImLJ<2DM$J|>tPNm5unfbK&!r*n-WoVWBA{&w(zJ-(MA<;pk4_Z9ic4Wwtf z6)7^@4R73gqtnW*EDu=%oyw9Nlr)VVksPI&bc#ez7lPfQ+~JkcUC z&708F#D@kSv4W01YShQ)EtcLk;}ps-qRzEe66>mu+E?pf*4hRzxONQ=s6K^Vhdj`+ zr4t2Heh|FvKvI-{qHfn6?9V0}o_o4Y*wpy}_MH3yDfj-ONaHf{x2_;PYY&sd^#tCW zx5a_t^(bQz03D64-QX*c%EwMxIym?hTv~92dJmb8V*9b2aj&Cjs`i$|&^>6X`IH9V zjEA<=I_gt$6HD)DbBd$SqfXaCvd~-!brNpEEN5RZJZ=vMhSb8Y*B$8C)e8lITL{tn zLpHe@qaJ@4T6Zpkb35k>KeKncbUhZsH3(6pnTh;8>q*b9r{q{3^Y9v)i-R7HK^dhD z&~dY}8+=El^GWo#WExz$c$9jlsiS!C6VAAp<=?P`MDJm5#d0DV{3RV)6%*-X)zet| zu$)tT@e6woA|&2A3wzrcLCgm$;AIVk17W7Hn@7+|t_uZ`<%IZFkd4u-cF9v6txvCj za}!#G4fp#%dMt~X~HO z_`}$n^;gGaj02UD!RY9i0^KqG0Y!Lb7L(SdK;->{$*FzI;GN(hy4c=;zd2{1Bb{aFrRwjvbUumxiX)g0%uzbg z%?riueYw70WzjVI9hvDVLX)?HXo$^d_^lK~Ctui&r7!w%%1RyBd#@o`Q7b^*ZPy`Y z+ym${XCoXq{SkJreuYlG(onFtn2^_+BWw%CG0e-^*k>{v zXz+vGr3L7uWru?0E68y3y(Fo3Jn9{9LBVgK%mqBauYD zd_K8keHt2ixuWY@5&Rwe9Xg`Sy1`c}oll~_XPI!h4d}#=yHV^lmNT`lM$@)*62*RJ zCRaLWNTfUbu!yHq7B9upw=*~ur+cWYFodif8HIYk=R$O4Z|Lh1!8|nWVfQbdLz3lgMxsd#~n9Z+*jl7U?8%HjDSl z`_Yhf3Gn^g9Xh3c4wg2o<5a5DQP*_`S-;mC^$XrY^upU<()%|YbPa$#TKCY2$3sDK zBN?6-!sd0HN4*wT6f9DPv;EcyZ^pYorr5cSH3rN zm_O?VUxie@*-WF(RwZzyHj7UBl7ZqGj+~iJ8TMOTPa>wZph?y_8gelTzNvG}$6`8` zev#!=e;A_f-Zf-HvK$&{zl52eDVQE%`d&0h=lUW7|c2p7fzE8=zQOT%3R2v1d zv!L?yV&Rq1PLO%43{qnzpvZ*zv7TB)6ntKi+K;{A{SifU8|wyL3+f24SCrQzMS7ir@onprOjGguMHnj zx9%d@u$|Q<*&TwJg^kcJdN~{{c?f$_)zHcE1Pam*5O-e{vi4XA>Q6U7t6Bn;NqdFo zpVUK^*&9e*x(`Ky3gn-jNfZ*pNiDOF_@G^lZWF&jmxnrZ$aW`Jeo8tY)1Nc*R=Vo$ zMt#z|P#oICnNR71{jLHDpEU(dlF!hP&Jt*hA3~=AyJxldaB6)S-``(k1Iq~-jOqz9 z!(M?|-`#NV!3fw>>Vi)FkE0;lj=1maPu7~bqkjAvw95F!dMjQD&#d)_tof%Qb(0;6 z1}ihZT%u5s(!_~M7>ht{=iX+=N^HwG7 z*Eo%Y{mnv?RdZ;lkv@DL@{La0!}$JQ=hR9KP|se2Y$#GigV3972A3t6)p)|ejt`V~H+~oKfJT%jKLBh7PSUe$s zh7OqmAOC97X+I}onbJ&7ee^=q^Xo%4l-Zy`;y{RccNWYS_kctFIw4*50y;UdJWk;d z!YSL6HJYlZU$zddzy;3yx+pwh;R<`TRzd24QWQ=8j{K8vh@#?8Qu|>Bd~~)%w-9gW zJbez@Kk&N2Cy8VKeLl>Q=r8XyTzx%&PGXp3*iJbb3RVO?0T}h;u9L`GZ#M8 zDADQTW?-4N9jE^4FX|;*k_{Ik*_LN0y@+BLi-Cz z4qw{$<*al*iT=)H!8J`5qy2h<;`xs_ix)*`Hhmrmy}bubW@*sSd7qO* zH8_p9GSn**k_|Ph(BK%Gfj9Fj@JsK)p{P5MK3WT%T#umOa1X*Qt|hB=kE8x~O|<-| z&U*W23yYmKVeg^gka}?_iq_O4zjO>yjJZx~UuVO|X10GZLs*WZ9@-yH>IUCA>3kCX z-CG0KT+h%cV|Jo=u?}asN`Pj|29nTaooEtynuewghK7}H)K@+c%dC5Hni{)M@6~#; z;Q`~ju>+#)H-ZKC6%K9M59zbcp_9-a1tl$n6VD>63Pot37KWCWHQ`KHknq5q*|7KL z1xUT=g`ylylFdfUB))93k?|W3U`G9uD2o zgY=SP=)^UkpiGBQT_IWdObrdF4O*^rgfmJfh5K+CWUn)T)OWfldcGg|2d5Dw^;A-O z=Lme3(L%R4c87d17TV8_?FQdP>3mG1E~b;=+Wwbx>iBvTCm!YmGo#S#ReutaGZRe$ z^=ata2k>Sr>k-szz%uV|oYp-T)b}?d8(J2lq0TLcT)PDkF$ zLPg(vmKA zN4^T}#};&h?~-&rrcoEyad53Vi%u=vhT>I&Icv3vU5afWhbeGF)r*`?Ec+Gasx`fs0nU<4~J}1#+hA#~>9tE$)&ZRSICt%t9*_=+# zDAX@rMUvFR&~W%gh%_<>t5O9hvd@GJt$K9w;!tq9fzShXWJOgj8f;mQmR1gMdc|4c zF6S!9nQQ}Ta*uH2Sk|Mw>lsn1Y$UanccD=>7u{B!fDZo;(4O7U4L(U6^zSn=R-(V? zF;FF&PpA19qIg{m*MH)5G>5MwxZwfgTSdcMec+`pP(SAJU$*8Yr;|Ah_3NjRB*S57 zI8_cJKJ);A5rrbJuaLofDV)YTp`bE?(EC@(iY07b1P3jqWRXU$Ue{04;mEI^it>_tw zH@x8b|FLBLSym+YBo9sed($u<4qnXtP5oBCz_MK`T<<|_hUgz_l4O1a4QDN2zTuuA zSTqWXq7xuv%w2SvsDgsCrDQ};0a@XqfCd+yp+(zhIBjDu+@fy;Igd*qO(z#e=5I!R z(i)=d{GHSmy@kg7v*^bBPCL{tvs!d^`;p3bO*)@Me_4~D%F>ulm&-$Oavf)ro{i>l zaU^&f%i{!T(6Crtc%HVL`n?#0Wd|Q~y=%s@+EN}#vb~OmY?fZc+CLz;%0bZvgpA0e z=;U()1?TRN5f0uY@wXcqJnDrOA9dh#53w-Sp29vOIY={d#F6z{$X}UDl;`&*wYjR$ z*v!tzjn>fq?klvXed-3Eq~_}1zt4FR{gq8;Ua0Y=rhj5C7Z0 z|1rk7E`1Fo8vPIjRV0u4Dzug#s_#al*kcGjtA{>GdHTl=BOg4Hza#Z-9W7exccu=&|-PMp47 zFEq%mCrRF`(6DwOgxB8#>x=85=*Jw$sApb50UsIPAu{6bR0=T05u`%fS${y=IMzJsr77tn3nT4*1&9ol`AyTMl@m5;gT(ILEL zQ04Q2`kqKe@z!k4u9o@tbX+IFy;z(c7f-|5#PB%p2n{$e56d;|IsL2G(V+4VN%A#9 z!{^QrelQdI%duG#y@o=@m+9yfJOl-o6v&9S;Mkby~16?llwP-QXr zwkMo@Yz~`MphSYcvp3bHOKG_7XL$78n+Eoj$8vrkXAn?;29F<;q!9Mo`&tO$D{n!6 zTnoi~XUJ51j837kjE@oz6FymX*%b{Z4@QgJi*QQ#Nw_S-19B50AZ?fzdUjq%{;1zX z<&FZW^*aGyQ+uG>&N0v~_ZHf1Z*^n;B)Oh{|32q4{S6tj6RM)(=#1dLDBj-5Iq23Q z->#YjJ*q>Km0C31u{S*Oh@*i4`>@>g7-!Iufd;=5Nm6tR8g?Z@xbFh!zj!GW4-0}! zGbeNk-_H0Vh==x{JiqTN>IZ0Xo$WyC=aOd^VzwitcPdEvgZX?hslGOuTiX|SQ zyT~$YrqP6rXt6a9PRYF%F6`L@a$kzsY&lIF6=92f=O08>w1?Ev68NUD0o`_wfwr@2 zpsl5EH~1ub{O|o^kvtu;{5VuC+)4d3N*P}l=jgwH>AnvMI=+d`Vq8JPBdp<};#eA_ z*N)|(VH~gjeHME=lcc4~kk{uBgzKn4|A*#K93h0vNge1kljW%{g%Xdofn@2cax~m{ z6fHK6gOl%4g|TXXAx}#I(l|D+Dx)3w18x!3m0wBike=|3#G>0CBWTMS4sEw3+LD&% zxGkMeqQ702plU@4^$TB#;$1H|C%F&EpPxyB_GF_;>PQ;CN*^A?`qQ9!6<8jh#qlm1 zqM`eBlC-82c{T`PORB2BKjmt5aOTW|LJ76wdOT z26^}i(nb{Fs9VfO$80}QJ>yJjZN|a3_`!_tEwn9dfVKnO(O}R%zgkIc-+l0n-EG{`i=oZ$8ni7R)s6kTBb`s8zv_=rwRbJ`@6AK;o(OK>7?!`? zbD9MC{$hMNG`##Q+@JiK2KS$U<#{2T(eHO?7<+~!ZU2Zo(OgzmG!$$$-h$#># z@#nC&{)_d*NR8CkOOI2u;ZMhl-tI5~$+s8L|Q;Y+I^ZOnQc9nC|2&qbtH)KyX|za5(TTt~Oe z5zuBn5!$Sr{#%28#5nh)^GP(?p$kp)j6O6Bz8?<8<%kd_XAWI`O*^D&&iy7SW zs-eNJb+G)#InKDhDjH^OAxQ;?kQbs4VT*-e(>f1|ud*|;xC))-+c3TXM5KF)EOBNr zzym&7cut3t<6a8`zWG32;{Zq-`v*s7K0x!fLeeW=fz-54fF^Ger`5|&4`8pd=8557eZz^yN4{uWpR29>zCe768_9Z!?)}k1kd24 z{ZpZz>@CRG83<_;;&62B3^f0)N_steMQXl`g{F1u7+*WIe)$cp@3wV=?}2narcqZr z52(62lLpKg&-hBY!7rG9&z-#_sE0Fqt5Tp5W+J#d#h-@kVP{CQ4%e5(*oIg8k)*QS z$XoUp!Z=kJ;8_jD4Z|Swf($w>l4pEjMC2hP3FjTquxSZe4BiSSHA02c@iycS5kcC- zb{yRihvx4O6E%H%Qu8VunogcTx4n;{_1;Wqy*{xUe3HA$zt6};On=e+to@}GYrfxpkA$@Z5t!tFBLdBfgRnJ;QZ&oNxzKQqwq;V+VOP6m0&ag22* znm~xVT!74b><$%Q!uX7dXl+lD zz&uNMS{z!K*+4~!ztH8I3{sDn%Bk=wNn|S=KOv5KJqZS?PFz-+h;-R z8o6%pJ(12Q(cji$sJbDdf!C8zoaMp|nRgcX?R!YzTNgCRET$0~KSKS%bQ-4Of)&ow zIMXX*k*BImlJ4(9p7;@jHmbmYLu){6^bj(iusc-3d6vgHOhmgllHh2AJRY0r*f#|# zwy6onpNNM1lM^9r#yK2Q=#1u9mJzkaJW^Bk6u!^j%lO_v>naB}Yd)kKd{3qFEtcr7 z=n7O-9j8J4rZT?eoU8stwCHh>1it>wd~qJoi2Y7bKSo5u!lz@!2v4qGKm_s(<4Dr8 z2gs|K2%(QY!GQ9mAhuG2%$JMMX~}8E=T1Zi29N~f3&=CiMvFcgP_byIaI825^6zeg zG=D!FQ^WFMmCZ!GPa>%i&w=lm;pmn-4_fD`LTi+DH~1v=4*&kXESBi+@^h%VrcZ<7 ztQcP<=gNATEmQ}Sz?a9-BsZQ$oSzG~n|{%-i>t9>B69s&Q<2AdNs`_vA@8CugjNe- zz~%2Cb_|5fcdF>Ll${S}9}!XcY1Z4y&Pbbc%x`QEn-Ba|g)?`2NQj=ehJXkZAPTAGQVp7N`DZYw(L38uS7! zw0@Gnr;%uqKbb~6&V$>#jcIt_<5&@B&zWsIk36S!B&kt=yc>e? z(GZ=MEo5u3fQYXAAo0!5kvGr=Ep%5wh1+}Ks7FVkpvMJB3mT1HnrdiXGJ&WszE5g0 z!{Gaed+3(82wErcq18X?zcu(rjPpV|pG2d7G@+_`F%7o3g5tdv+%SbdXrbRu0`HAL zlY(J1;%5!q<|1i$!bhx#QQ^#OyO1ZeB1u1tk#|o9LW|iRHyi^o=L?yQ8R)cpAmh^` zqWaq;{=q30%fCSj&FxTOYAf_Kd;$gf4GLKt5x=QhC^E&5#}fu}RkBrlvsTFbz#!((W~z%Z;>F`eTFZ$sYLk0j|Y z^FVmp2%$Svz}6rW#1k$vuiR>MN}SL5<`B_`L=vA`fxHnck0ZMq%0HJ1J$j#n0@wA- z<6#tf1zth(?5{-q>qkPu?K&zuE+rOXP*uU4(`I!EOy0cvJt2P?a--+?1 zac;k7poPUc5_sSTn&j-Gk(@f*itSG$(hg$9hLaq>gWazt_awz61-7i_ zLp)_4Wd2}z)Wlzm&zgw7k0bHSUytW`lX*HWfbx5pLi#is3PkKJC-f6~Exdu|8HGec z{S>KLwFR0(*D}6xXtnMGt&_WRk9;GYkLhoyZz5EEX`vx2^BS*Sn z#g4O_rQ?3&1!j_DwOPpfbsj>O^#$97+dv%1?ij!SGQLX2can&@UXXaj&&V792KjHb zp!}GU(EWo86!^9(46AK`0hcg@e*hq(VaZbJL!B9{iU3R z>K^Vi)GmkdUFYB(J0I)L0;=R z2#r$(+tdUQhunh9mL}Gh(1Y=9AtQV2C2?NjsfB&`rH2!s#Si{(6w_J z9~;iSQ3EX;rjfvit7x+0F^w$JfV!KBG)m?nR%GRIR^hS83%^W~b>xxPA%f5a(O}DJ zzQy6%klB{a_y#k+1!SaR4-!|E#PR^<$iKf8%F~U7!}D~ZAd=mI!)Bn@p-E`IxtVAL zm5~}&!`NIH$oO7BtDYOQ3eR_g@4a+BiT=*ZLAAzR8u}C&-xH2F3`Yw`7NZ6ZVt1&W zH1dif)SXqMQGNof$j;^jGLMiKX-|@SFJT@e?E5(nz*Zau;)q$0*?yJrO=Nr_WTbL0 z5?4NheTxPnzrGd9x77=WPk00c(LBb-q1Tb|XrA_kXv{PuHS<40^I?_;&%Y0?y5pdA z2+M%}-~Ia^W1J6C*C0Wn(MNo!)=H#d12xzhJmbi{`Do#!L<0TxvNf=xk#Jw?UDN+jywgKoyhp6F}~Miq|zr6cOskdvHq0$6HuO3EF3;01PW#qL0b3_ z^g3$5Jf21ojoCX%P3%)>KK2sb3T&XY_j_m^tlSO0Pty6AMu(|JLbawV4SRW*@xA2S zO`fv6#A6Z|#Lmc_JQ}6_8R|-&(3z}Wr6TJKXMM{Md9!XYjm|(L*-H?*&;o3Wyg(c+ zf-IRB#y5_|aIs{h!cr1f$-H(ZS0Vpi43sBTGrnC=FmFEd3bbW>%-<+EoM_CSOKN7Z zGvw4kbldL;tvZjO)nR-$_&!VLV;UXCPi7kRqTw!yDBj2C+^^`N#n9a(Fr3BUyS-@C zfEQ4=KZed^^9d@_JGuTdQ;@g7m?Ucf8p&5cXnZl)=6?b4oOO^Te~9t1dYlWYWTady ziMt+vyeaJ6|4|Z@uUIS`ZeIii3G5y@>pglMW8c`---yN%b5aw^Vw`KNX0`ARv}%Px zE5AE^9gR}?mN5Md6BaW*T^gRs@>IDWIBw=tv>5I{0;5@;F++w%dDKJQ&Pz19e+gFX ze9PI$vomDrGm@-M&`8x0LKC~dcJBZXFN}w*ULP2rISMYbdvZq&iF-7Y@x`;e(0VAJ ze?U0gfW_czeIRW?IOBVP<_RB(#@f@QW?CLJKg>qALpspf>ov4$cPG#BMLHkT->}Iy z+3#}#4S#2j;sQI4YV2cqPxg(S-O6H|uQV#~BGj#nrP1qJuwqLAXOq1Zc^mj7S!FpI zX?sHG21BsjodjYQ3uNg@diU5FSv{SIer+akAA*rLRR;NQoHzE0{1_j$vAZ_Ux z^g7;%=5zds#<@|y ze{uB0FSM9=g9OIfu^9CYjY>EIb>WdT`VC;kM#>Es%I=0cPLgE#KWM~z2ccV9z;=f{ zh}SKItbV2}#(9E*I&~syyg=f9WiY-%miID&^0CoEa_$opjWD-3KiK${F7a zcE@;4qqgscx)Hx=46eY6)mOOzcW)xEUrZu}QHPg8 zT|ZkIlW`U+mN;>?bJiiRyn`gQ?L#AnTnIh%32e9i0`cBqkmWXo@hw8Zvs5CwzmmkO z+aquK4CMb*f^yzgAsKWZ3T~xAT6PqARZM1eY3f9yE|AoyZG|7>3(>8j30mI1hL)q< z`F?(v&L`2|=^0RM@rOn-A2;#wk(@^XG9T?!#&-)%4!xsMRlabO&1;PL^BXH-Q#m^o zZ{*edV0U~r&r!&}pC`XEJ{b@fAAqbe3m6}(WoVc}MAgP5zRzlQA7SqzZGKSJVIaiD zy-@IZ3G-T=iC(81&|J_+G(O~z8$YbzM?yZjo$U)P_s>DgF81a7e-h&~OJ4(tM(?hI zYTF|;a@TYeSM=gUqiWD1C5Of7E70VK4vl&}7;e@bq_ZaV$BOXRoLzwnyC2VIc^nlq z8iNpeJp*hvUjp%&Ymnt1&+d^wQP9LEqEo|3`~a5onZaTT*%eUs_>vF{2f%*idPqB` zgI;IYyd$ktqSe$smCXSl`3(yELjp8E)oGptDM*V1=(UXHVEX-L3^B>CFo?nlT4LpEj_2 z2+P&o+znatSe%}C00nKoiRj=j5|0y*=dXko%Gpp>3PPN^6ZYG%x47Hv3^^N!W-Yyl zrnw)vQKkVup0Rt#b$e(z!5D*ey1^&O75w`fyNqenP2m<)!zLOvg1xt1(%?q!G((G0 z76U8_MU#`mSnT!yZpI*;-766*#_r(kpNvN%Blgz#gkzq4>FeTt&_>#0$fOZ z%pK&h`A!zbfl%geDug3fV1K+hq_tb2*Chis)A2XajNU+Q%svi3eVWki;bv%Ae;Hbg z)w;p=TRI=ppPQ>WRFBJ}QOyk~zSV>Ce03Ks-bInXWm#x)bq1a3IRk2cThiHVR%(UQ z9?ns#0gZgukff^5XteVdgc)mtEvxN3tll58&KzKTyV1JeY$BTbh{PucvG-PXZ?j$u zWdkCG;PnIc=jX85d6DRKC4==A>?E4o%g7DUQuvu}j&3j0pk?*|_|sI{4Zc6p`I!FP zyvIWIPF#nIYOxd-NQgV|pDc%zZdVaTppU8nCyx zWoRT`0bzq9z&36x9JV|KS&v3DK6|uwVBXWdLrDB#J>-Rjp@qwIDE-wg6h1eF{q>YAaE09HYXCprJVG~C+uGvY1b@zT=ljwkm2bI3f2>xx+E0hh%whF@ z&)@uito>zFRo(ah4`X*>OLv2$2%I?=>_tf_AfcidfPkc;B8Z4|Dk!#MpeRZ=2B@Hf zf>;O=cDLAZuj6-I|7W*{F+RWNjLCVewb$Bn&v;MHO6@($i>@c`sfSSFP8{_KKMz+u zkI{hen^-Z?oYS&o_vX<@ESEYJMd}`dhn)nd`3{3T@(uQX`NHDh=TV6aCFXPq32lFf zGrVe1&fFGCt0H;4rJ8Vj@GRJBx)p62TTy!9c{2W^5NZ674}IG9X!Jo6zUn@OFDcXd zv47tL^YPDL^f5NaWIOfw!s?Bl4(F_Hs-nC>H*w!5#Ae}qraqa=;OgWs8qj_VD+Wez zT959aNOLbqI8}-wJ&(Y{M}@`VenQ@&CvafeZN_JTN^`FebJay;!>FS;gYVP3?tsz_ zYk5ZP@^DLE(JuA)Bq-=XvaN3dAP~^*0l5k`V ziu_0hkJxZfGnof@8zSL=5kHsHfJ)0Y6Z45iWP=%tMf$0uoWCiQ>YnBqK`k5)7z$fA zDWXlQDC@s_OD4GgB8{0o(Dz_H@`l`lFJC6Wml^B&!S_QjAOHN7{ecFL$J96b1fKp{ z!P!W$8vTvc#J%P+N_;P;J`FL@?3P0Vx1PoF?pK_S=m!*)*-8@jY(dd!@4@5fKu}Y- z0(rYH!-1vwjE_U55H(`^;do9FY(3zQHf_}?^-_#X zV0{~n9*^L&$qD3*PlYcxH^ApEzHZ3h_xt}C$N4F64L0%5XsaqTc%7!cKTl%bK*HHv zK92H-rCBb=9wmo6QJ;r{q3LrY4SaP3%bN+OQ%OQhXCJ>v~8wG_!o<>Juope-M=H*X9{Cm%;HzA7JZwM4MYyD0NYXOz2rb z8g&N1=bWj?6S)Lm3KqcUgEjxH!9U_SzXbE~&**bkXz-Pys~ie2Z?q9->mPvfS5_1E zXJIHgMU?vd41uQjavEe2iRG2!INka6C>phsBqU^@sLM+5c;Ex7AMZk5mn$4#b%a`B zQmC}wg_zY|Az|Z~pT3TL*OWYjk~w2|v-@lzN9GW0y`PFUcbG2c9#qi=e-oh8* z0^}*IhcAhT;qzjCU%wz9?zdn*c1C#vC1rA{ z@8ou961Jv6NA0mZ+n3Y*5Qd_qLrKEsM<}`>0XzpOfoe|%2;lg#B)ihURYg5_KJU+9%-4 zvP$?o&7vQCe+2WfGs+Vwhla3q)NepD=1C=Tc4xv+VMZTWI#>iHXC9}%8p_a^kwJrn zM6i6@Qcf?;14W+)kOZb@EP8+gPuX@*ZJPr53YlG>KWy7kv4;0(ry{zRWg-zLtK}1MuBb z0X}LZJAXW#XV8%7O#NIQVxDR{H+T63R4_LpOGj)+Nux{D*J2ekj`pO%3p=oU<3Mhf zY7B}=TxK=7Nho?T9X!pKgX+~ekZ-322a(m}hR#Bz-cVw;GLnRyJdQJ>*&WnJpjc}i zPp>5ea^9FTO?Gp%>0X6WBD=`MF`A@d*+%%fdOq@)rr?*cm!L0>e|HFYJ_ipF%qPkC zY(=5rKo<4O|ATq@+qrq8^id%sjVv8L4kgX6Qs1R}p&?wD2A8K|`O3xItcH6i=KPu@ z1gN0si;dvvQ^EEx9`e_(g@eJ&hg%u; zKCmq`2yJ>TQ1aaxGI4n_X;9q;Uq4<#-ok0{ncZi7RI49+{F;`3e`7=v#^>b#4W)~y z|1fFHqi48zMct^7{fgC#-9kzGbJTZ31zdUbmad+tkL3>0oW7Soilwvj=M#%!!Y$yL zdI3~B`yl_wGB}vS>N(amqw<7YVx|;D!n#?^C$$LWr!+y)l4m>}MSVE2c?@hj{2OiV zKSRknDKhb_8M*S=8@{c7hCFX2_*@zSpMLB2gKv;vK6l0!nG6k0fz*HT9L$?%%h@j| zLxpy0vUC8`0a|>R`exL^70W!j+W!ugLo7FY2oJ@s@koNF4T>4@z_ZvNR3EN}{FYB} zu=gnA8;!~;TZ!2SH4^r12hP|Yf%1y=Q25~~PpeEDPF&jq+phMa%|la^+3LzN#hW>^W5g&)-g<`gR2rsI!@4F6@2@2|?whUBvXV775p9 zG1o&2P=2lr6i$lfX{67DlR>?Zu5b=*9<%$IJ3uDgoItKP#=;NLa^&s!1fL~4;L~*e z-T#;GfAet$4;8!yHEa!-_C(_tIU2D173PKdbB+$1Q86r+t$`;>#^Xy8ITTM5CkcywpxC)y@RIcg)xP^sup}0;c3x*Ss|Qdy0*GmL0SR|yH7z+I zDDR;G1&4}xYEKTr$;-Zw?$pNCU<*o4mn4&QMadNj*2|Iq0eRV1pzmcQd~DSHZw>zc z`#6L7`78m?a4+L~oWf?koTLHOGchkNlXLvZVr^xt=J8h(O74)LzF($8U6Bf1bC2~^ zy;#l}Mtno@8%tQ<(N+|DRRmsh8bS4UA{3Unh4xJsxSu%CwL&&RS`S)7r$FiK2M zVtnIJTqFs+f>waqsE1I%_T`XxENTUJqH^U@V!BL-gm2x<>gr~od@6g#lz!tWyG@7O z4O1Y!;t%6fVR42jWb&_J8eHxOO$<-WdYvuPoRd zw20+W?vN=frjyGt*6=IB2YGjHLmzh$KD31NgKwl@KEn7kgP?KKT^d-cfO#cmoYR*U zR0?K3c=t|}JnKMLky5z0bvO-qI~vPQb#pv736#jqB?)dvP&~W}yv{uXHPQ%$x~*_1 zpVg}b{y^m~>BN-HBMCofjx!n>QNExH@@krR@}ZC6l%64ENX=mHkZCBf_9&Th^*y=l zXam0`{vhvp2=onihYz7l`9DI{U(2o%qk1+T})LCt3z6b1ysp&#Q}U&kL* znOaBaj|U_?y%1;ISdH@M*mtyX6Hj*K7&x_aKV&#>WIlisO3Xb>rW&M?%d(B|yKXh| zex$*trcdxeLZTmhqXqLtGQJg((0KC&4GQ>(c{grxE>;n!^nDs}KOu*bHv;IYpt*2i zcrjg@y${P`ws5e25lWgGlLQa;d_IVTm7^^{ZGSQpo;(eQEu&ap&QDa)&m;8icM`sS zE~}Y4h4KxWaJp89CvEs0PW>1J8BC+Yre`8bsC*(*b6QFL=lAf(?-T-y<$X%^h4+{G zbN=|TNCD?Bi}7vT3{6A7(V)v7nDm0BgB)`?K~GzJdu@j)%W52&)hoX`pr5`RkkD zG)V9yejI0YNiLAlu$X;gn4!e*Gi2KI2vXn3=KG93f*|D#pX@Hf`<21{*uSxY`Dz$n z=5uJ`MbTjKUd;Pc&bekWP1l4*;_hmNl8;O1szWhQ<2RJ9TQmgA+y`;keFr6<_>zRx zjL-TetaP~z>eA{^B=;2#zuwRK#_pp^cnYDJ%_Ll;31@tKg7SBw;8b}OPwbQooW6V# zwhv*s{`QwB{#2AqOGzR1S!@R0ibMomG59oI0p1Tk)DOOKg86zGUx5oWg_P6awaYMn zNEWxiN(_~6Y7lo-_I`h}gs!Sw&-6iK>AG@NEVG@;k;n-sHTwlg*vM)*qKClBh@GIm z>JAin4u&HptY+Nz3aT6oB{bv&3417mGyc3q`Fq#kl$sq+#IgwTG`(TF35)aJ{DI<^ zwaN4$!lXV_2!+m7B3RCYkF9gyT`v3S|4)3J@dDQ%N{FpN!!g#q^qvm!MQ3Ux?Xq=mKim0#!`n+Dvh!@M;S_-iHDU(9)fzcClnpe zfg`&%vfjtzsB&=_VWM;-Ec*wFjNXUx_bnm!;BMZuTjG$%<_T}#JeI}kR-^a{aWXw} z6sdP$8u=nJ2yU<8Bb&YQ&d%?@HTZ{*GeIz)B;$K%1x>Fs>1w$s%vW^b79Pq)6~9oj zq>0@@e`M*Z=Of{4yER?!=ZCID=4>1g znvW3tndMz4!`n|=`@ttHn2#{NpVy&Tbva$VQ3CS~q_{;kUZ`@$hb+nXiBd!NQ$L{` zIP>-=U4Mo3{)_5xCLZ-Djcz32_y?5K41txe>Oo`G04UZdgrk-+tT%Tqs*d_V=%iO9 zY~pAXQTT}Rk1gP2=nme*Vjaj29}PPO=CNEyEQ$v|ATuJjllpOca6m@{Li{TDIDR<1 z-P73*K7PLL-*;@3yAZ`GOQ1POimtv{hxyhT+@f!5P<8Zsvc!pL9gdk!{iZ3x8KH6- zD#Lv6F@rd6ILi_4nL-k(*t^899lXbDf=1f}C|)}mjvl#&T3*vpRg)5~uYqhRKY}89 zY%cr5WH@nuC2#!qaL9kN8FsMVRh#qEQGCHGA~IB#)V)8B19>YD4p_s7RuOn>!m<XBMBG-3^w{@%lJ zxy~s4nZ>EDF}>j21>mi96K0xJK=HYekS(N&S{|LK>MTXLJN9IQ?Ftkz8-wy}ru+#r z7v5O$t5Co+#&#r*X7vDrQQTC6h@>`>y4ztm@US#O39CKcIt|{uH0cN5WWjt{jL&i> zTpdd3nrJo54;sTQwvR>C;u&Od^JSEp+C%-!nxJY-77e}Yho$caaMYG*S2#wJgeOB$ z@&$so<1Uz4{tilpZG-H^hgt7`CaP|XCS2tX658_>MV!=7{_Zx&Ij+nbrCk68cc;LP z7FJVTz@fNi4G|ToB6a6x;-C?R2u&P(u&aeP=}ehO;Qmb!%vZzsmK(!W`vkhC^DX9Y zxx+2~lZI-;zmvr=-%(0zAN6B*TIHyLbc4@(GP5vW{D%KiElzF<)h#o;scr* zIZ$Gs1KH=TQERy+svh+u+`gkEl=Tvdc(EC|H`O3#kQZ;bQ3n*xTMU^~SKM$EFSxqkM%@!Z>h=_F`C3SIbIM^lxaY7Tk zPjH3TaqO1~d_JcO=96T61#G4}H=Tw&^vC?Oo4BRJ&!hUJx5VwpER<5WqJD>Cq4e%) z8fH3?%`tG|%zBzpwkw4sx=lx^PeZ`_dJt%p)IurCv>ju)9IYj~s3y`#IIEdt-48^O z1G?-RV;N-sS#9*|$Pp;2i-*j zn=_9Yk8)f%N!*-*(zBV)UMu}0V0C=+!@~^ zb-31di>}SE#QaAOxMiL~sNPaQ7JZ6BDZMe&uVpI~XMU$)-y5*Bz?HL5u0}bg{hD~J z0Hq^&;4@+-Xg>&p()(;)#kq;7wa5k4{8kZedLmidvH?Zvn^8X77LH~*8NC~63B~mp zurn+Qu!PJQFo$Mw3O`#8FCr6!m-D4MhP%Y54rTSb9`~vuJHW`AKmkv5{#ZUfvBp zvH&_MVo;{L19DVWqt=3MRLiU<+<>KItt6W-*!dmhw~NA&UPq&6FQr*dP9Ao4KSP^k z$td=?kVyJIA$3c{ap;V4#5G~?&TlEal3@`hfoGIo*DBx+$`Ybv+5~8+4W;WiYb+T3 zlv{r35^7|eA&ca_8Q(|h_j4E&nv~J-0#7X6v4yi-XNU5e*d6=Y0A8miz4r<*c@v$IHJTE-QQ^hB`uY(YvvfVvHOE!ox_OK z1Se8AuK|Z{TZNcv2=7=-;AOo}KlsE2^VKjut*OweAwk#eb;ANF32w!jv#9aSkSr|y z!M>+hoe|TPD40-8H;z)o(&$)jj<^xZzn)5x#!U2nAy3oM^-9=D$3%*L%`L1PT#3!(nJ-EjI)HQiW~ilqxf zI4eI7RA}B!lI+H!%INF~$fRtc9NyZns z39cu;qw9|}VZma5&NEH|HTAT~g1J2?HR~nycaVcq%N1#a$V@EdR&myokD?-+AW42~ zmd5N9@Hu=1^jA-V^7k{~WEiWbau|#1-Yvu=t&ju@k3~^d2O}?~1X=LS=z__2DEk@# zyQ6QS^$SrH+joY@&N~{3+5w?Z%+-h4JoJVe-6Qd z)uT8s{fnr1q>#9_6|wh2Iji$afLzI=G$P~@n>#*@vp(m9ibbL%DKP?NV|Id1JQ0vOLW;_>3C?{a)X9CT4F(5Ip_6))kIC4 zPF&}yqm-@!_1}02PIM&Fh*svKj*j7MyuwjQ{tihx#_yM!20krqU@+?@RGg}W+|UiE zWmkpj=Szr*=Q$E+cmPEs-!lzIH#ks#%BYZc3o53>!k$@*toL68#e&`t*&pA?rE5Mo zV)Zm6np5G;+-i8f{{O3o`yYKAS;1=%$=0AH2yP4>PeV`b#DaZ++{*nd9u=KHT&})G zDeY|PpMD#1whg75lrLb(>vNp#gz2cX?>0%QX+b#&b?|xA3WhTCpmKCE4^?<7{wp$i8_R2b!~>4l2p4`I)?D`>sB8O2-+h}@CE8oGo5)+OB$v`Q;mE+fNW9bF_3>Ts zEcZb__~Zri)d*4J!OP(0kau*0n*$cqedBxv)u6WD58`}<#oM&DQ2#Ra*7H``q+SS)qUVQYA*1E(x9^SGn^j9^ke2kqlU2`G10h3{FZv6=yld- zmyrSc67`KTcQ7rhmJ--I=P+7p{6sOCLL%Sylw4YM07t$rK@vL)UeC>dXQZ_sd($U_nPM=Tm+hwVy~5XN&vn`P@wXuTOxZS(j*}XfKvT-{t0xzkn*k za!K-NcDJw@RlcIxzmI{>xJo}k7q1!6LO4e^b3M6r=otPkcp>>coum5)k7)$cOc zH#`lkZW*HJlWd|mFPdDEw8c?h8=C5#YTXt&TRJ zXx(0-B=nP9{4xMXM+`vH^$=d+N_aYWZ9n*w1@jTc7cdxZ3+2+V^JZ8$?FYB&HbLEm z$z=YG_b6p#L<7dOK-RHP8hLaWmW-_6>?d7D)yR<~c^>o4{#*uM^JhRR{h`_?9rBrO zm=>pk8gH73abE}VE*g$v=1d1za~14fd(FtBZ#kUNVHyEVtI;ZW9f}_QN|XvVk&8`b zIA+jOBrMnSviBxDIhfuLK7PJj!1L+O_!4fw?XYn)d}meMf^;1@lERzN3Y3`-3D64~)P<6MfF#WCQ9gzDOKjg`t#1Hx1AYg99V$ zXymV#SX}U#a|p0PwWxa}Ih@T9$zBA$i!#9^?gX4+Gw%vEvYK49$C;+$#JD$$cztz3 zvDj3mN238dUsxE?aj|eV*b4S%_@UMCb13SnK~#ht$;E&$94lOk#`=Tcr6j=P)|7ti zpPFF4EXH^K0Nn8~rr{0BSm;#2`F~rCdJheVVM*|jZfxR1o=w|0EES{IfIW~2p zdh%|Pd~`7?+H413@8`f0CUAB}5foN1KhJOx&fL>WjIX;APj}|4HZVQaw<(ah@T!r_ z%{6eYA_oq*C*d6CmWz()C93Ni$;HtwI8Lq@jYC4<#iC?*^yk8VYw(Xa2jABfz}L(8 z`VK)mZlfDF9K^y+o?PI{N}TonJaH&zvAC5_X+S^&?9pkao1<4^vE)c@{)P{zG4UNq zF29C~hjYN!Z#S4uNQASAdQjwQ!RC=T;mo?V#JE|EcpRS0YIY`}?Bgofk&$aONp>2X zUtA9d8bol;k~1jM>q^wroympv0326PhQ{0X!1HhC;L*Oue(=o{$QLUlL`}w*Li;gy zy77iL7G|VyK~lP?AC^EI7C5oFRa0p|)Kl2?b_v~FD1$|>!#F49G}PFyK$4r}QSs|G z@D0!a)2?(l`$G(he)OT%EDN0Z_Bt`Xl0jCyV)>eJIjr|M7PdFK8V$~>f|_A+a8O$r z=g66&NNFKad$O2ZI3kAQdBSL1GJ(yN5rIeg{mBJr3g(k!d@6U~?(owzLe&ThkEe1$ z9fml2=q2JXkiA3V2GW2XU9dCPmTvB9!=kD|oKr_R&Qz2l$=wd9WG4&0{yV|!@Fh6s zw*rc@ST0Ui2Q{ZZBgXYt$qJl=;yTi-cl;r27m6@^QT!Qd3M=5?fdsUCF&sq_eiQYq zx#YsC2prG!hKz4C!E+58czCNn?+`7)e1!3t4}!a%wlpGU1{PL(a={rbI6H$9`vMln z*>#8p|Z#Nn>ay1sk)N{^Bt8ivXIZ1wRk4ndkz}L45%-tWtx%;D`#54@Gw5Opa zSHk$Z$nw2x|6F5G_RcxT(A#L(TrnPM7q5h@QA5x&PX|TZT#3fQ=j4J;K2C6{LF12= z@a#$jJY2K7AJ3<@U_N)ox6Bako)@7J-2<_(WdgU_<}DgXz9jZ5SR5z!Bde3MgB?mD zG-}o`ESmd_b1}+CO_N6?WiadS`}G`rJ!8OPY9X9=n#g)LE~3`VKGgJ6W6$SJvRr5u zif_7wvh5Qfebq?Ad^!g%jF}Bt>$jq1&}S6UxJzbEFD11<*sS)aztCjjEqLaB8y=4L z=m#G^p8oIqB{q`rZH$19NfvaI-bXBaki@MSp2cPl@`%0Y6qKsDKm)EeL&o!oG-`P& z7KtQtE^ngPZ1D_|GIc8|J86RN;)h_-a2n1xuZPm@%tuvkLe0!M?0&gOmihXi_;IES z-Qf@0vN{dZ$8^Dkv%Qe@)D$gsBboNYE;6%&lG@teD7@YPO>`9C>E{#hAm?#E_;dyH zWih^8P0-<`PdBB#!NR^)Zq3E}XlQ(y%)31brEXuR0c>7edd^rHwRJcaKEBK9Sst@| z+dh(_qKnG;6T#Qicu7om6yo4?)d0$Xnu8hYnh zz{S9kaL8E=ExrxH8Epkb^MEL+ja!5hM}(k>V<9|E_y`Zkt$y(73FfO|d?nJ*QDICs zJ^O$~!|!n+o66DfRvekP?K4Wf8A1a-*upl?aWv}88Z6B3;}$q{qE_EMl7ehr`tS_! zwHO9-6vLqAtTU9oE@SiJmZ9d;`NX)Rkt}7ofAOzOyW!zB*gDMCP{Z93F3B8*LszDv z#TlkgcEo^ad0Zj2OnZ3Z-b-i_vJ9Sz)WH1?e!+^MZ;V-j`Fa^&%NFPy_MS#c39;ud zms@MZv}k?TlX-SCQF^Eb4IFF_Tcyis)U!4$+%SY&IBW%KCvYUiaWkqcD+XWv9GG** z0BUEoKslRPrlrX4&~aMC`0*g(Ubz@0qz^M~gK9|APcnF+5)GHy_rl@XFVP~BX^*X* zN3=DoN$q$!oTQ>L6_Zf{7Vr%f?4Rku)r;#?vSfoCi zTl-BOd4qP4d1FSPw1fl=oT3h?UDxTB$ud|-HMoV^h$PJ=cM54KMWvstq z|7|k2@iR*6=g~lg`;fBBf^ISP!osn8xJ7}ws8hU@q-^#^)oEwIcS0Um&-R83GaI3D zB=ciswz7QOdSW7^PL}LAhZ3P5nZ}wAr0kTLB^+r5^=46UM3SJz$ZVV;oJw@=7?YZv znmE~&Lz8x0cznePdMk$ZgU>)PA7Ok__o4ISP#Vc{Yen|4-1;@Y5e$sU+yutwAV~w6 z-gxq*_jHTjek{1_%el!#qVAljBxSb;s;)@_pKtHM`jrS=$hU&ZIz7~qGD58_*NMpl zAWK-?jl^*&l>H;Yx50jo5Y+!U0!OwdqIv5ZoX%#F=@wigH4B#G_UwM}@dWc_F}^kFaPM*l-K?5`MX?p!hGIV? zqA|p-BMGH*kp}u@L!y-p-SYke7Vs``ODsO(tSK5K<=G5WOS}(0SwF${O$A)iYJoFD z4cN@zDX8_)mBopN5VvLHQBtRyX+j?4+xW}Zpce{9`yQdW%2J#@SBB`jj3wufs^Zj& zeB|6F!b7H2(xcd)I28!yt6_XwwV`Vi`v!DX$D*AfT-X|QB(*b%-I3ua-MF3xM%;vi zbvtOZSRWRQI>xyRW#g=(0VH*BJE}bk1fPvOu-knUE|ndIGfn4FYw9u7W~HAdem}{g z_DLw|$uuw3tNAwmkMHwAropug&G>rP5^u?DE`gl)dWqBQ7a$iA3lGCKLw7YlPb%mg ziGulh8DDM}blHBQn`7Fs==dEjTsISqy)ucNuNg|em`VfFo4tQ3 zQ7jgf-{Zo+97B_F`-q)(5Xy`crGZ%wA@2He8Xa<*)$6?CmIggQ{nxf6)kGfEkIn`k zRXdpbRUYat7{IwjzfnuL7`5Go5|i9IvanhVC7W3u!$O8{<1b%R*a$ebBm>QMDB`r5 z0%9nCpPYNwiPK{#6vFLInx3Ovonp7$h z+uyrUMr9riEW7}*zdC93p)$-5Pv@4Y_~Y#4`6P9@9cm0r0q;K}VP1AF)LZ_7^NP$z z9j}4f5$yeN?KD}a9*t5$2T;yw5Z}gMzGfT%$L{8!nb$lvE3b_hN#>DrWvur>DiXPe zd*Q)|576b`#s2pHMI49!%>3KOi6?9g{)~d|v9UC2)Eg|ieV&WhcoDf3`o#8XJj&R- zpn(_SAy(O*Mzc9c`F7RZvd4SSKy@ZbjnzSorIWz>S`66R#zXy$v2ea`8ETEmM(u-l ziODAivf$WRmeVvqIgdSj8-Lf}>R@A5wn8AR{2yQAH#puh3C)E6;55C_1Y}gmIW7%FTo9@J7q~xa1>B3O>IWYc%ooY{ z^o~Gx=mi?(u>y-e4dNmPSt336huE%bMVXz4Y2d?45FMLNW8@}a-j8wIiiNk)(EkQW zZ4Jbk;=7O8H zP9d7UYQt$GtO+V_A?HRNM3Il{ky_+JZ^ARUH|k(N_)G=!WidYc_0XN8K%>&-uy~*l z7wI_wP5oPmt-~3VIrp9helmb9^G~*N!8unk!MND*@%Q7VvHS z-0`8r<-%B$p1Kz0D&qJy{_?fT?|~DP@tu&xsYQXr*hG(d=!u->p;(DJLnYU z`=5f|k>-N=dKn+Ci zQJwSL_62#acS)M%N7S5E4J%Ko!F*G3XvnC6OTw&POeh_7^eYJ0@r1arZ%t|Ybtrc| zg>U2k_&!X86SW7>H0cRWjbBSl?2nPNJ{c%hyAJ8;KhXVsFPq=Cq91&GpZDMQXMzyp zJ2n}5W_+bvrftAtB~xzmRzUMORbumt&CTWwp+Ry(VYAaI8gnBL^HvsfUUr|6_h%?c z3-LhB?H^&K$3d9iI+yi+#=@oNZK(O{KI%B0Aap_*aegj|(y7TP_cDTS<1gR!bG~pA z51}d3;G4Q6j&PnA$k|!mtUg{2X-h41vpLxv%Fg}ZvlPrH$@pr2LXZAEy2aE2i*p^Q2KrwFwQC(hADDBZ+*GpZT#hHOWF!2&t68;g(^68RuQ2Q?D-sW z5XC{~DhyqM0ovw8zGb+3fWVeP2dmy0@w+X%ffh&Vk7K^aRel()IV zxAB+nrs65ctx`i%{mD4xJG#&ib6nX-kB3EaE-8rskN`j78_jN@1fUV}&> zYC8E0^f;^1Elssp?DT}&B7Gm{tn?x_y(5`+UoQ<>aTdaNHPP73EqMA{Jm+H@fMiz^ z*{T_a+JjxeOEU$W!<(UbjW%3av=22uJV2eQ7sPbrRpL}?fiek9Q)$C&zK#D|gRk{) zN`D@js@%mXmuC_48;{AE(7`BK3}`xk4cx=E&~7;Bzcu)WkHi0N6L1G*F+R;>&|^1% zZuzk1 zjgrl%`5IB@RXZ`w$RbYO5-2+=8s*z{_%{CX-9DfTr}cBtbnI4~65&neOm8D+#0Q~N zcPyIjS_hp{(Qs#$2>V+>XVgwGUoYeHUI#sxN~7%^usBqPi*_tQ>x1iv?KnAriK!8=L8v04^5W;hIrAG!67b%@-c1JM2C& zW%*<$v&krHU5W}r%lS6`^4(c8p6OYNA^nz&Q(RsUD@-TVZ{<*WtrVJ8?S_twa=2Zd z*bhE_&A`8(PiBRh#<)R`t|^V)q=UsVFSzLHiVs@13Cin}{f|nTI#$Ud>a+@Hpfgrt5 zf>TCaAU0_~NHx=#k;!RA(?5UU?)vj^tL#BP`1s#s0``wEzO%B>BkVwMr#lX2s|=@C{E)F*WqaqJ1!tQ6iwZd$hK5#)J;DPE1n$(*TD(UdWt=xQRh*!`x5F#jU#3+ z>xq--L6o!4Lxr|6d>jAA*Od(UU5Q9H+`-A!^~CPs1yZeC&hlAT(9A3y+85Qq%`^O% zvY_YFQ7~U5Jg1SeU2Cn8X;xyYH<+d~3<1yxZ z8-Mva&&+}XA9nuc?#0RJwPfCC8&dTp809t~n)$fHot9jF60iO_1y{POmjsCzk^n6F(;oV-}A*zEiTZoFOd-*p0u0dBs5ELewlOZ z+tz}5!f%MhfL`MCS_I`6tV6{cZhRYm`MQ@rhazzeH%z?~5>P4!gSE9m;v1s4jh%Q6OQy}`;#bP&`K%IpY~P>5K_+x@<}+U$QxuvC?QRJ(bl516*(F?FZii!F+`A?G1#k4MsGU z+{F^rsa$;98FcJ8MCSUlxnW+eG!_#0G^T8m1jjrcbH^4*`zdK(}7K$AZKI4SKE zaegXBDvL9jHu5esH?M%3!Q0^a0{&SQw0{c)^SLv=@+r`zww1>EJ;xHVl}q3y;{1Jg z$=nu2RLnm?gUuwtqg0)zi6>R^0*z#@sAK$MBP_nTKO{z?B(z4yeb?_uo8OGXH&qScP z-yXQpQwFUsR`i2!kzl?^#@AK|_wMP_*ge0oWPUZ5kW+DMH1KK}@AdtQUvE=8z$(GT^WjUblG9uU`I z>8Nn55S6Wx_%{CXJ$R-9r88Jq&tZ$5Pw7}O-w1_!+r(Mo__+C9(4z2-*s?jY%AQ+S47PkYnF?AL@ZCPCa&A({iSc4L;E!5qn=g3S?03D@`E>7Ah!h-RhOgkTTQ-=zkH8sZK2F% zAsXND!inu&WRdMxQo-W>DoKp5HyzsKUqH)Ne#}k~-x9%my^K$eLg&3}G)~$bOLi~g z5?}2^m(!n!edu9SYB#095eH#O-7=a`@(WMyn!<%j%tqV!Gf2jfDm0j)2kt-SgVQ;4 zXkS_j?cWtpv+@_tT3=7*7&Maw73)zkz!z1FCHOY}@;xp%1!dn7&^YEfPCRKs+&n0$ z*xrV!a{6d7OdGCeWJ8OX*MEHfqmSb*a1D}$*cvd6vCg>9G|ny=OA4*HB-eT9x+ap? zKdnM#=?EH}91V+YifBSlI-Yde#f83cK|6`DB!k6$4AyP}_hZY!$vXk=jy?rVAo zSqsj}y+Y<}IZ75uh|SM9#os?cd%RRIpCsd3Bnq9{zi3?ec`RwT&n49d-~z*1;@~s}l~=8x!F%Sx zqIP|nIC3hUoY=%|ILD#gi)xbb(GCr6mxKE}ad4W_33n?Jq2t^))GR)LvwG#ooaXOj zVUGkV_I07kgBN@ofBBwnuY?M67D=ZqPPDclOH$)Wg~S3>a|uQZ$Dh!;Diy97j_C&< z|C#ys8BHdPZ{2$6=sil~PJG3ZhtgcK_Iq47=q7QvbPJWs#?auL;jqx-Fiq4+!V@jm zxvm(_E#G%@IceDuCgqAx@52a46AAJ1$v;aPL#+Tjz z9Vu=!?#?VM`8A45K6D2cHg^z5ox`a7=Qs^6W#5UPn`z?WH+UkknG1K1!g+DK$ab5(#iNbI%_AqLm)pABJ&oe<2I9Sxne z70|Ux6E#nKK>ZjKVs*-vxE*|sN;Qe7+Q#v1{N;NQIvc9=I}n@pq3}5svh1uqDfcTy z4JmW9Xkt1GCvBj)Z3_EaLFbR3`x3yH#rPU*;O?XSG+wh2OSP_YDG@i(Z5fdH(=Ve+ zMlcO-Jq*sWb7^AnCd~P5$VChtjt;6mWP1{uF**MrEdDACj@K38UXU4dJLsY&d*|z) zdq%9jFbx{R?WjC>8LCNd=G*wo_i~K`R6UA9^t*(@sl{YDtDP^`az~8{6SVm76Rrt+ zK(qate(-q;=Br_Rk0Ri1f)tHkB8H{5hq#p2FLAN@Ofr9mAFA|Br@>vnVg7kNn#i>L za>{;k5gjAYaX>KHUf{;&FSWzstfSxWrM{E7RJWD5_&Z0O#QjlKErkZZq~N&l9Zec`1#<$dxJ`NY(eX|< z*?ubtc@tm2VvAGY@FM`aZj6Iosr9ItrGT^b1`_LSE69@E^{AX2i)z<)@NN9%dmR|Y zdX$V2@(!c0Mj!F$wjgEIA8_VlNwhR6f##kE&}7`7T-8c}d?`Xg)M7>@v=`{n_{t6} zjhE$8uUg@f`fbFiL=;sc_R-+4tHJ(z0Zr0u!yE+%F4DvT=jR_K+rPg-UT_1ry^{im zKx^oZF@^iXx=?dp7tUVoORRhJhZ&XFHvaOx35tL-uNx3-I#F1tiFiIg zL&_q5p=Q`*wDj2s&8CUaSRTawR?z)fI7PbrpWH*;yc9q69H zzVGHQK-KF%>FOaVFmG=nO%rib`5o-pJjNb<7r6gs zI%@9TinEJ`6C1TQvNZf5s!X;*_0&^*8-MxUuJMBZA8BV9Rn_*jaZD5iJF&Y71rcFB zOZHMaq%pBODO*BOknV1f4k=MU?8J_%Uc2ksUGF+L?)&i`#`u3Y-_Cf(_^q|~+H=jU zNgNLSm&xdG;Tl`?@gl33VlMJ{cEdPKpHAm>rc-Jk|K)EQIdiSCu5HDEas?i5~GJsBiUE7PXJ9?Dl)q~(LZyAf6BI2%U_h_d6 z7_uImN_SpPru&!OMNI(1gtwQO`DV`MZnMNlr&k#Bp+ct7um*3|+f%K%7xZ_jqeJ>I zwxp>qt7!8MnwiI7T=j!aw?9WGcTfCx4gSNAvrImpv*246N7sg~<$eaEQGWl16w-GF z=8jQij%BYgdW$}H>ARII9=Y&cMLyVVIaTu7J`0Z6$0C>4f&#zMjQbTdb@>>&o7#pR z>>mY8#bxoD*1RyIxdFve)?;4Tw-kr@{AfTo|2Rd-eL zp7jz=KL@eMDmB396wMf!NS5d3(tYL5^vF;60Rk9w_cmu1tG}>?&4Vy%*bS)bj+1FL z@V$?;qq_O;p|^N0I`lAM%Ln_g^4W=^p4$v28b)+-(j+?3U3R|6JA+or=c^NZ`>)fL zndiCRspF_H2$w?LR4_lj1DoDg0q4;U4JtPOsW_nGOKc6$hmymJ!B z^rq=&Uy;SjGP-}nh90ju2aTOip! zOKATRY=!zxRzB1Mv5W78k}5IrUiau@4`WSrfX2iOllmR3i}M|UEo*X?0ZimG5u9@F$SYsjK`06o|= zo1Qq`gU0q*3q+sPP9Eq$9ryU1m9}8e8Tg`joygf2HnlM|BxoA*!D#Vn|2QiC&sWDHC|9N z^x`hFUXs!5IXqx%5;EV!Nat%r7}i!jL+r>sj9 z9g7Wa1fT3X`rqHkpneM6xXoO;v~C^ux5-0A)>?~`yMoP(d=0g9OYX94CK-00 z$OCd(BeQ@@+qzj}rr#14-21d0yMVNW8&E#%<}LVwrp_+ zjD|5Z742ji4Sb)krPJYw>d<}r9_<%LvenMjtjv2qv@`m{@Yj zCin)|(#5|ga(}Oxs5m)A3OBIFqFa~PtmWoV`_+QGcyKHh zjDK25WEPp0#?(W4v#dfsuquvL~puUkK6r8=H1uMzh5_L*Y7L!nHgf$z)9 z+jRI{E_7p7p*^)=Yu2f;GV>i6KTZKApB?C!b4QUszPhWlUOQNlx!u zl8N6*dOUwMJ^$$sjdiV{=RA~IxtwGxdx*RH=`?6Qekapt;QQA61Rcp62Hi=@Xy17( zTN`namGuC|A3g`uKIiFZ?g={Dyz*bZ|Ix;g-BskQfu~r5X%px|Qatzn`)^dXvy&o5 zuEi4H7R-6DKGe%6a+eStl1xYOz(LQD@ghdrzR&^A21+bS)M89J^NgHA)yOzsk)HH( zrWY@Aq2Vg#i{>gat9n1SYSSBx>DU8f9cRfj8rI-@Ur}2%KL-cMbl-#&MI+mm>IFo#^~eAHGW|2bG#%rHGUiES-_Z<|qb2 zqeDD*NpK>ARwsC%MHgfg8cN%*{)0KA|7Ou57H%+X1v!mbLPlp2>B+4Q^z!e?&{#vz z`%uoN4%@<3KaR&3$3qx<%2lS(!1qHhiH`ME#e~>+v^(^kx!y5mrKLsCc`yW~E6V7I z+iyDj=0_v=+~xDt3BI8Dbbk72zDs8dD(!zskzIAMY+Njx^Kw5lRu1JZ*$aprFXVw9 zn#fptTJkmgfw`(SESkr|z~>Y>o+=^3myhUaoEN=1E4~*iu0fv-VN2m8{g;6BE{Y!ZcDuAFun;;RWp)!RH~L@2=p> zo*Fh%mM^1?i&kt}*c zPZ-?kO^yqjlA($MJ##Fie-4>JW9cgB2UxPH_XjeUV_h)jaSp~6rph!L_{0pmW`W`L2k`s7&c9 zMKvwQ@+Sk>yqXcv9P*00)EN+QZ5}9cOfs5W6tUzjnD=b}i{4WKNms;i6sFM>^~3bM zTNJ$(=aCzKra|)}K~kdp`b!iTy-RC#6(6_;WTL z%#-c4JR5a`d_E@lKAxod8-w|-HyWsXzEX;M^9U=GhOh;}=b?F9+@Y?WrHMx#@*vfo zNRJJXcDBEd1-GnN%!oorZ#X%K9*|tjRDBU0LT@vwq2W9Zk=+7~+@C(c|Lg?VkBs$nd7Kf6@C$sbZ`}+{= ztiVm$t)Y578y?U{3wzr)m!cP^W7Wn|ws6BVj1~Szmj@oC>o=MQNgt5D_^q^an+X=4 zcVaP1E`pmZCi|1?Nh%scFCA0pUD9!A%s4HQbQpMmyDCevu(YvS)q zr*>sw{L6PxdH9xXTKbCZNg543Jr9^UI#OM&4b^RueNW}_ZIaLDDfosrr!z@Sd4QRO zy;|3#=)32!dRjbNw8#ZxBgCAs*KKKnWp^I5{4mmWk4rnhjKZQLjK$=6gJ+B&``I_i z;P2t|s^@%qA1CrPo#p@?Ett*8_H1K|Yfv{k3+-F&Wf~29P5Vv~`N_XUZQT&49A3;e zAN6H>T*aN^q!Y}xe5blTZ|T4T*?;BnZI;iMBKQop(dl3Pc!1ciz0)5^F-|M6M$A-Q z?C6cLZ^RwrTOjFlJuFO=9Y}9CK=NDehs9N0S8hq zrtydG-W00ec^TuobEwRZV4gocSjkT@t7B;#%-)$%?WEUK+e&28$bE)Ap7j$PO#WkXy zyEn|~G*$mprRrn4jo|Z^&&LE`-Bmhq_bCsYGZR(4)=6>u`@$_FlC2o70Ij_t+*R`n zY3f?@VCN%9GukEXstU)7z?Cd+YI{s6*+@1w%1Hl7FM3=4k-mnDSPp*y_Mru{*D_(= zDl?$*>$0#v&14#X__Dguxw9glaOVZ6wBpRC+i6zfZwLJR0`vJlsoK$ss{7VAg3m`j zpR?e*ew$8kO&%CrfGTN<6t6uO?!M>Q%Knc;UfU?{N=l^Bs{;=fvo+KD=STtSSFzIf zI*W@s2g83mogw4Dw>`B^ygIhoB$=6we95;Np>jiCJ{Uugfj#76LKlh5ZV_}*Qj<5`1wU~MZ@ zE$t=6@974QB`$1LpCo86d(B;ql}Np5e;!@Z!)blUra6(G zQCoUH7&dX5)1p_;NX_Lf%OUWAw4k zEP}1>+YQ=BuX9(MuQcZ6b{>3#A@y>!6xi=FR&U(J;`^J!ut1xvWA$mGtC$nozJh-2 zTni1|8ccdJj5(~j&$cZZ0?lh?&@Edi(`evRT+xy)_Ev({kGD|H*JIm9TCx%`yJC{? z!3O8e#-(!Nn68o?(!ujKI63BEyIbZpU49@O&&swxjj3AtCWUR{l?=|2hM`+9TN zS=Yq8txO)$G!LnTE2KaXt6Ae-#^M)Tf#L7vWIbjk=?Y)-hnwN_bDOBy7(X2bIwP3F zbxXE=Tr9@+wa3K1MKX;BzE&+d)5Qm(PvkixCU zf;yhW+O=I-d`>lttV9gzZ~{%J??xYYFQ8vu`8J<}v5TxQ(f_(k z;}2irD7us*a&pr~KzZeT=DYI_D?SwmgDq2GF|ZX?wa=oxr~f|}<$ttscFJ9YPzA9D zc6aFL(5pPi;}Z6@(2x={XJEsZ56opuFO0u8!M2ize@^kSq9g|S6ITBS{S{4PFDZS zBb{F5^m)=lDCny}V>E*_LSjzcJlT#S(d*%JSLn@MAk+B6SKpDYjQ53>aRHPyma-jp zs#vj@Zziod1B;c4R9RC^l^!AzESJw;J|7c&zAx$U-CsQD@_X#F9xWxM7GTri%goJu zBy@HR<*t4?H2h2$4@v)l)b5+5V6TO6o8O)#thxzf{byw5bC1STPx{h601EqqpfUV0 zqz$gj$$K)}8PFQz=mGT3EtP3B@F~qdOILpRK&y{4lsm?;ojcuFv4dEXr*W_dpFowJ z?o!2t?~UM-*?Iqc28B8czGNFZth<;8Hw(qSb<3sXe%{!e^NqRB4}i|SXWTVnJPo`2 z4-Yvr0V(gRrQjb?aG%|sB^2*~vHx$f>amQpr!S;0cL$)!1QDwmBKp9bGG$J$Rx`g9 zmod&a75e%bGL1icKdk8L(O`^we*kUYS1~{JMXXqTH~7qxu-L0j6-$;=h31e(@CC@{ z^AvoQS#&7Eh6iivU|-TYDLMHRwuJO$9-GZDL2nXwO)96M_dzWOT%E6;Rpd`;Fiektlh5b%O7yG95H6<-x%j*!S$Jl#*Nu&oL5P zUlfc9uZMHj(rq-PMJW&ERY=+4B!#Z&hV@g=vBXvNFj+B=EN--+u{G1_yR8G7?wJOS zUNPX6o!NAaNEXobD70qo0(l;jY5d`aCY3|UVwDeRKFFXSLw(Uq%|i6wG{fZPkJ$921Qzh+ zEwnN_gPxO2qk&J^p($M#KIm~)K4|MPf$cgmk`+ZNV#)v$SeiAb(rQ;KE&S35K5+w- z!zWHOZq|Ju)wNdR!LPKie_SgmHFYVxy0l~)@3x0-vbZCj=t+Zgr}NN=`$%C`QrNQl z*l4tbCBBS+$?r!Zj{1l+l{e6j?_p?`FF~VgGfcKtW;5D~9#7YW5AJ0cV7*+X@rUo_ zT+wr|9mWmMLtBUAEMVCxR!J+JN`)+9~FReoBMxr*!Um(TWC6*W#ho&ymvmg%tL@88#VIu%zL_Z*7ypgjxTiC^b``Tj>6N9>@yHDF>544+eNy$=sDd5-;?&P!<- zui^D0jcsXrRK$E`^SC`|z?K#~^x-oke|ML{7pG#gUKmSSGy|qV*#`eFQSxeQ}(Z$sPei&i`K8 z(^a_Z<1p%Pd{6TfJ1*EdPj?_@_FHm)AY zm9bL9B3o=7bC4xHu!LDp5i56UO=GSehr)iG7He(NxqsB@RPZq(m(=?Xc z-xOxEzmn;z2pZGr7Zjp~p{42*XtX$oDaX&TSray}u;I@!e(EwzGTbQB_``Q5oNkwK zjCI|LHkD6Va6%a?%)AeyxY@88Ec)$N>QT{O=NiEmC7-WO@MVQk_3~dlwB-R*w;m;B zlq`qOSq0`bd^7Zt%ehY%PAZ2P5VVji1yb2Vc_x3(_ zQ*os}R>3?he*uzhw@8uC6yT-QjU~sAf!Pzm*X1^i%IJV5tJXuY+hM5xUJFC}AU3=A z7E$-WF#gUf7&N;o)A+;p&mOvK@(p7(gV4r(B@4N4!wPMcU_9qFtd{Fg;ey^&7$b|5 z%Cq5Odq8!6%E?{rCG9-cRto zJWud-UV*Z4>#g&1A0)eBNKSo_s>Y~%%rH7+u-#(hNZM~ zh53?wWTN+&Mp{~;sfmPEUFxC!b*QKx+RL1UofGNkA!3SlFxWd$rqRIHN#!ElyITXz z53y)7_Av|V(~1=;+<{5|5LlHwq=Ihe#B6fcM)1jU9_8>c1#aHFJM9yZ+|a|Ss1Eok zWgTVMo|VOXM)rpO{k`06p^oB2}UONeM;+Uo+?RBBw>v<7cZaBS@5Y^Qq^AY(05Z%oj+IFZ8{Uay`!1W?u8(Y4ctvD zh*T{ddAR9PBwg7gMTkpK<7s`q=lw3jRwBXBBt@cBMh4RPD1I88VfhqWCi&XVe(fstUi69ywejYU#;?A zzW>q2k-fum_SjRbfu{nw-VbWdsbg?I3cc*M31$O3IGRUAiHu zB3FuWn**Pf+gM7mB`gLHBcl&7G<@v=G>dG9))68$_4+o9vK-i)ManEX^cW^cXCUnl zk!k!{gZ-jctkeaX$s3_mf1QQjv1A2aRxs62#nc{JlsBXo<)vl(y9WPZb2p=F)Z=|`9v)YNq!=A3=Bo*Oo^E0( z_g=wbjtv?4n$WQ8AJM$ocPMok3iX#4VDxAyn{#I{i!rIe1pk-d?LNvh8u+>x*U%#s z4`^=ZP|6$4B33+L1$JLxx??e>P9)0pI!JllhBbmONj_hl;ByY8y`v}du&p0a({jF) zeb)y&wxzJ`-9`aDZ*Vtphv;G6mxmvkfus#XrP$5+*fw`8OYQI+76~q*Prf$|lUkv< ziw=~cT0{NWNf;0K#pXKNu-K+!FyUfr@OgPMjX!+X;_1=#NN6q}2Bn>YS;W^2Rxm;h zrZ;b5>dZEjbGrrQ`rT;+U$T6@yMoWdmnw5_@~|R8&44FT&SFpO_}PtZ4|xbI`pMm< zf2Qtv&3O2;_eh%IF2yz7iETI2St`2>i>rIcFnaBLOX}W6&nH71SS`fpM%0n`hCT#jTK_>pT&YTU*F9 z{_wrirzb04h`BR%P-0(MRGTuEe_=e#JO^QF@+-=Y*+e;O7Bqq{RX$%o!I#OXBD)O_ zSAK{ZryWx6`bXILPYm-Fb>FOs5_enqn!33}@`wp-kThU|6tA3%?e&*fYTQv+8hOx^ z6CG&C&K78Ks1j{^Zh-pTYcRg3!{(hj$l`@hM|ZdAwKeUCOrwFXo5*Q+IzjY89GV5C zUiB<0)Q{z7D8TI8eM~*rmUe$~rR+P6dH-Z}g#UfML@>cu-GVBHnelM_NvLs&k@A|E z!Ecc+^Zoi2%q)|;t(!?*Z}sF6&Vfj3Q7FZSzlHCV1uXTL87w_}(iDdwH2A9vT8{07 zw($-kw*OS*?u&XUqunh2ToQCezpKf)k7ODReBImhpl8jT#azXKX#GWpMR&Dk`R;}= z?_-Rq_g>O&yQY+Fx>5XBo(-2SpU+wFUEELQxt)3V@(k1joRabaN5b!pFWa%|0$B7~ z?k3K&uEuA1#7;#dKHDZG^elpJZ4^s=^BtBI?`iU*-86Wm7h0wtg|g}tsNWR1wIt@m z9KXmCHtxklt#z3Eb-7IA4_{O!J*!uN#_#iJeM#`ezGeAFEn&XQ5!OwED64EX?XGy( z2)+#Ye4c{unKPA-*5Kg@%BacgCgpeYfxm+{+wssC?4FmHN8X#d?9<{AMH`V=Un?b~ zKE@7h7nau3AC@ma&}5fD8ua)I6gw9~InEa9fAxjQ+V*ULkqJv2v=S3H`H8+h8)O;{ zd_DS?(eo(LXXe!&v@STwVpMOi{2miwUhx6e13pq#=UcS9zs!dyZ~tVmAvw=yis1YG ziOPzO^YGJ~P*c58%1^U_|G778r&E7S8X3ynB34ruwR9eF^$8O9Op_9aM_@<6eU@fm z0IU8_X|lpK8Z@gCira5OrDt=fUzrROF|%~RsctN>UKr@G{rOg?Ja69 zzLE+?Ct#P+1-A2S7coC7jJqZ7r_MP_JmQx*5~HU}i6winbI?_mwm1V;c5jIXdeXqF z*--o}K_$)^>KE6*j&~AEa`S_pQWmD%-6GRySc9J0tLfzsQA1cS-qAVXEVkQJ zmRI!|7RDW6J@-6i{4IKUf0y|gCOgT0VeBj97-6r%R-Qs#(}|@E!9r z=z~cIMsT;RpVWD9a~?T3ABmglq$FKi?2NZ!X+d*g<;RHk@TGxPwP>~YG1~R~1@&`T zFl{o5Exd4!C98`1)~S17I4Vu1@rSQYi(bCG42|0TXsvsU#fF=+JUJH%%PR~*EXMN zJkq=c66g9$NrxA}uY(6mD>Z@D{%a&~qWmRvm; zdNDOH^cW%2Xy8*dPNY|RQlU{2h1Q+6us9WMmghK2*b~;UPMt~Vg{vv!e%D6u<;dsj zC-|I7Y0shIJi>1kYTGZ83NM-?p!6g2A5aVf%W&>iwUjyyKExwk9gt|WPf9j>1-~6; zEbW>VtX@@+q?SYjY)jGF>@wP`b`vw92f@@nhb_9J$x`f&L+{QJ7#^4_)A+-8F^&H5 zcm<8jeQ5P!Ka1P(iRBH+g{A5+Sl3CEuG)t(tO^^!mn)x-3BFZ7XpearkJ$SewF7QT zMYGonA+zC8Ho6O|9j$D zJD`g8u?L}kd=*T$n6br+JF%3or}UUhD0IM*Il0I=qg>D+IFK z5B9K}bq?0IA5og$TS~84+Xy~c{k)v#(^>HO>QKqedpzRlHq?$YmWp2WL14yK=Ks+O z1~;2?x6_r>QOw4TJoFTaT`i@QIn&|4<~mF7wFOfxb;&^LO#NMpprjFr4&4?*{m3Dh zrk`Vr->qh;YZgI&#c3EB>B}_!@IBZ-Zxlq{N9c33iYsUF9&s%9;9OXyj)nElNt7yj zC8Vp#-Yt3OOTK(QPr;Y4fJ&BK;*s6EqL!yi#T#`I)Ju)+67^M5Ut8{W`4V-g{mCPr z4@1Jw3Mu8K0sJ4wvUI&i!e*|ZNvF?K|29{ll)=y;Ld;|r{kcq!i+a;77A*CXsNXF+ z0VBV=GK~hl-pj1%&EYy|`29kwH7iBVfC9@6JO#`9?O>xilTufCQd*YG=PHk{Kt5lJ z;M=pEihtDbNW)yz+B}g;TGt~eJcR8MeKe$birnqiQ|e$<$D=yTLBgXQQmRKHc1`=m z(xss|%Zw8D3srP%FTRlnykPp&oGoor%+l8Nfd2P`qWsZZrtydGT@}6c z-3|?(WoTuX&Jt#9VY#A4%c_4@*i6u)lt<$zt*7jMB#%$_j>>sH>jdA4XetgY<&ho| zYUg&4N@D&(u+m-@FkmaBtOeZd@n>rP_yv#Bi9|yEVJWTIa_l=60qr$v6Y_>L$Z@5&NWHnW_)f5Yl(PuPTRpk#|vl(Kc`ziaRxew-5d zeEk%-rIH5~>1Fe%mVHsX{ex6$bQmG4{$hdVAHY{V=I%{?P`iECc~qe?5_T<;(sP0l zIQ#`mKOyYu*)D_?wbZvwDB3=Fica58h+4DdFtgvtmRm)z43{LJn*oeZ?2>6T@by!+ zr4ND4ps{{F6cd-SB;|oDXWLOsZNC^cgcuz3%=)*weJ}K*p8hUYevG2x`zIn5pkqMaUBhH{F$0@Nch>|Ka z8o?)vE&TTx8|5kZOm9=c?*%+6vLk9!bEUE$w-I{Pkp<21$7Ic3+`ZQ+QVBc9qX*7M z!pcx7)20eRTYj*NNpoR+cOmJ2kEcG(#y~}P0lKU;g?izBm_@{}m7Tt@%&P9dvox4& zh?Z&m;fqeBPiM-Zk&y~T9WR!=Nj#q|(=fHV2)508QKHD%P3qpG5q#zH`BDVmoKP|E zUA%uss!^MxCY1+|Mwmq~3)(06)_mvgg9}JSy(y12@kGL^ol@rgYy`bFWEpPbV55{r z`depE@1hS-$=iS~Z!@8uzgN^}WU-Y6PAsd>VlcG>;_w9G>m0!%Lj9{g30ScGL1icu`TF}v8dm<_YR7!Q&~#rS(bf93D%>B zz*esdC5#WIgj{DAz(bTf~A_iGKa>jJf;x zIi$S!3y+SeMS_==w7ba_1fLzsM9KqfX00H-?fa;AGY_=e^$uM>+=O~gOPC!}XR990 zW?3&si2Cy3Fdey6rqRGRu=@u3s<<1PN(N~8Wj0G4){13Uc))r=57;^!r1-L{lwjy2 z{wweN+$)zaT0!uoO{e^6^LVt)5!CM6DpeZ2MtIdt7JPCyrfAOQ?o5M}o9glC0}qf8 z)=AnO))66kcUh*k*uR~|q}OUG^~#@#cHb?~ZQT;6?-un@^_gt7*Jrj{^k!#2b78uu zvrOX;U$ho|Jt}6d={!Tr7y2yq_!*X+r3~vt2iUqyq<9T?imxzg1YebWzJ7wQ@;c?c zzQv<`Tv1yq_-+kA#MtdDWKd5`S!>7LjlNUcxHUZbiTM6yw~(?2)F33UC(GO}Y|4_K zG|~S8^|F1A_DkEN+mEkM&pZjUYuap0zsGEMyQ1%~4tJkgOKml;@)#9;BpmJ{WtUz>X!nOK^RJ( zKUSjsU)t#IZ3guWdzjt6$JQL|&$4@~iGGL4Fui?2rtxPD!Zy-(ii2kM1+=_1jivWC zVc8MIuu&cj+ngAR8?m0^f*a$j+b^HbS@7L2puFxWJo^3>)E>SlRki$t$RRIT$PF`0 zdDn@%PuoCkPWR(6TJA`ApeE%^o`FzbFP5cwNSyhRq#N{+RMSk+VRAKkwCWA@^d>NS zn9kPDO=Q_V#+Y=nEzDGV$TS-G2De*G-@l8wR?p6$<=Pk`-_K#JWx zl;RW?iT}!bN2}%Yc?!NSO({2T7LV!Zi`t_DrK*HzM5Zicq1w4H)Og9==V?%z1-3k9 z#$F`0njqx}|3;{o$C4E~0Jfv2l5YD`q&oQ>I_yb8kD$>|Pdx=Q5vy})Va~Fj7r>xx zH<&pbl4<DPjbBAU4uVC5H*I=_zAGUWEQ0yQZie3Ax5qvU#rJUz8 zMS)u>n^3OaHy&f4Blv=(eVWCH>Jh?1!#~1sO*MC4c8}UL>&aub2|tx)cPV#C3Bu+K zWm)ePVQV*oCWP&vo==veW1k!7*?BV5Q%Yd=d?|Cu5#M$jCm2}N2%BJ^OrwEsh~jVh z>6(nOn?9oD6J3@$xdqEk6@BT7#r}QkMKNiUDCT}+VjZ>e`RWAUfNhj>wvNZFc_#Qe zO8ZV4AS!GM3w?78h9!NuyO^7*lwreT@@68@IZw*{u@zzUU)gR)XV`8krU{+(sHY!C zNBb_(qkx zZ&oKI!yi26;vpo4pOf-}_aR(&8QXm@4YuiPNhk6%^&Dx2jvsBH+E?TQB>gR(Pao#` z{wK@rHxC9EPs3b!nM~sk-!C`%_3{YD4bFpNlMgJb?h?yBv>LYEUche5SBg#=NYPbp zjo_=3%NL^{_{`2y_B%};bHPNMpNpjZpU)xM+nI&s6v1fB1@6B69JPMchsS)=LgMLJ zQvN_^gl7e?Y&Bijo;*rA-Hua_GfC()+YhRl;{{(oalRBXx4643cl$q(I*)|8v4>2f zfp6&g=JY#zD8_ktL9xq3w%g|!%f8_cTa)FmGwwstJ?ByMFsnxJ9hA@4Pw>sTP1)XG zd91=W@r|4yRR^C$^w$?GyyY1ftysd{gBDZkh!;Gze$4L2=E{Nzjjb*2B*uM6r z@v+s^W4Sguom57z5vQP@=p()l|1fuhRF?bF2$EfQm~XF=Y5d`PuL%VWG57i2S168} z$Fhyvvh2^BV7u`h?B;c#s3@YSaG4K7-t#H*%l`NI62kk=UPUBUdP>xC zZ`f_RN>Lr0De~8@M(`b$&*v=oc3q*}DNa1r*)!QC5(cxK6Rf_KACw+Cq_IZ^jCCv=W|jo#V^pq`K;Y`7BU5wV=* z9T2|CE50HQ)kdcAhwpJc6kc3_R#5^J7j|MfcPd#9Vqkmg0PLdHQsgcbid@y^U%vm* z#yKK?4Lrpfr0k>Jqwez9kS5|DGF7Ub=8f1{^(1jBITzXi;vQM( z#`1QQu$;J#u%l4eog7RNTbEIU)u2Z39h1*jC-_b|QP!lsJodFMYEwQ*2ZB-%XS|q2 z{L>c3S=YFGRTomcSI=Xg8X$R@yHu3c15qQ+u)J>Knaf^BTEkjXw`t?hrM?<{j*2;t z2~)*AIi9T#-^vO)I)aDIg~fhznMMQO2%B^?ZSoP?zdl3p+9#Gj$DifYe}LV}BG}zG zpzv?kDZEbhUwLQHaru0A1>c>HlzIFmkLx4O*qHTF-SC-+t2xdh?UG>p=qz_X7)Xjc z9e7-O4J22WOT{`xh>ASK@-imEu3n$U>WmoHX9 z@V&35Ow%ts&LRo5!F{E=Bf*H*5Iq{}=D=j|5bl0TffPqJ;c+@zNNImiDn3_)XoZa| zUt6sCJ5w5`F@m}-Jch2(ebD!eq2LpK4liG};kg1UY;y>cmBV1Ew@;?gz&Fyc6Pi{% z5dBA{qm|Y$Ryfjwe7w9bPDB{bz zS&`~Dmg{{1_Dw&*ev~$aEgeB&DkB@gcS=4V6MVhyP=>`;9#?P+wd-$52Y;9&q5DD> zm5>LMjH%rH#wBXG#FWSF+=`SsBdO%q8$@4mWChC>!(MMMjn(f(U1r}yx0%z?@6sB< zmoEIo-PtDgkrj2niOIgpVR=YfrqRGRO1BivR{az;g+^$VY{ZJ&Rj}OSJz=la9QJ%U zg+5TBQ15Sz;5#j!&sp$kOr!Kmhj`qr^{8F(T{>{wxIE!fX-Ce0(()cJuXx*g!?Z@*XAa3(O*&u5!n+OeXjEtq^z z4Ec1q5qxLl^LYxs z$ww)DMgWgj?tt1klcmF2S42!viA67a57WNwxciG>YLOq!N?>kSNjVw+22`V z_AA(L&m>JVcj~-64c+_AME~o8FS&z=<*Z|yqc^eQw!<*_$2nL{vXp5w@Qofd1I-7= zV#19uwC>`~N#+4ZA z^xYKQJ<~8?##+JmUBu#i*cJm*R=nXnri^b5t1UV*jX!)DdT8#s1iB8_(AxGs+wjiv{#Z5a1MDcoyp)3PwEmaxf3$JV%3p&zu?8#GP@4N!9=}}NlP52ij;tAo#5-GA z%&5h2{Myg#E`K zu+Qj0!Nh7UQ``+k?~`-FW=Q zT}b=^upAIZDbmM_%>}six+#K zXSfSW%UiOFY8O_Z*a{BbZm@q|O+h+WC@}JY_^-VEyC|QJ3BCh^DCO8Fo-o1=waphw z$6hr>a`ILd8zSzz?&rBj@A1^k$A!n&TOob_4XNVH0>rB>V|xOp!NIAR)FMt%htGlN zX=jE(&-Oq)OYGlVbLM&6kL__1Gny>_!qmj$GL1icZ^F=WiUhs7o=~ccXO-om?qPu! z97<-xp=nbJEFVJwzhwE0^7t;v=W`Z(m((d`mLpGax`>*0Cerc14oFcs%VHnSg;~K; z?lE`?H5+Ki<3BkdqxXHOa?w-7dz-P+iDJz+9VNBFE2u-Xgr3E#F?hvDsAp@!RBtZx z>Y2^<6!wDQ_N$nBSv&&+4IB8>=N&}L6w$|0+Xro0Ft)cy*y_hZ;Ba?39D0nQK#dd% zn6teRe6sJTocGUD@I6tZZmswR_j;O0rf@8Z~a8S3SfI=tQRW0)&%G>$hdn(+MCi336_kN zC2W9$m_stgbRxCC+6AifJ7b8;La68cfXR!0nAd^!tkljHhOc+P+Mq_J(ZHu+xB-d| ziXhdwXp=Rb?aNVPg~3PRNRQwk>K_9}EvH@G8=G|VGmF9L6HC9@%UY{w`_`_HE3yOP+L>@~IwD~%P?azA4 z3O~odais)@S;@33KZ*P|M2i2)+rMk_`R)q70e2|ra4t{m7LJ;<*V3sDaY#KD$Kur$ zVD2OMCV!wNVYhig{9El-^C88v}!(y7w3NE=(v;=Mn@eD84XVWCJ( z)TZ-);SjME=Fk$xlai=ajd{ z*X8r|6MQBj{{Fc)Pjt6KjmK>1wEaq?rEFvISDj)0GKG8CcOr!|)jZ*!Ey$X#Dednf za#tVy!z$-$!_i_jjmoX0cG5QVs!PEzVV|m(4~EHvSmyofDl02^0i&uVu<3hErqRGR zwnYe99Ww>?k44+>8m!iT6)T?b6ON)@%OO3A{IxV_XY#a0@ZFHl#{}OjRZ0wT;fa|A zsBtclPJi8q^tKCF!iaEK^gGKvX7wb6r89YA_fg2IXeaG2O+%8&A-1>uCpfMSr%{IO zN#*)g^zPz`;mt%oN9AEr*OAP8%z{{Xt7sTKyDDaU9+PSO;dAMO)&mxTb>9GGn{;+y z{cKj89RQ~xd*QHeCHd_iN;})i^4;a_-%a^^&Vp~vK}sABo_P5;YK+%NXA<5a-9wcn zY`p;s+d}TKP?Z!E-|@srZ?Ldoi6-h-}Y;SEY9K-x+|Ss|s(w2k$(?Lj)v|7IEOVlf+qaVP&(6Y!>LX@1iEl{F0vKmLVm=T5VdW== z!q{jSY)&kYX*BSSGZFdMH$QK4OztsdK^wvkn+mBaY|NIT1@ESv7_ zV++{bl1iry=Ntp)V4#4A(rtGuA&O1f9fU}Cr-FcD7a}4kAc`#}DvG|tbFb(B?Y%G7 zdcI$4*7cj2b7s$uV{ek-{h#i%jqwj(W-rK0E`w3OUg+h1nigxP($rr@uuFIdo4><} z->h9^k9&LkRBdPWzu%Fki#T6`8#(>%G7E9%Hk{Np@wWdhoKIaq&jv1nc~b$~?DJh{ zy`s;~7UmtHnDH79w(63Joz$hJ}p}+ZtDN}m z-lhq*j^oH4ho@wh#{b2N|3@3=ndCX3d=7rzCa3f_u+Y(mP;eqfyeG%|;>_4gL;G!j z#l<+b`Rqoa<$*m5S+WPQla7f+8L|jp)}MEsw1A!0cA~oWK9Tu02%}H?LF4;E=-gX^ z=`OG6?t_gq=Ws`unlI*Y@b_(F{4)pHTIez2CybGbKDt}z6V8L@%H%Cqt zT87Qy-*6*hx9t-z&3lCKo4@FVnnkcXb%m&oZY44chhg+94QQ_AzT^sBOdq37cULT= zxg(=tx_Jubt@zM3#((%G4s$|}Z6{&8S{8i{^rdB;vuH-fK-kC4hHaoB+3hMvb}AXR zgYUUyK3~o!r%O(9Ut_2b*B^0r5$~_E>$z}0PGVo-r_)asa={L<*X_ki zKf2?bb|JmEZ5-_KWr)h{7exBr8OZ7L{#|clp;I*s)80nVJwu{tZlXI(Ljy4{KE7>? zfB1a3wo`otj3eft&!_pc>~12>)Xax{`2pCT+eLOY)RG;MZT5?#^?M=O&=8T8Jk5EGv^0F3jL*9wSr%vJAA!k}Rwgh(7 z7DQ$15h87H8**FkLTeGP{ePl_X(<+TkHdMIM+;zDW`}uis@ul+hp%28J;g&XuJJ|R zc{cRw`6`+jmk9e-S=iknTZ${o9ePR&ZQx`$= zm!8ASfs0_hq`7U3fB0f@(W{FH(Pu>rQNCS+%~e#E!1J^65Lzxns`^Q;`_+onm5 z51r4#mee4>Vx3r#y#O)4G3` z+iQ}sCO=8ncef!Q9tNGcJeKnz5K{|m>D~oBXo3G|%yhGa_49>oWBkLnW*>T$&V~5N z82wt!=uOQFG`k=i4&mKk*WZflI8sG?XSJ=hr1RyCWIoFI4s|5Q5)@e2@$1OXIVL`I zEkdm0SbENBFD$Jx+2(3%;p?~MEcC)<#8*0rmv4>3dGD#TI8}tbXGb!oWisjNEDL$= z2hzE#0G%)6FxBS=-5V)GFAU-_jXfJ-BiGzE#y@=JW$3MN11>1J;y_L-8%K6S;C&wt~yON6h(}%=LnJtJdaG~e8Ep558iEV!N zL-=Z($3kC~BVo!h@yfbBIA6VmmaNW({c$@oCfSd4xmy4Q&1&eH@>ucrUziFNy7z?- zy%2sHGvj4oB7pPur3w4m#w&lRXt4pHd8-kTY6Ew6*KSj zgw2V8ZDag12Pej(_tOzzACF;xWe0k@Wh%{GXbi_e{LY=*gKQTbkgbE;?srLh_`PJl zFwS>fpB!CY!@`x8BHvA2eB?3!ao&tZ1pR{Lvv{`ovxe~bQzQ!mL89~nv8><)B2Sso z(xwvF-&Y`GM)EjKo+=cwQlN(_=yqs?Nzq#Bw;+gK%v_3@pM79+zp8DFfB1fGLLUPq zn3(s%fXk=oomabQ?)MIGG?0PaQUl_9E0*}^jc5no2g!UzoUf*w9PQ-I!mXwtUwkB1 zNq<1xV;dUr@dW1doxwK$EEGQ5%CN9yr;)gEhj`WfDI$M-r2GQ?ADhn9z9Y zS64<0%a&r+M1J>8+txP5KYY3K(B~`f12JGZ2By{0dwJ0`fAldp`YOZjut>JmcO>3g zZ9YUv`}3njz7Q!XHn+ojazwuu3+MR^`O<^M$NY?qKjA>n=dH(_mEV|0_e$Z@#FH%S zQY^TZop>$z4WcrK| zd;=Dd!&m>X@Y?Ojdz&Lx_sB;4cWWA{cnfpR_%V+@j>5<2A{O@E0ZCW9#p~9;5Z$Ml zmVI6g2V5b_-D^lke>o^#w81#8eXKi}>lqc9QGdG(TJ*jVv%Dy5FWzYz;~%~a=IEOk zim9&-V9@zRwEVa$Eil^#$KuDZD@Z3>RSpnOgZ9|qZGOFfw*f*Z=NogM9CkKh=X#Ap z-tGBfb#6~2So2)<{mU@t#t7yyxKa3|$XNJLRU}U-60iSRg6I{8=+*2rIM|Csscbyy z@XZ{Gf5!8^X_V_6=Y#pmQ2!%W=%s*Om~|==w!aPuABR1d(s^PL*BoDse$ttkX2Ww_ zMw!tE{<~NxpKbAI^@uo{p_4!J@QiJ#F~Z0 zNXYm~BY$(Ph@V@T$7nC%^YO_n+++}vQ_hMvqO=iRHkV%8Dg}oP_C#s#Akx9LJCp>5 z@fuu1RbdSn?o$8T4`{LKUChc`2)jwgg{A{VQ!a(rKv21dehVLA+ST0{d?J%p_>80% zxL?(&6Tc&0B#|vE!pP49m}e1u-mvrXzFp-Kwjnv1YckDD^|vILtse%mGt4NdU|olbU4X} z!mecy@jj?QHu)@U2j4fzd|{l==?Xa{-<_R1rHH&u@5LuY(~!6}o<=?7{@uA>nTOU@ z;ag}I7Jha*Qo=OEo6R>6<8_kW=(-*bQ9(pWHjPM4aE4NDM@-=HbX_eih=mC>0Fkt0 zMLcGG{{Xwx7U9F83 zeMlYZB;E=QLCpOh^hVirI9v=Rig$yBzwn3Bw+u{(<9(~gO@O$qo(621N=y5j!faqF z?3%g?A4YdFIH;NjqIL@Xz1#AcFYr30R{Dt9(!!aBaI)v`HigT?v!RY`@Z&EeiF^3F zWWGAiw_^-BXx_@seV>6m!A`6lF%?N#Cuwx%ZdfJfGY>Ld_;JINg@5~k)Wc)M+taTi zR&6f5xi<_B4@VHi<2u5ho=2dp8-|JMhk3shd+<&UG$1~lmKH97nI5fXyNmzaN5ZIkrO)+&prWUePG*vmvjdGkjNJ*#rcki z-g?e%gb1<#-{V>n+8=bJiQXju`)&M9m{T2E2D{dopreM9Ii_6H8{ z-VjBXIN^774wP41#l*yG(51&Ac2J-JwUPAl%7rkqP=@_7OX2;DTL$+v6+mvD#ei|4 zFy%FKLtAa>HrdNjWcshB%%5c8P#MrbYgz|MI;LVAY<;@zp!5vQ6;Z|7csQwtOz8VVBicj%;de~hA;d=YtD72#aIKUiqWv& zQ%pAAk0q=w0RQa5Ro23P&dhKUVg`7|So1oEr>X`-3pRiNzk%m=6W&&DG*oRl0W^nUVB}cLlAVX))w%SEhdnL69|Na1Phfv)71`K1o2*)S zupR5yDw!{g^L-de_DeUh^S$~Zm**=sOdf_5cYhkE!?gyIPcV;Fok@o!w^&5SJIGi* zM!Y{Y74f45diPN>9Bs6T!s464cUxtQ@n3-{2GP)UGl$WQN*Z{}onAfs8)o+>!y%|y zc)M5DaLU~6poY6Js6#Vm?Qy{fo;Uf_Y$Gk1{~FFx8n92&BO4~Dkd@2Ye87_S=O4*@ zMV#;N7qTx=m7O zi9-Kl!nc7RF{T+XAnMRv-3vx@EoqS4GkWc#HOxD#gkuL8;Z2pIp+m}I&=O4yy08{z zp7SwM?;5RbX`!Xtyy2|26ZRFgWZhX8vU~~oFW>)W<8xoZcKDZW+h91Hj4}ZfIF;Xzwgl4*vf+$6Y!|=9A-m<26a}{u}Ik*<$2s zZ4+PonS|6k`858MH|AOCGLL<4Nau#>EF#AVS(BHE51MBq!FdubkI{x>oGp>R>Mwjw z8j7*J?!ypcpzEU!T3b$oR`#SfHok(nW&j*LDup*a9~k;veg-4s85r!P0`rAGF{;O7 zT3=*NFCXX&XPXH;-r+^oN_8Yl*X?QtUz^^?zuN#|l=Dq3C&4-c*!ge#j2(DVY)o-S zn(9TGuyh~hc|T+x$ET7m1#v8*u^Y0Y{ltoMzmX9CmOgMZgkw>EA|G`?__SUZV~@;* zVIluUciDqRRnedWM)amJ&v`Lk4#!Mm;q}RdhI_Xa!f5M941UxIbFLjQYSRGvEUA`W z>3HY#~JA2TCn%|fg zq0T%)lS$XZ!R&nho5=3>L40WO4GBLU(28L}aD3Q_$nWhed}J#zwk#O}Spwa_P|#Jp zPfY4&daL_(m|OF^rs;w3del9`1M>WQ%6*0*6S>Cj3`dNr*-jh6H_Kx zH9Kz<&->R=sNWY$*0 zBjFC|(ssZ|;0xn?-aAN;+71@!Yloa$zr|Nqzaf1buPe&jf_Wc0Fprd2(tX@~c7AmP zvg>w;m2uaRcp!{E3|b1Oj=PDxg`Mz0)*31rTtLjw5W1)MIojbM4SHWlZ~IK)HI38Y zZd40nwJZ#24!~@=DvS=(pf3)bp=Ev(;hd8Lhgp_nWvL!nNZaBflK9$k z&?WE{alW8GB=GTN7MZjMIoT7%*IRZVJ?I%t8Zj5vee0P=?j+K^^%pyTHXS*}+TtVI zC?r-p(MmB4PD8#E`H5!2yWd_=ae4-l-vHh4H^9wZG`M>{y`%jO=E2|Kbo7?+a^C>M z*z8~!yQ*TS^+C+uI~Su{Wocu;7h3k)9M1Q6yvnsRS@FY}EKqB+uO;zylgwAg`9ju^ zz~HMavL+ch;oZbHI*XD1B9SKfHo|&b3-h>CL8Obr*!dgP$O)4ZtGeDmlCl=9Z0Q0g z?NdZv{+{sm%T}oDO9c$$pc}glII*7w%kQUm>I`8XQVypZ@tTF&F@|O} zWA^K3kh6BCFZ~A4tIM0={MHu^>odp-Eh#d8tW!Jqx=Z8>m*RZMk4T_s#-e2IAt!LX z_~v;OGDr$dY6yk3jRW(z?n7jDoMGo%h9ReA822MjM$)Q&^ilFNI8EI`E75IOxN*QMo?(!a^E6NuS=`F9Y+WdN}>95E>UG)eET>O~Tzm_C z<#&T#efSeDT~5GZuNzsu;5u=iYT6FIw%VkB-=E=fobS>^67Xvwi<;DgoK3#s+miw^ zc&$$|bA`1>74sv0YvWOAK_JV8dOJa1})@$s*4hV zPFXbA`3}AJayZOy2Eloex$r{cvf&L!9%q&B$6E~8!t(nV$j@9v-vpG>YaxKk6h}BD z<&dS71BmOgwp<2D->9r)K3C4y@Pq`ck6}@~mq?EJKJk60wa7Hlp~-(OV4XXXc|5;B zdKBGck-K?c)(^eK>SA3av+?wCaTA;Z6Nuc4R^e60NT|-Ng%Q~f-Kzm04-V1bRr&P( zey&mdSQXAE`U=neOAX6w%^}X(i{SVhggg_gmuP zsnQO<9+LTdIo~%$5}^NtMU|)_$KZtcKDP%lPamf#cJpCf`H6YFKT3M~u3?eswaA;$ zTdY}|k7WNBw3_>9oX(XJxhIjrORmA8>X{Cs3trH@yBQ=Zj|OjXrR5VA!@QB7FIV3Q z4bNX0)~v3BxUmJp&)&nFL){_&co2OTphd6GJ`ERsM>$kHCrhSZBF;zu&lmYGHfm4F zd|^_|x~n_!Z{~cT#vw=5TKvHK#bkcEMN?9H@mjnO%%jS6C;q^AMc>8DKls~#1>(@&%UlHdUe2VxN zJY>2NZ55tK0 zO0XK-2MX5T=!Xpl==FE$aEY*h1MjK6D1Q%etVcWedQ0Z3<9sUDiT~~r7HwvToUXsc zrt0U&3h7Q$Z3n_edoJ_rzKHZLeZive5_wHA;?wP)kus0aC)3Bmsc`}4J1acry;D`W zw!g^z`?|dMD^Yf$!N>h*#gGVCbl(9N>oG$8-w4BImD3QPZ^wwsEwGyX0t)+<(&j_)Ud4_HD;Ixl133eCMP%-{fz^f6j0g&Gn75o8O8b4?RNGmzOj( zisx{fo@SnXSCKw``YdWy3i1^i#acZ-q#WBqpH$6;({Cdp_pnK5ICTJO>dPS(xI_12 zF@)CsH2Cx{T9G;$7X1dnWv84_?`C88r@#QLvn58VM8RrT4iqj8q#un;=#91ZaCxu= zj!Iq0Lan*PVcP%QA^-CIwdJ(@`~7fEj`PhNO8gblSaj?-WWPKkelnFu_KYJmwTag) zE=Xmb!*-IsrXeiq>@MWb4i{@1oRRX-hCW?z9L{~~iCpz-;o1EkP_y;{YqN2F{NV8n zBN`kcPahiD!eUr0T#|MQb;X~BPUjDU$uGjl!0E6`TL6U*Pw1ynr|6Biqj2GU&mAXP zlLd={i2cS*?bx4fb!Za!DCcvWMEriNV$qdq$gb)ye(q3&?9k3MO}7R%K90;&@jU6* zV-$5hDl3u4`o^++9%N}s+S2IM`CC(%z|56~M=PQkU)4LF+aB=bWr5WDkj zxpR{4zy6Z>Tshy$ImGY5NEXv&B(iTdeVLnf=BcHd5l(0X@P~>5V-uw z6>9zW3q3}>;94pxFv=nrR=f^Y(O?t(Tym1$l(B;Auv9oY?IG?}Gl^}5?SJ|HM;m8= z!=bFg(O@ynXVV)T0=`=X2ZW$hp2%;-YXPVw5t*i7a*L7MdUJHevWCL%xks#yQs z5~)GAXl?B!IM4n_LkLI>pnTIaVGA)D~U~OJ8I{;43x|l#`*U9 z5WiFJSd8mWWT$F~U)4?{=j;TUc4aYaF6uJwH6#P*D;901f&B7S;uHQJ!1j2NF1|9f8D}PnMV!{TvnluSdr^gBd*3Aa+|>AmX=mCX3lu zkL+_v;@5^iF7p$X8;6!%(D2y`Xi~ZgBRxP2>j` z3ANV}pss9+srkXsQ%HxP5KDstlIbJI!CYHK7OqP-2u~tpg(3TAf(4(z=ncAJa%%lj=1jrK&&;_wS%wiJC<+;)p5Smlf=*M5Q{0eg6u;t#BXPA z^ES69X!_{guzA^!d0Kua1EZ&~Xr9YnFldtayr&h?rVOL?^R?i-{|=EK(*K}F^7rEweMu!j05f9YxDK|J70tp=PM2;ep45)m^abL-hNMPwsuGE;RKpK z?G$WUikPQ^BN;UB7mIEbP#`#n&kL_0ZCx>~|Fi|p=lTBRvE-)-!BAhf9Mdx1Lr*`B z=WP6>!9HVXRlnY_;IS>&|Q3IB^6>^ihVlMY>D1P2bo4?f1n@uC(x^Dv< z^Yw{KzhE+VQG5JwLnZUcalZ0s;-|HW#SYnt?A7bV?|n>=+i;SmFR|o#Uarh@!A&w) zY7mRz^^65eOvM-L)*>ygl0MsW5YD;JiTu>{!c&cVP(L1n>DvC#Gt`6OxeOY-@dK^0 zPltu+XSm+EEmTL26_m1M!Sc%>ck(6X#_xxcau@pjX$`%lH5IN=eEn`+AkHq1#A;Jp zoK(^sGE6cb<$TZMiQll_EOx3LvK_9A->+{*p57dqzO5^4M};uYRny4es9P+C`Jmv~ zAF)xH@6TtT4e~SKeETtxx4tAixwr=E1zj;cCIotn=iID&z~4|SY1RHvSXj)4>-%@Y z;~!H5mAE3Xt4|>Ji|Zra+W{pC75X%I^cJPgm%;zh`Y`P|py{+;rHvBuX zb;8A;C`I1QwKV;BcV4fq#5}j#lOeC%Sj@R56#U&Qz6{Jqy7_VXe0daq8`Thb4=3SC zr|Zz@sE!%Dr>fq(PcW37&ENQEY1N(eyf#Z0Zpwp&s-q_bolSGVYIPug;Sc61^Bkqe zU1`geQhK|OA7A4UaO!-PI4;O0v&;6kgKwl{zA(-=IF9UX`paVPTtxOzMe%0~&mAA! zLetNlg{|2r<{9vr4BalxV(#;PfRl;%isz-K?_5P+jEsOwuQ5d4|GZF>kOmFKA25~u z4L#?BFevBWpS2aOdj1j?_Sta5ZsAe&En(cOK(JTVP#Cor^XB+KdGufUt9&}Wz4$NO zx}?Kt&?(|@=^?Rb_`g{3|7hckk~{}Rd=6Bi$lm9RSZwQ7WJ|e;Em;Kl?jAHf^cid& zwldEnhsm%3*(|ohX$Qpfow^IG4>87xkHBC;A?#b0ZAfA#ohe2s_0cBwk^3=zn% z$et`#SDNc1=!&nS>X7~>f;OHU3YW>liF{%|p{7qFG!_no>E|Tqt$qpv$9fuU(vwzw zQ-KAyo!r(s3zhaC1cRq`V9ocqPS6I-%UA;C+@JK1H1|2Hc))E^FE~vZOYD7%h`Hv2 zcJRqb8?E7#UI5(?W*{h4R1SDoyEHP;leK} zzOipb#>js3rF&1fnCBDuLLH&{_I_yWT7jAKzd_H#9|j|{X|Um7TJ?S`Eavk)?6*pI zcqCfDS#L0|X{{(^W8SM&jOlrs{?&U#?;JFSo8@IV%}gV9&q|4z_4an~$xG&w<9rUs z$llxgSlpgt$V!S5f4>=q0s~i?zI!ImrR~c+QxnMWJT(@3U??sc9}wU6o`nqaeELfF zCR`RQB=Yz63Dw6(K;sLsz7r~L_z9xr37B-~ z#BI0rupZqTV;1!_lG5u)@BBRqx8>Q~ciWHHOK3o??$$YMy&nJNI&&w>Xz7kpM`ig(%yP@EU z8%;O458I=a%=5A#8By58Vw=|C;$t82orgCvl2_2zPd~wB|4<^|{9CAY8wHIgxtNtK z4ZTB0F~u^72FrD!Rm($QvCJ24m$Zck26F{d{{b-RwgpNyPOv_B2xAqO8g*E5hu(cB z!Yx!5PTN$7?chve`jK0g5^WqM$$Y+?Z{HrWw`w+oEM3LOlP6mc_TD_euvqx_0T(Qf+^kk z_czF#Rt*(lvBCmwcf5r1bzXvbuS(uuH3mxQc3hjx17rP&QO9n7=)Glp{c=*^w7-Jb z_}3ECk*pnj%98oQIA7>aviH?^7H{|+SvtkyU%n0(X1%9r4MSlY$JhNfhg#l7pga`hNg}&*CKfUy@Yd^yoSeeIxeM;EO)|U^)$G>k{0gOTomSh zrZDLd59KALu$fWAiGT+oPsf0jWxYLX44OGH5^*-}_mqSK{{9@2-NTsV&T{N}!i%j>&RsXwVPP%7)djShE3cU$ljLefkQv4%fNnXfu?HJHsZR zH&kw=8Fl(Tl9qQE1^2EzC$1=v%=;cdrfq2RPyFYN@ju!)ZSjzQw*exh_#E8dMf?Vw zWbv05Bl8Ml9b^yTVz0S0O|1^L+5DZ{97{&`ImqH_35xdEiyu3NAoIvW`eAu6Tz;G- z3O4VA>T|)+oPQDKIlQ0oh3}YjyDeV+l~yjk2@76t?e;rexJyF>hfBO3hig`j8MX~J zHx@wE$kM3uIUX}O7zuZ|I_`V7C-b)5B2#x1{&x=k#m~`Z2T9#ee4c zL}5o+hh;gqILnr%)-8i=z7_M53MZp|!Oy78D02CPDAY8BFrpM}ryy=))&7VX;ntd*`LXomF~*i_$Te^s&U4b@Kd;nhMn% z1EVf;bm)UIrf@glc5LleGOuqsF*(_`KP9~*+u}VE_$cT5dXV_RizUcuA=9&pb-31w zi~edf^}uFcZ&Ja$WWvbkriUyZWw>PICw^Kr3z_e`(2omr;i@P@6t)!$)qfU3^GGl( ze6B$6j(|x@8);BgXZmp38_rh)cbVJ5?UQwadmy&~`fkLStGpIz_6?}%F{7@Xuh0h< zE8uQ@9ZpR%$lRC`!V2%UgHK&DpQ{wJ?Q(|r*-T&wW;>8MXAtYC>Vk`o8s@tnuQRYJ}9vCxeF3k!Ze>s3}^;!P_W zbbCInNYH@AdJDMsSu5NsEfW@gIRuk_g%~@M-%m&Upq4Bcbq(~`_r#Q7%O;d)o^ zSwe*|G9J8Pou-dR;o9po#lQ%**TR{XUOkbI*JTMET2XwXM*KQ00a?dx&@Wrd;p*Ij zDBO(_YMw5J=7$`vC0YZ$PkS*T$D9Tw{-Nbp`5n1F3+|(Xgc~Mng*EceU^4g{R0f8_ z&g~8~#=kb|_C%iN_RQyehHzGWLabEo5~Ilfiv|44`Kc|Lua5K0cuD*UomgVW708I4 z$2!GGqcC;~O|B@0?R915C3GSRgR)tI-gT7d`iWova9gj?oPKG21J{Kkh{B6r!V`Tv zXmz>=OY;cmwRFb>+jBH1q9-lyzKQb%^RvG|xW2SRSijdACPNIMvd9f~QFEbDaKWg1 zH-3-2eaHDs;5_j&nNv2L(DL^9`E?}nMM-f!hfc(=A&Vty2O?w3Q`WiLPZZXM(d0#K z>o=EqO;aZdzN1;f{1lX&=qrB9oWtMB-|5$_1L3-&3sLyFU3hZ(0knp=!IHm^^*e6E z`0oM@I?;>XAGeY7iG2MQ3D*KugiUWW`1);v3h%#V_vR!tP5h0z>xI!r$KG;2bvT>U zk~s_S5PVh9E)R~gi>6XgVx{-IE{;x#I3qG%P3_+*tP%8!M}W?ZJJpB zZUaQQa=v{Y#NXYDC1#yR`sYB_MP&(!wvM8SU$`B6=@0W-c#S9~rLctNR+Qd;C4PVW z7TGp+w7KIsxNeIhiW55vwZj>-tfVj})&Tm$<1y~qavHSh4zK;FobZJZ-e4dpce86%t#B#=XB6uEY2j4i!e7>A7G>-W1 zTf`C@jv~GI73<=62}P+U`P*?}2iLwZ>G2e* zuj^s|?Ig54tc`O<3ZC2&7b%41)RWOmatVwjQL4!-e{`NB9~NL=m(&iv36lAWIA8Hd;{RNYB?)to?skB6opBMD2L7Z8 z9=Bkd^NxA#3L#469a&=FI9%y^N^I#+itM5h^t&I0>%mJzal>w*E;sN?KPA~X6D9N2alUdF643J)OIkJx>DnJy*Ely^nwm}HTi3xhYXI}w z_lYR$KVpdmcX4IqU9lxM3fc8T=?`fUuE)KIqF=L6ue2OmrwU;8IUV|jNBAC{L4!=S z>5Y_3SgaZjw?93F5|abMUIjU@KkK1ZQV55%Q_xlIVkB)5MxU&o2KRk6a1I+xEIvn* zDaN1M!Pl0v^Y7KbO1FmOfiQ-vDp+00ZwBjQ$*T@0-ECG61#WV=r==HKx?&s(T zx1WcEV*5dY-%SekLkH?IfWwDF(9P2{lHNFiK2^!#eBI%k(2H2awvx%tZMk5Q)^D<8 zJ~__!?K25*)?rB{2atCCE9Nwx>O1OQ~6D}>u76Lq4 zz_`Yxy2UCus$7QN%ne4;C%x&@rP5!Py2g^`7@#cVvH1I0SLBc*^yi)faE(qR zikF*(XS`pW*3EgC`?w4A=O#h-aXJlBDWz9`a}74G+2Qs{S}0npCj_aug1s35^}{{j z=+*;zH8Dog1<|zj@IAN(aT}*Zi&#v|BomX`0nQMuet70A4DJjs|S7nZck5LY{{5L-{VA;-a+wsh(S*Mt}v+J zYQ|!o62BiDk3o024GkKZK(CJGwHZt2!0mmhP`K%>5L{6XR$mSEis5kN+T{8xj~Pin z4WMIq>Ckp!$gf+#1P}XE-2D`yT7QuL;GP zvNSfy1-7xV%&Yh{8Pl4>lCtLE>VkOj&zwid*{n}nd@A6Yx}7L~fY4y`16pq*dC#J? z&|k0;I={x#pnf5=jQ66pSo{laZ*7H(-m=1e-vwZg>Yy=j4;*hyhyI_QM$&(K(z@0I zaQAP3bJZwf&b3V^^i6Na9u_3?g>gOu3li{QKTF>D7^%NzvF;y7pxE{)jipOr8zaTM zZaI^&R_ZM2)gD~Eyi)uty9_y8zp$nG8eFp!iBd;FXvpL?T+4mT%i=cN3f|8lU=a=K zcA8%CoXBGxC*byaiEzQEML4M92zF;1H0I8N2O%f^JpHvY6|Q+_iPE4^!t=fxpe>z_d97v8U(a=(hWw?0zj^I= zoIETRs>AK&9-&~Hv~cLoUa-rnpmDGYP8!A-KcdP=#vqnHThJTsduPM>{TpKL<3Yw{ z{GTuKUu@L2yjBT(b)3(6FbULI!;){OAoZX*lTOP(aU$;{xu_p(&+lMf&uq!qpL1BU znGUXPf61iCO5~JorN5rJ!S&)NqNG~Kb5{RCdx$BljWeO|y%XBeLuufr3$*m{Vjhdj zg4+voA>T(yII?j&SY9+VZqI|0Z7asd-7}K0384*qzq;>!2Iud8iMiDpGH$@ucB~(j z$QL8U`BrZyftJr$@~>`4b$HKY28>4W!=5zyhYZ(LT*|!O)ex2G-B|LrXk2?@!=z5} z`jwhJ^!Hqz!&V|slmuVl`OUr19&?8G&)Ew7oxPwv?j{XvY^0^qTCi}R0=H);guKmW z!m%Njz>-C1N?(Q3&HSXT)4Rm*{)9XMY+==9A-mz8^{8 z+7m2g>};ftv1c+HLr~m$fJO&P!#3tdXN70=H3Jc`UVVjgY(ik8nJD8CZl7G?^Zp z;?`n9iL{YSz#jU1{SCP9D1(daVPf8OBhmZVR+A#>`!klzM>*diHxjt-G)u7xLdwT5 zCR3?{5~X1@dQ1jvLj~sD;R{iz_{)-?Kf?9k7S_S)F>+=4(pFthxZW5@lonVBFV^0I zwlVL0&?Oi82VX$T!hr_fTS<$(c}}N`4%}*I3ONow!pYfue;(TdO`p?ny3PGrv%VS0 zguBoea(ZyzJ{T?o2N1J{LZY|)VmtWS;;sMw{l&O)zKDk;Fs7NMY|BSV-c2SusRAW4 zqG?p=N7#nUXWl(_5!HcfS<2vpxc=-j>yWYxxudtz*3-#wyB z#?U{h1I?NxH1Nt@da0xj&t-_@d~!neG8#avVIYzy-q zJd~(fRI(IPXWSSc#5(rujNEa`^iRhoxZd|9N&%aM7ayFV?X(a!+qy$PjQhlwuAzYi z)9IytVX$x<%K55=ES+P*nbkwUyh@?@em9(Zuf`;YSR%sdGmSkAc$Q&iUhb@`6h8a=KQ(-A7<8hmA_{5aDj^VM;_*H=j3 z?^2ek-GtYF5%(qM?2qXStd#h%DrHJSb$yArN7 zSwyM$q|mss4%$2a!glNr=x45nMqgVRc(yw&RNcjM%I5JqvPnpLTOowK-UDW)1g-tN zmeW28lb^3PlKBxsUpWQBeX})Oj0Y35c~gjX>*4>d@xRyr(YvNdZD2w&v{(N+AKL5xZ0Q&96JpQ^IXoi zKuB6XRERor2&}gsv|XOVIrcUTzTPsDRg!E#-eCff-~RXbR(xDb@CIYJ|1dA$16LFTaqHAE*7=J%a<6SN zlJX6K>$^0fteh;obXx@Nd~et(Cqn;WFjQ+c(?IukG{4CP7PGjY>UB3EaeAB({Z|`I z$`sm%&cQj4_f+%pHj*8eOy8ay2KSY`zGcNMetw1$jfej2;4_oV7smPKaBYKKD_Giu zL?lHTvEDtNqcms~jWF|p?TJ9M;f?}ySC`ZbTCx-ymqT8lKF<#3G#OMbpw781t15MrHlxW4gt{#$-OTweo0 zYLAgD*+bvaXt*yQ0GAEx`5if!XlQs91o~T?Q7|fsKkCnCxfy`yc!J za^D=seqQs2&&+kttXb<^=Nf^exidwpISwd{59a%7=)B(?EtW1{#Vqdmh*Klipxp9> z&^*=(X*K&~wR@y>|8S8RyF^IOpDu-E`4sX%-3*(@&0zL-IbS=%iKnkSMVfyvD4*m= zM;i5!5|h_r@FPoD)^?=#d^1RE%4Dr!@w}#bDg36jgKuCMb4v7MJtBYi46BO4T~zZ` z5g+;cMCQ@{MBPFXYav=)*^0uPY`!my&X@H`Vrirev-mt-oC-EZ`Qj_0QL~mvtLrQ` zXl?|>=c~-v|E5&kKM0mLsQ!C+By3)2!)!wxUpufRPphC>++fm5RdtgRp5B*^YMjU5 zYc{Yl`vsq8tH4_5%37n_^4IGE;5Vf$d{=E?PUXj##VdN<{Xf3{7~_mqxdw@9v<9KY zEb_6RIF&{|qgs7LYg=^`-gw9N>2HEtR2Q*y%M;e4=`C^UWF^WA^hKj79gyB?liZ-+ zCn&yNXU0o>rRr_;4tcO1?w9EddfNtOrmlQ#?|Q&?1ECQd!M zieopQiPl?|qVTOL-+N{?+`^iQrF%EC9^GDwQ%|?yl2(yuRA_>9gI02bDV|XLxJf>_ z9i-}?#P@t9+{pvd=2JCHGs$C3|1v-8+@Jc6wnKSsv2-XgN=k|vj=?GJu!<~#Pn|i? zMImeX+~RK@P%e2A{YE$KV9vVVn0eyw?^o3~JXSRyC%z-iSyYc)ak}*Y96Mw$T7RuW zk>-59*LekLa!-q;M~AZ>7MbF7msz;vnj{(v{6XyU))=kmk5wdnhlAk>c0?B^@tpfWh(Mu*#kR-zGG3Z1+!DD_|gh zyCxHUO44ZWjA710Y5qlf`qx$RxvJ(<5MO30i=uY5(*w5S*q=Q_8_%^U>RQD2JlhYq zp#EZM>JQe#u0ou48iz}<=S1URCDI39kQ?M?L)qXQGtPJ?y(rUzz#X<~ePL3g z$Jc6P@>KExaIqu3SdoTwaB-A$;zKtK-g*gEZ%g6ZCK9}R6Ip9|Eq~Xm8T@?djy$k{ zInSo~5aHhS;QO6V|Mz!tVhHh-2e7CGt;FfcFUj}jnrM@4h$8y!>E|aNiWxG!b*J%Jc1{|R;wvY45smjYAv2Jt`}U$V_umW zC+&AslTLGv!An}fdaNIO^=T$hk9=8+dgI^!c^ZD6#FyNQIbW`3rZIu_;G3YDFPHe< zUt&>b9mMIZ={Wj)s%X1%CW^+?@VIQ6A2supSbC!~>oM%LIQ`-eT%H~$nr!}#^hJH- zhJ*G)*=#K{t{X1Bd_r^Ln!1vQ-)h*l<}l8V;SsmOdGh{HxR}3%^7wOUpUo*L*~<)r zXLN-1N@sfWcZZzRMb`Rj5&zI-5B%K8BOv25b7`W>OgqKZgYWkqtJuFPHQ}iq!J=-^ z|6jcgN7JT@w$F4>z>TS zV!rfhg%PaUJHey;HEg?%ME5#p9+BzAPrEOM3u&m72fU>{>fTZ+_1q2~Mg9j*rcqAg z69y&SleL1k@sA#x;5Y6Ue9wC@mtbpVB3-P<{{8NqQ^BWCe5TDVvL3d^B6&@BT(K$?O^=bs$YBq;VfIoe+dgF`e2Vm{s1R0N z9N|%|3tK&Hbl=;KM;y!Jr*bdCMW>YX`~}kP*RIl;CAH-5V1YjEBj9Vh9fNzmm9;{u z_{Xn3;5W7czE^9ROB&TS&;5?i{_p<#k1>vi>NViB27NEH=pIW%^0X=(wY@3YxAaC) zOdGy?%1gL;l!?Fw&sdM{79u%41XuoW7tOQ=ApLAJx#6?EPwrBe$} zH9BLBE};96Cp;pq7e8ec50@^Ki`-Eo?YfmGot?c2gL_m`e1Z*5`oRPvL3B>h~zglxRSJ4G@H5`=_SKu^%go%b~a-sGb*GSdtX=?j)!N*^RP8@ zgHcT-k63qvpF9k>bO?lU+ev9>*)b_?VmJnOvqGQw3d%`sg)rJEYptx~pL_lVKj#4W zJ|w+^^=8(+#=IVUUaI**h|kNPMSBbo$vJm$*EGkGzrOs2uJM=fl7=E7+6Pad&C<|j?G z;L?WPS(~p(JF-_v>Gtz5xGD7y?xno{fJP8I&dFMmFGj zP4(|MLB(%$5An_J!=nG_E0SNH!;!SUqJ#Y%6eZX2UD3v*d+s6v4L&oAhmAza#CN!A zk|(r`mLmP}Ia%GUACx+cnaLJ6sb*7eSXq$YC=S5ZS`$X{3?4E6E6oxe1D6&iP;P7? z#h&dgWi-8yL0^ZE?s_!wT_%0?DOqc^AOA9e`T|Crgzr0VHadO+>uz+b9{cxOm#l&> zm-s>&vgp;nL`sJw9NAzgI&9BCQBEG;HR3qjM#YH0o_m=^!8VZ+8HTHhbwVrT6Vl&3 zk<|k|pwt`AOpcgIHF*bM)hi30V~SyGX9B~weR)K{ZGNH`X;zz1-{v}9X?seVlyPMd z20eX;K0j{3cVI&dSxxV()yw&pXY|e*)(^h5Zfx|OY0T)9c0KrfRr6I5-}>t;ddCxy z!ozW7<|xtOXB>*klK8Ghlt&$YPXszRGK+mnL`t3|u5K$5TKDH6{b#ML9!F=afs&cz z?2>BUO@x)T20Z=TVB60ShH-!Lh>36b@nq_&(s%%6xvgnh^B4vgrjttu-I{JpA z=$akhSvUl4LySbA{E=CN3=k=wAK~hy(W3c)FUV*TFRSNmfYN9xGr4w5dabt*R<_OI zInNii1HZy>tOJi2De>dX87^w)pbTFsZOtwsi^r1~l(Q8!V^YXZtQ%-gyvPvm0mB|0IPm9dt^f99p<#C?m^%2fr zFF?7{P}=-CM#>Hg!=Rn%usN`V?!U_zW*%lik zHJ^g`ZZQ`9u7yZ>wF`+=HKJ3PABx^w{&Wc0lxYcSfo z9vhjdo}Tpj(h*omzu8i6aFQb{^xcbBZ0jl}-5Z|wcET+RZk;=ayale}A z?Cgc2pHKLX*hg@)i5G#3beQ?0-6FNl2-k|5ik7XOAwztUH9U=>?6r-VT5XnIe@TNC ze!?^DB5a*LLjP+E9?{I7AM2rn^Xr*VF0PU`?!7AI8cm~FoSP_?A5U@mO$>MMM{#;6 z|2`)aehvevkLfcT+o_Hj_OFkoY_e*;Ts7g<@;Qq!^%SWyXwKN0j-vBPZxlDw;5(+c z!_CTF1TIgf*|BZJ85=!Zdlw*D&Wa(guG_N4pMcVGJu{W3N^iREf|XoO9)(FO=^dP3kS6fYJJNQXfjIHTJn+q80iZ?n@lJyjo8>}7ns3| zbM@exs*>-R8u9f>Widm3iqzaUqB|q3s7z_Q8i9EdeAwSyVEu0^>CU1iR zY5m!*Ql5`5290a}8yU zoLnevA2HK8iPD?tZ(uca96YZT!PbrDt9Gp6;rEmHk*5sK51v3d=Z&=9bi0(7ycmO6 z3T*dB!?$}aMjUD?YtfAQpRF&z&uSMG{Y=@|WA~ZC-pqRJ-*nY{ocJb0vKX%y;!KCT zNYqaiU8VUbZuyJHQa;Yj_<{&LN_vjby~NqZb5RlYRJ3|B85v9V${Lk1P}E| zH-FI^aaasIug`$3rvdbyIr8vIb$;ZK4ClM|p`4v2t=r=(<^BBwgKQhXHcy7H!3~Uf z`%%_fXu^Nacn3dAxGB2DwR5ggtURtOBNy?X9FvvU?w)d#+t(%3Bw*Io#e0%;gF9?3U zilG?Pl#P8elsuu<)q`)QYQ7NSTQZr&Odl`KOuvVOFEyf@`by&a$YWRQ!_DxP2+Wh1 zd7B>MENP}HO1_HLac_{Zwp`Zu`2)&+f|+iqmfn!Y&uYX$+CLe#zN4WR9nQlGeE5-} z;Q3Q^8_S387I0;UQ2xQcm&bY}&>Cop!0R5&>}HKPdv_=*e%+y30r^?R zn#-EH2~ZB$%S?|JN^fQ!hn3?fcwV7AfZtu{4L-}mlXdx#2DWg%8cJu-N-6q*xs-o3 z34>bv4LcK8(#L(k$ft#})~qx9SDZckEE-TRtjt_T{mJy#T>EDY{v}SIqnfXZ_)b`} zm<992nU@2RP;gCX_uNirY#NUpz71~rk_fDN#>{dzi?lXtQQ2XrXhSm@Gxki7HG7SM za^OK`nmSf`6JSDo-{}td3%33N&@ZzWRfi9dQ(CL$9OKVw7mx$rKp}&&rzp|A0~oXQtV2r8i2- zm5*8v&x@^R=Zdq_XdZA}1EDkiDDkc4vF%CosMAygsjXmUs{=*a z$-hwP)KRp(T7irtGg)(VZ{mB;OfQ0de=CS@1@VQ$c4|}TR(|8*yQcBPwZU*cKaS3z z94V@}jZ`40e)Fypb~ET5+59jZqgKgUQ(o}8Kb{g_GbkqBV6NN9yS3rp_28SYnomJ| zweMKW8V_-H<3l8Dt`$0GPZ3`MkJZeBo3@4s(rU`g7K|5Z&n}_TNQjOW zy4}*~eCfuw{~$e1w;3Xca@}VBw?(?PIVvZ&6z!tdAS2mO*7PkSKH9$<6yq!mfR(ce zJTJ6{EonY=PcPu%TP%5^qCK3;8WUf+6gAyTD)5~M`PoU>E#C;=rfcAszlCbWpLpHr z0r2ad0EK5?=6YO*>D_r%559$}`SuWBw`(jW;tz4Q`VbPr%7kuk4)F!??VqUkxSP2M z((k~`COi}AV^*PZ_7%~thWvn29c9e`@+9I;%=C^e?Vktn`4Znw*iP>c-9v6XeB%M0 zI4%OtrBn}?-A#%bX(1I%+7J1$1?*_Hm2ZCGOD5d1LXU4u-kB(_`1RIfs^XB0(k9eXBy(3FVukuGD zDM}|&DwzBN@;z7L`xCzETZoVDNIyn=fy6h7__{II+y+c_ zN^eFQ!pcPf&vO<3?;GA?#lxc)@EYu)6r z>eRQQyHy1FS}`-1#Uf*UGAgI1h>m&@$Vds5HT_N!pEEOk@>+VM?+>fd!{J#nmH3LF zyQv=!kL<`3m%0+4JLRdaOHm!BNCn|*Ay?2HxuqCB)t8BHyR0>41+ROaOMGU;w~)D( zoM3t*f7gLk@dc{p3n9Mk0W4?il*j4IV>`U2H-?u8nwG-MycyZ| zHb*rAr9c^^ zE=9FDBo!RK4*3FkJ8a9O`9^`nN1EzEZ-}oO{0!O=Up{laG?D3{RXzBA>&pNAj6J@G z_>PRBJjXtfKHxAC0miH)b;?84xk^h!)V-d7KVrFx>$oT1tN|#X4@lJna99Ne$ z$0QTqpUm|2CFwQ!hgiAxf@c=#Ri@8@Zqz#-zABn0-sl78Lh_JXZ6-yvE|m(doQ0e} z5OzDx!RPcIIKG-KYgq|i_iO}tl$?gbw;yx8RmJprtgZ*&@7_5Te7VGz)t|)-J1){E zH$uYVYGLs06XhBGc&sDo;mo&*px`2A7PVevS|6tv{HN&DuQhp)cBB}bYT@h)GyQl+ zdQCY=tMO*=JhOxNY@r*zi-#|p&5v~20_Os%1;h-MqB;gkg&GGSr<%ZS4|%Z1&|KA* z`(>>zo9Pa5gr6?es(kM=*QY5=ud`V__?D^Wt0KNj^oFveJ8+#p5*FDDL$6vCYb@Zg z)R*bj`-un&AH&Q}C5z0-Ur}l5AUbV%jEwmEvS#0v#5bFnet##`l+J_I#2|Q{q&(HM z*U()R!owHO3K+4&{Y`be5E{i0*~E5eT}y3M9{_u%>)K*F7qSU)T0fC{MC+8pD~M#_#x3 z)%mhqHJ?85eR#y8e@G(zsSXnU*dUAyiLZejk3FkPwW??lMDxhZJ8Tx2R~DnNVhM z!bc;UML(DAC$w5KNLX;n#_E{Qjyi@7%Hy0i_Ry;P#$Nf ztf|qN@*K~ZS;r32t1)w6rHF**p3d~nx(?kxrtok-e}2@P@&MUNC<_!))Qo0Qkz50L zQE%8~k*8zsS~xzV-m+~IdEJAPwS6vGXpJw6@B%=cP~tO2)CadMUD(o!24TasmsHy?;^IWyD$BE2kC zhn4?8cl?EeXNrR2#O>0lJ8Y>p z*Ljx+$_6w4+(2ag@e37^HKNN5s>N;0lr?TrY&Ot_ne{v_z3fZ1s;T6;vHdn|r#ytN zuO<(7>BEn8ehBCELh3#KQ;I5*rQ+^+kjK1%U1bEk?J3Xkn0h-0QJ&+j2K-w4LNT>5 z8#i|<(|z3hpKthIV$|RF%)j3uC-x9u{{f^|*(friS0ce@fasp|gU+BTzC+;;w+Wge zsPqZ581tvditmVufK#GN8O3nxr%|ngY5@b)m{~s?>Bau%u$sAn_(=0OWgK+J8}M+k zjvotjAm2*T%zc!lsJhou@&3PQCRrQUJ;{UDi}P@NxJ_=>mij1f)xodDVJN24_qmL!`4eBnX@3b zy#o72uJDp$;dsA`+%!Rr*Hw}xw=vZk=gep08#ZLRC-dsDf4_5)|NecRR3pAQbiSA@ z6`3uTBf+sw7~gD6G57|);|1k$W(^WS)uf5vv`}OZF~qfpt3}tx4UrMiPu7_Ek@%)E zGrt-1HC1b6lfZhei~6wh1;KKbh{4ihA&ctLD=uzU32Gv}V4@bfEKdNONH_pcU0R z-1*MVBjC2sPXv9;U_G195!p*x;@U}F(Tx`)Bb2lZ&Zmj5FEg8`DLwD=3sxaj@Z5Ec z^5A=*YfQD`_ICWZwl|!QzlLA`8&XX7hf?XsIvR3e3w!dL^9-$q!XQ}P|e4QZ(}*f-smMi z9x)Hj$Ec^)>9Z8`SG82OD+RplJnZ>ma01@1DJnPlAsmOkui)$mZ zM7N(Ksn*z3)@Vtd8vXB)uftC1>0_$(N1lS`e(Krq`vl!4Sv-tJ{~rI53g;vG)NgV` zin&}ZopYsm)yETHKVcd?a1x4ilsZ*gtm0P^gr+q-+zp8B2}+J z2(3ZtG8VO))*v+<3B9%mQ-2#2>)7+1$J)UyX0QluZ^?SaRfwFhJ$ zd3Q1Ulc0c-Sk!Pt2xzuskHIZhI;-fu3n&zwWXvc|IdIlBA$@25A) zR_RHY6RfsVJ@V*Fsz zqBGysj_#1Xu_D+)jrFb|zU9wx^LplDhB&<^6;!ORL~NRMv>!)nh+c%FU^ zTSY_Y+?dV7%D3>7?xY9UUkbmtnbNw?n$m^S8Q`9iU>}zT_oaj2czJ}}_;piWSLg}l zo0U+kNoErpEnzx~ch!S0Mm1j*@x2ORQ8p7rmR$@I+Uf|iDAGGv-{-rA4~E;3ZX($B zE3*u&7CEUaaCPQ z)jorT&J|7KQi<+%*EqXA7v-7{n%KUuHTc_0hwvSIwud zCVX4wu*er)A}gXb4*v=j=B`w$5*B>dsrTejSs{WQn=-2xnj%*(5?5*igl_KwWGuZS zHw>UWV{>C>_QhLzNHfE&Qf|ZZ>Jr#`g+OO_3=i9v#7`C2!FeaeFAtkY8=N3rT6FTMJ|ALhGWke75>R}nm+JF`AISme6?z?IBqLN}5$xq*%42JgsY?RzXU zZ!Aewbx&ZGH4B~(C=cgp4W003JZw{QPMu3|jwQWxE$QLTg-e&CegV%c;n3zjCLZ4b z$I``eql8(^HkA)TWj(fhL z7{~nzbQUOh*y`2%bhZ}kPziel2_lR$IYCZTispbnIzQK!Gjf6j#JHp*O6K&QE(;t&Z|al@ZL`Od&l8nEU1-*|Nv={QVe_j!-Q<>!P&6`h~+`|{mesORRz4-vd5pV@XV6}j);;!2Y$ zp?5F~8Nsrwwu1b{@-3Np-$3bpW_MUs8p4ZoL$(ucKxZh$IMdX5azQnmH+8}!R7snB zOQdUb=ON-L9OmxA1ZRIZ7I@2=@BZdrOjkpB4cbIl>hky9~V~n#!^%~^T z8cYslkp^63dmG|#UXAE6I2pyuoAKRO@4)TzE)l%49kbJn5_!gkxO{P%&{q$l7$8qp z(IMjTT1sn?S&Q9XuP`T!*;v`o!&cnn5PL(8MzM5WuNIv1E} z42O;07=QCE9P=K_nuj*?PeqkbUi7BM>H9xx@Goc3R@Hn}#P?Stw)Ts< z$PRVE;pB~?NBmC|$86wnt$)D1!EO;8J(t=AiU-ncyRz0l85L&hq1Ue~%Q`5cEb^T}z4{Ys@J|g>091d@rC3?=pBVpZMq{vo0E>O0~CL(VCDhpcZs^;UwcT~aFPNz2n=~E7e?-D()sG&HkIgh)gfV)|H5q#nW>swwc z@;>|E($iRBu!P=`;de+!n+Ao)FJ``czI6NWG+6x&crCd_n)o`JyFHMHneOCg)*8b( zaxx|r6i8d=PLgi-j0B^ab6>;G7}tXGa9NZu30uwIww?+l`6BszJHmOQ`kCwf%f4;JgnPSezwPcIIktXs(5LeelzLL z8Vj(ij_5mVB3$Fz!ZGu^tTA{7f4y})lxLp8=W0Xd)q*qaeP8H*SM~e*{r7*5QBQ{u z-z8JFRxMfNxPQmt>B~f~tyJs3eUk54&X?1$}$N@%Y&=V7gD_}Lp~aE{o8Np;VqZP(69cb`oF zJGByhXQjZkPbKl~l-2((;x*d(P@bmxPC_p83cSIz&lJ^z@Ao@I1>YXxt6Ih)iYi6U zsx~<6VJUk37>?rVt9;M7Z*U*yD}t|mB;Rizk-zRME)BXZ3`uvDvGFAT)`C3bsE@|{ zz)|VOMe-}?vKd}yTTx%mPH4}}=V6W3@U)m&#Md1Dx~HV=YbQ(hXREaGm%!^B z?cb0Q&~}=`Lw{c4>8|v~r@2=C_#nj&?I}ITcmg(e1NvqqVyxd^#CK3u4_eD#=q`aW zaUy&sx-oCX1g8DtQa$+MRP$A-359wW7BTdL$hm2a!+jfz-uXjOqVbyV4Re9}!ZZ>5 z>L6p?=8F8U^HF~9hcI$kij18rcx`ivNnXri=4T?L%A==Y-D4WO?*9SXL3g3u%bJIN zyvj4QFB0D#_$#kUJJg>_4=G>A#?UOM=gl#u?jfBo9b|Pl@#nEgP#$~+pPnC?_mwoJ zW9<76-+zp8_NZKgWHnlY_8u%k^M=T6H~@!DdJ0S9%P47A$M?P{g8Q16BDi)t!vH-| z&{GfPNn98m8%6cVY5Yrz1o&RbXXZJxq>63JVQs5`*T-Gd8#oTy%{6)Gt8F~v`3G8q zbMRl)OxjWSOL}yYgW0S_zc#}$W_J>;!BtsZy%&Gh{u`8gOS%O1dHxk`p8HC z|J=HiX39}dOR>FlZIwB!C2x2)JqKIq1iHO=$wQy?=+G=D3!Xo`JC9ubmDXAe^+(J?o-XjiO;@(g|Dy? zxf6&_?YXe5`GFFfd3;~eBe*AA6w6wjVRHCmQLu3w%Ew(1-KTy-#))tIQ-^`@-FtzV zpT8|#o!c4KL#ckK9}3(4Z_%yz0S~>miD!jS9w6cs{7a8ZyT+cDp60cM^eqJarq0Lc z7hV*@4U-$Lzr`OnDu#0VT=JGRWxm>Vl!t3m55E1X`4q%A>=g^=9wIkn01mxgEUZTF zLdjqS-`|GAJ!7O;*6lGHlx86ciXWi7#{|*6_&VvuqWQ;e_u(79keOc|EnQKRz?$?% z-VO@b_HB)B`yTVq8@G7&$U}5TK7;?uW72LtHR-wQI7s(qqTlA@7`^ELX*!$A4ZWW6 zhe7YCf1dU)Xg2c=rCJ;}st4ciT*1HJA;}@c=dQ)V>S{!8qBRcPS}ClOhoQu^H{U-m z4(=C@ie+X7Y;a98QSe=Xat&i)+@1O!@;~zrCe*7xw+%DD7A;*KNB-(=N_abcr{3{) z=oa*ehh9_TIc+71;Vcl)ytlObO{i4;A_`Jo9{LrUW3&>o>xC zbTspQcZccD`27Y}^?e>x&9{g6rW>-btc@bK!U%_o)P;4YuPE`m$M;`b2lx9;#4_6j zY>2^iQP}GyECWVQX8Ig zvlYeQXA#hAq7;{NTY9#G2In9}+Ms{;op3opweYfoa)WY9e)lbTkw>V(>&pbDD5_<;_s`XX?~rP~D&mXm z$HE4Ni#*fMI21ccSU;GDlI7|A!1@vJP#Y(fIk~c7TM9+trX*b4WgtvgATpk~@wZ+^ z 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 WJ%7nEk$S+7J3C!R$^J5S{Cbw? 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

IDEVE%a% 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/refcase_readme.txt b/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/refcase_readme.txt deleted file mode 100644 index a3d0fe6058..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/refcase_readme.txt +++ /dev/null @@ -1 +0,0 @@ -To create a refcase run the snake_oil_simulator.py job with the this as working directory. \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/seed.txt b/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/seed.txt deleted file mode 100644 index 0009f6e89a..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/seed.txt +++ /dev/null @@ -1 +0,0 @@ -SEED:268776 \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/snake_oil_params.txt b/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/snake_oil_params.txt deleted file mode 100644 index 3868522924..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/snake_oil_params.txt +++ /dev/null @@ -1,10 +0,0 @@ -OP1_PERSISTENCE:0.15 -OP1_OCTAVES:4 -OP1_DIVERGENCE_SCALE:0.5 -OP1_OFFSET:0.0 -OP2_PERSISTENCE:0.25 -OP2_OCTAVES:7.0 -OP2_DIVERGENCE_SCALE:1.0 -OP2_OFFSET:0.0 -BPR_555_PERSISTENCE:0.25 -BPR_138_PERSISTENCE:0.35 diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/time_map.txt b/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/time_map.txt deleted file mode 100644 index d54b4293ae..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/refcase/time_map.txt +++ /dev/null @@ -1,2000 +0,0 @@ -01/01/2010 -02/01/2010 -03/01/2010 -04/01/2010 -05/01/2010 -06/01/2010 -07/01/2010 -08/01/2010 -09/01/2010 -10/01/2010 -11/01/2010 -12/01/2010 -13/01/2010 -14/01/2010 -15/01/2010 -16/01/2010 -17/01/2010 -18/01/2010 -19/01/2010 -20/01/2010 -21/01/2010 -22/01/2010 -23/01/2010 -24/01/2010 -25/01/2010 -26/01/2010 -27/01/2010 -28/01/2010 -29/01/2010 -30/01/2010 -31/01/2010 -01/02/2010 -02/02/2010 -03/02/2010 -04/02/2010 -05/02/2010 -06/02/2010 -07/02/2010 -08/02/2010 -09/02/2010 -10/02/2010 -11/02/2010 -12/02/2010 -13/02/2010 -14/02/2010 -15/02/2010 -16/02/2010 -17/02/2010 -18/02/2010 -19/02/2010 -20/02/2010 -21/02/2010 -22/02/2010 -23/02/2010 -24/02/2010 -25/02/2010 -26/02/2010 -27/02/2010 -28/02/2010 -01/03/2010 -02/03/2010 -03/03/2010 -04/03/2010 -05/03/2010 -06/03/2010 -07/03/2010 -08/03/2010 -09/03/2010 -10/03/2010 -11/03/2010 -12/03/2010 -13/03/2010 -14/03/2010 -15/03/2010 -16/03/2010 -17/03/2010 -18/03/2010 -19/03/2010 -20/03/2010 -21/03/2010 -22/03/2010 -23/03/2010 -24/03/2010 -25/03/2010 -26/03/2010 -27/03/2010 -28/03/2010 -29/03/2010 -30/03/2010 -31/03/2010 -01/04/2010 -02/04/2010 -03/04/2010 -04/04/2010 -05/04/2010 -06/04/2010 -07/04/2010 -08/04/2010 -09/04/2010 -10/04/2010 -11/04/2010 -12/04/2010 -13/04/2010 -14/04/2010 -15/04/2010 -16/04/2010 -17/04/2010 -18/04/2010 -19/04/2010 -20/04/2010 -21/04/2010 -22/04/2010 -23/04/2010 -24/04/2010 -25/04/2010 -26/04/2010 -27/04/2010 -28/04/2010 -29/04/2010 -30/04/2010 -01/05/2010 -02/05/2010 -03/05/2010 -04/05/2010 -05/05/2010 -06/05/2010 -07/05/2010 -08/05/2010 -09/05/2010 -10/05/2010 -11/05/2010 -12/05/2010 -13/05/2010 -14/05/2010 -15/05/2010 -16/05/2010 -17/05/2010 -18/05/2010 -19/05/2010 -20/05/2010 -21/05/2010 -22/05/2010 -23/05/2010 -24/05/2010 -25/05/2010 -26/05/2010 -27/05/2010 -28/05/2010 -29/05/2010 -30/05/2010 -31/05/2010 -01/06/2010 -02/06/2010 -03/06/2010 -04/06/2010 -05/06/2010 -06/06/2010 -07/06/2010 -08/06/2010 -09/06/2010 -10/06/2010 -11/06/2010 -12/06/2010 -13/06/2010 -14/06/2010 -15/06/2010 -16/06/2010 -17/06/2010 -18/06/2010 -19/06/2010 -20/06/2010 -21/06/2010 -22/06/2010 -23/06/2010 -24/06/2010 -25/06/2010 -26/06/2010 -27/06/2010 -28/06/2010 -29/06/2010 -30/06/2010 -01/07/2010 -02/07/2010 -03/07/2010 -04/07/2010 -05/07/2010 -06/07/2010 -07/07/2010 -08/07/2010 -09/07/2010 -10/07/2010 -11/07/2010 -12/07/2010 -13/07/2010 -14/07/2010 -15/07/2010 -16/07/2010 -17/07/2010 -18/07/2010 -19/07/2010 -20/07/2010 -21/07/2010 -22/07/2010 -23/07/2010 -24/07/2010 -25/07/2010 -26/07/2010 -27/07/2010 -28/07/2010 -29/07/2010 -30/07/2010 -31/07/2010 -01/08/2010 -02/08/2010 -03/08/2010 -04/08/2010 -05/08/2010 -06/08/2010 -07/08/2010 -08/08/2010 -09/08/2010 -10/08/2010 -11/08/2010 -12/08/2010 -13/08/2010 -14/08/2010 -15/08/2010 -16/08/2010 -17/08/2010 -18/08/2010 -19/08/2010 -20/08/2010 -21/08/2010 -22/08/2010 -23/08/2010 -24/08/2010 -25/08/2010 -26/08/2010 -27/08/2010 -28/08/2010 -29/08/2010 -30/08/2010 -31/08/2010 -01/09/2010 -02/09/2010 -03/09/2010 -04/09/2010 -05/09/2010 -06/09/2010 -07/09/2010 -08/09/2010 -09/09/2010 -10/09/2010 -11/09/2010 -12/09/2010 -13/09/2010 -14/09/2010 -15/09/2010 -16/09/2010 -17/09/2010 -18/09/2010 -19/09/2010 -20/09/2010 -21/09/2010 -22/09/2010 -23/09/2010 -24/09/2010 -25/09/2010 -26/09/2010 -27/09/2010 -28/09/2010 -29/09/2010 -30/09/2010 -01/10/2010 -02/10/2010 -03/10/2010 -04/10/2010 -05/10/2010 -06/10/2010 -07/10/2010 -08/10/2010 -09/10/2010 -10/10/2010 -11/10/2010 -12/10/2010 -13/10/2010 -14/10/2010 -15/10/2010 -16/10/2010 -17/10/2010 -18/10/2010 -19/10/2010 -20/10/2010 -21/10/2010 -22/10/2010 -23/10/2010 -24/10/2010 -25/10/2010 -26/10/2010 -27/10/2010 -28/10/2010 -29/10/2010 -30/10/2010 -31/10/2010 -01/11/2010 -02/11/2010 -03/11/2010 -04/11/2010 -05/11/2010 -06/11/2010 -07/11/2010 -08/11/2010 -09/11/2010 -10/11/2010 -11/11/2010 -12/11/2010 -13/11/2010 -14/11/2010 -15/11/2010 -16/11/2010 -17/11/2010 -18/11/2010 -19/11/2010 -20/11/2010 -21/11/2010 -22/11/2010 -23/11/2010 -24/11/2010 -25/11/2010 -26/11/2010 -27/11/2010 -28/11/2010 -29/11/2010 -30/11/2010 -01/12/2010 -02/12/2010 -03/12/2010 -04/12/2010 -05/12/2010 -06/12/2010 -07/12/2010 -08/12/2010 -09/12/2010 -10/12/2010 -11/12/2010 -12/12/2010 -13/12/2010 -14/12/2010 -15/12/2010 -16/12/2010 -17/12/2010 -18/12/2010 -19/12/2010 -20/12/2010 -21/12/2010 -22/12/2010 -23/12/2010 -24/12/2010 -25/12/2010 -26/12/2010 -27/12/2010 -28/12/2010 -29/12/2010 -30/12/2010 -31/12/2010 -01/01/2011 -02/01/2011 -03/01/2011 -04/01/2011 -05/01/2011 -06/01/2011 -07/01/2011 -08/01/2011 -09/01/2011 -10/01/2011 -11/01/2011 -12/01/2011 -13/01/2011 -14/01/2011 -15/01/2011 -16/01/2011 -17/01/2011 -18/01/2011 -19/01/2011 -20/01/2011 -21/01/2011 -22/01/2011 -23/01/2011 -24/01/2011 -25/01/2011 -26/01/2011 -27/01/2011 -28/01/2011 -29/01/2011 -30/01/2011 -31/01/2011 -01/02/2011 -02/02/2011 -03/02/2011 -04/02/2011 -05/02/2011 -06/02/2011 -07/02/2011 -08/02/2011 -09/02/2011 -10/02/2011 -11/02/2011 -12/02/2011 -13/02/2011 -14/02/2011 -15/02/2011 -16/02/2011 -17/02/2011 -18/02/2011 -19/02/2011 -20/02/2011 -21/02/2011 -22/02/2011 -23/02/2011 -24/02/2011 -25/02/2011 -26/02/2011 -27/02/2011 -28/02/2011 -01/03/2011 -02/03/2011 -03/03/2011 -04/03/2011 -05/03/2011 -06/03/2011 -07/03/2011 -08/03/2011 -09/03/2011 -10/03/2011 -11/03/2011 -12/03/2011 -13/03/2011 -14/03/2011 -15/03/2011 -16/03/2011 -17/03/2011 -18/03/2011 -19/03/2011 -20/03/2011 -21/03/2011 -22/03/2011 -23/03/2011 -24/03/2011 -25/03/2011 -26/03/2011 -27/03/2011 -28/03/2011 -29/03/2011 -30/03/2011 -31/03/2011 -01/04/2011 -02/04/2011 -03/04/2011 -04/04/2011 -05/04/2011 -06/04/2011 -07/04/2011 -08/04/2011 -09/04/2011 -10/04/2011 -11/04/2011 -12/04/2011 -13/04/2011 -14/04/2011 -15/04/2011 -16/04/2011 -17/04/2011 -18/04/2011 -19/04/2011 -20/04/2011 -21/04/2011 -22/04/2011 -23/04/2011 -24/04/2011 -25/04/2011 -26/04/2011 -27/04/2011 -28/04/2011 -29/04/2011 -30/04/2011 -01/05/2011 -02/05/2011 -03/05/2011 -04/05/2011 -05/05/2011 -06/05/2011 -07/05/2011 -08/05/2011 -09/05/2011 -10/05/2011 -11/05/2011 -12/05/2011 -13/05/2011 -14/05/2011 -15/05/2011 -16/05/2011 -17/05/2011 -18/05/2011 -19/05/2011 -20/05/2011 -21/05/2011 -22/05/2011 -23/05/2011 -24/05/2011 -25/05/2011 -26/05/2011 -27/05/2011 -28/05/2011 -29/05/2011 -30/05/2011 -31/05/2011 -01/06/2011 -02/06/2011 -03/06/2011 -04/06/2011 -05/06/2011 -06/06/2011 -07/06/2011 -08/06/2011 -09/06/2011 -10/06/2011 -11/06/2011 -12/06/2011 -13/06/2011 -14/06/2011 -15/06/2011 -16/06/2011 -17/06/2011 -18/06/2011 -19/06/2011 -20/06/2011 -21/06/2011 -22/06/2011 -23/06/2011 -24/06/2011 -25/06/2011 -26/06/2011 -27/06/2011 -28/06/2011 -29/06/2011 -30/06/2011 -01/07/2011 -02/07/2011 -03/07/2011 -04/07/2011 -05/07/2011 -06/07/2011 -07/07/2011 -08/07/2011 -09/07/2011 -10/07/2011 -11/07/2011 -12/07/2011 -13/07/2011 -14/07/2011 -15/07/2011 -16/07/2011 -17/07/2011 -18/07/2011 -19/07/2011 -20/07/2011 -21/07/2011 -22/07/2011 -23/07/2011 -24/07/2011 -25/07/2011 -26/07/2011 -27/07/2011 -28/07/2011 -29/07/2011 -30/07/2011 -31/07/2011 -01/08/2011 -02/08/2011 -03/08/2011 -04/08/2011 -05/08/2011 -06/08/2011 -07/08/2011 -08/08/2011 -09/08/2011 -10/08/2011 -11/08/2011 -12/08/2011 -13/08/2011 -14/08/2011 -15/08/2011 -16/08/2011 -17/08/2011 -18/08/2011 -19/08/2011 -20/08/2011 -21/08/2011 -22/08/2011 -23/08/2011 -24/08/2011 -25/08/2011 -26/08/2011 -27/08/2011 -28/08/2011 -29/08/2011 -30/08/2011 -31/08/2011 -01/09/2011 -02/09/2011 -03/09/2011 -04/09/2011 -05/09/2011 -06/09/2011 -07/09/2011 -08/09/2011 -09/09/2011 -10/09/2011 -11/09/2011 -12/09/2011 -13/09/2011 -14/09/2011 -15/09/2011 -16/09/2011 -17/09/2011 -18/09/2011 -19/09/2011 -20/09/2011 -21/09/2011 -22/09/2011 -23/09/2011 -24/09/2011 -25/09/2011 -26/09/2011 -27/09/2011 -28/09/2011 -29/09/2011 -30/09/2011 -01/10/2011 -02/10/2011 -03/10/2011 -04/10/2011 -05/10/2011 -06/10/2011 -07/10/2011 -08/10/2011 -09/10/2011 -10/10/2011 -11/10/2011 -12/10/2011 -13/10/2011 -14/10/2011 -15/10/2011 -16/10/2011 -17/10/2011 -18/10/2011 -19/10/2011 -20/10/2011 -21/10/2011 -22/10/2011 -23/10/2011 -24/10/2011 -25/10/2011 -26/10/2011 -27/10/2011 -28/10/2011 -29/10/2011 -30/10/2011 -31/10/2011 -01/11/2011 -02/11/2011 -03/11/2011 -04/11/2011 -05/11/2011 -06/11/2011 -07/11/2011 -08/11/2011 -09/11/2011 -10/11/2011 -11/11/2011 -12/11/2011 -13/11/2011 -14/11/2011 -15/11/2011 -16/11/2011 -17/11/2011 -18/11/2011 -19/11/2011 -20/11/2011 -21/11/2011 -22/11/2011 -23/11/2011 -24/11/2011 -25/11/2011 -26/11/2011 -27/11/2011 -28/11/2011 -29/11/2011 -30/11/2011 -01/12/2011 -02/12/2011 -03/12/2011 -04/12/2011 -05/12/2011 -06/12/2011 -07/12/2011 -08/12/2011 -09/12/2011 -10/12/2011 -11/12/2011 -12/12/2011 -13/12/2011 -14/12/2011 -15/12/2011 -16/12/2011 -17/12/2011 -18/12/2011 -19/12/2011 -20/12/2011 -21/12/2011 -22/12/2011 -23/12/2011 -24/12/2011 -25/12/2011 -26/12/2011 -27/12/2011 -28/12/2011 -29/12/2011 -30/12/2011 -31/12/2011 -01/01/2012 -02/01/2012 -03/01/2012 -04/01/2012 -05/01/2012 -06/01/2012 -07/01/2012 -08/01/2012 -09/01/2012 -10/01/2012 -11/01/2012 -12/01/2012 -13/01/2012 -14/01/2012 -15/01/2012 -16/01/2012 -17/01/2012 -18/01/2012 -19/01/2012 -20/01/2012 -21/01/2012 -22/01/2012 -23/01/2012 -24/01/2012 -25/01/2012 -26/01/2012 -27/01/2012 -28/01/2012 -29/01/2012 -30/01/2012 -31/01/2012 -01/02/2012 -02/02/2012 -03/02/2012 -04/02/2012 -05/02/2012 -06/02/2012 -07/02/2012 -08/02/2012 -09/02/2012 -10/02/2012 -11/02/2012 -12/02/2012 -13/02/2012 -14/02/2012 -15/02/2012 -16/02/2012 -17/02/2012 -18/02/2012 -19/02/2012 -20/02/2012 -21/02/2012 -22/02/2012 -23/02/2012 -24/02/2012 -25/02/2012 -26/02/2012 -27/02/2012 -28/02/2012 -29/02/2012 -01/03/2012 -02/03/2012 -03/03/2012 -04/03/2012 -05/03/2012 -06/03/2012 -07/03/2012 -08/03/2012 -09/03/2012 -10/03/2012 -11/03/2012 -12/03/2012 -13/03/2012 -14/03/2012 -15/03/2012 -16/03/2012 -17/03/2012 -18/03/2012 -19/03/2012 -20/03/2012 -21/03/2012 -22/03/2012 -23/03/2012 -24/03/2012 -25/03/2012 -26/03/2012 -27/03/2012 -28/03/2012 -29/03/2012 -30/03/2012 -31/03/2012 -01/04/2012 -02/04/2012 -03/04/2012 -04/04/2012 -05/04/2012 -06/04/2012 -07/04/2012 -08/04/2012 -09/04/2012 -10/04/2012 -11/04/2012 -12/04/2012 -13/04/2012 -14/04/2012 -15/04/2012 -16/04/2012 -17/04/2012 -18/04/2012 -19/04/2012 -20/04/2012 -21/04/2012 -22/04/2012 -23/04/2012 -24/04/2012 -25/04/2012 -26/04/2012 -27/04/2012 -28/04/2012 -29/04/2012 -30/04/2012 -01/05/2012 -02/05/2012 -03/05/2012 -04/05/2012 -05/05/2012 -06/05/2012 -07/05/2012 -08/05/2012 -09/05/2012 -10/05/2012 -11/05/2012 -12/05/2012 -13/05/2012 -14/05/2012 -15/05/2012 -16/05/2012 -17/05/2012 -18/05/2012 -19/05/2012 -20/05/2012 -21/05/2012 -22/05/2012 -23/05/2012 -24/05/2012 -25/05/2012 -26/05/2012 -27/05/2012 -28/05/2012 -29/05/2012 -30/05/2012 -31/05/2012 -01/06/2012 -02/06/2012 -03/06/2012 -04/06/2012 -05/06/2012 -06/06/2012 -07/06/2012 -08/06/2012 -09/06/2012 -10/06/2012 -11/06/2012 -12/06/2012 -13/06/2012 -14/06/2012 -15/06/2012 -16/06/2012 -17/06/2012 -18/06/2012 -19/06/2012 -20/06/2012 -21/06/2012 -22/06/2012 -23/06/2012 -24/06/2012 -25/06/2012 -26/06/2012 -27/06/2012 -28/06/2012 -29/06/2012 -30/06/2012 -01/07/2012 -02/07/2012 -03/07/2012 -04/07/2012 -05/07/2012 -06/07/2012 -07/07/2012 -08/07/2012 -09/07/2012 -10/07/2012 -11/07/2012 -12/07/2012 -13/07/2012 -14/07/2012 -15/07/2012 -16/07/2012 -17/07/2012 -18/07/2012 -19/07/2012 -20/07/2012 -21/07/2012 -22/07/2012 -23/07/2012 -24/07/2012 -25/07/2012 -26/07/2012 -27/07/2012 -28/07/2012 -29/07/2012 -30/07/2012 -31/07/2012 -01/08/2012 -02/08/2012 -03/08/2012 -04/08/2012 -05/08/2012 -06/08/2012 -07/08/2012 -08/08/2012 -09/08/2012 -10/08/2012 -11/08/2012 -12/08/2012 -13/08/2012 -14/08/2012 -15/08/2012 -16/08/2012 -17/08/2012 -18/08/2012 -19/08/2012 -20/08/2012 -21/08/2012 -22/08/2012 -23/08/2012 -24/08/2012 -25/08/2012 -26/08/2012 -27/08/2012 -28/08/2012 -29/08/2012 -30/08/2012 -31/08/2012 -01/09/2012 -02/09/2012 -03/09/2012 -04/09/2012 -05/09/2012 -06/09/2012 -07/09/2012 -08/09/2012 -09/09/2012 -10/09/2012 -11/09/2012 -12/09/2012 -13/09/2012 -14/09/2012 -15/09/2012 -16/09/2012 -17/09/2012 -18/09/2012 -19/09/2012 -20/09/2012 -21/09/2012 -22/09/2012 -23/09/2012 -24/09/2012 -25/09/2012 -26/09/2012 -27/09/2012 -28/09/2012 -29/09/2012 -30/09/2012 -01/10/2012 -02/10/2012 -03/10/2012 -04/10/2012 -05/10/2012 -06/10/2012 -07/10/2012 -08/10/2012 -09/10/2012 -10/10/2012 -11/10/2012 -12/10/2012 -13/10/2012 -14/10/2012 -15/10/2012 -16/10/2012 -17/10/2012 -18/10/2012 -19/10/2012 -20/10/2012 -21/10/2012 -22/10/2012 -23/10/2012 -24/10/2012 -25/10/2012 -26/10/2012 -27/10/2012 -28/10/2012 -29/10/2012 -30/10/2012 -31/10/2012 -01/11/2012 -02/11/2012 -03/11/2012 -04/11/2012 -05/11/2012 -06/11/2012 -07/11/2012 -08/11/2012 -09/11/2012 -10/11/2012 -11/11/2012 -12/11/2012 -13/11/2012 -14/11/2012 -15/11/2012 -16/11/2012 -17/11/2012 -18/11/2012 -19/11/2012 -20/11/2012 -21/11/2012 -22/11/2012 -23/11/2012 -24/11/2012 -25/11/2012 -26/11/2012 -27/11/2012 -28/11/2012 -29/11/2012 -30/11/2012 -01/12/2012 -02/12/2012 -03/12/2012 -04/12/2012 -05/12/2012 -06/12/2012 -07/12/2012 -08/12/2012 -09/12/2012 -10/12/2012 -11/12/2012 -12/12/2012 -13/12/2012 -14/12/2012 -15/12/2012 -16/12/2012 -17/12/2012 -18/12/2012 -19/12/2012 -20/12/2012 -21/12/2012 -22/12/2012 -23/12/2012 -24/12/2012 -25/12/2012 -26/12/2012 -27/12/2012 -28/12/2012 -29/12/2012 -30/12/2012 -31/12/2012 -01/01/2013 -02/01/2013 -03/01/2013 -04/01/2013 -05/01/2013 -06/01/2013 -07/01/2013 -08/01/2013 -09/01/2013 -10/01/2013 -11/01/2013 -12/01/2013 -13/01/2013 -14/01/2013 -15/01/2013 -16/01/2013 -17/01/2013 -18/01/2013 -19/01/2013 -20/01/2013 -21/01/2013 -22/01/2013 -23/01/2013 -24/01/2013 -25/01/2013 -26/01/2013 -27/01/2013 -28/01/2013 -29/01/2013 -30/01/2013 -31/01/2013 -01/02/2013 -02/02/2013 -03/02/2013 -04/02/2013 -05/02/2013 -06/02/2013 -07/02/2013 -08/02/2013 -09/02/2013 -10/02/2013 -11/02/2013 -12/02/2013 -13/02/2013 -14/02/2013 -15/02/2013 -16/02/2013 -17/02/2013 -18/02/2013 -19/02/2013 -20/02/2013 -21/02/2013 -22/02/2013 -23/02/2013 -24/02/2013 -25/02/2013 -26/02/2013 -27/02/2013 -28/02/2013 -01/03/2013 -02/03/2013 -03/03/2013 -04/03/2013 -05/03/2013 -06/03/2013 -07/03/2013 -08/03/2013 -09/03/2013 -10/03/2013 -11/03/2013 -12/03/2013 -13/03/2013 -14/03/2013 -15/03/2013 -16/03/2013 -17/03/2013 -18/03/2013 -19/03/2013 -20/03/2013 -21/03/2013 -22/03/2013 -23/03/2013 -24/03/2013 -25/03/2013 -26/03/2013 -27/03/2013 -28/03/2013 -29/03/2013 -30/03/2013 -31/03/2013 -01/04/2013 -02/04/2013 -03/04/2013 -04/04/2013 -05/04/2013 -06/04/2013 -07/04/2013 -08/04/2013 -09/04/2013 -10/04/2013 -11/04/2013 -12/04/2013 -13/04/2013 -14/04/2013 -15/04/2013 -16/04/2013 -17/04/2013 -18/04/2013 -19/04/2013 -20/04/2013 -21/04/2013 -22/04/2013 -23/04/2013 -24/04/2013 -25/04/2013 -26/04/2013 -27/04/2013 -28/04/2013 -29/04/2013 -30/04/2013 -01/05/2013 -02/05/2013 -03/05/2013 -04/05/2013 -05/05/2013 -06/05/2013 -07/05/2013 -08/05/2013 -09/05/2013 -10/05/2013 -11/05/2013 -12/05/2013 -13/05/2013 -14/05/2013 -15/05/2013 -16/05/2013 -17/05/2013 -18/05/2013 -19/05/2013 -20/05/2013 -21/05/2013 -22/05/2013 -23/05/2013 -24/05/2013 -25/05/2013 -26/05/2013 -27/05/2013 -28/05/2013 -29/05/2013 -30/05/2013 -31/05/2013 -01/06/2013 -02/06/2013 -03/06/2013 -04/06/2013 -05/06/2013 -06/06/2013 -07/06/2013 -08/06/2013 -09/06/2013 -10/06/2013 -11/06/2013 -12/06/2013 -13/06/2013 -14/06/2013 -15/06/2013 -16/06/2013 -17/06/2013 -18/06/2013 -19/06/2013 -20/06/2013 -21/06/2013 -22/06/2013 -23/06/2013 -24/06/2013 -25/06/2013 -26/06/2013 -27/06/2013 -28/06/2013 -29/06/2013 -30/06/2013 -01/07/2013 -02/07/2013 -03/07/2013 -04/07/2013 -05/07/2013 -06/07/2013 -07/07/2013 -08/07/2013 -09/07/2013 -10/07/2013 -11/07/2013 -12/07/2013 -13/07/2013 -14/07/2013 -15/07/2013 -16/07/2013 -17/07/2013 -18/07/2013 -19/07/2013 -20/07/2013 -21/07/2013 -22/07/2013 -23/07/2013 -24/07/2013 -25/07/2013 -26/07/2013 -27/07/2013 -28/07/2013 -29/07/2013 -30/07/2013 -31/07/2013 -01/08/2013 -02/08/2013 -03/08/2013 -04/08/2013 -05/08/2013 -06/08/2013 -07/08/2013 -08/08/2013 -09/08/2013 -10/08/2013 -11/08/2013 -12/08/2013 -13/08/2013 -14/08/2013 -15/08/2013 -16/08/2013 -17/08/2013 -18/08/2013 -19/08/2013 -20/08/2013 -21/08/2013 -22/08/2013 -23/08/2013 -24/08/2013 -25/08/2013 -26/08/2013 -27/08/2013 -28/08/2013 -29/08/2013 -30/08/2013 -31/08/2013 -01/09/2013 -02/09/2013 -03/09/2013 -04/09/2013 -05/09/2013 -06/09/2013 -07/09/2013 -08/09/2013 -09/09/2013 -10/09/2013 -11/09/2013 -12/09/2013 -13/09/2013 -14/09/2013 -15/09/2013 -16/09/2013 -17/09/2013 -18/09/2013 -19/09/2013 -20/09/2013 -21/09/2013 -22/09/2013 -23/09/2013 -24/09/2013 -25/09/2013 -26/09/2013 -27/09/2013 -28/09/2013 -29/09/2013 -30/09/2013 -01/10/2013 -02/10/2013 -03/10/2013 -04/10/2013 -05/10/2013 -06/10/2013 -07/10/2013 -08/10/2013 -09/10/2013 -10/10/2013 -11/10/2013 -12/10/2013 -13/10/2013 -14/10/2013 -15/10/2013 -16/10/2013 -17/10/2013 -18/10/2013 -19/10/2013 -20/10/2013 -21/10/2013 -22/10/2013 -23/10/2013 -24/10/2013 -25/10/2013 -26/10/2013 -27/10/2013 -28/10/2013 -29/10/2013 -30/10/2013 -31/10/2013 -01/11/2013 -02/11/2013 -03/11/2013 -04/11/2013 -05/11/2013 -06/11/2013 -07/11/2013 -08/11/2013 -09/11/2013 -10/11/2013 -11/11/2013 -12/11/2013 -13/11/2013 -14/11/2013 -15/11/2013 -16/11/2013 -17/11/2013 -18/11/2013 -19/11/2013 -20/11/2013 -21/11/2013 -22/11/2013 -23/11/2013 -24/11/2013 -25/11/2013 -26/11/2013 -27/11/2013 -28/11/2013 -29/11/2013 -30/11/2013 -01/12/2013 -02/12/2013 -03/12/2013 -04/12/2013 -05/12/2013 -06/12/2013 -07/12/2013 -08/12/2013 -09/12/2013 -10/12/2013 -11/12/2013 -12/12/2013 -13/12/2013 -14/12/2013 -15/12/2013 -16/12/2013 -17/12/2013 -18/12/2013 -19/12/2013 -20/12/2013 -21/12/2013 -22/12/2013 -23/12/2013 -24/12/2013 -25/12/2013 -26/12/2013 -27/12/2013 -28/12/2013 -29/12/2013 -30/12/2013 -31/12/2013 -01/01/2014 -02/01/2014 -03/01/2014 -04/01/2014 -05/01/2014 -06/01/2014 -07/01/2014 -08/01/2014 -09/01/2014 -10/01/2014 -11/01/2014 -12/01/2014 -13/01/2014 -14/01/2014 -15/01/2014 -16/01/2014 -17/01/2014 -18/01/2014 -19/01/2014 -20/01/2014 -21/01/2014 -22/01/2014 -23/01/2014 -24/01/2014 -25/01/2014 -26/01/2014 -27/01/2014 -28/01/2014 -29/01/2014 -30/01/2014 -31/01/2014 -01/02/2014 -02/02/2014 -03/02/2014 -04/02/2014 -05/02/2014 -06/02/2014 -07/02/2014 -08/02/2014 -09/02/2014 -10/02/2014 -11/02/2014 -12/02/2014 -13/02/2014 -14/02/2014 -15/02/2014 -16/02/2014 -17/02/2014 -18/02/2014 -19/02/2014 -20/02/2014 -21/02/2014 -22/02/2014 -23/02/2014 -24/02/2014 -25/02/2014 -26/02/2014 -27/02/2014 -28/02/2014 -01/03/2014 -02/03/2014 -03/03/2014 -04/03/2014 -05/03/2014 -06/03/2014 -07/03/2014 -08/03/2014 -09/03/2014 -10/03/2014 -11/03/2014 -12/03/2014 -13/03/2014 -14/03/2014 -15/03/2014 -16/03/2014 -17/03/2014 -18/03/2014 -19/03/2014 -20/03/2014 -21/03/2014 -22/03/2014 -23/03/2014 -24/03/2014 -25/03/2014 -26/03/2014 -27/03/2014 -28/03/2014 -29/03/2014 -30/03/2014 -31/03/2014 -01/04/2014 -02/04/2014 -03/04/2014 -04/04/2014 -05/04/2014 -06/04/2014 -07/04/2014 -08/04/2014 -09/04/2014 -10/04/2014 -11/04/2014 -12/04/2014 -13/04/2014 -14/04/2014 -15/04/2014 -16/04/2014 -17/04/2014 -18/04/2014 -19/04/2014 -20/04/2014 -21/04/2014 -22/04/2014 -23/04/2014 -24/04/2014 -25/04/2014 -26/04/2014 -27/04/2014 -28/04/2014 -29/04/2014 -30/04/2014 -01/05/2014 -02/05/2014 -03/05/2014 -04/05/2014 -05/05/2014 -06/05/2014 -07/05/2014 -08/05/2014 -09/05/2014 -10/05/2014 -11/05/2014 -12/05/2014 -13/05/2014 -14/05/2014 -15/05/2014 -16/05/2014 -17/05/2014 -18/05/2014 -19/05/2014 -20/05/2014 -21/05/2014 -22/05/2014 -23/05/2014 -24/05/2014 -25/05/2014 -26/05/2014 -27/05/2014 -28/05/2014 -29/05/2014 -30/05/2014 -31/05/2014 -01/06/2014 -02/06/2014 -03/06/2014 -04/06/2014 -05/06/2014 -06/06/2014 -07/06/2014 -08/06/2014 -09/06/2014 -10/06/2014 -11/06/2014 -12/06/2014 -13/06/2014 -14/06/2014 -15/06/2014 -16/06/2014 -17/06/2014 -18/06/2014 -19/06/2014 -20/06/2014 -21/06/2014 -22/06/2014 -23/06/2014 -24/06/2014 -25/06/2014 -26/06/2014 -27/06/2014 -28/06/2014 -29/06/2014 -30/06/2014 -01/07/2014 -02/07/2014 -03/07/2014 -04/07/2014 -05/07/2014 -06/07/2014 -07/07/2014 -08/07/2014 -09/07/2014 -10/07/2014 -11/07/2014 -12/07/2014 -13/07/2014 -14/07/2014 -15/07/2014 -16/07/2014 -17/07/2014 -18/07/2014 -19/07/2014 -20/07/2014 -21/07/2014 -22/07/2014 -23/07/2014 -24/07/2014 -25/07/2014 -26/07/2014 -27/07/2014 -28/07/2014 -29/07/2014 -30/07/2014 -31/07/2014 -01/08/2014 -02/08/2014 -03/08/2014 -04/08/2014 -05/08/2014 -06/08/2014 -07/08/2014 -08/08/2014 -09/08/2014 -10/08/2014 -11/08/2014 -12/08/2014 -13/08/2014 -14/08/2014 -15/08/2014 -16/08/2014 -17/08/2014 -18/08/2014 -19/08/2014 -20/08/2014 -21/08/2014 -22/08/2014 -23/08/2014 -24/08/2014 -25/08/2014 -26/08/2014 -27/08/2014 -28/08/2014 -29/08/2014 -30/08/2014 -31/08/2014 -01/09/2014 -02/09/2014 -03/09/2014 -04/09/2014 -05/09/2014 -06/09/2014 -07/09/2014 -08/09/2014 -09/09/2014 -10/09/2014 -11/09/2014 -12/09/2014 -13/09/2014 -14/09/2014 -15/09/2014 -16/09/2014 -17/09/2014 -18/09/2014 -19/09/2014 -20/09/2014 -21/09/2014 -22/09/2014 -23/09/2014 -24/09/2014 -25/09/2014 -26/09/2014 -27/09/2014 -28/09/2014 -29/09/2014 -30/09/2014 -01/10/2014 -02/10/2014 -03/10/2014 -04/10/2014 -05/10/2014 -06/10/2014 -07/10/2014 -08/10/2014 -09/10/2014 -10/10/2014 -11/10/2014 -12/10/2014 -13/10/2014 -14/10/2014 -15/10/2014 -16/10/2014 -17/10/2014 -18/10/2014 -19/10/2014 -20/10/2014 -21/10/2014 -22/10/2014 -23/10/2014 -24/10/2014 -25/10/2014 -26/10/2014 -27/10/2014 -28/10/2014 -29/10/2014 -30/10/2014 -31/10/2014 -01/11/2014 -02/11/2014 -03/11/2014 -04/11/2014 -05/11/2014 -06/11/2014 -07/11/2014 -08/11/2014 -09/11/2014 -10/11/2014 -11/11/2014 -12/11/2014 -13/11/2014 -14/11/2014 -15/11/2014 -16/11/2014 -17/11/2014 -18/11/2014 -19/11/2014 -20/11/2014 -21/11/2014 -22/11/2014 -23/11/2014 -24/11/2014 -25/11/2014 -26/11/2014 -27/11/2014 -28/11/2014 -29/11/2014 -30/11/2014 -01/12/2014 -02/12/2014 -03/12/2014 -04/12/2014 -05/12/2014 -06/12/2014 -07/12/2014 -08/12/2014 -09/12/2014 -10/12/2014 -11/12/2014 -12/12/2014 -13/12/2014 -14/12/2014 -15/12/2014 -16/12/2014 -17/12/2014 -18/12/2014 -19/12/2014 -20/12/2014 -21/12/2014 -22/12/2014 -23/12/2014 -24/12/2014 -25/12/2014 -26/12/2014 -27/12/2014 -28/12/2014 -29/12/2014 -30/12/2014 -31/12/2014 -01/01/2015 -02/01/2015 -03/01/2015 -04/01/2015 -05/01/2015 -06/01/2015 -07/01/2015 -08/01/2015 -09/01/2015 -10/01/2015 -11/01/2015 -12/01/2015 -13/01/2015 -14/01/2015 -15/01/2015 -16/01/2015 -17/01/2015 -18/01/2015 -19/01/2015 -20/01/2015 -21/01/2015 -22/01/2015 -23/01/2015 -24/01/2015 -25/01/2015 -26/01/2015 -27/01/2015 -28/01/2015 -29/01/2015 -30/01/2015 -31/01/2015 -01/02/2015 -02/02/2015 -03/02/2015 -04/02/2015 -05/02/2015 -06/02/2015 -07/02/2015 -08/02/2015 -09/02/2015 -10/02/2015 -11/02/2015 -12/02/2015 -13/02/2015 -14/02/2015 -15/02/2015 -16/02/2015 -17/02/2015 -18/02/2015 -19/02/2015 -20/02/2015 -21/02/2015 -22/02/2015 -23/02/2015 -24/02/2015 -25/02/2015 -26/02/2015 -27/02/2015 -28/02/2015 -01/03/2015 -02/03/2015 -03/03/2015 -04/03/2015 -05/03/2015 -06/03/2015 -07/03/2015 -08/03/2015 -09/03/2015 -10/03/2015 -11/03/2015 -12/03/2015 -13/03/2015 -14/03/2015 -15/03/2015 -16/03/2015 -17/03/2015 -18/03/2015 -19/03/2015 -20/03/2015 -21/03/2015 -22/03/2015 -23/03/2015 -24/03/2015 -25/03/2015 -26/03/2015 -27/03/2015 -28/03/2015 -29/03/2015 -30/03/2015 -31/03/2015 -01/04/2015 -02/04/2015 -03/04/2015 -04/04/2015 -05/04/2015 -06/04/2015 -07/04/2015 -08/04/2015 -09/04/2015 -10/04/2015 -11/04/2015 -12/04/2015 -13/04/2015 -14/04/2015 -15/04/2015 -16/04/2015 -17/04/2015 -18/04/2015 -19/04/2015 -20/04/2015 -21/04/2015 -22/04/2015 -23/04/2015 -24/04/2015 -25/04/2015 -26/04/2015 -27/04/2015 -28/04/2015 -29/04/2015 -30/04/2015 -01/05/2015 -02/05/2015 -03/05/2015 -04/05/2015 -05/05/2015 -06/05/2015 -07/05/2015 -08/05/2015 -09/05/2015 -10/05/2015 -11/05/2015 -12/05/2015 -13/05/2015 -14/05/2015 -15/05/2015 -16/05/2015 -17/05/2015 -18/05/2015 -19/05/2015 -20/05/2015 -21/05/2015 -22/05/2015 -23/05/2015 -24/05/2015 -25/05/2015 -26/05/2015 -27/05/2015 -28/05/2015 -29/05/2015 -30/05/2015 -31/05/2015 -01/06/2015 -02/06/2015 -03/06/2015 -04/06/2015 -05/06/2015 -06/06/2015 -07/06/2015 -08/06/2015 -09/06/2015 -10/06/2015 -11/06/2015 -12/06/2015 -13/06/2015 -14/06/2015 -15/06/2015 -16/06/2015 -17/06/2015 -18/06/2015 -19/06/2015 -20/06/2015 -21/06/2015 -22/06/2015 -23/06/2015 diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/snake_oil.ert b/ThirdParty/Ert/test-data/local/snake_oil_no_data/snake_oil.ert deleted file mode 100644 index 72fef586d0..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/snake_oil.ert +++ /dev/null @@ -1,40 +0,0 @@ -QUEUE_SYSTEM LOCAL - -JOBNAME SNAKE_OIL_%d -NUM_REALIZATIONS 25 - -DEFINE storage/ - -STORE_SEED SEED -LOAD_SEED SEED - -RUNPATH_FILE directory/test_runpath_list.txt -RUNPATH /runpath/realisation-%d/iter-%d -ENSPATH /ensemble -ECLBASE SNAKE_OIL_FIELD -SUMMARY * - -HISTORY_SOURCE REFCASE_HISTORY -REFCASE refcase/SNAKE_OIL_FIELD - -TIME_MAP refcase/time_map.txt -OBS_CONFIG observations/observations.txt - -INSTALL_JOB SNAKE_OIL_SIMULATOR jobs/SNAKE_OIL_SIMULATOR -INSTALL_JOB SNAKE_OIL_NPV jobs/SNAKE_OIL_NPV -INSTALL_JOB SNAKE_OIL_DIFF jobs/SNAKE_OIL_DIFF - -FORWARD_MODEL SNAKE_OIL_SIMULATOR -FORWARD_MODEL SNAKE_OIL_NPV -FORWARD_MODEL SNAKE_OIL_DIFF - -RUN_TEMPLATE templates/seed_template.txt seed.txt -GEN_KW SNAKE_OIL_PARAM templates/snake_oil_template.txt snake_oil_params.txt parameters/snake_oil_parameters.txt -CUSTOM_KW SNAKE_OIL_NPV snake_oil_npv.txt -GEN_DATA SNAKE_OIL_OPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_opr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_WPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_wpr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_GPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_gpr_diff_%d.txt REPORT_STEPS:199 - -LOG_LEVEL 3 -LOG_FILE log/log.txt -UPDATE_LOG_PATH log/update diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/snake_oil_GEO_ID.ert b/ThirdParty/Ert/test-data/local/snake_oil_no_data/snake_oil_GEO_ID.ert deleted file mode 100644 index 5818bd064d..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/snake_oil_GEO_ID.ert +++ /dev/null @@ -1,39 +0,0 @@ -QUEUE_SYSTEM LOCAL - -JOBNAME SNAKE_OIL_%d -NUM_REALIZATIONS 25 - -DEFINE storage/ - -STORE_SEED SEED -LOAD_SEED SEED - -RUNPATH simulations//realisation-%d/iter-%d -ENSPATH /ensemble -ECLBASE SNAKE_OIL_FIELD -SUMMARY * - -HISTORY_SOURCE REFCASE_HISTORY -REFCASE refcase/SNAKE_OIL_FIELD - -TIME_MAP refcase/time_map.txt -OBS_CONFIG observations/observations.txt - -INSTALL_JOB SNAKE_OIL_SIMULATOR jobs/SNAKE_OIL_SIMULATOR -INSTALL_JOB SNAKE_OIL_NPV jobs/SNAKE_OIL_NPV -INSTALL_JOB SNAKE_OIL_DIFF jobs/SNAKE_OIL_DIFF - -FORWARD_MODEL SNAKE_OIL_SIMULATOR -FORWARD_MODEL SNAKE_OIL_NPV -FORWARD_MODEL SNAKE_OIL_DIFF - -RUN_TEMPLATE templates/seed_template.txt seed.txt -GEN_KW SNAKE_OIL_PARAM templates/snake_oil_template.txt snake_oil_params.txt parameters/snake_oil_parameters.txt -CUSTOM_KW SNAKE_OIL_NPV snake_oil_npv.txt -GEN_DATA SNAKE_OIL_OPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_opr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_WPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_wpr_diff_%d.txt REPORT_STEPS:199 -GEN_DATA SNAKE_OIL_GPR_DIFF INPUT_FORMAT:ASCII RESULT_FILE:snake_oil_gpr_diff_%d.txt REPORT_STEPS:199 - -LOG_LEVEL 3 -LOG_FILE log/log.txt -UPDATE_LOG_PATH log/update diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/templates/seed_template.txt b/ThirdParty/Ert/test-data/local/snake_oil_no_data/templates/seed_template.txt deleted file mode 100644 index a0bca49fbd..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/templates/seed_template.txt +++ /dev/null @@ -1 +0,0 @@ -SEED: \ No newline at end of file diff --git a/ThirdParty/Ert/test-data/local/snake_oil_no_data/templates/snake_oil_template.txt b/ThirdParty/Ert/test-data/local/snake_oil_no_data/templates/snake_oil_template.txt deleted file mode 100644 index ad2c648a0b..0000000000 --- a/ThirdParty/Ert/test-data/local/snake_oil_no_data/templates/snake_oil_template.txt +++ /dev/null @@ -1,10 +0,0 @@ -OP1_PERSISTENCE: -OP1_OCTAVES: -OP1_DIVERGENCE_SCALE: -OP1_OFFSET: -OP2_PERSISTENCE: -OP2_OCTAVES: -OP2_DIVERGENCE_SCALE: -OP2_OFFSET: -BPR_555_PERSISTENCE: -BPR_138_PERSISTENCE: From 448f59983ec44fb868b1a35749e1810f8781c1b8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 24 Apr 2017 21:54:55 +0200 Subject: [PATCH 021/157] #1396 Update file reader based on API changes in ERT --- .../FileInterface/RifEclipseInputFileTools.cpp | 14 +++++++------- .../FileInterface/RifEclipseOutputFileTools.cpp | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index d4f9478a67..59e9f44c8f 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -121,22 +121,22 @@ bool RifEclipseInputFileTools::openGridFile(const QString& fileName, RigEclipseC bool allKwReadOk = true; fseek(gridFilePointer, specgridPos, SEEK_SET); - allKwReadOk = allKwReadOk && NULL != (specGridKw = ecl_kw_fscanf_alloc_current_grdecl__(gridFilePointer, false , ECL_INT_TYPE)); + allKwReadOk = allKwReadOk && NULL != (specGridKw = ecl_kw_fscanf_alloc_current_grdecl__(gridFilePointer, false , ecl_type_create_from_type(ECL_INT_TYPE))); progress.setProgress(1); fseek(gridFilePointer, zcornPos, SEEK_SET); - allKwReadOk = allKwReadOk && NULL != (zCornKw = ecl_kw_fscanf_alloc_current_grdecl__(gridFilePointer, false , ECL_FLOAT_TYPE)); + allKwReadOk = allKwReadOk && NULL != (zCornKw = ecl_kw_fscanf_alloc_current_grdecl__(gridFilePointer, false , ecl_type_create_from_type(ECL_FLOAT_TYPE))); progress.setProgress(2); fseek(gridFilePointer, coordPos, SEEK_SET); - allKwReadOk = allKwReadOk && NULL != (coordKw = ecl_kw_fscanf_alloc_current_grdecl__(gridFilePointer, false , ECL_FLOAT_TYPE)); + allKwReadOk = allKwReadOk && NULL != (coordKw = ecl_kw_fscanf_alloc_current_grdecl__(gridFilePointer, false , ecl_type_create_from_type(ECL_FLOAT_TYPE))); progress.setProgress(3); // If ACTNUM is not defined, this pointer will be NULL, which is a valid condition if (actnumPos >= 0) { fseek(gridFilePointer, actnumPos, SEEK_SET); - allKwReadOk = allKwReadOk && NULL != (actNumKw = ecl_kw_fscanf_alloc_current_grdecl__(gridFilePointer, false , ECL_INT_TYPE)); + allKwReadOk = allKwReadOk && NULL != (actNumKw = ecl_kw_fscanf_alloc_current_grdecl__(gridFilePointer, false , ecl_type_create_from_type(ECL_INT_TYPE))); progress.setProgress(4); } @@ -144,7 +144,7 @@ bool RifEclipseInputFileTools::openGridFile(const QString& fileName, RigEclipseC if (mapaxesPos >= 0) { fseek(gridFilePointer, mapaxesPos, SEEK_SET); - mapAxesKw = ecl_kw_fscanf_alloc_current_grdecl__( gridFilePointer, false , ECL_FLOAT_TYPE); + mapAxesKw = ecl_kw_fscanf_alloc_current_grdecl__( gridFilePointer, false , ecl_type_create_from_type(ECL_FLOAT_TYPE)); } if (!allKwReadOk) @@ -228,7 +228,7 @@ std::map RifEclipseInputFileTools::readProperties(const QStrin fseek(gridFilePointer, fileKeywords[i].filePos, SEEK_SET); - ecl_kw_type* eclipseKeywordData = ecl_kw_fscanf_alloc_current_grdecl__(gridFilePointer, false, ECL_FLOAT_TYPE); + ecl_kw_type* eclipseKeywordData = ecl_kw_fscanf_alloc_current_grdecl__(gridFilePointer, false, ecl_type_create_from_type(ECL_FLOAT_TYPE)); if (eclipseKeywordData) { QString newResultName = caseData->results(RifReaderInterface::MATRIX_RESULTS)->makeResultNameUnique(fileKeywords[i].keyword); @@ -261,7 +261,7 @@ bool RifEclipseInputFileTools::readProperty(const QString& fileName, RigEclipseC FILE* filePointer = util_fopen(fileName.toLatin1().data(), "r"); if (!filePointer) return false; - ecl_kw_type* eclipseKeywordData = ecl_kw_fscanf_alloc_grdecl_dynamic__(filePointer, eclipseKeyWord.toLatin1().data(), false, ECL_FLOAT_TYPE); + ecl_kw_type* eclipseKeywordData = ecl_kw_fscanf_alloc_grdecl_dynamic__(filePointer, eclipseKeyWord.toLatin1().data(), false, ecl_type_create_from_type(ECL_FLOAT_TYPE)); bool isOk = false; if (eclipseKeywordData) { diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp index 4df896c398..5754c3edd8 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp @@ -382,8 +382,9 @@ void RifEclipseOutputFileTools::createReportStepsMetaData(std::vector Date: Mon, 24 Apr 2017 21:56:04 +0200 Subject: [PATCH 022/157] #1396 Add define for updated ERT API used from opm-flowdiag-app --- ThirdParty/custom-opm-flowdiag-app/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ThirdParty/custom-opm-flowdiag-app/CMakeLists.txt b/ThirdParty/custom-opm-flowdiag-app/CMakeLists.txt index 6b2a9d5bc4..cd458bfda0 100644 --- a/ThirdParty/custom-opm-flowdiag-app/CMakeLists.txt +++ b/ThirdParty/custom-opm-flowdiag-app/CMakeLists.txt @@ -21,6 +21,8 @@ foreach (file ${project_source_files} ) list(APPEND project_source_files_complete_path1 "opm-flowdiagnostics-applications/${file}" ) endforeach() +add_definitions(-DHAVE_ERT_ECL_TYPE_H) + add_library(custom-opm-flowdiag-app ${project_source_files_complete_path1} ) From 19b9afe4cb0a195feee80d4dfa849d762e19f396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Tue, 25 Apr 2017 09:41:17 +0200 Subject: [PATCH 023/157] Use cleaner vector iteration --- .../ProjectDataModel/Summary/RimSummaryCurveFilter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp index cd01636a56..e9a8fc4866 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp @@ -275,9 +275,9 @@ void RimSummaryCurveFilter::fieldChangedByUi(const caf::PdmFieldHandle* changedF } else if (changedField == &m_showLegend) { - for (size_t i = 0; i < m_curves().size(); ++i) + for (auto curve : m_curves) { - m_curves()[i]->showLegend(m_showLegend()); + curve->showLegend(m_showLegend()); } } else From 68cb4ab54f46e5b4f8029c8b45a1556de3438256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Tue, 25 Apr 2017 10:11:42 +0200 Subject: [PATCH 024/157] Better naming of legend configuration properties --- ApplicationCode/ProjectDataModel/RimPlotCurve.cpp | 2 +- ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp b/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp index 8e836719de..65f0a06ccd 100644 --- a/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimPlotCurve.cpp @@ -90,7 +90,7 @@ RimPlotCurve::RimPlotCurve() CAF_PDM_InitField(&m_symbolSkipPixelDistance, "SymbolSkipPxDist", 0.0f, "Symbol Skip Distance", "", "Minimum pixel distance between symbols", ""); - CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Show Legend", "", "", ""); + CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Contribute To Legend", "", "", ""); m_qwtPlotCurve = new RiuLineSegmentQwtPlotCurve; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index b2e94f5a7b..fd055b156c 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -58,9 +58,9 @@ RimSummaryPlot::RimSummaryPlot() CAF_PDM_InitObject("Summary Plot", ":/SummaryPlotLight16x16.png", "", ""); CAF_PDM_InitField(&m_userName, "PlotDescription", QString("Summary Plot"), "Name", "", "", ""); - CAF_PDM_InitField(&m_showPlotTitle, "ShowPlotTitle", true, "Show Plot Title", "", "", ""); + CAF_PDM_InitField(&m_showPlotTitle, "ShowPlotTitle", true, "Plot Title", "", "", ""); m_showPlotTitle.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Show Legend", "", "", ""); + CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Legend", "", "", ""); m_showLegend.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); CAF_PDM_InitFieldNoDefault(&m_curveFilters, "SummaryCurveFilters", "", "", "", ""); From 63cd817b857c759828b422d3c892f4e400a50a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Tue, 25 Apr 2017 10:31:37 +0200 Subject: [PATCH 025/157] #964 Improve code robustness in defineEditorAttribute --- .../Application/RiaPreferences.cpp | 4 +-- .../Application/RiaRegressionTest.cpp | 2 +- .../Commands/RicExportToLasFileResampleUi.cpp | 4 +-- .../FileInterface/RifReaderSettings.cpp | 2 +- .../RimBinaryExportSettings.cpp | 2 +- .../ProjectDataModel/RimCellRangeFilter.cpp | 2 +- .../RimEclipseStatisticsCase.cpp | 10 +++++-- .../RimExportInputPropertySettings.cpp | 2 +- .../ProjectDataModel/RimIntersection.cpp | 30 +++++++++++-------- .../ProjectDataModel/RimIntersectionBox.cpp | 16 ++++++---- .../ProjectDataModel/RimScriptCollection.cpp | 7 +++-- .../Summary/RimSummaryCurveFilter.cpp | 5 +++- .../Summary/RimSummaryPlot.cpp | 2 +- 13 files changed, 55 insertions(+), 33 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 43d55343d5..a2a16dad8e 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -113,7 +113,7 @@ void RiaPreferences::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt if (field == &scriptDirectories) { - caf::PdmUiFilePathEditorAttribute* myAttr = static_cast(attribute); + caf::PdmUiFilePathEditorAttribute* myAttr = dynamic_cast(attribute); if (myAttr) { myAttr->m_selectDirectory = true; @@ -129,7 +129,7 @@ void RiaPreferences::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt field == &showLasCurveWithoutTvdWarning || field == &autoCreatePlotsOnImport) { - caf::PdmUiCheckBoxEditorAttribute* myAttr = static_cast(attribute); + caf::PdmUiCheckBoxEditorAttribute* myAttr = dynamic_cast(attribute); if (myAttr) { myAttr->m_useNativeCheckBoxLabel = true; diff --git a/ApplicationCode/Application/RiaRegressionTest.cpp b/ApplicationCode/Application/RiaRegressionTest.cpp index f05e1f28e6..ce54c33d17 100644 --- a/ApplicationCode/Application/RiaRegressionTest.cpp +++ b/ApplicationCode/Application/RiaRegressionTest.cpp @@ -51,7 +51,7 @@ void RiaRegressionTest::defineEditorAttribute(const caf::PdmFieldHandle* field, { if (field == &applicationWorkingFolder || field == ®ressionTestFolder) { - caf::PdmUiFilePathEditorAttribute* myAttr = static_cast(attribute); + caf::PdmUiFilePathEditorAttribute* myAttr = dynamic_cast(attribute); if (myAttr) { myAttr->m_selectDirectory = true; diff --git a/ApplicationCode/Commands/RicExportToLasFileResampleUi.cpp b/ApplicationCode/Commands/RicExportToLasFileResampleUi.cpp index 3f45167a4d..43125dc085 100644 --- a/ApplicationCode/Commands/RicExportToLasFileResampleUi.cpp +++ b/ApplicationCode/Commands/RicExportToLasFileResampleUi.cpp @@ -121,7 +121,7 @@ void RicExportToLasFileResampleUi::defineEditorAttribute(const caf::PdmFieldHand { if (field == &exportFolder) { - caf::PdmUiFilePathEditorAttribute* myAttr = static_cast(attribute); + caf::PdmUiFilePathEditorAttribute* myAttr = dynamic_cast(attribute); if (myAttr) { myAttr->m_selectDirectory = true; @@ -130,7 +130,7 @@ void RicExportToLasFileResampleUi::defineEditorAttribute(const caf::PdmFieldHand if (field == &exportTvdrkb || field == &activateResample) { - caf::PdmUiCheckBoxEditorAttribute* myAttr = static_cast(attribute); + caf::PdmUiCheckBoxEditorAttribute* myAttr = dynamic_cast(attribute); if (myAttr) { myAttr->m_useNativeCheckBoxLabel = true; diff --git a/ApplicationCode/FileInterface/RifReaderSettings.cpp b/ApplicationCode/FileInterface/RifReaderSettings.cpp index ed6174d3d1..89fc15b397 100644 --- a/ApplicationCode/FileInterface/RifReaderSettings.cpp +++ b/ApplicationCode/FileInterface/RifReaderSettings.cpp @@ -52,7 +52,7 @@ void RifReaderSettings::defineEditorAttribute(const caf::PdmFieldHandle* field, field == &importAdvancedMswData || field == &importNNCs) { - caf::PdmUiCheckBoxEditorAttribute* myAttr = static_cast(attribute); + caf::PdmUiCheckBoxEditorAttribute* myAttr = dynamic_cast(attribute); if (myAttr) { myAttr->m_useNativeCheckBoxLabel = true; diff --git a/ApplicationCode/ProjectDataModel/RimBinaryExportSettings.cpp b/ApplicationCode/ProjectDataModel/RimBinaryExportSettings.cpp index fb579ce85b..d130d87ef0 100644 --- a/ApplicationCode/ProjectDataModel/RimBinaryExportSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimBinaryExportSettings.cpp @@ -43,7 +43,7 @@ void RimBinaryExportSettings::defineEditorAttribute(const caf::PdmFieldHandle* f { if (field == &fileName) { - caf::PdmUiFilePathEditorAttribute* myAttr = static_cast(attribute); + caf::PdmUiFilePathEditorAttribute* myAttr = dynamic_cast(attribute); if (myAttr) { myAttr->m_selectSaveFileName = true; diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp index 86d1466e93..79cba2b624 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp @@ -171,7 +171,7 @@ RimCellRangeFilterCollection* RimCellRangeFilter::parentContainer() //-------------------------------------------------------------------------------------------------- void RimCellRangeFilter::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute) { - caf::PdmUiSliderEditorAttribute* myAttr = static_cast(attribute); + caf::PdmUiSliderEditorAttribute* myAttr = dynamic_cast(attribute); if (!myAttr || !parentContainer()) { return; diff --git a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp index 4e4c402dd7..00bfc18079 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCase.cpp @@ -613,13 +613,19 @@ void RimEclipseStatisticsCase::defineEditorAttribute(const caf::PdmFieldHandle* if (&m_selectionSummary == field) { caf::PdmUiTextEditorAttribute* textEditAttrib = dynamic_cast (attribute); - textEditAttrib->textMode = caf::PdmUiTextEditorAttribute::HTML; + if (textEditAttrib) + { + textEditAttrib->textMode = caf::PdmUiTextEditorAttribute::HTML; + } } if (&m_calculateEditCommand == field) { caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast (attribute); - attrib->m_buttonText = hasComputedStatistics() ? "Edit (Will DELETE current results)": "Compute"; + if (attrib) + { + attrib->m_buttonText = hasComputedStatistics() ? "Edit (Will DELETE current results)": "Compute"; + } } } diff --git a/ApplicationCode/ProjectDataModel/RimExportInputPropertySettings.cpp b/ApplicationCode/ProjectDataModel/RimExportInputPropertySettings.cpp index 72ac153ea7..b7ac2b0bb2 100644 --- a/ApplicationCode/ProjectDataModel/RimExportInputPropertySettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimExportInputPropertySettings.cpp @@ -42,7 +42,7 @@ void RimExportInputSettings::defineEditorAttribute(const caf::PdmFieldHandle* fi { if (field == &fileName) { - caf::PdmUiFilePathEditorAttribute* myAttr = static_cast(attribute); + caf::PdmUiFilePathEditorAttribute* myAttr = dynamic_cast(attribute); if (myAttr) { myAttr->m_selectSaveFileName = true; diff --git a/ApplicationCode/ProjectDataModel/RimIntersection.cpp b/ApplicationCode/ProjectDataModel/RimIntersection.cpp index 0afe1b16e7..5506f75758 100644 --- a/ApplicationCode/ProjectDataModel/RimIntersection.cpp +++ b/ApplicationCode/ProjectDataModel/RimIntersection.cpp @@ -553,13 +553,16 @@ void RimIntersection::defineEditorAttribute(const caf::PdmFieldHandle* field, QS { caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast (attribute); - if (inputPolyLineFromViewerEnabled) + if (attrib) { - attrib->m_buttonText = "Stop picking points"; - } - else - { - attrib->m_buttonText = "Start picking points"; + if (inputPolyLineFromViewerEnabled) + { + attrib->m_buttonText = "Stop picking points"; + } + else + { + attrib->m_buttonText = "Start picking points"; + } } } else if (field == &m_userPolyline) @@ -574,13 +577,16 @@ void RimIntersection::defineEditorAttribute(const caf::PdmFieldHandle* field, QS { caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast (attribute); - if (inputExtrusionPointsFromViewerEnabled) + if (attrib) { - attrib->m_buttonText = "Stop picking points"; - } - else - { - attrib->m_buttonText = "Start picking points"; + if (inputExtrusionPointsFromViewerEnabled) + { + attrib->m_buttonText = "Stop picking points"; + } + else + { + attrib->m_buttonText = "Start picking points"; + } } } else if (field == &m_customExtrusionPoints) diff --git a/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp b/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp index 936d5e8d1d..54f543a790 100644 --- a/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp +++ b/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp @@ -404,14 +404,18 @@ void RimIntersectionBox::defineEditorAttribute(const caf::PdmFieldHandle* field, { caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast (attribute); - if (m_show3DManipulator) + if (attrib) { - attrib->m_buttonText = "Hide 3D manipulator"; - } - else - { - attrib->m_buttonText = "Show 3D manipulator"; + if (m_show3DManipulator) + { + attrib->m_buttonText = "Hide 3D manipulator"; + } + else + { + attrib->m_buttonText = "Show 3D manipulator"; + } } + } } diff --git a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp index 04908c574c..80acea1865 100644 --- a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp @@ -187,7 +187,10 @@ void RimScriptCollection::defineEditorAttribute(const caf::PdmFieldHandle* field { if (field == &directory) { - caf::PdmUiFilePathEditorAttribute* myAttr = static_cast(attribute); - myAttr->m_selectDirectory = true; + caf::PdmUiFilePathEditorAttribute* myAttr = dynamic_cast(attribute); + if (myAttr) + { + myAttr->m_selectDirectory = true; + } } } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp index e9a8fc4866..16e56ef630 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp @@ -423,7 +423,10 @@ void RimSummaryCurveFilter::defineEditorAttribute(const caf::PdmFieldHandle* fie if(&m_applyButtonField == field) { caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast (attribute); - attrib->m_buttonText = "Apply"; + if (attrib) + { + attrib->m_buttonText = "Apply"; + } } } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index fd055b156c..4356570764 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -984,7 +984,7 @@ void RimSummaryPlot::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt { if (field == &m_showLegend || field == &m_showPlotTitle) { - caf::PdmUiCheckBoxEditorAttribute* myAttr = static_cast(attribute); + caf::PdmUiCheckBoxEditorAttribute* myAttr = dynamic_cast(attribute); if (myAttr) { myAttr->m_useNativeCheckBoxLabel = true; From 8ec0d2d685c248b891f4a73383582ec943184353 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 25 Apr 2017 13:28:51 +0200 Subject: [PATCH 026/157] #1396 Add patch for synthetic ODB files --- patches/fix-synthetic-odb-cases.patch | 43 +++++++++++++++++++++++++++ patches/readme.txt | 6 ++++ 2 files changed, 49 insertions(+) create mode 100644 patches/fix-synthetic-odb-cases.patch create mode 100644 patches/readme.txt diff --git a/patches/fix-synthetic-odb-cases.patch b/patches/fix-synthetic-odb-cases.patch new file mode 100644 index 0000000000..6b3247c686 --- /dev/null +++ b/patches/fix-synthetic-odb-cases.patch @@ -0,0 +1,43 @@ +From 8d2557fe8dd00ac30f524197c8a50db2e89bf720 Mon Sep 17 00:00:00 2001 +From: Magne Sjaastad +Date: Tue, 25 Apr 2017 13:11:00 +0200 +Subject: [PATCH] #1396 Reapply fix for synthetic odb files + +--- + ThirdParty/Ert/libecl/src/ecl_rsthead.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/ThirdParty/Ert/libecl/src/ecl_rsthead.c b/ThirdParty/Ert/libecl/src/ecl_rsthead.c +index 52ad954..e382cc1 100644 +--- a/ThirdParty/Ert/libecl/src/ecl_rsthead.c ++++ b/ThirdParty/Ert/libecl/src/ecl_rsthead.c +@@ -88,7 +88,8 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ + // The only derived quantity + rsthead->sim_time = rsthead_date( rsthead->day , rsthead->month , rsthead->year ); + } +- rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); ++ if (doubhead_kw) ++ rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); + if (logihead_kw) + rsthead->dualp = ecl_kw_iget_bool( logihead_kw , LOGIHEAD_DUALP_INDEX); + +@@ -109,12 +110,15 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ + + ecl_rsthead_type * ecl_rsthead_alloc( const ecl_file_view_type * rst_view, int report_step) { + const ecl_kw_type * intehead_kw = ecl_file_view_iget_named_kw( rst_view , INTEHEAD_KW , 0); +- const ecl_kw_type * doubhead_kw = ecl_file_view_iget_named_kw( rst_view , DOUBHEAD_KW , 0); ++ const ecl_kw_type * doubhead_kw = NULL; + const ecl_kw_type * logihead_kw = NULL; + + if (ecl_file_view_has_kw(rst_view, LOGIHEAD_KW)) + logihead_kw = ecl_file_view_iget_named_kw( rst_view , LOGIHEAD_KW , 0); + ++ if (ecl_file_view_has_kw(rst_view, DOUBHEAD_KW)) ++ doubhead_kw = ecl_file_view_iget_named_kw(rst_view, DOUBHEAD_KW, 0); ++ + if (ecl_file_view_has_kw( rst_view , SEQNUM_KW)) { + const ecl_kw_type * seqnum_kw = ecl_file_view_iget_named_kw( rst_view , SEQNUM_KW , 0); + report_step = ecl_kw_iget_int( seqnum_kw , 0); +-- +2.10.2.windows.1 + diff --git a/patches/readme.txt b/patches/readme.txt new file mode 100644 index 0000000000..23d442149b --- /dev/null +++ b/patches/readme.txt @@ -0,0 +1,6 @@ + +Command line: +git apply --reject --whitespace=fix patches/fix-synthetic-odb-cases.patch + +Description: +Will fix reading of special Eclipse cases related to synthetic ODB test cases. Required for regression testing. From 64d41fa109fafe593bc32ce363e27ebc2bd0cc30 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 25 Apr 2017 13:30:09 +0200 Subject: [PATCH 027/157] #1396 Apply patch fix-synthetic-odb-cases --- ThirdParty/Ert/libecl/src/ecl_rsthead.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ThirdParty/Ert/libecl/src/ecl_rsthead.c b/ThirdParty/Ert/libecl/src/ecl_rsthead.c index 52ad95436d..2918838740 100644 --- a/ThirdParty/Ert/libecl/src/ecl_rsthead.c +++ b/ThirdParty/Ert/libecl/src/ecl_rsthead.c @@ -88,7 +88,8 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ // The only derived quantity rsthead->sim_time = rsthead_date( rsthead->day , rsthead->month , rsthead->year ); } - rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); + if (doubhead_kw) + rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); if (logihead_kw) rsthead->dualp = ecl_kw_iget_bool( logihead_kw , LOGIHEAD_DUALP_INDEX); @@ -109,12 +110,15 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ ecl_rsthead_type * ecl_rsthead_alloc( const ecl_file_view_type * rst_view, int report_step) { const ecl_kw_type * intehead_kw = ecl_file_view_iget_named_kw( rst_view , INTEHEAD_KW , 0); - const ecl_kw_type * doubhead_kw = ecl_file_view_iget_named_kw( rst_view , DOUBHEAD_KW , 0); + const ecl_kw_type * doubhead_kw = NULL; const ecl_kw_type * logihead_kw = NULL; if (ecl_file_view_has_kw(rst_view, LOGIHEAD_KW)) logihead_kw = ecl_file_view_iget_named_kw( rst_view , LOGIHEAD_KW , 0); + if (ecl_file_view_has_kw(rst_view, DOUBHEAD_KW)) + doubhead_kw = ecl_file_view_iget_named_kw(rst_view, DOUBHEAD_KW, 0); + if (ecl_file_view_has_kw( rst_view , SEQNUM_KW)) { const ecl_kw_type * seqnum_kw = ecl_file_view_iget_named_kw( rst_view , SEQNUM_KW , 0); report_step = ecl_kw_iget_int( seqnum_kw , 0); From 63b07b1152bb9ed402d81b9683b3b9e2f601c90c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 25 Apr 2017 15:01:31 +0200 Subject: [PATCH 028/157] #1430 When closing top level windows, do not close project if other is visible --- ApplicationCode/Application/RiaApplication.cpp | 18 ++++++++++++++++++ ApplicationCode/Application/RiaApplication.h | 3 +++ .../UserInterface/RiuMainPlotWindow.cpp | 6 ++++++ .../UserInterface/RiuMainWindow.cpp | 6 ++++++ 4 files changed, 33 insertions(+) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 8141bb3e6a..6cc13108d8 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1708,6 +1708,24 @@ RimViewWindow* RiaApplication::activeViewWindow() return viewWindow; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaApplication::isMain3dWindowVisible() const +{ + return RiuMainWindow::instance()->isVisible(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaApplication::isMainPlotWindowVisible() const +{ + if (!m_mainPlotWindow) return false; + + return m_mainPlotWindow->isVisible(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 79de925275..8e158e3ebc 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -185,6 +185,9 @@ public: static RimViewWindow* activeViewWindow(); + bool isMain3dWindowVisible() const; + bool isMainPlotWindowVisible() const; + bool tryCloseMainWindow(); bool tryClosePlotWindow(); diff --git a/ApplicationCode/UserInterface/RiuMainPlotWindow.cpp b/ApplicationCode/UserInterface/RiuMainPlotWindow.cpp index e00847420b..12454f36dd 100644 --- a/ApplicationCode/UserInterface/RiuMainPlotWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainPlotWindow.cpp @@ -138,6 +138,12 @@ void RiuMainPlotWindow::cleanupGuiBeforeProjectClose() void RiuMainPlotWindow::closeEvent(QCloseEvent* event) { RiaApplication* app = RiaApplication::instance(); + + if (app->isMain3dWindowVisible()) + { + return; + } + if (!app->askUserToSaveModifiedProject()) { event->ignore(); diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index e31450532f..be0be55803 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -198,6 +198,12 @@ void RiuMainWindow::cleanupGuiBeforeProjectClose() void RiuMainWindow::closeEvent(QCloseEvent* event) { RiaApplication* app = RiaApplication::instance(); + + if (app->isMainPlotWindowVisible()) + { + return; + } + if (!app->askUserToSaveModifiedProject()) { event->ignore(); From 1f7c357b678c1fa1c775b022911ffae3c1f009d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Apr 2017 12:31:49 +0200 Subject: [PATCH 029/157] #1427 Add simulation Well and branch index to well log extraction curve and make the extraction work in those cases. --- .../RimWellLogExtractionCurve.cpp | 264 ++++++++++++++++-- .../RimWellLogExtractionCurve.h | 13 + .../RimWellLogPlotCollection.cpp | 28 ++ .../RimWellLogPlotCollection.h | 7 +- 4 files changed, 284 insertions(+), 28 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp index 5da8286b36..55c0ad4896 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp @@ -28,6 +28,9 @@ #include "RigGeoMechCaseData.h" #include "RigGeoMechWellLogExtractor.h" #include "RigResultAccessorFactory.h" +#include "RigSimulationWellCenterLineCalculator.h" +#include "RigSimulationWellCoordsAndMD.h" +#include "RigSingleWellResultsData.h" #include "RigWellLogCurveData.h" #include "RigWellPath.h" @@ -38,6 +41,7 @@ #include "RimGeoMechCase.h" #include "RimGeoMechResultDefinition.h" #include "RimGeoMechView.h" +#include "RimMainPlotCollection.h" #include "RimOilField.h" #include "RimProject.h" #include "RimTools.h" @@ -63,6 +67,19 @@ CAF_PDM_SOURCE_INIT(RimWellLogExtractionCurve, "RimWellLogExtractionCurve"); + +namespace caf +{ +template<> +void AppEnum< RimWellLogExtractionCurve::TrajectoryType >::setUp() +{ + addItem(RimWellLogExtractionCurve::WELL_PATH, "WELL_PATH", "Well Path"); + addItem(RimWellLogExtractionCurve::SIMULATION_WELL, "SIMULATION_WELL", "Simulation Well"); + setDefault(RimWellLogExtractionCurve::WELL_PATH); +} +} + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -70,17 +87,22 @@ RimWellLogExtractionCurve::RimWellLogExtractionCurve() { CAF_PDM_InitObject("Well Log Curve", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_wellPath, "CurveWellPath", "Well Path", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_trajectoryType, "TrajectoryType", "Trajectory", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&m_wellPath, "CurveWellPath", " ", "", "", ""); m_wellPath.uiCapability()->setUiTreeChildrenHidden(true); - //m_wellPath.uiCapability()->setUiHidden(true); + + CAF_PDM_InitField(&m_simWellName, "SimulationWellName", QString("None"), " ", "", "", ""); + CAF_PDM_InitField(&m_branchIndex, "Branch", 0, " ", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_case, "CurveCase", "Case", "", "", ""); m_case.uiCapability()->setUiTreeChildrenHidden(true); - //m_case.uiCapability()->setUiHidden(true); + CAF_PDM_InitFieldNoDefault(&m_eclipseResultDefinition, "CurveEclipseResult", "", "", "", ""); m_eclipseResultDefinition.uiCapability()->setUiHidden(true); m_eclipseResultDefinition.uiCapability()->setUiTreeChildrenHidden(true); m_eclipseResultDefinition = new RimEclipseResultDefinition; + m_eclipseResultDefinition->findField("MResultType")->uiCapability()->setUiName("Result Type"); CAF_PDM_InitFieldNoDefault(&m_geomResultDefinition, "CurveGeomechResult", "", "", "", ""); m_geomResultDefinition.uiCapability()->setUiHidden(true); @@ -102,6 +124,8 @@ RimWellLogExtractionCurve::RimWellLogExtractionCurve() //-------------------------------------------------------------------------------------------------- RimWellLogExtractionCurve::~RimWellLogExtractionCurve() { + clearGeneratedSimWellPaths(); + delete m_geomResultDefinition; delete m_eclipseResultDefinition; } @@ -129,6 +153,7 @@ RimWellPath* RimWellLogExtractionCurve::wellPath() const void RimWellLogExtractionCurve::setCase(RimCase* rimCase) { m_case = rimCase; + clearGeneratedSimWellPaths(); } //-------------------------------------------------------------------------------------------------- @@ -165,6 +190,8 @@ void RimWellLogExtractionCurve::setPropertiesFromView(RimView* view) m_geomResultDefinition->setResultAddress(geoMechView->cellResultResultDefinition()->resultAddress()); m_timeStep = geoMechView->currentTimeStep(); } + + clearGeneratedSimWellPaths(); } //-------------------------------------------------------------------------------------------------- @@ -181,6 +208,23 @@ void RimWellLogExtractionCurve::clampTimestep() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogExtractionCurve::clampBranchIndex() +{ + int branchCount = static_cast(m_generatedSimulationWellPathBranches.size()); + if ( branchCount > 0 ) + { + if ( m_branchIndex >= branchCount ) m_branchIndex = branchCount - 1; + else if ( m_branchIndex < 0 ) m_branchIndex = 0; + } + else + { + m_branchIndex = -1; + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -191,6 +235,11 @@ void RimWellLogExtractionCurve::fieldChangedByUi(const caf::PdmFieldHandle* chan if (changedField == &m_case) { clampTimestep(); + + auto wellNameSet = findSortedWellNames(); + if (!wellNameSet.count(m_simWellName())) m_simWellName = "None"; + + clearGeneratedSimWellPaths(); this->loadDataAndUpdate(); } @@ -198,6 +247,17 @@ void RimWellLogExtractionCurve::fieldChangedByUi(const caf::PdmFieldHandle* chan { this->loadDataAndUpdate(); } + else if (changedField == &m_simWellName) + { + clearGeneratedSimWellPaths(); + + this->loadDataAndUpdate(); + } + else if (changedField == &m_trajectoryType || + changedField == &m_branchIndex) + { + this->loadDataAndUpdate(); + } else if (changedField == &m_timeStep) { this->loadDataAndUpdate(); @@ -230,12 +290,27 @@ void RimWellLogExtractionCurve::onLoadDataAndUpdate() m_eclipseResultDefinition->setEclipseCase(eclipseCase); m_geomResultDefinition->setGeoMechCase(geomCase); - RimWellLogPlotCollection* wellLogCollection = NULL; - this->firstAncestorOrThisOfType(wellLogCollection); - CVF_ASSERT(wellLogCollection); - if (!wellLogCollection) return; + updateGeneratedSimulationWellpath(); + clampBranchIndex(); - cvf::ref eclExtractor = wellLogCollection->findOrCreateExtractor(m_wellPath, eclipseCase); + RimWellLogPlotCollection* wellLogCollection; + this->firstAncestorOrThisOfTypeAsserted(wellLogCollection); + + cvf::ref eclExtractor; + if ( m_trajectoryType == WELL_PATH ) + { + eclExtractor = wellLogCollection->findOrCreateExtractor(m_wellPath, eclipseCase); + } + else + { + if (m_branchIndex >= 0 && m_branchIndex < m_generatedSimulationWellPathBranches.size() ) + { + eclExtractor = wellLogCollection->findOrCreateSimWellExtractor(m_simWellName, + eclipseCase->caseUserDescription(), + m_generatedSimulationWellPathBranches[m_branchIndex].p(), + eclipseCase->eclipseCaseData()); + } + } cvf::ref geomExtractor = wellLogCollection->findOrCreateExtractor(m_wellPath, geomCase); std::vector values; @@ -321,6 +396,94 @@ void RimWellLogExtractionCurve::onLoadDataAndUpdate() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RimWellLogExtractionCurve::findSortedWellNames() +{ + std::set sortedWellNames; + RimEclipseCase* eclipseCase = dynamic_cast(m_case.value()); + + if ( eclipseCase && eclipseCase->eclipseCaseData() ) + { + const cvf::Collection& wellRes = eclipseCase->eclipseCaseData()->wellResults(); + + for ( size_t wIdx = 0; wIdx < wellRes.size(); ++wIdx ) + { + sortedWellNames.insert(wellRes[wIdx]->m_wellName); + } + } + + return sortedWellNames; +} + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogExtractionCurve::updateGeneratedSimulationWellpath() +{ + if (m_generatedSimulationWellPathBranches.size()) return; // Already created. Nothing to do + + RimEclipseCase* eclipseCase = dynamic_cast(m_case.value()); + + if (!(!m_simWellName().isEmpty() && m_simWellName() != "None" && eclipseCase && eclipseCase->eclipseCaseData())) + { + return ; + } + + RigEclipseCaseData* eclCaseData = eclipseCase->eclipseCaseData(); + const RigSingleWellResultsData* wellResults = eclCaseData->findWellResult(m_simWellName()); + + if (!wellResults) return; + + std::vector< std::vector > pipeBranchesCLCoords; + std::vector< std::vector > pipeBranchesCellIds; + + RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellFrame(eclCaseData, + wellResults, + -1, + true, + true, + pipeBranchesCLCoords, + pipeBranchesCellIds); + + + for ( size_t brIdx = 0; brIdx < pipeBranchesCLCoords.size(); ++brIdx ) + { + auto wellMdCalculator = RigSimulationWellCoordsAndMD(pipeBranchesCLCoords[brIdx]); // Todo, branch index + + cvf::ref newWellPath = new RigWellPath(); + newWellPath->m_measuredDepths = wellMdCalculator.measuredDepths(); + newWellPath->m_wellPathPoints = wellMdCalculator.wellPathPoints(); + + m_generatedSimulationWellPathBranches.push_back(newWellPath.p() ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// Clean up existing generated well paths +//-------------------------------------------------------------------------------------------------- +void RimWellLogExtractionCurve::clearGeneratedSimWellPaths() +{ + RimWellLogPlotCollection* wellLogCollection = nullptr; + + // Need to use this approach, and not firstAnchestor because the curve might not be inside the hierarchy when deleted. + + RimProject * proj = RiaApplication::instance()->project(); + if (proj && proj->mainPlotCollection() ) wellLogCollection = proj->mainPlotCollection()->wellLogPlotCollection(); + + if (!wellLogCollection) return; + + for ( size_t wpIdx = 0; wpIdx < m_generatedSimulationWellPathBranches.size(); ++wpIdx ) + { + wellLogCollection->removeExtractors(m_generatedSimulationWellPathBranches[wpIdx].p()); + } + + m_generatedSimulationWellPathBranches.clear(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -335,19 +498,13 @@ QList RimWellLogExtractionCurve::calculateValueOptions(c { RimTools::wellPathOptionItems(&options); - if (options.size() > 0) - { - options.push_front(caf::PdmOptionItemInfo("None", nullptr)); - } + options.push_front(caf::PdmOptionItemInfo("None", nullptr)); } else if (fieldNeedingOptions == &m_case) { RimTools::caseOptionItems(&options); - if (options.size() > 0) - { - options.push_front(caf::PdmOptionItemInfo("None", nullptr)); - } + options.push_front(caf::PdmOptionItemInfo("None", nullptr)); } else if (fieldNeedingOptions == &m_timeStep) { @@ -363,7 +520,37 @@ QList RimWellLogExtractionCurve::calculateValueOptions(c options.push_back(caf::PdmOptionItemInfo(timeStepNames[i], i)); } } + else if (fieldNeedingOptions == &m_simWellName) + { + std::set sortedWellNames = this->findSortedWellNames(); + QIcon simWellIcon(":/Well.png"); + for ( const QString& wname: sortedWellNames ) + { + options.push_back(caf::PdmOptionItemInfo(wname, wname, false, simWellIcon)); + } + + if ( options.size() == 0 ) + { + options.push_front(caf::PdmOptionItemInfo("None", "None")); + } + } + else if (fieldNeedingOptions == &m_branchIndex) + { + updateGeneratedSimulationWellpath(); + + size_t branchCount = m_generatedSimulationWellPathBranches.size(); + + for ( int bIdx = 0; bIdx < branchCount; ++bIdx) + { + options.push_back(caf::PdmOptionItemInfo("Branch " + QString::number(bIdx + 1), QVariant::fromValue(bIdx) )); + } + + if (options.size() == 0) + { + options.push_front(caf::PdmOptionItemInfo("None", -1)); + } + } return options; } @@ -377,25 +564,39 @@ void RimWellLogExtractionCurve::defineUiOrdering(QString uiConfigName, caf::PdmU caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup("Curve Data"); - curveDataGroup->add(&m_wellPath); curveDataGroup->add(&m_case); - + RimGeoMechCase* geomCase = dynamic_cast(m_case.value()); RimEclipseCase* eclipseCase = dynamic_cast(m_case.value()); + curveDataGroup->add(&m_trajectoryType); + if (m_trajectoryType() == WELL_PATH) + { + curveDataGroup->add(&m_wellPath); + } + else + { + curveDataGroup->add(&m_simWellName); + if ( m_generatedSimulationWellPathBranches.size() > 1 ) + { + curveDataGroup->add(&m_branchIndex); + } + } + if (eclipseCase) { m_eclipseResultDefinition->uiOrdering(uiConfigName, *curveDataGroup); - if (m_eclipseResultDefinition->hasDynamicResult()) - { - curveDataGroup->add(&m_timeStep); - } } else if (geomCase) { m_geomResultDefinition->uiOrdering(uiConfigName, *curveDataGroup); - + + } + + if ( (eclipseCase && m_eclipseResultDefinition->hasDynamicResult()) + || geomCase) + { curveDataGroup->add(&m_timeStep); } @@ -471,9 +672,11 @@ QString RimWellLogExtractionCurve::createCurveAutoName() RimEclipseCase* eclipseCase = dynamic_cast(m_case.value()); QString generatedCurveName; - if (m_addWellNameToCurveName && m_wellPath) + if (m_addWellNameToCurveName ) { generatedCurveName += wellName(); + + // Todo: Branch } if (m_addCaseNameToCurveName && m_case()) @@ -578,13 +781,20 @@ QString RimWellLogExtractionCurve::wellLogChannelName() const //-------------------------------------------------------------------------------------------------- QString RimWellLogExtractionCurve::wellName() const { - if (m_wellPath) + if ( m_trajectoryType() == WELL_PATH ) { - return m_wellPath->name(); + if ( m_wellPath ) + { + return m_wellPath->name(); + } + else + { + return QString(); + } } else { - return QString(); + return m_simWellName; } } diff --git a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h index 2ebf168c03..f314989fc4 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h +++ b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h @@ -23,12 +23,14 @@ #include "cafPdmPtrField.h" #include "cafPdmChildField.h" +#include "cvfCollection.h" class RimCase; class RimEclipseResultDefinition; class RimGeoMechResultDefinition; class RimView; class RimWellPath; +class RigWellPath; //================================================================================================== /// @@ -41,6 +43,8 @@ public: RimWellLogExtractionCurve(); virtual ~RimWellLogExtractionCurve(); + enum TrajectoryType { WELL_PATH, SIMULATION_WELL}; + void setWellPath(RimWellPath* wellPath); RimWellPath* wellPath() const; @@ -73,9 +77,16 @@ protected: private: void setLogScaleFromSelectedResult(); void clampTimestep(); + void clampBranchIndex(); + std::set findSortedWellNames(); + void updateGeneratedSimulationWellpath(); + void clearGeneratedSimWellPaths(); private: caf::PdmPtrField m_wellPath; + caf::PdmField > m_trajectoryType; + caf::PdmField m_simWellName; + caf::PdmField m_branchIndex; caf::PdmPtrField m_case; caf::PdmChildField m_eclipseResultDefinition; caf::PdmChildField m_geomResultDefinition; @@ -86,5 +97,7 @@ private: caf::PdmField m_addWellNameToCurveName; caf::PdmField m_addTimestepToCurveName; caf::PdmField m_addDateToCurveName; + + cvf::Collection m_generatedSimulationWellPathBranches; }; diff --git a/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.cpp index fe8cbaf0d4..b1f0ac84d4 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.cpp @@ -52,6 +52,34 @@ RimWellLogPlotCollection::~RimWellLogPlotCollection() wellLogPlots.deleteAllChildObjects(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigEclipseWellLogExtractor* RimWellLogPlotCollection::findOrCreateSimWellExtractor(const QString& simWellName, + const QString& caseUserDescription, + const RigWellPath* wellPathGeom, + const RigEclipseCaseData* eclCaseData) +{ + if (!(wellPathGeom && eclCaseData)) + { + return nullptr; + } + + for (size_t exIdx = 0; exIdx < m_extractors.size(); ++exIdx) + { + if (m_extractors[exIdx]->caseData() == eclCaseData && m_extractors[exIdx]->wellPathData() == wellPathGeom) + { + return m_extractors[exIdx].p(); + } + } + + std::string errorIdName = (simWellName + " " + caseUserDescription).toStdString(); + cvf::ref extractor = new RigEclipseWellLogExtractor(eclCaseData, wellPathGeom, errorIdName); + m_extractors.push_back(extractor.p()); + + return extractor.p(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.h b/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.h index dba85804d5..11990bffbe 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.h @@ -45,7 +45,12 @@ class RimWellLogPlotCollection : public caf::PdmObject public: RimWellLogPlotCollection(); virtual ~RimWellLogPlotCollection(); - + + RigEclipseWellLogExtractor* findOrCreateSimWellExtractor(const QString& simWellName, + const QString& caseUserDescription, + const RigWellPath* wellPathGeom, + const RigEclipseCaseData* eclCaseData); + RigEclipseWellLogExtractor* findOrCreateExtractor(RimWellPath* wellPath, RimEclipseCase* eclCase); RigGeoMechWellLogExtractor* findOrCreateExtractor(RimWellPath* wellPath, RimGeoMechCase* eclCase); From f40cf3a9b740751e5755e582f27e3194965a6259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Apr 2017 15:49:07 +0200 Subject: [PATCH 030/157] #1427 Apply specific changes from pre-proto regarding selection in 3D To be used for transporting branch index from 3D context menu operation to feature. --- .../RivSimWellPipeSourceInfo.cpp | 8 +++ .../RivSimWellPipeSourceInfo.h | 2 + .../UserInterface/RiuSelectionManager.cpp | 46 +++++++++++++ .../UserInterface/RiuSelectionManager.h | 69 ++++++++++++++++++- 4 files changed, 123 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivSimWellPipeSourceInfo.cpp b/ApplicationCode/ModelVisualization/RivSimWellPipeSourceInfo.cpp index 63c3772722..8d77bf321d 100644 --- a/ApplicationCode/ModelVisualization/RivSimWellPipeSourceInfo.cpp +++ b/ApplicationCode/ModelVisualization/RivSimWellPipeSourceInfo.cpp @@ -38,3 +38,11 @@ RimEclipseWell* RivSimWellPipeSourceInfo::well() const { return m_eclipseWell.p(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RivSimWellPipeSourceInfo::branchIndex() const +{ + return m_branchIndex; +} diff --git a/ApplicationCode/ModelVisualization/RivSimWellPipeSourceInfo.h b/ApplicationCode/ModelVisualization/RivSimWellPipeSourceInfo.h index 5bf006482f..e765d59728 100644 --- a/ApplicationCode/ModelVisualization/RivSimWellPipeSourceInfo.h +++ b/ApplicationCode/ModelVisualization/RivSimWellPipeSourceInfo.h @@ -32,6 +32,8 @@ public: RimEclipseWell* well() const; + size_t branchIndex() const; + private: caf::PdmPointer m_eclipseWell; size_t m_branchIndex; diff --git a/ApplicationCode/UserInterface/RiuSelectionManager.cpp b/ApplicationCode/UserInterface/RiuSelectionManager.cpp index cab10fbd9f..71a40c0eac 100644 --- a/ApplicationCode/UserInterface/RiuSelectionManager.cpp +++ b/ApplicationCode/UserInterface/RiuSelectionManager.cpp @@ -21,6 +21,10 @@ #include "RimEclipseView.h" #include "RimGeoMechView.h" +#include "RimWellPath.h" + +#include "RivSimWellPipeSourceInfo.h" +#include "RivWellPathSourceInfo.h" #include "RiuSelectionChangedHandler.h" @@ -63,6 +67,24 @@ void RiuSelectionManager::selectedItems(std::vector& items, i items = s; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuSelectionItem* RiuSelectionManager::selectedItem(int role /*= RUI_APPLICATION_GLOBAL*/) const +{ + const std::vector& s = m_selection[role]; + + if (s.size() == 1) + { + if (s[0]) + { + return s[0]; + } + } + + return nullptr; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -181,3 +203,27 @@ RiuGeoMechSelectionItem::RiuGeoMechSelectionItem(RimGeoMechView* view, { } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuWellPathSelectionItem::RiuWellPathSelectionItem(const RivWellPathSourceInfo* wellPathSourceInfo, + const cvf::Vec3d& pipeCenterLineIntersectionInDomainCoords, + double measuredDepth) + : m_pipeCenterlineIntersectionInDomainCoords(pipeCenterLineIntersectionInDomainCoords), + m_measuredDepth(measuredDepth) +{ + m_wellpath = wellPathSourceInfo->wellPath(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuSimWellSelectionItem::RiuSimWellSelectionItem(RimEclipseWell* simwell, + cvf::Vec3d m_domainCoord, + size_t m_branchIndex) + : m_simWell(simwell), + m_domainCoord(m_domainCoord), + m_branchIndex(m_branchIndex) +{ +} \ No newline at end of file diff --git a/ApplicationCode/UserInterface/RiuSelectionManager.h b/ApplicationCode/UserInterface/RiuSelectionManager.h index f3360bf4fd..000604521f 100644 --- a/ApplicationCode/UserInterface/RiuSelectionManager.h +++ b/ApplicationCode/UserInterface/RiuSelectionManager.h @@ -28,11 +28,17 @@ #include #include #include +#include "RimEclipseWell.h" +// #include "RivWellPathSourceInfo.h" +// #include "RivWellPipeSourceInfo.h" class RimEclipseView; class RiuSelectionChangedHandler; class RiuSelectionItem; class RimGeoMechView; +class RimWellPath; +class RivWellPathSourceInfo; +class RivSimWellPipeSourceInfo; //================================================================================================== // @@ -54,7 +60,13 @@ public: // Returns selected items // Selection manager owns the selection items void selectedItems(std::vector& items, int role = RUI_APPLICATION_GLOBAL) const; - + + // Returns selected items + // Selection manager owns the selection items + RiuSelectionItem* selectedItem(int role = RUI_APPLICATION_GLOBAL) const; + // PdmUiItem* selectedItem(int role = SelectionManager::APPLICATION_GLOBAL); + + // Append item to selected items // SelectionManager takes ownership of the item void appendItemToSelection(RiuSelectionItem* item, int role = RUI_APPLICATION_GLOBAL); @@ -93,7 +105,9 @@ public: enum RiuSelectionType { ECLIPSE_SELECTION_OBJECT, - GEOMECH_SELECTION_OBJECT + GEOMECH_SELECTION_OBJECT, + WELLPATH_SELECTION_OBJECT, + SIMWELL_SELECTION_OBJECT }; public: @@ -173,3 +187,54 @@ public: cvf::Vec3d m_localIntersectionPoint; }; + +//================================================================================================== +// +// +// +//================================================================================================== +class RiuWellPathSelectionItem : public RiuSelectionItem +{ +public: + explicit RiuWellPathSelectionItem(const RivWellPathSourceInfo* wellPathSourceInfo, + const cvf::Vec3d& currentPickPositionInDomainCoords, + double measuredDepth); + + virtual ~RiuWellPathSelectionItem() {}; + + virtual RiuSelectionType type() const + { + return WELLPATH_SELECTION_OBJECT; + } + +public: + RimWellPath* m_wellpath; + cvf::Vec3d m_pipeCenterlineIntersectionInDomainCoords; + double m_measuredDepth; +}; + + + +//================================================================================================== +// +// +// +//================================================================================================== +class RiuSimWellSelectionItem : public RiuSelectionItem +{ +public: + explicit RiuSimWellSelectionItem(RimEclipseWell* simwell, cvf::Vec3d domainCoord, size_t branchIndex); + + + virtual ~RiuSimWellSelectionItem() {}; + + virtual RiuSelectionType type() const + { + return SIMWELL_SELECTION_OBJECT; + } + +public: + RimEclipseWell* m_simWell; + cvf::Vec3d m_domainCoord; + size_t m_branchIndex; +}; From 6f07a3698b2be739c05496f5faa159ceb9a62c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 25 Apr 2017 16:12:22 +0200 Subject: [PATCH 031/157] #1427 Enable the new Well Log Curve command for Simulation Wells --- .../RicNewWellLogCurveExtractionFeature.cpp | 41 +++++++++++++++---- .../RicNewWellLogCurveExtractionFeature.h | 6 ++- .../RicNewWellLogPlotFeature.cpp | 2 +- .../RicNewWellLogPlotTrackFeature.cpp | 2 +- .../RimWellLogExtractionCurve.cpp | 19 ++++++++- .../RimWellLogExtractionCurve.h | 2 + .../UserInterface/RiuViewerCommands.cpp | 15 +++++-- 7 files changed, 70 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.cpp index 6332124856..1ad9176a8f 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.cpp @@ -41,6 +41,8 @@ #include #include +#include "RimEclipseWell.h" +#include "RiuSelectionManager.h" CAF_CMD_SOURCE_INIT(RicNewWellLogCurveExtractionFeature, "RicNewWellLogCurveExtractionFeature"); @@ -51,8 +53,8 @@ CAF_CMD_SOURCE_INIT(RicNewWellLogCurveExtractionFeature, "RicNewWellLogCurveExtr bool RicNewWellLogCurveExtractionFeature::isCommandEnabled() { if (RicWellLogPlotCurveFeatureImpl::parentWellAllocationPlot()) return false; - - return (selectedWellLogPlotTrack() != NULL || selectedWellPath() != NULL) && caseAvailable(); + int branchIndex; + return (selectedWellLogPlotTrack() != nullptr || selectedWellPath() != nullptr || selectedSimulationWell(&branchIndex) != nullptr) && caseAvailable(); } //-------------------------------------------------------------------------------------------------- @@ -65,15 +67,17 @@ void RicNewWellLogCurveExtractionFeature::onActionTriggered(bool isChecked) RimWellLogTrack* wellLogPlotTrack = selectedWellLogPlotTrack(); if (wellLogPlotTrack) { - addCurve(wellLogPlotTrack, NULL, NULL); + addCurve(wellLogPlotTrack, NULL, NULL, nullptr, -1); } else { RimWellPath* wellPath = selectedWellPath(); - if (wellPath) + int branchIndex = -1; + RimEclipseWell* simWell = selectedSimulationWell(&branchIndex); + if (wellPath || simWell) { RimWellLogTrack* wellLogPlotTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack(); - RimWellLogExtractionCurve* plotCurve = addCurve(wellLogPlotTrack, RiaApplication::instance()->activeReservoirView(), wellPath); + RimWellLogExtractionCurve* plotCurve = addCurve(wellLogPlotTrack, RiaApplication::instance()->activeReservoirView(), wellPath, simWell, branchIndex); plotCurve->loadDataAndUpdate(); @@ -118,6 +122,27 @@ RimWellPath* RicNewWellLogCurveExtractionFeature::selectedWellPath() const return selection.size() > 0 ? selection[0] : NULL; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseWell* RicNewWellLogCurveExtractionFeature::selectedSimulationWell(int * branchIndex) const +{ + RiuSelectionItem* selItem = RiuSelectionManager::instance()->selectedItem(RiuSelectionManager::RUI_TEMPORARY); + RiuSimWellSelectionItem* simWellSelItem = dynamic_cast(selItem); + if (simWellSelItem) + { + (*branchIndex) = static_cast(simWellSelItem->m_branchIndex); + return simWellSelItem->m_simWell; + } + else + { + std::vector selection; + caf::SelectionManager::instance()->objectsByType(&selection); + (*branchIndex) = 0; + return selection.size() > 0 ? selection[0] : NULL; + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -132,14 +157,16 @@ bool RicNewWellLogCurveExtractionFeature::caseAvailable() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellLogExtractionCurve* RicNewWellLogCurveExtractionFeature::addCurve(RimWellLogTrack* plotTrack, RimView* view, RimWellPath* wellPath) +RimWellLogExtractionCurve* RicNewWellLogCurveExtractionFeature::addCurve(RimWellLogTrack* plotTrack, RimView* view, RimWellPath* wellPath, const RimEclipseWell* simWell, int branchIndex) { CVF_ASSERT(plotTrack); RimWellLogExtractionCurve* curve = new RimWellLogExtractionCurve(); cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable(plotTrack->curveCount()); curve->setColor(curveColor); - curve->setWellPath(wellPath); + if (wellPath) curve->setWellPath(wellPath); + if (simWell) curve->setFromSimulationWellName(simWell->name(), branchIndex); + curve->setPropertiesFromView(view); plotTrack->addCurve(curve); diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.h b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.h index 97d33a9b70..223d3ba079 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.h +++ b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogCurveExtractionFeature.h @@ -21,10 +21,11 @@ #include "cafCmdFeature.h" +class RimEclipseWell; +class RimView; class RimWellLogExtractionCurve; class RimWellLogTrack; class RimWellPath; -class RimView; //================================================================================================== /// @@ -34,7 +35,7 @@ class RicNewWellLogCurveExtractionFeature : public caf::CmdFeature CAF_CMD_HEADER_INIT; public: - static RimWellLogExtractionCurve* addCurve(RimWellLogTrack* plotTrack, RimView* view, RimWellPath* wellPath); + static RimWellLogExtractionCurve* addCurve(RimWellLogTrack* plotTrack, RimView* view, RimWellPath* wellPath, const RimEclipseWell* simWell, int branchIndex); protected: @@ -46,5 +47,6 @@ protected: private: RimWellLogTrack* selectedWellLogPlotTrack() const; RimWellPath* selectedWellPath() const; + RimEclipseWell* selectedSimulationWell(int * branchIndex) const; bool caseAvailable() const; }; diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeature.cpp index a743d82381..55cef779f9 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeature.cpp @@ -51,7 +51,7 @@ bool RicNewWellLogPlotFeature::isCommandEnabled() void RicNewWellLogPlotFeature::onActionTriggered(bool isChecked) { RimWellLogTrack* plotTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack(); - RicNewWellLogCurveExtractionFeature::addCurve(plotTrack, NULL, NULL); + RicNewWellLogCurveExtractionFeature::addCurve(plotTrack, NULL, NULL, nullptr, -1); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp index 47bf135c86..a487cf97de 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp @@ -57,7 +57,7 @@ void RicNewWellLogPlotTrackFeature::onActionTriggered(bool isChecked) plotTrack->setDescription(QString("Track %1").arg(wellLogPlot->trackCount())); wellLogPlot->updateConnectedEditors(); - RicNewWellLogCurveExtractionFeature::addCurve(plotTrack, NULL, NULL); + RicNewWellLogCurveExtractionFeature::addCurve(plotTrack, NULL, NULL, nullptr, -1); } } diff --git a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp index 55c0ad4896..ab09094d4c 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp @@ -59,6 +59,7 @@ #include "cafUtils.h" #include +#include "RimEclipseWell.h" //================================================================================================== /// @@ -147,6 +148,18 @@ RimWellPath* RimWellLogExtractionCurve::wellPath() const return m_wellPath; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogExtractionCurve::setFromSimulationWellName(const QString& simWellName, int branchIndex) +{ + m_trajectoryType = SIMULATION_WELL; + m_simWellName = simWellName; + m_branchIndex = branchIndex; + + clearGeneratedSimWellPaths(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -675,8 +688,10 @@ QString RimWellLogExtractionCurve::createCurveAutoName() if (m_addWellNameToCurveName ) { generatedCurveName += wellName(); - - // Todo: Branch + if (m_trajectoryType == SIMULATION_WELL && m_generatedSimulationWellPathBranches.size() > 1) + { + generatedCurveName += " Br" + QString::number(m_branchIndex + 1); + } } if (m_addCaseNameToCurveName && m_case()) diff --git a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h index f314989fc4..0c05ad8545 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h +++ b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h @@ -48,6 +48,8 @@ public: void setWellPath(RimWellPath* wellPath); RimWellPath* wellPath() const; + void setFromSimulationWellName(const QString& simWellName, int branchIndex); + void setCase(RimCase* rimCase); RimCase* rimCase() const; diff --git a/ApplicationCode/UserInterface/RiuViewerCommands.cpp b/ApplicationCode/UserInterface/RiuViewerCommands.cpp index 39c48f0a22..f6dc88ae91 100644 --- a/ApplicationCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationCode/UserInterface/RiuViewerCommands.cpp @@ -294,8 +294,9 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event) { caf::SelectionManager::instance()->setSelectedItem(wellPath); - commandIds << "RicNewWellLogFileCurveFeature"; commandIds << "RicNewWellLogCurveExtractionFeature"; + commandIds << "RicNewWellLogFileCurveFeature"; + commandIds << "Separator"; commandIds << "RicNewWellPathIntersectionFeature"; } } @@ -308,10 +309,16 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event) { caf::SelectionManager::instance()->setSelectedItem(well); - commandIds << "RicNewSimWellIntersectionFeature"; + commandIds << "RicNewWellLogCurveExtractionFeature"; commandIds << "RicShowWellAllocationPlotFeature"; - commandIds << "RicShowContributingWellsFeature"; commandIds << "RicPlotProductionRateFeature"; + commandIds << "Separator"; + commandIds << "RicShowContributingWellsFeature"; + commandIds << "Separator"; + commandIds << "RicNewSimWellIntersectionFeature"; + + RiuSelectionItem* selItem = new RiuSimWellSelectionItem(eclipseWellSourceInfo->well(), m_currentPickPositionInDomainCoords, eclipseWellSourceInfo->branchIndex()); + RiuSelectionManager::instance()->setSelectedItem(selItem, RiuSelectionManager::RUI_TEMPORARY); } } @@ -333,7 +340,7 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event) RimContextCommandBuilder::appendCommandsToMenu(commandIds, &menu); - if (menu.actions().size() > 0) + if (!menu.isEmpty()) { menu.exec(event->globalPos()); } From cf18f5324f311c314045d940c248c5b6f99e3ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 26 Apr 2017 09:39:17 +0200 Subject: [PATCH 032/157] #165 Keep original days since simulation start --- .../RifEclipseOutputFileTools.cpp | 15 ++++------ .../FileInterface/RifEclipseOutputFileTools.h | 2 +- .../RifEclipseRestartDataAccess.h | 2 +- .../RifEclipseRestartFilesetAccess.cpp | 10 +++++-- .../RifEclipseRestartFilesetAccess.h | 3 +- .../RifEclipseUnifiedRestartFileAccess.cpp | 14 ++++----- .../RifEclipseUnifiedRestartFileAccess.h | 2 +- .../FileInterface/RifReaderEclipseOutput.cpp | 19 ++++++++---- .../FileInterface/RifReaderEclipseOutput.h | 1 + .../FileInterface/RifReaderMockModel.cpp | 10 +++++-- .../RimEclipseStatisticsCaseEvaluator.cpp | 3 +- .../RimIdenticalGridCaseGroup.cpp | 3 +- .../RimReservoirCellResultsStorage.cpp | 4 ++- .../RimReservoirCellResultsStorage.h | 1 + .../RigCaseCellResultsData.cpp | 29 ++++++++++++++++++- .../RigCaseCellResultsData.h | 5 +++- 16 files changed, 86 insertions(+), 37 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp index 5754c3edd8..d2dab4a787 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp @@ -115,7 +115,7 @@ void getDayMonthYear(const ecl_kw_type* intehead_kw, int* day, int* month, int* //-------------------------------------------------------------------------------------------------- /// Get list of time step texts (dates) //-------------------------------------------------------------------------------------------------- -void RifEclipseOutputFileTools::timeSteps(ecl_file_type* ecl_file, std::vector* timeSteps) +void RifEclipseOutputFileTools::timeSteps(ecl_file_type* ecl_file, std::vector* timeSteps, std::vector* daysSinceSimulationStart) { if (!ecl_file) return; @@ -127,7 +127,7 @@ void RifEclipseOutputFileTools::timeSteps(ecl_file_type* ecl_file, std::vector dayFractions(numINTEHEAD, 0.0); // Init fraction to zero + std::vector dayValues(numINTEHEAD, 0.0); // Init fraction to zero // Read out fraction of day if number of keywords are identical if (numINTEHEAD == numDOUBHEAD) @@ -137,12 +137,7 @@ void RifEclipseOutputFileTools::timeSteps(ecl_file_type* ecl_file, std::vector(dayFraction * 24.0 * 60.0 * 60.0 * 1000.0); int seconds = milliseconds % 1000; milliseconds -= seconds * 1000; @@ -172,6 +168,7 @@ void RifEclipseOutputFileTools::timeSteps(ecl_file_type* ecl_file, std::vectorbegin(), timeSteps->end(), reportDateTime) == timeSteps->end()) { timeSteps->push_back(reportDateTime); + daysSinceSimulationStart->push_back(dayValue); } } } diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h index 53d13376b2..a9f6a87aaf 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h @@ -51,7 +51,7 @@ public: static bool keywordData(ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector* values); static bool keywordData(ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector* values); - static void timeSteps(ecl_file_type* ecl_file, std::vector* timeSteps); + static void timeSteps(ecl_file_type* ecl_file, std::vector* timeSteps, std::vector* daysSinceSimulationStart); static bool findSiblingFilesWithSameBaseName(const QString& fileName, QStringList* fileSet); diff --git a/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h b/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h index 92024f378b..6884afe0bf 100644 --- a/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h +++ b/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h @@ -98,7 +98,7 @@ public: virtual void setTimeSteps(const std::vector& timeSteps) {}; virtual size_t timeStepCount() = 0; - virtual std::vector timeSteps() = 0; + virtual void timeSteps(std::vector* timeSteps, std::vector* daysSinceSimulationStart) = 0; virtual std::vector reportNumbers() = 0; virtual void resultNames(QStringList* resultNames, std::vector* resultDataItemCounts) = 0; diff --git a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp index 418dce66d9..cc4b1fceb8 100644 --- a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp +++ b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp @@ -119,7 +119,7 @@ size_t RifEclipseRestartFilesetAccess::timeStepCount() //-------------------------------------------------------------------------------------------------- /// Get the time steps //-------------------------------------------------------------------------------------------------- -std::vector RifEclipseRestartFilesetAccess::timeSteps() +void RifEclipseRestartFilesetAccess::timeSteps(std::vector* timeSteps, std::vector* daysSinceSimulationStart) { if (m_timeSteps.size() == 0) { @@ -128,24 +128,28 @@ std::vector RifEclipseRestartFilesetAccess::timeSteps() for (i = 0; i < numSteps; i++) { std::vector stepTime; + std::vector stepDays; openTimeStep(i); - RifEclipseOutputFileTools::timeSteps(m_ecl_files[i], &stepTime); + RifEclipseOutputFileTools::timeSteps(m_ecl_files[i], &stepTime, &stepDays); if (stepTime.size() == 1) { m_timeSteps.push_back(stepTime[0]); + m_daysSinceSimulationStart.push_back(stepDays[0]); } else { m_timeSteps.push_back(QDateTime()); + m_daysSinceSimulationStart.push_back(0.0); } } } - return m_timeSteps; + *timeSteps = m_timeSteps; + *daysSinceSimulationStart = m_daysSinceSimulationStart; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h index 494d9378cd..9bb4ac7749 100644 --- a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h +++ b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h @@ -43,7 +43,7 @@ public: void setTimeSteps(const std::vector& timeSteps); size_t timeStepCount(); - std::vector timeSteps(); + void timeSteps(std::vector* timeSteps, std::vector* daysSinceSimulationStart) override; std::vector reportNumbers(); void resultNames(QStringList* resultNames, std::vector* resultDataItemCounts); @@ -58,6 +58,7 @@ private: private: QStringList m_fileNames; std::vector m_timeSteps; + std::vector m_daysSinceSimulationStart; std::vector< ecl_file_type* > m_ecl_files; }; diff --git a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp index 3b486c1351..f5006c4b0f 100644 --- a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp +++ b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp @@ -85,23 +85,23 @@ size_t RifEclipseUnifiedRestartFileAccess::timeStepCount() { return 0; } + std::vector timeSteps; + std::vector daysSinceSimulationStart; - return timeSteps().size(); + this->timeSteps(&timeSteps, &daysSinceSimulationStart); + + return timeSteps.size(); } //-------------------------------------------------------------------------------------------------- /// Get the time steps //-------------------------------------------------------------------------------------------------- -std::vector RifEclipseUnifiedRestartFileAccess::timeSteps() +void RifEclipseUnifiedRestartFileAccess::timeSteps(std::vector* timeSteps, std::vector* daysSinceSimulationStart) { - std::vector timeSteps; - if (openFile()) { - RifEclipseOutputFileTools::timeSteps(m_ecl_file, &timeSteps); + RifEclipseOutputFileTools::timeSteps(m_ecl_file, timeSteps, daysSinceSimulationStart); } - - return timeSteps; } diff --git a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h index 14a0e1d14b..2344ed3266 100644 --- a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h +++ b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h @@ -46,7 +46,7 @@ public: void close(); size_t timeStepCount(); - std::vector timeSteps(); + void timeSteps(std::vector* timeSteps, std::vector* daysSinceSimulationStart) override; std::vector reportNumbers(); void resultNames(QStringList* resultNames, std::vector* resultDataItemCounts); diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index 4bc4cf0ec0..235acb9971 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -657,7 +657,7 @@ void RifReaderEclipseOutput::buildMetaData() progInfo.incrementProgress(); // Get time steps - m_timeSteps = m_dynamicResultsAccess->timeSteps(); + m_dynamicResultsAccess->timeSteps(&m_timeSteps, &m_daysSinceSimulationStart); std::vector reportNumbers = m_dynamicResultsAccess->reportNumbers(); QStringList resultNames; @@ -673,7 +673,7 @@ void RifReaderEclipseOutput::buildMetaData() for (int i = 0; i < matrixResultNames.size(); ++i) { size_t resIndex = matrixModelResults->addEmptyScalarResult(RimDefines::DYNAMIC_NATIVE, matrixResultNames[i], false); - matrixModelResults->setTimeStepDates(resIndex, m_timeSteps, reportNumbers); + matrixModelResults->setTimeStepDates(resIndex, m_timeSteps, m_daysSinceSimulationStart, reportNumbers); } } @@ -686,7 +686,7 @@ void RifReaderEclipseOutput::buildMetaData() for (int i = 0; i < fractureResultNames.size(); ++i) { size_t resIndex = fractureModelResults->addEmptyScalarResult(RimDefines::DYNAMIC_NATIVE, fractureResultNames[i], false); - fractureModelResults->setTimeStepDates(resIndex, m_timeSteps, reportNumbers); + fractureModelResults->setTimeStepDates(resIndex, m_timeSteps, m_daysSinceSimulationStart, reportNumbers); } } @@ -723,12 +723,17 @@ void RifReaderEclipseOutput::buildMetaData() RifEclipseOutputFileTools::findKeywordsAndItemCount(filesUsedToFindAvailableKeywords, &resultNames, &resultNamesDataItemCounts); std::vector staticDate; + std::vector staticDay; std::vector staticReportNumber; { if ( m_timeSteps.size() > 0 ) { staticDate.push_back(m_timeSteps.front()); } + if (m_daysSinceSimulationStart.size() > 0) + { + staticDay.push_back(m_daysSinceSimulationStart.front()); + } std::vector reportNumbers; if (m_dynamicResultsAccess.notNull()) @@ -754,7 +759,7 @@ void RifReaderEclipseOutput::buildMetaData() for (int i = 0; i < matrixResultNames.size(); ++i) { size_t resIndex = matrixModelResults->addEmptyScalarResult(RimDefines::STATIC_NATIVE, matrixResultNames[i], false); - matrixModelResults->setTimeStepDates(resIndex, staticDate, staticReportNumber); + matrixModelResults->setTimeStepDates(resIndex, staticDate, staticDay, staticReportNumber); } } @@ -769,7 +774,7 @@ void RifReaderEclipseOutput::buildMetaData() for (int i = 0; i < fractureResultNames.size(); ++i) { size_t resIndex = fractureModelResults->addEmptyScalarResult(RimDefines::STATIC_NATIVE, fractureResultNames[i], false); - fractureModelResults->setTimeStepDates(resIndex, staticDate, staticReportNumber); + fractureModelResults->setTimeStepDates(resIndex, staticDate, staticDay, staticReportNumber); } } } @@ -1124,7 +1129,9 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid, boo m_dynamicResultsAccess->readWellData(ert_well_info, importCompleteMswData); - std::vector timeSteps = m_dynamicResultsAccess->timeSteps(); + std::vector daysSinceSimulationStart; + std::vector timeSteps; + m_dynamicResultsAccess->timeSteps(&timeSteps, &daysSinceSimulationStart); std::vector reportNumbers = m_dynamicResultsAccess->reportNumbers(); bool sameCount = false; diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h index c4b31d6c9e..fa74becd6b 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h @@ -93,6 +93,7 @@ private: RigEclipseCaseData* m_eclipseCase; std::vector m_timeSteps; + std::vector m_daysSinceSimulationStart; ecl_file_type* m_ecl_init_file; // File access to static results cvf::ref m_dynamicResultsAccess; // File access to dynamic results diff --git a/ApplicationCode/FileInterface/RifReaderMockModel.cpp b/ApplicationCode/FileInterface/RifReaderMockModel.cpp index 0872e9b07b..316b536d07 100644 --- a/ApplicationCode/FileInterface/RifReaderMockModel.cpp +++ b/ApplicationCode/FileInterface/RifReaderMockModel.cpp @@ -38,24 +38,28 @@ bool RifReaderMockModel::open(const QString& fileName, RigEclipseCaseData* eclip std::vector dates; + std::vector days; std::vector repNumbers; for (int i = 0; i < static_cast(m_reservoirBuilder.timeStepCount()); i++) { dates.push_back(QDateTime(QDate(2012+i, 6, 1))); + days.push_back(i); repNumbers.push_back(i); } for (size_t i = 0; i < m_reservoirBuilder.resultCount(); i++) { size_t resIdx = cellResults->addEmptyScalarResult(RimDefines::DYNAMIC_NATIVE, QString("Dynamic_Result_%1").arg(i), false); - cellResults->setTimeStepDates(resIdx, dates, repNumbers); + cellResults->setTimeStepDates(resIdx, dates, days, repNumbers); } if (m_reservoirBuilder.timeStepCount() == 0) return true; std::vector staticDates; staticDates.push_back(dates[0]); + std::vector staticDays; + staticDays.push_back(days[0]); std::vector staticRepNumbers; staticRepNumbers.push_back(0); @@ -68,7 +72,7 @@ bool RifReaderMockModel::open(const QString& fileName, RigEclipseCaseData* eclip if (i > 1) resIndex = i; size_t resIdx = cellResults->addEmptyScalarResult(RimDefines::STATIC_NATIVE, QString("Static_Result_%1%2").arg(resIndex).arg(varEnd), false); - cellResults->setTimeStepDates(resIdx, staticDates, staticRepNumbers); + cellResults->setTimeStepDates(resIdx, staticDates, staticDays, staticRepNumbers); } @@ -77,7 +81,7 @@ bool RifReaderMockModel::open(const QString& fileName, RigEclipseCaseData* eclip size_t resIdx; \ QString resultName(Name); \ resIdx = cellResults->addEmptyScalarResult(RimDefines::INPUT_PROPERTY, resultName, false); \ - cellResults->setTimeStepDates(resIdx, staticDates, staticRepNumbers); \ + cellResults->setTimeStepDates(resIdx, staticDates, staticDays, staticRepNumbers); \ cellResults->cellScalarResults(resIdx).resize(1); \ std::vector& values = cellResults->cellScalarResults(resIdx)[0]; \ this->inputProperty(resultName, &values); \ diff --git a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.cpp index d3e25f35f2..5234ae4313 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseStatisticsCaseEvaluator.cpp @@ -44,12 +44,13 @@ void RimEclipseStatisticsCaseEvaluator::addNamedResult(RigCaseCellResultsData* d CVF_ASSERT(m_sourceCases.size() > 0); std::vector sourceTimeStepDates = m_sourceCases[0]->results(RifReaderInterface::MATRIX_RESULTS)->cellResults()->timeStepDates(0); + std::vector sourceDaysSinceSimulationStart = m_sourceCases[0]->results(RifReaderInterface::MATRIX_RESULTS)->cellResults()->daysSinceSimulationStart(0); std::vector sourceReportStepNumbers = m_sourceCases[0]->results(RifReaderInterface::MATRIX_RESULTS)->cellResults()->reportStepNumbers(0); size_t destinationScalarResultIndex = destinationCellResults->addEmptyScalarResult(resultType, resultName, true); CVF_ASSERT(destinationScalarResultIndex != cvf::UNDEFINED_SIZE_T); - destinationCellResults->setTimeStepDates(destinationScalarResultIndex, sourceTimeStepDates, sourceReportStepNumbers); + destinationCellResults->setTimeStepDates(destinationScalarResultIndex, sourceTimeStepDates, sourceDaysSinceSimulationStart, sourceReportStepNumbers); std::vector< std::vector >& dataValues = destinationCellResults->cellScalarResults(destinationScalarResultIndex); dataValues.resize(sourceTimeStepDates.size()); diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 58823e4b22..c68751c22d 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -239,6 +239,7 @@ void RimIdenticalGridCaseGroup::loadMainCaseAndActiveCellInfo() RifReaderInterface::PorosityModelResultType poroModel = RifReaderInterface::MATRIX_RESULTS; std::vector timeStepDates = rigCaseData->results(poroModel)->timeStepDates(0); + std::vector daysSinceSimulationStart = rigCaseData->results(poroModel)->daysSinceSimulationStart(0); std::vector reportStepNumbers = rigCaseData->results(poroModel)->reportStepNumbers(0); const std::vector resultInfos = rigCaseData->results(poroModel)->infoForEachResultIndex(); @@ -264,7 +265,7 @@ void RimIdenticalGridCaseGroup::loadMainCaseAndActiveCellInfo() if (mustBeCalculated) cellResultsStorage->cellResults()->setMustBeCalculated(scalarResultIndex); - cellResultsStorage->cellResults()->setTimeStepDates(scalarResultIndex, timeStepDates, reportStepNumbers); + cellResultsStorage->cellResults()->setTimeStepDates(scalarResultIndex, timeStepDates, daysSinceSimulationStart, reportStepNumbers); std::vector< std::vector >& dataValues = cellResultsStorage->cellResults()->cellScalarResults(scalarResultIndex); dataValues.resize(timeStepDates.size()); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 055ae3e4a5..04a502ffe2 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -137,6 +137,7 @@ void RimReservoirCellResultsStorage::setupBeforeSave() cacheEntry->m_resultType = resInfo[rIdx].m_resultType; cacheEntry->m_resultName = resInfo[rIdx].m_resultName; cacheEntry->m_timeStepDates = resInfo[rIdx].m_timeStepDates; + cacheEntry->m_daysSinceSimulationStart = resInfo[rIdx].m_daysSinceSimulationStart; // Take note of the file position for fast lookup later cacheEntry->m_filePosition = cacheFile.pos(); @@ -1436,7 +1437,7 @@ void RimReservoirCellResultsStorage::setCellResults(RigCaseCellResultsData* cell RimReservoirCellResultsStorageEntryInfo* resInfo = m_resultCacheMetaData[rIdx]; size_t resultIndex = m_cellResults->addEmptyScalarResult(resInfo->m_resultType(), resInfo->m_resultName(), true); - m_cellResults->setTimeStepDates(resultIndex, resInfo->m_timeStepDates(), std::vector()); // Hack: Using no report step numbers. Not really used except for Flow Diagnostics... + m_cellResults->setTimeStepDates(resultIndex, resInfo->m_timeStepDates(), resInfo->m_daysSinceSimulationStart(), std::vector()); // Hack: Using no report step numbers. Not really used except for Flow Diagnostics... progress.setProgressDescription(resInfo->m_resultName); @@ -1556,6 +1557,7 @@ RimReservoirCellResultsStorageEntryInfo::RimReservoirCellResultsStorageEntryInfo CAF_PDM_InitField(&m_resultType, "ResultType", caf::AppEnum(RimDefines::REMOVED), "ResultType", "", "" ,""); CAF_PDM_InitField(&m_resultName, "ResultName", QString(), "ResultName", "", "" ,""); CAF_PDM_InitFieldNoDefault(&m_timeStepDates, "TimeSteps", "TimeSteps", "", "" ,""); + CAF_PDM_InitFieldNoDefault(&m_daysSinceSimulationStart, "DaysSinceSimulationStart", "DaysSinceSimulationStart", "", "", ""); CAF_PDM_InitField(&m_filePosition, "FilePositionDataStart", qint64(-1), "FilePositionDataStart", "", "" ,""); } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h index 1acdcfd157..9793d7d67f 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h @@ -101,6 +101,7 @@ public: caf::PdmField > m_resultType; caf::PdmField m_resultName; caf::PdmField< std::vector > m_timeStepDates; + caf::PdmField< std::vector > m_daysSinceSimulationStart; caf::PdmField m_filePosition; }; diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index eddd5f422d..60ece82835 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -420,6 +420,32 @@ std::vector RigCaseCellResultsData::timeStepDates() const return timeStepDates(scalarResWithMostTimeSteps); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigCaseCellResultsData::daysSinceSimulationStart() const +{ + size_t scalarResWithMostTimeSteps = cvf::UNDEFINED_SIZE_T; + maxTimeStepCount(&scalarResWithMostTimeSteps); + + return daysSinceSimulationStart(scalarResWithMostTimeSteps); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigCaseCellResultsData::daysSinceSimulationStart(size_t scalarResultIndex) const +{ + if (scalarResultIndex < m_resultInfos.size()) + { + return m_resultInfos[scalarResultIndex].m_daysSinceSimulationStart; + } + else + { + return std::vector(); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -446,11 +472,12 @@ std::vector RigCaseCellResultsData::reportStepNumbers(size_t scalarResultIn //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCaseCellResultsData::setTimeStepDates(size_t scalarResultIndex, const std::vector& dates, const std::vector& reportStepNumbers) +void RigCaseCellResultsData::setTimeStepDates(size_t scalarResultIndex, const std::vector& dates, const std::vector& daysSinceSimulationStart, const std::vector& reportStepNumbers) { CVF_ASSERT(scalarResultIndex < m_resultInfos.size() ); m_resultInfos[scalarResultIndex].m_timeStepDates = dates; + m_resultInfos[scalarResultIndex].m_daysSinceSimulationStart = daysSinceSimulationStart; m_resultInfos[scalarResultIndex].m_timeStepReportNumbers = reportStepNumbers; std::vector< std::vector >& dataValues = this->cellScalarResults(scalarResultIndex); diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h index 89839fc59d..2723669748 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h @@ -76,9 +76,11 @@ public: std::vector timeStepDates() const; QDateTime timeStepDate(size_t scalarResultIndex, size_t timeStepIndex) const; std::vector timeStepDates(size_t scalarResultIndex) const; + std::vector daysSinceSimulationStart() const; + std::vector daysSinceSimulationStart(size_t scalarResultIndex) const; int reportStepNumber(size_t scalarResultIndex, size_t timeStepIndex) const; std::vector reportStepNumbers(size_t scalarResultIndex) const; - void setTimeStepDates(size_t scalarResultIndex, const std::vector& dates, const std::vector& reportStepNumbers); + void setTimeStepDates(size_t scalarResultIndex, const std::vector& dates, const std::vector& daysSinceSimulationStart, const std::vector& reportStepNumbers); // Find or create a slot for the results @@ -119,6 +121,7 @@ public: size_t m_gridScalarResultIndex; std::vector m_timeStepDates; std::vector m_timeStepReportNumbers; + std::vector m_daysSinceSimulationStart; }; const std::vector& infoForEachResultIndex() { return m_resultInfos;} From 2c8358e9e93bdeca6b169ad87780bedd49e75b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 26 Apr 2017 09:40:08 +0200 Subject: [PATCH 033/157] #165 Return original days since simulation start from riGetTimeStepDays --- .../SocketInterface/RiaCaseInfoCommands.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp index 207037dd8e..3d998de20c 100644 --- a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp @@ -518,26 +518,17 @@ public: return true; } - std::vector timeStepDates = rimCase->eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS)->timeStepDates(scalarIndexWithMaxTimeStepCount); + std::vector daysSinceSimulationStart = rimCase->eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS)->daysSinceSimulationStart(scalarIndexWithMaxTimeStepCount); - quint64 timeStepCount = timeStepDates.size(); + quint64 timeStepCount = daysSinceSimulationStart.size(); quint64 byteCount = sizeof(quint64) + timeStepCount * sizeof(qint32); socketStream << byteCount; socketStream << timeStepCount; - if (timeStepCount > 0) + for (double day : daysSinceSimulationStart) { - double secondsInADay = 24 * 60 * 60; - - for (size_t i = 0; i < timeStepCount; i++) - { - double secondsDiff = timeStepDates[0].secsTo(timeStepDates[i]); - - double decimalDaysDiff = secondsDiff / secondsInADay; - - socketStream << decimalDaysDiff; - } + socketStream << day; } return true; From ad4657d610589c397cf70b5c58dfb96ad86ff9d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 26 Apr 2017 09:40:42 +0200 Subject: [PATCH 034/157] #165 Use original days since simulation start when plotting time history curves --- .../RimGridTimeHistoryCurve.cpp | 89 +++++++++++++++---- .../RimGridTimeHistoryCurve.h | 1 + .../Summary/RimSummaryTimeAxisProperties.cpp | 30 +++++++ .../Summary/RimSummaryTimeAxisProperties.h | 1 + 4 files changed, 103 insertions(+), 18 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp b/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp index ba42a7f85f..247acb6d6f 100644 --- a/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp @@ -294,7 +294,6 @@ void RimGridTimeHistoryCurve::onLoadDataAndUpdate() if (isCurveVisible()) { - std::vector dateTimes; std::vector values; RimEclipseGeometrySelectionItem* eclTopItem = eclipseGeomSelectionItem(); @@ -309,39 +308,43 @@ void RimGridTimeHistoryCurve::onLoadDataAndUpdate() m_geoMechResultDefinition->loadResult(); } - dateTimes = timeStepValues(); values = yValues(); RimSummaryPlot* plot = nullptr; firstAncestorOrThisOfType(plot); bool isLogCurve = plot->isLogarithmicScaleEnabled(this->yAxis()); - if (dateTimes.size() > 0 && dateTimes.size() == values.size()) + if (plot->timeAxisProperties()->timeMode() == RimSummaryTimeAxisProperties::DATE) { - if (plot->timeAxisProperties()->timeMode() == RimSummaryTimeAxisProperties::DATE) + std::vector dateTimes = timeStepValues(); + if (dateTimes.size() > 0 && dateTimes.size() == values.size()) { m_qwtPlotCurve->setSamplesFromTimeTAndValues(dateTimes, values, isLogCurve); } else { - double timeScale = plot->timeAxisProperties()->fromTimeTToDisplayUnitScale(); - - std::vector times; - if (dateTimes.size()) - { - time_t startDate = dateTimes[0]; - for (time_t& date : dateTimes) - { - times.push_back(timeScale*(date - startDate)); - } - } - - m_qwtPlotCurve->setSamplesFromTimeAndValues(times, values, isLogCurve); + m_qwtPlotCurve->setSamplesFromTimeTAndValues(std::vector(), std::vector(), isLogCurve); } } else { - m_qwtPlotCurve->setSamplesFromTimeTAndValues(std::vector(), std::vector(), isLogCurve); + std::vector days = daysSinceSimulationStart(); + if (days.size() > 0 && days.size() == values.size()) + { + double timeScale = plot->timeAxisProperties()->fromDaysToDisplayUnitScale(); + + std::vector times; + for (double day : days) + { + times.push_back(timeScale * day); + } + + m_qwtPlotCurve->setSamplesFromTimeAndValues(times, values, isLogCurve); + } + else + { + m_qwtPlotCurve->setSamplesFromTimeTAndValues(std::vector(), std::vector(), isLogCurve); + } } updateZoomInParentPlot(); @@ -404,6 +407,56 @@ std::vector RimGridTimeHistoryCurve::timeStepValues() const return dateTimes; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimGridTimeHistoryCurve::daysSinceSimulationStart() const +{ + std::vector daysSinceSimulationStart; + RimEclipseGeometrySelectionItem* eclTopItem = eclipseGeomSelectionItem(); + if (eclTopItem && eclTopItem->eclipseCase()) + { + RimReservoirCellResultsStorage* cellResStorage = m_eclipseResultDefinition->currentGridCellResults(); + RigCaseCellResultsData* cellResultsData = cellResStorage->cellResults(); + + daysSinceSimulationStart = cellResultsData->daysSinceSimulationStart(); + } + + RimGeoMechGeometrySelectionItem* geoMechTopItem = geoMechGeomSelectionItem(); + if (geoMechTopItem && geoMechTopItem->geoMechCase()) + { + std::unique_ptr timeHistResultAccessor = femTimeHistoryResultAccessor(); + if (timeHistResultAccessor) + { + std::vector values = timeHistResultAccessor->timeHistoryValues(); + + QStringList stepNames = geoMechTopItem->geoMechCase()->timeStepStrings(); + std::vector dates = RimGeoMechCase::dateTimeVectorFromTimeStepStrings(stepNames); + if (dates.size() == values.size()) + { + if (!dates.empty()) { + time_t startDate = dates[0].toTime_t(); + double secondsToDaysConversion = (24.0 * 60.0 * 60.0); + for (QDateTime dt : dates) + { + double timeDifference = static_cast(dt.toTime_t() - startDate); + daysSinceSimulationStart.push_back(timeDifference / secondsToDaysConversion); + } + } + } + else + { + for (size_t i = 0; i < values.size(); i++) + { + daysSinceSimulationStart.push_back(i); + } + } + } + } + + return daysSinceSimulationStart; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.h b/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.h index e2ec0995be..94e9aa7181 100644 --- a/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.h +++ b/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.h @@ -56,6 +56,7 @@ public: std::vector yValues() const; std::vector timeStepValues() const; + std::vector daysSinceSimulationStart() const; QString quantityName() const; QString caseName() const; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp index d42b3ef8ec..42cb6cb51b 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.cpp @@ -278,6 +278,36 @@ double RimSummaryTimeAxisProperties::fromTimeTToDisplayUnitScale() return scale; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimSummaryTimeAxisProperties::fromDaysToDisplayUnitScale() +{ + double scale = 1.0; + switch (m_timeUnit()) + { + case SECONDS: + scale = 60.0 * 60.0 * 24.0; + break; + case MINUTES: + scale = 60.0 * 24.0; + break; + case HOURS: + scale = 24.0; + break; + case DAYS: + break; + case YEARS: + scale = 1.0/365.2425; + break; + default: + CVF_ASSERT(false); + break; + } + + return scale; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h index 3e528c7be9..1f67606a0c 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryTimeAxisProperties.h @@ -69,6 +69,7 @@ public: TimeModeType timeMode() const { return m_timeMode(); } void setTimeMode(TimeModeType val) { m_timeMode = val; } double fromTimeTToDisplayUnitScale(); + double fromDaysToDisplayUnitScale(); double visibleRangeMin() const; double visibleRangeMax() const; From 6a5f924c0f2c2eb8b058cd8be2a2902c59f3371e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 26 Apr 2017 13:03:52 +0200 Subject: [PATCH 035/157] #1431 Update version of Ert so-files to be installed --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2ba9e11ba..7b8272fd67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -364,19 +364,19 @@ if (RESINSIGHT_PRIVATE_INSTALL) set(ERT_SHARED_LIB_FILES ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2 - ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2.1 + ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl.so.2.2 ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libeclxx.so ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libeclxx.so.2 - ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libeclxx.so.2.1 + ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libeclxx.so.2.2 ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl_well.so ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl_well.so.2 - ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl_well.so.2.1 + ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libecl_well.so.2.2 ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libert_geometry.so ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libert_geometry.so.2 - ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libert_geometry.so.2.1 + ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libert_geometry.so.2.2 ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libert_util.so ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libert_util.so.2 - ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libert_util.so.2.1 + ${CMAKE_BINARY_DIR}/ThirdParty/Ert/${CMAKE_INSTALL_LIBDIR}/libert_util.so.2.2 ) install(FILES ${ERT_SHARED_LIB_FILES} DESTINATION ${RESINSIGHT_INSTALL_FOLDER} ) From 76f55c211ff66053e9f0b887313595ca06e7e09f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 26 Apr 2017 15:17:58 +0200 Subject: [PATCH 036/157] #1031 Fix parallel projection for linked Eclipse and GeoMech cases --- .../ProjectDataModel/RimViewManipulator.cpp | 74 ++++++++++--------- Fwk/AppFwk/cafViewer/cafViewer.cpp | 8 ++ Fwk/AppFwk/cafViewer/cafViewer.h | 1 + 3 files changed, 50 insertions(+), 33 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimViewManipulator.cpp b/ApplicationCode/ProjectDataModel/RimViewManipulator.cpp index af213af74e..ac8712139c 100644 --- a/ApplicationCode/ProjectDataModel/RimViewManipulator.cpp +++ b/ApplicationCode/ProjectDataModel/RimViewManipulator.cpp @@ -22,6 +22,7 @@ #include "RimEclipseView.h" #include "RimView.h" +#include "RimCase.h" #include "RiuViewer.h" @@ -36,25 +37,35 @@ //-------------------------------------------------------------------------------------------------- void RimViewManipulator::applySourceViewCameraOnDestinationViews(RimView* sourceView, std::vector& destinationViews) { + bool setPointOfInterest = false; cvf::Vec3d sourceCamUp; cvf::Vec3d sourceCamEye; cvf::Vec3d sourceCamViewRefPoint; + cvf::Vec3d sourcePointOfInterest; sourceView->viewer()->mainCamera()->toLookAt(&sourceCamEye, &sourceCamViewRefPoint, &sourceCamUp); cvf::Vec3d sourceCamGlobalEye = sourceCamEye; cvf::Vec3d sourceCamGlobalViewRefPoint = sourceCamViewRefPoint; + if (sourceView->viewer()->getNavigationPolicy() != nullptr) + { + setPointOfInterest = true; + sourcePointOfInterest = sourceView->viewer()->pointOfInterest(); + } // Source bounding box in global coordinates including scaleZ cvf::BoundingBox sourceSceneBB = sourceView->viewer()->currentScene()->boundingBox(); - - RimEclipseView* eclipseView = dynamic_cast(sourceView); - if (eclipseView && eclipseView->mainGrid()) { - cvf::Vec3d offset = eclipseView->mainGrid()->displayModelOffset(); - offset.z() *= eclipseView->scaleZ(); + cvf::Vec3d offset = cvf::Vec3d::ZERO; + RimCase* sourceOwnerCase = sourceView->ownerCase(); + if (sourceOwnerCase) + { + offset = sourceOwnerCase->displayModelOffset(); + offset.z() *= sourceView->scaleZ(); + } sourceCamGlobalEye += offset; sourceCamGlobalViewRefPoint += offset; + if (setPointOfInterest) sourcePointOfInterest += offset; cvf::Mat4d trans; trans.setTranslation(offset); @@ -74,44 +85,41 @@ void RimViewManipulator::applySourceViewCameraOnDestinationViews(RimView* source // Destination bounding box in global coordinates including scaleZ cvf::BoundingBox destSceneBB = destinationViewer->currentScene()->boundingBox(); + cvf::Vec3d destinationCamEye = sourceCamGlobalEye; + cvf::Vec3d destinationCamViewRefPoint = sourceCamGlobalViewRefPoint; + cvf::Vec3d offset = cvf::Vec3d::ZERO; - RimEclipseView* destEclipseView = dynamic_cast(destinationView); - if (destEclipseView && destEclipseView->mainGrid()) + RimCase* destinationOwnerCase = destinationView->ownerCase(); + if (destinationOwnerCase) { - cvf::Vec3d destOffset = destEclipseView->mainGrid()->displayModelOffset(); - destOffset.z() *= destEclipseView->scaleZ(); + offset = destinationOwnerCase->displayModelOffset(); + offset.z() *= destinationView->scaleZ(); + } - cvf::Vec3d destinationCamEye = sourceCamGlobalEye - destOffset; - cvf::Vec3d destinationCamViewRefPoint = sourceCamGlobalViewRefPoint - destOffset; + destinationCamEye -= offset; + destinationCamViewRefPoint -= offset; - cvf::Mat4d trans; - trans.setTranslation(destOffset); - destSceneBB.transform(trans); + cvf::Mat4d trans; + trans.setTranslation(offset); + destSceneBB.transform(trans); - if (isBoundingBoxesOverlappingOrClose(sourceSceneBB, destSceneBB)) - { - destinationViewer->mainCamera()->setFromLookAt(destinationCamEye, destinationCamViewRefPoint, sourceCamUp); - } - else - { - // Fallback using values from source camera - destinationViewer->mainCamera()->setFromLookAt(sourceCamEye, sourceCamViewRefPoint, sourceCamUp); - } + if (isBoundingBoxesOverlappingOrClose(sourceSceneBB, destSceneBB)) + { + destinationViewer->mainCamera()->setFromLookAt(destinationCamEye, destinationCamViewRefPoint, sourceCamUp); } else { - if (isBoundingBoxesOverlappingOrClose(sourceSceneBB, destSceneBB)) - { - destinationViewer->mainCamera()->setFromLookAt(sourceCamGlobalEye, sourceCamGlobalViewRefPoint, sourceCamUp); - } - else - { - // Fallback using values from source camera - destinationViewer->mainCamera()->setFromLookAt(sourceCamEye, sourceCamViewRefPoint, sourceCamUp); - } + // Fallback using values from source camera + destinationViewer->mainCamera()->setFromLookAt(sourceCamEye, sourceCamViewRefPoint, sourceCamUp); } - destinationViewer->updateParallelProjectionSettings(sourceView->viewer()); + if (setPointOfInterest) + { + cvf::Vec3d pointOfInterest = sourcePointOfInterest; + pointOfInterest -= offset; + destinationViewer->updateParallelProjectionHeightFromMoveZoom(pointOfInterest); + destinationViewer->updateParallelProjectionCameraPosFromPointOfInterestMove(pointOfInterest); + } destinationViewer->update(); } diff --git a/Fwk/AppFwk/cafViewer/cafViewer.cpp b/Fwk/AppFwk/cafViewer/cafViewer.cpp index d5f37bdb96..66aa61ddb5 100644 --- a/Fwk/AppFwk/cafViewer/cafViewer.cpp +++ b/Fwk/AppFwk/cafViewer/cafViewer.cpp @@ -461,6 +461,14 @@ void caf::Viewer::setNavigationPolicy(caf::NavigationPolicy* navigationPolicy) if (m_navigationPolicy.notNull()) m_navigationPolicy->setViewer(this); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const caf::NavigationPolicy* caf::Viewer::getNavigationPolicy() const +{ + return m_navigationPolicy.p(); +} + //-------------------------------------------------------------------------------------------------- /// diff --git a/Fwk/AppFwk/cafViewer/cafViewer.h b/Fwk/AppFwk/cafViewer/cafViewer.h index c90fb63721..23db03d2d6 100644 --- a/Fwk/AppFwk/cafViewer/cafViewer.h +++ b/Fwk/AppFwk/cafViewer/cafViewer.h @@ -117,6 +117,7 @@ public: // Set the navigation policy void setNavigationPolicy(caf::NavigationPolicy* navigationPolicy); + const caf::NavigationPolicy* getNavigationPolicy() const; void enableNavigationPolicy(bool enable); void setView( const cvf::Vec3d& alongDirection, const cvf::Vec3d& upDirection ); void zoomAll(); From 700a73ca19456aeb8b7ad28cf9d391726a635f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 26 Apr 2017 15:43:34 +0200 Subject: [PATCH 037/157] #1012 Do not toggle object when pressing enter after renaming in summary window --- .../UserInterface/RiuTreeViewEventFilter.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/UserInterface/RiuTreeViewEventFilter.cpp b/ApplicationCode/UserInterface/RiuTreeViewEventFilter.cpp index eedc2637a5..fdf3c47298 100644 --- a/ApplicationCode/UserInterface/RiuTreeViewEventFilter.cpp +++ b/ApplicationCode/UserInterface/RiuTreeViewEventFilter.cpp @@ -21,12 +21,16 @@ #include "ToggleCommands/RicToggleItemsFeatureImpl.h" +#include "RiaApplication.h" + #include "RimCaseCollection.h" #include "RimEclipseCase.h" #include "RimGeoMechCase.h" #include "RimGeoMechView.h" #include "RimIdenticalGridCaseGroup.h" + #include "RiuMainWindow.h" +#include "RiuMainPlotWindow.h" #include "cafCmdFeature.h" #include "cafCmdFeatureManager.h" @@ -85,7 +89,18 @@ bool RiuTreeViewEventFilter::eventFilter(QObject *obj, QEvent *event) } } - if (!RiuMainWindow::instance()->projectTreeView()->isTreeItemEditWidgetActive()) + // Do not toggle state if currently editing a name in the tree view + bool toggleStateForSelection = true; + if (RiuMainWindow::instance()->projectTreeView()->isTreeItemEditWidgetActive()) + { + toggleStateForSelection = false; + } + else if (RiaApplication::instance()->mainPlotWindow() && RiaApplication::instance()->mainPlotWindow()->projectTreeView()->isTreeItemEditWidgetActive()) + { + toggleStateForSelection = false; + } + + if (toggleStateForSelection) { switch (keyEvent->key()) { From b91af152146df84b99aed2c462dedf5e3e43757a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 26 Apr 2017 16:59:52 +0200 Subject: [PATCH 038/157] #1428 Respect current timestep of well log extraction curves when getting flow diagnostics result address --- .../RimEclipseResultDefinition.cpp | 14 ++++++++++++++ .../ProjectDataModel/RimWellLogExtractionCurve.cpp | 8 ++++++++ .../ProjectDataModel/RimWellLogExtractionCurve.h | 2 ++ 3 files changed, 24 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index 8f96a08926..19d19dd8ac 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -37,6 +37,8 @@ #include "RimReservoirCellResultsStorage.h" #include "RimView.h" #include "RimViewLinker.h" +#include "RimGridTimeHistoryCurve.h" +#include "RimWellLogExtractionCurve.h" #include "cafPdmUiListEditor.h" @@ -662,6 +664,18 @@ RigFlowDiagResultAddress RimEclipseResultDefinition::flowDiagResAddress() const { timeStep = rimView->currentTimeStep(); } + RimWellLogExtractionCurve* wellLogExtractionCurve = nullptr; + this->firstAncestorOrThisOfType(wellLogExtractionCurve); + if (wellLogExtractionCurve) + { + timeStep = static_cast(wellLogExtractionCurve->currentTimeStep()); + } + + // Time history curves are not supported, since it requires the time + // step to access to be supplied. + RimGridTimeHistoryCurve* timeHistoryCurve = nullptr; + this->firstAncestorOrThisOfType(timeHistoryCurve); + CVF_ASSERT(timeHistoryCurve == nullptr); std::set selTracerNames; if (m_flowTracerSelectionMode == FLOW_TR_BY_SELECTION) diff --git a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp index ab09094d4c..1a2f41a4a8 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp @@ -899,3 +899,11 @@ double RimWellLogExtractionCurve::rkbDiff() const return HUGE_VAL; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RimWellLogExtractionCurve::currentTimeStep() const +{ + return m_timeStep(); +} diff --git a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h index 0c05ad8545..70734a3414 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h +++ b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.h @@ -63,6 +63,8 @@ public: QString caseName() const; double rkbDiff() const; + int currentTimeStep() const; + protected: virtual QString createCurveAutoName(); virtual void onLoadDataAndUpdate(); From 7dc903102de9835858f828dd563802a11170a585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 26 Apr 2017 17:07:39 +0200 Subject: [PATCH 039/157] #1425 Disable flow diagnostics results for time history curves --- .../ProjectDataModel/RimEclipseResultDefinition.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index 19d19dd8ac..8b6497ec70 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -428,9 +428,11 @@ QList RimEclipseResultDefinition::calculateValueOptions( hasFlowDiagFluxes = eclResCase->eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS)->hasFlowDiagUsableFluxes(); } - // Do not include flow diag results if not available + RimGridTimeHistoryCurve* timeHistoryCurve; + this->firstAncestorOrThisOfType(timeHistoryCurve); - if ( !hasFlowDiagFluxes ) + // Do not include flow diagnostics results if not available or is a time history curve + if ( !hasFlowDiagFluxes || timeHistoryCurve != nullptr ) { using ResCatEnum = caf::AppEnum< RimDefines::ResultCatType >; for ( size_t i = 0; i < ResCatEnum::size(); ++i ) From 7ff27a1938720e7e090e83a11f5ac018a0893671 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 27 Apr 2017 08:14:42 +0200 Subject: [PATCH 040/157] #1384 Use case insensitive path part compare on Windows --- ApplicationCode/ProjectDataModel/RimTools.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimTools.cpp b/ApplicationCode/ProjectDataModel/RimTools.cpp index e9dc626ea2..85396c40a9 100644 --- a/ApplicationCode/ProjectDataModel/RimTools.cpp +++ b/ApplicationCode/ProjectDataModel/RimTools.cpp @@ -130,7 +130,15 @@ QString RimTools::relocateFile(const QString& orgFileName, const QString& orgNew int firstDiffIdx = 0; for (firstDiffIdx = 0; firstDiffIdx < gridPathElements.size() && firstDiffIdx < oldProjPathElements.size(); ++firstDiffIdx) { - if (gridPathElements[firstDiffIdx] == oldProjPathElements[firstDiffIdx]) +#ifdef WIN32 + // When comparing parts of a file path, the drive letter has been seen to be a mix of + // upper and lower cases. Always use case insensitive compare on Windows, as this is a valid approach + // for all parts for a file path + Qt::CaseSensitivity cs = Qt::CaseInsensitive; +#else + Qt::CaseSensitivity cs = Qt::CaseSensitive; +#endif + if (gridPathElements[firstDiffIdx].compare(oldProjPathElements[firstDiffIdx], cs) == 0) { pathStartsAreEqual = pathStartsAreEqual || !gridPathElements[firstDiffIdx].isEmpty(); } From ff1b8c6db8095a40aa674e92070639f944c9f8f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 27 Apr 2017 09:51:31 +0200 Subject: [PATCH 041/157] Fix assert in Show Contibuting Wells due to wrongful use of firstAnchestorOf --- .../FlowCommands/RicShowContributingWellsFromPlotFeature.cpp | 3 +-- .../ProjectDataModel/Flow/RimWellAllocationPlot.cpp | 4 ++-- ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/Commands/FlowCommands/RicShowContributingWellsFromPlotFeature.cpp b/ApplicationCode/Commands/FlowCommands/RicShowContributingWellsFromPlotFeature.cpp index e805a344de..40f4e73c58 100644 --- a/ApplicationCode/Commands/FlowCommands/RicShowContributingWellsFromPlotFeature.cpp +++ b/ApplicationCode/Commands/FlowCommands/RicShowContributingWellsFromPlotFeature.cpp @@ -54,8 +54,7 @@ void RicShowContributingWellsFromPlotFeature::onActionTriggered(bool isChecked) int timeStep = wellAllocationPlot->timeStep(); QString wellName = wellAllocationPlot->wellName(); - RimEclipseResultCase* wellAllocationResultCase = nullptr; - wellAllocationPlot->flowDiagSolution()->firstAncestorOrThisOfTypeAsserted(wellAllocationResultCase); + RimEclipseResultCase* wellAllocationResultCase = wellAllocationPlot->rimCase(); RicShowContributingWellsFeatureImpl::maniuplateSelectedView(wellAllocationResultCase, wellName, timeStep); } diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp index 3aeec6add7..7691d9b018 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp @@ -516,9 +516,9 @@ caf::PdmObject* RimWellAllocationPlot::plotLegend() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFlowDiagSolution* RimWellAllocationPlot::flowDiagSolution() +RimEclipseResultCase* RimWellAllocationPlot::rimCase() { - return m_flowDiagSolution(); + return m_case(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h index ccb401c3d2..741edad7d2 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h @@ -69,7 +69,7 @@ public: RimWellLogPlot* accumulatedWellFlowPlot(); RimTotalWellAllocationPlot* totalWellFlowPlot(); caf::PdmObject* plotLegend(); - RimFlowDiagSolution* flowDiagSolution(); + RimEclipseResultCase* rimCase(); int timeStep(); QString wellName() const; From 129b07bf7743e2a7acc9adb1e479aadaaba566ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 27 Apr 2017 09:54:03 +0200 Subject: [PATCH 042/157] #1436 Rename to Advanced Snapshots Export --- .../Commands/RicExportMultipleSnapshotsFeature.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Commands/RicExportMultipleSnapshotsFeature.cpp b/ApplicationCode/Commands/RicExportMultipleSnapshotsFeature.cpp index 3062534c09..5d8c09df3a 100644 --- a/ApplicationCode/Commands/RicExportMultipleSnapshotsFeature.cpp +++ b/ApplicationCode/Commands/RicExportMultipleSnapshotsFeature.cpp @@ -95,8 +95,8 @@ void RicExportMultipleSnapshotsFeature::onActionTriggered(bool isChecked) //-------------------------------------------------------------------------------------------------- void RicExportMultipleSnapshotsFeature::setupActionLook(QAction* actionToSetup) { - actionToSetup->setText("Export Multiple Snapshots ..."); - //actionToSetup->setIcon(QIcon(":/Save.png")); + actionToSetup->setText("Advanced Snapshot Export ..."); + actionToSetup->setIcon(QIcon(":/SnapShotSaveViews.png")); } //-------------------------------------------------------------------------------------------------- From 0848e9f8ebc22306799956530fe59228f099340e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 27 Apr 2017 10:53:53 +0200 Subject: [PATCH 043/157] #1433 Fix export property to file for flow diagnostics properties --- ...icSaveEclipseResultAsInputPropertyExec.cpp | 3 +-- .../RifEclipseInputFileTools.cpp | 21 +++++++------------ .../FileInterface/RifEclipseInputFileTools.h | 3 ++- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/Commands/EclipseCommands/RicSaveEclipseResultAsInputPropertyExec.cpp b/ApplicationCode/Commands/EclipseCommands/RicSaveEclipseResultAsInputPropertyExec.cpp index e8cb054c3f..b28c89474f 100644 --- a/ApplicationCode/Commands/EclipseCommands/RicSaveEclipseResultAsInputPropertyExec.cpp +++ b/ApplicationCode/Commands/EclipseCommands/RicSaveEclipseResultAsInputPropertyExec.cpp @@ -94,9 +94,8 @@ void RicSaveEclipseResultAsInputPropertyExec::redo() if (propertyDialog.exec() == QDialog::Accepted) { size_t timeStep = m_cellColors->reservoirView()->currentTimeStep(); - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(m_cellColors->porosityModel()); - bool isOk = RifEclipseInputFileTools::writeBinaryResultToTextFile(exportSettings.fileName, m_cellColors->reservoirView()->eclipseCase()->eclipseCaseData(), porosityModel, timeStep, m_cellColors->resultVariable(), exportSettings.eclipseKeyword, exportSettings.undefinedValue); + bool isOk = RifEclipseInputFileTools::writeBinaryResultToTextFile(exportSettings.fileName, m_cellColors->reservoirView()->eclipseCase()->eclipseCaseData(), timeStep, m_cellColors, exportSettings.eclipseKeyword, exportSettings.undefinedValue); if (!isOk) { QMessageBox::critical(NULL, "File export", "Failed to exported current result to " + exportSettings.fileName); diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 59e9f44c8f..da057819d2 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -474,18 +474,17 @@ bool RifEclipseInputFileTools::writePropertyToTextFile(const QString& fileName, /// Create and write a result vector with values for all cells. /// undefinedValue is used for cells with no result //-------------------------------------------------------------------------------------------------- -bool RifEclipseInputFileTools::writeBinaryResultToTextFile(const QString& fileName, - RigEclipseCaseData* eclipseCase, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStep, - const QString& resultName, - const QString& eclipseKeyWord, +bool RifEclipseInputFileTools::writeBinaryResultToTextFile(const QString& fileName, + RigEclipseCaseData* eclipseCase, + size_t timeStep, + RimEclipseResultDefinition* resultDefinition, + const QString& eclipseKeyWord, const double undefinedValue) { CVF_ASSERT(eclipseCase); - size_t resultIndex = eclipseCase->results(porosityModel)->findScalarResultIndex(resultName); - if (resultIndex == cvf::UNDEFINED_SIZE_T) + cvf::ref resultAccessor = RigResultAccessorFactory::createFromResultDefinition(eclipseCase, eclipseCase->mainGrid()->gridIndex(), timeStep, resultDefinition); + if (resultAccessor.isNull()) { return false; } @@ -496,12 +495,6 @@ bool RifEclipseInputFileTools::writeBinaryResultToTextFile(const QString& fileNa return false; } - cvf::ref resultAccessor = RigResultAccessorFactory::createFromUiResultName(eclipseCase, eclipseCase->mainGrid()->gridIndex(), porosityModel, timeStep, resultName); - if (resultAccessor.isNull()) - { - return false; - } - std::vector resultData; size_t i, j, k; for (k = 0; k < eclipseCase->mainGrid()->cellCountK(); k++) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.h b/ApplicationCode/FileInterface/RifEclipseInputFileTools.h index 6e14274bc8..f1172c08b6 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.h +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.h @@ -36,6 +36,7 @@ class RigEclipseCaseData; class QFile; +class RimEclipseResultDefinition; //-------------------------------------------------------------------------------------------------- @@ -76,7 +77,7 @@ public: static bool writePropertyToTextFile(const QString& fileName, RigEclipseCaseData* eclipseCase, size_t timeStep, const QString& resultName, const QString& eclipseKeyWord); - static bool writeBinaryResultToTextFile(const QString& fileName, RigEclipseCaseData* eclipseCase, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStep, const QString& resultName, const QString& eclipseKeyWord, const double undefinedValue); + static bool writeBinaryResultToTextFile(const QString& fileName, RigEclipseCaseData* eclipseCase, size_t timeStep, RimEclipseResultDefinition* resultdefinition, const QString& eclipseKeyWord, const double undefinedValue); static bool readFaultsAndParseIncludeStatementsRecursively( QFile& file, qint64 startPos, From cd9f496ea9481de4499ca30ac940ab3b8501af5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 27 Apr 2017 11:35:05 +0200 Subject: [PATCH 044/157] #1435 Move contribute to legend to curve name configuration --- ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp | 2 +- ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp | 2 +- .../ProjectDataModel/Summary/RimSummaryCurveFilter.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp b/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp index 247acb6d6f..e9ac2b3c6f 100644 --- a/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp @@ -481,13 +481,13 @@ void RimGridTimeHistoryCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiO } uiOrdering.add(&m_plotAxis); - uiOrdering.add(&m_showLegend); caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance"); RimPlotCurve::appearanceUiOrdering(*appearanceGroup); caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup("Curve Name"); nameGroup->setCollapsedByDefault(true); + nameGroup->add(&m_showLegend); RimPlotCurve::curveNameUiOrdering(*nameGroup); } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index 3f25468a2f..ab60c6bbc7 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -446,13 +446,13 @@ void RimSummaryCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& curveVarSelectionGroup->add(&m_uiFilterResultSelection); uiOrdering.add(&m_plotAxis); - uiOrdering.add(&m_showLegend); caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance"); RimPlotCurve::appearanceUiOrdering(*appearanceGroup); caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup("Curve Name"); nameGroup->setCollapsedByDefault(true); + nameGroup->add(&m_showLegend); RimPlotCurve::curveNameUiOrdering(*nameGroup); if (m_isUsingAutoName) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp index 16e56ef630..47c0e082d9 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp @@ -198,7 +198,6 @@ void RimSummaryCurveFilter::defineUiOrdering(QString uiConfigName, caf::PdmUiOrd curveVarSelectionGroup->add(&m_uiFilterResultMultiSelection); uiOrdering.add(&m_plotAxis); - uiOrdering.add(&m_showLegend); caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance settings"); appearanceGroup->setCollapsedByDefault(true); @@ -219,6 +218,7 @@ void RimSummaryCurveFilter::defineUiOrdering(QString uiConfigName, caf::PdmUiOrd caf::PdmUiGroup* autoNameGroup = uiOrdering.addNewGroup("Curve Name Configuration"); autoNameGroup->setCollapsedByDefault(true); + autoNameGroup->add(&m_showLegend); m_curveNameConfig->uiOrdering(uiConfigName, *autoNameGroup); uiOrdering.add(&m_autoApplyChangesToPlot); From 74d783d5a3f236818890ecd6d3e23a22c7ca178b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 27 Apr 2017 11:36:02 +0200 Subject: [PATCH 045/157] #1435 Capitalize Settings in "Appearance Settings" --- .../ProjectDataModel/Summary/RimSummaryCurveFilter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp index 47c0e082d9..0030f9bb75 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp @@ -199,7 +199,7 @@ void RimSummaryCurveFilter::defineUiOrdering(QString uiConfigName, caf::PdmUiOrd uiOrdering.add(&m_plotAxis); - caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance settings"); + caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance Settings"); appearanceGroup->setCollapsedByDefault(true); appearanceGroup->add(&m_useAutoAppearanceAssignment); appearanceGroup->add(&m_caseAppearanceType); From 6596186df819ff410b74893071776203dc30c13f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 27 Apr 2017 11:38:41 +0200 Subject: [PATCH 046/157] #1435 Auto apply changes to summary curve filter by default --- .../ProjectDataModel/Summary/RimSummaryCurveFilter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp index 0030f9bb75..1af3b1f1ab 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveFilter.cpp @@ -98,7 +98,7 @@ RimSummaryCurveFilter::RimSummaryCurveFilter() m_applyButtonField.uiCapability()->setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName()); m_applyButtonField.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::LEFT); - CAF_PDM_InitField(&m_autoApplyChangesToPlot, "AutoApplyFilterChanges", false, "Auto Apply Changes", "", "", ""); + CAF_PDM_InitField(&m_autoApplyChangesToPlot, "AutoApplyFilterChanges", true, "Auto Apply Changes", "", "", ""); CAF_PDM_InitField(&m_showCurves, "IsActive", true, "Show Curves", "", "", ""); m_showCurves.uiCapability()->setUiHidden(true); From 2bb2405682f56fc95a494b2ef27c1f3d6b6dfa1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 27 Apr 2017 12:08:41 +0200 Subject: [PATCH 047/157] #1434 Specify tracer selection options are for open injectors and producers, not all --- .../ProjectDataModel/RimEclipseResultDefinition.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index 8b6497ec70..daf912c695 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -47,9 +47,9 @@ namespace caf template<> void RimEclipseResultDefinition::FlowTracerSelectionEnum::setUp() { - addItem(RimEclipseResultDefinition::FLOW_TR_INJ_AND_PROD, "FLOW_TR_INJ_AND_PROD", "All Injectors and Producers"); - addItem(RimEclipseResultDefinition::FLOW_TR_PRODUCERS, "FLOW_TR_PRODUCERS", "All Producers"); - addItem(RimEclipseResultDefinition::FLOW_TR_INJECTORS, "FLOW_TR_INJECTORS", "All Injectors"); + addItem(RimEclipseResultDefinition::FLOW_TR_INJ_AND_PROD, "FLOW_TR_INJ_AND_PROD", "Open Injectors and Producers"); + addItem(RimEclipseResultDefinition::FLOW_TR_PRODUCERS, "FLOW_TR_PRODUCERS", "Open Producers"); + addItem(RimEclipseResultDefinition::FLOW_TR_INJECTORS, "FLOW_TR_INJECTORS", "Open Injectors"); addItem(RimEclipseResultDefinition::FLOW_TR_BY_SELECTION, "FLOW_TR_BY_SELECTION", "By Selection"); setDefault(RimEclipseResultDefinition::FLOW_TR_INJ_AND_PROD); From 174d65821951af4f3f2614086eda0ed4bb1c36b5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 27 Apr 2017 12:11:43 +0200 Subject: [PATCH 048/157] #1384 Relocate filenames containing faults when opening project --- .../ProjectDataModel/RimEclipseResultCase.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp index 3bf93c0448..3432d203e7 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp @@ -356,6 +356,15 @@ void RimEclipseResultCase::updateFilePathsFromProjectPath(const QString& newProj // Update filename and folder paths when opening project from a different file location caseFileName = RimTools::relocateFile(caseFileName(), newProjectPath, oldProjectPath, &foundFile, &searchedPaths); + + std::vector relocatedFaultFiles; + for (auto faultFileName : filesContainingFaults()) + { + QString relocatedFaultFile = RimTools::relocateFile(faultFileName, newProjectPath, oldProjectPath, &foundFile, &searchedPaths); + relocatedFaultFiles.push_back(relocatedFaultFile); + } + + filesContainingFaults = relocatedFaultFiles; #if 0 // Output the search path for debugging for (size_t i = 0; i < searchedPaths.size(); ++i) From 0c07493dc121c5599f47f1c8a4f21823edf157d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 27 Apr 2017 13:16:44 +0200 Subject: [PATCH 049/157] #1414 New eclipse tab and fixed capitalization in preferences --- .../Application/RiaPreferences.cpp | 56 ++++++++++--------- .../FileInterface/RifReaderSettings.cpp | 4 +- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index a2a16dad8e..07e53e4d47 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -33,7 +33,7 @@ CAF_PDM_SOURCE_INIT(RiaPreferences, "RiaPreferences"); //-------------------------------------------------------------------------------------------------- RiaPreferences::RiaPreferences(void) { - CAF_PDM_InitField(&navigationPolicy, "navigationPolicy", caf::AppEnum(RiaApplication::NAVIGATION_POLICY_CEETRON), "Navigation mode", "", "", ""); + CAF_PDM_InitField(&navigationPolicy, "navigationPolicy", caf::AppEnum(RiaApplication::NAVIGATION_POLICY_CEETRON), "Navigation Mode", "", "", ""); CAF_PDM_InitFieldNoDefault(&scriptDirectories, "scriptDirectory", "Shared Script Folder(s)", "", "", ""); scriptDirectories.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); @@ -41,27 +41,27 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitField(&scriptEditorExecutable, "scriptEditorExecutable", QString("kate"), "Script Editor", "", "", ""); scriptEditorExecutable.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); - CAF_PDM_InitField(&octaveExecutable, "octaveExecutable", QString("octave"), "Octave executable location", "", "", ""); + CAF_PDM_InitField(&octaveExecutable, "octaveExecutable", QString("octave"), "Octave Executable Location", "", "", ""); octaveExecutable.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); octaveExecutable.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::TOP); - CAF_PDM_InitField(&octaveShowHeaderInfoWhenExecutingScripts, "octaveShowHeaderInfoWhenExecutingScripts", false, "Show text header when executing scripts", "", "", ""); + CAF_PDM_InitField(&octaveShowHeaderInfoWhenExecutingScripts, "octaveShowHeaderInfoWhenExecutingScripts", false, "Show Text Header When Executing Scripts", "", "", ""); octaveShowHeaderInfoWhenExecutingScripts.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitField(&ssihubAddress, "ssihubAddress", QString("http://"), "ssihub Address", "", "", ""); + CAF_PDM_InitField(&ssihubAddress, "ssihubAddress", QString("http://"), "SSIHUB Address", "", "", ""); ssihubAddress.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::TOP); CAF_PDM_InitField(&defaultGridLines, "defaultGridLines", true, "Gridlines", "", "", ""); - CAF_PDM_InitField(&defaultGridLineColors, "defaultGridLineColors", cvf::Color3f(0.92f, 0.92f, 0.92f), "Mesh color", "", "", ""); - CAF_PDM_InitField(&defaultFaultGridLineColors, "defaultFaultGridLineColors", cvf::Color3f(0.08f, 0.08f, 0.08f), "Mesh color along faults", "", "", ""); - CAF_PDM_InitField(&defaultWellLabelColor, "defaultWellLableColor", cvf::Color3f(0.92f, 0.92f, 0.92f), "Well label color", "", "The default well label color in new views", ""); + CAF_PDM_InitField(&defaultGridLineColors, "defaultGridLineColors", cvf::Color3f(0.92f, 0.92f, 0.92f), "Mesh Color", "", "", ""); + CAF_PDM_InitField(&defaultFaultGridLineColors, "defaultFaultGridLineColors", cvf::Color3f(0.08f, 0.08f, 0.08f), "Mesh Color Along Faults", "", "", ""); + CAF_PDM_InitField(&defaultWellLabelColor, "defaultWellLableColor", cvf::Color3f(0.92f, 0.92f, 0.92f), "Well Label Color", "", "The default well label color in new views", ""); - CAF_PDM_InitField(&defaultViewerBackgroundColor, "defaultViewerBackgroundColor", cvf::Color3f(0.69f, 0.77f, 0.87f), "Viewer background", "", "The viewer background color for new views", ""); + CAF_PDM_InitField(&defaultViewerBackgroundColor, "defaultViewerBackgroundColor", cvf::Color3f(0.69f, 0.77f, 0.87f), "Viewer Background", "", "The viewer background color for new views", ""); - CAF_PDM_InitField(&defaultScaleFactorZ, "defaultScaleFactorZ", 5, "Default Z scale factor", "", "", ""); - CAF_PDM_InitField(&fontSizeInScene, "fontSizeInScene", QString("8"), "Font size", "", "", ""); + CAF_PDM_InitField(&defaultScaleFactorZ, "defaultScaleFactorZ", 5, "Default Z Scale Factor", "", "", ""); + CAF_PDM_InitField(&fontSizeInScene, "fontSizeInScene", QString("8"), "Font Size", "", "", ""); - CAF_PDM_InitField(&showLasCurveWithoutTvdWarning, "showLasCurveWithoutTvdWarning", true, "Show LAS curve without TVD warning", "", "", ""); + CAF_PDM_InitField(&showLasCurveWithoutTvdWarning, "showLasCurveWithoutTvdWarning", true, "Show LAS Curve Without TVD Warning", "", "", ""); showLasCurveWithoutTvdWarning.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); CAF_PDM_InitField(&useShaders, "useShaders", true, "Use Shaders", "", "", ""); @@ -77,13 +77,13 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitFieldNoDefault(&lastUsedProjectFileName,"lastUsedProjectFileName", "Last Used Project File", "", "", ""); lastUsedProjectFileName.uiCapability()->setUiHidden(true); - CAF_PDM_InitField(&autocomputeDepthRelatedProperties, "autocomputeDepth", true, "Compute DEPTH related properties", "", "DEPTH, DX, DY, DZ, TOP, BOTTOM", ""); + CAF_PDM_InitField(&autocomputeDepthRelatedProperties, "autocomputeDepth", true, "Compute DEPTH Related Properties", "", "DEPTH, DX, DY, DZ, TOP, BOTTOM", ""); autocomputeDepthRelatedProperties.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitField(&loadAndShowSoil, "loadAndShowSoil", true, "Load and show SOIL", "", "", ""); + CAF_PDM_InitField(&loadAndShowSoil, "loadAndShowSoil", true, "Load and Show SOIL", "", "", ""); loadAndShowSoil.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitFieldNoDefault(&readerSettings, "readerSettings", "Reader settings", "", "", ""); + CAF_PDM_InitFieldNoDefault(&readerSettings, "readerSettings", "Reader Settings", "", "", ""); readerSettings = new RifReaderSettings; CAF_PDM_InitField(&autoCreatePlotsOnImport, "AutoCreatePlotsOnImport", true, "Automatically Create Summary Plots On Import", "", "", ""); @@ -92,6 +92,7 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitField(&defaultCurveFilter, "DefaultCurveFilter", QString("F*PT"), "Default Vector Selection Filter", "", "", ""); m_tabNames << "General"; + m_tabNames << "Eclipse"; m_tabNames << "Octave"; m_tabNames << "Summary"; } @@ -144,7 +145,7 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& { if (uiConfigName == m_tabNames[0]) { - caf::PdmUiGroup* defaultSettingsGroup = uiOrdering.addNewGroup("Default settings"); + caf::PdmUiGroup* defaultSettingsGroup = uiOrdering.addNewGroup("Default Settings"); defaultSettingsGroup->add(&defaultViewerBackgroundColor); defaultSettingsGroup->add(&defaultGridLines); defaultSettingsGroup->add(&defaultGridLineColors); @@ -152,25 +153,28 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& defaultSettingsGroup->add(&defaultWellLabelColor); defaultSettingsGroup->add(&fontSizeInScene); - caf::PdmUiGroup* viewsGroup = uiOrdering.addNewGroup("3D views"); + caf::PdmUiGroup* viewsGroup = uiOrdering.addNewGroup("3D Views"); viewsGroup->add(&navigationPolicy); viewsGroup->add(&useShaders); viewsGroup->add(&showHud); - caf::PdmUiGroup* newCaseBehaviourGroup = uiOrdering.addNewGroup("Behavior when loading new case"); - newCaseBehaviourGroup->add(&defaultScaleFactorZ); - newCaseBehaviourGroup->add(&autocomputeDepthRelatedProperties); - newCaseBehaviourGroup->add(&loadAndShowSoil); - newCaseBehaviourGroup->add(&showLasCurveWithoutTvdWarning); - - readerSettings->defineUiOrdering(uiConfigName, *newCaseBehaviourGroup); - caf::PdmUiGroup* ssihubGroup = uiOrdering.addNewGroup("SSIHUB"); - ssihubGroup->add(&ssihubAddress); + caf::PdmUiGroup* otherGroup = uiOrdering.addNewGroup("Other"); + otherGroup->add(&ssihubAddress); + otherGroup->add(&showLasCurveWithoutTvdWarning); uiOrdering.add(&appendClassNameToUiText); } else if (uiConfigName == m_tabNames[1]) + { + caf::PdmUiGroup* newCaseBehaviourGroup = uiOrdering.addNewGroup("Behavior When Loading Data"); + newCaseBehaviourGroup->add(&defaultScaleFactorZ); + newCaseBehaviourGroup->add(&autocomputeDepthRelatedProperties); + newCaseBehaviourGroup->add(&loadAndShowSoil); + + readerSettings->defineUiOrdering(uiConfigName, *newCaseBehaviourGroup); + } + else if (uiConfigName == m_tabNames[2]) { caf::PdmUiGroup* octaveGroup = uiOrdering.addNewGroup("Octave"); octaveGroup->add(&octaveExecutable); @@ -180,7 +184,7 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& scriptGroup->add(&scriptDirectories); scriptGroup->add(&scriptEditorExecutable); } - else if (uiConfigName == m_tabNames[2]) + else if (uiConfigName == m_tabNames[3]) { uiOrdering.add(&autoCreatePlotsOnImport); uiOrdering.add(&defaultCurveFilter); diff --git a/ApplicationCode/FileInterface/RifReaderSettings.cpp b/ApplicationCode/FileInterface/RifReaderSettings.cpp index 89fc15b397..473a86271c 100644 --- a/ApplicationCode/FileInterface/RifReaderSettings.cpp +++ b/ApplicationCode/FileInterface/RifReaderSettings.cpp @@ -31,13 +31,13 @@ RifReaderSettings::RifReaderSettings() { CAF_PDM_InitObject("RifReaderSettings", "", "", ""); - CAF_PDM_InitField(&importFaults, "importFaults", true, "Import faults", "", "", ""); + CAF_PDM_InitField(&importFaults, "importFaults", true, "Import Faults", "", "", ""); importFaults.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); CAF_PDM_InitField(&importNNCs, "importSimulationNNCs", true, "Import NNCs", "", "", ""); importNNCs.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitField(&importAdvancedMswData, "importAdvancedMswData", false, "Import advanced MSW data", "", "", ""); + CAF_PDM_InitField(&importAdvancedMswData, "importAdvancedMswData", false, "Import Advanced MSW Data", "", "", ""); importAdvancedMswData.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); CAF_PDM_InitField(&faultIncludeFileAbsolutePathPrefix, "faultIncludeFileAbsolutePathPrefix", QString(), "Fault Include File Absolute Path Prefix", "", "Path used to prefix absolute UNIX paths in fault include statements on Windows", ""); From 67e652713f09cd274516f179e2f06f7ed39d2bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 27 Apr 2017 14:14:06 +0200 Subject: [PATCH 050/157] Moved debug output regarding Well Log Extraction Curves to the Log Message window. Also removed some debug output. --- .../SummaryPlotCommands/RicAsciiExportSummaryPlotFeature.cpp | 2 +- .../WellLogCommands/RicAsciiExportWellLogPlotFeature.cpp | 2 +- ApplicationCode/ReservoirDataModel/RigMainGrid.cpp | 2 +- ApplicationCode/ReservoirDataModel/RigWellLogExtractor.cpp | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicAsciiExportSummaryPlotFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicAsciiExportSummaryPlotFeature.cpp index d86baf0014..f441dfc4d7 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicAsciiExportSummaryPlotFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicAsciiExportSummaryPlotFeature.cpp @@ -95,7 +95,7 @@ void RicAsciiExportSummaryPlotFeature::onActionTriggered(bool isChecked) bool writeFiles = caf::Utils::getSaveDirectoryAndCheckOverwriteFiles(defaultDir, fileNames, &saveDir); if (!writeFiles) return; - RiaLogging::debug(QString("Writing to directory %1").arg(saveDir)); + RiaLogging::info(QString("Writing to directory %1").arg(saveDir)); for (RimSummaryPlot* summaryPlot : selectedSummaryPlots) { QString fileName = saveDir + "/" + caf::Utils::makeValidFileBasename(summaryPlot->description()) + ".ascii"; diff --git a/ApplicationCode/Commands/WellLogCommands/RicAsciiExportWellLogPlotFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicAsciiExportWellLogPlotFeature.cpp index 7f0fb08227..f4f8c37791 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicAsciiExportWellLogPlotFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicAsciiExportWellLogPlotFeature.cpp @@ -93,7 +93,7 @@ void RicAsciiExportWellLogPlotFeature::onActionTriggered(bool isChecked) bool writeFiles = caf::Utils::getSaveDirectoryAndCheckOverwriteFiles(defaultDir, fileNames, &saveDir); if (!writeFiles) return; - RiaLogging::debug(QString("Writing to directory %!").arg(saveDir)); + RiaLogging::info(QString("Writing to directory %!").arg(saveDir)); for (RimWellLogPlot* wellLogPlot : selectedWellLogPlots) { QString fileName = saveDir + "/" + caf::Utils::makeValidFileBasename(wellLogPlot->description()) + ".ascii"; diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index 81612a8ed8..6c1a1b1d0a 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -240,7 +240,7 @@ void RigMainGrid::calculateFaults(const RigActiveCellInfo* activeCellInfo) if (hasFaultWithName(RimDefines::undefinedGridFaultName()) && hasFaultWithName(RimDefines::undefinedGridFaultWithInactiveName())) { - RiaLogging::debug(QString("Calculate faults already run for grid.")); + //RiaLogging::debug(QString("Calculate faults already run for grid.")); return; } m_faultsPrCellAcc = new RigFaultsPrCellAccumulator(m_cells.size()); diff --git a/ApplicationCode/ReservoirDataModel/RigWellLogExtractor.cpp b/ApplicationCode/ReservoirDataModel/RigWellLogExtractor.cpp index 8786191416..8475aefc88 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellLogExtractor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigWellLogExtractor.cpp @@ -20,6 +20,7 @@ #include "RigWellLogExtractor.h" #include "RigWellPath.h" #include "cvfTrace.h" +#include "RiaLogging.h" //-------------------------------------------------------------------------------------------------- /// @@ -202,7 +203,7 @@ void RigWellLogExtractor::populateReturnArrays(std::mapfirst.measuredDepth))); + RiaLogging::warning(QString("Well Log Extraction : ") + QString::fromStdString(m_wellCaseErrorMsgName) + (" Discards a point at MD: ") + QString::number((double)(it1->first.measuredDepth))); // Found that 8 to 10 is not connected, after finding 7 to 9 it1 = it21; // Discard 8 by Jumping to 10 @@ -211,7 +212,7 @@ void RigWellLogExtractor::populateReturnArrays(std::mapfirst.measuredDepth))); + RiaLogging::warning(QString("Well Log Extraction : ") + QString::fromStdString(m_wellCaseErrorMsgName) + (" Discards a point at MD: ") + QString::number((double)(it1->first.measuredDepth))); // Found that 10 to 11 is not connected, and not 10 to 12 either ++it1; // Discard 10 and jump to 11 and hope that recovers us From 5e14e566094951ebcb9224725a61d3f2a5f2023e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 27 Apr 2017 14:13:40 +0200 Subject: [PATCH 051/157] #1062 Use minimalistic title flags for dialogs --- .../Commands/ApplicationCommands/RicShowPlotDataFeature.cpp | 3 ++- ApplicationCode/UserInterface/RiuMultiCaseImportDialog.cpp | 2 +- ApplicationCode/UserInterface/RiuPropertyViewTabWidget.cpp | 2 +- Fwk/AppFwk/cafUserInterface/cafAboutDialog.cpp | 2 +- Fwk/VizFwk/LibGuiQt/cvfqtBasicAboutDialog.cpp | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp index d01b0c2226..da5bffebb5 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp @@ -103,7 +103,8 @@ void RiuQPlainTextEdit::slotSelectAll() /// /// //-------------------------------------------------------------------------------------------------- -RicTextWidget::RicTextWidget(QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint) +RicTextWidget::RicTextWidget(QWidget* parent) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint) { m_textEdit = new RiuQPlainTextEdit(this); m_textEdit->setReadOnly(true); diff --git a/ApplicationCode/UserInterface/RiuMultiCaseImportDialog.cpp b/ApplicationCode/UserInterface/RiuMultiCaseImportDialog.cpp index 7eafd19858..e7d6ea6389 100644 --- a/ApplicationCode/UserInterface/RiuMultiCaseImportDialog.cpp +++ b/ApplicationCode/UserInterface/RiuMultiCaseImportDialog.cpp @@ -76,7 +76,7 @@ private: /// //-------------------------------------------------------------------------------------------------- RiuMultiCaseImportDialog::RiuMultiCaseImportDialog(QWidget *parent /*= 0*/) - : QDialog(parent) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint) { ui = new Ui::RiuMultiCaseImportDialog; ui->setupUi(this); diff --git a/ApplicationCode/UserInterface/RiuPropertyViewTabWidget.cpp b/ApplicationCode/UserInterface/RiuPropertyViewTabWidget.cpp index ba2a5eeb07..4aa3cd5a86 100644 --- a/ApplicationCode/UserInterface/RiuPropertyViewTabWidget.cpp +++ b/ApplicationCode/UserInterface/RiuPropertyViewTabWidget.cpp @@ -32,7 +32,7 @@ /// //-------------------------------------------------------------------------------------------------- RiuPropertyViewTabWidget::RiuPropertyViewTabWidget(QWidget* parent, caf::PdmObject* object, const QString& windowTitle, const QStringList& uiConfigNameForTabs) - : QDialog(parent) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint) { setWindowTitle(windowTitle); diff --git a/Fwk/AppFwk/cafUserInterface/cafAboutDialog.cpp b/Fwk/AppFwk/cafUserInterface/cafAboutDialog.cpp index e75db01d57..ce5716554c 100644 --- a/Fwk/AppFwk/cafUserInterface/cafAboutDialog.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafAboutDialog.cpp @@ -60,7 +60,7 @@ namespace caf { /// //-------------------------------------------------------------------------------------------------- AboutDialog::AboutDialog(QWidget* parent) -: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint) { m_isCreated = false; diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtBasicAboutDialog.cpp b/Fwk/VizFwk/LibGuiQt/cvfqtBasicAboutDialog.cpp index d05f149cb5..765f19ee91 100644 --- a/Fwk/VizFwk/LibGuiQt/cvfqtBasicAboutDialog.cpp +++ b/Fwk/VizFwk/LibGuiQt/cvfqtBasicAboutDialog.cpp @@ -62,7 +62,7 @@ namespace cvfqt { /// //-------------------------------------------------------------------------------------------------- BasicAboutDialog::BasicAboutDialog(QWidget* parent) -: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint) { m_isCreated = false; From d05049af53871c62439cb1c227c4aa11f0e46a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Mon, 1 May 2017 08:38:00 +0200 Subject: [PATCH 052/157] #1414 Adjust margin for property view --- Fwk/AppFwk/cafUserInterface/cafPdmUiPropertyView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiPropertyView.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiPropertyView.cpp index 09326ee398..1f9408cd1b 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiPropertyView.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiPropertyView.cpp @@ -91,7 +91,7 @@ PdmUiPropertyView::PdmUiPropertyView(QWidget* parent, Qt::WindowFlags f) scrollArea->setWidget(m_placeholder); m_placeHolderLayout = new QVBoxLayout(); - m_placeHolderLayout->setContentsMargins(5,0,0,0); + m_placeHolderLayout->setContentsMargins(5,5,5,0); m_placeholder->setLayout(m_placeHolderLayout); QVBoxLayout* dummy = new QVBoxLayout(this); From f4aa49b31e23b9a759380939ba59d8f141c94a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Mon, 1 May 2017 20:13:13 +0200 Subject: [PATCH 053/157] #1006 Add legend control for well log file and well log extraction curves --- ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp | 1 + ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp index 1a2f41a4a8..8f97854bce 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp @@ -618,6 +618,7 @@ void RimWellLogExtractionCurve::defineUiOrdering(QString uiConfigName, caf::PdmU caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup("Curve Name"); nameGroup->setCollapsedByDefault(true); + nameGroup->add(&m_showLegend); RimPlotCurve::curveNameUiOrdering(*nameGroup); if (m_isUsingAutoName) diff --git a/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp index fcf1dab8b9..cd47b5849b 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp @@ -179,6 +179,7 @@ void RimWellLogFileCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiOrder RimPlotCurve::appearanceUiOrdering(*appearanceGroup); caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup("Curve Name"); + nameGroup->add(&m_showLegend); RimPlotCurve::curveNameUiOrdering(*nameGroup); } From 59d239cfab07ee41528a04e48955542794dd6dca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 2 May 2017 07:43:42 +0200 Subject: [PATCH 054/157] Add project tree context command on Simulaton Wells to create well log extraction curve --- ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 834191df57..1ed541ec64 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -333,6 +333,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection() } else if (dynamic_cast(uiItem)) { + commandIds << "RicNewWellLogCurveExtractionFeature"; commandIds << "RicNewSimWellIntersectionFeature"; commandIds << "RicShowWellAllocationPlotFeature"; } From 06bd9659be5817152b4c914ec8c14864189361ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Tue, 2 May 2017 09:35:08 +0200 Subject: [PATCH 055/157] Update icon for snapshot all plots to file --- ApplicationCode/Commands/RicSnapshotViewToClipboardFeature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/RicSnapshotViewToClipboardFeature.cpp b/ApplicationCode/Commands/RicSnapshotViewToClipboardFeature.cpp index 056314c980..05b198be5f 100644 --- a/ApplicationCode/Commands/RicSnapshotViewToClipboardFeature.cpp +++ b/ApplicationCode/Commands/RicSnapshotViewToClipboardFeature.cpp @@ -278,6 +278,6 @@ void RicSnapshotAllPlotsToFileFeature::onActionTriggered(bool isChecked) void RicSnapshotAllPlotsToFileFeature::setupActionLook(QAction* actionToSetup) { actionToSetup->setText("Snapshot All Plots To File"); - actionToSetup->setIcon(QIcon(":/SnapShotSave.png")); + actionToSetup->setIcon(QIcon(":/SnapShotSaveViews.png")); } From 7440b49e5bcbcbfc5b1ff4f8622c593cb59fae10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Tue, 2 May 2017 11:25:15 +0200 Subject: [PATCH 056/157] #1438 Rename tracer selection options to indicate all producers and/or selectors are used --- .../ProjectDataModel/RimEclipseResultDefinition.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index daf912c695..8b6497ec70 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -47,9 +47,9 @@ namespace caf template<> void RimEclipseResultDefinition::FlowTracerSelectionEnum::setUp() { - addItem(RimEclipseResultDefinition::FLOW_TR_INJ_AND_PROD, "FLOW_TR_INJ_AND_PROD", "Open Injectors and Producers"); - addItem(RimEclipseResultDefinition::FLOW_TR_PRODUCERS, "FLOW_TR_PRODUCERS", "Open Producers"); - addItem(RimEclipseResultDefinition::FLOW_TR_INJECTORS, "FLOW_TR_INJECTORS", "Open Injectors"); + addItem(RimEclipseResultDefinition::FLOW_TR_INJ_AND_PROD, "FLOW_TR_INJ_AND_PROD", "All Injectors and Producers"); + addItem(RimEclipseResultDefinition::FLOW_TR_PRODUCERS, "FLOW_TR_PRODUCERS", "All Producers"); + addItem(RimEclipseResultDefinition::FLOW_TR_INJECTORS, "FLOW_TR_INJECTORS", "All Injectors"); addItem(RimEclipseResultDefinition::FLOW_TR_BY_SELECTION, "FLOW_TR_BY_SELECTION", "By Selection"); setDefault(RimEclipseResultDefinition::FLOW_TR_INJ_AND_PROD); From 33468faa28717ffc1dc187b6598ffba520885c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 2 May 2017 12:03:15 +0200 Subject: [PATCH 057/157] Adjust headers in Advanced Snapshot Export dialog table --- .../RimMultiSnapshotDefinition.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimMultiSnapshotDefinition.cpp b/ApplicationCode/ProjectDataModel/RimMultiSnapshotDefinition.cpp index a01b2d574d..8234936beb 100644 --- a/ApplicationCode/ProjectDataModel/RimMultiSnapshotDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimMultiSnapshotDefinition.cpp @@ -62,16 +62,16 @@ RimMultiSnapshotDefinition::RimMultiSnapshotDefinition() CAF_PDM_InitFieldNoDefault(&view, "View", "View", "", "", ""); CAF_PDM_InitFieldNoDefault(&eclipseResultType, "EclipseResultType", "Result Type", "", "", ""); - CAF_PDM_InitFieldNoDefault(&selectedEclipseResults, "SelectedEclipseResults", "Result Name", "", "", ""); + CAF_PDM_InitFieldNoDefault(&selectedEclipseResults, "SelectedEclipseResults", "Properties", "", "", ""); - CAF_PDM_InitField(&timeStepStart, "TimeStepStart", 0, "Timestep Start", "", "", ""); - CAF_PDM_InitField(&timeStepEnd, "TimeStepEnd", 0, "Timestep End", "", "", ""); + CAF_PDM_InitField(&timeStepStart, "TimeStepStart", 0, "Start Time", "", "", ""); + CAF_PDM_InitField(&timeStepEnd, "TimeStepEnd", 0, "End Time", "", "", ""); - CAF_PDM_InitField(&sliceDirection, "SnapShotDirection", caf::AppEnum(NO_RANGEFILTER), "Range Filter direction", "", "", ""); - CAF_PDM_InitField(&startSliceIndex, "RangeFilterStart", 1, "RangeFilter Start", "", "", ""); - CAF_PDM_InitField(&endSliceIndex, "RangeFilterEnd", 1, "RangeFilter End", "", "", ""); + CAF_PDM_InitField(&sliceDirection, "SnapShotDirection", caf::AppEnum(NO_RANGEFILTER), "Range Filter Slice", "", "", ""); + CAF_PDM_InitField(&startSliceIndex, "RangeFilterStart", 1, "Range Start", "", "", ""); + CAF_PDM_InitField(&endSliceIndex, "RangeFilterEnd", 1, "Range End", "", "", ""); - CAF_PDM_InitFieldNoDefault(&additionalCases, "AdditionalCases", "Case List", "", "", ""); + CAF_PDM_InitFieldNoDefault(&additionalCases, "AdditionalCases", "Cases", "", "", ""); } //-------------------------------------------------------------------------------------------------- From 15d3e08f7047f404a88306344fbd582637b62ec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 2 May 2017 14:31:05 +0200 Subject: [PATCH 058/157] Adjust the TVD warning for LAS curves --- ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp index cd47b5849b..e6811a4ace 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp @@ -84,7 +84,7 @@ void RimWellLogFileCurve::onLoadDataAndUpdate() { if (RiaApplication::instance()->preferences()->showLasCurveWithoutTvdWarning()) { - QString tmp = QString("Display of True Vertical Depth (TVD) for LAS curves in not yet supported, and no LAS curve will be displayed in this mode.\n\n"); + QString tmp = QString("Display of True Vertical Depth (TVD) for LAS curves is not yet supported, and the LAS curve will be hidden in this mode.\n\n"); tmp += "Control display of this warning from \"Preferences->Show LAS curve without TVD warning\""; QMessageBox::warning(NULL, "LAS curve without TVD", tmp); From 3fc0a59f06eb7397228492582c9b3c350834ce36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 3 May 2017 12:31:45 +0200 Subject: [PATCH 059/157] #1444 Reallocate summary case file names when opening project --- .../ProjectDataModel/RimProject.cpp | 18 +++++++++--------- .../Summary/RimFileSummaryCase.cpp | 10 ++++++++++ .../Summary/RimFileSummaryCase.h | 1 + .../Summary/RimGridSummaryCase.cpp | 8 ++++++++ .../Summary/RimGridSummaryCase.h | 1 + .../ProjectDataModel/Summary/RimSummaryCase.h | 2 ++ .../Summary/RimSummaryCaseCollection.cpp | 11 +++++++++++ .../Summary/RimSummaryCaseCollection.h | 2 ++ 8 files changed, 44 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimProject.cpp b/ApplicationCode/ProjectDataModel/RimProject.cpp index 8502c277aa..f784c71e42 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationCode/ProjectDataModel/RimProject.cpp @@ -417,20 +417,20 @@ void RimProject::setProjectFileNameAndUpdateDependencies(const QString& fileName } // Update path to well path file cache - for (size_t oilFieldIdx = 0; oilFieldIdx < oilFields().size(); oilFieldIdx++) - { - RimOilField* oilField = oilFields[oilFieldIdx]; - if (oilField == NULL || oilField->wellPathCollection == NULL) continue; - oilField->wellPathCollection->updateFilePathsFromProjectPath(newProjectPath, oldProjectPath); - } - for(RimOilField* oilField: oilFields) { - if(oilField == NULL) continue; - if(oilField->formationNamesCollection() != NULL) + if (oilField == NULL) continue; + if (oilField->wellPathCollection() != NULL) + { + oilField->wellPathCollection()->updateFilePathsFromProjectPath(newProjectPath, oldProjectPath); + } + if (oilField->formationNamesCollection() != NULL) { oilField->formationNamesCollection()->updateFilePathsFromProjectPath(newProjectPath, oldProjectPath); } + if (oilField->summaryCaseCollection() != NULL) { + oilField->summaryCaseCollection()->updateFilePathsFromProjectPath(newProjectPath, oldProjectPath); + } } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimFileSummaryCase.cpp b/ApplicationCode/ProjectDataModel/Summary/RimFileSummaryCase.cpp index 41feed1223..101d485c0c 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimFileSummaryCase.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimFileSummaryCase.cpp @@ -17,6 +17,8 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimFileSummaryCase.h" +#include "RimTools.h" + #include "QFileInfo" @@ -71,3 +73,11 @@ QString RimFileSummaryCase::caseName() return caseFileName.completeBaseName(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFileSummaryCase::updateFilePathsFromProjectPath(const QString & newProjectPath, const QString & oldProjectPath) +{ + m_summaryHeaderFilename = RimTools::relocateFile(m_summaryHeaderFilename(), newProjectPath, oldProjectPath, nullptr, nullptr); +} diff --git a/ApplicationCode/ProjectDataModel/Summary/RimFileSummaryCase.h b/ApplicationCode/ProjectDataModel/Summary/RimFileSummaryCase.h index 88eedb07f8..64df13c198 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimFileSummaryCase.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimFileSummaryCase.h @@ -35,6 +35,7 @@ public: void setSummaryHeaderFilename(const QString& fileName); virtual QString summaryHeaderFilename() const override; virtual QString caseName() override; + virtual void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath) override; private: }; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimGridSummaryCase.cpp b/ApplicationCode/ProjectDataModel/Summary/RimGridSummaryCase.cpp index 248623cc2e..e0ed20797a 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimGridSummaryCase.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimGridSummaryCase.cpp @@ -154,3 +154,11 @@ QString RimGridSummaryCase::eclipseGridFileName() const return m_eclipseCase()->gridFileName(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridSummaryCase::updateFilePathsFromProjectPath(const QString & newProjectPath, const QString & oldProjectPath) +{ + // Shouldn't have to do anything +} + diff --git a/ApplicationCode/ProjectDataModel/Summary/RimGridSummaryCase.h b/ApplicationCode/ProjectDataModel/Summary/RimGridSummaryCase.h index 9baa242e5d..368b233333 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimGridSummaryCase.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimGridSummaryCase.h @@ -41,6 +41,7 @@ public: virtual QString summaryHeaderFilename() const override; virtual QString caseName() override; + virtual void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath) override; private: QString eclipseGridFileName() const; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.h index e572ffa1a5..009004f6d4 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.h @@ -48,6 +48,8 @@ public: void loadCase(); RigSummaryCaseData* caseData(); + virtual void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath) = 0; + protected: void updateTreeItemName(); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp index cbc4ffff3f..b9eba91efd 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp @@ -264,3 +264,14 @@ QString RimSummaryCaseCollection::uniqueShortNameForCase(RimSummaryCase* summary return shortName; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryCaseCollection::updateFilePathsFromProjectPath(const QString & newProjectPath, const QString & oldProjectPath) +{ + for (auto summaryCase : m_cases) + { + summaryCase->updateFilePathsFromProjectPath(newProjectPath, oldProjectPath); + } +} + diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h index 5eaaa731a1..14db31be05 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h @@ -47,6 +47,8 @@ public: QString uniqueShortNameForCase(RimSummaryCase* summaryCase); + void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath); + private: private: From cd8ad75db5823fde0629fd6e1cac10f8fabde028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 3 May 2017 13:39:36 +0200 Subject: [PATCH 060/157] #1445 Use correct colors in pie chart for well alloc plots in well flow mode --- .../Flow/RimWellAllocationPlot.cpp | 23 +++++++++++-------- .../Flow/RimWellAllocationPlot.h | 6 +++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp index 7691d9b018..1017d9cc1e 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp @@ -295,10 +295,10 @@ void RimWellAllocationPlot::updateFromWell() for ( const auto& tracerVal : totalTracerFractions ) { cvf::Color3f color; - if ( m_flowDiagSolution ) + if (m_flowDiagSolution) color = m_flowDiagSolution->tracerColor(tracerVal.first); else - color = cvf::Color3f::DARK_GRAY; + color = getTracerColor(tracerVal.first); double tracerPercent = 100*tracerVal.second; @@ -394,13 +394,7 @@ void RimWellAllocationPlot::addStackedCurve(const QString& tracerName, } else { - cvf::Color3f color = cvf::Color3f::DARK_GRAY; - - if (tracerName == RIG_FLOW_OIL_NAME) color = cvf::Color3f::DARK_GREEN; - if (tracerName == RIG_FLOW_GAS_NAME) color = cvf::Color3f::DARK_RED; - if (tracerName == RIG_FLOW_WATER_NAME) color = cvf::Color3f::BLUE; - - curve->setColor(color); + curve->setColor(getTracerColor(tracerName)); } plotTrack->addCurve(curve); @@ -767,4 +761,15 @@ QWidget* RimWellAllocationPlot::createViewWidget(QWidget* mainWindowParent) return m_wellAllocationPlotWidget; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Color3f RimWellAllocationPlot::getTracerColor(const QString& tracerName) +{ + + if (tracerName == RIG_FLOW_OIL_NAME) return cvf::Color3f::DARK_GREEN; + if (tracerName == RIG_FLOW_GAS_NAME) return cvf::Color3f::DARK_RED; + if (tracerName == RIG_FLOW_WATER_NAME) return cvf::Color3f::BLUE; + return cvf::Color3f::DARK_GRAY; +} diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h index 741edad7d2..b8261e7d05 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h @@ -37,6 +37,10 @@ class RiuWellAllocationPlot; class RimWellLogTrack; class RigSingleWellResultsData; +namespace cvf { + class Color3f; +} + namespace caf { class PdmOptionItemInfo; } @@ -111,6 +115,8 @@ private: virtual QWidget* createViewWidget(QWidget* mainWindowParent) override; virtual void deleteViewWidget() override; + cvf::Color3f getTracerColor(const QString& tracerName); + private: caf::PdmField m_showPlotTitle; caf::PdmField m_userName; From c845eefb96a42716d9069c8a396daa8859adb3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 3 May 2017 13:44:37 +0200 Subject: [PATCH 061/157] #1447 Moved Default Z Scale Factor to Default Settings --- ApplicationCode/Application/RiaPreferences.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 07e53e4d47..6816ab4cae 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -152,6 +152,7 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& defaultSettingsGroup->add(&defaultFaultGridLineColors); defaultSettingsGroup->add(&defaultWellLabelColor); defaultSettingsGroup->add(&fontSizeInScene); + defaultSettingsGroup->add(&defaultScaleFactorZ); caf::PdmUiGroup* viewsGroup = uiOrdering.addNewGroup("3D Views"); viewsGroup->add(&navigationPolicy); @@ -168,7 +169,6 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& else if (uiConfigName == m_tabNames[1]) { caf::PdmUiGroup* newCaseBehaviourGroup = uiOrdering.addNewGroup("Behavior When Loading Data"); - newCaseBehaviourGroup->add(&defaultScaleFactorZ); newCaseBehaviourGroup->add(&autocomputeDepthRelatedProperties); newCaseBehaviourGroup->add(&loadAndShowSoil); From a08dbc91ba92c2851b396318e0789ce142b23e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 4 May 2017 14:28:32 +0200 Subject: [PATCH 062/157] #1446 Ensure batch execution does not crash when closing ResInsight --- ApplicationCode/Application/RiaApplication.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 6cc13108d8..2436e0b9e8 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1399,7 +1399,8 @@ bool RiaApplication::parseArguments() std::vector gridFiles = readFileListFromTextFile(gridListFile); runMultiCaseSnapshots(projectFileName, gridFiles, "multiCaseSnapshots"); - closeProject(); + closeAllWindows(); + processEvents(); return false; } @@ -1552,7 +1553,8 @@ bool RiaApplication::parseArguments() } } - closeProject(); + closeAllWindows(); + processEvents(); } // Returning false will exit the application From 0664592ec8c75343d120124ac0d921fa7d3fa844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 5 May 2017 11:50:08 +0200 Subject: [PATCH 063/157] Move a method --- .../ReservoirDataModel/RigFlowDiagResults.cpp | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp b/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp index ce61f758ea..1261d74b61 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagResults.cpp @@ -258,6 +258,35 @@ std::vector* RigFlowDiagResults::calculateAverageTOFResult(const RigFlow } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFlowDiagResults::calculateSumOfFractionAndFractionMultTOF(size_t activeCellCount, + const std::vector *> & fractions, + const std::vector *> & TOFs, + std::vector *sumOfFractions, + std::vector *fractionMultTOF) +{ + sumOfFractions->resize(activeCellCount, 0.0); + fractionMultTOF->resize(activeCellCount, 0.0); + + for ( size_t iIdx = 0; iIdx < fractions.size() ; ++iIdx ) + { + const std::vector * frInj = fractions[iIdx]; + const std::vector * tofInj = TOFs[iIdx]; + + if ( ! (frInj && tofInj) ) continue; + + for ( size_t acIdx = 0 ; acIdx < activeCellCount; ++acIdx ) + { + if ( (*frInj)[acIdx] == HUGE_VAL ) continue; + + (*sumOfFractions)[acIdx] += (*frInj)[acIdx]; + (*fractionMultTOF)[acIdx] += (*frInj)[acIdx] * (*tofInj)[acIdx]; + } + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -434,35 +463,6 @@ RigFlowDiagResults::findNamedResultsForSelectedTracers(const RigFlowDiagResultAd } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigFlowDiagResults::calculateSumOfFractionAndFractionMultTOF(size_t activeCellCount, - const std::vector *> & fractions, - const std::vector *> & TOFs, - std::vector *sumOfFractions, - std::vector *fractionMultTOF) -{ - sumOfFractions->resize(activeCellCount, 0.0); - fractionMultTOF->resize(activeCellCount, 0.0); - - for ( size_t iIdx = 0; iIdx < fractions.size() ; ++iIdx ) - { - const std::vector * frInj = fractions[iIdx]; - const std::vector * tofInj = TOFs[iIdx]; - - if ( ! (frInj && tofInj) ) continue; - - for ( size_t acIdx = 0 ; acIdx < activeCellCount; ++acIdx ) - { - if ( (*frInj)[acIdx] == HUGE_VAL ) continue; - - (*sumOfFractions)[acIdx] += (*frInj)[acIdx]; - (*fractionMultTOF)[acIdx] += (*frInj)[acIdx] * (*tofInj)[acIdx]; - } - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- From 562afb1a7ab5663ec8fed7c891e8e6ef97ff7f5e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 3 May 2017 10:55:20 +0200 Subject: [PATCH 064/157] Add doc for well path part manager --- doc/well_path_part_manager.plantuml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 doc/well_path_part_manager.plantuml diff --git a/doc/well_path_part_manager.plantuml b/doc/well_path_part_manager.plantuml new file mode 100644 index 0000000000..7c5e7509b3 --- /dev/null +++ b/doc/well_path_part_manager.plantuml @@ -0,0 +1,23 @@ +@startuml + + + +RimView --> RivWellPathCollectionPartMgr + +RivWellPathCollectionPartMgr -* "N" RivWellPathPartMgr + +class RivWellPathPartMgr { +RimWellPath* m_wellPath +} + +class RimWellPath { +RimWellPathFractureCollection m_fractureCollection; +} + +class RimWellPathFractureCollection { +caf::PdmChildArrayField fractures; +} + + + +@enduml From a8e9cdbd1713de200d8f3f0bbee6eff05c08303f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 3 May 2017 15:02:53 +0200 Subject: [PATCH 065/157] AppFwk : Make sure edit flag is updated in PdmUiListEditor --- Fwk/AppFwk/cafUserInterface/cafPdmUiListEditor.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiListEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiListEditor.cpp index b9869b89d0..1b8e725f8c 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiListEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiListEditor.cpp @@ -186,6 +186,10 @@ void PdmUiListEditor::configureAndUpdateUi(const QString& uiConfigName) { m_isEditOperationsAvailable = false; } + else + { + m_isEditOperationsAvailable = true; + } PdmUiListEditorAttribute attributes; caf::PdmUiObjectHandle* uiObject = uiObj(field()->fieldHandle()->ownerObject()); From a8cab547a0a847814371d0cc9e1559821ad89556 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 5 May 2017 12:05:38 +0200 Subject: [PATCH 066/157] 1251 Added RivObjectSourceInfo for selecting any pdmObject --- .../ModelVisualization/CMakeLists_files.cmake | 2 + .../RivObjectSourceInfo.cpp | 38 ++++++++++++++++ .../ModelVisualization/RivObjectSourceInfo.h | 43 +++++++++++++++++++ .../ProjectDataModel/RimNamedObject.h | 2 +- .../UserInterface/RiuViewerCommands.cpp | 9 +++- 5 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 ApplicationCode/ModelVisualization/RivObjectSourceInfo.cpp create mode 100644 ApplicationCode/ModelVisualization/RivObjectSourceInfo.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index 53a89564b0..87798e377c 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -35,6 +35,7 @@ ${CEE_CURRENT_LIST_DIR}RivSingleCellPartGenerator.h ${CEE_CURRENT_LIST_DIR}RivSimWellPipeSourceInfo.h ${CEE_CURRENT_LIST_DIR}RivWellSpheresPartMgr.h ${CEE_CURRENT_LIST_DIR}RivPartPriority.h +${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.h ${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.h ) @@ -67,6 +68,7 @@ ${CEE_CURRENT_LIST_DIR}RivPipeQuadToSegmentMapper.cpp ${CEE_CURRENT_LIST_DIR}RivSingleCellPartGenerator.cpp ${CEE_CURRENT_LIST_DIR}RivSimWellPipeSourceInfo.cpp ${CEE_CURRENT_LIST_DIR}RivWellSpheresPartMgr.cpp +${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.cpp ${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.cpp ) diff --git a/ApplicationCode/ModelVisualization/RivObjectSourceInfo.cpp b/ApplicationCode/ModelVisualization/RivObjectSourceInfo.cpp new file mode 100644 index 0000000000..d42b13fcd3 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivObjectSourceInfo.cpp @@ -0,0 +1,38 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 - Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivObjectSourceInfo.h" + +#include "cafPdmObject.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivObjectSourceInfo::RivObjectSourceInfo(caf::PdmObject* object) + : m_object(object) +{ + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmObject* RivObjectSourceInfo::object() const +{ + return m_object; +} diff --git a/ApplicationCode/ModelVisualization/RivObjectSourceInfo.h b/ApplicationCode/ModelVisualization/RivObjectSourceInfo.h new file mode 100644 index 0000000000..837a417e24 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivObjectSourceInfo.h @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 - Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmPointer.h" + +#include "cvfBase.h" +#include "cvfObject.h" + +namespace caf { + class PdmObject; +} + +//================================================================================================== +/// +/// +//================================================================================================== +class RivObjectSourceInfo : public cvf::Object +{ +public: + RivObjectSourceInfo(caf::PdmObject* object); + + caf::PdmObject* object() const; + +private: + caf::PdmPointer m_object; +}; diff --git a/ApplicationCode/ProjectDataModel/RimNamedObject.h b/ApplicationCode/ProjectDataModel/RimNamedObject.h index 4836df2b75..6bd7578a55 100644 --- a/ApplicationCode/ProjectDataModel/RimNamedObject.h +++ b/ApplicationCode/ProjectDataModel/RimNamedObject.h @@ -40,7 +40,7 @@ public: protected: virtual caf::PdmFieldHandle* userDescriptionField() override; -private: +protected: caf::PdmField m_name; }; diff --git a/ApplicationCode/UserInterface/RiuViewerCommands.cpp b/ApplicationCode/UserInterface/RiuViewerCommands.cpp index f6dc88ae91..ce48b92831 100644 --- a/ApplicationCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationCode/UserInterface/RiuViewerCommands.cpp @@ -63,10 +63,11 @@ #include "RivFemPickSourceInfo.h" #include "RivIntersectionBoxSourceInfo.h" #include "RivIntersectionSourceInfo.h" +#include "RivObjectSourceInfo.h" +#include "RivSimWellPipeSourceInfo.h" #include "RivSourceInfo.h" #include "RivTernarySaturationOverlayItem.h" #include "RivWellPathSourceInfo.h" -#include "RivSimWellPipeSourceInfo.h" #include "cafCmdExecCommandManager.h" #include "cafCmdFeatureManager.h" @@ -520,12 +521,18 @@ void RiuViewerCommands::handlePickAction(int winPosX, int winPosY, Qt::KeyboardM if (firstHitPart && firstHitPart->sourceInfo()) { + const RivObjectSourceInfo* rivObjectSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivSourceInfo* rivSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivFemPickSourceInfo* femSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivIntersectionSourceInfo* crossSectionSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivIntersectionBoxSourceInfo* intersectionBoxSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); const RivSimWellPipeSourceInfo* eclipseWellSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); + if (rivObjectSourceInfo) + { + RiuMainWindow::instance()->selectAsCurrentItem(rivObjectSourceInfo->object()); + } + if (rivSourceInfo) { gridIndex = rivSourceInfo->gridIndex(); From 2dcf3c75f56513a844d1e099372ff32e0f6f3c52 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 5 May 2017 12:12:51 +0200 Subject: [PATCH 067/157] Fishbones : Propagate displayCoordTransform to well path part manager --- .../ModelVisualization/RivWellPathCollectionPartMgr.cpp | 5 +++-- .../ModelVisualization/RivWellPathCollectionPartMgr.h | 8 +++++++- ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp | 4 +++- ApplicationCode/ModelVisualization/RivWellPathPartMgr.h | 7 ++++++- ApplicationCode/ProjectDataModel/RimView.cpp | 3 ++- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp index c3f79c55a8..039f306272 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp @@ -67,7 +67,8 @@ void RivWellPathCollectionPartMgr::setScaleTransform(cvf::Transform * scaleTrans /// //-------------------------------------------------------------------------------------------------- void RivWellPathCollectionPartMgr::appendStaticGeometryPartsToModel(cvf::ModelBasicList* model, cvf::Vec3d displayModelOffset, - cvf::Transform* scaleTransform, double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox) + cvf::Transform* scaleTransform, double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox, + caf::DisplayCoordTransform* displayCoordTransform) { setScaleTransform(scaleTransform); @@ -78,7 +79,7 @@ void RivWellPathCollectionPartMgr::appendStaticGeometryPartsToModel(cvf::ModelBa { RivWellPathPartMgr* partMgr = m_wellPathCollection->wellPaths[wIdx]->partMgr(); partMgr->setScaleTransform(scaleTransform); - partMgr->appendStaticGeometryPartsToModel(model, displayModelOffset, characteristicCellSize, wellPathClipBoundingBox); + partMgr->appendStaticGeometryPartsToModel(model, displayModelOffset, characteristicCellSize, wellPathClipBoundingBox, displayCoordTransform); } } diff --git a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h index 6c8131905e..cf4fc4821d 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h @@ -38,6 +38,11 @@ namespace cvf class ModelBasicList; } +namespace caf +{ + class DisplayCoordTransform; +} + class RivWellPathCollectionPartMgr : public cvf::Object { @@ -54,7 +59,8 @@ public: cvf::Vec3d displayModelOffset, cvf::Transform* scaleTransform, double characteristicCellSize, - cvf::BoundingBox wellPathClipBoundingBox); + cvf::BoundingBox wellPathClipBoundingBox, + caf::DisplayCoordTransform* displayCoordTransform); private: caf::PdmPointer m_wellPathCollection; diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 2c594ed4c3..d47f955880 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -30,6 +30,7 @@ #include "RivPipeGeometryGenerator.h" #include "RivPartPriority.h" +#include "RivPipeGeometryGenerator.h" #include "RivWellPathSourceInfo.h" #include "cafEffectGenerator.h" @@ -232,7 +233,8 @@ void RivWellPathPartMgr::buildWellPathParts(cvf::Vec3d displayModelOffset, doubl /// //-------------------------------------------------------------------------------------------------- void RivWellPathPartMgr::appendStaticGeometryPartsToModel(cvf::ModelBasicList* model, cvf::Vec3d displayModelOffset, - double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox) + double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox, + caf::DisplayCoordTransform* displayCoordTransform) { RimWellPathCollection* wellPathCollection = NULL; m_rimWellPath->firstAncestorOrThisOfType(wellPathCollection); diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h index adffbb73bf..686af43003 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h @@ -33,6 +33,10 @@ namespace cvf class ScalarMapper; } +namespace caf { + class DisplayCoordTransform; +} + class RivPipeGeometryGenerator; class RimProject; class RimWellPath; @@ -48,7 +52,8 @@ public: void scheduleGeometryRegen() { m_needsTransformUpdate = true; }//printf("R"); } void appendStaticGeometryPartsToModel(cvf::ModelBasicList* model, cvf::Vec3d displayModelOffset, - double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox); + double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox, + caf::DisplayCoordTransform* displayCoordTransform); size_t segmentIndexFromTriangleIndex(size_t triangleIndex); diff --git a/ApplicationCode/ProjectDataModel/RimView.cpp b/ApplicationCode/ProjectDataModel/RimView.cpp index 70970875f4..66e6784fc2 100644 --- a/ApplicationCode/ProjectDataModel/RimView.cpp +++ b/ApplicationCode/ProjectDataModel/RimView.cpp @@ -699,7 +699,8 @@ void RimView::addWellPathsToModel(cvf::ModelBasicList* wellPathModelBasicList, displayModelOffset, scaleTransform, characteristicCellSize, - wellPathClipBoundingBox); + wellPathClipBoundingBox, + this->displayCoordTransform().p()); } wellPathModelBasicList->updateBoundingBoxesRecursive(); From 414733899e17e61f098455367990a900ba3c4e73 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 5 May 2017 11:21:40 +0200 Subject: [PATCH 068/157] Fishbones : Add model and visualization --- ApplicationCode/CMakeLists.txt | 3 + .../FishbonesCommands/CMakeLists_files.cmake | 23 + .../RicNewFishbonesSubsFeature.cpp | 87 ++++ .../RicNewFishbonesSubsFeature.h | 39 ++ .../Commands/RicDeleteItemFeature.cpp | 2 + .../ModelVisualization/CMakeLists_files.cmake | 7 +- .../RivFishbonesSubsPartMgr.cpp | 233 +++++++++++ .../RivFishbonesSubsPartMgr.h | 67 +++ .../RivWellConnectionsPartMgr.cpp | 2 +- .../ModelVisualization/RivWellPathPartMgr.cpp | 40 +- .../ModelVisualization/RivWellPathPartMgr.h | 13 +- .../Fishbones/CMakeLists_files.cmake | 23 + .../Fishbones/RimFishbonesMultipleSubs.cpp | 396 ++++++++++++++++++ .../Fishbones/RimFishbonesMultipleSubs.h | 106 +++++ .../RimContextCommandBuilder.cpp | 2 + .../ProjectDataModel/RimWellPath.cpp | 16 + .../ProjectDataModel/RimWellPath.h | 7 +- .../ReservoirDataModel/RigWellPath.cpp | 105 +++++ .../ReservoirDataModel/RigWellPath.h | 3 + 19 files changed, 1167 insertions(+), 7 deletions(-) create mode 100644 ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake create mode 100644 ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp create mode 100644 ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h create mode 100644 ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp create mode 100644 ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h create mode 100644 ApplicationCode/ProjectDataModel/Fishbones/CMakeLists_files.cmake create mode 100644 ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp create mode 100644 ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index c1ec89d9a5..de25a61c04 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -49,6 +49,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel ${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Summary ${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Flow + ${CMAKE_CURRENT_SOURCE_DIR}/ProjectDataModel/Fishbones ${CMAKE_CURRENT_SOURCE_DIR}/ResultStatisticsCache ${CMAKE_CURRENT_SOURCE_DIR}/ReservoirDataModel @@ -107,6 +108,7 @@ list( APPEND REFERENCED_CMAKE_FILES ProjectDataModel/CMakeLists_files.cmake ProjectDataModel/Summary/CMakeLists_files.cmake ProjectDataModel/Flow/CMakeLists_files.cmake + ProjectDataModel/Fishbones/CMakeLists_files.cmake GeoMech/GeoMechVisualization/CMakeLists_files.cmake @@ -121,6 +123,7 @@ list( APPEND REFERENCED_CMAKE_FILES Commands/CrossSectionCommands/CMakeLists_files.cmake Commands/EclipseCommands/CMakeLists_files.cmake Commands/EclipseCommands/EclipseWell/CMakeLists_files.cmake + Commands/FishbonesCommands/CMakeLists_files.cmake Commands/FlowCommands/CMakeLists_files.cmake Commands/IntersectionBoxCommands/CMakeLists_files.cmake Commands/OctaveScriptCommands/CMakeLists_files.cmake diff --git a/ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake new file mode 100644 index 0000000000..9017dfe068 --- /dev/null +++ b/ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake @@ -0,0 +1,23 @@ + +# Use this workaround until we're on 2.8.3 on all platforms and can use CMAKE_CURRENT_LIST_DIR directly +if (${CMAKE_VERSION} VERSION_GREATER "2.8.2") + set(CEE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_DIR}/) +endif() + +set (SOURCE_GROUP_HEADER_FILES +${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsFeature.h +) + +set (SOURCE_GROUP_SOURCE_FILES +${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsFeature.cpp +) + +list(APPEND CODE_HEADER_FILES +${SOURCE_GROUP_HEADER_FILES} +) + +list(APPEND CODE_SOURCE_FILES +${SOURCE_GROUP_SOURCE_FILES} +) + +source_group( "CommandFeature\\Fishbones" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CEE_CURRENT_LIST_DIR}CMakeLists_files.cmake ) diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp new file mode 100644 index 0000000000..e8ec34a36d --- /dev/null +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicNewFishbonesSubsFeature.h" + +#include "RimFishbonesMultipleSubs.h" +#include "RimWellPath.h" + +#include "RiuMainWindow.h" + +#include "cafSelectionManager.h" + +#include + + +CAF_CMD_SOURCE_INIT(RicNewFishbonesSubsFeature, "RicNewFishbonesSubsFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewFishbonesSubsFeature::onActionTriggered(bool isChecked) +{ + RimWellPath* wellPath = selectedWellPath(); + CVF_ASSERT(wellPath); + + RimFishbonesMultipleSubs* obj = new RimFishbonesMultipleSubs; + obj->setName(QString("Fishbones Subs (%1)").arg(wellPath->fishbonesSubs.size())); + wellPath->fishbonesSubs.push_back(obj); + + wellPath->updateConnectedEditors(); + RiuMainWindow::instance()->selectAsCurrentItem(obj); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPath* RicNewFishbonesSubsFeature::selectedWellPath() +{ + RimWellPath* wellPath = nullptr; + + caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem(); + + caf::PdmObjectHandle* objHandle = dynamic_cast(pdmUiItem); + if (objHandle) + { + objHandle->firstAncestorOrThisOfType(wellPath); + } + + return wellPath; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewFishbonesSubsFeature::setupActionLook(QAction* actionToSetup) +{ + //actionToSetup->setIcon(QIcon(":/FractureSymbol16x16.png")); + actionToSetup->setText("New Fishbones Subs Definition"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewFishbonesSubsFeature::isCommandEnabled() +{ + if (selectedWellPath()) + { + return true; + } + + return false; +} diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h new file mode 100644 index 0000000000..fc47d45cfc --- /dev/null +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h @@ -0,0 +1,39 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +class RimWellPath; + +//================================================================================================== +/// +//================================================================================================== +class RicNewFishbonesSubsFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; +protected: + + virtual void onActionTriggered(bool isChecked) override; + virtual void setupActionLook(QAction* actionToSetup) override; + virtual bool isCommandEnabled() override; + +private: + static RimWellPath* selectedWellPath(); +}; diff --git a/ApplicationCode/Commands/RicDeleteItemFeature.cpp b/ApplicationCode/Commands/RicDeleteItemFeature.cpp index 78a495e348..a982baf470 100644 --- a/ApplicationCode/Commands/RicDeleteItemFeature.cpp +++ b/ApplicationCode/Commands/RicDeleteItemFeature.cpp @@ -25,6 +25,7 @@ #include "RimEclipseInputProperty.h" #include "RimEclipsePropertyFilter.h" #include "RimEclipseView.h" +#include "RimFishbonesMultipleSubs.h" #include "RimFormationNames.h" #include "RimFormationNamesCollection.h" #include "RimGeoMechPropertyFilter.h" @@ -92,6 +93,7 @@ bool isDeletable(PdmUiItem * uiItem) if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; + if (dynamic_cast(uiItem)) return true; return false; } diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index 87798e377c..6213d8535b 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -35,9 +35,11 @@ ${CEE_CURRENT_LIST_DIR}RivSingleCellPartGenerator.h ${CEE_CURRENT_LIST_DIR}RivSimWellPipeSourceInfo.h ${CEE_CURRENT_LIST_DIR}RivWellSpheresPartMgr.h ${CEE_CURRENT_LIST_DIR}RivPartPriority.h +${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.h ${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.h ${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.h - +${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.h +${CEE_CURRENT_LIST_DIR}RivFishbonesSubsPartMgr.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -68,8 +70,11 @@ ${CEE_CURRENT_LIST_DIR}RivPipeQuadToSegmentMapper.cpp ${CEE_CURRENT_LIST_DIR}RivSingleCellPartGenerator.cpp ${CEE_CURRENT_LIST_DIR}RivSimWellPipeSourceInfo.cpp ${CEE_CURRENT_LIST_DIR}RivWellSpheresPartMgr.cpp +${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.cpp ${CEE_CURRENT_LIST_DIR}RivWellConnectionsPartMgr.cpp +${CEE_CURRENT_LIST_DIR}RivObjectSourceInfo.cpp +${CEE_CURRENT_LIST_DIR}RivFishbonesSubsPartMgr.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp new file mode 100644 index 0000000000..244247bce3 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp @@ -0,0 +1,233 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivFishbonesSubsPartMgr.h" + +#include "RigWellPath.h" + +#include "RimFishbonesMultipleSubs.h" +#include "RimWellPath.h" + +#include "RivObjectSourceInfo.h" +#include "RivPipeGeometryGenerator.h" + +#include "cafDisplayCoordTransform.h" +#include "cafEffectGenerator.h" + +#include "cvfDrawableGeo.h" +#include "cvfModelBasicList.h" +#include "cvfPart.h" +#include "cvfTransform.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivFishbonesSubsPartMgr::RivFishbonesSubsPartMgr(RimFishbonesMultipleSubs* subs) + : m_rimFishbonesSubs(subs) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivFishbonesSubsPartMgr::~RivFishbonesSubsPartMgr() +{ + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivFishbonesSubsPartMgr::appendGeometryPartsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize) +{ + clearGeometryCache(); + + if (!m_rimFishbonesSubs->isChecked()) return; + + if (m_parts.size() == 0) + { + buildParts(displayCoordTransform, characteristicCellSize); + } + + for (auto part : m_parts) + { + model->addPart(part.p()); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivFishbonesSubsPartMgr::clearGeometryCache() +{ + m_parts.clear(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivFishbonesSubsPartMgr::buildParts(caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize) +{ + std::vector locationOfSubs = m_rimFishbonesSubs->locationOfSubs(); + + RimWellPath* wellPath = nullptr; + m_rimFishbonesSubs->firstAncestorOrThisOfTypeAsserted(wellPath); + + RigWellPath* rigWellPath = wellPath->wellPathGeometry(); + + RivPipeGeometryGenerator geoGenerator; + geoGenerator.setRadius(m_rimFishbonesSubs->tubingRadius()); + + for (size_t instanceIndex = 0; instanceIndex < locationOfSubs.size(); instanceIndex++) + { + double measuredDepth = locationOfSubs[instanceIndex]; + + cvf::Vec3d position = rigWellPath->interpolatedPointAlongWellPath(measuredDepth); + + cvf::Vec3d p1 = cvf::Vec3d::UNDEFINED; + cvf::Vec3d p2 = cvf::Vec3d::UNDEFINED; + rigWellPath->twoClosestPoints(position, &p1, &p2); + + if (!p1.isUndefined() && !p2.isUndefined()) + { + std::vector lateralLengths = m_rimFishbonesSubs->lateralLengths(); + cvf::Mat4d buildAngleRotationMatrix; + + for (size_t i = 0; i < lateralLengths.size(); i++) + { + cvf::Vec3d lateralDirection; + { + cvf::Vec3d alongWellPath = (p2 - p1).getNormalized(); + cvf::Vec3d lateralInitialDirection = cvf::Vec3d::Z_AXIS; + { + double intialRotationAngle = m_rimFishbonesSubs->rotationAngle(instanceIndex); + double lateralOffsetDegrees = 360.0 / lateralLengths.size(); + + double lateralOffsetRadians = cvf::Math::toRadians(intialRotationAngle + lateralOffsetDegrees * i); + + cvf::Mat4d lateralOffsetMatrix = cvf::Mat4d::fromRotation(alongWellPath, lateralOffsetRadians); + + lateralInitialDirection = lateralInitialDirection.getTransformedVector(lateralOffsetMatrix); + } + + cvf::Vec3d rotationAxis; + rotationAxis.cross(alongWellPath, lateralInitialDirection); + + double exitAngleRadians = cvf::Math::toRadians(m_rimFishbonesSubs->exitAngle()); + cvf::Mat4d lateralRotationMatrix = cvf::Mat4d::fromRotation(rotationAxis, exitAngleRadians); + + lateralDirection = alongWellPath.getTransformedVector(lateralRotationMatrix); + + double buildAngleRadians = cvf::Math::toRadians(m_rimFishbonesSubs->buildAngle()); + buildAngleRotationMatrix = cvf::Mat4d::fromRotation(rotationAxis, buildAngleRadians); + } + + std::vector domainCoords; + + // Compute coordinates along the lateral by modifying the lateral direction by the build angle for + // every unit vector along the lateral + { + cvf::Vec3d accumulatedPosition = position; + double accumulatedLength = 0.0; + while (accumulatedLength < lateralLengths[i]) + { + domainCoords.push_back(accumulatedPosition); + + double delta = 1.0; + + if (lateralLengths[i] - accumulatedLength < 1.0) + { + delta = lateralLengths[i] - accumulatedLength; + } + + accumulatedPosition += delta * lateralDirection; + + // Modify the lateral direction by the build angle for each unit vector + lateralDirection = lateralDirection.getTransformedVector(buildAngleRotationMatrix); + + accumulatedLength += delta; + } + + // Add the last accumulated position if it is not present + if (domainCoords.back() != accumulatedPosition) + { + domainCoords.push_back(accumulatedPosition); + } + } + + std::vector displayCoords; + for (auto domainCoord : domainCoords) + { + displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(domainCoord)); + } + + cylinderWithCenterLineParts(&m_parts, displayCoords, wellPath->wellPathColor(), wellPath->combinedScaleFactor() * characteristicCellSize * 0.5); + + cvf::ref objectSourceInfo = new RivObjectSourceInfo(m_rimFishbonesSubs); + + for (auto p : m_parts) + { + p->setSourceInfo(objectSourceInfo.p()); + } + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivFishbonesSubsPartMgr::cylinderWithCenterLineParts(cvf::Collection* destinationParts, const std::vector& centerCoords, const cvf::Color3f& color, double radius) +{ + cvf::ref geoGenerator = new RivPipeGeometryGenerator; + geoGenerator->setRadius(radius); + geoGenerator->setCrossSectionVertexCount(12); + + cvf::ref cvfCoords = new cvf::Vec3dArray(centerCoords); + geoGenerator->setPipeCenterCoords(cvfCoords.p()); + + cvf::ref surfaceGeo = geoGenerator->createPipeSurface(); + if (surfaceGeo.notNull()) + { + cvf::Part* part = new cvf::Part; + part->setDrawable(surfaceGeo.p()); + + caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(color), caf::PO_1); + cvf::ref eff = surfaceGen.generateCachedEffect(); + + part->setEffect(eff.p()); + + destinationParts->push_back(part); + } + + cvf::ref centerLineGeo = geoGenerator->createCenterLine(); + if (centerLineGeo.notNull()) + { + cvf::Part* part = new cvf::Part; + part->setDrawable(centerLineGeo.p()); + + caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(color), caf::PO_1); + cvf::ref eff = surfaceGen.generateCachedEffect(); + + part->setEffect(eff.p()); + + destinationParts->push_back(part); + } +} + diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h new file mode 100644 index 0000000000..8a28a7bc07 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h @@ -0,0 +1,67 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmPointer.h" + +#include "cvfBase.h" +#include "cvfMatrix4.h" +#include "cvfObject.h" +#include "cvfVector3.h" + +#include "cvfCollection.h" +#include "cvfColor3.h" + + +namespace cvf +{ + class ModelBasicList; + class DrawableGeo; + class Part; + class Transform; +} + +namespace caf +{ + class DisplayCoordTransform; +} + +class RimFishbonesMultipleSubs; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RivFishbonesSubsPartMgr : public cvf::Object +{ +public: + RivFishbonesSubsPartMgr(RimFishbonesMultipleSubs* subs); + ~RivFishbonesSubsPartMgr(); + + void appendGeometryPartsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize); + void clearGeometryCache(); + +private: + void buildParts(caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize); + + static void cylinderWithCenterLineParts(cvf::Collection* destinationParts, const std::vector& centerCoords, const cvf::Color3f& color, double radius); + +private: + caf::PdmPointer m_rimFishbonesSubs; + cvf::Collection m_parts; +}; diff --git a/ApplicationCode/ModelVisualization/RivWellConnectionsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellConnectionsPartMgr.cpp index 2f22b6e803..f5a1fe8d7e 100644 --- a/ApplicationCode/ModelVisualization/RivWellConnectionsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellConnectionsPartMgr.cpp @@ -351,4 +351,4 @@ cvf::ref< cvf::DrawableGeo> RivWellConnectionsPartMgr::createArrowGeometry(const geo->computeNormals(); return geo; -} \ No newline at end of file +} diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index d47f955880..14e4bb3b13 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -25,10 +25,11 @@ #include "RigWellPath.h" +#include "RimFishbonesMultipleSubs.h" #include "RimWellPath.h" #include "RimWellPathCollection.h" -#include "RivPipeGeometryGenerator.h" +#include "RivFishbonesSubsPartMgr.h" #include "RivPartPriority.h" #include "RivPipeGeometryGenerator.h" #include "RivWellPathSourceInfo.h" @@ -83,6 +84,31 @@ RivWellPathPartMgr::~RivWellPathPartMgr() clearAllBranchData(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivWellPathPartMgr::appendFishbonesPartsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize) +{ + if (!m_rimWellPath) return; + + // This concept is taken from RivReservoirSimWellsPartMgr, and is required to be able to have + // separate part managers for each view + if (m_fishbonesPartMgrs.size() != m_rimWellPath->fishbonesSubs().size()) + { + m_fishbonesPartMgrs.clear(); + + for (auto rimFishboneSubs : m_rimWellPath->fishbonesSubs()) + { + m_fishbonesPartMgrs.push_back(new RivFishbonesSubsPartMgr(rimFishboneSubs)); + } + } + + for (auto rivFishbonesPartManager : m_fishbonesPartMgrs) + { + rivFishbonesPartManager->appendGeometryPartsToModel(model, displayCoordTransform, characteristicCellSize); + } +} + //-------------------------------------------------------------------------------------------------- /// The pipe geometry needs to be rebuilt on scale change to keep the pipes round //-------------------------------------------------------------------------------------------------- @@ -268,6 +294,8 @@ void RivWellPathPartMgr::appendStaticGeometryPartsToModel(cvf::ModelBasicList* m { model->addPart(m_wellLabelPart.p()); } + + appendFishbonesPartsToModel(model, displayCoordTransform, characteristicCellSize); } //-------------------------------------------------------------------------------------------------- @@ -282,6 +310,16 @@ void RivWellPathPartMgr::setScaleTransform( cvf::Transform * scaleTransform ) } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivWellPathPartMgr::scheduleGeometryRegen() +{ + m_needsTransformUpdate = true; + + m_fishbonesPartMgrs.clear(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h index 686af43003..df60feadb6 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h @@ -22,6 +22,7 @@ #include "cafPdmPointer.h" #include "cvfBoundingBox.h" +#include "cvfCollection.h" namespace cvf { @@ -40,6 +41,7 @@ namespace caf { class RivPipeGeometryGenerator; class RimProject; class RimWellPath; +class RivFishbonesSubsPartMgr; class RivWellPathPartMgr : public cvf::Object { @@ -49,7 +51,7 @@ public: void setScaleTransform(cvf::Transform * scaleTransform); - void scheduleGeometryRegen() { m_needsTransformUpdate = true; }//printf("R"); } + void scheduleGeometryRegen(); void appendStaticGeometryPartsToModel(cvf::ModelBasicList* model, cvf::Vec3d displayModelOffset, double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox, @@ -57,14 +59,17 @@ public: size_t segmentIndexFromTriangleIndex(size_t triangleIndex); +private: + void appendFishbonesPartsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize); + void buildWellPathParts(cvf::Vec3d displayModelOffset, double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox); + void clearAllBranchData(); + private: caf::PdmPointer m_rimWellPath; cvf::ref m_scaleTransform; bool m_needsTransformUpdate; - void buildWellPathParts(cvf::Vec3d displayModelOffset, double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox); - void clearAllBranchData(); struct RivPipeBranchData { cvf::ref m_pipeGeomGenerator; @@ -80,4 +85,6 @@ private: cvf::ref m_scalarMapper; cvf::ref m_scalarMapperSurfaceEffect; cvf::ref m_scalarMapperMeshEffect; + + cvf::Collection m_fishbonesPartMgrs; }; diff --git a/ApplicationCode/ProjectDataModel/Fishbones/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/Fishbones/CMakeLists_files.cmake new file mode 100644 index 0000000000..3487f95ce0 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/Fishbones/CMakeLists_files.cmake @@ -0,0 +1,23 @@ + +# Use this workaround until we're on 2.8.3 on all platforms and can use CMAKE_CURRENT_LIST_DIR directly +if (${CMAKE_VERSION} VERSION_GREATER "2.8.2") + set(CEE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_DIR}/) +endif() + +set (SOURCE_GROUP_HEADER_FILES +${CEE_CURRENT_LIST_DIR}RimFishbonesMultipleSubs.h +) + +set (SOURCE_GROUP_SOURCE_FILES +${CEE_CURRENT_LIST_DIR}RimFishbonesMultipleSubs.cpp +) + +list(APPEND CODE_HEADER_FILES +${SOURCE_GROUP_HEADER_FILES} +) + +list(APPEND CODE_SOURCE_FILES +${SOURCE_GROUP_SOURCE_FILES} +) + +source_group( "ProjectDataModel\\Fishbones" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CEE_CURRENT_LIST_DIR}CMakeLists_files.cmake ) diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp new file mode 100644 index 0000000000..41e48122e2 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp @@ -0,0 +1,396 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimFishbonesMultipleSubs.h" + +#include "RimProject.h" + +#include "cafPdmUiListEditor.h" + +#include "cvfAssert.h" + +#include +#include +#include + + +CAF_PDM_SOURCE_INIT(RimFishbonesMultipleSubs, "FishbonesMultipleSubs"); + +namespace caf { + template<> + void AppEnum::setUp() + { + addItem(RimFishbonesMultipleSubs::FB_SUB_COUNT_END, "FB_SUB_COUNT", "Start/End/Count"); + addItem(RimFishbonesMultipleSubs::FB_SUB_SPACING_END, "FB_SUB_SPACING", "Start/End/Spacing"); + addItem(RimFishbonesMultipleSubs::FB_SUB_USER_DEFINED, "FB_SUB_CUSTOM", "User Specification"); + setDefault(RimFishbonesMultipleSubs::FB_SUB_USER_DEFINED); + } + + template<> + void AppEnum::setUp() + { + addItem(RimFishbonesMultipleSubs::FB_LATERAL_ORIENTATION_FIXED, "FB_LATERAL_ORIENTATION_FIXED", "Fixed Angle"); + addItem(RimFishbonesMultipleSubs::FB_LATERAL_ORIENTATION_RANDOM, "FB_LATERAL_ORIENTATION_RANDOM", "Random Angle"); + setDefault(RimFishbonesMultipleSubs::FB_LATERAL_ORIENTATION_RANDOM); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFishbonesMultipleSubs::RimFishbonesMultipleSubs() +{ + CAF_PDM_InitObject("FishbonesMultipleSubs", ":/Default.png", "", ""); + + CAF_PDM_InitField(&m_lateralCountPerSub, "LateralCountPerSub", size_t(3), "Count Per Sub", "", "", ""); + CAF_PDM_InitField(&m_lateralLength, "LateralLength", QString("12.0"), "Length(s) [m]", "", "Specify multiple length values if the sub lengths differ", ""); + + CAF_PDM_InitField(&m_lateralExitAngle, "LateralExitAngle", 35.0, "Exit Angle [deg]", "", "", ""); + CAF_PDM_InitField(&m_lateralBuildAngle, "LateralBuildAngle", 5.0, "Build Angle [deg/m]", "", "", ""); + + CAF_PDM_InitField(&m_lateralHoleRadius, "LateralHoleRadius", 12.0, "Hole Radius [mm]", "", "", ""); + CAF_PDM_InitField(&m_lateralTubingRadius, "LateralTubingRadius", 8.0, "Tubing Radius [mm]", "", "", ""); + + CAF_PDM_InitField(&m_lateralOpenHoleRoghnessFactor, "LateralOpenHoleRoghnessFactor", 0.001, "Open Hole Roghness Factor [m]", "", "", ""); + CAF_PDM_InitField(&m_lateralTubingRoghnessFactor, "LateralTubingRoghnessFactor", 1e-5, "Tubing Roghness Factor [m]", "", "", ""); + + CAF_PDM_InitField(&m_lateralLengthFraction, "LateralLengthFraction", 100.0, "Length Fraction [0..1]", "", "", ""); + CAF_PDM_InitField(&m_lateralInstallFraction, "LateralInstallFraction", 100.0, "Install Fraction [0..1]", "", "", ""); + + CAF_PDM_InitField(&m_icdCount, "IcdCount", size_t(2), "ICD Count", "", "", ""); + CAF_PDM_InitField(&m_icdOrificeRadius, "IcdOrificeRadius", 8.0, "ICD Orifice Radius [mm]", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&m_locationOfSubs, "LocationOfSubs", "Measured Depths [m]", "", "", ""); + m_locationOfSubs.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName()); + + CAF_PDM_InitField(&m_subsLocationMode, "SubsLocationMode", caf::AppEnum(FB_SUB_USER_DEFINED), "Location Defined By", "", "", ""); + CAF_PDM_InitField(&m_rangeStart, "RangeStart", 100.0, "Start [m]", "", "", ""); + CAF_PDM_InitField(&m_rangeEnd, "RangeEnd", 250.0, "End [m]", "", "", ""); + CAF_PDM_InitField(&m_rangeSubSpacing, "RangeSubSpacing", 40.0, "Spacing [m]", "", "", ""); + CAF_PDM_InitField(&m_rangeSubCount, "RangeSubCount", size_t(25), "Count", "", "", ""); + + CAF_PDM_InitField(&m_subsOrientationMode, "SubsOrientationMode", caf::AppEnum(FB_LATERAL_ORIENTATION_RANDOM), "Orientation", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&m_installationRotationAngles, "InstallationRotationAngles", "Installation Rotation Angles [deg]", "", "", ""); + m_installationRotationAngles.uiCapability()->setUiHidden(true); + CAF_PDM_InitField(&m_fixedInstallationRotationAngle, "FixedInstallationRotationAngle", 0.0, " Fixed Angle [deg]", "", "", ""); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFishbonesMultipleSubs::~RimFishbonesMultipleSubs() +{ + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimFishbonesMultipleSubs::locationOfSubs() const +{ + return m_locationOfSubs; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFishbonesMultipleSubs::rotationAngle(size_t index) const +{ + if (m_subsOrientationMode == FB_LATERAL_ORIENTATION_FIXED) + { + return m_fixedInstallationRotationAngle; + } + else + { + CVF_ASSERT(index < m_installationRotationAngles().size()); + + return m_installationRotationAngles()[index]; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFishbonesMultipleSubs::exitAngle() const +{ + return m_lateralExitAngle; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFishbonesMultipleSubs::buildAngle() const +{ + return m_lateralBuildAngle; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFishbonesMultipleSubs::tubingRadius() const +{ + return m_lateralTubingRadius; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFishbonesMultipleSubs::lateralCountPerSub() const +{ + return m_lateralCountPerSub; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimFishbonesMultipleSubs::lateralLengths() const +{ + QStringList items = m_lateralLength().split(' '); + double currentLength = 0.0; + + std::vector lengths; + for (int i = 0; i < static_cast(m_lateralCountPerSub); i++) + { + if (i < items.size()) + { + bool conversionOk = false; + double candidateValue = items[i].toDouble(&conversionOk); + if (conversionOk) + { + currentLength = candidateValue; + } + } + + lengths.push_back(currentLength); + } + + return lengths; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFishbonesMultipleSubs::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + bool recomputeLocations = false; + + if (changedField == &m_subsLocationMode) + { + if (m_subsLocationMode == FB_SUB_COUNT_END || m_subsLocationMode == FB_SUB_SPACING_END) + { + recomputeLocations = true; + } + } + + if (changedField == &m_rangeStart || + changedField == &m_rangeEnd || + changedField == &m_rangeSubCount || + changedField == &m_rangeSubSpacing) + { + recomputeLocations = true; + } + + if (recomputeLocations) + { + if (m_subsLocationMode == FB_SUB_COUNT_END) + { + size_t divisor = 1; + if (m_rangeSubCount > 2) divisor = m_rangeSubCount - 1; + + m_rangeSubSpacing = fabs(m_rangeStart - m_rangeEnd) / divisor; + } + else if (m_subsLocationMode == FB_SUB_SPACING_END) + { + m_rangeSubCount = (fabs(m_rangeStart - m_rangeEnd) / m_rangeSubSpacing) + 1; + + if (m_rangeSubCount < 1) + { + m_rangeSubCount = 1; + } + } + + if (m_subsLocationMode == FB_SUB_COUNT_END || m_subsLocationMode == FB_SUB_SPACING_END) + { + std::vector measuredDepths = locationsFromStartSpacingAndCount(m_rangeStart, m_rangeSubSpacing, m_rangeSubCount); + m_locationOfSubs = measuredDepths; + } + } + + if (recomputeLocations || + changedField == &m_locationOfSubs || + changedField == &m_subsOrientationMode) + { + m_installationRotationAngles.v().clear(); + + recomputeIntallationRotationAngles(); + } + + RimProject* proj; + this->firstAncestorOrThisOfTypeAsserted(proj); + proj->createDisplayModelAndRedrawAllViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFishbonesMultipleSubs::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + uiOrdering.add(&m_name); // From RimNamedObject + + { + caf::PdmUiGroup* group = uiOrdering.addNewGroup("Location"); + + group->add(&m_subsLocationMode); + if (m_subsLocationMode() != FB_SUB_USER_DEFINED) + { + group->add(&m_rangeStart); + group->add(&m_rangeEnd); + + if (m_subsLocationMode() == FB_SUB_COUNT_END) + { + group->add(&m_rangeSubCount); + group->add(&m_rangeSubSpacing); + } + else if (m_subsLocationMode() == FB_SUB_SPACING_END) + { + group->add(&m_rangeSubSpacing); + group->add(&m_rangeSubCount); + } + } + + group->add(&m_locationOfSubs); + } + + { + caf::PdmUiGroup* group = uiOrdering.addNewGroup("Lateral Configuration"); + + group->add(&m_lateralCountPerSub); + group->add(&m_lateralLength); + + group->add(&m_lateralExitAngle); + group->add(&m_lateralBuildAngle); + + group->add(&m_subsOrientationMode); + if (m_subsOrientationMode == FB_LATERAL_ORIENTATION_FIXED) + { + group->add(&m_fixedInstallationRotationAngle); + } + + caf::PdmUiGroup* successGroup = group->addNewGroup("Installation Success Factors"); + successGroup->add(&m_lateralLengthFraction); + successGroup->add(&m_lateralInstallFraction); + + caf::PdmUiGroup* mswGroup = group->addNewGroup("Multi Segment Wells"); + mswGroup->setCollapsedByDefault(true); + mswGroup->add(&m_lateralHoleRadius); + mswGroup->add(&m_lateralTubingRadius); + mswGroup->add(&m_lateralOpenHoleRoghnessFactor); + mswGroup->add(&m_lateralTubingRoghnessFactor); + mswGroup->add(&m_icdCount); + mswGroup->add(&m_icdOrificeRadius); + } + + // Visibility + + if (m_subsLocationMode == FB_SUB_USER_DEFINED) + { + m_locationOfSubs.uiCapability()->setUiReadOnly(false); + + m_rangeSubSpacing.uiCapability()->setUiReadOnly(true); + m_rangeSubCount.uiCapability()->setUiReadOnly(true); + m_rangeStart.uiCapability()->setUiReadOnly(true); + m_rangeEnd.uiCapability()->setUiReadOnly(true); + } + else + { + m_locationOfSubs.uiCapability()->setUiReadOnly(true); + + m_rangeSubSpacing.uiCapability()->setUiReadOnly(false); + m_rangeSubCount.uiCapability()->setUiReadOnly(false); + m_rangeStart.uiCapability()->setUiReadOnly(false); + m_rangeEnd.uiCapability()->setUiReadOnly(false); + + if (m_subsLocationMode == FB_SUB_COUNT_END) + { + m_rangeSubSpacing.uiCapability()->setUiReadOnly(true); + m_rangeSubCount.uiCapability()->setUiReadOnly(false); + } + else + { + m_rangeSubSpacing.uiCapability()->setUiReadOnly(false); + m_rangeSubCount.uiCapability()->setUiReadOnly(true); + } + } + + uiOrdering.skipRemainingFields(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFishbonesMultipleSubs::initAfterRead() +{ + if (m_locationOfSubs().size() != m_installationRotationAngles().size()) + { + recomputeIntallationRotationAngles(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFishbonesMultipleSubs::recomputeIntallationRotationAngles() +{ + std::vector vals; + + for (size_t i = 0; i < m_locationOfSubs().size(); i++) + { + vals.push_back(RimFishbonesMultipleSubs::randomValue(0, 360)); + } + + m_installationRotationAngles = vals; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimFishbonesMultipleSubs::locationsFromStartSpacingAndCount(double start, double spacing, size_t count) +{ + std::vector measuredDepths; + + for (size_t i = 0; i < count; i++) + { + measuredDepths.push_back(start + spacing * i); + } + + return measuredDepths; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RimFishbonesMultipleSubs::randomValue(int min, int max) +{ + int range = abs(max - min); + int random_integer = min + int(range*rand() / (RAND_MAX + 1.0)); + + return random_integer; +} + diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h new file mode 100644 index 0000000000..78d94ccbbf --- /dev/null +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -0,0 +1,106 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimCheckableNamedObject.h" + + + +//================================================================================================== +/// +/// +//================================================================================================== +class RimFishbonesMultipleSubs : public RimCheckableNamedObject +{ + CAF_PDM_HEADER_INIT; + +public: + enum LocationType + { + FB_SUB_COUNT_END, + FB_SUB_SPACING_END, + FB_SUB_USER_DEFINED + }; + + enum LateralsOrientationType + { + FB_LATERAL_ORIENTATION_FIXED, + FB_LATERAL_ORIENTATION_RANDOM + }; + +public: + RimFishbonesMultipleSubs(); + virtual ~RimFishbonesMultipleSubs(); + + std::vector locationOfSubs() const; + + double rotationAngle(size_t index) const; + double exitAngle() const; + double buildAngle() const; + + double tubingRadius() const; + double lateralCountPerSub() const; + std::vector lateralLengths() const; + + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; + +protected: + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; + virtual void initAfterRead() override; + +private: + void recomputeIntallationRotationAngles(); + + static std::vector locationsFromStartSpacingAndCount(double start, double spacing, size_t count); + static int randomValue(int min, int max); + +private: + caf::PdmField m_lateralCountPerSub; + caf::PdmField m_lateralLength; + + caf::PdmField m_lateralExitAngle; + caf::PdmField m_lateralBuildAngle; + + caf::PdmField m_lateralHoleRadius; + caf::PdmField m_lateralTubingRadius; + + caf::PdmField m_lateralOpenHoleRoghnessFactor; + caf::PdmField m_lateralTubingRoghnessFactor; + + caf::PdmField m_lateralLengthFraction; + caf::PdmField m_lateralInstallFraction; + + caf::PdmField m_icdCount; + caf::PdmField m_icdOrificeRadius; + + caf::PdmField > m_subsLocationMode; + caf::PdmField m_rangeStart; + caf::PdmField m_rangeEnd; + caf::PdmField m_rangeSubSpacing; + caf::PdmField m_rangeSubCount; + + caf::PdmField > m_subsOrientationMode; + + + caf::PdmField> m_locationOfSubs; // Given in measured depth + + caf::PdmField> m_installationRotationAngles; + caf::PdmField m_fixedInstallationRotationAngle; + +}; diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 1ed541ec64..f6fb1498d5 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -394,6 +394,8 @@ QStringList RimContextCommandBuilder::commandsFromSelection() commandIds << "RicShowTotalAllocationDataFeature"; commandIds << "RicSummaryCurveSwitchAxisFeature"; + + commandIds << "RicNewFishbonesSubsFeature"; // Work in progress -- End diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index b64df06551..fea8f08a74 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -32,6 +32,8 @@ #include "RimWellLogPlotCollection.h" #include "RimWellPathCollection.h" +#include "RimFishbonesMultipleSubs.h" + #include "RiuMainWindow.h" #include "RivWellPathPartMgr.h" @@ -101,6 +103,9 @@ RimWellPath::RimWellPath() CAF_PDM_InitFieldNoDefault(&m_wellLogFile, "WellLogFile", "Well Log File", "", "", ""); m_wellLogFile.uiCapability()->setUiHidden(true); + CAF_PDM_InitFieldNoDefault(&fishbonesSubs, "FishbonesSubs", "fishbonesSubs", "", "", ""); + fishbonesSubs.uiCapability()->setUiHidden(true); + m_wellPath = NULL; } @@ -421,6 +426,17 @@ void RimWellPath::updateFilePathsFromProjectPath(const QString& newProjectPath, } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimWellPath::combinedScaleFactor() const +{ + RimWellPathCollection* wellPathColl = nullptr; + this->firstAncestorOrThisOfTypeAsserted(wellPathColl); + + return this->wellPathRadiusScaleFactor() * wellPathColl->wellPathRadiusScaleFactor(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index 253ffaeaab..e9aa47fd93 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -29,6 +29,7 @@ // Include to make Pdm work for cvf::Color #include "cafPdmFieldCvfColor.h" +#include "cafPdmChildArrayField.h" #include "cvfObject.h" class RifWellPathAsciiFileReader; @@ -37,6 +38,8 @@ class RimProject; class RimWellLogFile; class RivWellPathPartMgr; +class RimFishbonesMultipleSubs; + //================================================================================================== /// /// @@ -70,12 +73,14 @@ public: caf::PdmChildField m_wellLogFile; RigWellPath* wellPathGeometry(); + caf::PdmChildArrayField fishbonesSubs; + RivWellPathPartMgr* partMgr(); bool readWellPathFile(QString * errorMessage, RifWellPathAsciiFileReader* asciiReader); void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath); - + double combinedScaleFactor() const; private: diff --git a/ApplicationCode/ReservoirDataModel/RigWellPath.cpp b/ApplicationCode/ReservoirDataModel/RigWellPath.cpp index 7c84a68612..72dcab590a 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellPath.cpp +++ b/ApplicationCode/ReservoirDataModel/RigWellPath.cpp @@ -18,6 +18,8 @@ #include "RigWellPath.h" +#include "cvfGeometryTools.h" + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -52,3 +54,106 @@ double RigWellPath::datumElevation() const return m_datumElevation; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RigWellPath::interpolatedPointAlongWellPath(double measuredDepth) +{ + cvf::Vec3d wellPathPoint = cvf::Vec3d::ZERO; + + size_t i = 0; + while (i < m_measuredDepths.size() && m_measuredDepths.at(i) < measuredDepth ) + { + i++; + } + + if (m_measuredDepths.size() > i) + { + if (i == 0) + { + //For measuredDepth same or lower than first point, use this first point + wellPathPoint = m_wellPathPoints.at(0); + } + else + { + //Do interpolation + double stepsize = (measuredDepth - m_measuredDepths.at(i-1)) / + (m_measuredDepths.at(i) - m_measuredDepths.at(i - 1)); + wellPathPoint = m_wellPathPoints.at(i - 1) + stepsize * (m_wellPathPoints.at(i) - m_wellPathPoints.at(i-1)); + } + } + else + { + //Use endpoint if measuredDepth same or higher than last point + wellPathPoint = m_wellPathPoints.at(i-1); + } + + + return wellPathPoint; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigWellPath::wellPathAzimuthAngle(const cvf::Vec3d& position) const +{ + double azimuthAngle = 0.0; + + cvf::Vec3d p1 = cvf::Vec3d::UNDEFINED; + cvf::Vec3d p2 = cvf::Vec3d::UNDEFINED; + + twoClosestPoints(position, &p1, &p2); + if (!p1.isUndefined() && !p2.isUndefined()) + { + cvf::Vec3d direction = p1 - p2; + + if (abs(direction.x()) > 1e-5) + { + double atanValue = direction.y() / direction.x(); + azimuthAngle = atan(atanValue); + azimuthAngle = cvf::Math::toDegrees(azimuthAngle); + azimuthAngle = -azimuthAngle; + } + } + + return azimuthAngle; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigWellPath::twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2) const +{ + CVF_ASSERT(p1 && p2); + + size_t closestIndex = cvf::UNDEFINED_SIZE_T; + double closestDistance = cvf::UNDEFINED_DOUBLE; + + for (size_t i = 1; i < m_wellPathPoints.size(); i++) + { + cvf::Vec3d p1 = m_wellPathPoints[i - 1]; + cvf::Vec3d p2 = m_wellPathPoints[i - 0]; + + double candidateDistance = cvf::GeometryTools::linePointSquareDist(p1, p2, position); + if (candidateDistance < closestDistance) + { + closestDistance = candidateDistance; + closestIndex = i; + } + } + + if (closestIndex != cvf::UNDEFINED_DOUBLE) + { + if (closestIndex > 0) + { + *p1 = m_wellPathPoints[closestIndex - 1]; + *p2 = m_wellPathPoints[closestIndex - 0]; + } + else + { + *p1 = m_wellPathPoints[closestIndex + 1]; + *p2 = m_wellPathPoints[closestIndex + 0]; + } + } +} + diff --git a/ApplicationCode/ReservoirDataModel/RigWellPath.h b/ApplicationCode/ReservoirDataModel/RigWellPath.h index d77cf8e77e..8c08a6acf6 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellPath.h +++ b/ApplicationCode/ReservoirDataModel/RigWellPath.h @@ -40,6 +40,9 @@ public: void setDatumElevation(double value); bool hasDatumElevation() const; double datumElevation() const; + cvf::Vec3d interpolatedPointAlongWellPath(double measuredDepth); + double wellPathAzimuthAngle(const cvf::Vec3d& position) const; + void twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2) const; private: bool m_hasDatumElevation; From 710236f7f590491b2bbfe17decfe7b76a1d899db Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 5 May 2017 13:32:50 +0200 Subject: [PATCH 069/157] #1450 Use x-axis as lateral start axis if well path is close to z-axis --- .../RivFishbonesSubsPartMgr.cpp | 45 ++++++++++++++++++- .../RivFishbonesSubsPartMgr.h | 2 + 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp index 244247bce3..0ac351084e 100644 --- a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp @@ -90,10 +90,10 @@ void RivFishbonesSubsPartMgr::buildParts(caf::DisplayCoordTransform* displayCoor m_rimFishbonesSubs->firstAncestorOrThisOfTypeAsserted(wellPath); RigWellPath* rigWellPath = wellPath->wellPathGeometry(); - + RivPipeGeometryGenerator geoGenerator; geoGenerator.setRadius(m_rimFishbonesSubs->tubingRadius()); - + for (size_t instanceIndex = 0; instanceIndex < locationOfSubs.size(); instanceIndex++) { double measuredDepth = locationOfSubs[instanceIndex]; @@ -114,7 +114,15 @@ void RivFishbonesSubsPartMgr::buildParts(caf::DisplayCoordTransform* displayCoor cvf::Vec3d lateralDirection; { cvf::Vec3d alongWellPath = (p2 - p1).getNormalized(); + cvf::Vec3d lateralInitialDirection = cvf::Vec3d::Z_AXIS; + + if (RivFishbonesSubsPartMgr::closestMainAxis(alongWellPath) == cvf::Vec3d::Z_AXIS) + { + // Use x-axis if well path is heading close to z-axis + lateralInitialDirection = cvf::Vec3d::X_AXIS; + } + { double intialRotationAngle = m_rimFishbonesSubs->rotationAngle(instanceIndex); double lateralOffsetDegrees = 360.0 / lateralLengths.size(); @@ -231,3 +239,36 @@ void RivFishbonesSubsPartMgr::cylinderWithCenterLineParts(cvf::Collection maxValue) + { + maxComponent = 1; + maxValue = cvf::Math::abs(vec.y()); + } + + if (cvf::Math::abs(vec.z()) > maxValue) + { + maxComponent = 2; + maxValue = cvf::Math::abs(vec.z()); + } + + if (maxComponent == 0) + { + return cvf::Vec3d::X_AXIS; + } + else if (maxComponent == 1) + { + return cvf::Vec3d::Y_AXIS; + } + else if (maxComponent == 2) + { + return cvf::Vec3d::Z_AXIS; + } +} + diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h index 8a28a7bc07..e09e1faef6 100644 --- a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h @@ -61,6 +61,8 @@ private: static void cylinderWithCenterLineParts(cvf::Collection* destinationParts, const std::vector& centerCoords, const cvf::Color3f& color, double radius); + static cvf::Vec3d closestMainAxis(const cvf::Vec3d& vec); + private: caf::PdmPointer m_rimFishbonesSubs; cvf::Collection m_parts; From f326d5e2a38277b0d409913e9e2088da1b484f21 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 5 May 2017 13:45:07 +0200 Subject: [PATCH 070/157] #1441 Add skin factor and rename UI --- .../Fishbones/RimFishbonesMultipleSubs.cpp | 51 +++++++++++-------- .../Fishbones/RimFishbonesMultipleSubs.h | 2 + 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp index 41e48122e2..d86aa0bcfc 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp @@ -35,7 +35,7 @@ namespace caf { template<> void AppEnum::setUp() { - addItem(RimFishbonesMultipleSubs::FB_SUB_COUNT_END, "FB_SUB_COUNT", "Start/End/Count"); + addItem(RimFishbonesMultipleSubs::FB_SUB_COUNT_END, "FB_SUB_COUNT", "Start/End/Number of Subs"); addItem(RimFishbonesMultipleSubs::FB_SUB_SPACING_END, "FB_SUB_SPACING", "Start/End/Spacing"); addItem(RimFishbonesMultipleSubs::FB_SUB_USER_DEFINED, "FB_SUB_CUSTOM", "User Specification"); setDefault(RimFishbonesMultipleSubs::FB_SUB_USER_DEFINED); @@ -58,7 +58,7 @@ RimFishbonesMultipleSubs::RimFishbonesMultipleSubs() { CAF_PDM_InitObject("FishbonesMultipleSubs", ":/Default.png", "", ""); - CAF_PDM_InitField(&m_lateralCountPerSub, "LateralCountPerSub", size_t(3), "Count Per Sub", "", "", ""); + CAF_PDM_InitField(&m_lateralCountPerSub, "LateralCountPerSub", size_t(3), "Laterals Per Sub", "", "", ""); CAF_PDM_InitField(&m_lateralLength, "LateralLength", QString("12.0"), "Length(s) [m]", "", "Specify multiple length values if the sub lengths differ", ""); CAF_PDM_InitField(&m_lateralExitAngle, "LateralExitAngle", 35.0, "Exit Angle [deg]", "", "", ""); @@ -70,8 +70,9 @@ RimFishbonesMultipleSubs::RimFishbonesMultipleSubs() CAF_PDM_InitField(&m_lateralOpenHoleRoghnessFactor, "LateralOpenHoleRoghnessFactor", 0.001, "Open Hole Roghness Factor [m]", "", "", ""); CAF_PDM_InitField(&m_lateralTubingRoghnessFactor, "LateralTubingRoghnessFactor", 1e-5, "Tubing Roghness Factor [m]", "", "", ""); - CAF_PDM_InitField(&m_lateralLengthFraction, "LateralLengthFraction", 100.0, "Length Fraction [0..1]", "", "", ""); - CAF_PDM_InitField(&m_lateralInstallFraction, "LateralInstallFraction", 100.0, "Install Fraction [0..1]", "", "", ""); + CAF_PDM_InitField(&m_lateralLengthFraction, "LateralLengthFraction", 0.8, "Length Fraction [0..1]", "", "", ""); + CAF_PDM_InitField(&m_lateralInstallFraction, "LateralInstallFraction", 0.7, "Install Fraction [0..1]", "", "", ""); + CAF_PDM_InitField(&m_skinFactor, "SkinFactor", 1.0, "Skin Factor [0..1]", "", "", ""); CAF_PDM_InitField(&m_icdCount, "IcdCount", size_t(2), "ICD Count", "", "", ""); CAF_PDM_InitField(&m_icdOrificeRadius, "IcdOrificeRadius", 8.0, "ICD Orifice Radius [mm]", "", "", ""); @@ -80,10 +81,10 @@ RimFishbonesMultipleSubs::RimFishbonesMultipleSubs() m_locationOfSubs.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName()); CAF_PDM_InitField(&m_subsLocationMode, "SubsLocationMode", caf::AppEnum(FB_SUB_USER_DEFINED), "Location Defined By", "", "", ""); - CAF_PDM_InitField(&m_rangeStart, "RangeStart", 100.0, "Start [m]", "", "", ""); - CAF_PDM_InitField(&m_rangeEnd, "RangeEnd", 250.0, "End [m]", "", "", ""); + CAF_PDM_InitField(&m_rangeStart, "RangeStart", 100.0, "Start MD [m]", "", "", ""); + CAF_PDM_InitField(&m_rangeEnd, "RangeEnd", 250.0, "End MD [m]", "", "", ""); CAF_PDM_InitField(&m_rangeSubSpacing, "RangeSubSpacing", 40.0, "Spacing [m]", "", "", ""); - CAF_PDM_InitField(&m_rangeSubCount, "RangeSubCount", size_t(25), "Count", "", "", ""); + CAF_PDM_InitField(&m_rangeSubCount, "RangeSubCount", size_t(25), "Number of Subs", "", "", ""); CAF_PDM_InitField(&m_subsOrientationMode, "SubsOrientationMode", caf::AppEnum(FB_LATERAL_ORIENTATION_RANDOM), "Orientation", "", "", ""); @@ -279,27 +280,37 @@ void RimFishbonesMultipleSubs::defineUiOrdering(QString uiConfigName, caf::PdmUi } { - caf::PdmUiGroup* group = uiOrdering.addNewGroup("Lateral Configuration"); + caf::PdmUiGroup* lateralConfigGroup = uiOrdering.addNewGroup("Lateral Configuration"); - group->add(&m_lateralCountPerSub); - group->add(&m_lateralLength); + lateralConfigGroup->add(&m_lateralCountPerSub); + lateralConfigGroup->add(&m_lateralLength); - group->add(&m_lateralExitAngle); - group->add(&m_lateralBuildAngle); + lateralConfigGroup->add(&m_lateralExitAngle); + lateralConfigGroup->add(&m_lateralBuildAngle); - group->add(&m_subsOrientationMode); + lateralConfigGroup->add(&m_subsOrientationMode); if (m_subsOrientationMode == FB_LATERAL_ORIENTATION_FIXED) { - group->add(&m_fixedInstallationRotationAngle); + lateralConfigGroup->add(&m_fixedInstallationRotationAngle); } - caf::PdmUiGroup* successGroup = group->addNewGroup("Installation Success Factors"); - successGroup->add(&m_lateralLengthFraction); - successGroup->add(&m_lateralInstallFraction); - - caf::PdmUiGroup* mswGroup = group->addNewGroup("Multi Segment Wells"); + { + caf::PdmUiGroup* wellGroup = lateralConfigGroup->addNewGroup("Well Properties"); + + wellGroup->add(&m_lateralHoleRadius); + wellGroup->add(&m_skinFactor); + } + + { + caf::PdmUiGroup* successGroup = lateralConfigGroup->addNewGroup("Installation Success Fractions"); + successGroup->add(&m_lateralLengthFraction); + successGroup->add(&m_lateralInstallFraction); + } + } + + { + caf::PdmUiGroup* mswGroup = uiOrdering.addNewGroup("Multi Segment Wells"); mswGroup->setCollapsedByDefault(true); - mswGroup->add(&m_lateralHoleRadius); mswGroup->add(&m_lateralTubingRadius); mswGroup->add(&m_lateralOpenHoleRoghnessFactor); mswGroup->add(&m_lateralTubingRoghnessFactor); diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h index 78d94ccbbf..4b8591835d 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -77,6 +77,8 @@ private: caf::PdmField m_lateralExitAngle; caf::PdmField m_lateralBuildAngle; + caf::PdmField m_skinFactor; + caf::PdmField m_lateralHoleRadius; caf::PdmField m_lateralTubingRadius; From 2d4e4b47b35dd867072da9948a3eedc5679418b9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 5 May 2017 13:45:07 +0200 Subject: [PATCH 071/157] #1441 Add skin factor and rename UI --- .../Fishbones/RimFishbonesMultipleSubs.cpp | 14 +++++--------- .../Fishbones/RimFishbonesMultipleSubs.h | 15 +++++---------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp index d86aa0bcfc..322d64d13b 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp @@ -24,8 +24,6 @@ #include "cvfAssert.h" -#include -#include #include @@ -238,9 +236,7 @@ void RimFishbonesMultipleSubs::fieldChangedByUi(const caf::PdmFieldHandle* chang changedField == &m_locationOfSubs || changedField == &m_subsOrientationMode) { - m_installationRotationAngles.v().clear(); - - recomputeIntallationRotationAngles(); + computeRotationAngles(); } RimProject* proj; @@ -360,20 +356,20 @@ void RimFishbonesMultipleSubs::initAfterRead() { if (m_locationOfSubs().size() != m_installationRotationAngles().size()) { - recomputeIntallationRotationAngles(); + computeRotationAngles(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFishbonesMultipleSubs::recomputeIntallationRotationAngles() +void RimFishbonesMultipleSubs::computeRotationAngles() { std::vector vals; for (size_t i = 0; i < m_locationOfSubs().size(); i++) { - vals.push_back(RimFishbonesMultipleSubs::randomValue(0, 360)); + vals.push_back(RimFishbonesMultipleSubs::randomValueFromRange(0, 360)); } m_installationRotationAngles = vals; @@ -397,7 +393,7 @@ std::vector RimFishbonesMultipleSubs::locationsFromStartSpacingAndCount( //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -int RimFishbonesMultipleSubs::randomValue(int min, int max) +int RimFishbonesMultipleSubs::randomValueFromRange(int min, int max) { int range = abs(max - min); int random_integer = min + int(range*rand() / (RAND_MAX + 1.0)); diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h index 4b8591835d..1c41bc510b 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -20,8 +20,6 @@ #include "RimCheckableNamedObject.h" - - //================================================================================================== /// /// @@ -58,17 +56,16 @@ public: double lateralCountPerSub() const; std::vector lateralLengths() const; - virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; - protected: - virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; - virtual void initAfterRead() override; + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; + virtual void initAfterRead() override; private: - void recomputeIntallationRotationAngles(); + void computeRotationAngles(); static std::vector locationsFromStartSpacingAndCount(double start, double spacing, size_t count); - static int randomValue(int min, int max); + static int randomValueFromRange(int min, int max); private: caf::PdmField m_lateralCountPerSub; @@ -99,10 +96,8 @@ private: caf::PdmField > m_subsOrientationMode; - caf::PdmField> m_locationOfSubs; // Given in measured depth caf::PdmField> m_installationRotationAngles; caf::PdmField m_fixedInstallationRotationAngle; - }; From dce5f801912ccdc28a712a84cf76bb2055fcf639 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 5 May 2017 14:50:54 +0200 Subject: [PATCH 072/157] Fix signed/unsighed compare --- .../ProjectDataModel/RimWellLogExtractionCurve.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp index 8f97854bce..7182c85e2b 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp @@ -316,7 +316,7 @@ void RimWellLogExtractionCurve::onLoadDataAndUpdate() } else { - if (m_branchIndex >= 0 && m_branchIndex < m_generatedSimulationWellPathBranches.size() ) + if (m_branchIndex >= 0 && m_branchIndex < static_cast(m_generatedSimulationWellPathBranches.size()) ) { eclExtractor = wellLogCollection->findOrCreateSimWellExtractor(m_simWellName, eclipseCase->caseUserDescription(), @@ -554,7 +554,7 @@ QList RimWellLogExtractionCurve::calculateValueOptions(c size_t branchCount = m_generatedSimulationWellPathBranches.size(); - for ( int bIdx = 0; bIdx < branchCount; ++bIdx) + for ( int bIdx = 0; bIdx < static_cast(branchCount); ++bIdx) { options.push_back(caf::PdmOptionItemInfo("Branch " + QString::number(bIdx + 1), QVariant::fromValue(bIdx) )); } From a85883228c1cb389d530163e526ccb2b90d27797 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 5 May 2017 15:09:22 +0200 Subject: [PATCH 073/157] Fishbones : Extract method for computing lateral coords --- .../RivFishbonesSubsPartMgr.cpp | 79 +++++++++++-------- .../RivFishbonesSubsPartMgr.h | 10 ++- 2 files changed, 52 insertions(+), 37 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp index 0ac351084e..d8a8510a05 100644 --- a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp @@ -146,41 +146,11 @@ void RivFishbonesSubsPartMgr::buildParts(caf::DisplayCoordTransform* displayCoor buildAngleRotationMatrix = cvf::Mat4d::fromRotation(rotationAxis, buildAngleRadians); } - std::vector domainCoords; - - // Compute coordinates along the lateral by modifying the lateral direction by the build angle for - // every unit vector along the lateral - { - cvf::Vec3d accumulatedPosition = position; - double accumulatedLength = 0.0; - while (accumulatedLength < lateralLengths[i]) - { - domainCoords.push_back(accumulatedPosition); - - double delta = 1.0; - - if (lateralLengths[i] - accumulatedLength < 1.0) - { - delta = lateralLengths[i] - accumulatedLength; - } - - accumulatedPosition += delta * lateralDirection; - - // Modify the lateral direction by the build angle for each unit vector - lateralDirection = lateralDirection.getTransformedVector(buildAngleRotationMatrix); - - accumulatedLength += delta; - } - - // Add the last accumulated position if it is not present - if (domainCoords.back() != accumulatedPosition) - { - domainCoords.push_back(accumulatedPosition); - } - } + std::vector lateralDomainCoords = + RivFishbonesSubsPartMgr::computeLateralCoords(position, lateralLengths[i], lateralDirection, buildAngleRotationMatrix); std::vector displayCoords; - for (auto domainCoord : domainCoords) + for (auto domainCoord : lateralDomainCoords) { displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(domainCoord)); } @@ -198,6 +168,47 @@ void RivFishbonesSubsPartMgr::buildParts(caf::DisplayCoordTransform* displayCoor } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RivFishbonesSubsPartMgr::computeLateralCoords(const cvf::Vec3d& startCoord, double lateralLength, const cvf::Vec3d& lateralStartDirection, const cvf::Mat4d& buildAngleRotationMatrix) +{ + std::vector coords; + + cvf::Vec3d lateralDirection(lateralStartDirection); + + // Compute coordinates along the lateral by modifying the lateral direction by the build angle for + // every unit vector along the lateral + cvf::Vec3d accumulatedPosition = startCoord; + double accumulatedLength = 0.0; + while (accumulatedLength < lateralLength) + { + coords.push_back(accumulatedPosition); + + double delta = 1.0; + + if (lateralLength - accumulatedLength < 1.0) + { + delta = lateralLength - accumulatedLength; + } + + accumulatedPosition += delta * lateralDirection; + + // Modify the lateral direction by the build angle for each unit vector + lateralDirection = lateralDirection.getTransformedVector(buildAngleRotationMatrix); + + accumulatedLength += delta; + } + + // Add the last accumulated position if it is not present + if (coords.back() != accumulatedPosition) + { + coords.push_back(accumulatedPosition); + } + + return coords; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -266,7 +277,7 @@ cvf::Vec3d RivFishbonesSubsPartMgr::closestMainAxis(const cvf::Vec3d& vec) { return cvf::Vec3d::Y_AXIS; } - else if (maxComponent == 2) + else { return cvf::Vec3d::Z_AXIS; } diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h index e09e1faef6..867b781020 100644 --- a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h @@ -58,12 +58,16 @@ public: private: void buildParts(caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize); - + + static std::vector computeLateralCoords(const cvf::Vec3d& startCoord, + double lateralLength, const cvf::Vec3d& lateralStartDirection, + const cvf::Mat4d& buildAngleRotationMatrix); + static void cylinderWithCenterLineParts(cvf::Collection* destinationParts, const std::vector& centerCoords, const cvf::Color3f& color, double radius); static cvf::Vec3d closestMainAxis(const cvf::Vec3d& vec); private: - caf::PdmPointer m_rimFishbonesSubs; - cvf::Collection m_parts; + caf::PdmPointer m_rimFishbonesSubs; + cvf::Collection m_parts; }; From b0c5ceeab66151b452f0f9cbe7ee51fe8d2ac6ad Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 May 2017 07:54:02 +0200 Subject: [PATCH 074/157] #1442 Moved geometry functions to RigFishbonesGeometry --- .../RivFishbonesSubsPartMgr.cpp | 152 ++------------ .../RivFishbonesSubsPartMgr.h | 6 - .../Fishbones/RimFishbonesMultipleSubs.cpp | 19 ++ .../Fishbones/RimFishbonesMultipleSubs.h | 12 ++ .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../RigFishbonesGeometry.cpp | 187 ++++++++++++++++++ .../ReservoirDataModel/RigFishbonesGeometry.h | 56 ++++++ 7 files changed, 288 insertions(+), 146 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.h diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp index d8a8510a05..b3bf2ebb56 100644 --- a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp @@ -84,131 +84,36 @@ void RivFishbonesSubsPartMgr::clearGeometryCache() //-------------------------------------------------------------------------------------------------- void RivFishbonesSubsPartMgr::buildParts(caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize) { - std::vector locationOfSubs = m_rimFishbonesSubs->locationOfSubs(); - RimWellPath* wellPath = nullptr; m_rimFishbonesSubs->firstAncestorOrThisOfTypeAsserted(wellPath); - RigWellPath* rigWellPath = wellPath->wellPathGeometry(); - RivPipeGeometryGenerator geoGenerator; geoGenerator.setRadius(m_rimFishbonesSubs->tubingRadius()); - for (size_t instanceIndex = 0; instanceIndex < locationOfSubs.size(); instanceIndex++) + for (size_t subIndex = 0; subIndex < m_rimFishbonesSubs->locationOfSubs().size(); subIndex++) { - double measuredDepth = locationOfSubs[instanceIndex]; - - cvf::Vec3d position = rigWellPath->interpolatedPointAlongWellPath(measuredDepth); - - cvf::Vec3d p1 = cvf::Vec3d::UNDEFINED; - cvf::Vec3d p2 = cvf::Vec3d::UNDEFINED; - rigWellPath->twoClosestPoints(position, &p1, &p2); - - if (!p1.isUndefined() && !p2.isUndefined()) + for (size_t lateralIndex = 0; lateralIndex < m_rimFishbonesSubs->lateralLengths().size(); lateralIndex++) { - std::vector lateralLengths = m_rimFishbonesSubs->lateralLengths(); - cvf::Mat4d buildAngleRotationMatrix; + std::vector lateralDomainCoords = m_rimFishbonesSubs->coordsForLateral(subIndex, lateralIndex); - for (size_t i = 0; i < lateralLengths.size(); i++) + std::vector displayCoords; + for (auto domainCoord : lateralDomainCoords) { - cvf::Vec3d lateralDirection; - { - cvf::Vec3d alongWellPath = (p2 - p1).getNormalized(); + displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(domainCoord)); + } - cvf::Vec3d lateralInitialDirection = cvf::Vec3d::Z_AXIS; + cylinderWithCenterLineParts(&m_parts, displayCoords, wellPath->wellPathColor(), wellPath->combinedScaleFactor() * characteristicCellSize * 0.5); - if (RivFishbonesSubsPartMgr::closestMainAxis(alongWellPath) == cvf::Vec3d::Z_AXIS) - { - // Use x-axis if well path is heading close to z-axis - lateralInitialDirection = cvf::Vec3d::X_AXIS; - } + cvf::ref objectSourceInfo = new RivObjectSourceInfo(m_rimFishbonesSubs); - { - double intialRotationAngle = m_rimFishbonesSubs->rotationAngle(instanceIndex); - double lateralOffsetDegrees = 360.0 / lateralLengths.size(); - - double lateralOffsetRadians = cvf::Math::toRadians(intialRotationAngle + lateralOffsetDegrees * i); - - cvf::Mat4d lateralOffsetMatrix = cvf::Mat4d::fromRotation(alongWellPath, lateralOffsetRadians); - - lateralInitialDirection = lateralInitialDirection.getTransformedVector(lateralOffsetMatrix); - } - - cvf::Vec3d rotationAxis; - rotationAxis.cross(alongWellPath, lateralInitialDirection); - - double exitAngleRadians = cvf::Math::toRadians(m_rimFishbonesSubs->exitAngle()); - cvf::Mat4d lateralRotationMatrix = cvf::Mat4d::fromRotation(rotationAxis, exitAngleRadians); - - lateralDirection = alongWellPath.getTransformedVector(lateralRotationMatrix); - - double buildAngleRadians = cvf::Math::toRadians(m_rimFishbonesSubs->buildAngle()); - buildAngleRotationMatrix = cvf::Mat4d::fromRotation(rotationAxis, buildAngleRadians); - } - - std::vector lateralDomainCoords = - RivFishbonesSubsPartMgr::computeLateralCoords(position, lateralLengths[i], lateralDirection, buildAngleRotationMatrix); - - std::vector displayCoords; - for (auto domainCoord : lateralDomainCoords) - { - displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(domainCoord)); - } - - cylinderWithCenterLineParts(&m_parts, displayCoords, wellPath->wellPathColor(), wellPath->combinedScaleFactor() * characteristicCellSize * 0.5); - - cvf::ref objectSourceInfo = new RivObjectSourceInfo(m_rimFishbonesSubs); - - for (auto p : m_parts) - { - p->setSourceInfo(objectSourceInfo.p()); - } + for (auto p : m_parts) + { + p->setSourceInfo(objectSourceInfo.p()); } } } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RivFishbonesSubsPartMgr::computeLateralCoords(const cvf::Vec3d& startCoord, double lateralLength, const cvf::Vec3d& lateralStartDirection, const cvf::Mat4d& buildAngleRotationMatrix) -{ - std::vector coords; - - cvf::Vec3d lateralDirection(lateralStartDirection); - - // Compute coordinates along the lateral by modifying the lateral direction by the build angle for - // every unit vector along the lateral - cvf::Vec3d accumulatedPosition = startCoord; - double accumulatedLength = 0.0; - while (accumulatedLength < lateralLength) - { - coords.push_back(accumulatedPosition); - - double delta = 1.0; - - if (lateralLength - accumulatedLength < 1.0) - { - delta = lateralLength - accumulatedLength; - } - - accumulatedPosition += delta * lateralDirection; - - // Modify the lateral direction by the build angle for each unit vector - lateralDirection = lateralDirection.getTransformedVector(buildAngleRotationMatrix); - - accumulatedLength += delta; - } - - // Add the last accumulated position if it is not present - if (coords.back() != accumulatedPosition) - { - coords.push_back(accumulatedPosition); - } - - return coords; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -250,36 +155,3 @@ void RivFishbonesSubsPartMgr::cylinderWithCenterLineParts(cvf::Collection maxValue) - { - maxComponent = 1; - maxValue = cvf::Math::abs(vec.y()); - } - - if (cvf::Math::abs(vec.z()) > maxValue) - { - maxComponent = 2; - maxValue = cvf::Math::abs(vec.z()); - } - - if (maxComponent == 0) - { - return cvf::Vec3d::X_AXIS; - } - else if (maxComponent == 1) - { - return cvf::Vec3d::Y_AXIS; - } - else - { - return cvf::Vec3d::Z_AXIS; - } -} - diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h index 867b781020..3a01ce97be 100644 --- a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h @@ -59,14 +59,8 @@ public: private: void buildParts(caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize); - static std::vector computeLateralCoords(const cvf::Vec3d& startCoord, - double lateralLength, const cvf::Vec3d& lateralStartDirection, - const cvf::Mat4d& buildAngleRotationMatrix); - static void cylinderWithCenterLineParts(cvf::Collection* destinationParts, const std::vector& centerCoords, const cvf::Color3f& color, double radius); - static cvf::Vec3d closestMainAxis(const cvf::Vec3d& vec); - private: caf::PdmPointer m_rimFishbonesSubs; cvf::Collection m_parts; diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp index 322d64d13b..37c91407e3 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp @@ -19,6 +19,7 @@ #include "RimFishbonesMultipleSubs.h" #include "RimProject.h" +#include "RigFishbonesGeometry.h" #include "cafPdmUiListEditor.h" @@ -89,6 +90,8 @@ RimFishbonesMultipleSubs::RimFishbonesMultipleSubs() CAF_PDM_InitFieldNoDefault(&m_installationRotationAngles, "InstallationRotationAngles", "Installation Rotation Angles [deg]", "", "", ""); m_installationRotationAngles.uiCapability()->setUiHidden(true); CAF_PDM_InitField(&m_fixedInstallationRotationAngle, "FixedInstallationRotationAngle", 0.0, " Fixed Angle [deg]", "", "", ""); + + m_rigFishbonesGeometry = std::unique_ptr(new RigFisbonesGeometry(this)); } //-------------------------------------------------------------------------------------------------- @@ -183,6 +186,22 @@ std::vector RimFishbonesMultipleSubs::lateralLengths() const return lengths; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimFishbonesMultipleSubs::coordsForLateral(size_t subIndex, size_t lateralIndex) const +{ + std::vector coordsAndMD = m_rigFishbonesGeometry->coordsForLateral(subIndex, lateralIndex); + + std::vector domainCoords; + for (auto c :coordsAndMD) + { + domainCoords.push_back(c.m_coord); + } + + return domainCoords; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h index 1c41bc510b..b08d584493 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -20,6 +20,14 @@ #include "RimCheckableNamedObject.h" +#include "cvfBase.h" +#include "cvfVector3.h" + +#include +#include + +class RigFisbonesGeometry; + //================================================================================================== /// /// @@ -56,6 +64,8 @@ public: double lateralCountPerSub() const; std::vector lateralLengths() const; + std::vector coordsForLateral(size_t subIndex, size_t lateralIndex) const; + protected: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; @@ -100,4 +110,6 @@ private: caf::PdmField> m_installationRotationAngles; caf::PdmField m_fixedInstallationRotationAngle; + + std::unique_ptr m_rigFishbonesGeometry; }; diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index f4e9eb5681..13f97b648e 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -51,6 +51,7 @@ ${CEE_CURRENT_LIST_DIR}RigCurveDataTools.h ${CEE_CURRENT_LIST_DIR}RigSummaryCaseData.h ${CEE_CURRENT_LIST_DIR}RigLasFileExporter.h ${CEE_CURRENT_LIST_DIR}RigSimulationWellCoordsAndMD.h +${CEE_CURRENT_LIST_DIR}RigFishbonesGeometry.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -96,6 +97,7 @@ ${CEE_CURRENT_LIST_DIR}RigCurveDataTools.cpp ${CEE_CURRENT_LIST_DIR}RigSummaryCaseData.cpp ${CEE_CURRENT_LIST_DIR}RigLasFileExporter.cpp ${CEE_CURRENT_LIST_DIR}RigSimulationWellCoordsAndMD.cpp +${CEE_CURRENT_LIST_DIR}RigFishbonesGeometry.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp new file mode 100644 index 0000000000..a356cc659b --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp @@ -0,0 +1,187 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigFishbonesGeometry.h" + +#include "RimFishbonesMultipleSubs.h" + +#include "cvfAssert.h" +#include "RimWellPath.h" +#include "RigWellPath.h" +#include "cvfMatrix4.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigFisbonesGeometry::RigFisbonesGeometry(RimFishbonesMultipleSubs* fishbonesSub) + : m_fishbonesSub(fishbonesSub) +{ + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> RigFisbonesGeometry::coordsForLateral(size_t subIndex, size_t lateralIndex) const +{ + CVF_ASSERT(subIndex < m_fishbonesSub->locationOfSubs().size()); + CVF_ASSERT(lateralIndex < m_fishbonesSub->lateralLengths().size()); + + cvf::Vec3d position; + cvf::Vec3d lateralInitialDirection; + cvf::Mat4d buildAngleRotationMatrix; + + computeLateralPositionAndOrientation(subIndex, lateralIndex, &position, &lateralInitialDirection, &buildAngleRotationMatrix); + + return computeCoordsAlongLateral(m_fishbonesSub->locationOfSubs()[subIndex], m_fishbonesSub->lateralLengths()[lateralIndex], position, lateralInitialDirection, buildAngleRotationMatrix); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigFisbonesGeometry::computeLateralPositionAndOrientation(size_t subIndex, size_t lateralIndex, cvf::Vec3d* startCoord, cvf::Vec3d* startDirection, cvf::Mat4d* buildAngleMatrix) const +{ + RimWellPath* wellPath = nullptr; + m_fishbonesSub->firstAncestorOrThisOfTypeAsserted(wellPath); + + RigWellPath* rigWellPath = wellPath->wellPathGeometry(); + CVF_ASSERT(rigWellPath); + + double measuredDepth = m_fishbonesSub->locationOfSubs()[subIndex]; + + cvf::Vec3d position = rigWellPath->interpolatedPointAlongWellPath(measuredDepth); + + cvf::Mat4d buildAngleMat; + cvf::Vec3d lateralInitialDirection = cvf::Vec3d::Z_AXIS; + + { + cvf::Vec3d p1 = cvf::Vec3d::UNDEFINED; + cvf::Vec3d p2 = cvf::Vec3d::UNDEFINED; + rigWellPath->twoClosestPoints(position, &p1, &p2); + + CVF_ASSERT(!p1.isUndefined() && !p2.isUndefined()); + + cvf::Vec3d lateralDirection; + cvf::Vec3d alongWellPath = (p2 - p1).getNormalized(); + + if (RigFisbonesGeometry::closestMainAxis(alongWellPath) == cvf::Vec3d::Z_AXIS) + { + // Use x-axis if well path is heading close to z-axis + lateralInitialDirection = cvf::Vec3d::X_AXIS; + } + + { + double intialRotationAngle = m_fishbonesSub->rotationAngle(subIndex); + double lateralOffsetDegrees = 360.0 / m_fishbonesSub->lateralLengths().size(); + + double lateralOffsetRadians = cvf::Math::toRadians(intialRotationAngle + lateralOffsetDegrees * lateralIndex); + + cvf::Mat4d lateralOffsetMatrix = cvf::Mat4d::fromRotation(alongWellPath, lateralOffsetRadians); + + lateralInitialDirection = lateralInitialDirection.getTransformedVector(lateralOffsetMatrix); + } + + cvf::Vec3d rotationAxis; + rotationAxis.cross(alongWellPath, lateralInitialDirection); + + double exitAngleRadians = cvf::Math::toRadians(m_fishbonesSub->exitAngle()); + cvf::Mat4d lateralRotationMatrix = cvf::Mat4d::fromRotation(rotationAxis, exitAngleRadians); + + lateralDirection = alongWellPath.getTransformedVector(lateralRotationMatrix); + + double buildAngleRadians = cvf::Math::toRadians(m_fishbonesSub->buildAngle()); + buildAngleMat = cvf::Mat4d::fromRotation(rotationAxis, buildAngleRadians); + } + + *startCoord = position; + *startDirection = lateralInitialDirection; + *buildAngleMatrix = buildAngleMat; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> RigFisbonesGeometry::computeCoordsAlongLateral(double startMeasuredDepth, double lateralLength, const cvf::Vec3d& startCoord, const cvf::Vec3d& startDirection, const cvf::Mat4d& buildAngleMatrix) +{ + std::vector> coords; + + cvf::Vec3d lateralDirection(startDirection); + + // Compute coordinates along the lateral by modifying the lateral direction by the build angle for + // every unit vector along the lateral + cvf::Vec3d accumulatedPosition = startCoord; + double measuredDepth = startMeasuredDepth; + + double accumulatedLength = 0.0; + while (accumulatedLength < lateralLength) + { + coords.push_back(std::make_pair(accumulatedPosition, measuredDepth)); + + double delta = 1.0; + + if (lateralLength - accumulatedLength < 1.0) + { + delta = lateralLength - accumulatedLength; + } + + accumulatedPosition += delta * lateralDirection; + + // Modify the lateral direction by the build angle for each unit vector + lateralDirection = lateralDirection.getTransformedVector(buildAngleMatrix); + + accumulatedLength += delta; + measuredDepth += delta; + } + + coords.push_back(std::make_pair(accumulatedPosition, measuredDepth)); + + return coords; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RigFisbonesGeometry::closestMainAxis(const cvf::Vec3d& vec) +{ + size_t maxComponent = 0; + double maxValue = cvf::Math::abs(vec.x()); + if (cvf::Math::abs(vec.y()) > maxValue) + { + maxComponent = 1; + maxValue = cvf::Math::abs(vec.y()); + } + + if (cvf::Math::abs(vec.z()) > maxValue) + { + maxComponent = 2; + maxValue = cvf::Math::abs(vec.z()); + } + + if (maxComponent == 0) + { + return cvf::Vec3d::X_AXIS; + } + else if (maxComponent == 1) + { + return cvf::Vec3d::Y_AXIS; + } + else + { + return cvf::Vec3d::Z_AXIS; + } +} diff --git a/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.h b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.h new file mode 100644 index 0000000000..7a32137be9 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.h @@ -0,0 +1,56 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmPointer.h" + +#include "cvfBase.h" +#include "cvfVector3.h" +#include "cvfMatrix4.h" + +#include + +class RimFishbonesMultipleSubs; + +//================================================================================================== +/// +/// +//================================================================================================== +class RigFisbonesGeometry +{ +public: + explicit RigFisbonesGeometry(RimFishbonesMultipleSubs* fishbonesSub); + + std::vector> coordsForLateral(size_t subIndex, size_t lateralIndex) const; + +private: + void computeLateralPositionAndOrientation(size_t subIndex, size_t lateralIndex, + cvf::Vec3d* startCoord, cvf::Vec3d* startDirection, + cvf::Mat4d* buildAngleMatrix) const; + + static std::vector> computeCoordsAlongLateral(double startMeasuredDepth, double lateralLength, + const cvf::Vec3d& startCoord, const cvf::Vec3d& startDirection, + const cvf::Mat4d& buildAngleMatrix); + + static cvf::Vec3d closestMainAxis(const cvf::Vec3d& vec); + +private: + caf::PdmPointer m_fishbonesSub; +}; + From 342a58a0aefcb04dac3f5fc0045faa57b5b4d99f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 May 2017 10:48:11 +0200 Subject: [PATCH 075/157] #1452 Fishbones : Export laterals to text file --- .../FishbonesCommands/CMakeLists_files.cmake | 2 + .../RicExportFishbonesLateralsFeature.cpp | 142 ++++++++++++++++++ .../RicExportFishbonesLateralsFeature.h | 39 +++++ .../Fishbones/RimFishbonesMultipleSubs.cpp | 14 +- .../Fishbones/RimFishbonesMultipleSubs.h | 3 +- .../RimContextCommandBuilder.cpp | 1 + 6 files changed, 197 insertions(+), 4 deletions(-) create mode 100644 ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp create mode 100644 ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h diff --git a/ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake index 9017dfe068..52f320aeda 100644 --- a/ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake @@ -6,10 +6,12 @@ endif() set (SOURCE_GROUP_HEADER_FILES ${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsFeature.h +${CEE_CURRENT_LIST_DIR}RicExportFishbonesLateralsFeature.h ) set (SOURCE_GROUP_SOURCE_FILES ${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsFeature.cpp +${CEE_CURRENT_LIST_DIR}RicExportFishbonesLateralsFeature.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp new file mode 100644 index 0000000000..be71bfcc77 --- /dev/null +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp @@ -0,0 +1,142 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicExportFishbonesLateralsFeature.h" + +#include "RiaApplication.h" +#include "RiaLogging.h" + +#include "RimFishbonesMultipleSubs.h" +#include "RimWellPath.h" + +#include "cafSelectionManager.h" +#include "cafUtils.h" + +#include "cvfAssert.h" + +#include +#include +#include + +CAF_CMD_SOURCE_INIT(RicExportFishbonesLateralsFeature, "RicExportFishbonesLateralsFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportFishbonesLateralsFeature::onActionTriggered(bool isChecked) +{ + RimWellPath* wellPath = selectedWellPath(); + CVF_ASSERT(wellPath); + + RiaApplication* app = RiaApplication::instance(); + QString projectFolder = app->currentProjectPath(); + + QString defaultDir = app->lastUsedDialogDirectoryWithFallback("WELL_PATH_EXPORT_DIR", projectFolder); + + QString defaultFileName = defaultDir + "/" + caf::Utils::makeValidFileBasename((wellPath->name())) + ".dev"; + QString completeFilename = QFileDialog::getSaveFileName(nullptr, "Select File for Well Path Data Export", defaultFileName, "Well Path Text File(*.dev);;All files(*.*)"); + if (completeFilename.isEmpty()) return; + + QFile exportFile(completeFilename); + + RiaLogging::info("Starting export of Fishbones well path laterals to : " + completeFilename); + + if (!exportFile.open(QIODevice::WriteOnly)) + { + RiaLogging::error("Could not open the file :\n" + completeFilename); + return; + } + + + // See RifWellPathAsciiFileReader::readAllWellData for reading of dev files + // Export format + // + // wellname : __ + // for each coordinate along lateral, export + // x y TVD MD + // separate laterals using -999 on a single line + + QTextStream stream(&exportFile); + for (RimFishbonesMultipleSubs* fishbone : wellPath->fishbonesSubs()) + { + if (!fishbone->isChecked()) continue; + + for (size_t subIndex = 0; subIndex < fishbone->locationOfSubs().size(); subIndex++) + { + for (size_t lateralIndex = 0; lateralIndex < fishbone->lateralLengths().size(); lateralIndex++) + { + std::vector> coordsAndMD = fishbone->coordsAndMDForLateral(subIndex, lateralIndex); + + // Pad with "0" to get a total of two characters defining the sub index text + QString subIndexText = QString("%1").arg(subIndex, 2, 10, QChar('0')); + + QString lateralName = QString("%1_%2_%3_%4").arg(wellPath->name()).arg(fishbone->name()).arg(subIndexText).arg(lateralIndex); + stream << "wellname : " << lateralName << endl; + + for (auto coordMD : coordsAndMD) + { + // Export X and Y unchanged, invert sign of Z to get TVD, export MD unchanged + stream << coordMD.first.x() << " " << coordMD.first.y() << " " << -coordMD.first.z() << " " << coordMD.second << endl; + } + stream << -999 << endl << endl; + } + } + } + + RiaLogging::info("Completed export of Fishbones well path laterals to : " + completeFilename); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPath* RicExportFishbonesLateralsFeature::selectedWellPath() +{ + RimWellPath* wellPath = nullptr; + + caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem(); + + caf::PdmObjectHandle* objHandle = dynamic_cast(pdmUiItem); + if (objHandle) + { + objHandle->firstAncestorOrThisOfType(wellPath); + } + + return wellPath; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportFishbonesLateralsFeature::setupActionLook(QAction* actionToSetup) +{ + //actionToSetup->setIcon(QIcon(":/FractureSymbol16x16.png")); + actionToSetup->setText("Export Fishbones Laterals"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicExportFishbonesLateralsFeature::isCommandEnabled() +{ + if (selectedWellPath()) + { + return true; + } + + return false; +} diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h new file mode 100644 index 0000000000..d0ad4caa46 --- /dev/null +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h @@ -0,0 +1,39 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +class RimWellPath; + +//================================================================================================== +/// +//================================================================================================== +class RicExportFishbonesLateralsFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + virtual void onActionTriggered(bool isChecked) override; + virtual void setupActionLook(QAction* actionToSetup) override; + virtual bool isCommandEnabled() override; + +private: + static RimWellPath* selectedWellPath(); +}; diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp index 37c91407e3..7270290b45 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp @@ -191,17 +191,25 @@ std::vector RimFishbonesMultipleSubs::lateralLengths() const //-------------------------------------------------------------------------------------------------- std::vector RimFishbonesMultipleSubs::coordsForLateral(size_t subIndex, size_t lateralIndex) const { - std::vector coordsAndMD = m_rigFishbonesGeometry->coordsForLateral(subIndex, lateralIndex); + std::vector> coordsAndMD = m_rigFishbonesGeometry->coordsForLateral(subIndex, lateralIndex); std::vector domainCoords; - for (auto c :coordsAndMD) + for (const auto& coordMD : coordsAndMD) { - domainCoords.push_back(c.m_coord); + domainCoords.push_back(coordMD.first); } return domainCoords; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> RimFishbonesMultipleSubs::coordsAndMDForLateral(size_t subIndex, size_t lateralIndex) const +{ + return m_rigFishbonesGeometry->coordsForLateral(subIndex, lateralIndex); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h index b08d584493..250ad35a63 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -64,7 +64,8 @@ public: double lateralCountPerSub() const; std::vector lateralLengths() const; - std::vector coordsForLateral(size_t subIndex, size_t lateralIndex) const; + std::vector coordsForLateral(size_t subIndex, size_t lateralIndex) const; + std::vector> coordsAndMDForLateral(size_t subIndex, size_t lateralIndex) const; protected: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index f6fb1498d5..29e3f8564e 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -396,6 +396,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection() commandIds << "RicSummaryCurveSwitchAxisFeature"; commandIds << "RicNewFishbonesSubsFeature"; + commandIds << "RicExportFishbonesLateralsFeature"; // Work in progress -- End From 53ba4967cc9e7c9a9a40a09193f1cb4b9775fa54 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 May 2017 11:06:51 +0200 Subject: [PATCH 076/157] System : Add shortcut for Save, Save As, Exit and Open --- .../Commands/ApplicationCommands/RicExitApplicationFeature.cpp | 1 + .../Commands/ApplicationCommands/RicOpenProjectFeature.cpp | 1 + .../Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp | 1 + .../Commands/ApplicationCommands/RicSaveProjectFeature.cpp | 1 + 4 files changed, 4 insertions(+) diff --git a/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp index 92feded515..24aaa0dd11 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp @@ -51,4 +51,5 @@ void RicExitApplicationFeature::onActionTriggered(bool isChecked) void RicExitApplicationFeature::setupActionLook(QAction* actionToSetup) { actionToSetup->setText("E&xit"); + actionToSetup->setShortcuts(QKeySequence::Quit); } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp index 857c4579f8..64f5da34df 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp @@ -66,4 +66,5 @@ void RicOpenProjectFeature::setupActionLook(QAction* actionToSetup) { actionToSetup->setText("Open Project"); actionToSetup->setIcon(QIcon(":/openFolder24x24.png")); + actionToSetup->setShortcuts(QKeySequence::Open); } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp index f119d5ea2e..a8616fb13e 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp @@ -54,4 +54,5 @@ void RicSaveProjectAsFeature::setupActionLook(QAction* actionToSetup) { actionToSetup->setText("Save Project &As"); actionToSetup->setIcon(QIcon(":/Save.png")); + actionToSetup->setShortcuts(QKeySequence::SaveAs); } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp index 5bfcadd436..8a5c33c660 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp @@ -51,6 +51,7 @@ void RicSaveProjectFeature::setupActionLook(QAction* actionToSetup) { actionToSetup->setText("&Save Project"); actionToSetup->setIcon(QIcon(":/Save.png")); + actionToSetup->setShortcuts(QKeySequence::Save); } //-------------------------------------------------------------------------------------------------- From 47517d734bfe5ea15f8532e75d9afc6b6a171a61 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 May 2017 11:06:51 +0200 Subject: [PATCH 077/157] System : Add shortcut for Save, Save As, Exit and Open --- .../Commands/ApplicationCommands/RicExitApplicationFeature.cpp | 1 + .../Commands/ApplicationCommands/RicOpenProjectFeature.cpp | 1 + .../Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp | 1 + .../Commands/ApplicationCommands/RicSaveProjectFeature.cpp | 1 + 4 files changed, 4 insertions(+) diff --git a/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp index 92feded515..24aaa0dd11 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicExitApplicationFeature.cpp @@ -51,4 +51,5 @@ void RicExitApplicationFeature::onActionTriggered(bool isChecked) void RicExitApplicationFeature::setupActionLook(QAction* actionToSetup) { actionToSetup->setText("E&xit"); + actionToSetup->setShortcuts(QKeySequence::Quit); } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp index 857c4579f8..64f5da34df 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicOpenProjectFeature.cpp @@ -66,4 +66,5 @@ void RicOpenProjectFeature::setupActionLook(QAction* actionToSetup) { actionToSetup->setText("Open Project"); actionToSetup->setIcon(QIcon(":/openFolder24x24.png")); + actionToSetup->setShortcuts(QKeySequence::Open); } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp index f119d5ea2e..a8616fb13e 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectAsFeature.cpp @@ -54,4 +54,5 @@ void RicSaveProjectAsFeature::setupActionLook(QAction* actionToSetup) { actionToSetup->setText("Save Project &As"); actionToSetup->setIcon(QIcon(":/Save.png")); + actionToSetup->setShortcuts(QKeySequence::SaveAs); } diff --git a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp index 5bfcadd436..8a5c33c660 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicSaveProjectFeature.cpp @@ -51,6 +51,7 @@ void RicSaveProjectFeature::setupActionLook(QAction* actionToSetup) { actionToSetup->setText("&Save Project"); actionToSetup->setIcon(QIcon(":/Save.png")); + actionToSetup->setShortcuts(QKeySequence::Save); } //-------------------------------------------------------------------------------------------------- From 59cccf60f0e311cb62049b8e36a52ab343315fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 8 May 2017 12:04:58 +0200 Subject: [PATCH 078/157] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0e4137db44..a83b1fee87 100644 --- a/README.md +++ b/README.md @@ -9,15 +9,15 @@ The main input data is *.GRID and *.EGRID files along with their *.INIT and rest ResInsight has been co-developed by Statoil ASA, Ceetron Solutions AS, and Ceetron AS with the aim to provide a versatile tool for professionals who need to visualize and process reservoir models. The software is copyrighted by Ceetron and Statoil and licensed under GPL 3+. See COPYING for details. ### Dependencies -ResInsight uses the Ensambles/ert library to access Eclipse result files, and the two projects collaborates closely. The source code of the approved ert library version is embedded in the ResInsight source code tree, making downloading and building simple. +ResInsight uses the Statoil/libecl (formerly Ensambles/ert) library to access Eclipse result files, and the two projects collaborates closely. The source code of the approved libecl version is embedded in the ResInsight source code tree, making downloading and building simple. ResInsight also features an interface to Octave for retrieval of data from ResInsight, processing using Octave, and communication of data back into ResInsight for further handling and visualization. Octave : [http://www.gnu.org/software/octave/](http://www.gnu.org/software/octave/) -Ensembles/ert : [https://github.com/Ensembles/ert](https://github.com/Ensembles/ert) +Statoil/libecl : [https://github.com/Statoil/libecl](https://github.com/Statoil/libecl) ### Supported Platforms -ResInsight is designed cross-platform from the start. Efforts have been made to ensure that code will compile and run on Linux and Windows platforms. Tested platforms are currently 64 bit RHEL6 and Windows 7. +ResInsight is designed cross-platform from the start. Efforts have been made to ensure that code will compile and run on Linux and Windows platforms. Tested platforms are currently 64 bit RHEL6 and Windows 7/8/10, and we have also received reports on successful builds on Ubuntu based systems. ### Documentation @@ -38,4 +38,4 @@ Release branches that might pop up are dedicated bug fix branches for the releas ### Building ResInsight -See [ Build Instructions ] (http://resinsight.org/docs/buildinstructions/) +See [ Build Instructions ](http://resinsight.org/docs/buildinstructions/) From f5d1d2d1f9f60db340035e4a15705d1cf086f13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 8 May 2017 13:37:39 +0200 Subject: [PATCH 079/157] #1396 Update libEcl to 06a39878636af0bc52582430ad0431450e51139c To include phase split well connection rates and some summary intersect support. Supposedly Final update before release. --- ResInsightVersion.cmake | 2 +- ThirdParty/Ert/.gitignore | 5 +- ThirdParty/Ert/CMakeLists.txt | 32 +- ThirdParty/Ert/README.md | 1 + ThirdParty/Ert/cmake/cmake_pyc | 35 -- ThirdParty/Ert/cmake/cmake_pyc2 | 32 -- ThirdParty/Ert/cmake/cmake_pyc_file | 20 -- ThirdParty/Ert/cmake/cmake_pyc_tree | 35 -- .../Ert/cmake/libecl-config-version.cmake.in | 14 + ThirdParty/Ert/cmake/libecl-config.cmake.in | 10 + ThirdParty/Ert/cmake/python.cmake | 25 -- .../docs/course/config/jobs/snake_oil_diff.py | 2 +- .../docs/course/config/jobs/snake_oil_npv.py | 2 +- .../course/config/jobs/snake_oil_simulator.py | 4 +- .../Ert/libecl/include/ert/ecl/ecl_kw.h | 5 +- .../Ert/libecl/include/ert/ecl/ecl_kw_magic.h | 1 + .../Ert/libecl/include/ert/ecl/ecl_type.h | 40 ++- .../Ert/libecl/include/ert/ecl/ecl_units.h | 46 +++ ThirdParty/Ert/libecl/src/CMakeLists.txt | 3 +- ThirdParty/Ert/libecl/src/ecl_file.c | 7 - ThirdParty/Ert/libecl/src/ecl_file_view.c | 4 +- ThirdParty/Ert/libecl/src/ecl_grid.c | 6 +- ThirdParty/Ert/libecl/src/ecl_kw.c | 310 ++++++++++-------- ThirdParty/Ert/libecl/src/ecl_kw_grdecl.c | 2 +- ThirdParty/Ert/libecl/src/ecl_rsthead.c | 18 +- ThirdParty/Ert/libecl/src/ecl_smspec.c | 91 +++-- ThirdParty/Ert/libecl/src/ecl_type.c | 150 +++++---- ThirdParty/Ert/libecl/src/ecl_type_python.c | 8 +- ThirdParty/Ert/libecl/src/ecl_util.c | 17 +- ThirdParty/Ert/libecl/src/smspec_node.c | 10 +- ThirdParty/Ert/libecl/tests/ecl_kw_ix_types.c | 41 --- ThirdParty/Ert/libecl/tests/tests.cmake | 4 - .../include/ert/ecl_well/well_const.h | 6 +- .../include/ert/ecl_well/well_state.h | 1 + ThirdParty/Ert/libecl_well/src/CMakeLists.txt | 2 +- ThirdParty/Ert/libecl_well/src/well_conn.c | 1 + ThirdParty/Ert/libecl_well/src/well_state.c | 47 ++- ThirdParty/Ert/libeclxx/src/CMakeLists.txt | 2 +- ThirdParty/Ert/libert_util/src/CMakeLists.txt | 2 +- .../Ert/libert_utilxx/src/CMakeLists.txt | 2 +- ThirdParty/Ert/libgeometry/src/CMakeLists.txt | 2 +- ThirdParty/Ert/python/CMakeLists.txt | 25 +- ThirdParty/Ert/python/README | 2 +- .../cmake/Modules/add_python_package.cmake} | 7 +- .../cmake/Modules/add_python_test.cmake | 38 +++ .../find_python_package.cmake} | 23 +- .../python/cmake/Modules/init_python.cmake | 175 ++++++++++ .../Ert/python/cmake/find_python_module.cmake | 27 -- ThirdParty/Ert/python/python/CMakeLists.txt | 2 +- ThirdParty/Ert/python/python/cwrap/cfile.py | 2 +- ThirdParty/Ert/python/python/cwrap/clib.py | 6 +- .../Ert/python/python/ecl/CMakeLists.txt | 14 + .../python/python/{ert => ecl}/__init__.py | 34 +- .../python/{ert => ecl}/ecl/CMakeLists.txt | 2 +- .../python/{ert => ecl}/ecl/__init__.py | 8 +- .../python/{ert => ecl}/ecl/ecl_3d_file.py | 2 +- .../python/{ert => ecl}/ecl/ecl_3dkw.py | 4 +- .../python/python/{ert => ecl}/ecl/ecl_cmp.py | 2 +- .../python/{ert => ecl}/ecl/ecl_file.py | 10 +- .../python/{ert => ecl}/ecl/ecl_file_view.py | 4 +- .../python/{ert => ecl}/ecl/ecl_grav.py | 4 +- .../python/{ert => ecl}/ecl/ecl_grav_calc.py | 2 +- .../python/{ert => ecl}/ecl/ecl_grid.py | 6 +- .../{ert => ecl}/ecl/ecl_grid_generator.py | 4 +- .../python/{ert => ecl}/ecl/ecl_init_file.py | 2 +- .../python/python/{ert => ecl}/ecl/ecl_kw.py | 14 +- .../python/python/{ert => ecl}/ecl/ecl_npv.py | 2 +- .../python/{ert => ecl}/ecl/ecl_region.py | 10 +- .../{ert => ecl}/ecl/ecl_restart_file.py | 23 +- .../python/python/{ert => ecl}/ecl/ecl_rft.py | 4 +- .../python/{ert => ecl}/ecl/ecl_rft_cell.py | 2 +- .../{ert => ecl}/ecl/ecl_smspec_node.py | 2 +- .../python/{ert => ecl}/ecl/ecl_subsidence.py | 4 +- .../python/python/{ert => ecl}/ecl/ecl_sum.py | 16 +- .../ecl/ecl_sum_keyword_vector.py | 2 +- .../python/{ert => ecl}/ecl/ecl_sum_node.py | 0 .../python/{ert => ecl}/ecl/ecl_sum_tstep.py | 4 +- .../{ert => ecl}/ecl/ecl_sum_var_type.py | 2 +- .../python/{ert => ecl}/ecl/ecl_sum_vector.py | 2 +- .../python/{ert => ecl}/ecl/ecl_type.py | 32 +- .../python/{ert => ecl}/ecl/ecl_util.py | 2 +- .../{ert => ecl}/ecl/faults/CMakeLists.txt | 2 +- .../{ert => ecl}/ecl/faults/__init__.py | 0 .../python/{ert => ecl}/ecl/faults/fault.py | 6 +- .../{ert => ecl}/ecl/faults/fault_block.py | 6 +- .../ecl/faults/fault_block_collection.py | 2 +- .../ecl/faults/fault_block_layer.py | 4 +- .../ecl/faults/fault_collection.py | 2 +- .../{ert => ecl}/ecl/faults/fault_line.py | 4 +- .../{ert => ecl}/ecl/faults/fault_segments.py | 0 .../python/{ert => ecl}/ecl/faults/layer.py | 4 +- .../python/python/{ert => ecl}/ecl/fortio.py | 6 +- .../python/{ert => ecl}/ecl/local.cmake | 4 +- .../python/python/ecl/ecl/rft/CMakeLists.txt | 6 + .../python/{ert => ecl}/ecl/rft/__init__.py | 0 .../{ert => ecl}/ecl/rft/well_trajectory.py | 0 .../ecl_lib_info_build.py.in} | 0 .../ecl_lib_info_install.py.in} | 0 .../python/{ert => ecl}/geo/CMakeLists.txt | 2 +- .../python/{ert => ecl}/geo/__init__.py | 4 +- .../python/{ert => ecl}/geo/cpolyline.py | 2 +- .../{ert => ecl}/geo/cpolyline_collection.py | 2 +- .../python/{ert => ecl}/geo/geo_pointset.py | 2 +- .../python/{ert => ecl}/geo/geo_region.py | 4 +- .../python/{ert => ecl}/geo/geometry_tools.py | 0 .../python/{ert => ecl}/geo/polyline.py | 0 .../python/python/{ert => ecl}/geo/surface.py | 4 +- .../python/python/{ert => ecl}/geo/xyz_io.py | 0 .../python/{ert => ecl}/test/CMakeLists.txt | 3 +- .../python/{ert => ecl}/test/__init__.py | 5 +- .../python/ecl/test/ecl_mock/CMakeLists.txt | 7 + .../{ert => ecl}/test/ecl_mock/__init__.py | 0 .../test/ecl_mock/ecl_sum_mock.py | 2 +- .../{ert => ecl}/test/ert_test_context.py | 0 .../{ert => ecl}/test/ert_test_runner.py | 0 .../{ert => ecl}/test/extended_testcase.py | 15 +- .../python/ecl/test/import_test_case.py | 49 +++ .../{ert => ecl}/test/lint_test_case.py | 0 .../python/{ert => ecl}/test/path_context.py | 0 .../{ert => ecl}/test/source_enumerator.py | 0 .../python/{ert => ecl}/test/temp_area.py | 2 +- .../python/{ert => ecl}/test/test_area.py | 2 +- .../python/{ert => ecl}/test/test_run.py | 0 .../python/{ert => ecl}/util/CMakeLists.txt | 2 +- .../python/{ert => ecl}/util/__init__.py | 4 +- .../python/{ert => ecl}/util/arg_pack.py | 2 +- .../python/{ert => ecl}/util/bool_vector.py | 4 +- .../python/python/{ert => ecl}/util/buffer.py | 2 +- .../python/{ert => ecl}/util/cthread_pool.py | 2 +- .../python/python/{ert => ecl}/util/ctime.py | 2 +- .../python/{ert => ecl}/util/double_vector.py | 2 +- .../{ert => ecl}/util/enums/CMakeLists.txt | 2 +- .../{ert => ecl}/util/enums/__init__.py | 0 .../util/enums/llsq_result_enum.py | 0 .../util/enums/rng_alg_type_enum.py | 0 .../util/enums/rng_init_mode_enum.py | 0 .../util/enums/ui_return_status_enum.py | 0 .../python/python/{ert => ecl}/util/hash.py | 2 +- .../util/install_abort_signals.py | 2 +- .../python/{ert => ecl}/util/int_vector.py | 2 +- .../python/python/{ert => ecl}/util/log.py | 2 +- .../python/{ert => ecl}/util/lookup_table.py | 2 +- .../python/python/{ert => ecl}/util/matrix.py | 2 +- .../python/{ert => ecl}/util/path_format.py | 2 +- .../{ert => ecl}/util/permutation_vector.py | 2 +- .../python/{ert => ecl}/util/profiler.py | 0 .../python/python/{ert => ecl}/util/rng.py | 4 +- .../python/python/{ert => ecl}/util/stat.py | 6 +- .../python/{ert => ecl}/util/stringlist.py | 2 +- .../{ert => ecl}/util/substitution_list.py | 2 +- .../python/{ert => ecl}/util/thread_pool.py | 0 .../python/{ert => ecl}/util/time_vector.py | 2 +- .../python/{ert => ecl}/util/ui_return.py | 2 +- .../python/{ert => ecl}/util/util_func.py | 2 +- .../{ert => ecl}/util/vector_template.py | 2 +- .../python/{ert => ecl}/util/version.py | 2 +- .../python/{ert => ecl}/well/CMakeLists.txt | 2 +- .../python/{ert => ecl}/well/__init__.py | 10 +- .../{ert => ecl}/well/well_connection.py | 2 +- .../well/well_connection_direction_enum.py | 0 .../python/{ert => ecl}/well/well_info.py | 7 +- .../python/{ert => ecl}/well/well_segment.py | 2 +- .../python/{ert => ecl}/well/well_state.py | 11 +- .../{ert => ecl}/well/well_time_line.py | 2 +- .../{ert => ecl}/well/well_type_enum.py | 0 .../Ert/python/python/ert/CMakeLists.txt | 14 - .../python/python/ert/ecl/rft/CMakeLists.txt | 6 - .../python/python/ert/sched/CMakeLists.txt | 9 - .../Ert/python/python/ert/sched/__init__.py | 33 -- .../Ert/python/python/ert/sched/history.py | 68 ---- .../python/ert/sched/history_source_enum.py | 16 - .../Ert/python/python/ert/sched/sched_file.py | 56 ---- .../python/ert/test/ecl_mock/CMakeLists.txt | 7 - ThirdParty/Ert/python/tests/CMakeLists.txt | 34 +- ThirdParty/Ert/python/tests/ctest_import.py | 16 - ThirdParty/Ert/python/tests/ctest_run.py | 43 --- .../Ert/python/tests/cwrap/CMakeLists.txt | 10 +- .../Ert/python/tests/cwrap/test_basecclass.py | 2 +- .../Ert/python/tests/cwrap/test_basecenum.py | 2 +- .../Ert/python/tests/cwrap/test_basecvalue.py | 6 +- .../Ert/python/tests/cwrap/test_cfile.py | 8 +- .../Ert/python/tests/cwrap/test_metawrap.py | 6 +- .../Ert/python/tests/ecl/CMakeLists.txt | 78 ++--- .../Ert/python/tests/ecl/test_deprecation.py | 10 +- .../Ert/python/tests/ecl/test_ecl_3dkw.py | 6 +- .../Ert/python/tests/ecl/test_ecl_cmp.py | 6 +- .../Ert/python/tests/ecl/test_ecl_file.py | 6 +- .../python/tests/ecl/test_ecl_file_statoil.py | 109 +++++- .../python/tests/ecl/test_ecl_init_file.py | 4 +- .../Ert/python/tests/ecl/test_ecl_kw.py | 91 +++-- .../python/tests/ecl/test_ecl_kw_statoil.py | 4 +- .../python/tests/ecl/test_ecl_restart_file.py | 4 +- .../Ert/python/tests/ecl/test_ecl_sum.py | 4 +- .../python/tests/ecl/test_ecl_sum_tstep.py | 4 +- .../python/tests/ecl/test_ecl_sum_vector.py | 4 +- .../Ert/python/tests/ecl/test_ecl_type.py | 106 ++++-- .../Ert/python/tests/ecl/test_ecl_util.py | 25 +- .../Ert/python/tests/ecl/test_fault_blocks.py | 8 +- .../tests/ecl/test_fault_blocks_statoil.py | 6 +- .../Ert/python/tests/ecl/test_faults.py | 10 +- .../Ert/python/tests/ecl/test_fortio.py | 4 +- .../Ert/python/tests/ecl/test_geertsma.py | 4 +- ThirdParty/Ert/python/tests/ecl/test_grav.py | 4 +- .../Ert/python/tests/ecl/test_grdecl.py | 4 +- ThirdParty/Ert/python/tests/ecl/test_grid.py | 10 +- .../Ert/python/tests/ecl/test_grid_statoil.py | 6 +- .../Ert/python/tests/ecl/test_indexed_read.py | 10 +- .../Ert/python/tests/ecl/test_kw_function.py | 6 +- ThirdParty/Ert/python/tests/ecl/test_layer.py | 10 +- ThirdParty/Ert/python/tests/ecl/test_npv.py | 8 +- .../Ert/python/tests/ecl/test_region.py | 6 +- .../python/tests/ecl/test_region_statoil.py | 6 +- .../Ert/python/tests/ecl/test_removed.py | 4 +- .../Ert/python/tests/ecl/test_restart.py | 4 +- .../Ert/python/tests/ecl/test_restart_head.py | 41 +++ ThirdParty/Ert/python/tests/ecl/test_rft.py | 10 +- .../Ert/python/tests/ecl/test_rft_cell.py | 4 +- .../Ert/python/tests/ecl/test_rft_statoil.py | 6 +- .../python/tests/ecl/test_statoil_faults.py | 6 +- ThirdParty/Ert/python/tests/ecl/test_sum.py | 6 +- .../Ert/python/tests/ecl/test_sum_statoil.py | 62 +++- .../Ert/python/tests/geometry/CMakeLists.txt | 22 +- .../python/tests/geometry/test_convex_hull.py | 4 +- .../python/tests/geometry/test_cpolyline.py | 6 +- .../geometry/test_cpolyline_collection.py | 8 +- .../tests/geometry/test_geo_pointset.py | 4 +- .../python/tests/geometry/test_geo_region.py | 4 +- .../tests/geometry/test_geometry_tools.py | 6 +- .../tests/geometry/test_intersection.py | 4 +- .../tests/geometry/test_point_in_polygon.py | 6 +- .../tests/geometry/test_polygon_slicing.py | 4 +- .../python/tests/geometry/test_polyline.py | 6 +- .../Ert/python/tests/geometry/test_surface.py | 4 +- .../Ert/python/tests/global/CMakeLists.txt | 12 + .../Ert/python/tests/global/__init__.py | 0 .../Ert/python/tests/global/test_import.py | 26 ++ .../Ert/python/tests/global/test_pylint.py | 33 ++ ThirdParty/Ert/python/tests/import_tester.py | 72 ---- .../Ert/python/tests/share/CMakeLists.txt | 2 +- .../python/tests/share/test_synthesizer.py | 2 +- ThirdParty/Ert/python/tests/test_pylint.py | 11 +- .../Ert/python/tests/util/CMakeLists.txt | 34 +- .../Ert/python/tests/util/test_arg_pack.py | 8 +- .../Ert/python/tests/util/test_cstring.py | 6 +- .../python/tests/util/test_cthread_pool.py | 8 +- .../Ert/python/tests/util/test_ctime.py | 2 +- ThirdParty/Ert/python/tests/util/test_hash.py | 4 +- .../python/tests/util/test_lookup_table.py | 2 +- .../Ert/python/tests/util/test_matrix.py | 6 +- .../python/tests/util/test_path_context.py | 2 +- ThirdParty/Ert/python/tests/util/test_rng.py | 6 +- .../Ert/python/tests/util/test_spawn.py | 8 +- ThirdParty/Ert/python/tests/util/test_stat.py | 6 +- .../Ert/python/tests/util/test_string_list.py | 2 +- .../tests/util/test_substitution_list.py | 4 +- .../Ert/python/tests/util/test_thread_pool.py | 6 +- .../Ert/python/tests/util/test_ui_return.py | 6 +- .../Ert/python/tests/util/test_vectors.py | 2 +- .../Ert/python/tests/util/test_version.py | 14 +- .../Ert/python/tests/util/test_work_area.py | 2 +- .../Ert/python/tests/well/CMakeLists.txt | 6 +- .../Ert/python/tests/well/test_ecl_well.py | 8 +- .../Ert/python/tests/well/test_ecl_well2.py | 8 +- .../Ert/python/tests/well/test_ecl_well3.py | 8 +- 264 files changed, 1776 insertions(+), 1482 deletions(-) delete mode 100644 ThirdParty/Ert/cmake/cmake_pyc delete mode 100644 ThirdParty/Ert/cmake/cmake_pyc2 delete mode 100644 ThirdParty/Ert/cmake/cmake_pyc_file delete mode 100644 ThirdParty/Ert/cmake/cmake_pyc_tree create mode 100644 ThirdParty/Ert/cmake/libecl-config-version.cmake.in create mode 100644 ThirdParty/Ert/cmake/libecl-config.cmake.in delete mode 100644 ThirdParty/Ert/cmake/python.cmake create mode 100644 ThirdParty/Ert/libecl/include/ert/ecl/ecl_units.h delete mode 100644 ThirdParty/Ert/libecl/tests/ecl_kw_ix_types.c rename ThirdParty/Ert/{cmake/python.cmake2 => python/cmake/Modules/add_python_package.cmake} (83%) create mode 100644 ThirdParty/Ert/python/cmake/Modules/add_python_test.cmake rename ThirdParty/Ert/python/cmake/{python_package_versions.cmake => Modules/find_python_package.cmake} (70%) create mode 100644 ThirdParty/Ert/python/cmake/Modules/init_python.cmake delete mode 100644 ThirdParty/Ert/python/cmake/find_python_module.cmake create mode 100644 ThirdParty/Ert/python/python/ecl/CMakeLists.txt rename ThirdParty/Ert/python/python/{ert => ecl}/__init__.py (84%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/CMakeLists.txt (91%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/__init__.py (97%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_3d_file.py (97%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_3dkw.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_cmp.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_file.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_file_view.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_grav.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_grav_calc.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_grid.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_grid_generator.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_init_file.py (94%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_kw.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_npv.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_region.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_restart_file.py (89%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_rft.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_rft_cell.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_smspec_node.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_subsidence.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_sum.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_sum_keyword_vector.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_sum_node.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_sum_tstep.py (97%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_sum_var_type.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_sum_vector.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_type.py (82%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/ecl_util.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/faults/CMakeLists.txt (60%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/faults/__init__.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/faults/fault.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/faults/fault_block.py (97%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/faults/fault_block_collection.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/faults/fault_block_layer.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/faults/fault_collection.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/faults/fault_line.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/faults/fault_segments.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/faults/layer.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/fortio.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/local.cmake (81%) create mode 100644 ThirdParty/Ert/python/python/ecl/ecl/rft/CMakeLists.txt rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/rft/__init__.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/ecl/rft/well_trajectory.py (100%) rename ThirdParty/Ert/python/python/{ert/ert_lib_info_build.py.in => ecl/ecl_lib_info_build.py.in} (100%) rename ThirdParty/Ert/python/python/{ert/ert_lib_info_install.py.in => ecl/ecl_lib_info_install.py.in} (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/geo/CMakeLists.txt (66%) rename ThirdParty/Ert/python/python/{ert => ecl}/geo/__init__.py (96%) rename ThirdParty/Ert/python/python/{ert => ecl}/geo/cpolyline.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/geo/cpolyline_collection.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/geo/geo_pointset.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/geo/geo_region.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/geo/geometry_tools.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/geo/polyline.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/geo/surface.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/geo/xyz_io.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/test/CMakeLists.txt (67%) rename ThirdParty/Ert/python/python/{ert => ecl}/test/__init__.py (80%) create mode 100644 ThirdParty/Ert/python/python/ecl/test/ecl_mock/CMakeLists.txt rename ThirdParty/Ert/python/python/{ert => ecl}/test/ecl_mock/__init__.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/test/ecl_mock/ecl_sum_mock.py (97%) rename ThirdParty/Ert/python/python/{ert => ecl}/test/ert_test_context.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/test/ert_test_runner.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/test/extended_testcase.py (90%) create mode 100644 ThirdParty/Ert/python/python/ecl/test/import_test_case.py rename ThirdParty/Ert/python/python/{ert => ecl}/test/lint_test_case.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/test/path_context.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/test/source_enumerator.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/test/temp_area.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/test/test_area.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/test/test_run.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/CMakeLists.txt (83%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/__init__.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/arg_pack.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/bool_vector.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/buffer.py (96%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/cthread_pool.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/ctime.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/double_vector.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/enums/CMakeLists.txt (56%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/enums/__init__.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/enums/llsq_result_enum.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/enums/rng_alg_type_enum.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/enums/rng_init_mode_enum.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/enums/ui_return_status_enum.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/hash.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/install_abort_signals.py (89%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/int_vector.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/log.py (97%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/lookup_table.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/matrix.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/path_format.py (92%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/permutation_vector.py (96%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/profiler.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/rng.py (96%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/stat.py (93%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/stringlist.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/substitution_list.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/thread_pool.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/time_vector.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/ui_return.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/util_func.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/vector_template.py (99%) rename ThirdParty/Ert/python/python/{ert => ecl}/util/version.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/well/CMakeLists.txt (67%) rename ThirdParty/Ert/python/python/{ert => ecl}/well/__init__.py (84%) rename ThirdParty/Ert/python/python/{ert => ecl}/well/well_connection.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/well/well_connection_direction_enum.py (100%) rename ThirdParty/Ert/python/python/{ert => ecl}/well/well_info.py (95%) rename ThirdParty/Ert/python/python/{ert => ecl}/well/well_segment.py (98%) rename ThirdParty/Ert/python/python/{ert => ecl}/well/well_state.py (94%) rename ThirdParty/Ert/python/python/{ert => ecl}/well/well_time_line.py (95%) rename ThirdParty/Ert/python/python/{ert => ecl}/well/well_type_enum.py (100%) delete mode 100644 ThirdParty/Ert/python/python/ert/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/ecl/rft/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/sched/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/python/ert/sched/__init__.py delete mode 100644 ThirdParty/Ert/python/python/ert/sched/history.py delete mode 100644 ThirdParty/Ert/python/python/ert/sched/history_source_enum.py delete mode 100644 ThirdParty/Ert/python/python/ert/sched/sched_file.py delete mode 100644 ThirdParty/Ert/python/python/ert/test/ecl_mock/CMakeLists.txt delete mode 100644 ThirdParty/Ert/python/tests/ctest_import.py delete mode 100644 ThirdParty/Ert/python/tests/ctest_run.py create mode 100644 ThirdParty/Ert/python/tests/ecl/test_restart_head.py create mode 100644 ThirdParty/Ert/python/tests/global/CMakeLists.txt create mode 100644 ThirdParty/Ert/python/tests/global/__init__.py create mode 100644 ThirdParty/Ert/python/tests/global/test_import.py create mode 100644 ThirdParty/Ert/python/tests/global/test_pylint.py delete mode 100644 ThirdParty/Ert/python/tests/import_tester.py diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index aa44761c48..2f00b8f1e8 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -8,7 +8,7 @@ set(RESINSIGHT_INCREMENT_VERSION "flow.13") set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") # https://github.com/Statoil/libecl -set(ERT_GITHUB_SHA "f39d2e7fd196350ab1db86bb1bd5a3faca72d75d") +set(ERT_GITHUB_SHA "06a39878636af0bc52582430ad0431450e51139c") # https://github.com/OPM/opm-flowdiagnostics set(OPM_FLOWDIAGNOSTICS_SHA "a14dc4ba1302bcc1e0aeb35c5de6b4bd39bce98") diff --git a/ThirdParty/Ert/.gitignore b/ThirdParty/Ert/.gitignore index b0601e3c62..b835bff007 100644 --- a/ThirdParty/Ert/.gitignore +++ b/ThirdParty/Ert/.gitignore @@ -22,6 +22,5 @@ python/lib64 scratch.sparsebundle *.iml *.DS_Store -__ert_lib_path.py -__ert_lib_info.py - +__ecl_lib_path.py +__ecl_lib_info.py diff --git a/ThirdParty/Ert/CMakeLists.txt b/ThirdParty/Ert/CMakeLists.txt index af90f27865..cb4d90eb8f 100644 --- a/ThirdParty/Ert/CMakeLists.txt +++ b/ThirdParty/Ert/CMakeLists.txt @@ -129,17 +129,6 @@ set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin) -if (BUILD_SHARED_LIBS) - set( LIBRARY_TYPE SHARED ) -else() - set( LIBRARY_TYPE STATIC ) - if (BUILD_ERT) - message(FATAL_ERROR "The full ERT application must be built with shared libraries") - endif() - if (BUILD_PYTHON) - message(FATAL_ERROR "The Python wrappers require shared libraries") - endif() -endif() if (MSVC) add_definitions( -D__func__="\\"????\\"") @@ -179,12 +168,14 @@ endif() include_directories( ${PROJECT_SOURCE_DIR}/libecl_well/include ) add_subdirectory( libecl_well ) - if (BUILD_PYTHON) if (ERT_WINDOWS) - message(STATUS "Python is not supported on Windows") + message(WARNING "Python is not supported on Windows") + set( BUILD_PYTHON OFF ) else() - include(cmake/python.cmake2) + # If finding the Python interpreter and required packages + # fails in the python/CMakeLists.txt file the BUILD_PYTHON + # will be set to OFF. add_subdirectory( python ) if(ERT_DOC) @@ -193,3 +184,16 @@ if (BUILD_PYTHON) endif() endif() +if (BUILD_PYTHON) + if (NOT ${BUILD_SHARED_LIBS}) + message(FATAL_ERROR "The Python wrappers require shared libraries") + endif() +endif() + + + +configure_file( cmake/libecl-config.cmake.in libecl-config.cmake @ONLY) +configure_file( cmake/libecl-config-version.cmake.in libecl-config-version.cmake @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libecl-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/libecl-config-version.cmake + DESTINATION lib/libecl ) diff --git a/ThirdParty/Ert/README.md b/ThirdParty/Ert/README.md index 783bfb5291..b63800a9ba 100644 --- a/ThirdParty/Ert/README.md +++ b/ThirdParty/Ert/README.md @@ -131,6 +131,7 @@ filesystem. One level above the toplevel source directory is a practical choice. ccmake ``` Go through several 'configure' steps with CMake and generate native build files. + 3. Exit ccmake and invoke the native build system, i.e. ordinarily 'make' on Linux. 4. Subsequent builds can be performed using just the native make command, as in diff --git a/ThirdParty/Ert/cmake/cmake_pyc b/ThirdParty/Ert/cmake/cmake_pyc deleted file mode 100644 index 7d0ab553b6..0000000000 --- a/ThirdParty/Ert/cmake/cmake_pyc +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python -import py_compile -import os -import os.path -import sys - -# Small 'python compiler' used in the build system for ert. The -# commandline arguments should be: -# -# cmake_pyc.py src1.py src2.py src3.py /path/to/pyc/files -# -# The input source files can contain a path component like -# path/src1.py, but the path will not be recreated in the target -# domain. - - -def compile_file(src_file , target_file): - path = os.path.dirname( target_file ) - if not os.path.exists( path ): - os.makedirs( path ) - try: - py_compile.compile( src_file , cfile = target_file , doraise = True) - except Exception as error: - sys.exit(str(error)) - - -target_path = sys.argv[-1] -for src_file in sys.argv[1:-1]: - compile_file( src_file , "%s/%sc" % (target_path , os.path.basename(src_file))) - -sys.exit(0) - - - - diff --git a/ThirdParty/Ert/cmake/cmake_pyc2 b/ThirdParty/Ert/cmake/cmake_pyc2 deleted file mode 100644 index 885720d4a0..0000000000 --- a/ThirdParty/Ert/cmake/cmake_pyc2 +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python -import py_compile -import os -import os.path -import sys -import shutil - - -src_file = sys.argv[1] -target_file = sys.argv[2] - -(target_path , tail) = os.path.split( target_file ) -if not os.path.exists( target_path ): - try: - os.makedirs( target_path ) - except: - # When running with make -j 4 there might be a race to create this directory. - pass - -shutil.copyfile( src_file , target_file ) -shutil.copystat( src_file , target_file ) -try: - py_compile.compile( target_file , doraise = True) -except Exception as error: - sys.exit("py_compile(%s) failed:%s" % (target_file , error)) - - -sys.exit(0) - - - - diff --git a/ThirdParty/Ert/cmake/cmake_pyc_file b/ThirdParty/Ert/cmake/cmake_pyc_file deleted file mode 100644 index 22c7425a4d..0000000000 --- a/ThirdParty/Ert/cmake/cmake_pyc_file +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python -import py_compile -import os -import sys -import os.path - -# Small 'python compiler' used in the build system for ert. - -for file in sys.argv[1:]: - try: - py_compile.compile( file , doraise = True ) - except Exception as error: - sys.exit("py_compile(%s) failed:%s" % (file , error)) - - -sys.exit(0) - - - - diff --git a/ThirdParty/Ert/cmake/cmake_pyc_tree b/ThirdParty/Ert/cmake/cmake_pyc_tree deleted file mode 100644 index 249eb84ede..0000000000 --- a/ThirdParty/Ert/cmake/cmake_pyc_tree +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python -import py_compile -import os -import sys -import os.path - -# Small 'python compiler' used in the build system for ert. The -# commandline argument should be the top level name of directory -# containing python source code. The 'compiler' will walk through the -# tree and in-place compile all the python files. - - -root_path = sys.argv[1] -for (root , dir_list , file_list) in os.walk( root_path ): - for file in file_list: - full_path = os.path.join( root , file ) - (tmp , ext) = os.path.splitext( full_path ) - if ext == ".py": - py_file = full_path - pyc_file = full_path + "c" - if os.path.exists( pyc_file ): - os.unlink( pyc_file ) - - try: - print "Compiling: %s" % py_file - py_compile.compile( py_file , doraise = True ) - except Exception as error: - sys.exit("py_compile(%s) failed:%s" % (py_file , error)) - - -sys.exit(0) - - - - diff --git a/ThirdParty/Ert/cmake/libecl-config-version.cmake.in b/ThirdParty/Ert/cmake/libecl-config-version.cmake.in new file mode 100644 index 0000000000..3a8e633c45 --- /dev/null +++ b/ThirdParty/Ert/cmake/libecl-config-version.cmake.in @@ -0,0 +1,14 @@ +set(PACKAGE_VERSION @ERT_VERSION_MAJOR@.@ERT_VERSION_MINOR@.@ERT_VERSION_PATCH@) +set(PACKAGE_VERSION_MAJOR @ERT_VERSION_MAJOR@) +set(PACKAGE_VERSION_MINOR @ERT_VERSION_MINOR@) +set(PACKAGE_VERSION_PATCH @ERT_VERSION_MICRO@) + +set(libecl_INCLUDE_DIRS @CMAKE_INSTALL_PREFIX@/include) +set(libecl_LIBRARIES -lecl_well -lecl -lert_geometry -lert_util) +link_directories( @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ ) +include_directories( @CMAKE_INSTALL_PREFIX@/include ) + +set( CMAKE_MODULE_PATH @CMAKE_INSTALL_PREFIX@/share/cmake/Modules ${CMAKE_MODULE_PATH}) +if (@BUILD_PYTHON@) + set(libecl_PYTHONPATH @CMAKE_INSTALL_PREFIX@/@PYTHON_INSTALL_PREFIX@ ) +endif() \ No newline at end of file diff --git a/ThirdParty/Ert/cmake/libecl-config.cmake.in b/ThirdParty/Ert/cmake/libecl-config.cmake.in new file mode 100644 index 0000000000..318a35c20b --- /dev/null +++ b/ThirdParty/Ert/cmake/libecl-config.cmake.in @@ -0,0 +1,10 @@ +set(libecl_INCLUDE_DIRS @CMAKE_INSTALL_PREFIX@/include) +set(libecl_LIBRARIES -lecl_well -lecl -lert_geometry -lert_util) + +set( CMAKE_MODULE_PATH @CMAKE_INSTALL_PREFIX@/share/cmake/Modules ${CMAKE_MODULE_PATH}) +link_directories( @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ ) +include_directories( @CMAKE_INSTALL_PREFIX@/include ) + +if (@BUILD_PYTHON@) + set(libecl_PYTHONPATH @CMAKE_INSTALL_PREFIX@/@PYTHON_INSTALL_PREFIX@ ) +endif() \ No newline at end of file diff --git a/ThirdParty/Ert/cmake/python.cmake b/ThirdParty/Ert/cmake/python.cmake deleted file mode 100644 index 6b567a8d35..0000000000 --- a/ThirdParty/Ert/cmake/python.cmake +++ /dev/null @@ -1,25 +0,0 @@ -macro(add_python_target tgt PYTHON_INSTALL_PATH) - SET(OUT_FILES "") - foreach(file ${python_source_files}) - set(OUT ${CMAKE_CURRENT_BINARY_DIR}/${file}.pyc) - list(APPEND OUT_FILES ${OUT}) -#------------------------------------------------------ - ADD_CUSTOM_COMMAND( - OUTPUT ${OUT} - COMMAND ${PROJECT_SOURCE_DIR}/cmake/cmake_pyc - ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.py ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PATH} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.py) -#------------------------------------------------------ - if (INSTALL_ERT) - install(FILES ${PROJECT_BINARY_DIR}/${PYTHON}/${file}.pyc DESTINATION ${CMAKE_INSTALL_PREFIX}/${PYTHON_INSTALL_PATH}) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${file}.py DESTINATION ${CMAKE_INSTALL_PREFIX}/${PYTHON_INSTALL_PATH}) - endif() - endforeach(file) - list(REMOVE_DUPLICATES OUT_FILES) - - ADD_CUSTOM_TARGET( - ${tgt} ALL DEPENDS ${OUT_FILES}) - -endmacro() - - diff --git a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_diff.py b/ThirdParty/Ert/docs/course/config/jobs/snake_oil_diff.py index afabb261f9..51ef5d472f 100644 --- a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_diff.py +++ b/ThirdParty/Ert/docs/course/config/jobs/snake_oil_diff.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from ert.ecl import EclSum +from ecl.ecl import EclSum def writeDiff(filename, vector1, vector2): with open(filename, "w") as f: diff --git a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_npv.py b/ThirdParty/Ert/docs/course/config/jobs/snake_oil_npv.py index 4ff61251bc..126c917725 100644 --- a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_npv.py +++ b/ThirdParty/Ert/docs/course/config/jobs/snake_oil_npv.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from ert.ecl import EclSum +from ecl.ecl import EclSum OIL_PRICES = {"2010-01-01": 78.33, "2010-02-01": 76.39, diff --git a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py b/ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py index cf1557b19b..40b4d4a6a1 100644 --- a/ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py +++ b/ThirdParty/Ert/docs/course/config/jobs/snake_oil_simulator.py @@ -3,8 +3,8 @@ from datetime import datetime import os import sys -from ert.ecl import EclSum, EclSumTStep -from ert.test import ExtendedTestCase +from ecl.ecl import EclSum, EclSumTStep +from ecl.test import ExtendedTestCase try: from synthesizer import OilSimulator diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw.h index eca17750c8..72a74fd20f 100644 --- a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw.h +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw.h @@ -40,8 +40,7 @@ extern "C" { typedef enum { ECL_KW_READ_OK = 0, - ECL_KW_READ_FAIL = 1, - ECL_KW_READ_SKIP = 2 + ECL_KW_READ_FAIL = 1 } ecl_read_status_enum; /* @@ -111,6 +110,8 @@ extern "C" { void ecl_kw_iset(ecl_kw_type *ecl_kw , int i , const void *iptr); void ecl_kw_iset_char_ptr( ecl_kw_type * ecl_kw , int index, const char * s); void ecl_kw_iset_string8(ecl_kw_type * ecl_kw , int index , const char *s8); + void ecl_kw_iset_string_ptr(ecl_kw_type*, int, const char*); + const char * ecl_kw_iget_string_ptr(const ecl_kw_type *, int); const char * ecl_kw_iget_char_ptr( const ecl_kw_type * ecl_kw , int i); void * ecl_kw_iget_ptr(const ecl_kw_type *, int); int ecl_kw_get_size(const ecl_kw_type *); diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw_magic.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw_magic.h index 8bdd9512b6..846ad40765 100644 --- a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw_magic.h +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_kw_magic.h @@ -414,6 +414,7 @@ values (2e20) are denoted with '*'. #define MINISTEP_KW "MINISTEP" #define STARTDAT_KW "STARTDAT" /* Intgere keyword containing day,month,year. */ #define WGNAMES_KW "WGNAMES" /* The names of wells/groups for the summary vectors. */ +#define NAMES_KW "NAMES" /* Alias for WGNAMES_KW. */ #define KEYWORDS_KW "KEYWORDS" /* The variable type for the various summary vectors. */ #define UNITS_KW "UNITS" /* The units, i.e SM^3/DAY the summary vectors. */ #define DIMENS_KW "DIMENS" /* The dimensions of the grid - also used in the GRID files. */ diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_type.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_type.h index 8ae1597916..7a596ddcf3 100644 --- a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_type.h +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_type.h @@ -38,6 +38,8 @@ extern "C" { different code paths for C and C++. */ +#define ECL_STRING8_LENGTH 8 +#define ECL_TYPE_LENGTH 4 typedef enum { ECL_CHAR_TYPE = 0, @@ -46,7 +48,7 @@ typedef enum { ECL_INT_TYPE = 3, ECL_BOOL_TYPE = 4, ECL_MESS_TYPE = 5, - ECL_C010_TYPE = 6 // See comment immediately above about the limited support of this type. + ECL_STRING_TYPE = 7 } ecl_type_enum; #define ECL_TYPE_ENUM_DEFS {.value = 0 , .name = "ECL_CHAR_TYPE"}, \ @@ -54,9 +56,10 @@ typedef enum { {.value = 2 , .name = "ECL_DOUBLE_TYPE"}, \ {.value = 3 , .name = "ECL_INT_TYPE"}, \ {.value = 4 , .name = "ECL_BOOL_TYPE"}, \ -{.value = 5 , .name = "ECL_MESS_TYPE"} +{.value = 5 , .name = "ECL_MESS_TYPE"}, \ +{.value = 7 , .name = "ECL_STRING_TYPE"} -#define ECL_TYPE_ENUM_SIZE 6 +#define ECL_TYPE_ENUM_SIZE 7 /* Character data in ECLIPSE files comes as an array of fixed-length @@ -77,13 +80,13 @@ typedef enum { #ifdef __cplusplus struct ecl_type_struct { - const ecl_type_enum type; - const size_t element_size; + const ecl_type_enum type; + const size_t element_size; - ecl_type_struct( ecl_type_enum t, size_t es) : - type( t ), - element_size( es ) - {} + ecl_type_struct( ecl_type_enum t, size_t es) : + type( t ), + element_size( es ) + {} }; #define ECL_INT ecl_data_type( ECL_INT_TYPE, sizeof(int)) @@ -92,13 +95,13 @@ struct ecl_type_struct { #define ECL_BOOL ecl_data_type( ECL_BOOL_TYPE, sizeof(int)) #define ECL_CHAR ecl_data_type( ECL_CHAR_TYPE, ECL_STRING8_LENGTH + 1) #define ECL_MESS ecl_data_type( ECL_MESS_TYPE, 0) -#define ECL_C010 ecl_data_type( ECL_C010_TYPE . ECL_STRING10_LENGTH + 1) +#define ECL_STRING(size) ecl_data_type(ECL_STRING_TYPE, size + 1) #else struct ecl_type_struct { - const ecl_type_enum type; - const size_t element_size; + const ecl_type_enum type; + const size_t element_size; }; #define ECL_CHAR (ecl_data_type) {.type = ECL_CHAR_TYPE, .element_size = ECL_STRING8_LENGTH + 1} @@ -107,26 +110,23 @@ struct ecl_type_struct { #define ECL_DOUBLE (ecl_data_type) {.type = ECL_DOUBLE_TYPE, .element_size = sizeof(double)} #define ECL_BOOL (ecl_data_type) {.type = ECL_BOOL_TYPE, .element_size = sizeof(int)} #define ECL_MESS (ecl_data_type) {.type = ECL_MESS_TYPE, .element_size = 0} -#define ECL_C010 (ecl_data_type) {.type = ECL_C010_TYPE, .element_size = ECL_STRING10_LENGTH + 1} +#define ECL_STRING(size) (ecl_data_type) {.type = ECL_STRING_TYPE, .element_size = size + 1} #endif - #ifdef __cplusplus extern "C" { #endif typedef struct ecl_type_struct ecl_data_type; - - ecl_data_type ecl_type_create_from_name(const char *); ecl_data_type ecl_type_create(const ecl_type_enum, const size_t); ecl_data_type ecl_type_create_from_type(const ecl_type_enum); ecl_type_enum ecl_type_get_type(const ecl_data_type); -const char * ecl_type_get_name(const ecl_data_type); +char * ecl_type_alloc_name(const ecl_data_type); int ecl_type_get_sizeof_ctype(const ecl_data_type); int ecl_type_get_sizeof_ctype_fortio(const ecl_data_type); @@ -134,14 +134,18 @@ int ecl_type_get_sizeof_ctype_fortio(const ecl_data_type); bool ecl_type_is_equal(const ecl_data_type, const ecl_data_type); bool ecl_type_is_numeric(const ecl_data_type); +bool ecl_type_is_alpha(const ecl_data_type); bool ecl_type_is_char(const ecl_data_type); bool ecl_type_is_int(const ecl_data_type); bool ecl_type_is_float(const ecl_data_type); bool ecl_type_is_double(const ecl_data_type); bool ecl_type_is_mess(const ecl_data_type); bool ecl_type_is_bool(const ecl_data_type); -bool ecl_type_is_C010(const ecl_data_type); +bool ecl_type_is_string(const ecl_data_type); +// Temporary fixup for OPM. +char * ecl_type_get_name(const ecl_data_type); + #ifdef __cplusplus } #endif diff --git a/ThirdParty/Ert/libecl/include/ert/ecl/ecl_units.h b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_units.h new file mode 100644 index 0000000000..ecee98a662 --- /dev/null +++ b/ThirdParty/Ert/libecl/include/ert/ecl/ecl_units.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2017 Statoil ASA, Norway. + + The file 'ecl_units.h' is part of ERT - Ensemble based Reservoir Tool. + + ERT 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. + + ERT 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 at + for more details. +*/ + +#ifndef ECL_UNITS_H +#define ECL_UNITS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define ECL_UNITS_CUBIC(x) ((x)*(x)*(x)) +#define ECL_UNITS_MILLI(x) ((x)*0.001) +#define ECL_UNITS_MEGA(x) ((x)*1000000) + +#define ECL_UNITS_LENGTH_INCH 0.0254 +#define ECL_UNITS_LENGTH_FEET 12 * ECL_UNITS_LENGTH_INCH + +#define ECL_UNITS_VOLUME_GALLON 231 * ECL_UNITS_CUBIC( ECL_UNITS_LENGTH_INCH ) +#define ECL_UNITS_VOLUME_BARREL ECL_UNITS_VOLUME_GALLON * 42 +#define ECL_UNITS_VOLUME_LITER 0.001 +#define ECL_UNITS_VOLUME_MILLI_LITER ECL_UNITS_MILLI( ECL_UNITS_VOLUME_LITER ) +#define ECL_UNITS_VOLUME_GAS_FIELD ECL_UNITS_MEGA( ECL_UNITS_CUBIC( ECL_UNITS_LENGTH_FEET ) ) + +#define ECL_UNITS_TIME_HOUR 3600 +#define ECL_UNITS_TIME_DAY 24 * ECL_UNITS_TIME_HOUR + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ThirdParty/Ert/libecl/src/CMakeLists.txt b/ThirdParty/Ert/libecl/src/CMakeLists.txt index d59c9baf95..dcbf36677a 100644 --- a/ThirdParty/Ert/libecl/src/CMakeLists.txt +++ b/ThirdParty/Ert/libecl/src/CMakeLists.txt @@ -45,6 +45,7 @@ set( source_files ${ext_source}) set( header_files + ecl_units.h ecl_rsthead.h ecl_sum_tstep.h ecl_rst_file.h @@ -95,7 +96,7 @@ if (ERT_USE_OPENMP) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OpenMP_SHARED_LINKER_FLAGS}") endif() -add_library( ecl ${LIBRARY_TYPE} ${source_files} ) +add_library( ecl ${source_files} ) set_target_properties( ecl PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR}) if (USE_RUNPATH) add_runpath( ecl ) diff --git a/ThirdParty/Ert/libecl/src/ecl_file.c b/ThirdParty/Ert/libecl/src/ecl_file.c index 064cb0d027..5a5f3c695f 100644 --- a/ThirdParty/Ert/libecl/src/ecl_file.c +++ b/ThirdParty/Ert/libecl/src/ecl_file.c @@ -539,13 +539,6 @@ static bool ecl_file_scan( ecl_file_type * ecl_file ) { else break; } - - if (read_status == ECL_KW_READ_SKIP) { - bool skip_ok = ecl_kw_fskip_data( work_kw , ecl_file->fortio ); - fprintf(stderr,"** Warning: keyword %s is of type \'C010\' - will be skipped when loading file. skip_ok:%d\n" , ecl_kw_get_header( work_kw ) , skip_ok); - if (!skip_ok) - break; - } } } diff --git a/ThirdParty/Ert/libecl/src/ecl_file_view.c b/ThirdParty/Ert/libecl/src/ecl_file_view.c index 5f74d3f1ce..8798a90caf 100644 --- a/ThirdParty/Ert/libecl/src/ecl_file_view.c +++ b/ThirdParty/Ert/libecl/src/ecl_file_view.c @@ -358,10 +358,12 @@ void ecl_file_view_fprintf_kw_list(const ecl_file_view_type * ecl_file_view , FI int i; for (i=0; i < vector_get_size( ecl_file_view->kw_list ); i++) { const ecl_file_kw_type * file_kw = vector_iget_const( ecl_file_view->kw_list , i ); + char * type_name = ecl_type_alloc_name(ecl_file_kw_get_data_type(file_kw)); fprintf(stream , "%-8s %7d:%s\n", ecl_file_kw_get_header( file_kw ) , ecl_file_kw_get_size( file_kw ) , - ecl_type_get_name( ecl_file_kw_get_data_type( file_kw ))); + type_name); + free(type_name); } } diff --git a/ThirdParty/Ert/libecl/src/ecl_grid.c b/ThirdParty/Ert/libecl/src/ecl_grid.c index 5f9004ceee..0e2dd610ef 100644 --- a/ThirdParty/Ert/libecl/src/ecl_grid.c +++ b/ThirdParty/Ert/libecl/src/ecl_grid.c @@ -5401,7 +5401,7 @@ static bool ecl_grid_get_property__(const ecl_grid_type * ecl_grid , const ecl_k return false; } else { - util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_type_get_name( data_type ) , __func__); + util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_type_alloc_name( data_type ) , __func__); return false; } } @@ -5466,7 +5466,7 @@ double ecl_grid_get_property(const ecl_grid_type * ecl_grid , const ecl_kw_type return -1; /* Tried to lookup an inactive cell. */ } else { - util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_type_get_name( data_type ) , __func__); + util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_type_alloc_name( data_type ) , __func__); return -1; } } @@ -5517,7 +5517,7 @@ void ecl_grid_get_column_property(const ecl_grid_type * ecl_grid , const ecl_kw_ } } } else - util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_type_get_name( data_type ) , __func__); + util_abort("%s: sorry - can not lookup ECLIPSE type:%s with %s.\n",__func__ , ecl_type_alloc_name( data_type ) , __func__); } diff --git a/ThirdParty/Ert/libecl/src/ecl_kw.c b/ThirdParty/Ert/libecl/src/ecl_kw.c index d7ebf1ef87..d562f1a09a 100644 --- a/ThirdParty/Ert/libecl/src/ecl_kw.c +++ b/ThirdParty/Ert/libecl/src/ecl_kw.c @@ -61,7 +61,6 @@ UTIL_IS_INSTANCE_FUNCTION(ecl_kw , ECL_KW_TYPE_ID ) #define BLOCKSIZE_NUMERIC 1000 #define BLOCKSIZE_CHAR 105 -#define BLOCKSIZE_C010 105 @@ -113,7 +112,6 @@ UTIL_IS_INSTANCE_FUNCTION(ecl_kw , ECL_KW_TYPE_ID ) */ #define READ_FMT_CHAR "%8c" -#define READ_FMT_C010 "%10c" #define READ_FMT_FLOAT "%gE" #define READ_FMT_INT "%d" #define READ_FMT_MESS "%8c" @@ -122,7 +120,6 @@ UTIL_IS_INSTANCE_FUNCTION(ecl_kw , ECL_KW_TYPE_ID ) #define WRITE_FMT_CHAR " '%-8s'" -#define WRITE_FMT_C010 " '%-10s'" #define WRITE_FMT_INT " %11d" #define WRITE_FMT_FLOAT " %11.8fE%+03d" #define WRITE_FMT_DOUBLE " %17.14fD%+03d" @@ -161,75 +158,68 @@ UTIL_IS_INSTANCE_FUNCTION(ecl_kw , ECL_KW_TYPE_ID ) ecl_type_enum ecl_kw_get_type(const ecl_kw_type *); void ecl_kw_set_data_type(ecl_kw_type * ecl_kw, ecl_data_type data_type); -static const char * get_read_fmt(const ecl_data_type data_type ) { +static char * alloc_read_fmt_string(const ecl_data_type ecl_type) { + return util_alloc_sprintf( + "%%%dc", + ecl_type_get_sizeof_ctype_fortio(ecl_type) + ); +} + +static char * alloc_read_fmt(const ecl_data_type data_type ) { switch(ecl_type_get_type(data_type)) { case(ECL_CHAR_TYPE): - return READ_FMT_CHAR; - break; - case(ECL_C010_TYPE): - return READ_FMT_C010; - break; + return util_alloc_string_copy(READ_FMT_CHAR); case(ECL_INT_TYPE): - return READ_FMT_INT; - break; + return util_alloc_string_copy(READ_FMT_INT); case(ECL_FLOAT_TYPE): - return READ_FMT_FLOAT; - break; + return util_alloc_string_copy(READ_FMT_FLOAT); case(ECL_DOUBLE_TYPE): - return READ_FMT_DOUBLE; - break; + return util_alloc_string_copy(READ_FMT_DOUBLE); case(ECL_BOOL_TYPE): - return READ_FMT_BOOL; - break; + return util_alloc_string_copy(READ_FMT_BOOL); case(ECL_MESS_TYPE): - return READ_FMT_MESS; - break; + return util_alloc_string_copy(READ_FMT_MESS); + case(ECL_STRING_TYPE): + return alloc_read_fmt_string(data_type); default: - util_abort("%s: invalid ecl_type:%d \n",__func__ , ecl_type_get_type(data_type)); + util_abort("%s: invalid ecl_type:%s \n",__func__ , ecl_type_alloc_name(data_type)); return NULL; } } +static char * alloc_write_fmt_string(const ecl_data_type ecl_type) { + return util_alloc_sprintf( + " '%%-%ds'", + ecl_type_get_sizeof_ctype_fortio(ecl_type) + ); +} -static const char * ecl_kw_get_write_fmt(const ecl_data_type data_type) { +static char * alloc_write_fmt(const ecl_data_type data_type) { switch(ecl_type_get_type(data_type)) { case(ECL_CHAR_TYPE): - return WRITE_FMT_CHAR; - break; - case(ECL_C010_TYPE): - return WRITE_FMT_C010; - break; + return util_alloc_string_copy(WRITE_FMT_CHAR); case(ECL_INT_TYPE): - return WRITE_FMT_INT; - break; + return util_alloc_string_copy(WRITE_FMT_INT); case(ECL_FLOAT_TYPE): - return WRITE_FMT_FLOAT; - break; + return util_alloc_string_copy(WRITE_FMT_FLOAT); case(ECL_DOUBLE_TYPE): - return WRITE_FMT_DOUBLE; - break; + return util_alloc_string_copy(WRITE_FMT_DOUBLE); case(ECL_BOOL_TYPE): - return WRITE_FMT_BOOL; - break; + return util_alloc_string_copy(WRITE_FMT_BOOL); case(ECL_MESS_TYPE): - return WRITE_FMT_MESS; - break; + return util_alloc_string_copy(WRITE_FMT_MESS); + case(ECL_STRING_TYPE): + return alloc_write_fmt_string(data_type); default: - util_abort("%s: invalid ecl_type:%d \n",__func__ , ecl_type_get_type(data_type)); + util_abort("%s: invalid ecl_type: %s\n",__func__ , ecl_type_alloc_name(data_type)); return NULL; } } static int get_blocksize( ecl_data_type data_type ) { - if (ecl_type_is_char(data_type)) + if (ecl_type_is_alpha(data_type)) return BLOCKSIZE_CHAR; - if (ecl_type_is_mess(data_type)) - return BLOCKSIZE_CHAR; - - if (ecl_type_is_C010(data_type)) - return BLOCKSIZE_C010; - return BLOCKSIZE_NUMERIC; } @@ -238,24 +228,20 @@ static int get_columns(const ecl_data_type data_type) { switch(ecl_type_get_type(data_type)) { case(ECL_CHAR_TYPE): return COLUMNS_CHAR; - break; case(ECL_INT_TYPE): return COLUMNS_INT; - break; case(ECL_FLOAT_TYPE): return COLUMNS_FLOAT; - break; case(ECL_DOUBLE_TYPE): return COLUMNS_DOUBLE; - break; case(ECL_BOOL_TYPE): return COLUMNS_BOOL; - break; case(ECL_MESS_TYPE): return COLUMNS_MESSAGE; - break; + case(ECL_STRING_TYPE): + return COLUMNS_CHAR; // TODO: Is this correct? default: - util_abort("%s: invalid ecl_type:%d \n",__func__ , ecl_type_get_type(data_type)); + util_abort("%s: invalid ecl_type: %s\n",__func__ , ecl_type_alloc_name(data_type)); return -1; } } @@ -535,17 +521,13 @@ ecl_kw_type * ecl_kw_alloc_new(const char * header , int size, ecl_data_type da ecl_kw_type * ecl_kw_alloc( const char * header , int size , ecl_data_type data_type ) { - if (ecl_type_is_C010(data_type)) - return NULL; - { - ecl_kw_type *ecl_kw; + ecl_kw_type *ecl_kw; - ecl_kw = ecl_kw_alloc_empty(); - ecl_kw_initialize(ecl_kw , header , size , data_type); - ecl_kw_alloc_data(ecl_kw); + ecl_kw = ecl_kw_alloc_empty(); + ecl_kw_initialize(ecl_kw , header , size , data_type); + ecl_kw_alloc_data(ecl_kw); - return ecl_kw; - } + return ecl_kw; } @@ -812,6 +794,12 @@ const char * ecl_kw_iget_char_ptr( const ecl_kw_type * ecl_kw , int i) { return ecl_kw_iget_ptr( ecl_kw , i ); } +const char * ecl_kw_iget_string_ptr( const ecl_kw_type * ecl_kw, int i) { + if (ecl_kw_get_type(ecl_kw) != ECL_STRING_TYPE) + util_abort("%s: Keyword: %s is wrong type - aborting \n",__func__ , ecl_kw_get_header8(ecl_kw)); + return ecl_kw_iget_ptr( ecl_kw , i ); +} + /** This will set the elemnts of the ecl_kw data storage in index to @@ -864,6 +852,30 @@ void ecl_kw_iset_char_ptr( ecl_kw_type * ecl_kw , int index, const char * s) { } } +/** + * This function will verify that the given string is of approperiate length + * (0 <= lenght <= data_type.element_size). If so, the elements of @s will be + * written to the @ecl_kw string array starting at @index. + */ +void ecl_kw_iset_string_ptr( ecl_kw_type * ecl_kw, int index, const char * s) { + if(!ecl_type_is_alpha(ecl_kw_get_data_type(ecl_kw))) { + char * type_name = ecl_type_alloc_name(ecl_kw_get_data_type(ecl_kw)); + util_abort("%s: Expected alphabetic data type (CHAR, CXXX or MESS), was %s\n", __func__, type_name); + } + + size_t input_len = strlen(s); + size_t type_len = ecl_type_get_sizeof_ctype_fortio(ecl_kw_get_data_type(ecl_kw)); + + if(input_len > type_len) + util_abort("%s: String of length %d cannot hold input string of length %d\n", __func__, type_len, input_len); + + char * ecl_string = (char *) ecl_kw_iget_ptr(ecl_kw, index); + for(int i = 0; i < input_len; ++i) + ecl_string[i] = s[i]; + + ecl_string[input_len] = '\0'; +} + /** This function will compare the string at position @index with the @@ -1078,7 +1090,7 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { const int blocksize = get_blocksize( ecl_kw->data_type ); if (fmt_file) { const int blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1); - const char * read_fmt = get_read_fmt( ecl_kw->data_type ); + char * read_fmt = alloc_read_fmt( ecl_kw->data_type ); FILE * stream = fortio_get_FILE(fortio); int offset = 0; int index = 0; @@ -1090,6 +1102,14 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { case(ECL_CHAR_TYPE): ecl_kw_fscanf_qstring(&ecl_kw->data[offset] , read_fmt , 8, stream); break; + case(ECL_STRING_TYPE): + ecl_kw_fscanf_qstring( + &ecl_kw->data[offset], + read_fmt, + ecl_type_get_sizeof_ctype_fortio(ecl_kw_get_data_type(ecl_kw)), + stream + ); + break; case(ECL_INT_TYPE): { int iread = fscanf(stream , read_fmt , (int *) &ecl_kw->data[offset]); @@ -1141,10 +1161,11 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { /* Skip the trailing newline */ fortio_fseek( fortio , 1 , SEEK_CUR); + free(read_fmt); return true; } else { bool read_ok = true; - if (ecl_type_is_char(ecl_kw->data_type) || ecl_type_is_mess(ecl_kw->data_type)) { + if (ecl_type_is_char(ecl_kw->data_type) || ecl_type_is_mess(ecl_kw->data_type) || ecl_type_is_string(ecl_kw->data_type)) { const int blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1); int ib = 0; while (true) { @@ -1157,9 +1178,11 @@ bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { int record_size = fortio_init_read(fortio); if (record_size >= 0) { int ir; + const int sizeof_ctype = ecl_type_get_sizeof_ctype(ecl_kw->data_type); + const int sizeof_ctype_fortio = ecl_type_get_sizeof_ctype_fortio(ecl_kw->data_type); for (ir = 0; ir < read_elm; ir++) { - util_fread( &ecl_kw->data[(ib * blocksize + ir) * ecl_kw_get_sizeof_ctype(ecl_kw)] , 1 , ECL_STRING8_LENGTH , stream , __func__); - ecl_kw->data[(ib * blocksize + ir) * ecl_kw_get_sizeof_ctype(ecl_kw) + ECL_STRING8_LENGTH] = null_char; + util_fread( &ecl_kw->data[(ib * blocksize + ir) * sizeof_ctype] , 1 , sizeof_ctype_fortio , stream , __func__); + ecl_kw->data[(ib * blocksize + ir) * sizeof_ctype + sizeof_ctype_fortio] = null_char; } read_ok = fortio_complete_read(fortio , record_size); } else @@ -1228,31 +1251,27 @@ bool ecl_kw_fread_realloc_data(ecl_kw_type *ecl_kw, fortio_type *fortio) { */ bool ecl_kw_fskip_data__( ecl_data_type data_type , const int element_count , fortio_type * fortio) { + if (element_count <= 0) + return true; + bool fmt_file = fortio_fmt_file(fortio); - bool skip_ok = true; - if (element_count > 0) { - if (fmt_file) { - /* Formatted skipping actually involves reading the data - nice ??? */ - ecl_kw_type * tmp_kw = ecl_kw_alloc_empty( ); - ecl_kw_initialize( tmp_kw , "WORK" , element_count , data_type ); - ecl_kw_alloc_data(tmp_kw); - ecl_kw_fread_data(tmp_kw , fortio); - ecl_kw_free( tmp_kw ); - } else { - const int blocksize = get_blocksize( data_type ); - const int block_count = element_count / blocksize + (element_count % blocksize == 0 ? 0 : 1); + if (fmt_file) { + /* Formatted skipping actually involves reading the data - nice ??? */ + ecl_kw_type * tmp_kw = ecl_kw_alloc_empty( ); + ecl_kw_initialize( tmp_kw , "WORK" , element_count , data_type ); + ecl_kw_alloc_data(tmp_kw); + ecl_kw_fread_data(tmp_kw , fortio); + ecl_kw_free( tmp_kw ); + } else { + const int blocksize = get_blocksize( data_type ); + const int block_count = element_count / blocksize + (element_count % blocksize != 0); + int element_size = ecl_type_get_sizeof_ctype_fortio(data_type); - int element_size = ecl_type_get_sizeof_ctype(data_type); - if(ecl_type_is_char(data_type)) - element_size = ECL_STRING8_LENGTH; - - if(ecl_type_is_C010(data_type)) - element_size = ECL_STRING10_LENGTH; - - skip_ok = fortio_data_fskip(fortio, element_size, element_count, block_count); - } + if(!fortio_data_fskip(fortio, element_size, element_count, block_count)) + return false; } - return skip_ok; + + return true; } @@ -1289,51 +1308,47 @@ ecl_read_status_enum ecl_kw_fread_header(ecl_kw_type *ecl_kw , fortio_type * for char ecl_type_str[ECL_TYPE_LENGTH + 1]; int record_size; int size; - bool OK = true; if (fmt_file) { - OK = ecl_kw_fscanf_qstring(header , "%8c" , 8 , stream); - if (OK) { - int read_count = fscanf(stream , "%d" , &size); - if (read_count == 1) { - ecl_kw_fscanf_qstring(ecl_type_str , "%4c" , 4 , stream); - fgetc(stream); /* Reading the trailing newline ... */ - } else - util_abort("%s: reading failed - at end of file?\n",__func__); - } - } else { - header[ECL_STRING8_LENGTH] = null_char; + if(!ecl_kw_fscanf_qstring(header , "%8c" , 8 , stream)) + return ECL_KW_READ_FAIL; + + int read_count = fscanf(stream , "%d" , &size); + if (read_count != 1) + util_abort("%s: reading failed - at end of file?\n",__func__); + + ecl_kw_fscanf_qstring(ecl_type_str , "%4c" , 4 , stream); + fgetc(stream); /* Reading the trailing newline ... */ + } + else { + header[ECL_STRING8_LENGTH] = null_char; ecl_type_str[ECL_TYPE_LENGTH] = null_char; record_size = fortio_init_read(fortio); - if (record_size > 0) { - char buffer[ECL_KW_HEADER_DATA_SIZE]; - size_t read_bytes = fread(buffer , 1 , ECL_KW_HEADER_DATA_SIZE , stream); - if (read_bytes == ECL_KW_HEADER_DATA_SIZE) { - memcpy( header , &buffer[0] , ECL_STRING8_LENGTH); - size = *( (int *) &buffer[ECL_STRING8_LENGTH] ); - memcpy( ecl_type_str , &buffer[ECL_STRING8_LENGTH + sizeof(size)] , ECL_TYPE_LENGTH); + if (record_size <= 0) + return ECL_KW_READ_FAIL; - OK = fortio_complete_read(fortio , record_size); - } else - OK = false; + char buffer[ECL_KW_HEADER_DATA_SIZE]; + size_t read_bytes = fread(buffer , 1 , ECL_KW_HEADER_DATA_SIZE , stream); - if (OK && ECL_ENDIAN_FLIP) - util_endian_flip_vector(&size , sizeof size , 1); - } else - OK = false; + if (read_bytes != ECL_KW_HEADER_DATA_SIZE) + return ECL_KW_READ_FAIL; + + memcpy( header , &buffer[0] , ECL_STRING8_LENGTH); + size = *( (int *) &buffer[ECL_STRING8_LENGTH] ); + memcpy( ecl_type_str , &buffer[ECL_STRING8_LENGTH + sizeof(size)] , ECL_TYPE_LENGTH); + + if(!fortio_complete_read(fortio , record_size)) + return ECL_KW_READ_FAIL; + + if (ECL_ENDIAN_FLIP) + util_endian_flip_vector(&size , sizeof size , 1); } - if (OK) { - ecl_data_type data_type = ecl_type_create_from_name( ecl_type_str ); - ecl_kw_initialize( ecl_kw , header , size , data_type); + ecl_data_type data_type = ecl_type_create_from_name( ecl_type_str ); + ecl_kw_initialize( ecl_kw , header , size , data_type); - if (ecl_type_is_C010(data_type)) - return ECL_KW_READ_SKIP; - - return ECL_KW_READ_OK; - } else - return ECL_KW_READ_FAIL; + return ECL_KW_READ_OK; } @@ -1526,18 +1541,19 @@ static void ecl_kw_fwrite_data_unformatted( ecl_kw_type * ecl_kw , fortio_type * for (block_nr = 0; block_nr < num_blocks; block_nr++) { int this_blocksize = util_int_min((block_nr + 1)*blocksize , ecl_kw->size) - block_nr*blocksize; - if (ecl_type_is_char(ecl_kw->data_type) || ecl_type_is_mess(ecl_kw->data_type)) { + if (ecl_type_is_char(ecl_kw->data_type) || ecl_type_is_mess(ecl_kw->data_type) || ecl_type_is_string(ecl_kw->data_type)) { /* Due to the terminating \0 characters there is not a continous file/memory mapping - the \0 characters arel skipped. */ - FILE *stream = fortio_get_FILE(fortio); - int record_size = this_blocksize * ECL_STRING8_LENGTH; /* The total size in bytes of the record written by the fortio layer. */ - int i; + FILE *stream = fortio_get_FILE(fortio); + int word_size = ecl_type_get_sizeof_ctype_fortio(ecl_kw->data_type); + int record_size = this_blocksize * word_size; /* The total size in bytes of the record written by the fortio layer. */ + int i; fortio_init_write(fortio , record_size ); for (i = 0; i < this_blocksize; i++) - fwrite(&ecl_kw->data[(block_nr * blocksize + i) * ecl_kw_get_sizeof_ctype(ecl_kw)] , 1 , ECL_STRING8_LENGTH , stream); + fwrite(&ecl_kw->data[(block_nr * blocksize + i) * ecl_kw_get_sizeof_ctype(ecl_kw)] , 1 , word_size , stream); fortio_complete_write(fortio , record_size); } else { int record_size = this_blocksize * ecl_kw_get_sizeof_ctype(ecl_kw); /* The total size in bytes of the record written by the fortio layer. */ @@ -1595,7 +1611,7 @@ static void ecl_kw_fwrite_data_formatted( ecl_kw_type * ecl_kw , fortio_type * f FILE * stream = fortio_get_FILE( fortio ); const int blocksize = get_blocksize( ecl_kw->data_type ); const int columns = get_columns( ecl_kw->data_type ); - const char * write_fmt = ecl_kw_get_write_fmt( ecl_kw->data_type ); + char * write_fmt = alloc_write_fmt( ecl_kw->data_type ); const int num_blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1); int block_nr; @@ -1613,7 +1629,7 @@ static void ecl_kw_fwrite_data_formatted( ecl_kw_type * ecl_kw , fortio_type * f case(ECL_CHAR_TYPE): fprintf(stream , write_fmt , data_ptr); break; - case(ECL_C010_TYPE): + case(ECL_STRING_TYPE): fprintf(stream , write_fmt , data_ptr); break; case(ECL_INT_TYPE): @@ -1651,6 +1667,8 @@ static void ecl_kw_fwrite_data_formatted( ecl_kw_type * ecl_kw , fortio_type * f fprintf(stream , "\n"); } } + + free(write_fmt); } } @@ -1670,8 +1688,10 @@ void ecl_kw_fwrite_data(const ecl_kw_type *_ecl_kw , fortio_type *fortio) { void ecl_kw_fwrite_header(const ecl_kw_type *ecl_kw , fortio_type *fortio) { FILE *stream = fortio_get_FILE(fortio); bool fmt_file = fortio_fmt_file(fortio); + char * type_name = ecl_type_alloc_name(ecl_kw->data_type); + if (fmt_file) - fprintf(stream , WRITE_HEADER_FMT , ecl_kw->header8 , ecl_kw->size , ecl_type_get_name( ecl_kw->data_type )); + fprintf(stream , WRITE_HEADER_FMT , ecl_kw->header8 , ecl_kw->size , type_name); else { int size = ecl_kw->size; if (ECL_ENDIAN_FLIP) @@ -1681,11 +1701,13 @@ void ecl_kw_fwrite_header(const ecl_kw_type *ecl_kw , fortio_type *fortio) { fwrite(ecl_kw->header8 , sizeof(char) , ECL_STRING8_LENGTH , stream); fwrite(&size , sizeof(int) , 1 , stream); - fwrite(ecl_type_get_name( ecl_kw->data_type ) , sizeof(char) , ECL_TYPE_LENGTH , stream); + fwrite(type_name , sizeof(char) , ECL_TYPE_LENGTH , stream); fortio_complete_write(fortio , ECL_KW_HEADER_DATA_SIZE); } + + free(type_name); } @@ -1892,9 +1914,11 @@ void ecl_kw_fread_double_param(const char * filename , bool fmt_file , double * void ecl_kw_summarize(const ecl_kw_type * ecl_kw) { + char * type_name = ecl_type_alloc_name(ecl_kw->data_type); printf("%8s %10d:%4s \n",ecl_kw_get_header8(ecl_kw), ecl_kw_get_size(ecl_kw), - ecl_type_get_name( ecl_kw->data_type)); + type_name); + free(type_name); } @@ -2109,7 +2133,7 @@ void ecl_kw_inplace_add_indexed( ecl_kw_type * target_kw , const int_vector_type ecl_kw_inplace_add_indexed_int( target_kw , index_set , add_kw ); break; default: - util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); + util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2147,7 +2171,7 @@ void ecl_kw_inplace_add( ecl_kw_type * target_kw , const ecl_kw_type * add_kw) { ecl_kw_inplace_add_int( target_kw , add_kw ); break; default: - util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); + util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2186,7 +2210,7 @@ void ecl_kw_inplace_sub( ecl_kw_type * target_kw , const ecl_kw_type * sub_kw) { ecl_kw_inplace_sub_int( target_kw , sub_kw ); break; default: - util_abort("%s: inplace sub not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); + util_abort("%s: inplace sub not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2226,7 +2250,7 @@ void ecl_kw_inplace_sub_indexed( ecl_kw_type * target_kw , const int_vector_type ecl_kw_inplace_sub_indexed_int( target_kw , index_set , sub_kw ); break; default: - util_abort("%s: inplace sub not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); + util_abort("%s: inplace sub not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2261,7 +2285,7 @@ void ecl_kw_inplace_abs( ecl_kw_type * kw ) { ecl_kw_inplace_abs_int( kw ); break; default: - util_abort("%s: inplace abs not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(kw) )); + util_abort("%s: inplace abs not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(kw) )); } } @@ -2298,7 +2322,7 @@ void ecl_kw_inplace_mul( ecl_kw_type * target_kw , const ecl_kw_type * mul_kw) { ecl_kw_inplace_mul_int( target_kw , mul_kw ); break; default: - util_abort("%s: inplace mul not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); + util_abort("%s: inplace mul not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2338,7 +2362,7 @@ void ecl_kw_inplace_mul_indexed( ecl_kw_type * target_kw , const int_vector_type ecl_kw_inplace_mul_indexed_int( target_kw , index_set , mul_kw ); break; default: - util_abort("%s: inplace mul not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); + util_abort("%s: inplace mul not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2376,7 +2400,7 @@ void ecl_kw_inplace_div( ecl_kw_type * target_kw , const ecl_kw_type * div_kw) { ecl_kw_inplace_div_int( target_kw , div_kw ); break; default: - util_abort("%s: inplace div not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); + util_abort("%s: inplace div not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2417,7 +2441,7 @@ void ecl_kw_inplace_div_indexed( ecl_kw_type * target_kw , const int_vector_type ecl_kw_inplace_div_indexed_int( target_kw , index_set , div_kw ); break; default: - util_abort("%s: inplace div not implemented for type:%s \n",__func__ , ecl_type_get_name( ecl_kw_get_data_type(target_kw) )); + util_abort("%s: inplace div not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) )); } } @@ -2673,7 +2697,7 @@ static void ecl_kw_fprintf_data_bool( const ecl_kw_type * ecl_kw , const char * } -static void ecl_kw_fprintf_data_char( const ecl_kw_type * ecl_kw , const char * fmt , FILE * stream) { +static void ecl_kw_fprintf_data_string( const ecl_kw_type * ecl_kw , const char * fmt , FILE * stream) { int i; for (i=0; i < ecl_kw->size; i++) fprintf(stream , fmt , &ecl_kw->data[ i * ecl_kw_get_sizeof_ctype(ecl_kw)]); @@ -2689,8 +2713,8 @@ void ecl_kw_fprintf_data( const ecl_kw_type * ecl_kw , const char * fmt , FILE * ecl_kw_fprintf_data_int( ecl_kw , fmt , stream ); else if (ecl_type_is_bool(ecl_kw->data_type)) ecl_kw_fprintf_data_bool( ecl_kw , fmt , stream ); - else if (ecl_type_is_char(ecl_kw->data_type)) - ecl_kw_fprintf_data_char( ecl_kw , fmt , stream ); + else if (ecl_type_is_char(ecl_kw->data_type) || ecl_type_is_string(ecl_kw->data_type)) + ecl_kw_fprintf_data_string( ecl_kw , fmt , stream ); } diff --git a/ThirdParty/Ert/libecl/src/ecl_kw_grdecl.c b/ThirdParty/Ert/libecl/src/ecl_kw_grdecl.c index 9140a295c1..bf44d6cff3 100644 --- a/ThirdParty/Ert/libecl/src/ecl_kw_grdecl.c +++ b/ThirdParty/Ert/libecl/src/ecl_kw_grdecl.c @@ -413,7 +413,7 @@ static char * fscanf_alloc_grdecl_data( const char * header , bool strict , ecl_ value_ptr = &value; } else - util_abort("%s: sorry type:%s not supported \n",__func__ , ecl_type_get_name(data_type)); + util_abort("%s: sorry type:%s not supported \n",__func__ , ecl_type_alloc_name(data_type)); /* Removing this warning on user request: diff --git a/ThirdParty/Ert/libecl/src/ecl_rsthead.c b/ThirdParty/Ert/libecl/src/ecl_rsthead.c index 2918838740..e8d9cef33a 100644 --- a/ThirdParty/Ert/libecl/src/ecl_rsthead.c +++ b/ThirdParty/Ert/libecl/src/ecl_rsthead.c @@ -88,8 +88,7 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ // The only derived quantity rsthead->sim_time = rsthead_date( rsthead->day , rsthead->month , rsthead->year ); } - if (doubhead_kw) - rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); + rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); if (logihead_kw) rsthead->dualp = ecl_kw_iget_bool( logihead_kw , LOGIHEAD_DUALP_INDEX); @@ -110,15 +109,12 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ ecl_rsthead_type * ecl_rsthead_alloc( const ecl_file_view_type * rst_view, int report_step) { const ecl_kw_type * intehead_kw = ecl_file_view_iget_named_kw( rst_view , INTEHEAD_KW , 0); - const ecl_kw_type * doubhead_kw = NULL; + const ecl_kw_type * doubhead_kw = ecl_file_view_iget_named_kw( rst_view , DOUBHEAD_KW , 0); const ecl_kw_type * logihead_kw = NULL; if (ecl_file_view_has_kw(rst_view, LOGIHEAD_KW)) logihead_kw = ecl_file_view_iget_named_kw( rst_view , LOGIHEAD_KW , 0); - if (ecl_file_view_has_kw(rst_view, DOUBHEAD_KW)) - doubhead_kw = ecl_file_view_iget_named_kw(rst_view, DOUBHEAD_KW, 0); - if (ecl_file_view_has_kw( rst_view , SEQNUM_KW)) { const ecl_kw_type * seqnum_kw = ecl_file_view_iget_named_kw( rst_view , SEQNUM_KW , 0); report_step = ecl_kw_iget_int( seqnum_kw , 0); @@ -233,3 +229,13 @@ void ecl_rsthead_fprintf_struct( const ecl_rsthead_type * header , FILE * stream void ecl_rsthead_free( ecl_rsthead_type * rsthead ) { free( rsthead ); } + + +int ecl_rsthead_get_nxconz( const ecl_rsthead_type * rsthead ) { + return rsthead->nxconz; +} + + +int ecl_rsthead_get_ncwmax( const ecl_rsthead_type * rsthead ) { + return rsthead->ncwmax; +} diff --git a/ThirdParty/Ert/libecl/src/ecl_smspec.c b/ThirdParty/Ert/libecl/src/ecl_smspec.c index ae64dde627..07e86b53d6 100644 --- a/ThirdParty/Ert/libecl/src/ecl_smspec.c +++ b/ThirdParty/Ert/libecl/src/ecl_smspec.c @@ -234,11 +234,14 @@ static const char* special_vars[] = {"NEWTON", this simple list. */ -static const char* smspec_required_keywords[] = {WGNAMES_KW, - KEYWORDS_KW, - STARTDAT_KW, - UNITS_KW, - DIMENS_KW}; +static const size_t num_req_keywords = 5; +static const char* smspec_required_keywords[] = { + WGNAMES_KW, + KEYWORDS_KW, + STARTDAT_KW, + UNITS_KW, + DIMENS_KW + }; /*****************************************************************/ @@ -333,6 +336,21 @@ void ecl_smspec_lock( ecl_smspec_type * smspec ) { smspec->locked = true; } +/** + * Returns an ecl data type for which all names will fit. If the maximum name + * length is at most 8, an ECL_CHAR is returned and otherwise a large enough + * ECL_STRING. + */ +static ecl_data_type get_wgnames_type(const ecl_smspec_type * smspec) { + size_t max_len = 0; + for(int i = 0; i < ecl_smspec_num_nodes(smspec); ++i) { + const char * name = smspec_node_get_wgname(ecl_smspec_iget_node(smspec, i)); + if(name != NULL) + max_len = util_size_t_max(max_len, strlen(name)); + } + + return max_len <= 8 ? ECL_CHAR : ECL_STRING(max_len); +} // DIMENS // KEYWORDS @@ -371,10 +389,18 @@ static void ecl_smspec_fortio_fwrite( const ecl_smspec_type * smspec , fortio_ty { ecl_kw_type * keywords_kw = ecl_kw_alloc( KEYWORDS_KW , num_nodes , ECL_CHAR ); - ecl_kw_type * wgnames_kw = ecl_kw_alloc( WGNAMES_KW , num_nodes , ECL_CHAR ); ecl_kw_type * units_kw = ecl_kw_alloc( UNITS_KW , num_nodes , ECL_CHAR ); ecl_kw_type * nums_kw = NULL; + // If the names_type is an ECL_STRING we expect this to be an INTERSECT + // summary, otherwise an ECLIPSE summary. + ecl_data_type names_type = get_wgnames_type(smspec); + ecl_kw_type * wgnames_kw = ecl_kw_alloc( + ecl_type_is_char(names_type) ? WGNAMES_KW : NAMES_KW, + num_nodes, + names_type + ); + if (smspec->need_nums) nums_kw = ecl_kw_alloc( NUMS_KW , num_nodes , ECL_INT); { @@ -403,7 +429,7 @@ static void ecl_smspec_fortio_fwrite( const ecl_smspec_type * smspec , fortio_ty if (smspec_node_get_var_type( smspec_node ) == ECL_SMSPEC_INVALID_VAR) { ecl_kw_iset_string8( keywords_kw , i , "WWCT" ); ecl_kw_iset_string8( units_kw , i , "????????"); - ecl_kw_iset_string8( wgnames_kw , i , DUMMY_WELL); + ecl_kw_iset_string_ptr( wgnames_kw , i , DUMMY_WELL); } else { ecl_kw_iset_string8( keywords_kw , i , smspec_node_get_keyword( smspec_node )); ecl_kw_iset_string8( units_kw , i , smspec_node_get_unit( smspec_node )); @@ -411,7 +437,7 @@ static void ecl_smspec_fortio_fwrite( const ecl_smspec_type * smspec , fortio_ty const char * wgname = DUMMY_WELL; if (smspec_node_get_wgname( smspec_node ) != NULL) wgname = smspec_node_get_wgname( smspec_node ); - ecl_kw_iset_string8( wgnames_kw , i , wgname); + ecl_kw_iset_string_ptr( wgnames_kw , i , wgname); } } @@ -958,7 +984,7 @@ bool ecl_smspec_equal( const ecl_smspec_type * self , const ecl_smspec_type * ot static void ecl_smspec_load_restart( ecl_smspec_type * ecl_smspec , const ecl_file_type * header ) { if (ecl_file_has_kw( header , RESTART_KW )) { - const ecl_kw_type * restart_kw = ecl_file_iget_kw( header , 0 ); + const ecl_kw_type * restart_kw = ecl_file_iget_named_kw(header, RESTART_KW , 0); char tmp_base[73]; /* To accomodate a maximum of 9 items which consist of 8 characters each. */ char * restart_base; int i; @@ -1058,16 +1084,25 @@ const int_vector_type * ecl_smspec_get_index_map( const ecl_smspec_type * smspec return smspec->index_map; } +/** + * This function is to support the NAMES alias for WGNAMES. If similar + * situations occur in the future, this is a sane starting point for general + * support. + */ +static const char * get_active_keyword_alias(ecl_file_type * header, const char * keyword) { + if (strcmp(keyword, WGNAMES_KW) == 0 || strcmp(keyword, NAMES_KW) == 0) + return ecl_file_has_kw(header, WGNAMES_KW) ? WGNAMES_KW : NAMES_KW; + + return keyword; +} + static bool ecl_smspec_check_header( ecl_file_type * header ) { bool OK = true; - int num_required = sizeof( smspec_required_keywords ) / sizeof( smspec_required_keywords[0] ); - int i; - - for (i=0; i < num_required; i++) { - if (!ecl_file_has_kw( header , smspec_required_keywords[i])) { - OK = false; - break; - } + for (int i=0; i < num_req_keywords && OK; i++) { + OK &= ecl_file_has_kw( + header, + get_active_keyword_alias(header, smspec_required_keywords[i]) + ); } return OK; @@ -1077,16 +1112,18 @@ static bool ecl_smspec_check_header( ecl_file_type * header ) { static bool ecl_smspec_fread_header(ecl_smspec_type * ecl_smspec, const char * header_file , bool include_restart) { ecl_file_type * header = ecl_file_open( header_file , 0); if (header && ecl_smspec_check_header( header )) { - ecl_kw_type *wells = ecl_file_iget_named_kw(header, WGNAMES_KW , 0); - ecl_kw_type *keywords = ecl_file_iget_named_kw(header, KEYWORDS_KW , 0); - ecl_kw_type *startdat = ecl_file_iget_named_kw(header, STARTDAT_KW , 0); - ecl_kw_type *units = ecl_file_iget_named_kw(header, UNITS_KW , 0); - ecl_kw_type *dimens = ecl_file_iget_named_kw(header, DIMENS_KW , 0); - ecl_kw_type *nums = NULL; - ecl_kw_type *lgrs = NULL; - ecl_kw_type *numlx = NULL; - ecl_kw_type *numly = NULL; - ecl_kw_type *numlz = NULL; + const char * names_alias = get_active_keyword_alias(header, WGNAMES_KW); + ecl_kw_type *wells = ecl_file_iget_named_kw(header, names_alias , 0); + ecl_kw_type *keywords = ecl_file_iget_named_kw(header, KEYWORDS_KW , 0); + ecl_kw_type *startdat = ecl_file_iget_named_kw(header, STARTDAT_KW , 0); + ecl_kw_type *units = ecl_file_iget_named_kw(header, UNITS_KW , 0); + ecl_kw_type *dimens = ecl_file_iget_named_kw(header, DIMENS_KW , 0); + ecl_kw_type *nums = NULL; + ecl_kw_type *lgrs = NULL; + ecl_kw_type *numlx = NULL; + ecl_kw_type *numly = NULL; + ecl_kw_type *numlz = NULL; + int params_index; ecl_smspec->num_regions = 0; if (startdat == NULL) diff --git a/ThirdParty/Ert/libecl/src/ecl_type.c b/ThirdParty/Ert/libecl/src/ecl_type.c index efb79e29d7..a259bb5428 100644 --- a/ThirdParty/Ert/libecl/src/ecl_type.c +++ b/ThirdParty/Ert/libecl/src/ecl_type.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -27,71 +28,96 @@ types. */ #define ECL_TYPE_NAME_CHAR "CHAR" -#define ECL_TYPE_NAME_C010 "C010" #define ECL_TYPE_NAME_FLOAT "REAL" #define ECL_TYPE_NAME_INT "INTE" #define ECL_TYPE_NAME_DOUBLE "DOUB" #define ECL_TYPE_NAME_BOOL "LOGI" #define ECL_TYPE_NAME_MESSAGE "MESS" +static char * alloc_string_name(const ecl_data_type ecl_type) { + return util_alloc_sprintf( + "C%03d", + ecl_type_get_sizeof_ctype_fortio(ecl_type) + ); +} + +static bool is_ecl_string_name(const char * type_name) { + return (type_name[0] == 'C' && + isdigit(type_name[1]) && + isdigit(type_name[2]) && + isdigit(type_name[3]) + ); +} + +static size_t get_ecl_string_length(const char * type_name) { + if(!is_ecl_string_name(type_name)) + util_abort("%s: Expected eclipse string (CXXX), received %s\n", + __func__, type_name); + + return atoi(type_name+1); +} ecl_data_type ecl_type_create(const ecl_type_enum type, const size_t element_size) { - ecl_data_type ecl_type = ecl_type_create_from_type(type); + ecl_data_type ecl_type = ( + type == ECL_STRING_TYPE ? + ECL_STRING(element_size) : + ecl_type_create_from_type(type) + ); - if(ecl_type.element_size != element_size) - util_abort( - "%s: element_size mismatch for type %d, was: %d, expected: %d\n", - __func__, type, element_size, ecl_type.element_size); + if(ecl_type_get_sizeof_ctype_fortio(ecl_type) != element_size) + util_abort( + "%s: element_size mismatch for type %d, was: %d, expected: %d\n", + __func__, type, + element_size, ecl_type_get_sizeof_ctype_fortio(ecl_type) + ); - return ecl_type; + return ecl_type; } ecl_data_type ecl_type_create_from_type(const ecl_type_enum type) { - switch(type) { - case(ECL_CHAR_TYPE): - return ECL_CHAR; - case(ECL_INT_TYPE): - return ECL_INT; - case(ECL_FLOAT_TYPE): - return ECL_FLOAT; - case(ECL_DOUBLE_TYPE): - return ECL_DOUBLE; - case(ECL_BOOL_TYPE): - return ECL_BOOL; - case(ECL_MESS_TYPE): - return ECL_MESS; - case(ECL_C010_TYPE): - return ECL_C010; - default: - util_abort("%s: invalid ecl_type: %d\n", __func__, type); - return ECL_INT; /* Dummy */ - } + switch(type) { + case(ECL_CHAR_TYPE): + return ECL_CHAR; + case(ECL_INT_TYPE): + return ECL_INT; + case(ECL_FLOAT_TYPE): + return ECL_FLOAT; + case(ECL_DOUBLE_TYPE): + return ECL_DOUBLE; + case(ECL_BOOL_TYPE): + return ECL_BOOL; + case(ECL_MESS_TYPE): + return ECL_MESS; + case(ECL_STRING_TYPE): + util_abort("%s: Variable length string type cannot be created" + " from type alone!\n" , __func__); + return ECL_STRING(0); /* Dummy */ + default: + util_abort("%s: invalid ecl_type: %d\n", __func__, type); + return ECL_INT; /* Dummy */ + } } ecl_type_enum ecl_type_get_type(const ecl_data_type ecl_type) { return ecl_type.type; } -size_t ecl_type_get_element_size(const ecl_data_type ecl_type) { - return ecl_type.element_size; -} - -const char * ecl_type_get_name(const ecl_data_type ecl_type) { +char * ecl_type_alloc_name(const ecl_data_type ecl_type) { switch (ecl_type.type) { case(ECL_CHAR_TYPE): - return ECL_TYPE_NAME_CHAR ; - case(ECL_C010_TYPE): - return ECL_TYPE_NAME_C010; + return util_alloc_string_copy(ECL_TYPE_NAME_CHAR); + case(ECL_STRING_TYPE): + return alloc_string_name(ecl_type); case(ECL_FLOAT_TYPE): - return ECL_TYPE_NAME_FLOAT; + return util_alloc_string_copy(ECL_TYPE_NAME_FLOAT); case(ECL_DOUBLE_TYPE): - return ECL_TYPE_NAME_DOUBLE; + return util_alloc_string_copy(ECL_TYPE_NAME_DOUBLE); case(ECL_INT_TYPE): - return ECL_TYPE_NAME_INT; + return util_alloc_string_copy(ECL_TYPE_NAME_INT); case(ECL_BOOL_TYPE): - return ECL_TYPE_NAME_BOOL; + return util_alloc_string_copy(ECL_TYPE_NAME_BOOL); case(ECL_MESS_TYPE): - return ECL_TYPE_NAME_MESSAGE; + return util_alloc_string_copy(ECL_TYPE_NAME_MESSAGE); default: util_abort("Internal error in %s - internal eclipse_type: %d not recognized - aborting \n",__func__ , ecl_type.type); return NULL; /* Dummy */ @@ -107,8 +133,8 @@ ecl_data_type ecl_type_create_from_name( const char * type_name ) { return ECL_DOUBLE; else if (strncmp( type_name , ECL_TYPE_NAME_CHAR , ECL_TYPE_LENGTH) == 0) return ECL_CHAR; - else if (strncmp( type_name , ECL_TYPE_NAME_C010 , ECL_TYPE_LENGTH) == 0) - return ECL_C010; + else if (is_ecl_string_name(type_name)) + return ECL_STRING(get_ecl_string_length(type_name)); else if (strncmp( type_name , ECL_TYPE_NAME_MESSAGE , ECL_TYPE_LENGTH) == 0) return ECL_MESS; else if (strncmp( type_name , ECL_TYPE_NAME_BOOL , ECL_TYPE_LENGTH) == 0) @@ -121,52 +147,64 @@ ecl_data_type ecl_type_create_from_name( const char * type_name ) { int ecl_type_get_sizeof_ctype_fortio(const ecl_data_type ecl_type) { - if(ecl_type_is_char(ecl_type) || ecl_type_is_C010(ecl_type)) + if(ecl_type_is_char(ecl_type) || ecl_type_is_string(ecl_type)) return ecl_type.element_size - 1; else return ecl_type_get_sizeof_ctype(ecl_type); } int ecl_type_get_sizeof_ctype(const ecl_data_type ecl_type) { - return ecl_type.element_size; + return ecl_type.element_size; } bool ecl_type_is_numeric(const ecl_data_type ecl_type) { - return (ecl_type_is_int(ecl_type) || - ecl_type_is_float(ecl_type) || - ecl_type_is_double(ecl_type)); + return (ecl_type_is_int(ecl_type) || + ecl_type_is_float(ecl_type) || + ecl_type_is_double(ecl_type)); +} + +bool ecl_type_is_alpha(const ecl_data_type ecl_type) { + return (ecl_type_is_char(ecl_type) || + ecl_type_is_mess(ecl_type) || + ecl_type_is_string(ecl_type)); } bool ecl_type_is_equal(const ecl_data_type ecl_type1, const ecl_data_type ecl_type2) { - return (ecl_type1.type == ecl_type2.type && - ecl_type1.element_size == ecl_type2.element_size); + return (ecl_type1.type == ecl_type2.type && + ecl_type1.element_size == ecl_type2.element_size); } bool ecl_type_is_char(const ecl_data_type ecl_type) { - return (ecl_type.type == ECL_CHAR_TYPE); + return (ecl_type.type == ECL_CHAR_TYPE); } bool ecl_type_is_int(const ecl_data_type ecl_type) { - return (ecl_type.type == ECL_INT_TYPE); + return (ecl_type.type == ECL_INT_TYPE); } bool ecl_type_is_float(const ecl_data_type ecl_type) { - return (ecl_type.type == ECL_FLOAT_TYPE); + return (ecl_type.type == ECL_FLOAT_TYPE); } bool ecl_type_is_double(const ecl_data_type ecl_type) { - return (ecl_type.type == ECL_DOUBLE_TYPE); + return (ecl_type.type == ECL_DOUBLE_TYPE); } bool ecl_type_is_mess(const ecl_data_type ecl_type) { - return (ecl_type.type == ECL_MESS_TYPE); + return (ecl_type.type == ECL_MESS_TYPE); } bool ecl_type_is_bool(const ecl_data_type ecl_type) { - return (ecl_type.type == ECL_BOOL_TYPE); + return (ecl_type.type == ECL_BOOL_TYPE); } -bool ecl_type_is_C010(const ecl_data_type ecl_type) { - return (ecl_type.type == ECL_C010_TYPE); +bool ecl_type_is_string(const ecl_data_type ecl_type) { + return (ecl_type.type == ECL_STRING_TYPE); } + +// Temporary fixup for OPM. + char * ecl_type_get_name(const ecl_data_type ecl_type) { + return ecl_type_alloc_name( ecl_type ); + } + diff --git a/ThirdParty/Ert/libecl/src/ecl_type_python.c b/ThirdParty/Ert/libecl/src/ecl_type_python.c index 2ad25981d0..8e5f843dd9 100644 --- a/ThirdParty/Ert/libecl/src/ecl_type_python.c +++ b/ThirdParty/Ert/libecl/src/ecl_type_python.c @@ -36,8 +36,8 @@ ecl_type_enum ecl_type_get_type_python(const ecl_data_type * ecl_type) { return ecl_type_get_type(*ecl_type); } -const char * ecl_type_get_name_python(const ecl_data_type * ecl_type) { - return ecl_type_get_name(*ecl_type); +const char * ecl_type_alloc_name_python(const ecl_data_type * ecl_type) { + return ecl_type_alloc_name(*ecl_type); } int ecl_type_get_sizeof_ctype_fortio_python(const ecl_data_type * ecl_type) { @@ -81,8 +81,8 @@ bool ecl_type_is_bool_python(const ecl_data_type * ecl_type) { return ecl_type_is_bool(*ecl_type); } -bool ecl_type_is_C010_python(const ecl_data_type * ecl_type) { - return ecl_type_is_C010(*ecl_type); +bool ecl_type_is_string_python(const ecl_data_type * ecl_type) { + return ecl_type_is_string(*ecl_type); } /** diff --git a/ThirdParty/Ert/libecl/src/ecl_util.c b/ThirdParty/Ert/libecl/src/ecl_util.c index 6e11822ffb..6b1dae13f9 100644 --- a/ThirdParty/Ert/libecl/src/ecl_util.c +++ b/ThirdParty/Ert/libecl/src/ecl_util.c @@ -33,21 +33,6 @@ #include -/*****************************************************************/ -/* The string names for the different ECLIPSE low-level - types. -*/ - - -#define ECL_TYPE_NAME_CHAR "CHAR" -#define ECL_TYPE_NAME_C010 "C010" -#define ECL_TYPE_NAME_FLOAT "REAL" -#define ECL_TYPE_NAME_INT "INTE" -#define ECL_TYPE_NAME_DOUBLE "DOUB" -#define ECL_TYPE_NAME_BOOL "LOGI" -#define ECL_TYPE_NAME_MESSAGE "MESS" - - #define ECL_PHASE_NAME_OIL "SOIL" // SHould match the keywords found in restart file #define ECL_PHASE_NAME_WATER "SWAT" #define ECL_PHASE_NAME_GAS "SGAS" @@ -700,7 +685,7 @@ void ecl_util_memcpy_typed_data(void *_target_data , const void * _src_data , ec break; } default: - util_abort("%s con not convert %s -> %s \n",__func__ , ecl_type_get_name(src_type) , ecl_type_get_name(target_type)); + util_abort("%s con not convert %s -> %s \n",__func__ , ecl_type_alloc_name(src_type) , ecl_type_alloc_name(target_type)); } } } diff --git a/ThirdParty/Ert/libecl/src/smspec_node.c b/ThirdParty/Ert/libecl/src/smspec_node.c index 2d4bd373f0..e009a53272 100644 --- a/ThirdParty/Ert/libecl/src/smspec_node.c +++ b/ThirdParty/Ert/libecl/src/smspec_node.c @@ -407,20 +407,12 @@ smspec_node_type * smspec_node_alloc_new(int params_index, float default_value) } -/** - Observe that the wellname can have max 8 characters; anything - beyond that is silently dropped. -*/ - static void smspec_node_set_wgname( smspec_node_type * index , const char * wgname ) { if (wgname == NULL) { util_safe_free( index->wgname ); index->wgname = NULL; } else { - if (strlen(wgname) > 8) - index->wgname = util_realloc_substring_copy(index->wgname , wgname , 8); - else - index->wgname = util_realloc_string_copy(index->wgname , wgname ); + index->wgname = util_realloc_string_copy(index->wgname , wgname ); } } diff --git a/ThirdParty/Ert/libecl/tests/ecl_kw_ix_types.c b/ThirdParty/Ert/libecl/tests/ecl_kw_ix_types.c deleted file mode 100644 index ac66484ffd..0000000000 --- a/ThirdParty/Ert/libecl/tests/ecl_kw_ix_types.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - Copyright (C) 2017 Statoil ASA, Norway. - - The file 'ecl_kw_ix_types.c' is part of ERT - Ensemble based Reservoir Tool. - - ERT 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. - - ERT 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 at - for more details. -*/ -#include -#include - -#include - -#include -#include - - -/* - The behaviour of the ECL_C010_TYPE is quite unclear; we therefor do - not alloaw instanstiation of keywords with this type. -*/ - - -void test_create_ECL_C010_TYPE() { - ecl_kw_type * ecl_kw = ecl_kw_alloc("TEST" , 1000 , ECL_C010 ); - test_assert_NULL( ecl_kw ); -} - - -int main( int argc , char ** argv) { - test_create_ECL_C010_TYPE(); -} diff --git a/ThirdParty/Ert/libecl/tests/tests.cmake b/ThirdParty/Ert/libecl/tests/tests.cmake index 667b44fcea..9da02ab0f8 100644 --- a/ThirdParty/Ert/libecl/tests/tests.cmake +++ b/ThirdParty/Ert/libecl/tests/tests.cmake @@ -14,10 +14,6 @@ add_executable( ecl_kw_init ecl_kw_init.c ) target_link_libraries( ecl_kw_init ecl ) add_test( ecl_kw_init ${EXECUTABLE_OUTPUT_PATH}/ecl_kw_init ) -add_executable( ecl_kw_ix_types ecl_kw_ix_types.c ) -target_link_libraries( ecl_kw_ix_types ecl ) -add_test( ecl_kw_ix_types ${EXECUTABLE_OUTPUT_PATH}/ecl_kw_ix_types ) - add_executable( ecl_grid_init_fwrite ecl_grid_init_fwrite.c ) target_link_libraries( ecl_grid_init_fwrite ecl ) add_test( ecl_grid_init_fwrite ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_init_fwrite ) diff --git a/ThirdParty/Ert/libecl_well/include/ert/ecl_well/well_const.h b/ThirdParty/Ert/libecl_well/include/ert/ecl_well/well_const.h index ddca00c01a..41a2ade9f2 100644 --- a/ThirdParty/Ert/libecl_well/include/ert/ecl_well/well_const.h +++ b/ThirdParty/Ert/libecl_well/include/ert/ecl_well/well_const.h @@ -105,9 +105,9 @@ extern "C" { #define SCON_CF_INDEX 0 -#define XCON_WRAT_INDEX 46 -#define XCON_GRAT_INDEX 47 -#define XCON_ORAT_INDEX 48 +#define XCON_ORAT_INDEX 0 +#define XCON_WRAT_INDEX 1 +#define XCON_GRAT_INDEX 2 #define XCON_QR_INDEX 49 #define RSEG_LENGTH_INDEX 0 diff --git a/ThirdParty/Ert/libecl_well/include/ert/ecl_well/well_state.h b/ThirdParty/Ert/libecl_well/include/ert/ecl_well/well_state.h index d0042c8e29..1afe9eb488 100644 --- a/ThirdParty/Ert/libecl_well/include/ert/ecl_well/well_state.h +++ b/ThirdParty/Ert/libecl_well/include/ert/ecl_well/well_state.h @@ -82,6 +82,7 @@ extern "C" { bool well_state_is_open( const well_state_type * well_state ); int well_state_get_well_nr( const well_state_type * well_state ); + const well_conn_type * well_state_get_global_wellhead( const well_state_type * well_state ); const well_conn_type * well_state_iget_wellhead( const well_state_type * well_state , int grid_nr); const well_conn_type * well_state_get_wellhead( const well_state_type * well_state , const char * grid_name); diff --git a/ThirdParty/Ert/libecl_well/src/CMakeLists.txt b/ThirdParty/Ert/libecl_well/src/CMakeLists.txt index f71887f102..84eacde50a 100644 --- a/ThirdParty/Ert/libecl_well/src/CMakeLists.txt +++ b/ThirdParty/Ert/libecl_well/src/CMakeLists.txt @@ -32,7 +32,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) include_directories( ${libgeometry_src_path} ) -add_library( ecl_well ${LIBRARY_TYPE} ${source_files} ) +add_library( ecl_well ${source_files} ) set_target_properties( ecl_well PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR} ) target_link_libraries( ecl_well ecl ) if (USE_RUNPATH) diff --git a/ThirdParty/Ert/libecl_well/src/well_conn.c b/ThirdParty/Ert/libecl_well/src/well_conn.c index e084127cba..74e87521b7 100644 --- a/ThirdParty/Ert/libecl_well/src/well_conn.c +++ b/ThirdParty/Ert/libecl_well/src/well_conn.c @@ -227,6 +227,7 @@ well_conn_type * well_conn_alloc_from_kw( const ecl_kw_type * icon_kw , if (xcon_kw) { const int xcon_offset = header->nxconz * (header->ncwmax * well_nr + conn_nr); + conn->water_rate = ecl_kw_iget_as_double(xcon_kw, xcon_offset + XCON_WRAT_INDEX); conn->gas_rate = ecl_kw_iget_as_double(xcon_kw, xcon_offset + XCON_GRAT_INDEX); conn->oil_rate = ecl_kw_iget_as_double(xcon_kw, xcon_offset + XCON_ORAT_INDEX); diff --git a/ThirdParty/Ert/libecl_well/src/well_state.c b/ThirdParty/Ert/libecl_well/src/well_state.c index 20f38214d0..06baf2e8be 100644 --- a/ThirdParty/Ert/libecl_well/src/well_state.c +++ b/ThirdParty/Ert/libecl_well/src/well_state.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include @@ -173,7 +175,7 @@ struct well_state_struct { double gas_rate; double water_rate; double volume_rate; - + ert_ecl_unit_enum unit_system; hash_type * connections; // hash well_segment_collection_type * segments; @@ -210,7 +212,7 @@ well_state_type * well_state_alloc(const char * well_name , int global_well_nr , well_state->gas_rate = 0; well_state->water_rate = 0; well_state->volume_rate = 0; - + well_state->unit_system = ECL_METRIC_UNITS; /* See documentation of the 'IWEL_UNDOCUMENTED_ZERO' in well_const.h */ if ((type == ECL_WELL_ZERO) && open) @@ -240,17 +242,44 @@ double well_state_get_volume_rate( const well_state_type * well_state) { } double well_state_get_oil_rate_si( const well_state_type * well_state ) { - return well_state->oil_rate; + double conversion_factor = 1; + + if (well_state->unit_system == ECL_METRIC_UNITS) + conversion_factor = 1.0 / ECL_UNITS_TIME_DAY; + else if (well_state->unit_system == ECL_FIELD_UNITS) + conversion_factor = ECL_UNITS_VOLUME_BARREL / ECL_UNITS_TIME_DAY; + else if (well_state->unit_system == ECL_LAB_UNITS) + conversion_factor = ECL_UNITS_VOLUME_MILLI_LITER / ECL_UNITS_TIME_HOUR; + + return well_state->oil_rate * conversion_factor; } double well_state_get_gas_rate_si( const well_state_type * well_state ) { - return well_state->gas_rate; + double conversion_factor = 1; + + if (well_state->unit_system == ECL_METRIC_UNITS) + conversion_factor = 1.0 / ECL_UNITS_TIME_DAY; + else if (well_state->unit_system == ECL_FIELD_UNITS) + conversion_factor = ECL_UNITS_VOLUME_GAS_FIELD / ECL_UNITS_TIME_DAY; + else if (well_state->unit_system == ECL_LAB_UNITS) + conversion_factor = ECL_UNITS_VOLUME_MILLI_LITER / ECL_UNITS_TIME_HOUR; + + return well_state->gas_rate * conversion_factor; } double well_state_get_water_rate_si( const well_state_type * well_state) { - return well_state->water_rate; + double conversion_factor = 1; + + if (well_state->unit_system == ECL_METRIC_UNITS) + conversion_factor = 1.0 / ECL_UNITS_TIME_DAY; + else if (well_state->unit_system == ECL_FIELD_UNITS) + conversion_factor = ECL_UNITS_VOLUME_BARREL / ECL_UNITS_TIME_DAY; + else if (well_state->unit_system == ECL_LAB_UNITS) + conversion_factor = ECL_UNITS_VOLUME_MILLI_LITER / ECL_UNITS_TIME_HOUR; + + return well_state->water_rate * conversion_factor; } double well_state_get_volume_rate_si( const well_state_type * well_state) { @@ -278,6 +307,7 @@ static bool well_state_add_rates( well_state_type * well_state , ecl_rsthead_type *header = ecl_rsthead_alloc(rst_view, -1); int offset = header->nxwelz * well_nr; + well_state->unit_system = header->unit_system; well_state->oil_rate = ecl_kw_iget_double(xwel_kw, offset + XWEL_RES_ORAT_ITEM); well_state->gas_rate = ecl_kw_iget_double(xwel_kw, offset + XWEL_RES_GRAT_ITEM); well_state->water_rate = ecl_kw_iget_double(xwel_kw, offset + XWEL_RES_WRAT_ITEM); @@ -611,6 +641,13 @@ const well_conn_type * well_state_get_wellhead( const well_state_type * well_sta return NULL; } +const well_conn_type * well_state_get_global_wellhead( const well_state_type * well_state ) { + if (hash_has_key( well_state->name_wellhead , ECL_GRID_GLOBAL_GRID)) + return hash_get( well_state->name_wellhead , ECL_GRID_GLOBAL_GRID ); + else + return NULL; +} + well_type_enum well_state_get_type( const well_state_type * well_state){ return well_state->type; diff --git a/ThirdParty/Ert/libeclxx/src/CMakeLists.txt b/ThirdParty/Ert/libeclxx/src/CMakeLists.txt index 8dc07fc2dd..4a108238a8 100644 --- a/ThirdParty/Ert/libeclxx/src/CMakeLists.txt +++ b/ThirdParty/Ert/libeclxx/src/CMakeLists.txt @@ -12,7 +12,7 @@ set( header_files ) -add_library( eclxx ${LIBRARY_TYPE} ${source_files} ) +add_library( eclxx ${source_files} ) set_target_properties( eclxx PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR}) if (USE_RUNPATH) add_runpath( eclxx ) diff --git a/ThirdParty/Ert/libert_util/src/CMakeLists.txt b/ThirdParty/Ert/libert_util/src/CMakeLists.txt index 4765a45a9c..e2a9d9c228 100644 --- a/ThirdParty/Ert/libert_util/src/CMakeLists.txt +++ b/ThirdParty/Ert/libert_util/src/CMakeLists.txt @@ -161,7 +161,7 @@ if (ERT_BUILD_CXX) list( APPEND header_files test_util.hpp ) endif() -add_library( ert_util ${LIBRARY_TYPE} ${source_files} ) +add_library( ert_util ${source_files} ) message(STATUS "Linking with: ${ERT_EXTERNAL_UTIL_LIBS}") set_target_properties( ert_util PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR} ) diff --git a/ThirdParty/Ert/libert_utilxx/src/CMakeLists.txt b/ThirdParty/Ert/libert_utilxx/src/CMakeLists.txt index a82f5ee1d5..9ff4095fa7 100644 --- a/ThirdParty/Ert/libert_utilxx/src/CMakeLists.txt +++ b/ThirdParty/Ert/libert_utilxx/src/CMakeLists.txt @@ -8,7 +8,7 @@ set( header_files ) -add_library( ert_utilxx ${LIBRARY_TYPE} ${source_files} ) +add_library( ert_utilxx ${source_files} ) set_target_properties( ert_utilxx PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR}) if (USE_RUNPATH) add_runpath( ert_utilxx ) diff --git a/ThirdParty/Ert/libgeometry/src/CMakeLists.txt b/ThirdParty/Ert/libgeometry/src/CMakeLists.txt index 181eaeecef..c33a248603 100644 --- a/ThirdParty/Ert/libgeometry/src/CMakeLists.txt +++ b/ThirdParty/Ert/libgeometry/src/CMakeLists.txt @@ -1,7 +1,7 @@ set( source_files geo_surface.c geo_util.c geo_pointset.c geo_region.c geo_polygon.c geo_polygon_collection.c) set( header_files geo_surface.h geo_util.h geo_pointset.h geo_region.h geo_polygon.h geo_polygon_collection.h) -add_library( ert_geometry ${LIBRARY_TYPE} ${source_files} ) +add_library( ert_geometry ${source_files} ) set_target_properties( ert_geometry PROPERTIES VERSION ${ERT_VERSION_MAJOR}.${ERT_VERSION_MINOR} SOVERSION ${ERT_VERSION_MAJOR}) target_link_libraries( ert_geometry ert_util ) if (USE_RUNPATH) diff --git a/ThirdParty/Ert/python/CMakeLists.txt b/ThirdParty/Ert/python/CMakeLists.txt index 954db0c30c..291b431b70 100644 --- a/ThirdParty/Ert/python/CMakeLists.txt +++ b/ThirdParty/Ert/python/CMakeLists.txt @@ -1,28 +1,21 @@ -include(cmake/find_python_module.cmake) -include(cmake/python_package_versions.cmake) # finds version +install( DIRECTORY cmake DESTINATION share ) -FIND_PACKAGE(PythonInterp 2.7 EXACT) -if (NOT DEFINED PYTHON_EXECUTABLE) - message("Python2.7 interpreter not found - Python wrappers not enabled") - return() -endif() +set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") +include(init_python) +init_python( 2.7 ) -python_package(numpy 1.7.1) +find_python_package(numpy 1.7.1 ${PYTHON_INSTALL_PREFIX}) if (NOT DEFINED PY_numpy) - message("numpy module not found - Python wrappers not enabled") + message(WARNING "numpy module not found - Python wrappers not enabled") + set( BUILD_PYTHON OFF PARENT_SCOPE ) return() endif() -if (EXISTS "/etc/debian_version") - set( PYTHON_PACKAGE_PATH "dist-packages") -else() - set( PYTHON_PACKAGE_PATH "site-packages") -endif() -set(PYTHON_INSTALL_PREFIX "lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/${PYTHON_PACKAGE_PATH}" CACHE STRING "Subdirectory to install Python modules in") - if (BUILD_TESTS) add_subdirectory( tests ) endif() add_subdirectory( python ) + + diff --git a/ThirdParty/Ert/python/README b/ThirdParty/Ert/python/README index 6fd7d377d9..10154c0b78 100644 --- a/ThirdParty/Ert/python/README +++ b/ThirdParty/Ert/python/README @@ -4,4 +4,4 @@ Python. More detailed documentation of the wrapping can be found in -docs/devel.txt. +doc/devel.txt. diff --git a/ThirdParty/Ert/cmake/python.cmake2 b/ThirdParty/Ert/python/cmake/Modules/add_python_package.cmake similarity index 83% rename from ThirdParty/Ert/cmake/python.cmake2 rename to ThirdParty/Ert/python/cmake/Modules/add_python_package.cmake index 740fe86618..9d1527d309 100644 --- a/ThirdParty/Ert/cmake/python.cmake2 +++ b/ThirdParty/Ert/python/cmake/Modules/add_python_package.cmake @@ -1,6 +1,3 @@ -if (NOT PYTHONINTERP_FOUND) - find_package (PythonInterp REQUIRED) -endif () function(add_python_package target package_path source_files install_package) set(build_files "") @@ -27,14 +24,14 @@ function(add_python_package target package_path source_files install_package) add_custom_command( OUTPUT ${build_file} COMMAND ${PYTHON_EXECUTABLE} - ARGS ${PROJECT_SOURCE_DIR}/cmake/cmake_pyc2 ${source_file} ${build_file} + ARGS ${PROJECT_BINARY_DIR}/bin/cmake_pyc ${source_file} ${build_file} ${dependent_target}) list(APPEND build_files ${build_file} ) if (install_package) install(FILES ${build_file} DESTINATION ${CMAKE_INSTALL_PREFIX}/${package_path}) - install(CODE "execute_process(COMMAND ${PROJECT_SOURCE_DIR}/cmake/cmake_pyc_file ${install_file})") + install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_BINARY_DIR}/bin/cmake_pyc_file ${install_file})") endif() endforeach() diff --git a/ThirdParty/Ert/python/cmake/Modules/add_python_test.cmake b/ThirdParty/Ert/python/cmake/Modules/add_python_test.cmake new file mode 100644 index 0000000000..26583c5090 --- /dev/null +++ b/ThirdParty/Ert/python/cmake/Modules/add_python_test.cmake @@ -0,0 +1,38 @@ +# This macro will create a ctest based on the supplied TEST_CLASS. The +# TEST_CLASS argument should correspond to a valid Python path, i.e. +# +# >> import ${TEST_CLASS} +# +# should work. The actual test is by running a small test script which +# will invoke normal Python test discovery functionality. This is a +# macro, and relevant variables must be crrectly set in calling scope +# before it is invoked: +# +# PYTHON_TEST_RUNNER: Path to executable which will load the testcase +# given by ${TEST_CLASS} and run it. +# +# +# CTEST_PYTHONPATH: Normal colon separated path variable, should at +# least include the binary root directory of the current python +# installation, but can in addition contain the path to +# additional packages. The PYTHON_TEST_RUNNER should inspect the +# $CTEST_PYTHONPATH environment variable and update sys.path +# accordingly. + +macro( addPythonTest TEST_CLASS ) + set(TEST_NAME ${TEST_CLASS}) + + add_test(NAME ${TEST_NAME} + WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}" + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_BINARY_DIR}/bin/ctest_run_python ${TEST_CLASS} ) + + set(oneValueArgs LABELS) + cmake_parse_arguments(TEST_OPTIONS "" "${oneValueArgs}" "" ${ARGN}) + if(TEST_OPTIONS_LABELS) + set_property(TEST ${TEST_NAME} PROPERTY LABELS "Python:${TEST_OPTIONS_LABELS}") + else() + set_property(TEST ${TEST_NAME} PROPERTY LABELS "Python") + endif() + + set_property(TEST ${TEST_NAME} PROPERTY ENVIRONMENT "CTEST_PYTHONPATH=${CTEST_PYTHONPATH}") +endmacro( ) diff --git a/ThirdParty/Ert/python/cmake/python_package_versions.cmake b/ThirdParty/Ert/python/cmake/Modules/find_python_package.cmake similarity index 70% rename from ThirdParty/Ert/python/cmake/python_package_versions.cmake rename to ThirdParty/Ert/python/cmake/Modules/find_python_package.cmake index 309a8f679d..9cfd68f6aa 100644 --- a/ThirdParty/Ert/python/cmake/python_package_versions.cmake +++ b/ThirdParty/Ert/python/cmake/Modules/find_python_package.cmake @@ -1,6 +1,6 @@ # try import python module, if success, check its version, store as PY_module. # the module is imported as-is, hence the case (e.g. PyQt4) must be correct. -function(python_package_version package) +function(find_python_package_version package) set(PY_VERSION_ACCESSOR "__version__") set(PY_package_name ${package}) @@ -30,8 +30,25 @@ endfunction() # If we find the correct module and new enough version, set PY_package, where # "package" is the given argument to the version we found else, display warning # and do not set any variables. -function(python_package package version) - python_package_version(${package}) +function(find_python_package package version python_prefix) + + if (CMAKE_PREFIX_PATH) + set( ORG_PYTHONPATH $ENV{PYTHONPATH} ) + foreach ( PREFIX_PATH ${CMAKE_PREFIX_PATH} ) + set(THIS_PYTHONPATH "${PREFIX_PATH}/${python_prefix}") + set(ENV{PYTHONPATH} "${THIS_PYTHONPATH}:${ORG_PYTHONPATH}") + find_python_package_version(${package}) + if (DEFINED PY_${package}) + if (${PY_${package}_PATH} STREQUAL ${THIS_PYTHONPATH}) + set(CTEST_PYTHONPATH "${PY_${package}_PATH}:${CTEST_PYTHONPATH}" PARENT_SCOPE) + endif() + break( ) + endif() + endforeach() + set(ENV{PYTHONPATH} ${ORG_PYTHONPATH}) + else() + find_python_package_version(${package}) + endif() if(NOT DEFINED PY_${package}) message("Could not find Python package " ${package}) diff --git a/ThirdParty/Ert/python/cmake/Modules/init_python.cmake b/ThirdParty/Ert/python/cmake/Modules/init_python.cmake new file mode 100644 index 0000000000..414879259c --- /dev/null +++ b/ThirdParty/Ert/python/cmake/Modules/init_python.cmake @@ -0,0 +1,175 @@ +# This macro will initialize the current cmake session for Python. The +# macro starts by looking for the Python interpreter of correct +# version. When a Python interepreter of the correct version has been +# located the macro will continue to set variables, load other cmake +# modules and generate scripts to be used in the remaining part of the +# cmake process. +# +# Variables which will be set: +# ---------------------------- +# +# PYTHON_INSTALL_PREFIX: All python packages will be located in +# ${GLOBAL_PREFIX}/${PYTHON_INSTALL_PREFIX} - this applies both +# when searching for dependencies and when installing. +# +# CTEST_PYTHONPATH: Normal ':' separated path variables which is +# passed to the test runner. Should contain the PYTHONPATH to +# all third party packages which are not in the default search +# path. The CTEST_PYTHONPATH variable will be updated by the +# python_package( ) function when searching for third party +# packages. +# +# +# New functions/macros which will be available: +# --------------------------------------------- +# +# add_python_package( ): This function will copy python source files +# to the build directory, 'compile' them and set up installation. +# +# +# add_python_test( ): Set up a test based on invoking a Python test +# class with a small python executable front end. +# +# find_python_package( ): Will search for a python package. +# +# +# New scripts generated: +# ---------------------- +# +# +# cmake_pyc: Small script which will run in-place Python compilation +# of a directory tree recursively. +# +# cmake_pyc_file: Small script which will compile one python file. +# +# ctest_run_python: Small script which will invoke one Python test class. +# +# All the generated scripts will be located in ${PROJECT_BINARY_DIR}/bin. +# +# +# Downstream projects should use this as: +# +# include( init_python ) +# init_python( 2.7 ) +# ... + +macro(init_python target_version) + + FIND_PACKAGE(PythonInterp) + if (NOT DEFINED PYTHON_EXECUTABLE) + message(WARNING "Python interpreter not found - Python wrappers not enabled") + set( BUILD_PYTHON OFF PARENT_SCOPE ) + return() + endif() + + if (NOT "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" STREQUAL "${target_version}") + message(WARNING "Need Python version ${target_version}, found version: ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} - Python wrappers not enabled") + set( BUILD_PYTHON OFF PARENT_SCOPE ) + return() + endif() + + if (EXISTS "/etc/debian_version") + set( PYTHON_PACKAGE_PATH "dist-packages") + else() + set( PYTHON_PACKAGE_PATH "site-packages") + endif() + + set(PYTHON_INSTALL_PREFIX "lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/${PYTHON_PACKAGE_PATH}" CACHE STRING "Subdirectory to install Python modules in") + set(CTEST_PYTHONPATH ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}) + configure_python_env( ) + include(add_python_test) + include(find_python_package) + include(add_python_package) +endmacro() + + + +# The function configure_python_env( ) will generate three small +# Python scripts which will be located in ${PROJECT_BINARY_DIR}/bin +# and will be used when 'compiling' and testing Python code. The +# function will be called from the init_python() macro. + +function( configure_python_env ) + +FILE(WRITE "${PROJECT_BINARY_DIR}/bin/ctest_run_python" +"import sys +import os +from unittest import TextTestRunner + + +def runTestCase(tests, verbosity=0): + test_result = TextTestRunner(verbosity=verbosity).run(tests) + + if len(test_result.errors) or len(test_result.failures): + test_result.printErrors() + sys.exit(1) + + +def update_path(): + for path in os.environ['CTEST_PYTHONPATH'].split(':'): + sys.path.insert(0 , path) + + +if __name__ == '__main__': + update_path( ) + from ecl.test import ErtTestRunner + + for test_class in sys.argv[1:]: + tests = ErtTestRunner.getTestsFromTestClass(test_class) + + # Set verbosity to 2 to see which test method in a class that fails. + runTestCase(tests, verbosity=0) +") + +#----------------------------------------------------------------- + +FILE(WRITE "${PROJECT_BINARY_DIR}/bin/cmake_pyc" +" +import py_compile +import os +import os.path +import sys +import shutil + + +src_file = sys.argv[1] +target_file = sys.argv[2] + +(target_path , tail) = os.path.split( target_file ) +if not os.path.exists( target_path ): + try: + os.makedirs( target_path ) + except: + # When running make with multiple processes there might be a + # race to create this directory. + pass + +shutil.copyfile( src_file , target_file ) +shutil.copystat( src_file , target_file ) +try: + py_compile.compile( target_file , doraise = True) +except Exception as error: + sys.exit('py_compile(%s) failed:%s' % (target_file , error)) +") + +#----------------------------------------------------------------- + +FILE(WRITE "${PROJECT_BINARY_DIR}/bin/cmake_pyc_file" +" +import py_compile +import os +import sys +import os.path + +# Small 'python compiler' used in the build system for ert. + +for file in sys.argv[1:]: + try: + py_compile.compile( file , doraise = True ) + except Exception as error: + sys.exit('py_compile(%s) failed:%s' % (file , error)) +") + + + +endfunction() \ No newline at end of file diff --git a/ThirdParty/Ert/python/cmake/find_python_module.cmake b/ThirdParty/Ert/python/cmake/find_python_module.cmake deleted file mode 100644 index a0218650b3..0000000000 --- a/ThirdParty/Ert/python/cmake/find_python_module.cmake +++ /dev/null @@ -1,27 +0,0 @@ -# Found from: github user ivansafrin -# -# Find if a Python module is installed -# Found at http://www.cmake.org/pipermail/cmake/2011-January/041666.html -# To use do: find_python_module(PyQt4 REQUIRED) -function(find_python_module module) - string(TOUPPER ${module} module_upper) - if(NOT PY_${module_upper}) - if(ARGC GREATER 1 AND ARGV1 STREQUAL "REQUIRED") - set(${module}_FIND_REQUIRED TRUE) - endif() - # A module's location is usually a directory, but for binary modules - # it's a .so file. - execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" - "import re, ${module}; print(re.compile('/__init__.py.*').sub('',${module}.__file__))" - RESULT_VARIABLE _${module}_status - OUTPUT_VARIABLE _${module}_location - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - - if(NOT _${module}_status) - set(PY_${module_upper} ${_${module}_location} CACHE STRING - "Location of Python module ${module}") - endif() - endif(NOT PY_${module_upper}) - find_package_handle_standard_args(PY_${module} DEFAULT_MSG PY_${module_upper}) -endfunction(find_python_module) diff --git a/ThirdParty/Ert/python/python/CMakeLists.txt b/ThirdParty/Ert/python/python/CMakeLists.txt index 7c82391422..c6d592545b 100644 --- a/ThirdParty/Ert/python/python/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/CMakeLists.txt @@ -1,5 +1,5 @@ configure_file(test_env.py.in ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/test_env.py ) add_subdirectory(cwrap) -add_subdirectory( ert ) +add_subdirectory( ecl ) add_subdirectory( bin ) diff --git a/ThirdParty/Ert/python/python/cwrap/cfile.py b/ThirdParty/Ert/python/python/cwrap/cfile.py index f687a3e060..4b46d420f9 100644 --- a/ThirdParty/Ert/python/python/cwrap/cfile.py +++ b/ThirdParty/Ert/python/python/cwrap/cfile.py @@ -55,7 +55,7 @@ class CFILE(BaseCClass): If the supplied argument is not of type py_file the function will raise a TypeException. - Examples: ert.ecl.ecl_kw.EclKW.fprintf_grdecl() + Examples: ecl.ecl.ecl_kw.EclKW.fprintf_grdecl() """ c_ptr = self._as_file(py_file) try: diff --git a/ThirdParty/Ert/python/python/cwrap/clib.py b/ThirdParty/Ert/python/python/cwrap/clib.py index c1a1fb71e5..2c24cb43fb 100644 --- a/ThirdParty/Ert/python/python/cwrap/clib.py +++ b/ThirdParty/Ert/python/python/cwrap/clib.py @@ -17,13 +17,13 @@ Observe that to ensure that all libraries are loaded through the same code path, all required libraries should be loaded explicitly through -the use of import statements; i.e. the ert.geo package requires the +the use of import statements; i.e. the ecl.geo package requires the libert_util librarary, to ensure that the correct version of the libert_util.so library file is loaded we should manually load that first as: - import ert.util - GEO_LIB = ert.load("libert_geometry") + import ecl.util + GEO_LIB = ecl.load("libert_geometry") Otherwise the standard operating system dependency resolve code will be invoked when loading libert_geometry, and that could in principle diff --git a/ThirdParty/Ert/python/python/ecl/CMakeLists.txt b/ThirdParty/Ert/python/python/ecl/CMakeLists.txt new file mode 100644 index 0000000000..3ba6f862bc --- /dev/null +++ b/ThirdParty/Ert/python/python/ecl/CMakeLists.txt @@ -0,0 +1,14 @@ +set(PYTHON_SOURCES + __init__.py +) +add_python_package("python.ecl" ${PYTHON_INSTALL_PREFIX}/ecl "${PYTHON_SOURCES}" True) + +add_subdirectory(ecl) +add_subdirectory(geo) +add_subdirectory(test) +add_subdirectory(util) +add_subdirectory(well) + +configure_file(ecl_lib_info_build.py.in ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ecl/__ecl_lib_info.py ) +configure_file(ecl_lib_info_install.py.in ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ecl_lib_info_install.py ) +install(FILES ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ecl_lib_info_install.py DESTINATION ${PYTHON_INSTALL_PREFIX}/ecl RENAME __ecl_lib_info.py) diff --git a/ThirdParty/Ert/python/python/ert/__init__.py b/ThirdParty/Ert/python/python/ecl/__init__.py similarity index 84% rename from ThirdParty/Ert/python/python/ert/__init__.py rename to ThirdParty/Ert/python/python/ecl/__init__.py index 9b6111b954..c5496bbb79 100644 --- a/ThirdParty/Ert/python/python/ert/__init__.py +++ b/ThirdParty/Ert/python/python/ecl/__init__.py @@ -18,12 +18,10 @@ ert - Ensemble Reservoir Tool - a package for reservoir modeling. The ert package itself has no code, but contains several subpackages: -ert.ecl: Package for working with ECLIPSE files. The far most mature +ecl.ecl: Package for working with ECLIPSE files. The far most mature package in ert. -ert.job_queue: - -ert.util: +ecl.util: The ert package is based on wrapping the libriaries from the ERT C code with ctypes; an essential part of ctypes approach is to load the @@ -69,22 +67,22 @@ except ImportError: pass -required_version_hex = 0x02060000 +required_version_hex = 0x02070000 -ert_lib_path = None +ecl_lib_path = None ert_so_version = "" __version__ = "0.0.0" -# 1. Try to load the __ert_lib_info module; this module has been +# 1. Try to load the __ecl_lib_info module; this module has been # configured by cmake during the build configuration process. The # module should contain the variable lib_path pointing to the # directory with shared object files. try: - import __ert_lib_info - ert_lib_path = __ert_lib_info.lib_path - ert_so_version = __ert_lib_info.so_version - __version__ = __ert_lib_info.__version__ + import __ecl_lib_info + ecl_lib_path = __ecl_lib_info.lib_path + ert_so_version = __ecl_lib_info.so_version + __version__ = __ecl_lib_info.__version__ except ImportError: pass except AttributeError: @@ -105,23 +103,23 @@ if env_lib_path: # Check that the final ert_lib_path setting corresponds to an existing # directory. -if ert_lib_path: - if not os.path.isdir( ert_lib_path ): - ert_lib_path = None +if ecl_lib_path: + if not os.path.isdir( ecl_lib_path ): + ecl_lib_path = None if sys.hexversion < required_version_hex: - raise Exception("ERT Python requires at least version 2.6 of Python") + raise Exception("ERT Python requires Python 2.7.") # This load() function is *the* function actually loading shared # libraries. def load(name): - return cwrapload( name , path = ert_lib_path , so_version = ert_so_version) + return cwrapload(name, path=ecl_lib_path, so_version=ert_so_version) -from ert.util import Version -from ert.util import updateAbortSignals +from .util import Version +from .util import updateAbortSignals updateAbortSignals( ) diff --git a/ThirdParty/Ert/python/python/ert/ecl/CMakeLists.txt b/ThirdParty/Ert/python/python/ecl/ecl/CMakeLists.txt similarity index 91% rename from ThirdParty/Ert/python/python/ert/ecl/CMakeLists.txt rename to ThirdParty/Ert/python/python/ecl/ecl/CMakeLists.txt index 49605f4c5d..c1cb314101 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/ecl/ecl/CMakeLists.txt @@ -30,7 +30,7 @@ set(PYTHON_SOURCES ecl_grid_generator.py ) -add_python_package("python.ert.ecl" ${PYTHON_INSTALL_PREFIX}/ert/ecl "${PYTHON_SOURCES}" True) +add_python_package("python.ecl.ecl" ${PYTHON_INSTALL_PREFIX}/ecl/ecl "${PYTHON_SOURCES}" True) add_subdirectory(faults) add_subdirectory(rft) diff --git a/ThirdParty/Ert/python/python/ert/ecl/__init__.py b/ThirdParty/Ert/python/python/ecl/ecl/__init__.py similarity index 97% rename from ThirdParty/Ert/python/python/ert/ecl/__init__.py rename to ThirdParty/Ert/python/python/ecl/ecl/__init__.py index feb2077c53..1c6b26062d 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/__init__.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/__init__.py @@ -72,19 +72,19 @@ per module organization: namespace 'ecl'. """ -import ert.util -import ert.geo +import ecl.util +import ecl.geo from cwrap import Prototype class EclPrototype(Prototype): - lib = ert.load("libecl") + lib = ecl.load("libecl") def __init__(self, prototype, bind=True): super(EclPrototype, self).__init__(EclPrototype.lib, prototype, bind=bind) -ECL_LIB = ert.load("libecl") +ECL_LIB = ecl.load("libecl") from .ecl_util import EclFileEnum, EclFileFlagEnum, EclPhaseEnum, EclUnitTypeEnum , EclUtil from .ecl_type import EclTypeEnum, EclDataType diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_3d_file.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_3d_file.py similarity index 97% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_3d_file.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_3d_file.py index 27a5ef71c7..449641efee 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_3d_file.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_3d_file.py @@ -14,7 +14,7 @@ # See the GNU General Public License at # for more details. -from ert.ecl import EclFile, Ecl3DKW +from ecl.ecl import EclFile, Ecl3DKW class Ecl3DFile(EclFile): diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_3dkw.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_3dkw.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_3dkw.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_3dkw.py index edeb817086..1d1a3ace11 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_3dkw.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_3dkw.py @@ -37,7 +37,7 @@ class Ecl3DKW(EclKW): Usage example: - from ert.ecl import EclInitFile,EclGrid + from ecl.ecl import EclInitFile,EclGrid grid = EclGrid("ECLIPSE.EGRID") file = EclInitFile(grid , "ECLIPSE.INIT") @@ -168,7 +168,7 @@ class Ecl3DKW(EclKW): 2. Convert the keyword to a 3D keyword. - from ert.ecl import EclGrid,EclKW,Ecl3DKW + from ecl.ecl import EclGrid,EclKW,Ecl3DKW grid = EclGrid("ECLIPSE.EGRID") poro = EclKW.read_grdecl(open("poro.grdecl") , "PORO") diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_cmp.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_cmp.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_cmp.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_cmp.py index 8608730ec1..38f76f2c28 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_cmp.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_cmp.py @@ -14,7 +14,7 @@ # See the GNU General Public License at # for more details. -from ert.ecl import EclSum +from ecl.ecl import EclSum class EclCase(object): diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_file.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_file.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_file.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_file.py index b50cf38869..111b081fd1 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_file.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_file.py @@ -41,8 +41,8 @@ import datetime import ctypes from cwrap import BaseCClass -from ert.ecl import EclPrototype, EclKW, EclFileEnum, EclFileView -from ert.util import CTime +from ecl.ecl import EclPrototype, EclKW, EclFileEnum, EclFileView +from ecl.util import CTime class EclFile(BaseCClass): @@ -100,7 +100,7 @@ class EclFile(BaseCClass): corresponding to @report_step can be found. Since this is a classmethod it is invoked like this: - import ert.ecl.ecl as ecl + import ecl.ecl.ecl as ecl .... if ecl.EclFile.contains_report_step("ECLIPSE.UNRST" , 20): print "OK - file contains report step 20" @@ -124,7 +124,7 @@ class EclFile(BaseCClass): time corresponding to @dtime can be found. Since this is a classmethod it is invoked like this: - import ert.ecl.ecl as ecl + import ecl.ecl.ecl as ecl .... if ecl.EclFile.contains_sim_time("ECLIPSE.UNRST" , datetime.datetime( 2007 , 10 , 10) ): print "OK - file contains 10th of October 2007" @@ -669,7 +669,7 @@ class EclFile(BaseCClass): This method will write the current EclFile instance to a FortIO stream already opened for writing: - import ert.ecl.ecl as ecl + import ecl.ecl.ecl as ecl ... fortio = ecl.FortIO( "FILE.XX" ) file.fwrite( fortio ) diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_file_view.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_file_view.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_file_view.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_file_view.py index fc6626eff9..558f585e60 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_file_view.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_file_view.py @@ -17,8 +17,8 @@ from __future__ import absolute_import, division, print_function, unicode_literals from six import string_types from cwrap import BaseCClass -from ert.ecl import EclPrototype -from ert.util import CTime +from ecl.ecl import EclPrototype +from ecl.util import CTime class EclFileView(BaseCClass): TYPE_NAME = "ecl_file_view" diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_grav.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_grav.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_grav.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_grav.py index 5b06f7b953..fee8ea71dc 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_grav.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_grav.py @@ -22,7 +22,7 @@ different surveys. The implementation is a thin wrapper around the ecl_grav.c implementation in the libecl library. """ from cwrap import BaseCClass -from ert.ecl import EclPhaseEnum, EclPrototype +from ecl.ecl import EclPhaseEnum, EclPrototype class EclGrav(BaseCClass): @@ -84,7 +84,7 @@ class EclGrav(BaseCClass): to load the @restart_view argument is: import datetime - from ert.ecl import EclRestartFile + from ecl.ecl import EclRestartFile ... ... date = datetime.datetime( year , month , day ) diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_grav_calc.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_grav_calc.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_grav_calc.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_grav_calc.py index 793ad89586..44e5c2006c 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_grav_calc.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_grav_calc.py @@ -14,7 +14,7 @@ # See the GNU General Public License at # for more details. -from ert.ecl import EclPrototype +from ecl.ecl import EclPrototype _phase_deltag = EclPrototype("double ecl_grav_phase_deltag( double, double ,double , ecl_grid , ecl_file , ecl_kw , ecl_kw , ecl_kw , ecl_kw , ecl_kw , ecl_kw") diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_grid.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_grid.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_grid.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_grid.py index 75b01cc72a..7d9bdb6a65 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_grid.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_grid.py @@ -32,8 +32,8 @@ import os.path import math import itertools from cwrap import CFILE, BaseCClass -from ert.util import IntVector -from ert.ecl import EclPrototype, EclDataType, EclKW, FortIO, EclUnitTypeEnum +from ecl.util import IntVector +from ecl.ecl import EclPrototype, EclDataType, EclKW, FortIO, EclUnitTypeEnum class EclGrid(BaseCClass): @@ -222,7 +222,7 @@ class EclGrid(BaseCClass): super(EclGrid, self).__init__(c_ptr) else: raise IOError("Loading grid from:%s failed" % filename) - self.__str__ = self.__repr__ + def free(self): self._free( ) diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_grid_generator.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_grid_generator.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_grid_generator.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_grid_generator.py index 827ac6ac2d..b40e6ca335 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_grid_generator.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_grid_generator.py @@ -17,8 +17,8 @@ import itertools import numpy -from ert.util import IntVector -from ert.ecl import EclGrid, EclKW, EclDataType, EclPrototype +from ecl.util import IntVector +from ecl.ecl import EclGrid, EclKW, EclDataType, EclPrototype class EclGridGenerator: diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_init_file.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_init_file.py similarity index 94% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_init_file.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_init_file.py index 587f194c3b..0b53571149 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_init_file.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_init_file.py @@ -14,7 +14,7 @@ # See the GNU General Public License at # for more details. -from ert.ecl import EclFileEnum , EclFile, Ecl3DKW , Ecl3DFile +from ecl.ecl import EclFileEnum , EclFile, Ecl3DKW , Ecl3DFile class EclInitFile(Ecl3DFile): diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_kw.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_kw.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_kw.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_kw.py index 7678e61dba..dac994f3cb 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_kw.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_kw.py @@ -45,8 +45,8 @@ import warnings import numpy from cwrap import CFILE, BaseCClass -from ert.ecl import EclDataType -from ert.ecl import EclTypeEnum, EclUtil, EclPrototype +from ecl.ecl import EclDataType +from ecl.ecl import EclTypeEnum, EclUtil, EclPrototype def dump_type_deprecation_warning(): warnings.warn("EclTypeEnum is deprecated. " + @@ -109,6 +109,8 @@ class EclKW(BaseCClass): _get_type = EclPrototype("ecl_type_enum ecl_kw_get_type( ecl_kw )") _iget_char_ptr = EclPrototype("char* ecl_kw_iget_char_ptr( ecl_kw , int )") _iset_char_ptr = EclPrototype("void ecl_kw_iset_char_ptr( ecl_kw , int , char*)") + _iget_string_ptr = EclPrototype("char* ecl_kw_iget_string_ptr( ecl_kw , int )") + _iset_string_ptr = EclPrototype("void ecl_kw_iset_string_ptr( ecl_kw , int, char*)") _iget_bool = EclPrototype("bool ecl_kw_iget_bool( ecl_kw , int)") _iset_bool = EclPrototype("bool ecl_kw_iset_bool( ecl_kw , int, bool)") _iget_int = EclPrototype("int ecl_kw_iget_int( ecl_kw , int )") @@ -398,6 +400,8 @@ class EclKW(BaseCClass): self.str_fmt = "%d" elif self.data_type.is_mess(): self.str_fmt = "%s" #"Message type" + elif self.data_type.is_string(): + self.str_fmt = "%" + str(self.data_type.element_size) + "s" else: raise ValueError("Unknown EclDataType (%s)!" % self.data_type.type_name) @@ -474,6 +478,8 @@ class EclKW(BaseCClass): return self._iget_bool( index) elif self.data_type.is_char(): return self._iget_char_ptr( index ) + elif self.data_type.is_string(): + return self._iget_string_ptr( index ) else: raise TypeError("Internal implementation error ...") elif isinstance( index , slice): @@ -502,6 +508,8 @@ class EclKW(BaseCClass): self._iset_bool( index , value) elif self.data_type.is_char(): return self._iset_char_ptr( index , value) + elif self.data_type.is_string(): + return self._iset_string_ptr( index, value) else: raise SystemError("Internal implementation error ...") elif isinstance( index , slice): @@ -1059,7 +1067,7 @@ class EclKW(BaseCClass): existing GRDECL file, set all poro values below 0.05 to 0.00 and write back an updated GRDECL file. - poro = ecl.EclKW.load_grdecl( open("poro1.grdecl" , "r") , "PORO" ) + poro = ecl.EclKW.read_grdecl( open("poro1.grdecl" , "r") , "PORO" ) grid = ecl.EclGrid( "ECLIPSE.EGRID" ) reg = ecl.EclRegion( grid , False ) diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_npv.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_npv.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_npv.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_npv.py index 3645b29ca0..ebdbdf7df2 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_npv.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_npv.py @@ -17,7 +17,7 @@ import re import datetime import numbers -from ert.ecl import EclSum +from ecl.ecl import EclSum class NPVParseKey(object): diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_region.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_region.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_region.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_region.py index c329f3bcff..d34c3f3b72 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_region.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_region.py @@ -28,10 +28,10 @@ queried for the corresponding list of indices. import ctypes from cwrap import BaseCClass -from ert.ecl.faults import Layer -from ert.ecl import EclKW, EclDataType, EclPrototype -from ert.geo import CPolyline -from ert.util import IntVector +from ecl.ecl.faults import Layer +from ecl.ecl import EclKW, EclDataType, EclPrototype +from ecl.geo import CPolyline +from ecl.util import IntVector def select_method(select): @@ -825,7 +825,7 @@ class EclRegion(BaseCClass): vertical coordinate @k. The input @layer should be of type Layer - from the - ert.ecl.faults.layer module. The k value must in the range + ecl.ecl.faults.layer module. The k value must in the range [0,grid.nz) and the dimensions of the layer must correspond exactly to nx,ny of the grid. """ diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_restart_file.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_restart_file.py similarity index 89% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_restart_file.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_restart_file.py index f36f6a6ba3..a67393a68c 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_restart_file.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_restart_file.py @@ -14,8 +14,8 @@ # See the GNU General Public License at # for more details. -from ert.util import CTime -from ert.ecl import EclPrototype , EclFile, Ecl3DKW , Ecl3DFile, EclFileEnum +from ecl.util import CTime +from ecl.ecl import EclPrototype , EclFile, Ecl3DKW , Ecl3DFile, EclFileEnum from cwrap import BaseCClass class EclRestartHead(BaseCClass): @@ -26,7 +26,9 @@ class EclRestartHead(BaseCClass): _get_report_step = EclPrototype("int ecl_rsthead_get_report_step(ecl_rsthead)") _get_sim_time = EclPrototype("time_t ecl_rsthead_get_sim_time(ecl_rsthead)") _get_sim_days = EclPrototype("double ecl_rsthead_get_sim_days(ecl_rsthead)") - + _get_nxconz = EclPrototype("int ecl_rsthead_get_nxconz(ecl_rsthead)") + _get_ncwmax = EclPrototype("int ecl_rsthead_get_ncwmax(ecl_rsthead)") + def __init__(self , kw_arg = None , rst_view = None): if kw_arg is None and rst_view is None: raise ValueError('Cannot construct EclRestartHead without one of kw_arg and rst_view, both were None!') @@ -53,6 +55,11 @@ class EclRestartHead(BaseCClass): def getSimDays(self): return self._get_sim_days( ) + def well_details(self): + return {"NXCONZ" : self._get_nxconz(), + "NCWMAX" : self._get_ncwmax()} + + class EclRestartFile(Ecl3DFile): @@ -129,3 +136,13 @@ class EclRestartFile(Ecl3DFile): time_list.append( (header.getReportStep() , header.getSimDate( ) , header.getSimDays( )) ) return time_list + + + def headers(self): + self.assertHeaders() + return self.rst_headers + + + def get_header(self, index): + self.assertHeaders() + return self.rst_headers[index] diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_rft.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_rft.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_rft.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_rft.py index e337a86a59..fdfae66487 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_rft.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_rft.py @@ -20,8 +20,8 @@ Module for loading ECLIPSE RFT files. from __future__ import absolute_import, division, print_function, unicode_literals from cwrap import BaseCClass -from ert.ecl import EclRFTCell, EclPLTCell, EclPrototype -from ert.util import CTime +from ecl.ecl import EclRFTCell, EclPLTCell, EclPrototype +from ecl.util import CTime class EclRFT(BaseCClass): """The EclRFT class contains the information for *one* RFT. diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_rft_cell.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_rft_cell.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_rft_cell.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_rft_cell.py index b7ce4a93dc..6c6e312a2b 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_rft_cell.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_rft_cell.py @@ -15,7 +15,7 @@ # for more details. from cwrap import BaseCClass -from ert.ecl import EclPrototype +from ecl.ecl import EclPrototype class RFTCell(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_smspec_node.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_smspec_node.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_smspec_node.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_smspec_node.py index 8ee4469057..f651df551a 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_smspec_node.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_smspec_node.py @@ -15,7 +15,7 @@ # for more details. from cwrap import BaseCClass -from ert.ecl import EclPrototype +from ecl.ecl import EclPrototype class EclSMSPECNode(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_subsidence.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_subsidence.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_subsidence.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_subsidence.py index 3c395d7db6..dedba06ec7 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_subsidence.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_subsidence.py @@ -23,7 +23,7 @@ different surveys. The implementation is a thin wrapper around the ecl_subsidence.c implementation in the libecl library. """ from cwrap import BaseCClass -from ert.ecl import EclPrototype +from ecl.ecl import EclPrototype class EclSubsidence(BaseCClass): @@ -79,7 +79,7 @@ class EclSubsidence(BaseCClass): to load the @restart_file argument is: import datetime - import ert.ecl.ecl as ecl + import ecl.ecl.ecl as ecl ... ... date = datetime.datetime( year , month , day ) diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_sum.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_sum.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_sum.py index d4ad01a5fa..0a4d99bf4c 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_sum.py @@ -31,18 +31,18 @@ import os.path # index as the first argument and the key/key_index as second # argument. In the python code this order has been reversed. from cwrap import BaseCClass, CFILE -from ert.ecl import EclSumTStep -from ert.ecl import EclSumVarType -from ert.ecl.ecl_sum_vector import EclSumVector -from ert.ecl.ecl_smspec_node import EclSMSPECNode -from ert.util import StringList, CTime, DoubleVector, TimeVector, IntVector -from ert.ecl import EclPrototype +from ecl.ecl import EclSumTStep +from ecl.ecl import EclSumVarType +from ecl.ecl.ecl_sum_vector import EclSumVector +from ecl.ecl.ecl_smspec_node import EclSMSPECNode +from ecl.util import StringList, CTime, DoubleVector, TimeVector, IntVector +from ecl.ecl import EclPrototype #, EclSumKeyWordVector -#import ert.ecl_plot.sum_plot as sum_plot +#import ecl.ecl_plot.sum_plot as sum_plot # The date2num function is a verbatim copy of the _to_ordinalf() # function from the matplotlib.dates module. Inserted here only to @@ -1240,5 +1240,5 @@ class EclSum(BaseCClass): -import ert.ecl.ecl_sum_keyword_vector +import ecl.ecl.ecl_sum_keyword_vector EclSum._dump_csv_line = EclPrototype("void ecl_sum_fwrite_interp_csv_line(ecl_sum , time_t , ecl_sum_vector, FILE)" , bind = False) diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_keyword_vector.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_keyword_vector.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_sum_keyword_vector.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_keyword_vector.py index 01d586e5fa..336c0697eb 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_keyword_vector.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_keyword_vector.py @@ -24,7 +24,7 @@ import datetime # argument. In the python code this order has been reversed. from cwrap import BaseCClass -from ert.ecl import EclPrototype +from ecl.ecl import EclPrototype diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_node.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_node.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_sum_node.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_node.py diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_tstep.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_tstep.py similarity index 97% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_sum_tstep.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_tstep.py index 1d5f3bf97e..e0995bb8aa 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_tstep.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_tstep.py @@ -1,6 +1,6 @@ from cwrap import BaseCClass -from ert.ecl import EclPrototype -from ert.util import CTime +from ecl.ecl import EclPrototype +from ecl.util import CTime class EclSumTStep(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_var_type.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_var_type.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_sum_var_type.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_var_type.py index 51ac02bb12..73039c39eb 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_var_type.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_var_type.py @@ -14,7 +14,7 @@ # See the GNU General Public License at # for more details. from cwrap import BaseCEnum -from ert.ecl import ECL_LIB +from ecl.ecl import ECL_LIB class EclSumVarType(BaseCEnum): diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_vector.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_vector.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_sum_vector.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_vector.py index 9c76452e5f..3080a65306 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_sum_vector.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_sum_vector.py @@ -16,7 +16,7 @@ from __future__ import print_function import warnings -from ert.ecl.ecl_sum_node import EclSumNode +from ecl.ecl.ecl_sum_node import EclSumNode class EclSumVector(object): diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_type.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_type.py similarity index 82% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_type.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_type.py index 2778ab627f..a16109caa3 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_type.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_type.py @@ -15,7 +15,7 @@ # for more details. from cwrap import BaseCClass, BaseCEnum -from ert.ecl import EclPrototype +from ecl.ecl import EclPrototype class EclTypeEnum(BaseCEnum): TYPE_NAME="ecl_type_enum" @@ -25,6 +25,7 @@ class EclTypeEnum(BaseCEnum): ECL_INT_TYPE = None ECL_BOOL_TYPE = None ECL_MESS_TYPE = None + ECL_STRING_TYPE = None EclTypeEnum.addEnum("ECL_CHAR_TYPE" , 0 ) EclTypeEnum.addEnum("ECL_FLOAT_TYPE" , 1 ) @@ -32,6 +33,7 @@ EclTypeEnum.addEnum("ECL_DOUBLE_TYPE" , 2 ) EclTypeEnum.addEnum("ECL_INT_TYPE" , 3 ) EclTypeEnum.addEnum("ECL_BOOL_TYPE" , 4 ) EclTypeEnum.addEnum("ECL_MESS_TYPE" , 5 ) +EclTypeEnum.addEnum("ECL_STRING_TYPE" , 7 ) #----------------------------------------------------------------- @@ -44,14 +46,15 @@ class EclDataType(BaseCClass): _alloc_from_name = EclPrototype("void* ecl_type_alloc_from_name_python(char*)", bind = False) _free = EclPrototype("void ecl_type_free_python(ecl_data_type)") _get_type = EclPrototype("ecl_type_enum ecl_type_get_type_python(ecl_data_type)") - _get_element_size = EclPrototype("size_t ecl_type_get_sizeof_ctype_python(ecl_data_type)") + _get_element_size = EclPrototype("size_t ecl_type_get_sizeof_ctype_fortio_python(ecl_data_type)") _is_int = EclPrototype("bool ecl_type_is_int_python(ecl_data_type)") _is_char = EclPrototype("bool ecl_type_is_char_python(ecl_data_type)") _is_float = EclPrototype("bool ecl_type_is_float_python(ecl_data_type)") _is_double = EclPrototype("bool ecl_type_is_double_python(ecl_data_type)") _is_mess = EclPrototype("bool ecl_type_is_mess_python(ecl_data_type)") _is_bool = EclPrototype("bool ecl_type_is_bool_python(ecl_data_type)") - _get_name = EclPrototype("char* ecl_type_get_name_python(ecl_data_type)") + _is_string = EclPrototype("bool ecl_type_is_string_python(ecl_data_type)") + _get_name = EclPrototype("char* ecl_type_alloc_name_python(ecl_data_type)") _is_numeric = EclPrototype("bool ecl_type_is_numeric_python(ecl_data_type)") _is_equal = EclPrototype("bool ecl_type_is_equal_python(ecl_data_type, ecl_data_type)") @@ -60,7 +63,7 @@ class EclDataType(BaseCClass): if type_name: c_ptr = self._alloc_from_name(type_name) - elif not element_size: + elif element_size is None: c_ptr = self._alloc_from_type(type_enum) else: c_ptr = self._alloc(type_enum, element_size) @@ -70,10 +73,22 @@ class EclDataType(BaseCClass): def _assert_valid_arguments(self, type_enum, element_size, type_name): if type_name is not None: if type_enum is not None or element_size is not None: - raise ValueError("Type name given (%s). Expected both type_enum and element_size to be None") + err_msg = ("Type name given (%s). Expected both " + + "type_enum and element_size to be None") + raise ValueError(err_msg % type_name) + elif type_enum is None: raise ValueError("Both type_enum and type_name is None!") + elif type_enum == EclTypeEnum.ECL_STRING_TYPE: + if element_size is None: + raise ValueError("When creating an ECL_STRING one must " + + "provide an element size!") + + if not (0 <= element_size <= 999): + raise ValueError("Expected element_size to be in the range " + + "[0, 999], was: %d" % element_size) + @property def type(self): return self._get_type() @@ -107,6 +122,9 @@ class EclDataType(BaseCClass): def is_bool(self): return self._is_bool() + def is_string(self): + return self._is_string() + def is_numeric(self): return self._is_numeric() @@ -160,3 +178,7 @@ class EclDataType(BaseCClass): @classproperty def ECL_CHAR(cls): return EclDataType(EclTypeEnum.ECL_CHAR_TYPE) + + @classmethod + def ECL_STRING(cls, elem_size): + return EclDataType(EclTypeEnum.ECL_STRING_TYPE, elem_size) diff --git a/ThirdParty/Ert/python/python/ert/ecl/ecl_util.py b/ThirdParty/Ert/python/python/ecl/ecl/ecl_util.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/ecl_util.py rename to ThirdParty/Ert/python/python/ecl/ecl/ecl_util.py index 4be14720c7..2849c5d604 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/ecl_util.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/ecl_util.py @@ -26,7 +26,7 @@ functions from ecl_util.c which are not bound to any class type. """ import ctypes from cwrap import BaseCEnum -from ert.ecl import EclPrototype, ECL_LIB +from ecl.ecl import EclPrototype, ECL_LIB class EclFileEnum(BaseCEnum): TYPE_NAME="ecl_file_enum" diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/CMakeLists.txt b/ThirdParty/Ert/python/python/ecl/ecl/faults/CMakeLists.txt similarity index 60% rename from ThirdParty/Ert/python/python/ert/ecl/faults/CMakeLists.txt rename to ThirdParty/Ert/python/python/ecl/ecl/faults/CMakeLists.txt index bedc35aa82..d7955a8c6e 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/ecl/ecl/faults/CMakeLists.txt @@ -9,4 +9,4 @@ set(PYTHON_SOURCES layer.py ) -add_python_package("python.ert.ecl.faults" ${PYTHON_INSTALL_PREFIX}/ert/ecl/faults "${PYTHON_SOURCES}" True) +add_python_package("python.ecl.ecl.faults" ${PYTHON_INSTALL_PREFIX}/ecl/ecl/faults "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/__init__.py b/ThirdParty/Ert/python/python/ecl/ecl/faults/__init__.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/ecl/faults/__init__.py rename to ThirdParty/Ert/python/python/ecl/ecl/faults/__init__.py diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/fault.py b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/faults/fault.py rename to ThirdParty/Ert/python/python/ecl/ecl/faults/fault.py index bc392ccaac..d65fed4406 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/fault.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault.py @@ -14,9 +14,9 @@ # See the GNU General Public License at # for more details. -from ert.geo import Polyline, CPolyline, GeometryTools -from ert.util import stat -from ert.util import Matrix +from ecl.geo import Polyline, CPolyline, GeometryTools +from ecl.util import stat +from ecl.util import Matrix from .fault_line import FaultLine from .fault_segments import FaultSegment, SegmentMap diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block.py b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault_block.py similarity index 97% rename from ThirdParty/Ert/python/python/ert/ecl/faults/fault_block.py rename to ThirdParty/Ert/python/python/ecl/ecl/faults/fault_block.py index 4dc7545d4e..76830ba0c1 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault_block.py @@ -15,10 +15,10 @@ # for more details. import ctypes -from ert.ecl import EclPrototype +from ecl.ecl import EclPrototype from cwrap import BaseCClass -from ert.geo import Polyline, GeometryTools , CPolylineCollection -from ert.util import DoubleVector , IntVector +from ecl.geo import Polyline, GeometryTools , CPolylineCollection +from ecl.util import DoubleVector , IntVector class FaultBlockCell(object): def __init__(self , i,j,k ,x,y,z): diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block_collection.py b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault_block_collection.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/ecl/faults/fault_block_collection.py rename to ThirdParty/Ert/python/python/ecl/ecl/faults/fault_block_collection.py index e2d6524545..14b9d6d9ae 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block_collection.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault_block_collection.py @@ -16,7 +16,7 @@ from cwrap import BaseCClass -from ert.ecl import EclPrototype +from ecl.ecl import EclPrototype class FaultBlockCollection(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block_layer.py b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault_block_layer.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/faults/fault_block_layer.py rename to ThirdParty/Ert/python/python/ecl/ecl/faults/fault_block_layer.py index e09b10462b..d2c0b953ee 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_block_layer.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault_block_layer.py @@ -16,8 +16,8 @@ from __future__ import print_function from cwrap import BaseCClass -from ert.ecl import EclDataType, EclPrototype -from ert.ecl.faults import Fault +from ecl.ecl import EclDataType, EclPrototype +from ecl.ecl.faults import Fault class FaultBlockLayer(BaseCClass): TYPE_NAME = "fault_block_layer" diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_collection.py b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault_collection.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/faults/fault_collection.py rename to ThirdParty/Ert/python/python/ecl/ecl/faults/fault_collection.py index b0d33daef4..ca180d7cc5 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_collection.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault_collection.py @@ -16,7 +16,7 @@ import re from .fault import Fault -from ert.ecl import EclGrid +from ecl.ecl import EclGrid comment_regexp = re.compile("--.*") diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_line.py b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault_line.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/faults/fault_line.py rename to ThirdParty/Ert/python/python/ecl/ecl/faults/fault_line.py index 581f18fa15..e2ed3f9c26 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_line.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault_line.py @@ -16,8 +16,8 @@ from __future__ import print_function import sys -from ert.util import DoubleVector,stat -from ert.geo import CPolyline +from ecl.util import DoubleVector,stat +from ecl.geo import CPolyline from .fault_segments import FaultSegment diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/fault_segments.py b/ThirdParty/Ert/python/python/ecl/ecl/faults/fault_segments.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/ecl/faults/fault_segments.py rename to ThirdParty/Ert/python/python/ecl/ecl/faults/fault_segments.py diff --git a/ThirdParty/Ert/python/python/ert/ecl/faults/layer.py b/ThirdParty/Ert/python/python/ecl/ecl/faults/layer.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/ecl/faults/layer.py rename to ThirdParty/Ert/python/python/ecl/ecl/faults/layer.py index 75c246b64f..6b5a27ad51 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/faults/layer.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/faults/layer.py @@ -16,8 +16,8 @@ import ctypes from cwrap import BaseCClass -from ert.ecl import EclPrototype -from ert.util import IntVector +from ecl.ecl import EclPrototype +from ecl.util import IntVector class Layer(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/ecl/fortio.py b/ThirdParty/Ert/python/python/ecl/ecl/fortio.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/ecl/fortio.py rename to ThirdParty/Ert/python/python/ecl/ecl/fortio.py index 2c680f4a9d..3acd2f43ce 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/fortio.py +++ b/ThirdParty/Ert/python/python/ecl/ecl/fortio.py @@ -40,7 +40,7 @@ import ctypes import os import sys from cwrap import BaseCClass -from ert.ecl import EclPrototype +from ecl.ecl import EclPrototype class FortIO(BaseCClass): @@ -85,7 +85,7 @@ class FortIO(BaseCClass): all the pressure keywords to another file: import sys - from ert.ecl import FortIO, EclFile + from ecl.ecl import FortIO, EclFile rst_file = EclFile(sys.argv[1]) fortio = FortIO("PRESSURE", mode=FortIO.WRITE_MODE) @@ -194,7 +194,7 @@ def openFortIO(file_name, mode=FortIO.READ_MODE, fmt_file=False, endian_flip_hea the situation where you need to ensure resource cleanup. import sys - from ert.ecl import FortIO, EclFile + from ecl.ecl import FortIO, EclFile rst_file = EclFile(sys.argv[1]) with openFortIO("PRESSURE", mode=FortIO.WRITE_MODE) as fortio: diff --git a/ThirdParty/Ert/python/python/ert/ecl/local.cmake b/ThirdParty/Ert/python/python/ecl/ecl/local.cmake similarity index 81% rename from ThirdParty/Ert/python/python/ert/ecl/local.cmake rename to ThirdParty/Ert/python/python/ecl/ecl/local.cmake index 2eb2643d73..f2431a2a7a 100644 --- a/ThirdParty/Ert/python/python/ert/ecl/local.cmake +++ b/ThirdParty/Ert/python/python/ecl/ecl/local.cmake @@ -9,5 +9,5 @@ if (EXISTS ${ECL_LOCAL_TARGET}) endif() if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ecl_local.py") - add_python_package( "Python ert.ecl.ecl_local" ${PYTHON_INSTALL_PREFIX}/ert/ecl "ecl_local.py" True) -endif() \ No newline at end of file + add_python_package( "Python ecl.ecl.ecl_local" ${PYTHON_INSTALL_PREFIX}/ecl/ecl "ecl_local.py" True) +endif() diff --git a/ThirdParty/Ert/python/python/ecl/ecl/rft/CMakeLists.txt b/ThirdParty/Ert/python/python/ecl/ecl/rft/CMakeLists.txt new file mode 100644 index 0000000000..d41bccb489 --- /dev/null +++ b/ThirdParty/Ert/python/python/ecl/ecl/rft/CMakeLists.txt @@ -0,0 +1,6 @@ +set(PYTHON_SOURCES + __init__.py + well_trajectory.py +) + +add_python_package("python.ecl.ecl.rft" ${PYTHON_INSTALL_PREFIX}/ecl/ecl/rft "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/python/python/ert/ecl/rft/__init__.py b/ThirdParty/Ert/python/python/ecl/ecl/rft/__init__.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/ecl/rft/__init__.py rename to ThirdParty/Ert/python/python/ecl/ecl/rft/__init__.py diff --git a/ThirdParty/Ert/python/python/ert/ecl/rft/well_trajectory.py b/ThirdParty/Ert/python/python/ecl/ecl/rft/well_trajectory.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/ecl/rft/well_trajectory.py rename to ThirdParty/Ert/python/python/ecl/ecl/rft/well_trajectory.py diff --git a/ThirdParty/Ert/python/python/ert/ert_lib_info_build.py.in b/ThirdParty/Ert/python/python/ecl/ecl_lib_info_build.py.in similarity index 100% rename from ThirdParty/Ert/python/python/ert/ert_lib_info_build.py.in rename to ThirdParty/Ert/python/python/ecl/ecl_lib_info_build.py.in diff --git a/ThirdParty/Ert/python/python/ert/ert_lib_info_install.py.in b/ThirdParty/Ert/python/python/ecl/ecl_lib_info_install.py.in similarity index 100% rename from ThirdParty/Ert/python/python/ert/ert_lib_info_install.py.in rename to ThirdParty/Ert/python/python/ecl/ecl_lib_info_install.py.in diff --git a/ThirdParty/Ert/python/python/ert/geo/CMakeLists.txt b/ThirdParty/Ert/python/python/ecl/geo/CMakeLists.txt similarity index 66% rename from ThirdParty/Ert/python/python/ert/geo/CMakeLists.txt rename to ThirdParty/Ert/python/python/ecl/geo/CMakeLists.txt index c38229e4ca..563a73db75 100644 --- a/ThirdParty/Ert/python/python/ert/geo/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/ecl/geo/CMakeLists.txt @@ -10,4 +10,4 @@ set(PYTHON_SOURCES surface.py ) -add_python_package("python.ert.geo" ${PYTHON_INSTALL_PREFIX}/ert/geo "${PYTHON_SOURCES}" True) +add_python_package("python.ecl.geo" ${PYTHON_INSTALL_PREFIX}/ecl/geo "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/python/python/ert/geo/__init__.py b/ThirdParty/Ert/python/python/ecl/geo/__init__.py similarity index 96% rename from ThirdParty/Ert/python/python/ert/geo/__init__.py rename to ThirdParty/Ert/python/python/ecl/geo/__init__.py index 23a518af9a..6818408383 100644 --- a/ThirdParty/Ert/python/python/ert/geo/__init__.py +++ b/ThirdParty/Ert/python/python/ecl/geo/__init__.py @@ -17,11 +17,11 @@ Simple package for working with 2D geometry. """ -import ert +import ecl from cwrap import Prototype class GeoPrototype(Prototype): - lib = ert.load("libert_geometry") + lib = ecl.load("libert_geometry") def __init__(self, prototype, bind=True): super(GeoPrototype, self).__init__(GeoPrototype.lib, prototype, bind=bind) diff --git a/ThirdParty/Ert/python/python/ert/geo/cpolyline.py b/ThirdParty/Ert/python/python/ecl/geo/cpolyline.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/geo/cpolyline.py rename to ThirdParty/Ert/python/python/ecl/geo/cpolyline.py index 24ef9f6c45..4014059ed8 100644 --- a/ThirdParty/Ert/python/python/ert/geo/cpolyline.py +++ b/ThirdParty/Ert/python/python/ecl/geo/cpolyline.py @@ -20,7 +20,7 @@ import ctypes import os.path from cwrap import BaseCClass -from ert.geo import GeoPrototype +from ecl.geo import GeoPrototype from .geometry_tools import GeometryTools diff --git a/ThirdParty/Ert/python/python/ert/geo/cpolyline_collection.py b/ThirdParty/Ert/python/python/ecl/geo/cpolyline_collection.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/geo/cpolyline_collection.py rename to ThirdParty/Ert/python/python/ecl/geo/cpolyline_collection.py index 3df802dd93..b93f5596d9 100644 --- a/ThirdParty/Ert/python/python/ert/geo/cpolyline_collection.py +++ b/ThirdParty/Ert/python/python/ecl/geo/cpolyline_collection.py @@ -19,7 +19,7 @@ Create a polygon import ctypes from cwrap import BaseCClass -from ert.geo import GeoPrototype, CPolyline +from ecl.geo import GeoPrototype, CPolyline class CPolylineCollection(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/geo/geo_pointset.py b/ThirdParty/Ert/python/python/ecl/geo/geo_pointset.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/geo/geo_pointset.py rename to ThirdParty/Ert/python/python/ecl/geo/geo_pointset.py index 31c46ccef0..ff9fa3b2ec 100644 --- a/ThirdParty/Ert/python/python/ert/geo/geo_pointset.py +++ b/ThirdParty/Ert/python/python/ecl/geo/geo_pointset.py @@ -14,7 +14,7 @@ # See the GNU General Public License at # for more details. from cwrap import BaseCClass -from ert.geo import GeoPrototype +from ecl.geo import GeoPrototype class GeoPointset(BaseCClass): TYPE_NAME = "geo_pointset" diff --git a/ThirdParty/Ert/python/python/ert/geo/geo_region.py b/ThirdParty/Ert/python/python/ecl/geo/geo_region.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/geo/geo_region.py rename to ThirdParty/Ert/python/python/ecl/geo/geo_region.py index 648a0dabc7..a4238d8650 100644 --- a/ThirdParty/Ert/python/python/ert/geo/geo_region.py +++ b/ThirdParty/Ert/python/python/ecl/geo/geo_region.py @@ -14,8 +14,8 @@ # See the GNU General Public License at # for more details. from cwrap import BaseCClass -from ert.util import IntVector -from ert.geo import GeoPrototype +from ecl.util import IntVector +from ecl.geo import GeoPrototype from .cpolyline import CPolyline from ctypes import c_double diff --git a/ThirdParty/Ert/python/python/ert/geo/geometry_tools.py b/ThirdParty/Ert/python/python/ecl/geo/geometry_tools.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/geo/geometry_tools.py rename to ThirdParty/Ert/python/python/ecl/geo/geometry_tools.py diff --git a/ThirdParty/Ert/python/python/ert/geo/polyline.py b/ThirdParty/Ert/python/python/ecl/geo/polyline.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/geo/polyline.py rename to ThirdParty/Ert/python/python/ecl/geo/polyline.py diff --git a/ThirdParty/Ert/python/python/ert/geo/surface.py b/ThirdParty/Ert/python/python/ecl/geo/surface.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/geo/surface.py rename to ThirdParty/Ert/python/python/ecl/geo/surface.py index f16d18b8da..6dfeae9b9a 100644 --- a/ThirdParty/Ert/python/python/ert/geo/surface.py +++ b/ThirdParty/Ert/python/python/ecl/geo/surface.py @@ -21,8 +21,8 @@ import ctypes from numpy import zeros from cwrap import BaseCClass -from ert.geo import GeoPrototype -from ert.geo import GeoPointset +from ecl.geo import GeoPrototype +from ecl.geo import GeoPointset class Surface(BaseCClass): TYPE_NAME = "surface" diff --git a/ThirdParty/Ert/python/python/ert/geo/xyz_io.py b/ThirdParty/Ert/python/python/ecl/geo/xyz_io.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/geo/xyz_io.py rename to ThirdParty/Ert/python/python/ecl/geo/xyz_io.py diff --git a/ThirdParty/Ert/python/python/ert/test/CMakeLists.txt b/ThirdParty/Ert/python/python/ecl/test/CMakeLists.txt similarity index 67% rename from ThirdParty/Ert/python/python/ert/test/CMakeLists.txt rename to ThirdParty/Ert/python/python/ecl/test/CMakeLists.txt index 3bb95d6c6b..bce318e98c 100644 --- a/ThirdParty/Ert/python/python/ert/test/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/ecl/test/CMakeLists.txt @@ -9,8 +9,9 @@ set(PYTHON_SOURCES temp_area.py path_context.py lint_test_case.py + import_test_case.py ) -add_python_package("python.ert.test" ${PYTHON_INSTALL_PREFIX}/ert/test "${PYTHON_SOURCES}" True) +add_python_package("python.ecl.test" ${PYTHON_INSTALL_PREFIX}/ecl/test "${PYTHON_SOURCES}" True) add_subdirectory(ecl_mock) diff --git a/ThirdParty/Ert/python/python/ert/test/__init__.py b/ThirdParty/Ert/python/python/ecl/test/__init__.py similarity index 80% rename from ThirdParty/Ert/python/python/ert/test/__init__.py rename to ThirdParty/Ert/python/python/ecl/test/__init__.py index cc522e3733..de61efbb8c 100644 --- a/ThirdParty/Ert/python/python/ert/test/__init__.py +++ b/ThirdParty/Ert/python/python/ecl/test/__init__.py @@ -7,7 +7,4 @@ from .temp_area import TempArea , TempAreaContext from .ert_test_runner import ErtTestRunner from .path_context import PathContext from .lint_test_case import LintTestCase -try: - from .ert_test_context import ErtTestContext, ErtTest -except ImportError: - pass +from .import_test_case import ImportTestCase diff --git a/ThirdParty/Ert/python/python/ecl/test/ecl_mock/CMakeLists.txt b/ThirdParty/Ert/python/python/ecl/test/ecl_mock/CMakeLists.txt new file mode 100644 index 0000000000..19ffbf7540 --- /dev/null +++ b/ThirdParty/Ert/python/python/ecl/test/ecl_mock/CMakeLists.txt @@ -0,0 +1,7 @@ +set(PYTHON_SOURCES + __init__.py + ecl_sum_mock.py +) + +# The ecl_mock package is not installed. +add_python_package("python.ecl.test.ecl_mock" ${PYTHON_INSTALL_PREFIX}/ecl/test/ecl_mock "${PYTHON_SOURCES}" False) diff --git a/ThirdParty/Ert/python/python/ert/test/ecl_mock/__init__.py b/ThirdParty/Ert/python/python/ecl/test/ecl_mock/__init__.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/test/ecl_mock/__init__.py rename to ThirdParty/Ert/python/python/ecl/test/ecl_mock/__init__.py diff --git a/ThirdParty/Ert/python/python/ert/test/ecl_mock/ecl_sum_mock.py b/ThirdParty/Ert/python/python/ecl/test/ecl_mock/ecl_sum_mock.py similarity index 97% rename from ThirdParty/Ert/python/python/ert/test/ecl_mock/ecl_sum_mock.py rename to ThirdParty/Ert/python/python/ecl/test/ecl_mock/ecl_sum_mock.py index 3b0e3f4f7d..eb2b779229 100644 --- a/ThirdParty/Ert/python/python/ert/test/ecl_mock/ecl_sum_mock.py +++ b/ThirdParty/Ert/python/python/ecl/test/ecl_mock/ecl_sum_mock.py @@ -1,5 +1,5 @@ import datetime -from ert.ecl import EclSum +from ecl.ecl import EclSum def mock_func(ecl_sum , key , days): diff --git a/ThirdParty/Ert/python/python/ert/test/ert_test_context.py b/ThirdParty/Ert/python/python/ecl/test/ert_test_context.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/test/ert_test_context.py rename to ThirdParty/Ert/python/python/ecl/test/ert_test_context.py diff --git a/ThirdParty/Ert/python/python/ert/test/ert_test_runner.py b/ThirdParty/Ert/python/python/ecl/test/ert_test_runner.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/test/ert_test_runner.py rename to ThirdParty/Ert/python/python/ecl/test/ert_test_runner.py diff --git a/ThirdParty/Ert/python/python/ert/test/extended_testcase.py b/ThirdParty/Ert/python/python/ecl/test/extended_testcase.py similarity index 90% rename from ThirdParty/Ert/python/python/ert/test/extended_testcase.py rename to ThirdParty/Ert/python/python/ecl/test/extended_testcase.py index 90da55c510..d1adb0ecfa 100644 --- a/ThirdParty/Ert/python/python/ert/test/extended_testcase.py +++ b/ThirdParty/Ert/python/python/ecl/test/extended_testcase.py @@ -10,8 +10,8 @@ except ImportError: from unittest import TestCase from .source_enumerator import SourceEnumerator -from ert.util import installAbortSignals -from ert.util import Version +from ecl.util import installAbortSignals +from ecl.util import Version TESTDATA_ROOT = None SHARE_ROOT = None @@ -27,7 +27,7 @@ try: except ImportError: sys.stderr.write("Warning: could not import file test_env.py - this might lead to test failures.") - + class _AssertNotRaisesContext(object): def __init__(self, test_class): @@ -58,6 +58,12 @@ class ExtendedTestCase(TestCase): super(ExtendedTestCase , self).__init__(*args , **kwargs) + def __str__(self): + return 'ExtendedTestCase( TESTADATA_ROOT=%s, SOURCE_ROOT=%s, SHARE_ROOT=%s, BUILD_ROOT=%s)' % (TESTDATA_ROOT, + SOURCE_ROOT, + SHARE_ROOT, + BUILD_ROOT) + def assertFloatEqual(self, first, second, msg=None, tolerance=1e-6): try: f_first, f_second = float(first), float(second) @@ -136,7 +142,7 @@ class ExtendedTestCase(TestCase): @staticmethod def createSharePath(path): return os.path.realpath(os.path.join(SHARE_ROOT , path)) - + @staticmethod def createTestPath(path): @@ -170,4 +176,3 @@ class ExtendedTestCase(TestCase): return True else: return False - diff --git a/ThirdParty/Ert/python/python/ecl/test/import_test_case.py b/ThirdParty/Ert/python/python/ecl/test/import_test_case.py new file mode 100644 index 0000000000..f803f3c57c --- /dev/null +++ b/ThirdParty/Ert/python/python/ecl/test/import_test_case.py @@ -0,0 +1,49 @@ +# Copyright (C) 2017 Statoil ASA, Norway. +# +# This file is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. + +import importlib +import os +import sys +import traceback +import unittest +import inspect + +class ImportTestCase(unittest.TestCase): + + + def import_module(self , module): + mod = importlib.import_module( module ) + return mod + + def import_package(self, package): + module = self.import_module( package ) + path = os.path.dirname( inspect.getfile( module ) ) + + for entry in sorted(os.listdir(path)): + entry_path = os.path.join(path, entry) + if os.path.isdir( entry_path ): + module = os.path.basename( entry ) + sub_module = "%s.%s" % (package , module) + self.import_package( sub_module ) + else: + module, ext = os.path.splitext( entry ) + if module == "__init__": + continue + + if ext == "py": + self.import_module("%s.%s" % (package , module)) + + return True diff --git a/ThirdParty/Ert/python/python/ert/test/lint_test_case.py b/ThirdParty/Ert/python/python/ecl/test/lint_test_case.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/test/lint_test_case.py rename to ThirdParty/Ert/python/python/ecl/test/lint_test_case.py diff --git a/ThirdParty/Ert/python/python/ert/test/path_context.py b/ThirdParty/Ert/python/python/ecl/test/path_context.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/test/path_context.py rename to ThirdParty/Ert/python/python/ecl/test/path_context.py diff --git a/ThirdParty/Ert/python/python/ert/test/source_enumerator.py b/ThirdParty/Ert/python/python/ecl/test/source_enumerator.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/test/source_enumerator.py rename to ThirdParty/Ert/python/python/ecl/test/source_enumerator.py diff --git a/ThirdParty/Ert/python/python/ert/test/temp_area.py b/ThirdParty/Ert/python/python/ecl/test/temp_area.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/test/temp_area.py rename to ThirdParty/Ert/python/python/ecl/test/temp_area.py index d7271f103b..4679eed017 100644 --- a/ThirdParty/Ert/python/python/ert/test/temp_area.py +++ b/ThirdParty/Ert/python/python/ecl/test/temp_area.py @@ -16,7 +16,7 @@ import os import os.path -from ert.util import UtilPrototype +from ecl.util import UtilPrototype from . import TestArea class TempArea(TestArea): diff --git a/ThirdParty/Ert/python/python/ert/test/test_area.py b/ThirdParty/Ert/python/python/ecl/test/test_area.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/test/test_area.py rename to ThirdParty/Ert/python/python/ecl/test/test_area.py index e7414f0412..0d2cb1cf57 100644 --- a/ThirdParty/Ert/python/python/ert/test/test_area.py +++ b/ThirdParty/Ert/python/python/ecl/test/test_area.py @@ -16,7 +16,7 @@ import os.path from cwrap import BaseCClass -from ert.util import UtilPrototype +from ecl.util import UtilPrototype class TestArea(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/test/test_run.py b/ThirdParty/Ert/python/python/ecl/test/test_run.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/test/test_run.py rename to ThirdParty/Ert/python/python/ecl/test/test_run.py diff --git a/ThirdParty/Ert/python/python/ert/util/CMakeLists.txt b/ThirdParty/Ert/python/python/ecl/util/CMakeLists.txt similarity index 83% rename from ThirdParty/Ert/python/python/ert/util/CMakeLists.txt rename to ThirdParty/Ert/python/python/ecl/util/CMakeLists.txt index d07fc4c308..4f8ecb2888 100644 --- a/ThirdParty/Ert/python/python/ert/util/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/ecl/util/CMakeLists.txt @@ -27,6 +27,6 @@ set(PYTHON_SOURCES path_format.py ) -add_python_package("python.ert.util" ${PYTHON_INSTALL_PREFIX}/ert/util "${PYTHON_SOURCES}" True) +add_python_package("python.ecl.util" ${PYTHON_INSTALL_PREFIX}/ecl/util "${PYTHON_SOURCES}" True) add_subdirectory(enums) diff --git a/ThirdParty/Ert/python/python/ert/util/__init__.py b/ThirdParty/Ert/python/python/ecl/util/__init__.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/util/__init__.py rename to ThirdParty/Ert/python/python/ecl/util/__init__.py index 96b963f10a..c9071da3c7 100644 --- a/ThirdParty/Ert/python/python/ert/util/__init__.py +++ b/ThirdParty/Ert/python/python/ecl/util/__init__.py @@ -39,12 +39,12 @@ The modules included in the util package are: from __future__ import (absolute_import, division, print_function, unicode_literals) -import ert +import ecl from cwrap import Prototype class UtilPrototype(Prototype): - lib = ert.load("libert_util") + lib = ecl.load("libert_util") def __init__(self, prototype, bind=True): super(UtilPrototype, self).__init__(UtilPrototype.lib, prototype, bind=bind) diff --git a/ThirdParty/Ert/python/python/ert/util/arg_pack.py b/ThirdParty/Ert/python/python/ecl/util/arg_pack.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/util/arg_pack.py rename to ThirdParty/Ert/python/python/ecl/util/arg_pack.py index 1297514086..e20bd3fe99 100644 --- a/ThirdParty/Ert/python/python/ert/util/arg_pack.py +++ b/ThirdParty/Ert/python/python/ecl/util/arg_pack.py @@ -15,7 +15,7 @@ # for more details. from cwrap import BaseCClass -from ert.util import UtilPrototype +from ecl.util import UtilPrototype class ArgPack(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/util/bool_vector.py b/ThirdParty/Ert/python/python/ecl/util/bool_vector.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/util/bool_vector.py rename to ThirdParty/Ert/python/python/ecl/util/bool_vector.py index 88ea0edb24..9f920628a9 100644 --- a/ThirdParty/Ert/python/python/ert/util/bool_vector.py +++ b/ThirdParty/Ert/python/python/ecl/util/bool_vector.py @@ -14,7 +14,7 @@ # See the GNU General Public License at # for more details. -from ert.util import VectorTemplate, UtilPrototype +from ecl.util import VectorTemplate, UtilPrototype class BoolVector(VectorTemplate): @@ -119,7 +119,7 @@ class BoolVector(VectorTemplate): return bool_vector def createActiveList(self): - """ @rtype: ert.util.IntVector """ + """ @rtype: ecl.util.IntVector """ return self._active_list(self) def _tostr(self, arr = None): diff --git a/ThirdParty/Ert/python/python/ert/util/buffer.py b/ThirdParty/Ert/python/python/ecl/util/buffer.py similarity index 96% rename from ThirdParty/Ert/python/python/ert/util/buffer.py rename to ThirdParty/Ert/python/python/ecl/util/buffer.py index 9fa3a36dce..44a96cfd62 100644 --- a/ThirdParty/Ert/python/python/ert/util/buffer.py +++ b/ThirdParty/Ert/python/python/ecl/util/buffer.py @@ -15,7 +15,7 @@ # for more details. from cwrap import BaseCClass -from ert.util import UtilPrototype +from ecl.util import UtilPrototype class Buffer(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/util/cthread_pool.py b/ThirdParty/Ert/python/python/ecl/util/cthread_pool.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/util/cthread_pool.py rename to ThirdParty/Ert/python/python/ecl/util/cthread_pool.py index 07a4eb7213..5c5824b2b7 100644 --- a/ThirdParty/Ert/python/python/ert/util/cthread_pool.py +++ b/ThirdParty/Ert/python/python/ecl/util/cthread_pool.py @@ -17,7 +17,7 @@ import ctypes from cwrap import BaseCClass -from ert.util import UtilPrototype +from ecl.util import UtilPrototype class CThreadPool(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/util/ctime.py b/ThirdParty/Ert/python/python/ecl/util/ctime.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/util/ctime.py rename to ThirdParty/Ert/python/python/ecl/util/ctime.py index d0fc1c1ef2..04d7d42e2a 100644 --- a/ThirdParty/Ert/python/python/ert/util/ctime.py +++ b/ThirdParty/Ert/python/python/ecl/util/ctime.py @@ -20,7 +20,7 @@ import datetime import time from cwrap import BaseCValue -from ert.util import UtilPrototype +from ecl.util import UtilPrototype class CTime(BaseCValue): diff --git a/ThirdParty/Ert/python/python/ert/util/double_vector.py b/ThirdParty/Ert/python/python/ecl/util/double_vector.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/util/double_vector.py rename to ThirdParty/Ert/python/python/ecl/util/double_vector.py index 548dcbc5c6..28a39cfc20 100644 --- a/ThirdParty/Ert/python/python/ert/util/double_vector.py +++ b/ThirdParty/Ert/python/python/ecl/util/double_vector.py @@ -14,7 +14,7 @@ # See the GNU General Public License at # for more details. -from ert.util import VectorTemplate, UtilPrototype +from ecl.util import VectorTemplate, UtilPrototype class DoubleVector(VectorTemplate): diff --git a/ThirdParty/Ert/python/python/ert/util/enums/CMakeLists.txt b/ThirdParty/Ert/python/python/ecl/util/enums/CMakeLists.txt similarity index 56% rename from ThirdParty/Ert/python/python/ert/util/enums/CMakeLists.txt rename to ThirdParty/Ert/python/python/ecl/util/enums/CMakeLists.txt index a1f96b233e..18c2673477 100644 --- a/ThirdParty/Ert/python/python/ert/util/enums/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/ecl/util/enums/CMakeLists.txt @@ -6,5 +6,5 @@ set(PYTHON_SOURCES llsq_result_enum.py ) -add_python_package("python.ert.util.enums" ${PYTHON_INSTALL_PREFIX}/ert/util/enums "${PYTHON_SOURCES}" True) +add_python_package("python.ecl.util.enums" ${PYTHON_INSTALL_PREFIX}/ecl/util/enums "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/python/python/ert/util/enums/__init__.py b/ThirdParty/Ert/python/python/ecl/util/enums/__init__.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/util/enums/__init__.py rename to ThirdParty/Ert/python/python/ecl/util/enums/__init__.py diff --git a/ThirdParty/Ert/python/python/ert/util/enums/llsq_result_enum.py b/ThirdParty/Ert/python/python/ecl/util/enums/llsq_result_enum.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/util/enums/llsq_result_enum.py rename to ThirdParty/Ert/python/python/ecl/util/enums/llsq_result_enum.py diff --git a/ThirdParty/Ert/python/python/ert/util/enums/rng_alg_type_enum.py b/ThirdParty/Ert/python/python/ecl/util/enums/rng_alg_type_enum.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/util/enums/rng_alg_type_enum.py rename to ThirdParty/Ert/python/python/ecl/util/enums/rng_alg_type_enum.py diff --git a/ThirdParty/Ert/python/python/ert/util/enums/rng_init_mode_enum.py b/ThirdParty/Ert/python/python/ecl/util/enums/rng_init_mode_enum.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/util/enums/rng_init_mode_enum.py rename to ThirdParty/Ert/python/python/ecl/util/enums/rng_init_mode_enum.py diff --git a/ThirdParty/Ert/python/python/ert/util/enums/ui_return_status_enum.py b/ThirdParty/Ert/python/python/ecl/util/enums/ui_return_status_enum.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/util/enums/ui_return_status_enum.py rename to ThirdParty/Ert/python/python/ecl/util/enums/ui_return_status_enum.py diff --git a/ThirdParty/Ert/python/python/ert/util/hash.py b/ThirdParty/Ert/python/python/ecl/util/hash.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/util/hash.py rename to ThirdParty/Ert/python/python/ecl/util/hash.py index dbf2086197..bd2a18289d 100644 --- a/ThirdParty/Ert/python/python/ert/util/hash.py +++ b/ThirdParty/Ert/python/python/ecl/util/hash.py @@ -16,7 +16,7 @@ from ctypes import c_void_p from cwrap import BaseCClass -from ert.util import StringList, UtilPrototype +from ecl.util import StringList, UtilPrototype class Hash(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/util/install_abort_signals.py b/ThirdParty/Ert/python/python/ecl/util/install_abort_signals.py similarity index 89% rename from ThirdParty/Ert/python/python/ert/util/install_abort_signals.py rename to ThirdParty/Ert/python/python/ecl/util/install_abort_signals.py index 01cd6c74b1..59cddabe75 100644 --- a/ThirdParty/Ert/python/python/ert/util/install_abort_signals.py +++ b/ThirdParty/Ert/python/python/ecl/util/install_abort_signals.py @@ -1,4 +1,4 @@ -from ert.util import UtilPrototype +from ecl.util import UtilPrototype def installAbortSignals(): diff --git a/ThirdParty/Ert/python/python/ert/util/int_vector.py b/ThirdParty/Ert/python/python/ecl/util/int_vector.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/util/int_vector.py rename to ThirdParty/Ert/python/python/ecl/util/int_vector.py index 0809d5b0cc..277a76f9eb 100644 --- a/ThirdParty/Ert/python/python/ert/util/int_vector.py +++ b/ThirdParty/Ert/python/python/ecl/util/int_vector.py @@ -14,7 +14,7 @@ # See the GNU General Public License at # for more details. -from ert.util import VectorTemplate, UtilPrototype +from ecl.util import VectorTemplate, UtilPrototype class IntVector(VectorTemplate): diff --git a/ThirdParty/Ert/python/python/ert/util/log.py b/ThirdParty/Ert/python/python/ecl/util/log.py similarity index 97% rename from ThirdParty/Ert/python/python/ert/util/log.py rename to ThirdParty/Ert/python/python/ecl/util/log.py index 550a18e07f..2e766b83a6 100644 --- a/ThirdParty/Ert/python/python/ert/util/log.py +++ b/ThirdParty/Ert/python/python/ecl/util/log.py @@ -16,7 +16,7 @@ from __future__ import print_function from cwrap import BaseCClass -from ert.util import UtilPrototype +from ecl.util import UtilPrototype class Log(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/util/lookup_table.py b/ThirdParty/Ert/python/python/ecl/util/lookup_table.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/util/lookup_table.py rename to ThirdParty/Ert/python/python/ecl/util/lookup_table.py index 4cb6fb87f2..6497a8273c 100644 --- a/ThirdParty/Ert/python/python/ert/util/lookup_table.py +++ b/ThirdParty/Ert/python/python/ecl/util/lookup_table.py @@ -16,7 +16,7 @@ from cwrap import BaseCClass -from ert.util import UtilPrototype +from ecl.util import UtilPrototype class LookupTable(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/util/matrix.py b/ThirdParty/Ert/python/python/ecl/util/matrix.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/util/matrix.py rename to ThirdParty/Ert/python/python/ecl/util/matrix.py index e4ddafea31..1c8392daba 100644 --- a/ThirdParty/Ert/python/python/ert/util/matrix.py +++ b/ThirdParty/Ert/python/python/ecl/util/matrix.py @@ -29,7 +29,7 @@ from cwrap import BaseCClass,CFILE -from ert.util import UtilPrototype +from ecl.util import UtilPrototype class Matrix(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/util/path_format.py b/ThirdParty/Ert/python/python/ecl/util/path_format.py similarity index 92% rename from ThirdParty/Ert/python/python/ert/util/path_format.py rename to ThirdParty/Ert/python/python/ecl/util/path_format.py index 165cff2905..0fe290891e 100644 --- a/ThirdParty/Ert/python/python/ert/util/path_format.py +++ b/ThirdParty/Ert/python/python/ecl/util/path_format.py @@ -1,5 +1,5 @@ from cwrap import BaseCClass -from ert.util import UtilPrototype +from ecl.util import UtilPrototype class PathFormat(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/util/permutation_vector.py b/ThirdParty/Ert/python/python/ecl/util/permutation_vector.py similarity index 96% rename from ThirdParty/Ert/python/python/ert/util/permutation_vector.py rename to ThirdParty/Ert/python/python/ecl/util/permutation_vector.py index a5c272304f..dabbd3788f 100644 --- a/ThirdParty/Ert/python/python/ert/util/permutation_vector.py +++ b/ThirdParty/Ert/python/python/ecl/util/permutation_vector.py @@ -1,5 +1,5 @@ from cwrap import BaseCClass -from ert.util import UtilPrototype +from ecl.util import UtilPrototype class PermutationVector(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/util/profiler.py b/ThirdParty/Ert/python/python/ecl/util/profiler.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/util/profiler.py rename to ThirdParty/Ert/python/python/ecl/util/profiler.py diff --git a/ThirdParty/Ert/python/python/ert/util/rng.py b/ThirdParty/Ert/python/python/ecl/util/rng.py similarity index 96% rename from ThirdParty/Ert/python/python/ert/util/rng.py rename to ThirdParty/Ert/python/python/ecl/util/rng.py index 26e8eb623e..a747d31887 100644 --- a/ThirdParty/Ert/python/python/ert/util/rng.py +++ b/ThirdParty/Ert/python/python/ecl/util/rng.py @@ -16,8 +16,8 @@ import os.path from cwrap import BaseCClass -from ert.util import UtilPrototype -from ert.util.enums import RngInitModeEnum, RngAlgTypeEnum +from ecl.util import UtilPrototype +from ecl.util.enums import RngInitModeEnum, RngAlgTypeEnum class RandomNumberGenerator(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/util/stat.py b/ThirdParty/Ert/python/python/ecl/util/stat.py similarity index 93% rename from ThirdParty/Ert/python/python/ert/util/stat.py rename to ThirdParty/Ert/python/python/ecl/util/stat.py index 8efcbe587b..d219a7869a 100644 --- a/ThirdParty/Ert/python/python/ert/util/stat.py +++ b/ThirdParty/Ert/python/python/ecl/util/stat.py @@ -16,14 +16,14 @@ from collections import Sequence from cwrap import PrototypeError -from ert.util import LLSQResultEnum, UtilPrototype, Matrix +from ecl.util import LLSQResultEnum, UtilPrototype, Matrix quantile = UtilPrototype("double statistics_empirical_quantile(double_vector, double)") -"""@type: (ert.util.DoubleVector, float)->float""" +"""@type: (ecl.util.DoubleVector, float)->float""" quantile_sorted = UtilPrototype("double statistics_empirical_quantile(double_vector, double)") -"""@type: (ert.util.DoubleVector, float)->float""" +"""@type: (ecl.util.DoubleVector, float)->float""" try: _polyfit = UtilPrototype("llsq_result_enum matrix_stat_polyfit(matrix, matrix, matrix, matrix)") diff --git a/ThirdParty/Ert/python/python/ert/util/stringlist.py b/ThirdParty/Ert/python/python/ecl/util/stringlist.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/util/stringlist.py rename to ThirdParty/Ert/python/python/ecl/util/stringlist.py index 25432da8a9..f4e22b03c6 100644 --- a/ThirdParty/Ert/python/python/ert/util/stringlist.py +++ b/ThirdParty/Ert/python/python/ecl/util/stringlist.py @@ -32,7 +32,7 @@ hardly need to notice that the StringList class is at play. """ from __future__ import absolute_import, division, print_function, unicode_literals from six import string_types -from ert.util import UtilPrototype +from ecl.util import UtilPrototype from cwrap import BaseCClass diff --git a/ThirdParty/Ert/python/python/ert/util/substitution_list.py b/ThirdParty/Ert/python/python/ecl/util/substitution_list.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/util/substitution_list.py rename to ThirdParty/Ert/python/python/ecl/util/substitution_list.py index d0902b7f45..925a9de086 100644 --- a/ThirdParty/Ert/python/python/ert/util/substitution_list.py +++ b/ThirdParty/Ert/python/python/ecl/util/substitution_list.py @@ -1,5 +1,5 @@ from cwrap import BaseCClass -from ert.util import UtilPrototype +from ecl.util import UtilPrototype class SubstitutionList(BaseCClass): diff --git a/ThirdParty/Ert/python/python/ert/util/thread_pool.py b/ThirdParty/Ert/python/python/ecl/util/thread_pool.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/util/thread_pool.py rename to ThirdParty/Ert/python/python/ecl/util/thread_pool.py diff --git a/ThirdParty/Ert/python/python/ert/util/time_vector.py b/ThirdParty/Ert/python/python/ecl/util/time_vector.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/util/time_vector.py rename to ThirdParty/Ert/python/python/ecl/util/time_vector.py index 68b39dc17e..7821057fc7 100644 --- a/ThirdParty/Ert/python/python/ert/util/time_vector.py +++ b/ThirdParty/Ert/python/python/ecl/util/time_vector.py @@ -16,7 +16,7 @@ import datetime import re -from ert.util import VectorTemplate, CTime, UtilPrototype +from ecl.util import VectorTemplate, CTime, UtilPrototype class TimeVector(VectorTemplate): diff --git a/ThirdParty/Ert/python/python/ert/util/ui_return.py b/ThirdParty/Ert/python/python/ecl/util/ui_return.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/util/ui_return.py rename to ThirdParty/Ert/python/python/ecl/util/ui_return.py index d498863188..cfe4b28180 100644 --- a/ThirdParty/Ert/python/python/ert/util/ui_return.py +++ b/ThirdParty/Ert/python/python/ecl/util/ui_return.py @@ -18,7 +18,7 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) from cwrap import BaseCClass -from ert.util import UtilPrototype +from ecl.util import UtilPrototype from .enums import UIReturnStatusEnum diff --git a/ThirdParty/Ert/python/python/ert/util/util_func.py b/ThirdParty/Ert/python/python/ecl/util/util_func.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/util/util_func.py rename to ThirdParty/Ert/python/python/ecl/util/util_func.py index 382b000ac6..0d9e4aa2ac 100644 --- a/ThirdParty/Ert/python/python/ert/util/util_func.py +++ b/ThirdParty/Ert/python/python/ecl/util/util_func.py @@ -17,7 +17,7 @@ Module with utility functions from util.c """ -from ert.util import UtilPrototype +from ecl.util import UtilPrototype strcmp_int = UtilPrototype("int util_strcmp_int( char* , char* )") """ diff --git a/ThirdParty/Ert/python/python/ert/util/vector_template.py b/ThirdParty/Ert/python/python/ecl/util/vector_template.py similarity index 99% rename from ThirdParty/Ert/python/python/ert/util/vector_template.py rename to ThirdParty/Ert/python/python/ecl/util/vector_template.py index fbb9f048b8..56b96c582b 100644 --- a/ThirdParty/Ert/python/python/ert/util/vector_template.py +++ b/ThirdParty/Ert/python/python/ecl/util/vector_template.py @@ -45,7 +45,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera import sys from cwrap import CFILE, BaseCClass -from ert.util import UtilPrototype +from ecl.util import UtilPrototype diff --git a/ThirdParty/Ert/python/python/ert/util/version.py b/ThirdParty/Ert/python/python/ecl/util/version.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/util/version.py rename to ThirdParty/Ert/python/python/ecl/util/version.py index b17bb6b056..95b8957ea7 100644 --- a/ThirdParty/Ert/python/python/ert/util/version.py +++ b/ThirdParty/Ert/python/python/ecl/util/version.py @@ -1,4 +1,4 @@ -from ert.util import UtilPrototype +from ecl.util import UtilPrototype def cmp_method(method): diff --git a/ThirdParty/Ert/python/python/ert/well/CMakeLists.txt b/ThirdParty/Ert/python/python/ecl/well/CMakeLists.txt similarity index 67% rename from ThirdParty/Ert/python/python/ert/well/CMakeLists.txt rename to ThirdParty/Ert/python/python/ecl/well/CMakeLists.txt index c9601f7487..b37c7f17c4 100644 --- a/ThirdParty/Ert/python/python/ert/well/CMakeLists.txt +++ b/ThirdParty/Ert/python/python/ecl/well/CMakeLists.txt @@ -9,5 +9,5 @@ set(PYTHON_SOURCES well_type_enum.py ) -add_python_package("python.ert.well" ${PYTHON_INSTALL_PREFIX}/ert/well "${PYTHON_SOURCES}" True) +add_python_package("python.ecl.well" ${PYTHON_INSTALL_PREFIX}/ecl/well "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/python/python/ert/well/__init__.py b/ThirdParty/Ert/python/python/ecl/well/__init__.py similarity index 84% rename from ThirdParty/Ert/python/python/ert/well/__init__.py rename to ThirdParty/Ert/python/python/ecl/well/__init__.py index de69509186..5050afb29e 100644 --- a/ThirdParty/Ert/python/python/ert/well/__init__.py +++ b/ThirdParty/Ert/python/python/ecl/well/__init__.py @@ -1,12 +1,12 @@ -import ert -import ert.util -import ert.geo -import ert.ecl +import ecl +import ecl.util +import ecl.geo +import ecl.ecl from cwrap import Prototype class WellPrototype(Prototype): - lib = ert.load("libecl_well") + lib = ecl.load("libecl_well") def __init__(self, prototype, bind=True): super(WellPrototype, self).__init__(WellPrototype.lib, prototype, bind=bind) diff --git a/ThirdParty/Ert/python/python/ert/well/well_connection.py b/ThirdParty/Ert/python/python/ecl/well/well_connection.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/well/well_connection.py rename to ThirdParty/Ert/python/python/ecl/well/well_connection.py index 9b42d21694..8dc86af3ac 100644 --- a/ThirdParty/Ert/python/python/ert/well/well_connection.py +++ b/ThirdParty/Ert/python/python/ecl/well/well_connection.py @@ -1,5 +1,5 @@ from cwrap import BaseCClass -from ert.well import WellPrototype, WellConnectionDirectionEnum +from ecl.well import WellPrototype, WellConnectionDirectionEnum class WellConnection(BaseCClass): TYPE_NAME = "well_connection" diff --git a/ThirdParty/Ert/python/python/ert/well/well_connection_direction_enum.py b/ThirdParty/Ert/python/python/ecl/well/well_connection_direction_enum.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/well/well_connection_direction_enum.py rename to ThirdParty/Ert/python/python/ecl/well/well_connection_direction_enum.py diff --git a/ThirdParty/Ert/python/python/ert/well/well_info.py b/ThirdParty/Ert/python/python/ecl/well/well_info.py similarity index 95% rename from ThirdParty/Ert/python/python/ert/well/well_info.py rename to ThirdParty/Ert/python/python/ecl/well/well_info.py index 160a0659fb..31276ec8b2 100644 --- a/ThirdParty/Ert/python/python/ert/well/well_info.py +++ b/ThirdParty/Ert/python/python/ecl/well/well_info.py @@ -1,7 +1,7 @@ from cwrap import BaseCClass -from ert.ecl import EclGrid -from ert.ecl.ecl_file import EclFile -from ert.well import WellTimeLine, WellPrototype +from ecl.ecl import EclGrid +from ecl.ecl.ecl_file import EclFile +from ecl.well import WellTimeLine, WellPrototype class WellInfo(BaseCClass): @@ -33,7 +33,6 @@ class WellInfo(BaseCClass): self.addWellFile(item, load_segment_information) else: self.addWellFile(rst_file, load_segment_information) - self.__str__ = self.__repr__ def __repr__(self): diff --git a/ThirdParty/Ert/python/python/ert/well/well_segment.py b/ThirdParty/Ert/python/python/ecl/well/well_segment.py similarity index 98% rename from ThirdParty/Ert/python/python/ert/well/well_segment.py rename to ThirdParty/Ert/python/python/ecl/well/well_segment.py index 99a527cd97..6e7aeb2f40 100644 --- a/ThirdParty/Ert/python/python/ert/well/well_segment.py +++ b/ThirdParty/Ert/python/python/ecl/well/well_segment.py @@ -1,5 +1,5 @@ from cwrap import BaseCClass -from ert.well import WellPrototype +from ecl.well import WellPrototype class WellSegment(BaseCClass): TYPE_NAME = "well_segment" diff --git a/ThirdParty/Ert/python/python/ert/well/well_state.py b/ThirdParty/Ert/python/python/ecl/well/well_state.py similarity index 94% rename from ThirdParty/Ert/python/python/ert/well/well_state.py rename to ThirdParty/Ert/python/python/ecl/well/well_state.py index 103f16f4ff..6d0cadf567 100644 --- a/ThirdParty/Ert/python/python/ert/well/well_state.py +++ b/ThirdParty/Ert/python/python/ecl/well/well_state.py @@ -1,6 +1,6 @@ from cwrap import BaseCClass -from ert.well import WellTypeEnum, WellConnection, WellPrototype -from ert.util import CTime +from ecl.well import WellTypeEnum, WellConnection, WellPrototype +from ecl.util import CTime class WellState(BaseCClass): TYPE_NAME = "well_state" @@ -30,7 +30,7 @@ class WellState(BaseCClass): _gas_rate_si = WellPrototype("double well_state_get_gas_rate_si(well_state)") _water_rate_si = WellPrototype("double well_state_get_water_rate_si(well_state)") _volume_rate_si = WellPrototype("double well_state_get_volume_rate_si(well_state)") - + _get_global_well_head = WellPrototype("well_connection_ref well_state_get_global_wellhead(well_state)") def __init__(self): raise NotImplementedError("Class can not be instantiated directly") @@ -46,6 +46,11 @@ class WellState(BaseCClass): def free(self): pass + def wellHead(self): + well_head = self._get_global_well_head() + well_head.setParent( self ) + return well_head + def wellNumber(self): """ @rtype: int """ return self._well_number( ) diff --git a/ThirdParty/Ert/python/python/ert/well/well_time_line.py b/ThirdParty/Ert/python/python/ecl/well/well_time_line.py similarity index 95% rename from ThirdParty/Ert/python/python/ert/well/well_time_line.py rename to ThirdParty/Ert/python/python/ecl/well/well_time_line.py index 2ea55bf9df..bc42a20e82 100644 --- a/ThirdParty/Ert/python/python/ert/well/well_time_line.py +++ b/ThirdParty/Ert/python/python/ecl/well/well_time_line.py @@ -1,5 +1,5 @@ from cwrap import BaseCClass -from ert.well import WellState, WellPrototype +from ecl.well import WellState, WellPrototype class WellTimeLine(BaseCClass): TYPE_NAME = "well_time_line" diff --git a/ThirdParty/Ert/python/python/ert/well/well_type_enum.py b/ThirdParty/Ert/python/python/ecl/well/well_type_enum.py similarity index 100% rename from ThirdParty/Ert/python/python/ert/well/well_type_enum.py rename to ThirdParty/Ert/python/python/ecl/well/well_type_enum.py diff --git a/ThirdParty/Ert/python/python/ert/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/CMakeLists.txt deleted file mode 100644 index f6ccc6a6b0..0000000000 --- a/ThirdParty/Ert/python/python/ert/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(PYTHON_SOURCES - __init__.py -) -add_python_package("python.ert" ${PYTHON_INSTALL_PREFIX}/ert "${PYTHON_SOURCES}" True) - -add_subdirectory(ecl) -add_subdirectory(geo) -add_subdirectory(test) -add_subdirectory(util) -add_subdirectory(well) - -configure_file(ert_lib_info_build.py.in ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ert/__ert_lib_info.py ) -configure_file(ert_lib_info_install.py.in ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ert_lib_info_install.py ) -install(FILES ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ert_lib_info_install.py DESTINATION ${PYTHON_INSTALL_PREFIX}/ert RENAME __ert_lib_info.py) diff --git a/ThirdParty/Ert/python/python/ert/ecl/rft/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/ecl/rft/CMakeLists.txt deleted file mode 100644 index 9a13752492..0000000000 --- a/ThirdParty/Ert/python/python/ert/ecl/rft/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - well_trajectory.py -) - -add_python_package("python.ert.ecl.rft" ${PYTHON_INSTALL_PREFIX}/ert/ecl/rft "${PYTHON_SOURCES}" True) diff --git a/ThirdParty/Ert/python/python/ert/sched/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/sched/CMakeLists.txt deleted file mode 100644 index 57c42355e3..0000000000 --- a/ThirdParty/Ert/python/python/ert/sched/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - history.py - history_source_enum.py - sched_file.py -) - -add_python_package("python.ert.sched" ${PYTHON_INSTALL_PREFIX}/ert/sched "${PYTHON_SOURCES}" True) - diff --git a/ThirdParty/Ert/python/python/ert/sched/__init__.py b/ThirdParty/Ert/python/python/ert/sched/__init__.py deleted file mode 100644 index 7c48506dc5..0000000000 --- a/ThirdParty/Ert/python/python/ert/sched/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file '__init__.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import ert -import ert.ecl -import ert.util -import ert.geo - -from cwrap import Prototype - -class SchedulePrototype(Prototype): - lib = ert.load("libsched") - - def __init__(self, prototype, bind=True): - super(SchedulePrototype, self).__init__(SchedulePrototype.lib, prototype, bind=bind) - -SCHED_LIB = ert.load("libsched") - -from .sched_file import SchedFile -from .history_source_enum import HistorySourceEnum -from .history import History diff --git a/ThirdParty/Ert/python/python/ert/sched/history.py b/ThirdParty/Ert/python/python/ert/sched/history.py deleted file mode 100644 index dbd66ab6e4..0000000000 --- a/ThirdParty/Ert/python/python/ert/sched/history.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) 2013 Statoil ASA, Norway. -# -# The file 'history.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. - -from cwrap import BaseCClass -from ert.sched import SchedFile, HistorySourceEnum, SchedulePrototype -from ert.ecl import EclSum - -class History(BaseCClass): - TYPE_NAME = "history" - - _alloc_from_refcase = SchedulePrototype("void* history_alloc_from_refcase(ecl_sum, bool)", bind = False) - _alloc_from_sched_file = SchedulePrototype("void* history_alloc_from_sched_file(char*, sched_file)", bind = False) - _get_source_string = SchedulePrototype("char* history_get_source_string(history_source_enum)", bind = False) - _free = SchedulePrototype("void history_free( history )") - # _history_get_source_type = SchedulePrototype("history_source_type_enum history_get_source_type(char*)", bind = False) - - def __init__(self, refcase = None, use_history = False, sched_file = None): - """ - @type refcase: EclSum - @type use_history: bool - @rtype: HistoryType - """ - self._init_from = '' - self._init_val = '' - if sched_file is not None: - self._init_from = 'sched_file' - self._init_val = str(sched_file) - c_ptr = self._alloc_from_sched_file(sched_file, use_history) - else: - self._init_from = 'refcase' - self._init_val = str(refcase) - c_ptr = self._alloc_from_refcase(refcase, use_history) - if c_ptr: - super(History, self).__init__(c_ptr) - else: - if sched_file is None and refcase is None: - raise ArgumentError('Need to specify either sched_file or refcase.') - raise ValueError('Invalid input. Failed to create History.') - - @staticmethod - def get_source_string(history_source_type): - """ - @type history_source_type: HistorySourceEnum - @rtype: str - """ - return self._get_source_string(history_source_type) - - def free(self): - self._free( self ) - - def __repr__(self): - fr = self._init_from - va = self._init_val - ad = self._ad_str() - return 'History(init_from = %s: %s) %s' % (fr,va,ad) diff --git a/ThirdParty/Ert/python/python/ert/sched/history_source_enum.py b/ThirdParty/Ert/python/python/ert/sched/history_source_enum.py deleted file mode 100644 index bc20276aca..0000000000 --- a/ThirdParty/Ert/python/python/ert/sched/history_source_enum.py +++ /dev/null @@ -1,16 +0,0 @@ -from cwrap import BaseCEnum -from ert.sched import SCHED_LIB - - -class HistorySourceEnum(BaseCEnum): - TYPE_NAME = "history_source_enum" - SCHEDULE = None - REFCASE_SIMULATED = None - REFCASE_HISTORY = None - HISTORY_SOURCE_INVALID = None - -HistorySourceEnum.addEnum("SCHEDULE", 0) -HistorySourceEnum.addEnum("REFCASE_SIMULATED", 1) -HistorySourceEnum.addEnum("REFCASE_HISTORY", 2) -HistorySourceEnum.addEnum("HISTORY_SOURCE_INVALID", 10) - diff --git a/ThirdParty/Ert/python/python/ert/sched/sched_file.py b/ThirdParty/Ert/python/python/ert/sched/sched_file.py deleted file mode 100644 index 5948fc2afb..0000000000 --- a/ThirdParty/Ert/python/python/ert/sched/sched_file.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (C) 2012 Statoil ASA, Norway. -# -# The file 'sched_file.py' is part of ERT - Ensemble based Reservoir Tool. -# -# ERT 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. -# -# ERT 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 at -# for more details. -import os.path - -from cwrap import BaseCClass -from ert.sched import SchedulePrototype -from ert.util import CTime - - -class SchedFile(BaseCClass): - TYPE_NAME = "sched_file" - - _parse = SchedulePrototype("void* sched_file_parse_alloc( char*, time_t )", bind = False) - _write = SchedulePrototype("void sched_file_fprintf_i( sched_file , int , char* , bool)") - _length = SchedulePrototype("int sched_file_get_num_restart_files( sched_file )") - _free = SchedulePrototype("void sched_file_free( sched_file )") - - def __init__(self, filename, start_time): - if os.path.isfile(filename): - c_ptr = self._parse(filename, CTime(start_time)) - super(SchedFile, self).__init__(c_ptr) - if not c_ptr: - err_msg = 'start_time = "%s", filename = "%s"' % (str(start_time), str(filename)) - raise ValueError('Unable to construct SchedFile with %s.' % err_msg) - else: - raise IOError('No such file "%s"' % filename) - - @property - def length(self): - """ @rtype: int """ - return len(self) - - def __len__(self): - return self._length() - - def write(self, filename, num_dates, add_end=True): - self._write( num_dates, filename, add_end ) - - def free(self): - self._free( ) - - def __repr__(self): - return 'SchedFile(len = %d) %s' % (len(self), self._ad_str()) diff --git a/ThirdParty/Ert/python/python/ert/test/ecl_mock/CMakeLists.txt b/ThirdParty/Ert/python/python/ert/test/ecl_mock/CMakeLists.txt deleted file mode 100644 index f9c0405c26..0000000000 --- a/ThirdParty/Ert/python/python/ert/test/ecl_mock/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set(PYTHON_SOURCES - __init__.py - ecl_sum_mock.py -) - -# The ecl_mock package is not installed. -add_python_package("python.ert.test.ecl_mock" ${PYTHON_INSTALL_PREFIX}/ert/test/ecl_mock "${PYTHON_SOURCES}" False) diff --git a/ThirdParty/Ert/python/tests/CMakeLists.txt b/ThirdParty/Ert/python/tests/CMakeLists.txt index 5ebbfa3c82..985fe07610 100644 --- a/ThirdParty/Ert/python/tests/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/CMakeLists.txt @@ -1,40 +1,16 @@ set(TEST_SOURCES __init__.py - ctest_import.py - ctest_run.py - import_tester.py - test_pylint.py ) -set(TEST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) -set(INSTALL_DIRECTORY ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}) - add_python_package("python.tests" "${PYTHON_INSTALL_PREFIX}/tests" "${TEST_SOURCES}" False) - -function (addPythonTest TEST_NAME TEST_CLASS) - set(oneValueArgs LABELS) - set(multiValueArgs ARGUMENTS ENVIRONMENT) - cmake_parse_arguments(TEST_OPTIONS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - add_test(NAME python.tests.${TEST_NAME} - WORKING_DIRECTORY ${INSTALL_DIRECTORY} - COMMAND tests/ctest_run.py ${INSTALL_DIRECTORY} ${TEST_CLASS} ${TEST_OPTIONS_ARGUMENTS}) - - if(TEST_OPTIONS_LABELS) - set_property(TEST python.tests.${TEST_NAME} PROPERTY LABELS "Python:${TEST_OPTIONS_LABELS}") - else() - set_property(TEST python.tests.${TEST_NAME} PROPERTY LABELS "Python") - endif() - - if(TEST_OPTIONS_ENVIRONMENT) - set_property(TEST python.tests.${TEST_NAME} PROPERTY ENVIRONMENT ${TEST_OPTIONS_ENVIRONMENT}) - endif() -endfunction(addPythonTest) - +set(CTEST_PYTHONPATH ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}) add_subdirectory(geometry) add_subdirectory(util) add_subdirectory(ecl) add_subdirectory(well) add_subdirectory(cwrap) -addPythonTest(lint test_pylint.LintErt) +add_subdirectory(global) + + + diff --git a/ThirdParty/Ert/python/tests/ctest_import.py b/ThirdParty/Ert/python/tests/ctest_import.py deleted file mode 100644 index c7892a0ec3..0000000000 --- a/ThirdParty/Ert/python/tests/ctest_import.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -PYTHONPATH = sys.argv[1] -sys.path.insert(0, PYTHONPATH) - -from import_tester import ImportTester - -package_name = sys.argv[2] -package_path = os.path.join(PYTHONPATH, package_name) - -if ImportTester.importRecursively(package_path, package_name): - sys.exit(0) -else: - sys.exit(1) diff --git a/ThirdParty/Ert/python/tests/ctest_run.py b/ThirdParty/Ert/python/tests/ctest_run.py deleted file mode 100644 index 1ab2bb37a6..0000000000 --- a/ThirdParty/Ert/python/tests/ctest_run.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -try: - from unittest2 import TextTestRunner -except ImportError: - from unittest import TextTestRunner - - -def runTestCase(tests, verbosity=0): - test_result = TextTestRunner(verbosity=verbosity).run(tests) - - if len(test_result.errors) or len(test_result.failures): - test_result.printErrors() - return False - else: - return True - - -if __name__ == '__main__': - TEST_PYTHONPATH = sys.argv[1] - os.environ["PYTHONPATH"] = TEST_PYTHONPATH + os.pathsep + os.getenv("PYTHONPATH", "") - for path_element in reversed(TEST_PYTHONPATH.split(os.pathsep)): - sys.path.insert(0, path_element) - - test_class_path = sys.argv[2] - argv = [] - - try: - argv = sys.argv[3:] - except IndexError: - pass - - from ert.test import ErtTestRunner - - tests = ErtTestRunner.getTestsFromTestClass(test_class_path, argv) - - # Set verbosity to 2 to see which test method in a class that fails. - if runTestCase(tests, verbosity=0): - sys.exit(0) - else: - sys.exit(1) diff --git a/ThirdParty/Ert/python/tests/cwrap/CMakeLists.txt b/ThirdParty/Ert/python/tests/cwrap/CMakeLists.txt index 5ae758b143..56200ef2d9 100644 --- a/ThirdParty/Ert/python/tests/cwrap/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/cwrap/CMakeLists.txt @@ -9,9 +9,9 @@ set(TEST_SOURCES add_python_package("python.tests.cwrap" ${PYTHON_INSTALL_PREFIX}/tests/cwrap "${TEST_SOURCES}" False) -addPythonTest(cwrap.basecclass tests.cwrap.test_basecclass.BaseCClassTest) -addPythonTest(cwrap.basecenum tests.cwrap.test_basecenum.BaseCEnumTest) -addPythonTest(cwrap.basecvalue tests.cwrap.test_basecvalue.BaseCValueTest) -addPythonTest(cwrap.metacwrap tests.cwrap.test_metawrap.MetaWrapTest) -addPythonTest(cwrap.cfile tests.cwrap.test_cfile.CFILETest) +addPythonTest(tests.cwrap.test_basecclass.BaseCClassTest) +addPythonTest(tests.cwrap.test_basecenum.BaseCEnumTest) +addPythonTest(tests.cwrap.test_basecvalue.BaseCValueTest) +addPythonTest(tests.cwrap.test_metawrap.MetaWrapTest) +addPythonTest(tests.cwrap.test_cfile.CFILETest) diff --git a/ThirdParty/Ert/python/tests/cwrap/test_basecclass.py b/ThirdParty/Ert/python/tests/cwrap/test_basecclass.py index 7670b41b0a..f2925d67b6 100644 --- a/ThirdParty/Ert/python/tests/cwrap/test_basecclass.py +++ b/ThirdParty/Ert/python/tests/cwrap/test_basecclass.py @@ -1,5 +1,5 @@ from cwrap import BaseCClass -from ert.test import ExtendedTestCase +from ecl.test import ExtendedTestCase class BaseCClassTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/cwrap/test_basecenum.py b/ThirdParty/Ert/python/tests/cwrap/test_basecenum.py index 9018be265b..b5f44efa95 100644 --- a/ThirdParty/Ert/python/tests/cwrap/test_basecenum.py +++ b/ThirdParty/Ert/python/tests/cwrap/test_basecenum.py @@ -1,5 +1,5 @@ from cwrap import BaseCEnum -from ert.test import ExtendedTestCase +from ecl.test import ExtendedTestCase diff --git a/ThirdParty/Ert/python/tests/cwrap/test_basecvalue.py b/ThirdParty/Ert/python/tests/cwrap/test_basecvalue.py index f0096c1a9f..6f2bb647d6 100644 --- a/ThirdParty/Ert/python/tests/cwrap/test_basecvalue.py +++ b/ThirdParty/Ert/python/tests/cwrap/test_basecvalue.py @@ -1,10 +1,10 @@ -import ert +import ecl from ctypes import c_ubyte, c_double from cwrap import BaseCValue, Prototype -from ert.test import ExtendedTestCase +from ecl.test import ExtendedTestCase class TestPrototype(Prototype): - lib = ert.load("libert_util") + lib = ecl.load("libert_util") def __init__(self, prototype): super(TestPrototype, self).__init__(self.lib, prototype) diff --git a/ThirdParty/Ert/python/tests/cwrap/test_cfile.py b/ThirdParty/Ert/python/tests/cwrap/test_cfile.py index e790cbb7f1..3fb5093a55 100644 --- a/ThirdParty/Ert/python/tests/cwrap/test_cfile.py +++ b/ThirdParty/Ert/python/tests/cwrap/test_cfile.py @@ -1,12 +1,12 @@ -import ert +import ecl from cwrap import Prototype, CFILE -from ert.test.extended_testcase import ExtendedTestCase -from ert.test.test_area import TestAreaContext +from ecl.test.extended_testcase import ExtendedTestCase +from ecl.test.test_area import TestAreaContext # Local copies so that the real ones don't get changed class TestUtilPrototype(Prototype): - lib = ert.load("libert_util") + lib = ecl.load("libert_util") def __init__(self, prototype, bind=False): super(TestUtilPrototype, self).__init__(TestUtilPrototype.lib, prototype, bind=bind) diff --git a/ThirdParty/Ert/python/tests/cwrap/test_metawrap.py b/ThirdParty/Ert/python/tests/cwrap/test_metawrap.py index afbc5bd5af..2f9c5c2b90 100644 --- a/ThirdParty/Ert/python/tests/cwrap/test_metawrap.py +++ b/ThirdParty/Ert/python/tests/cwrap/test_metawrap.py @@ -2,14 +2,14 @@ from __future__ import absolute_import, division, print_function, unicode_litera from six import string_types import ctypes -import ert +import ecl from cwrap import BaseCClass, Prototype, PrototypeError -from ert.test import ExtendedTestCase +from ecl.test import ExtendedTestCase # Local copies so that the real ones don't get changed class TestUtilPrototype(Prototype): - lib = ert.load("libert_util") + lib = ecl.load("libert_util") def __init__(self, prototype, bind=False): super(TestUtilPrototype, self).__init__(TestUtilPrototype.lib, prototype, bind=bind) diff --git a/ThirdParty/Ert/python/tests/ecl/CMakeLists.txt b/ThirdParty/Ert/python/tests/ecl/CMakeLists.txt index e2cdb6551d..85a308d90e 100644 --- a/ThirdParty/Ert/python/tests/ecl/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/ecl/CMakeLists.txt @@ -39,49 +39,51 @@ set(TEST_SOURCES test_grav.py test_geertsma.py test_ecl_type.py + test_restart_head.py ) add_python_package("python.tests.ecl" ${PYTHON_INSTALL_PREFIX}/tests/ecl "${TEST_SOURCES}" False) -addPythonTest(ecl.ecl_grid ecl.test_grid.GridTest ) -addPythonTest(ecl.ecl_kw ecl.test_ecl_kw.KWTest) -addPythonTest(ecl.ecl_kw_function ecl.test_kw_function.KWFunctionTest) -addPythonTest(ecl.ecl_3dkw ecl.test_ecl_3dkw.Ecl3DKWTest ) -addPythonTest(ecl.ecl_rft ecl.test_rft.RFTTest) -addPythonTest(ecl.ecl_rft_cell ecl.test_rft_cell.RFTCellTest) -addPythonTest(ecl.ecl_sum2 ecl.test_sum.SumTest) -addPythonTest(ecl.layer ecl.test_layer.LayerTest ) -addPythonTest(ecl.faults ecl.test_faults.FaultTest ) -addPythonTest(ecl.fault_blocks ecl.test_fault_blocks.FaultBlockTest ) -addPythonTest(ecl.ecl_deprecation1.9 ecl.test_deprecation.Deprecation_1_9_Test ) -addPythonTest(ecl.ecl_deprecation2.0 ecl.test_deprecation.Deprecation_2_0_Test ) -addPythonTest(ecl.ecl_deprecation2.1 ecl.test_deprecation.Deprecation_2_1_Test ) -addPythonTest(ecl.ecl_removed2.1 ecl.test_removed.Removed_2_1_Test ) -addPythonTest(ecl.ecl_util ecl.test_ecl_util.EclUtilTest ) -addPythonTest(ecl.fortio ecl.test_fortio.FortIOTest) -addPythonTest(ecl.ecl_file ecl.test_ecl_file.EclFileTest) -addPythonTest(ecl.ecl_grav ecl.test_grav.EclGravTest) -addPythonTest(ecl.ecl_geertsma ecl.test_geertsma.GeertsmaTest) -addPythonTest(ecl.ecl_type ecl.test_ecl_type.EclDataTypeTest) -addPythonTest(ecl.ecl_region ecl.test_region.RegionTest) +addPythonTest(tests.ecl.test_grid.GridTest ) +addPythonTest(tests.ecl.test_ecl_kw.KWTest) +addPythonTest(tests.ecl.test_kw_function.KWFunctionTest) +addPythonTest(tests.ecl.test_ecl_3dkw.Ecl3DKWTest ) +addPythonTest(tests.ecl.test_rft.RFTTest) +addPythonTest(tests.ecl.test_rft_cell.RFTCellTest) +addPythonTest(tests.ecl.test_sum.SumTest) +addPythonTest(tests.ecl.test_layer.LayerTest ) +addPythonTest(tests.ecl.test_faults.FaultTest ) +addPythonTest(tests.ecl.test_fault_blocks.FaultBlockTest ) +addPythonTest(tests.ecl.test_deprecation.Deprecation_1_9_Test ) +addPythonTest(tests.ecl.test_deprecation.Deprecation_2_0_Test ) +addPythonTest(tests.ecl.test_deprecation.Deprecation_2_1_Test ) +addPythonTest(tests.ecl.test_removed.Removed_2_1_Test ) +addPythonTest(tests.ecl.test_ecl_util.EclUtilTest ) +addPythonTest(tests.ecl.test_fortio.FortIOTest) +addPythonTest(tests.ecl.test_ecl_file.EclFileTest) +addPythonTest(tests.ecl.test_grav.EclGravTest) +addPythonTest(tests.ecl.test_geertsma.GeertsmaTest) +addPythonTest(tests.ecl.test_ecl_type.EclDataTypeTest) +addPythonTest(tests.ecl.test_region.RegionTest) if (STATOIL_TESTDATA_ROOT) - addPythonTest(ecl.ecl_file_statoil ecl.test_ecl_file_statoil.EclFileStatoilTest LABELS StatoilData) - addPythonTest(ecl.ecl_grdecl ecl.test_grdecl.GRDECLTest LABELS StatoilData) - addPythonTest(ecl.ecl_grid_statoil ecl.test_grid_statoil.GridTest LABELS StatoilData:Slow) - addPythonTest(ecl.ecl_kw_statoil ecl.test_ecl_kw_statoil.KWTest LABELS StatoilData) - addPythonTest(ecl.ecl_init_file ecl.test_ecl_init_file.InitFileTest LABELS StatoilData) - addPythonTest(ecl.ecl_restart_file ecl.test_ecl_restart_file.RestartFileTest LABELS StatoilData) - addPythonTest(ecl.ecl_restart ecl.test_restart.RestartTest LABELS StatoilData ) - addPythonTest(ecl.ecl_region_statoil ecl.test_region_statoil.RegionTest LABELS StatoilData) - addPythonTest(ecl.ecl_rft_statoil ecl.test_rft_statoil.RFTTest LABELS StatoilData) - addPythonTest(ecl.ecl_sum1 ecl.test_sum_statoil.SumTest LABELS StatoilData) - addPythonTest(ecl.ecl_sum_vector ecl.test_ecl_sum_vector.EclSumVectorTest LABELS StatoilData) - addPythonTest(ecl.ecl_sum_time_range ecl.test_ecl_sum.EclSumTest LABELS StatoilData) - addPythonTest(ecl.statoil_faults ecl.test_statoil_faults.StatoilFaultTest LABELS StatoilData) - addPythonTest(ecl.fault_blocks_statoil ecl.test_fault_blocks_statoil.FaultBlockTest LABELS StatoilData) - addPythonTest(ecl.ecl_npv ecl.test_npv.NPVTest LABELS StatoilData) - addPythonTest(ecl.indexed_read ecl.test_indexed_read.EclIndexedReadTest LABELS StatoilData) - addPythonTest(ecl.ecl_cmp ecl.test_ecl_cmp.EclCmpTest LABELS StatoilData) + addPythonTest(tests.ecl.test_ecl_file_statoil.EclFileStatoilTest LABELS StatoilData) + addPythonTest(tests.ecl.test_grdecl.GRDECLTest LABELS StatoilData) + addPythonTest(tests.ecl.test_grid_statoil.GridTest LABELS StatoilData:Slow) + addPythonTest(tests.ecl.test_ecl_kw_statoil.KWTest LABELS StatoilData) + addPythonTest(tests.ecl.test_ecl_init_file.InitFileTest LABELS StatoilData) + addPythonTest(tests.ecl.test_ecl_restart_file.RestartFileTest LABELS StatoilData) + addPythonTest(tests.ecl.test_restart.RestartTest LABELS StatoilData ) + addPythonTest(tests.ecl.test_region_statoil.RegionTest LABELS StatoilData) + addPythonTest(tests.ecl.test_rft_statoil.RFTTest LABELS StatoilData) + addPythonTest(tests.ecl.test_sum_statoil.SumTest LABELS StatoilData) + addPythonTest(tests.ecl.test_ecl_sum_vector.EclSumVectorTest LABELS StatoilData) + addPythonTest(tests.ecl.test_ecl_sum.EclSumTest LABELS StatoilData) + addPythonTest(tests.ecl.test_statoil_faults.StatoilFaultTest LABELS StatoilData) + addPythonTest(tests.ecl.test_fault_blocks_statoil.FaultBlockTest LABELS StatoilData) + addPythonTest(tests.ecl.test_npv.NPVTest LABELS StatoilData) + addPythonTest(tests.ecl.test_indexed_read.EclIndexedReadTest LABELS StatoilData) + addPythonTest(tests.ecl.test_ecl_cmp.EclCmpTest LABELS StatoilData) + addPythonTest(tests.ecl.test_restart_head.RestartHeadTest LABELS StatoilData) endif() diff --git a/ThirdParty/Ert/python/tests/ecl/test_deprecation.py b/ThirdParty/Ert/python/tests/ecl/test_deprecation.py index 87b08dc51a..cd818abc5e 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_deprecation.py +++ b/ThirdParty/Ert/python/tests/ecl/test_deprecation.py @@ -18,11 +18,11 @@ import warnings import time import datetime -from ert.test import ExtendedTestCase, TestAreaContext -from ert.ecl import EclFile, EclGrid, EclKW, EclDataType, EclGrid, EclRegion -from ert.ecl import FortIO, openFortIO, EclRFT, EclGridGenerator -from ert.test.ecl_mock import createEclSum -from ert.util import BoolVector +from ecl.test import ExtendedTestCase, TestAreaContext +from ecl.ecl import EclFile, EclGrid, EclKW, EclDataType, EclGrid, EclRegion +from ecl.ecl import FortIO, openFortIO, EclRFT, EclGridGenerator +from ecl.test.ecl_mock import createEclSum +from ecl.util import BoolVector # The class Deprecation_1_9_Test contains methods which will be marked # as deprecated in the 1.9.x versions. diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_3dkw.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_3dkw.py index 8e586b57db..f6bdabb0c3 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_3dkw.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_3dkw.py @@ -17,9 +17,9 @@ import os import random -from ert.util import IntVector -from ert.ecl import Ecl3DKW , EclKW, EclDataType, EclFile, FortIO, EclFileFlagEnum , EclGrid -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.util import IntVector +from ecl.ecl import Ecl3DKW , EclKW, EclDataType, EclFile, FortIO, EclFileFlagEnum , EclGrid +from ecl.test import ExtendedTestCase , TestAreaContext diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_cmp.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_cmp.py index 0c2782f3d3..807c0b9ab0 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_cmp.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_cmp.py @@ -14,9 +14,9 @@ # See the GNU General Public License at # for more details. -from ert.test import ExtendedTestCase , TestAreaContext -from ert.test.ecl_mock import createEclSum -from ert.ecl import EclCmp +from ecl.test import ExtendedTestCase , TestAreaContext +from ecl.test.ecl_mock import createEclSum +from ecl.ecl import EclCmp class EclCmpTest(ExtendedTestCase): def setUp(self): diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_file.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_file.py index 71bf8bfe1c..66a70196eb 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_file.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_file.py @@ -20,10 +20,10 @@ import gc from unittest import skipIf -from ert.ecl import EclFile, FortIO, EclKW , openFortIO , openEclFile -from ert.ecl import EclFileFlagEnum, EclDataType, EclFileEnum +from ecl.ecl import EclFile, FortIO, EclKW , openFortIO , openEclFile +from ecl.ecl import EclFileFlagEnum, EclDataType, EclFileEnum -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.test import ExtendedTestCase , TestAreaContext def createFile( name , kw_list ): with openFortIO(name , mode = FortIO.WRITE_MODE) as f: diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_file_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_file_statoil.py index 234882e854..5d13e0f913 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_file_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_file_statoil.py @@ -18,10 +18,10 @@ import datetime import os.path from unittest import skipIf -from ert.ecl import EclFile, FortIO, EclKW , openFortIO , openEclFile -from ert.ecl import EclFileFlagEnum, EclFileEnum +from ecl.ecl import EclFile, FortIO, EclKW , openFortIO , openEclFile +from ecl.ecl import EclFileFlagEnum, EclFileEnum -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.test import ExtendedTestCase , TestAreaContext @@ -153,3 +153,106 @@ class EclFileStatoilTest(ExtendedTestCase): v = f.restartView( sim_time = datetime.date( 2004,1,1) ) v = f.restartView( report_step = 30 ) v = f.restartView( seqnum_index = 30 ) + + def test_ix_case(self): + f = EclFile( self.createTestPath( "Statoil/ECLIPSE/ix/summary/Create_Region_Around_Well.SMSPEC")) + + # Keywords + self.assertTrue( "KEYWORDS" in f ) + keywords_loaded = list(f["KEYWORDS"][0]) + keywords_from_file = [ + 'TIME', 'YEARS', 'AAQR', 'AAQT', 'AAQP', 'AAQR', 'AAQT', + 'AAQP', 'AAQR', 'AAQT', 'AAQP', 'FPPW', 'FPPO', 'FPPG', 'FNQT', + 'FNQR', 'FEIP', 'FWPT', 'FWIT', 'FWIP', 'FWGR', 'FVPT', 'FVPR', + 'FVIT', 'FVIR', 'FPR', 'FOPT', 'FOIT', 'FOIR', 'FOIPL', + 'FOIPG', 'FOIP', 'FGPT', 'FGIT', 'FGIPL', 'FGIPG', 'FGIP', + 'FAQT', 'FAQR', 'FGOR', 'FWCT', 'FGSR', 'FGIR', 'FGPR', 'FWIR', + 'FWPR', 'FOPR', 'MEMORYTS', 'NAIMFRAC', 'TCPUDAY', 'TCPUTS', + 'NBAKFL', 'NNUMST', 'NNUMFL', 'NEWTFL', 'MSUMNEWT', 'MSUMLINS', + 'MLINEARS', 'NLINEARS', 'NEWTON', 'ELAPSED', 'TCPU', + 'TIMESTEP', 'GOPR', 'GOPR', 'GOPR', 'GWPR', 'GWPR', 'GWPR', + 'GWIR', 'GWIR', 'GWIR', 'GGPR', 'GGPR', 'GGPR', 'GWCT', 'GWCT', + 'GWCT', 'GGOR', 'GGOR', 'GGOR', 'GGIR', 'GGIR', 'GGIR', 'GGIT', + 'GGIT', 'GGIT', 'GGPT', 'GGPT', 'GGPT', 'GOIR', 'GOIR', 'GOIR', + 'GOIT', 'GOIT', 'GOIT', 'GOPT', 'GOPT', 'GOPT', 'GVIR', 'GVIR', + 'GVIR', 'GVIT', 'GVIT', 'GVIT', 'GVPR', 'GVPR', 'GVPR', 'GVPT', + 'GVPT', 'GVPT', 'GWGR', 'GWGR', 'GWGR', 'GWIT', 'GWIT', 'GWIT', + 'GWPT', 'GWPT', 'GWPT', 'WOPR', 'WOPR', 'WOPR', 'WOPR', 'WOPR', + 'WOPR', 'WWPR', 'WWPR', 'WWPR', 'WWPR', 'WWPR', 'WWPR', 'WWIR', + 'WWIR', 'WWIR', 'WWIR', 'WWIR', 'WWIR', 'WGPR', 'WGPR', 'WGPR', + 'WGPR', 'WGPR', 'WGPR', 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', + 'WWCT', 'WMCTL', 'WMCTL', 'WMCTL', 'WMCTL', 'WMCTL', 'WMCTL', + 'WGOR', 'WGOR', 'WGOR', 'WGOR', 'WGOR', 'WGOR', 'WAPI', 'WAPI', + 'WAPI', 'WAPI', 'WAPI', 'WAPI', 'WBHP', 'WBHP', 'WBHP', 'WBHP', + 'WBHP', 'WBHP', 'WGIR', 'WGIR', 'WGIR', 'WGIR', 'WGIR', 'WGIR', + 'WGIT', 'WGIT', 'WGIT', 'WGIT', 'WGIT', 'WGIT', 'WGPT', 'WGPT', + 'WGPT', 'WGPT', 'WGPT', 'WGPT', 'WOIR', 'WOIR', 'WOIR', 'WOIR', + 'WOIR', 'WOIR', 'WOIT', 'WOIT', 'WOIT', 'WOIT', 'WOIT', 'WOIT', + 'WOPT', 'WOPT', 'WOPT', 'WOPT', 'WOPT', 'WOPT', 'WPIG', 'WPIG', + 'WPIG', 'WPIG', 'WPIG', 'WPIG', 'WPIO', 'WPIO', 'WPIO', 'WPIO', + 'WPIO', 'WPIO', 'WPIW', 'WPIW', 'WPIW', 'WPIW', 'WPIW', 'WPIW', + 'WTHP', 'WTHP', 'WTHP', 'WTHP', 'WTHP', 'WTHP', 'WVIR', 'WVIR', + 'WVIR', 'WVIR', 'WVIR', 'WVIR', 'WVIT', 'WVIT', 'WVIT', 'WVIT', + 'WVIT', 'WVIT', 'WVPR', 'WVPR', 'WVPR', 'WVPR', 'WVPR', 'WVPR', + 'WVPT', 'WVPT', 'WVPT', 'WVPT', 'WVPT', 'WVPT', 'WWGR', 'WWGR', + 'WWGR', 'WWGR', 'WWGR', 'WWGR', 'WWIT', 'WWIT', 'WWIT', 'WWIT', + 'WWIT', 'WWIT', 'WWPT', 'WWPT', 'WWPT', 'WWPT', 'WWPT', 'WWPT', + 'WBHT', 'WBHT', 'WBHT', 'WBHT', 'WBHT', 'WBHT', 'WBP', 'WBP', + 'WBP', 'WBP', 'WBP', 'WBP', 'WWCT', 'WWCT', 'WWCT', 'WWCT', + 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', + 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', + 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT', 'WWCT' + ] + + padd = lambda str_len : (lambda s : s + (" " * (max(0, str_len-len(s))))) + self.assertEqual(map(padd(8), keywords_from_file), keywords_loaded) + + # Names + self.assertTrue( "NAMES" in f ) + names_loaded = list(f["NAMES"][0]) + names_from_file = [ + '', '', 'AQFR_1', 'AQFR_1', 'AQFR_1', 'AQFR_2', 'AQFR_2', + 'AQFR_2', 'AQFR_3', 'AQFR_3', 'AQFR_3', 'FIELD', 'FIELD', + 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', + 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', + 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', + 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', + 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', + 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', + 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', 'FIELD', + 'FIELD', 'ONE', 'TWO', 'FIELD', 'ONE', 'TWO', 'FIELD', 'ONE', + 'TWO', 'FIELD', 'ONE', 'TWO', 'FIELD', 'ONE', 'TWO', 'FIELD', + 'ONE', 'TWO', 'FIELD', 'ONE', 'TWO', 'FIELD', 'ONE', 'TWO', + 'FIELD', 'ONE', 'TWO', 'FIELD', 'ONE', 'TWO', 'FIELD', 'ONE', + 'TWO', 'FIELD', 'ONE', 'TWO', 'FIELD', 'ONE', 'TWO', 'FIELD', + 'ONE', 'TWO', 'FIELD', 'ONE', 'TWO', 'FIELD', 'ONE', 'TWO', + 'FIELD', 'ONE', 'TWO', 'FIELD', 'ONE', 'TWO', 'FIELD', 'ONE', + 'TWO', 'FIELD', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', + 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', + 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', + 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', + 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', + 'I6', 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', + 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', + 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', + 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', + 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', + 'I6', 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', + 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', + 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', + 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', + 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', + 'I6', 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', + 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', + 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', + 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', + 'GI', 'I2', 'I4', 'I6', 'I8', 'HWELL_PROD', 'GI', 'I2', 'I4', + 'I6', 'I8', ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', + ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', + ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', + ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', + ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', + ':+:+:+:+', ':+:+:+:+', ':+:+:+:+', ':+:+:+:+' + ] + + self.assertEqual(map(padd(10), names_from_file), names_loaded) diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_init_file.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_init_file.py index 6ba97937b5..703be6be23 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_init_file.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_init_file.py @@ -15,8 +15,8 @@ # for more details. -from ert.test import ExtendedTestCase -from ert.ecl import Ecl3DKW , EclKW, EclInitFile , EclFile, FortIO, EclFileFlagEnum , EclGrid +from ecl.test import ExtendedTestCase +from ecl.ecl import Ecl3DKW , EclKW, EclInitFile , EclFile, FortIO, EclFileFlagEnum , EclGrid class InitFileTest(ExtendedTestCase): def setUp(self): diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_kw.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_kw.py index 4634bf78e4..5079b06dbe 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_kw.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_kw.py @@ -19,9 +19,9 @@ import random import numpy import warnings -from ert.ecl import EclKW, EclDataType, EclTypeEnum, EclFile, FortIO, EclFileFlagEnum , openFortIO +from ecl.ecl import EclKW, EclDataType, EclTypeEnum, EclFile, FortIO, EclFileFlagEnum , openFortIO -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.test import ExtendedTestCase , TestAreaContext def copy_long(): @@ -88,13 +88,11 @@ class KWTest(ExtendedTestCase): with self.assertRaises(ValueError): EclKW( "ToGodDamnLong" , 100 , EclDataType.ECL_CHAR ) - - def test_sum( self ): - kw_string = EclKW( "STRING" , 100 , EclDataType.ECL_CHAR ) - with self.assertRaises(ValueError): - kw_string.sum() - + for ecl_type in [EclDataType.ECL_CHAR, EclDataType.ECL_STRING(42)]: + kw_string = EclKW("STRING", 100, ecl_type) + with self.assertRaises(ValueError): + kw_string.sum() kw_int = EclKW( "INT" , 4 , EclDataType.ECL_INT ) kw_int[0] = 1 @@ -134,6 +132,9 @@ class KWTest(ExtendedTestCase): self.kw_test(EclDataType.ECL_BOOL, [True, True, True, False, True], "%4d\n") self.kw_test(EclDataType.ECL_CHAR, ["1", "22", "4444", "666666", "88888888"], "%-8s\n") + for str_len in range(1000): + self.kw_test(EclDataType.ECL_STRING(str_len), [str(i)*str_len for i in range(10)], "%s\n") + def test_kw_write(self): with TestAreaContext("python/ecl_kw/writing"): @@ -217,13 +218,14 @@ class KWTest(ExtendedTestCase): def test_abs(self): - kw = EclKW("NAME" , 10 , EclDataType.ECL_CHAR) - with self.assertRaises(TypeError): - abs_kw = abs(kw) - - kw = EclKW("NAME" , 10 , EclDataType.ECL_BOOL) - with self.assertRaises(TypeError): - abs_kw = abs(kw) + for ecl_type in [ + EclDataType.ECL_CHAR, + EclDataType.ECL_BOOL, + EclDataType.ECL_STRING(32) + ]: + kw = EclKW("NAME" , 10 , ecl_type) + with self.assertRaises(TypeError): + abs_kw = abs(kw) kw = EclKW("NAME" , 10 , EclDataType.ECL_INT) for i in range(len(kw)): @@ -362,14 +364,13 @@ class KWTest(ExtendedTestCase): self.assertTrue( view[ 0 ] == kw1[ 0 ] ) self.assertTrue( copy[ 0 ] == kw1[ 0 ] - 1) - - kw2 = EclKW("CHAR", 10, EclDataType.ECL_CHAR ) - with self.assertRaises(ValueError): - kw2.numpyView( ) - - kw3 = EclKW("BOOL", 10, EclDataType.ECL_BOOL ) - with self.assertRaises(ValueError): - kw3.numpyView( ) + for ecl_type in [ + EclDataType.ECL_CHAR, + EclDataType.ECL_BOOL, + EclDataType.ECL_STRING(19)]: + kw2 = EclKW("TEST_KW", 10, ecl_type) + with self.assertRaises(ValueError): + kw2.numpyView() def test_slice(self): N = 100 @@ -409,3 +410,47 @@ class KWTest(ExtendedTestCase): kw = EclKW("KW" , 100 , EclDataType.ECL_INT) self.assertEqual( kw.typeName( ) , "INTE") + + def test_string_alloc(self): + kw = EclKW("KW" , 10, EclDataType.ECL_STRING(30)) + + for i in range(10): + kw[i] = str(i)*30 + + for i in range(10): + self.assertEqual(str(i)*30, kw[i]) + + def test_string_write_read_unformatted(self): + for str_len in range(1000): + with TestAreaContext("my_space"): + + kw = EclKW("TEST_KW" , 10, EclDataType.ECL_STRING(str_len)) + for i in range(10): + kw[i] = str(i)*str_len + + file_name = "ecl_kw_test" + + with openFortIO(file_name, mode=FortIO.WRITE_MODE) as fortio: + kw.fwrite(fortio) + + with openFortIO(file_name) as fortio: + loaded_kw = EclKW.fread(fortio) + + self.assertEqual(kw, loaded_kw) + + def test_string_write_read_formatted(self): + for str_len in range(1000): + with TestAreaContext("my_space"): + + kw = EclKW("TEST_KW" , 10, EclDataType.ECL_STRING(str_len)) + for i in range(10): + kw[i] = str(i)*str_len + + file_name = "ecl_kw_test" + with openFortIO(file_name, mode=FortIO.WRITE_MODE, fmt_file=True) as fortio: + kw.fwrite(fortio) + + with openFortIO(file_name, fmt_file=True) as fortio: + loaded_kw = EclKW.fread(fortio) + + self.assertEqual(kw, loaded_kw) diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_kw_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_kw_statoil.py index a96827fbf7..21d6b63c40 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_kw_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_kw_statoil.py @@ -16,9 +16,9 @@ # for more details. import os import random -from ert.ecl import EclKW, EclDataType, EclFile, FortIO, EclFileFlagEnum +from ecl.ecl import EclKW, EclDataType, EclFile, FortIO, EclFileFlagEnum -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.test import ExtendedTestCase , TestAreaContext def copy_long(): diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_restart_file.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_restart_file.py index a46681b383..e2779e6d5e 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_restart_file.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_restart_file.py @@ -15,8 +15,8 @@ # for more details. import datetime -from ert.test import ExtendedTestCase -from ert.ecl import Ecl3DKW , EclKW, EclRestartFile , EclFile, FortIO, EclFileFlagEnum , EclGrid +from ecl.test import ExtendedTestCase +from ecl.ecl import Ecl3DKW , EclKW, EclRestartFile , EclFile, FortIO, EclFileFlagEnum , EclGrid class RestartFileTest(ExtendedTestCase): def setUp(self): diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_sum.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_sum.py index 8e9baf2c76..7e81dd49dc 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_sum.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_sum.py @@ -17,8 +17,8 @@ import datetime import os.path from cwrap import CFILE -from ert.ecl import EclSum, EclSumKeyWordVector, EclFile,FortIO, openFortIO,openEclFile,EclKW -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.ecl import EclSum, EclSumKeyWordVector, EclFile,FortIO, openFortIO,openEclFile,EclKW +from ecl.test import ExtendedTestCase , TestAreaContext class EclSumTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_sum_tstep.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_sum_tstep.py index ddcdcaa609..8a15241a09 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_sum_tstep.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_sum_tstep.py @@ -1,7 +1,7 @@ from datetime import datetime import random -from ert.ecl import EclSumTStep, EclSum -from ert.test import ExtendedTestCase +from ecl.ecl import EclSumTStep, EclSum +from ecl.test import ExtendedTestCase class EclSumTStepTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_sum_vector.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_sum_vector.py index aa9612e4e9..09bc438ea8 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_sum_vector.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_sum_vector.py @@ -22,8 +22,8 @@ except ImportError: import warnings -from ert.ecl import EclSumVector, EclSum -from ert.test import ExtendedTestCase +from ecl.ecl import EclSumVector, EclSum +from ecl.test import ExtendedTestCase class EclSumVectorTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_type.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_type.py index c700801874..48da066718 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_type.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_type.py @@ -1,6 +1,9 @@ -from ert.test import TestAreaContext, ExtendedTestCase +from ecl.test import TestAreaContext, ExtendedTestCase -from ert.ecl import EclDataType, EclTypeEnum +from ecl.ecl import EclDataType, EclTypeEnum + +def get_const_size_types(): + return EclTypeEnum.enums()[:-1:] class EclDataTypeTest(ExtendedTestCase): @@ -8,9 +11,9 @@ class EclDataTypeTest(ExtendedTestCase): # EclTypeEnum! # [char, float, double, int, bool, mess] - ELEMENT_SIZE = [9, 4, 8, 4, 4, 0] + CONST_SIZES = [8, 4, 8, 4, 4, 0] - VERIFIERS = [ + CONST_VERIFIERS = [ EclDataType.is_char, EclDataType.is_float, EclDataType.is_double, @@ -19,34 +22,60 @@ class EclDataTypeTest(ExtendedTestCase): EclDataType.is_mess ] - TYPE_NAMES = ["CHAR", "REAL", "DOUB", "INTE", "LOGI", "MESS"] + CONST_NAMES = ["CHAR", "REAL", "DOUB", "INTE", "LOGI", "MESS"] + + STRING_NAMES = ["C000", "C010", "C020", "C042", "C999"] + + STRING_SIZES = [0, 10, 20, 42, 999] + + TYPES = (get_const_size_types() + + len(STRING_SIZES) * [EclTypeEnum.ECL_STRING_TYPE]) + + SIZES = CONST_SIZES + STRING_SIZES + + NAMES = CONST_NAMES + STRING_NAMES + def test_alloc_from_type(self): - for (ecl_type, element_size) in zip(EclTypeEnum.enums(), self.ELEMENT_SIZE): + types, sizes = get_const_size_types(), self.CONST_SIZES + for (ecl_type, element_size) in zip(types, sizes): data_type = EclDataType(ecl_type) self.assertEqual(ecl_type, data_type.type) self.assertEqual(element_size, data_type.element_size) + def test_invalid_string_alloc(self): + with self.assertRaises(ValueError): + data_type = EclDataType(EclTypeEnum.ECL_STRING_TYPE) + + with self.assertRaises(ValueError): + data_type = EclDataType(EclTypeEnum.ECL_STRING_TYPE, -1) + + with self.assertRaises(ValueError): + data_type = EclDataType(EclTypeEnum.ECL_STRING_TYPE, 1000) + def test_alloc(self): - for (ecl_type, element_size) in zip(EclTypeEnum.enums(), self.ELEMENT_SIZE): + for (ecl_type, element_size) in zip(self.TYPES, self.SIZES): data_type = EclDataType(ecl_type, element_size) self.assertEqual(ecl_type, data_type.type) self.assertEqual(element_size, data_type.element_size) - + def test_type_verifiers(self): - for (ecl_type, verifier) in zip(EclTypeEnum.enums(), self.VERIFIERS): - ecl_type = EclDataType(ecl_type) - self.assertTrue(verifier(ecl_type)) + test_base = zip(self.TYPES, self.SIZES, self.CONST_VERIFIERS) + for (ecl_type, elem_size, verifier) in test_base: + data_type = EclDataType(ecl_type, elem_size) + self.assertTrue(verifier(data_type)) def test_get_type_name(self): - for (ecl_type, type_name) in zip(EclTypeEnum.enums(), self.TYPE_NAMES): - self.assertEqual(type_name, EclDataType(ecl_type).type_name) + test_base = zip(self.TYPES, self.SIZES, self.NAMES) + for (ecl_type, elem_size, type_name) in test_base: + data_type = EclDataType(ecl_type, elem_size) + self.assertEqual(type_name, data_type.type_name) def test_initialization_validation(self): invalid_args = [ - (None, 0, self.TYPE_NAMES[0]), - (1, None, self.TYPE_NAMES[0]), - (1, 0, self.TYPE_NAMES[0]), + (None, 0, self.CONST_NAMES[0]), + (1, None, self.CONST_NAMES[0]), + (1, 0, self.CONST_NAMES[0]), (None, None, None), (None, 12, None) ] @@ -56,8 +85,12 @@ class EclDataTypeTest(ExtendedTestCase): EclDataType(inv_arg[0], inv_arg[1], inv_arg[2]) def test_create_from_type_name(self): - for (ecl_type, type_name) in zip(EclTypeEnum.enums(), self.TYPE_NAMES): - self.assertEqual(ecl_type, EclDataType.create_from_type_name(type_name).type) + test_base = zip(self.TYPES, self.SIZES, self.NAMES) + for (ecl_type, elem_size, type_name) in test_base: + data_type = EclDataType.create_from_type_name(type_name) + self.assertEqual(ecl_type, data_type.type) + self.assertEqual(elem_size, data_type.element_size) + self.assertEqual(type_name, data_type.type_name) def test_is_numeric(self): numeric_types = [ @@ -69,25 +102,38 @@ class EclDataTypeTest(ExtendedTestCase): for ecl_type in numeric_types: self.assertTrue(EclDataType(ecl_type).is_numeric()) - for ecl_type in set(EclTypeEnum.enums())-set(numeric_types): + for ecl_type in set(get_const_size_types())-set(numeric_types): self.assertFalse(EclDataType(ecl_type).is_numeric()) - def test_equals(self): - for ecl_type in EclTypeEnum.enums(): - self.assertTrue( EclDataType(ecl_type).is_equal(EclDataType(ecl_type)) ) - self.assertEqual( EclDataType(ecl_type), EclDataType(ecl_type) ) + for elem_size in self.STRING_SIZES: + data_type = EclDataType(EclTypeEnum.ECL_STRING_TYPE, elem_size) + self.assertFalse(data_type.is_numeric()) - for other in set(EclTypeEnum.enums())-set([ecl_type]): - self.assertFalse( EclDataType(ecl_type).is_equal(EclDataType(other)) ) - self.assertNotEqual( EclDataType(ecl_type), EclDataType(other) ) + def test_equals(self): + test_base = zip(self.TYPES, self.SIZES) + for ecl_type, elem_size in test_base: + a = EclDataType(ecl_type, elem_size) + b = EclDataType(ecl_type, elem_size) + + self.assertTrue(a.is_equal(b)) + self.assertEqual(a, b) + + for otype, osize in set(test_base)-set([(ecl_type, elem_size)]): + self.assertFalse(a.is_equal(EclDataType(otype, osize))) + self.assertNotEqual(a, EclDataType(otype, osize)) def test_hash(self): all_types = set() + test_base = zip(self.TYPES, self.SIZES) - for index, ecl_type in enumerate(EclTypeEnum.enums()): - all_types.add(EclDataType(ecl_type)) + for index, (ecl_type, elem_size) in enumerate(test_base): + all_types.add(EclDataType(ecl_type, elem_size)) self.assertEqual(index+1, len(all_types)) - for index, ecl_type in enumerate(EclTypeEnum.enums()): + for index, (ecl_type, elem_size) in enumerate(test_base): + all_types.add(EclDataType(ecl_type, elem_size)) + + for index, ecl_type in enumerate(get_const_size_types()): all_types.add(EclDataType(ecl_type)) - self.assertEqual(len(EclTypeEnum.enums()), len(all_types)) + + self.assertEqual(len(test_base), len(all_types)) diff --git a/ThirdParty/Ert/python/tests/ecl/test_ecl_util.py b/ThirdParty/Ert/python/tests/ecl/test_ecl_util.py index 539e7f79b3..0704b17cf1 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_ecl_util.py +++ b/ThirdParty/Ert/python/tests/ecl/test_ecl_util.py @@ -14,8 +14,8 @@ # See the GNU General Public License at # for more details. -from ert.ecl import EclGrid , EclUtil, EclTypeEnum , EclFileEnum, EclPhaseEnum, EclUnitTypeEnum -from ert.test import ExtendedTestCase +from ecl.ecl import EclGrid , EclUtil, EclTypeEnum , EclFileEnum, EclPhaseEnum, EclUnitTypeEnum +from ecl.test import ExtendedTestCase class EclUtilTest(ExtendedTestCase): @@ -26,25 +26,8 @@ class EclUtilTest(ExtendedTestCase): self.assertEnumIsFullyDefined(EclPhaseEnum, "ecl_phase_enum", source_file_path) self.assertEnumIsFullyDefined(EclUnitTypeEnum, "ert_ecl_unit_enum", source_file_path) - # The ecl_type_enum has an extra type ECL_C010_TYPE defined in - # C, the implementation/behavior of that type is based on - # guessing and might very well be wrong, it is therefor not - # exposed in Python. For this reason we have commented out the - # default enum test, and instead test the element manually. - # - # self.assertEnumIsFullyDefined(EclTypeEnum, "ecl_type_enum", source_file_path) - - enum_elements = [ EclTypeEnum.ECL_CHAR_TYPE, - EclTypeEnum.ECL_FLOAT_TYPE, - EclTypeEnum.ECL_DOUBLE_TYPE, - EclTypeEnum.ECL_INT_TYPE, - EclTypeEnum.ECL_BOOL_TYPE, - EclTypeEnum.ECL_MESS_TYPE ] - - for (value , enum_elm) in zip( [0,1,2,3,4,5] , enum_elements): - self.assertEqual( value , enum_elm.value ) - - + source_file_path = "libecl/include/ert/ecl/ecl_type.h" + self.assertEnumIsFullyDefined(EclTypeEnum, "ecl_type_enum", source_file_path) def test_file_type(self): file_type , fmt , report = EclUtil.inspectExtension("CASE.X0078") diff --git a/ThirdParty/Ert/python/tests/ecl/test_fault_blocks.py b/ThirdParty/Ert/python/tests/ecl/test_fault_blocks.py index 1f46ca524f..9275c9a5dc 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_fault_blocks.py +++ b/ThirdParty/Ert/python/tests/ecl/test_fault_blocks.py @@ -18,10 +18,10 @@ from __future__ import print_function from unittest import skipIf import warnings -from ert.ecl import EclGrid, EclKW , EclRegion, EclDataType -from ert.ecl.faults import FaultBlock, FaultBlockLayer, FaultBlockCell,FaultCollection -from ert.geo import Polyline , CPolylineCollection -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.ecl import EclGrid, EclKW , EclRegion, EclDataType +from ecl.ecl.faults import FaultBlock, FaultBlockLayer, FaultBlockCell,FaultCollection +from ecl.geo import Polyline , CPolylineCollection +from ecl.test import ExtendedTestCase , TestAreaContext class FaultBlockTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_fault_blocks_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_fault_blocks_statoil.py index 9c7d88f7f8..8be7f2fc0a 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_fault_blocks_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_fault_blocks_statoil.py @@ -19,9 +19,9 @@ try: except ImportError: from unittest import skipIf -from ert.ecl import EclGrid, EclDataType , EclKW -from ert.test import ExtendedTestCase -from ert.ecl.faults import FaultBlock, FaultBlockLayer +from ecl.ecl import EclGrid, EclDataType , EclKW +from ecl.test import ExtendedTestCase +from ecl.ecl.faults import FaultBlock, FaultBlockLayer class FaultBlockTest(ExtendedTestCase): def setUp(self): diff --git a/ThirdParty/Ert/python/tests/ecl/test_faults.py b/ThirdParty/Ert/python/tests/ecl/test_faults.py index 0a2f1873a7..aa73ceae9f 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_faults.py +++ b/ThirdParty/Ert/python/tests/ecl/test_faults.py @@ -17,12 +17,12 @@ from unittest import skipIf import time -from ert import util +from ecl import util -from ert.ecl.faults import FaultCollection, Fault, FaultLine, FaultSegment,FaultBlockLayer -from ert.ecl import EclGrid, EclKW, EclDataType -from ert.test import ExtendedTestCase, TestAreaContext -from ert.geo import Polyline , CPolyline +from ecl.ecl.faults import FaultCollection, Fault, FaultLine, FaultSegment,FaultBlockLayer +from ecl.ecl import EclGrid, EclKW, EclDataType +from ecl.test import ExtendedTestCase, TestAreaContext +from ecl.geo import Polyline , CPolyline class FaultTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_fortio.py b/ThirdParty/Ert/python/tests/ecl/test_fortio.py index 9ef02be191..01e51ff3d3 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_fortio.py +++ b/ThirdParty/Ert/python/tests/ecl/test_fortio.py @@ -16,8 +16,8 @@ # for more details. import os from random import randint -from ert.ecl import FortIO, EclDataType, EclKW , openFortIO, EclFile -from ert.test import ExtendedTestCase, TestAreaContext +from ecl.ecl import FortIO, EclDataType, EclKW , openFortIO, EclFile +from ecl.test import ExtendedTestCase, TestAreaContext diff --git a/ThirdParty/Ert/python/tests/ecl/test_geertsma.py b/ThirdParty/Ert/python/tests/ecl/test_geertsma.py index 1b85f97e9a..5ff2850716 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_geertsma.py +++ b/ThirdParty/Ert/python/tests/ecl/test_geertsma.py @@ -1,7 +1,7 @@ import datetime -from ert.ecl import EclGrid, EclKW, EclDataType, openFortIO, FortIO, EclFile, EclSubsidence +from ecl.ecl import EclGrid, EclKW, EclDataType, openFortIO, FortIO, EclFile, EclSubsidence -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.test import ExtendedTestCase , TestAreaContext import numpy as np diff --git a/ThirdParty/Ert/python/tests/ecl/test_grav.py b/ThirdParty/Ert/python/tests/ecl/test_grav.py index 8cc10d13fa..3772db8448 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_grav.py +++ b/ThirdParty/Ert/python/tests/ecl/test_grav.py @@ -1,6 +1,6 @@ import time -from ert.ecl import EclGrav, EclKW, EclGrid, EclFile, EclDataType, openFortIO, FortIO -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.ecl import EclGrav, EclKW, EclGrid, EclFile, EclDataType, openFortIO, FortIO +from ecl.test import ExtendedTestCase , TestAreaContext class EclGravTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_grdecl.py b/ThirdParty/Ert/python/tests/ecl/test_grdecl.py index 3ff4f63b01..7c6b1b05c6 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_grdecl.py +++ b/ThirdParty/Ert/python/tests/ecl/test_grdecl.py @@ -16,8 +16,8 @@ # for more details. import os -from ert.ecl import EclKW,EclGrid,Ecl3DKW -from ert.test import ExtendedTestCase +from ecl.ecl import EclKW,EclGrid,Ecl3DKW +from ecl.test import ExtendedTestCase diff --git a/ThirdParty/Ert/python/tests/ecl/test_grid.py b/ThirdParty/Ert/python/tests/ecl/test_grid.py index e7ce0ebdb9..08dded9868 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_grid.py +++ b/ThirdParty/Ert/python/tests/ecl/test_grid.py @@ -20,11 +20,11 @@ import time import itertools from numpy import linspace -from ert.util import IntVector -from ert.ecl import EclGrid, EclKW, EclDataType, EclUnitTypeEnum, EclFile -from ert.ecl import EclGridGenerator as GridGen -from ert.ecl.faults import Layer , FaultCollection -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.util import IntVector +from ecl.ecl import EclGrid, EclKW, EclDataType, EclUnitTypeEnum, EclFile +from ecl.ecl import EclGridGenerator as GridGen +from ecl.ecl.faults import Layer , FaultCollection +from ecl.test import ExtendedTestCase , TestAreaContext # This dict is used to verify that corners are mapped to the correct # cell with respect to containment. diff --git a/ThirdParty/Ert/python/tests/ecl/test_grid_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_grid_statoil.py index 920cdaa95b..db64e14680 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_grid_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_grid_statoil.py @@ -22,9 +22,9 @@ except ImportError: from unittest import skipIf import time -from ert.ecl import EclDataType, EclKW, EclGrid, EclFile, openEclFile -from ert.util import DoubleVector, IntVector -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.ecl import EclDataType, EclKW, EclGrid, EclFile, openEclFile +from ecl.util import DoubleVector, IntVector +from ecl.test import ExtendedTestCase , TestAreaContext class GridTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_indexed_read.py b/ThirdParty/Ert/python/tests/ecl/test_indexed_read.py index 0e26f31df4..8de919409a 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_indexed_read.py +++ b/ThirdParty/Ert/python/tests/ecl/test_indexed_read.py @@ -1,10 +1,10 @@ import ctypes -import ert +import ecl -from ert.ecl import EclPrototype -from ert.ecl import EclKW, EclFile, EclDataType, FortIO -from ert.test import ExtendedTestCase, TestAreaContext -from ert.util import IntVector +from ecl.ecl import EclPrototype +from ecl.ecl import EclKW, EclFile, EclDataType, FortIO +from ecl.test import ExtendedTestCase, TestAreaContext +from ecl.util import IntVector class EclIndexedReadTest(ExtendedTestCase): _freadIndexedData = EclPrototype("void ecl_kw_fread_indexed_data_python(fortio, int, ecl_data_type, int, int_vector, char*)", bind = False) # fortio, offset, type, count, index_map, buffer diff --git a/ThirdParty/Ert/python/tests/ecl/test_kw_function.py b/ThirdParty/Ert/python/tests/ecl/test_kw_function.py index a492f4b096..4f45f2f313 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_kw_function.py +++ b/ThirdParty/Ert/python/tests/ecl/test_kw_function.py @@ -16,9 +16,9 @@ # for more details. import os import random -from ert.ecl import EclKW, EclDataType, EclGrid , Ecl3DKW -from ert.util import IntVector -from ert.test import ExtendedTestCase +from ecl.ecl import EclKW, EclDataType, EclGrid , Ecl3DKW +from ecl.util import IntVector +from ecl.test import ExtendedTestCase class KWFunctionTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_layer.py b/ThirdParty/Ert/python/tests/ecl/test_layer.py index 2791b0179f..370eb6ae8e 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_layer.py +++ b/ThirdParty/Ert/python/tests/ecl/test_layer.py @@ -18,11 +18,11 @@ from unittest import skipIf import time -from ert.util import IntVector -from ert.ecl import EclGrid -from ert.geo import CPolyline -from ert.ecl.faults import Layer , FaultCollection -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.util import IntVector +from ecl.ecl import EclGrid +from ecl.geo import CPolyline +from ecl.ecl.faults import Layer , FaultCollection +from ecl.test import ExtendedTestCase , TestAreaContext class LayerTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_npv.py b/ThirdParty/Ert/python/tests/ecl/test_npv.py index ac31d398ef..dceda077c1 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_npv.py +++ b/ThirdParty/Ert/python/tests/ecl/test_npv.py @@ -24,11 +24,11 @@ try: except ImportError: from unittest import skipIf, skipUnless, skipIf -from ert.ecl import EclSum -from ert.ecl import EclNPV , NPVPriceVector +from ecl.ecl import EclSum +from ecl.ecl import EclNPV , NPVPriceVector -from ert.util import StringList, TimeVector, DoubleVector , CTime -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.util import StringList, TimeVector, DoubleVector , CTime +from ecl.test import ExtendedTestCase , TestAreaContext base = "ECLIPSE" diff --git a/ThirdParty/Ert/python/tests/ecl/test_region.py b/ThirdParty/Ert/python/tests/ecl/test_region.py index 921ef1457a..5e3cef90d8 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_region.py +++ b/ThirdParty/Ert/python/tests/ecl/test_region.py @@ -14,9 +14,9 @@ # # See the GNU General Public License at # for more details. -from ert.ecl import EclGrid, EclKW, EclRegion, EclDataType -from ert.ecl.faults import Layer -from ert.test import ExtendedTestCase +from ecl.ecl import EclGrid, EclKW, EclRegion, EclDataType +from ecl.ecl.faults import Layer +from ecl.test import ExtendedTestCase class RegionTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_region_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_region_statoil.py index 46ebe821a7..fbe0c8035c 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_region_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_region_statoil.py @@ -14,9 +14,9 @@ # # See the GNU General Public License at # for more details. -from ert.ecl import EclFile, EclGrid, EclRegion -from ert.ecl.faults import Layer -from ert.test import ExtendedTestCase +from ecl.ecl import EclFile, EclGrid, EclRegion +from ecl.ecl.faults import Layer +from ecl.test import ExtendedTestCase class RegionTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_removed.py b/ThirdParty/Ert/python/tests/ecl/test_removed.py index 3596802101..fd41e1e434 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_removed.py +++ b/ThirdParty/Ert/python/tests/ecl/test_removed.py @@ -1,8 +1,8 @@ import time import datetime -from ert.test import ExtendedTestCase, TestAreaContext -from ert.ecl import EclFile,EclKW,EclDataType,openFortIO, FortIO +from ecl.test import ExtendedTestCase, TestAreaContext +from ecl.ecl import EclFile,EclKW,EclDataType,openFortIO, FortIO diff --git a/ThirdParty/Ert/python/tests/ecl/test_restart.py b/ThirdParty/Ert/python/tests/ecl/test_restart.py index 7ce8773361..c9e91be399 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_restart.py +++ b/ThirdParty/Ert/python/tests/ecl/test_restart.py @@ -17,8 +17,8 @@ from _ctypes import ArgumentError import os import datetime -from ert.ecl import EclFile -from ert.test import ExtendedTestCase +from ecl.ecl import EclFile +from ecl.test import ExtendedTestCase diff --git a/ThirdParty/Ert/python/tests/ecl/test_restart_head.py b/ThirdParty/Ert/python/tests/ecl/test_restart_head.py new file mode 100644 index 0000000000..bd1468a73e --- /dev/null +++ b/ThirdParty/Ert/python/tests/ecl/test_restart_head.py @@ -0,0 +1,41 @@ +# Copyright (C) 2015 Statoil ASA, Norway. +# +# The file 'test_ecl_init_file.py' is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. +import datetime + +from ecl.test import ExtendedTestCase +from ecl.ecl import Ecl3DKW , EclKW, EclRestartFile , EclFile, FortIO, EclFileFlagEnum , EclGrid + +class RestartHeadTest(ExtendedTestCase): + def setUp(self): + self.grid_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID") + self.unrst_file = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.UNRST") + self.xrst_file0 = self.createTestPath("Statoil/ECLIPSE/Gurbat/ECLIPSE.X0000") + + def test_headers(self): + g = EclGrid( self.grid_file ) + f = EclRestartFile( g , self.unrst_file ) + + headers = f.headers( ) + self.assertEqual( len(headers) , 63 ) + + with self.assertRaises(IndexError): + f.get_header(1000) + + header = f.get_header( 10 ) + details = header.well_details( ) + self.assertTrue( "NXCONZ" in details ) + self.assertTrue( "NCWMAX" in details ) + diff --git a/ThirdParty/Ert/python/tests/ecl/test_rft.py b/ThirdParty/Ert/python/tests/ecl/test_rft.py index 109b5296ee..3ff440b42c 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_rft.py +++ b/ThirdParty/Ert/python/tests/ecl/test_rft.py @@ -17,11 +17,11 @@ import datetime -from ert.util import CTime -from ert.ecl import EclRFTFile, EclRFTCell, EclPLTCell -from ert.ecl.rft import WellTrajectory -from ert.test import ExtendedTestCase -from ert.ecl import EclRFT +from ecl.util import CTime +from ecl.ecl import EclRFTFile, EclRFTCell, EclPLTCell +from ecl.ecl.rft import WellTrajectory +from ecl.test import ExtendedTestCase +from ecl.ecl import EclRFT class RFTTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_rft_cell.py b/ThirdParty/Ert/python/tests/ecl/test_rft_cell.py index ea134d4a3f..87276f6ad3 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_rft_cell.py +++ b/ThirdParty/Ert/python/tests/ecl/test_rft_cell.py @@ -16,8 +16,8 @@ # for more details. -from ert.ecl import EclRFTCell, EclPLTCell -from ert.test import ExtendedTestCase +from ecl.ecl import EclRFTCell, EclPLTCell +from ecl.test import ExtendedTestCase # def out_of_range(): diff --git a/ThirdParty/Ert/python/tests/ecl/test_rft_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_rft_statoil.py index e1e9b07bfb..be3329e230 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_rft_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_rft_statoil.py @@ -17,9 +17,9 @@ from __future__ import print_function import datetime -from ert.ecl import EclRFTFile, EclRFTCell, EclPLTCell -from ert.ecl.rft import WellTrajectory -from ert.test import ExtendedTestCase +from ecl.ecl import EclRFTFile, EclRFTCell, EclPLTCell +from ecl.ecl.rft import WellTrajectory +from ecl.test import ExtendedTestCase class RFTTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/ecl/test_statoil_faults.py b/ThirdParty/Ert/python/tests/ecl/test_statoil_faults.py index 0804a9e41a..2d362b8713 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_statoil_faults.py +++ b/ThirdParty/Ert/python/tests/ecl/test_statoil_faults.py @@ -20,9 +20,9 @@ except ImportError: from unittest import skipIf import time -from ert.ecl.faults import FaultCollection, Fault, FaultLine, FaultSegment -from ert.ecl import EclGrid, EclKW, EclDataType -from ert.test import ExtendedTestCase +from ecl.ecl.faults import FaultCollection, Fault, FaultLine, FaultSegment +from ecl.ecl import EclGrid, EclKW, EclDataType +from ecl.test import ExtendedTestCase diff --git a/ThirdParty/Ert/python/tests/ecl/test_sum.py b/ThirdParty/Ert/python/tests/ecl/test_sum.py index c7965a9ea3..c41d1da0a9 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_sum.py +++ b/ThirdParty/Ert/python/tests/ecl/test_sum.py @@ -20,9 +20,9 @@ import datetime import csv from unittest import skipIf, skipUnless, skipIf -from ert.ecl import EclSum, EclSumVarType -from ert.test import ExtendedTestCase, TestAreaContext -from ert.test.ecl_mock import createEclSum +from ecl.ecl import EclSum, EclSumVarType +from ecl.test import ExtendedTestCase, TestAreaContext +from ecl.test.ecl_mock import createEclSum def fopr(days): return days diff --git a/ThirdParty/Ert/python/tests/ecl/test_sum_statoil.py b/ThirdParty/Ert/python/tests/ecl/test_sum_statoil.py index b31b83b7e7..650aff9987 100644 --- a/ThirdParty/Ert/python/tests/ecl/test_sum_statoil.py +++ b/ThirdParty/Ert/python/tests/ecl/test_sum_statoil.py @@ -20,11 +20,11 @@ import datetime from unittest import skipIf, skipUnless, skipIf -from ert.ecl import EclSum, EclFile +from ecl.ecl import EclSum, EclFile -from ert.util import StringList, TimeVector, DoubleVector +from ecl.util import StringList, TimeVector, DoubleVector -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.test import ExtendedTestCase , TestAreaContext import csv base = "ECLIPSE" @@ -450,13 +450,55 @@ class SumTest(ExtendedTestCase): self.assertEqual( total.iget( "WGPR:NOT_21_D", 5) , 0) # Default value + def test_write(self): + with TestAreaContext("my_space") as area: + intersect_summary = EclSum( self.createTestPath( "Statoil/ECLIPSE/SummaryRestart/iter-1/NOR-2013A_R007-0") ) + self.assertIsNotNone(intersect_summary) + + write_location = os.path.join(os.getcwd(), "CASE") + intersect_summary.fwrite(ecl_case=write_location) + + reloaded_summary = EclSum(write_location) + self.assertEqual(intersect_summary.keys(), reloaded_summary.keys()) def test_ix_case(self): - # This should ideally load OK; the current assertRaises() test - # is just to ensure that it does not go *completely* up in flames. - with self.assertRaises(IOError): - EclSum( self.createTestPath( "Statoil/ECLIPSE/ix/summary/Create_Region_Around_Well")) + intersect_summary = EclSum(self.createTestPath("Statoil/ECLIPSE/ix/summary/Create_Region_Around_Well")) + self.assertIsNotNone(intersect_summary) - f = EclFile( self.createTestPath( "Statoil/ECLIPSE/ix/summary/Create_Region_Around_Well.SMSPEC")) - self.assertTrue( "KEYWORDS" in f ) - self.assertFalse( "NAMES" in f ) + self.assertTrue( + "HWELL_PROD" in + [intersect_summary.smspec_node(key).wgname for key in intersect_summary.keys()] + ) + + eclipse_summary = EclSum(self.createTestPath("Statoil/ECLIPSE/ix/summary/ECL100/E100_CREATE_REGION_AROUND_WELL")) + self.assertIsNotNone(eclipse_summary) + + hwell_padder = lambda key : key if key.split(":")[-1] != "HWELL_PR" else key + "OD" + self.assertEqual( + intersect_summary.keys("WWCT*"), + map(hwell_padder, eclipse_summary.keys("WWCT*")) + ) + + def test_ix_write(self): + for data_set in [ + "Statoil/ECLIPSE/ix/summary/Create_Region_Around_Well", + "Statoil/ECLIPSE/ix/troll/IX_NOPH3_R04_75X75X1_grid2.SMSPEC" + ]: + + with TestAreaContext("my_space" + data_set.split("/")[-1]) as area: + intersect_summary = EclSum(self.createTestPath(data_set)) + self.assertIsNotNone(intersect_summary) + + write_location = os.path.join(os.getcwd(), "CASE") + intersect_summary.fwrite(ecl_case=write_location) + + reloaded_summary = EclSum(write_location) + self.assertEqual( + list(intersect_summary.keys()), + list(reloaded_summary.keys()) + ) + + def test_ix_caseII(self): + troll_summary = EclSum( self.createTestPath("Statoil/ECLIPSE/ix/troll/IX_NOPH3_R04_75X75X1_grid2.SMSPEC")) + self.assertIsNotNone(troll_summary) + self.assertTrue("WMCTL:Q21BH1" in list(troll_summary.keys())) diff --git a/ThirdParty/Ert/python/tests/geometry/CMakeLists.txt b/ThirdParty/Ert/python/tests/geometry/CMakeLists.txt index 5cfaf5c6a7..1795decd10 100644 --- a/ThirdParty/Ert/python/tests/geometry/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/geometry/CMakeLists.txt @@ -15,14 +15,14 @@ set(TEST_SOURCES add_python_package("python.tests.geometry" ${PYTHON_INSTALL_PREFIX}/tests/geometry "${TEST_SOURCES}" False) -addPythonTest(geometry.geo_pointset tests.geometry.test_geo_pointset.GeoPointsetTest) -addPythonTest(geometry.geo_region tests.geometry.test_geo_region.GeoRegionTest) -addPythonTest(geometry.surface tests.geometry.test_surface.SurfaceTest) -addPythonTest(geometry.polyline tests.geometry.test_polyline.PolylineTest) -addPythonTest(geometry.intersection tests.geometry.test_intersection.IntersectionTest) -addPythonTest(geometry.convex_hull tests.geometry.test_convex_hull.ConvexHullTest) -addPythonTest(geometry.point_in_polygon tests.geometry.test_point_in_polygon.PointInPolygonTest) -addPythonTest(geometry.polygon_slicing tests.geometry.test_polygon_slicing.PolygonSlicingTest) -addPythonTest(geometry.cpolyline tests.geometry.test_cpolyline.CPolylineTest) -addPythonTest(geometry.cpolyline_collection tests.geometry.test_cpolyline_collection.CPolylineCollectionTest) -addPythonTest(geometry.geometry_tools tests.geometry.test_geometry_tools.GeometryToolsTest ) +addPythonTest(tests.geometry.test_geo_pointset.GeoPointsetTest) +addPythonTest(tests.geometry.test_geo_region.GeoRegionTest) +addPythonTest(tests.geometry.test_surface.SurfaceTest) +addPythonTest(tests.geometry.test_polyline.PolylineTest) +addPythonTest(tests.geometry.test_intersection.IntersectionTest) +addPythonTest(tests.geometry.test_convex_hull.ConvexHullTest) +addPythonTest(tests.geometry.test_point_in_polygon.PointInPolygonTest) +addPythonTest(tests.geometry.test_polygon_slicing.PolygonSlicingTest) +addPythonTest(tests.geometry.test_cpolyline.CPolylineTest) +addPythonTest(tests.geometry.test_cpolyline_collection.CPolylineCollectionTest) +addPythonTest(tests.geometry.test_geometry_tools.GeometryToolsTest ) diff --git a/ThirdParty/Ert/python/tests/geometry/test_convex_hull.py b/ThirdParty/Ert/python/tests/geometry/test_convex_hull.py index 395fbe5fec..e0c27305f6 100644 --- a/ThirdParty/Ert/python/tests/geometry/test_convex_hull.py +++ b/ThirdParty/Ert/python/tests/geometry/test_convex_hull.py @@ -1,5 +1,5 @@ -from ert.geo.geometry_tools import GeometryTools -from ert.test.extended_testcase import ExtendedTestCase +from ecl.geo.geometry_tools import GeometryTools +from ecl.test.extended_testcase import ExtendedTestCase class ConvexHullTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/geometry/test_cpolyline.py b/ThirdParty/Ert/python/tests/geometry/test_cpolyline.py index cb517af936..6439f15923 100644 --- a/ThirdParty/Ert/python/tests/geometry/test_cpolyline.py +++ b/ThirdParty/Ert/python/tests/geometry/test_cpolyline.py @@ -1,8 +1,8 @@ import math -from ert.geo import CPolyline , Polyline -from ert.geo.xyz_io import XYZIo -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.geo import CPolyline , Polyline +from ecl.geo.xyz_io import XYZIo +from ecl.test import ExtendedTestCase , TestAreaContext class CPolylineTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/geometry/test_cpolyline_collection.py b/ThirdParty/Ert/python/tests/geometry/test_cpolyline_collection.py index 08fc345bce..11ab6a63cd 100644 --- a/ThirdParty/Ert/python/tests/geometry/test_cpolyline_collection.py +++ b/ThirdParty/Ert/python/tests/geometry/test_cpolyline_collection.py @@ -1,9 +1,9 @@ import gc -from ert.geo import CPolylineCollection , CPolyline -from ert.geo.xyz_io import XYZIo -from ert.test import ExtendedTestCase , TestAreaContext -from ert.util import DoubleVector +from ecl.geo import CPolylineCollection , CPolyline +from ecl.geo.xyz_io import XYZIo +from ecl.test import ExtendedTestCase , TestAreaContext +from ecl.util import DoubleVector class CPolylineCollectionTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/geometry/test_geo_pointset.py b/ThirdParty/Ert/python/tests/geometry/test_geo_pointset.py index 5e67e4aabf..1d1c423f17 100644 --- a/ThirdParty/Ert/python/tests/geometry/test_geo_pointset.py +++ b/ThirdParty/Ert/python/tests/geometry/test_geo_pointset.py @@ -1,5 +1,5 @@ -from ert.geo import GeoPointset, Surface -from ert.test import ExtendedTestCase, TestAreaContext +from ecl.geo import GeoPointset, Surface +from ecl.test import ExtendedTestCase, TestAreaContext class GeoPointsetTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/geometry/test_geo_region.py b/ThirdParty/Ert/python/tests/geometry/test_geo_region.py index 771a2af59e..949ced3128 100644 --- a/ThirdParty/Ert/python/tests/geometry/test_geo_region.py +++ b/ThirdParty/Ert/python/tests/geometry/test_geo_region.py @@ -1,5 +1,5 @@ -from ert.geo import GeoRegion, GeoPointset, CPolyline, Surface -from ert.test import ExtendedTestCase, TestAreaContext +from ecl.geo import GeoRegion, GeoPointset, CPolyline, Surface +from ecl.test import ExtendedTestCase, TestAreaContext class GeoRegionTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/geometry/test_geometry_tools.py b/ThirdParty/Ert/python/tests/geometry/test_geometry_tools.py index 80f0eb8489..0656677ad6 100644 --- a/ThirdParty/Ert/python/tests/geometry/test_geometry_tools.py +++ b/ThirdParty/Ert/python/tests/geometry/test_geometry_tools.py @@ -1,8 +1,8 @@ import math -from ert.geo import Polyline, GeometryTools , CPolyline -from ert.geo.xyz_io import XYZIo -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.geo import Polyline, GeometryTools , CPolyline +from ecl.geo.xyz_io import XYZIo +from ecl.test import ExtendedTestCase , TestAreaContext class GeometryToolsTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/geometry/test_intersection.py b/ThirdParty/Ert/python/tests/geometry/test_intersection.py index 2e36c59aaf..af78512e84 100644 --- a/ThirdParty/Ert/python/tests/geometry/test_intersection.py +++ b/ThirdParty/Ert/python/tests/geometry/test_intersection.py @@ -1,5 +1,5 @@ -from ert.geo import GeometryTools -from ert.test.extended_testcase import ExtendedTestCase +from ecl.geo import GeometryTools +from ecl.test.extended_testcase import ExtendedTestCase class IntersectionTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/geometry/test_point_in_polygon.py b/ThirdParty/Ert/python/tests/geometry/test_point_in_polygon.py index ad2e87c31b..8faeb9ca5f 100644 --- a/ThirdParty/Ert/python/tests/geometry/test_point_in_polygon.py +++ b/ThirdParty/Ert/python/tests/geometry/test_point_in_polygon.py @@ -1,6 +1,6 @@ -from ert.geo.geometry_tools import GeometryTools -from ert.geo.polyline import Polyline -from ert.test.extended_testcase import ExtendedTestCase +from ecl.geo.geometry_tools import GeometryTools +from ecl.geo.polyline import Polyline +from ecl.test.extended_testcase import ExtendedTestCase class PointInPolygonTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/geometry/test_polygon_slicing.py b/ThirdParty/Ert/python/tests/geometry/test_polygon_slicing.py index ad7c1780ac..e2493e6822 100644 --- a/ThirdParty/Ert/python/tests/geometry/test_polygon_slicing.py +++ b/ThirdParty/Ert/python/tests/geometry/test_polygon_slicing.py @@ -1,6 +1,6 @@ from math import sqrt -from ert.geo.geometry_tools import GeometryTools -from ert.test import ExtendedTestCase +from ecl.geo.geometry_tools import GeometryTools +from ecl.test import ExtendedTestCase class PolygonSlicingTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/geometry/test_polyline.py b/ThirdParty/Ert/python/tests/geometry/test_polyline.py index 8674e75460..bd9e262cff 100644 --- a/ThirdParty/Ert/python/tests/geometry/test_polyline.py +++ b/ThirdParty/Ert/python/tests/geometry/test_polyline.py @@ -1,7 +1,7 @@ -from ert.geo import Polyline, GeometryTools -from ert.geo.xyz_io import XYZIo -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.geo import Polyline, GeometryTools +from ecl.geo.xyz_io import XYZIo +from ecl.test import ExtendedTestCase , TestAreaContext class PolylineTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/geometry/test_surface.py b/ThirdParty/Ert/python/tests/geometry/test_surface.py index 1bfd204a04..995c34bcdb 100644 --- a/ThirdParty/Ert/python/tests/geometry/test_surface.py +++ b/ThirdParty/Ert/python/tests/geometry/test_surface.py @@ -1,6 +1,6 @@ import random -from ert.geo import Surface -from ert.test import ExtendedTestCase , TestAreaContext +from ecl.geo import Surface +from ecl.test import ExtendedTestCase , TestAreaContext class SurfaceTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/global/CMakeLists.txt b/ThirdParty/Ert/python/tests/global/CMakeLists.txt new file mode 100644 index 0000000000..957c12c570 --- /dev/null +++ b/ThirdParty/Ert/python/tests/global/CMakeLists.txt @@ -0,0 +1,12 @@ +set(TEST_SOURCES + __init__.py + test_import.py + test_pylint.py +) + +add_python_package("python.tests.global" "${PYTHON_INSTALL_PREFIX}/tests/global" "${TEST_SOURCES}" False) + +addPythonTest(tests.global.test_import.ImportEcl) +addPythonTest(tests.global.test_pylint.LintErt) + + diff --git a/ThirdParty/Ert/python/tests/global/__init__.py b/ThirdParty/Ert/python/tests/global/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ThirdParty/Ert/python/tests/global/test_import.py b/ThirdParty/Ert/python/tests/global/test_import.py new file mode 100644 index 0000000000..fe0835809a --- /dev/null +++ b/ThirdParty/Ert/python/tests/global/test_import.py @@ -0,0 +1,26 @@ +# Copyright (C) 2017 Statoil ASA, Norway. +# +# This file is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. + +import os +import sys + + +from ecl.test import ImportTestCase + +class ImportEcl(ImportTestCase): + + def test_import_ecl(self): + self.assertTrue( self.import_package( "ecl" )) diff --git a/ThirdParty/Ert/python/tests/global/test_pylint.py b/ThirdParty/Ert/python/tests/global/test_pylint.py new file mode 100644 index 0000000000..20206294f1 --- /dev/null +++ b/ThirdParty/Ert/python/tests/global/test_pylint.py @@ -0,0 +1,33 @@ +# Copyright (C) 2017 Statoil ASA, Norway. +# +# This file is part of ERT - Ensemble based Reservoir Tool. +# +# ERT 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. +# +# ERT 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 at +# for more details. + +from ecl.test import LintTestCase + +class LintErt(LintTestCase): + """Tests that no file in ert needs linting""" + + def test_lint_ecl(self): + white = ['ecl_kw.py', 'ecl_type.py', 'ecl_sum.py', 'ecl_grid.py', 'ecl_npv.py'] # TODO fix issues and remove + self.assertLinted('ecl/ecl', whitelist=white) + + def test_lint_geo(self): + self.assertLinted('ecl/geo') + + def test_lint_util(self): + self.assertLinted('ecl/util') + + def test_lint_well(self): + self.assertLinted('ecl/well') diff --git a/ThirdParty/Ert/python/tests/import_tester.py b/ThirdParty/Ert/python/tests/import_tester.py deleted file mode 100644 index b268c77e6b..0000000000 --- a/ThirdParty/Ert/python/tests/import_tester.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -import os -import sys -import traceback - -class ImportTester(object): - @staticmethod - def testImport(module): - try: - if '__pycache__' in str(module): - # python 3 hack - return True - else: - print('Importing module %s.' % str(module)) - __import__(module) - return True - except ImportError: - tb = traceback.format_exc() - sys.stderr.write("Error importing module %s!\n\n" % module) - sys.stderr.write(str(tb)) - sys.stderr.write("\n") - except Exception: - tb = traceback.format_exc() - sys.stderr.write("Import of module %s caused errors!\n\n" % module) - sys.stderr.write(str(tb)) - sys.stderr.write("\n") - - return False - - - @staticmethod - def importRecursively(path, package_name): - entries = os.listdir(path) - - result = True - - for entry in sorted(entries): - import_success = True - - entry_path = os.path.join(path, entry) - if os.path.isdir(entry_path): - package = "%s.%s" % (package_name, entry) - import_success = ImportTester.testImport(package) - new_path = os.path.join(path, entry) - import_success = import_success and ImportTester.importRecursively(new_path, package) - elif os.path.isfile(entry_path): - if not entry.startswith("__init__") and entry.endswith(".py"): - module = entry[0:len(entry) - 3] - import_success = ImportTester.testImport("%s.%s" % (package_name, module)) - else: - # skip other files - pass - # print("Skipped entry: %s" % entry) - - if not import_success: - result = False - - return result - - -if __name__ == '__main__': - PYTHONPATH = sys.argv[1] - package_name = sys.argv[2] - - sys.path.insert(0, PYTHONPATH) - - package_path = os.path.join(PYTHONPATH, package_name) - - if ImportTester.importRecursively(package_path, package_name): - sys.exit(0) - else: - sys.exit(1) diff --git a/ThirdParty/Ert/python/tests/share/CMakeLists.txt b/ThirdParty/Ert/python/tests/share/CMakeLists.txt index 572d5d0c4e..ef80c2d77d 100644 --- a/ThirdParty/Ert/python/tests/share/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/share/CMakeLists.txt @@ -5,4 +5,4 @@ set(TEST_SOURCES add_python_package("python.tests.share" ${PYTHON_INSTALL_PREFIX}/tests/share "${TEST_SOURCES}" False) -addPythonTest(share.synthesizer share.test_synthesizer.SynthesizerTest) \ No newline at end of file +addPythonTest(share.test_synthesizer.SynthesizerTest) diff --git a/ThirdParty/Ert/python/tests/share/test_synthesizer.py b/ThirdParty/Ert/python/tests/share/test_synthesizer.py index e6b75e2015..f5863f5e91 100644 --- a/ThirdParty/Ert/python/tests/share/test_synthesizer.py +++ b/ThirdParty/Ert/python/tests/share/test_synthesizer.py @@ -1,6 +1,6 @@ import sys import os -from ert.test import ExtendedTestCase +from ecl.test import ExtendedTestCase try: from synthesizer import OilSimulator diff --git a/ThirdParty/Ert/python/tests/test_pylint.py b/ThirdParty/Ert/python/tests/test_pylint.py index 1d327ef380..20206294f1 100644 --- a/ThirdParty/Ert/python/tests/test_pylint.py +++ b/ThirdParty/Ert/python/tests/test_pylint.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Copyright (C) 2017 Statoil ASA, Norway. # # This file is part of ERT - Ensemble based Reservoir Tool. @@ -15,20 +14,20 @@ # See the GNU General Public License at # for more details. -from ert.test import LintTestCase +from ecl.test import LintTestCase class LintErt(LintTestCase): """Tests that no file in ert needs linting""" def test_lint_ecl(self): white = ['ecl_kw.py', 'ecl_type.py', 'ecl_sum.py', 'ecl_grid.py', 'ecl_npv.py'] # TODO fix issues and remove - self.assertLinted('ert/ecl', whitelist=white) + self.assertLinted('ecl/ecl', whitelist=white) def test_lint_geo(self): - self.assertLinted('ert/geo') + self.assertLinted('ecl/geo') def test_lint_util(self): - self.assertLinted('ert/util') + self.assertLinted('ecl/util') def test_lint_well(self): - self.assertLinted('ert/well') + self.assertLinted('ecl/well') diff --git a/ThirdParty/Ert/python/tests/util/CMakeLists.txt b/ThirdParty/Ert/python/tests/util/CMakeLists.txt index 38485b80f9..fdac8c12eb 100644 --- a/ThirdParty/Ert/python/tests/util/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/util/CMakeLists.txt @@ -22,20 +22,20 @@ set(TEST_SOURCES add_python_package("python.tests.util" ${PYTHON_INSTALL_PREFIX}/tests/util "${TEST_SOURCES}" False) -addPythonTest(util.ctime util.test_ctime.CTimeTest) -addPythonTest(util.cstring util.test_cstring.CStringTest) -addPythonTest(util.hash util.test_hash.HashTest) -addPythonTest(util.lookup_table util.test_lookup_table.LookupTableTest ) -addPythonTest(util.matrix util.test_matrix.MatrixTest ) -addPythonTest(util.rng util.test_rng.RngTest ) -addPythonTest(util.stat util.test_stat.StatTest ) -addPythonTest(util.stringlist util.test_string_list.StringListTest) -addPythonTest(util.tvector util.test_vectors.UtilTest) -addPythonTest(util.ui_return util.test_ui_return.UIReturnTest) -addPythonTest(util.work_area util.test_work_area.WorkAreaTest) -addPythonTest(util.version util.test_version.VersionTest) -addPythonTest(util.path_context util.test_path_context.PathContextTest) -addPythonTest(util.thread_pool util.test_thread_pool.ThreadPoolTest) -addPythonTest(util.cthread_pool util.test_cthread_pool.CThreadPoolTest) -addPythonTest(util.arg_pack util.test_arg_pack.ArgPackTest) -addPythonTest(util.spawn util.test_spawn.SpawnTest) +addPythonTest(tests.util.test_ctime.CTimeTest) +addPythonTest(tests.util.test_cstring.CStringTest) +addPythonTest(tests.util.test_hash.HashTest) +addPythonTest(tests.util.test_lookup_table.LookupTableTest ) +addPythonTest(tests.util.test_matrix.MatrixTest ) +addPythonTest(tests.util.test_rng.RngTest ) +addPythonTest(tests.util.test_stat.StatTest ) +addPythonTest(tests.util.test_string_list.StringListTest) +addPythonTest(tests.util.test_vectors.UtilTest) +addPythonTest(tests.util.test_ui_return.UIReturnTest) +addPythonTest(tests.util.test_work_area.WorkAreaTest) +addPythonTest(tests.util.test_version.VersionTest) +addPythonTest(tests.util.test_path_context.PathContextTest) +addPythonTest(tests.util.test_thread_pool.ThreadPoolTest) +addPythonTest(tests.util.test_cthread_pool.CThreadPoolTest) +addPythonTest(tests.util.test_arg_pack.ArgPackTest) +addPythonTest(tests.util.test_spawn.SpawnTest) diff --git a/ThirdParty/Ert/python/tests/util/test_arg_pack.py b/ThirdParty/Ert/python/tests/util/test_arg_pack.py index fdd1ceef69..0ecbe23c05 100644 --- a/ThirdParty/Ert/python/tests/util/test_arg_pack.py +++ b/ThirdParty/Ert/python/tests/util/test_arg_pack.py @@ -1,8 +1,8 @@ -import ert -from ert.test import ExtendedTestCase -from ert.util import ArgPack, StringList +import ecl +from ecl.test import ExtendedTestCase +from ecl.util import ArgPack, StringList -TEST_LIB = ert.load("libert_util") +TEST_LIB = ecl.load("libert_util") class ArgPackTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/util/test_cstring.py b/ThirdParty/Ert/python/tests/util/test_cstring.py index 4e533f9e11..fe82c5a6fe 100644 --- a/ThirdParty/Ert/python/tests/util/test_cstring.py +++ b/ThirdParty/Ert/python/tests/util/test_cstring.py @@ -1,10 +1,10 @@ -import ert +import ecl from cwrap import Prototype -from ert.test.extended_testcase import ExtendedTestCase +from ecl.test.extended_testcase import ExtendedTestCase # Local copies so that the real ones don't get changed class TestUtilPrototype(Prototype): - lib = ert.load("libert_util") + lib = ecl.load("libert_util") def __init__(self, prototype, bind=False): super(TestUtilPrototype, self).__init__(TestUtilPrototype.lib, prototype, bind=bind) diff --git a/ThirdParty/Ert/python/tests/util/test_cthread_pool.py b/ThirdParty/Ert/python/tests/util/test_cthread_pool.py index d3ab2cfb11..ee55aa9ce6 100644 --- a/ThirdParty/Ert/python/tests/util/test_cthread_pool.py +++ b/ThirdParty/Ert/python/tests/util/test_cthread_pool.py @@ -1,9 +1,9 @@ import ctypes -import ert -from ert.test import ExtendedTestCase -from ert.util import CThreadPool, startCThreadPool +import ecl +from ecl.test import ExtendedTestCase +from ecl.util import CThreadPool, startCThreadPool -TEST_LIB = ert.load("libert_util") +TEST_LIB = ecl.load("libert_util") class CThreadPoolTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/util/test_ctime.py b/ThirdParty/Ert/python/tests/util/test_ctime.py index 8a74c2c51e..292a13153a 100644 --- a/ThirdParty/Ert/python/tests/util/test_ctime.py +++ b/ThirdParty/Ert/python/tests/util/test_ctime.py @@ -1,7 +1,7 @@ import time from datetime import datetime, date -from ert.util import CTime +from ecl.util import CTime try: diff --git a/ThirdParty/Ert/python/tests/util/test_hash.py b/ThirdParty/Ert/python/tests/util/test_hash.py index 1279794b08..528d123ee4 100644 --- a/ThirdParty/Ert/python/tests/util/test_hash.py +++ b/ThirdParty/Ert/python/tests/util/test_hash.py @@ -1,7 +1,7 @@ from ctypes import c_void_p -from ert.test import ExtendedTestCase -from ert.util import Hash, StringHash, DoubleHash, IntegerHash +from ecl.test import ExtendedTestCase +from ecl.util import Hash, StringHash, DoubleHash, IntegerHash class HashTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/util/test_lookup_table.py b/ThirdParty/Ert/python/tests/util/test_lookup_table.py index de4fef4241..9a0fdccdfe 100644 --- a/ThirdParty/Ert/python/tests/util/test_lookup_table.py +++ b/ThirdParty/Ert/python/tests/util/test_lookup_table.py @@ -3,7 +3,7 @@ try: except ImportError: from unittest import TestCase -from ert.util import LookupTable +from ecl.util import LookupTable class LookupTableTest(TestCase): diff --git a/ThirdParty/Ert/python/tests/util/test_matrix.py b/ThirdParty/Ert/python/tests/util/test_matrix.py index d5b6a626d1..d5d5205890 100644 --- a/ThirdParty/Ert/python/tests/util/test_matrix.py +++ b/ThirdParty/Ert/python/tests/util/test_matrix.py @@ -1,6 +1,6 @@ -from ert.util import Matrix , RandomNumberGenerator -from ert.util.enums import RngAlgTypeEnum, RngInitModeEnum -from ert.test import ExtendedTestCase, TestAreaContext +from ecl.util import Matrix , RandomNumberGenerator +from ecl.util.enums import RngAlgTypeEnum, RngInitModeEnum +from ecl.test import ExtendedTestCase, TestAreaContext class MatrixTest(ExtendedTestCase): def test_matrix(self): diff --git a/ThirdParty/Ert/python/tests/util/test_path_context.py b/ThirdParty/Ert/python/tests/util/test_path_context.py index 06cb537574..51587a5827 100644 --- a/ThirdParty/Ert/python/tests/util/test_path_context.py +++ b/ThirdParty/Ert/python/tests/util/test_path_context.py @@ -1,5 +1,5 @@ import os -from ert.test import ExtendedTestCase, PathContext,TestAreaContext +from ecl.test import ExtendedTestCase, PathContext,TestAreaContext class PathContextTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/util/test_rng.py b/ThirdParty/Ert/python/tests/util/test_rng.py index 21eea2177b..dc4b03f7ca 100644 --- a/ThirdParty/Ert/python/tests/util/test_rng.py +++ b/ThirdParty/Ert/python/tests/util/test_rng.py @@ -1,6 +1,6 @@ -from ert.util.enums import RngAlgTypeEnum, RngInitModeEnum -from ert.util.rng import RandomNumberGenerator -from ert.test import ExtendedTestCase,TestAreaContext +from ecl.util.enums import RngAlgTypeEnum, RngInitModeEnum +from ecl.util.rng import RandomNumberGenerator +from ecl.test import ExtendedTestCase,TestAreaContext class RngTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/util/test_spawn.py b/ThirdParty/Ert/python/tests/util/test_spawn.py index 2ef47ad027..a867da3336 100644 --- a/ThirdParty/Ert/python/tests/util/test_spawn.py +++ b/ThirdParty/Ert/python/tests/util/test_spawn.py @@ -2,14 +2,14 @@ import os import stat import sys -import ert -from ert.test.extended_testcase import ExtendedTestCase -from ert.test.test_area import TestAreaContext +import ecl +from ecl.test.extended_testcase import ExtendedTestCase +from ecl.test.test_area import TestAreaContext from cwrap import Prototype class _TestSpawnPrototype(Prototype): - lib = ert.load('libert_util') + lib = ecl.load('libert_util') def __init__(self, prototype, bind=True): super(_TestSpawnPrototype, self).__init__(_TestSpawnPrototype.lib, prototype, bind=bind) diff --git a/ThirdParty/Ert/python/tests/util/test_stat.py b/ThirdParty/Ert/python/tests/util/test_stat.py index e2a73bbf45..f1a79e9701 100644 --- a/ThirdParty/Ert/python/tests/util/test_stat.py +++ b/ThirdParty/Ert/python/tests/util/test_stat.py @@ -1,6 +1,6 @@ -from ert.test import ExtendedTestCase -from ert.util import DoubleVector, quantile, quantile_sorted, polyfit -from ert.util.rng import RandomNumberGenerator +from ecl.test import ExtendedTestCase +from ecl.util import DoubleVector, quantile, quantile_sorted, polyfit +from ecl.util.rng import RandomNumberGenerator class StatTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/util/test_string_list.py b/ThirdParty/Ert/python/tests/util/test_string_list.py index 627603546b..a4076fe2c8 100644 --- a/ThirdParty/Ert/python/tests/util/test_string_list.py +++ b/ThirdParty/Ert/python/tests/util/test_string_list.py @@ -5,7 +5,7 @@ try: except ImportError: from unittest import TestCase -from ert.util import StringList +from ecl.util import StringList class StringListTest(TestCase): diff --git a/ThirdParty/Ert/python/tests/util/test_substitution_list.py b/ThirdParty/Ert/python/tests/util/test_substitution_list.py index 0d60268ca9..8541b76044 100644 --- a/ThirdParty/Ert/python/tests/util/test_substitution_list.py +++ b/ThirdParty/Ert/python/tests/util/test_substitution_list.py @@ -1,5 +1,5 @@ -from ert.test import ExtendedTestCase -from ert.util import SubstitutionList +from ecl.test import ExtendedTestCase +from ecl.util import SubstitutionList class SubstitutionListTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/util/test_thread_pool.py b/ThirdParty/Ert/python/tests/util/test_thread_pool.py index 3c772ec633..ffe620dcd6 100644 --- a/ThirdParty/Ert/python/tests/util/test_thread_pool.py +++ b/ThirdParty/Ert/python/tests/util/test_thread_pool.py @@ -1,7 +1,7 @@ import time -from ert.util import ThreadPool -from ert.util.thread_pool import Task -from ert.test import ExtendedTestCase +from ecl.util import ThreadPool +from ecl.util.thread_pool import Task +from ecl.test import ExtendedTestCase class ThreadPoolTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/util/test_ui_return.py b/ThirdParty/Ert/python/tests/util/test_ui_return.py index b3dd1d5b6a..2e7dfe9e75 100644 --- a/ThirdParty/Ert/python/tests/util/test_ui_return.py +++ b/ThirdParty/Ert/python/tests/util/test_ui_return.py @@ -1,6 +1,6 @@ -from ert.test import ExtendedTestCase -from ert.util import UIReturn -from ert.util.enums import UIReturnStatusEnum +from ecl.test import ExtendedTestCase +from ecl.util import UIReturn +from ecl.util.enums import UIReturnStatusEnum class UIReturnTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/util/test_vectors.py b/ThirdParty/Ert/python/tests/util/test_vectors.py index 99b7fe7885..9b710567eb 100644 --- a/ThirdParty/Ert/python/tests/util/test_vectors.py +++ b/ThirdParty/Ert/python/tests/util/test_vectors.py @@ -24,7 +24,7 @@ try: except ImportError: from unittest import TestCase -from ert.util import DoubleVector, IntVector, BoolVector, TimeVector, CTime, PermutationVector +from ecl.util import DoubleVector, IntVector, BoolVector, TimeVector, CTime, PermutationVector class UtilTest(TestCase): def setUp(self): diff --git a/ThirdParty/Ert/python/tests/util/test_version.py b/ThirdParty/Ert/python/tests/util/test_version.py index 67f394cd6b..cb27655c8e 100644 --- a/ThirdParty/Ert/python/tests/util/test_version.py +++ b/ThirdParty/Ert/python/tests/util/test_version.py @@ -15,9 +15,9 @@ # for more details. import os.path -import ert -from ert.test import ExtendedTestCase -from ert.util import Version +import ecl +from ecl.test import ExtendedTestCase +from ecl.util import Version class VersionTest(ExtendedTestCase): @@ -99,7 +99,7 @@ class VersionTest(ExtendedTestCase): self.assertEqual(pfx, repr(current)[:len(pfx)]) def test_import(self): - from ert import Version as globalVersion + from ecl import Version as globalVersion v1 = globalVersion(1, 1, 2) v2 = Version(1, 1, 2) @@ -110,10 +110,10 @@ class VersionTest(ExtendedTestCase): def test_root_version(self): cv = Version.currentVersion( ) - self.assertEqual( ert.__version__ , cv.versionString() ) + self.assertEqual( ecl.__version__ , cv.versionString() ) def test_root_path(self): - self.assertTrue( os.path.isdir( os.path.join( ert.root() , "ert"))) - self.assertTrue( os.path.isfile( os.path.join( ert.root() , "ert", "__init__.py"))) + self.assertTrue( os.path.isdir( os.path.join( ecl.root() , "ecl"))) + self.assertTrue( os.path.isfile( os.path.join( ecl.root() , "ecl", "__init__.py"))) diff --git a/ThirdParty/Ert/python/tests/util/test_work_area.py b/ThirdParty/Ert/python/tests/util/test_work_area.py index 5123c827e6..51403f817d 100644 --- a/ThirdParty/Ert/python/tests/util/test_work_area.py +++ b/ThirdParty/Ert/python/tests/util/test_work_area.py @@ -23,7 +23,7 @@ try: except ImportError: from unittest import skipIf -from ert.test import ExtendedTestCase , TestAreaContext, TempAreaContext +from ecl.test import ExtendedTestCase , TestAreaContext, TempAreaContext class WorkAreaTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/well/CMakeLists.txt b/ThirdParty/Ert/python/tests/well/CMakeLists.txt index 33eeea468e..e5853b33f6 100644 --- a/ThirdParty/Ert/python/tests/well/CMakeLists.txt +++ b/ThirdParty/Ert/python/tests/well/CMakeLists.txt @@ -8,7 +8,7 @@ set(TEST_SOURCES add_python_package("python.tests.well" ${PYTHON_INSTALL_PREFIX}/tests/well "${TEST_SOURCES}" False) if (STATOIL_TESTDATA_ROOT) - addPythonTest(well.ecl_well well.test_ecl_well.EclWellTest LABELS StatoilData) - addPythonTest(well.ecl_well2 well.test_ecl_well2.EclWellTest2 LABELS StatoilData) - addPythonTest(well.ecl_well3 well.test_ecl_well3.EclWellTest3 LABELS StatoilData) + addPythonTest(well.test_ecl_well.EclWellTest LABELS StatoilData) + addPythonTest(well.test_ecl_well2.EclWellTest2 LABELS StatoilData) + addPythonTest(well.test_ecl_well3.EclWellTest3 LABELS StatoilData) endif() diff --git a/ThirdParty/Ert/python/tests/well/test_ecl_well.py b/ThirdParty/Ert/python/tests/well/test_ecl_well.py index 7c5fcaad69..bcbf872d17 100644 --- a/ThirdParty/Ert/python/tests/well/test_ecl_well.py +++ b/ThirdParty/Ert/python/tests/well/test_ecl_well.py @@ -1,8 +1,8 @@ import datetime -from ert.ecl import EclGrid, EclFile, EclFileFlagEnum -from ert.test import ExtendedTestCase -from ert.util.ctime import CTime -from ert.well import WellInfo, WellConnection, WellTypeEnum, WellConnectionDirectionEnum, WellSegment +from ecl.ecl import EclGrid, EclFile, EclFileFlagEnum +from ecl.test import ExtendedTestCase +from ecl.util.ctime import CTime +from ecl.well import WellInfo, WellConnection, WellTypeEnum, WellConnectionDirectionEnum, WellSegment class EclWellTest(ExtendedTestCase): diff --git a/ThirdParty/Ert/python/tests/well/test_ecl_well2.py b/ThirdParty/Ert/python/tests/well/test_ecl_well2.py index 07a78629f7..52797e2bfa 100644 --- a/ThirdParty/Ert/python/tests/well/test_ecl_well2.py +++ b/ThirdParty/Ert/python/tests/well/test_ecl_well2.py @@ -1,10 +1,10 @@ import datetime import os.path -from ert.ecl import EclGrid, EclFile, EclFileFlagEnum -from ert.test import ExtendedTestCase -from ert.util.ctime import CTime -from ert.well import WellInfo, WellConnection, WellTypeEnum, WellConnectionDirectionEnum, WellSegment +from ecl.ecl import EclGrid, EclFile, EclFileFlagEnum +from ecl.test import ExtendedTestCase +from ecl.util.ctime import CTime +from ecl.well import WellInfo, WellConnection, WellTypeEnum, WellConnectionDirectionEnum, WellSegment diff --git a/ThirdParty/Ert/python/tests/well/test_ecl_well3.py b/ThirdParty/Ert/python/tests/well/test_ecl_well3.py index 9ce0796177..66283d261e 100644 --- a/ThirdParty/Ert/python/tests/well/test_ecl_well3.py +++ b/ThirdParty/Ert/python/tests/well/test_ecl_well3.py @@ -1,10 +1,10 @@ import datetime import os.path -from ert.ecl import EclGrid, EclFile, EclSum -from ert.test import ExtendedTestCase -from ert.util.ctime import CTime -from ert.well import WellInfo, WellConnection, WellTypeEnum, WellConnectionDirectionEnum, WellSegment +from ecl.ecl import EclGrid, EclFile, EclSum +from ecl.test import ExtendedTestCase +from ecl.util.ctime import CTime +from ecl.well import WellInfo, WellConnection, WellTypeEnum, WellConnectionDirectionEnum, WellSegment class EclWellTest3(ExtendedTestCase): From 74a90e204c1aa01ceb0ecb055edcbb6ecb15a251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 8 May 2017 13:43:31 +0200 Subject: [PATCH 080/157] #1396 Apply patch fix-synthetic-odb-cases --- ThirdParty/Ert/libecl/src/ecl_rsthead.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ThirdParty/Ert/libecl/src/ecl_rsthead.c b/ThirdParty/Ert/libecl/src/ecl_rsthead.c index e8d9cef33a..e515df45fd 100644 --- a/ThirdParty/Ert/libecl/src/ecl_rsthead.c +++ b/ThirdParty/Ert/libecl/src/ecl_rsthead.c @@ -88,7 +88,8 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ // The only derived quantity rsthead->sim_time = rsthead_date( rsthead->day , rsthead->month , rsthead->year ); } - rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); + if (doubhead_kw) + rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX ); if (logihead_kw) rsthead->dualp = ecl_kw_iget_bool( logihead_kw , LOGIHEAD_DUALP_INDEX); @@ -109,12 +110,15 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ ecl_rsthead_type * ecl_rsthead_alloc( const ecl_file_view_type * rst_view, int report_step) { const ecl_kw_type * intehead_kw = ecl_file_view_iget_named_kw( rst_view , INTEHEAD_KW , 0); - const ecl_kw_type * doubhead_kw = ecl_file_view_iget_named_kw( rst_view , DOUBHEAD_KW , 0); + const ecl_kw_type * doubhead_kw = NULL; const ecl_kw_type * logihead_kw = NULL; if (ecl_file_view_has_kw(rst_view, LOGIHEAD_KW)) logihead_kw = ecl_file_view_iget_named_kw( rst_view , LOGIHEAD_KW , 0); + if (ecl_file_view_has_kw(rst_view, DOUBHEAD_KW)) + doubhead_kw = ecl_file_view_iget_named_kw(rst_view, DOUBHEAD_KW, 0); + if (ecl_file_view_has_kw( rst_view , SEQNUM_KW)) { const ecl_kw_type * seqnum_kw = ecl_file_view_iget_named_kw( rst_view , SEQNUM_KW , 0); report_step = ecl_kw_iget_int( seqnum_kw , 0); From 7c7f8ef627936bae892350916ab8c36afe733f1f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 May 2017 15:07:18 +0200 Subject: [PATCH 081/157] #1452 Use captal WELLHEAD and no space in names --- .../RicExportFishbonesLateralsFeature.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp index be71bfcc77..369106c8dd 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp @@ -64,9 +64,12 @@ void RicExportFishbonesLateralsFeature::onActionTriggered(bool isChecked) // See RifWellPathAsciiFileReader::readAllWellData for reading of dev files + // + // http://resinsight.org/docs/wellpaths/ // Export format // - // wellname : __ + // wellname : ____ + // // for each coordinate along lateral, export // x y TVD MD // separate laterals using -999 on a single line @@ -85,8 +88,11 @@ void RicExportFishbonesLateralsFeature::onActionTriggered(bool isChecked) // Pad with "0" to get a total of two characters defining the sub index text QString subIndexText = QString("%1").arg(subIndex, 2, 10, QChar('0')); - QString lateralName = QString("%1_%2_%3_%4").arg(wellPath->name()).arg(fishbone->name()).arg(subIndexText).arg(lateralIndex); - stream << "wellname : " << lateralName << endl; + QString lateralNameCandidate = QString("%1__%2_%3_%4").arg(wellPath->name()).arg(fishbone->name()).arg(subIndexText).arg(lateralIndex); + + QString lateralName = caf::Utils::makeValidFileBasename(lateralNameCandidate); + + stream << "WELLNAME: " << lateralName << endl; for (auto coordMD : coordsAndMD) { From cac2aefefd7d83aea510ec20ea0c4972d28e25c3 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 May 2017 15:08:57 +0200 Subject: [PATCH 082/157] #1450 Use Y-AXIS as default lateral direction for near-vertical wells --- ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp index a356cc659b..732118f286 100644 --- a/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp @@ -81,8 +81,8 @@ void RigFisbonesGeometry::computeLateralPositionAndOrientation(size_t subIndex, if (RigFisbonesGeometry::closestMainAxis(alongWellPath) == cvf::Vec3d::Z_AXIS) { - // Use x-axis if well path is heading close to z-axis - lateralInitialDirection = cvf::Vec3d::X_AXIS; + // Use Y-AXIS if well path is heading close to Z-AXIS + lateralInitialDirection = cvf::Vec3d::Y_AXIS; } { From f26c5ce75d65bed16e6c57edca2c14559276c4b7 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 May 2017 15:11:31 +0200 Subject: [PATCH 083/157] #1452 Use 'Export Laterals' as command name --- .../FishbonesCommands/RicExportFishbonesLateralsFeature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp index 369106c8dd..569489f4a2 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp @@ -131,7 +131,7 @@ RimWellPath* RicExportFishbonesLateralsFeature::selectedWellPath() void RicExportFishbonesLateralsFeature::setupActionLook(QAction* actionToSetup) { //actionToSetup->setIcon(QIcon(":/FractureSymbol16x16.png")); - actionToSetup->setText("Export Fishbones Laterals"); + actionToSetup->setText("Export Laterals"); } //-------------------------------------------------------------------------------------------------- From 141ce6b54bd2ed8b2b216ffb4f2708fc751b19d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 8 May 2017 16:02:42 +0200 Subject: [PATCH 084/157] #1381 Well Flow Plots show phase split (Oil Gas Water) Flow rates are explained in the plots as Surface/reservoir flow rates. Unit for field is [stb]/day for all fluids --- .../FileInterface/RifReaderEclipseOutput.cpp | 11 ++++++++++- .../FileInterface/RifReaderEclipseOutput.h | 2 +- .../ProjectDataModel/Flow/RimWellAllocationPlot.cpp | 9 ++++++++- .../ReservoirDataModel/RigAccWellFlowCalculator.cpp | 5 ++++- .../ReservoirDataModel/RigSingleWellResultsData.h | 8 ++++---- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index 235acb9971..9727079aa2 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -969,8 +969,17 @@ RigWellResultPoint RifReaderEclipseOutput::createWellResultPoint(const RigGridBa resultPoint.m_ertSegmentId = ertSegmentId; resultPoint.m_flowRate = volumeRate; resultPoint.m_oilRate = oilRate; - resultPoint.m_gasRate = gasRate; resultPoint.m_waterRate = waterRate; + + // If field unit, the Gas is in Mega ft^3 while the others are in [stb] (barrel) + // we convert gas to stb as well. Based on + // 1 [stb] = 0.15898729492800007 [m^3] + // 1 [ft] = 0.3048 [m] + // megaFt3ToStbFactor = 1.0 / (1.0e-6 * 0.15898729492800007 * ( 1.0 / 0.3048 )^3 ) + double megaFt3ToStbFactor = 178107.60668; + if (m_eclipseCase->unitsType() == RigEclipseCaseData::UNITS_FIELD) gasRate = megaFt3ToStbFactor * gasRate; + + resultPoint.m_gasRate = gasRate; } return resultPoint; diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h index fa74becd6b..55f0ec81ca 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h @@ -69,7 +69,7 @@ private: std::string ertGridName( size_t gridNr ); - static RigWellResultPoint createWellResultPoint(const RigGridBase* grid, const well_conn_type* ert_connection, int ertBranchId, int ertSegmentId, const char* wellName); + RigWellResultPoint createWellResultPoint(const RigGridBase* grid, const well_conn_type* ert_connection, int ertBranchId, int ertSegmentId, const char* wellName); void importFaults(const QStringList& fileSet, cvf::Collection* faults); diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp index 1017d9cc1e..89d9ce4244 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp @@ -374,7 +374,14 @@ void RimWellAllocationPlot::updateWellFlowPlotXAxisTitle(RimWellLogTrack* plotTr } - plotTrack->setXAxisTitle("Flow Rate " + unitText); + if (m_flowDiagSolution) + { + plotTrack->setXAxisTitle("Reservoir Flow Rate " + unitText); + } + else + { + plotTrack->setXAxisTitle("Surface Flow Rate " + unitText); + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp index 98f662ebbf..ab18acd9e3 100644 --- a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp @@ -46,7 +46,7 @@ size_t RigEclCellIndexCalculator::resultCellIndex(size_t gridIndex, size_t gridC /// //================================================================================================== -//#define USE_WELL_PHASE_RATES +#define USE_WELL_PHASE_RATES //-------------------------------------------------------------------------------------------------- /// @@ -105,6 +105,9 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto calculateAccumulatedFlowPrConnection(0, 1); calculateFlowPrPseudoLength(0, 0.0); +#ifdef USE_WELL_PHASE_RATES + sortTracers(); +#endif } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h b/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h index 7d33fff0d6..6b6479f085 100644 --- a/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h +++ b/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h @@ -128,10 +128,10 @@ struct RigWellResultPoint int m_ertSegmentId; cvf::Vec3d m_bottomPosition; //< The estimated bottom position of the well segment, when we have no grid cell connections for the segment. - double m_flowRate; - double m_oilRate; - double m_gasRate; - double m_waterRate; + double m_flowRate; //< Total reservoir rate + double m_oilRate; //< Surface oil rate + double m_gasRate; //< Surface gas rate For Field-unit, converted to [stb/day] to allign with oil and water. + double m_waterRate; //< Surface water rate }; //================================================================================================== From 338e51bced80304d891c9b65fae3e48f8dd69821 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 9 May 2017 10:14:02 +0200 Subject: [PATCH 085/157] Fishbones : Fix invalid start direction for lateral --- ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp index 732118f286..968cb4b6e0 100644 --- a/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp @@ -67,16 +67,16 @@ void RigFisbonesGeometry::computeLateralPositionAndOrientation(size_t subIndex, cvf::Vec3d position = rigWellPath->interpolatedPointAlongWellPath(measuredDepth); cvf::Mat4d buildAngleMat; - cvf::Vec3d lateralInitialDirection = cvf::Vec3d::Z_AXIS; + cvf::Vec3d lateralDirection; { + cvf::Vec3d lateralInitialDirection = cvf::Vec3d::Z_AXIS; cvf::Vec3d p1 = cvf::Vec3d::UNDEFINED; cvf::Vec3d p2 = cvf::Vec3d::UNDEFINED; rigWellPath->twoClosestPoints(position, &p1, &p2); CVF_ASSERT(!p1.isUndefined() && !p2.isUndefined()); - cvf::Vec3d lateralDirection; cvf::Vec3d alongWellPath = (p2 - p1).getNormalized(); if (RigFisbonesGeometry::closestMainAxis(alongWellPath) == cvf::Vec3d::Z_AXIS) @@ -109,7 +109,7 @@ void RigFisbonesGeometry::computeLateralPositionAndOrientation(size_t subIndex, } *startCoord = position; - *startDirection = lateralInitialDirection; + *startDirection = lateralDirection; *buildAngleMatrix = buildAngleMat; } From 04722305233c7ecc4d6e1f0ba7cc9fa0017897af Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 9 May 2017 13:35:06 +0200 Subject: [PATCH 086/157] #1473 Octave on Windows : Add Sleep before closing octave socket --- OctavePlugin/riSetActiveCellProperty.cpp | 7 +++++++ OctavePlugin/riSetGridProperty.cpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/OctavePlugin/riSetActiveCellProperty.cpp b/OctavePlugin/riSetActiveCellProperty.cpp index a079ccd0da..1aedda4c5f 100644 --- a/OctavePlugin/riSetActiveCellProperty.cpp +++ b/OctavePlugin/riSetActiveCellProperty.cpp @@ -88,6 +88,13 @@ void setEclipseProperty(const Matrix& propertyFrames, const QString &hostName, q { error("riSetActiveCellProperty : ResInsight refused to accept the data. Maybe the dimensions or porosity model is wrong"); } + +#ifdef WIN32 + // TODO: Due to synchronization issues seen on Windows 10, it is required to do a sleep here to be able to catch disconnect + // signals from the socket. No sleep causes the server to hang. + Sleep(100); +#endif //WIN32 + return; } diff --git a/OctavePlugin/riSetGridProperty.cpp b/OctavePlugin/riSetGridProperty.cpp index 3ef34adda4..890c9f2f51 100644 --- a/OctavePlugin/riSetGridProperty.cpp +++ b/OctavePlugin/riSetGridProperty.cpp @@ -110,6 +110,13 @@ void setEclipseProperty(const NDArray& propertyFrames, const QString &hostName, { error("riSetGridProperty : ResInsight refused to accept the data. Maybe the dimensions or porosity model is wrong.\n"); } + +#ifdef WIN32 + // TODO: Due to synchronization issues seen on Windows 10, it is required to do a sleep here to be able to catch disconnect + // signals from the socket. No sleep causes the server to hang. + Sleep(100); +#endif //WIN32 + return; } From bf704caa1672ffed2bca92f7d95ddc26a3f5f18e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 10 May 2017 12:19:46 +0200 Subject: [PATCH 087/157] #1475 Move well path import to own module --- .../FileInterface/CMakeLists_files.cmake | 2 + .../FileInterface/RifWellPathImporter.cpp | 386 ++++++++++++++++++ .../FileInterface/RifWellPathImporter.h | 77 ++++ .../ProjectDataModel/RimWellPath.cpp | 93 +---- .../ProjectDataModel/RimWellPath.h | 6 +- .../RimWellPathCollection.cpp | 226 +--------- .../ProjectDataModel/RimWellPathCollection.h | 32 +- 7 files changed, 494 insertions(+), 328 deletions(-) create mode 100644 ApplicationCode/FileInterface/RifWellPathImporter.cpp create mode 100644 ApplicationCode/FileInterface/RifWellPathImporter.h diff --git a/ApplicationCode/FileInterface/CMakeLists_files.cmake b/ApplicationCode/FileInterface/CMakeLists_files.cmake index b1dcb8274c..95fd893e9e 100644 --- a/ApplicationCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/FileInterface/CMakeLists_files.cmake @@ -19,6 +19,7 @@ ${CEE_CURRENT_LIST_DIR}RifReaderInterface.h ${CEE_CURRENT_LIST_DIR}RifReaderMockModel.h ${CEE_CURRENT_LIST_DIR}RifReaderSettings.h ${CEE_CURRENT_LIST_DIR}RifEclipseSummaryAddress.h +${CEE_CURRENT_LIST_DIR}RifWellPathImporter.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -36,6 +37,7 @@ ${CEE_CURRENT_LIST_DIR}RifReaderInterface.cpp ${CEE_CURRENT_LIST_DIR}RifReaderMockModel.cpp ${CEE_CURRENT_LIST_DIR}RifReaderSettings.cpp ${CEE_CURRENT_LIST_DIR}RifEclipseSummaryAddress.cpp +${CEE_CURRENT_LIST_DIR}RifWellPathImporter.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/FileInterface/RifWellPathImporter.cpp b/ApplicationCode/FileInterface/RifWellPathImporter.cpp new file mode 100644 index 0000000000..ebefc05b18 --- /dev/null +++ b/ApplicationCode/FileInterface/RifWellPathImporter.cpp @@ -0,0 +1,386 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RifWellPathImporter.h" + +#include "RifJsonEncodeDecode.h" + +#include + +#include + +#define ASCII_FILE_DEFAULT_START_INDEX 0 + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifWellPathImporter::canReadFile(const QString& filePath) +{ + QFileInfo fileInfo(filePath); + if (fileInfo.isFile() && fileInfo.exists()) + { + return true; + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifWellPathImporter::WellData RifWellPathImporter::readWellData(const QString& filePath, size_t indexInFile) +{ + CVF_ASSERT(canReadFile(filePath)); + + if (isJsonFile(filePath)) + { + return readJsonWellData(filePath); + } + else + { + return readAsciiWellData(filePath, indexInFile); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifWellPathImporter::WellData RifWellPathImporter::readWellData(const QString& filePath) +{ + return readWellData(filePath, ASCII_FILE_DEFAULT_START_INDEX); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifWellPathImporter::WellMetaData RifWellPathImporter::readWellMetaData(const QString& filePath, size_t indexInFile) +{ + CVF_ASSERT(canReadFile(filePath)); + + if (isJsonFile(filePath)) + { + return readJsonWellMetaData(filePath); + } + else + { + return readAsciiWellMetaData(filePath, indexInFile); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifWellPathImporter::WellMetaData RifWellPathImporter::readWellMetaData(const QString& filePath) +{ + return readWellMetaData(filePath, ASCII_FILE_DEFAULT_START_INDEX); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RifWellPathImporter::wellDataCount(const QString& filePath) +{ + if (isJsonFile(filePath)) + { + // Only support JSON files with single well data currently + return 1; + } + else + { + std::map >::iterator it = m_fileNameToWellDataGroupMap.find(filePath); + + // If we have the file in the map, assume it is already read. + if (it != m_fileNameToWellDataGroupMap.end()) + { + return it->second.size(); + } + + readAllAsciiWellData(filePath); + it = m_fileNameToWellDataGroupMap.find(filePath); + CVF_ASSERT(it != m_fileNameToWellDataGroupMap.end()); + + return it->second.size();; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifWellPathImporter::isJsonFile(const QString & filePath) +{ + QFileInfo fileInfo(filePath); + + if (fileInfo.suffix().compare("json") == 0) + { + return true; + } + else + { + return false; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifWellPathImporter::WellMetaData RifWellPathImporter::readJsonWellMetaData(const QString & filePath) +{ + ResInsightInternalJson::JsonReader jsonReader; + QMap jsonMap = jsonReader.decodeFile(filePath); + WellMetaData metadata; + + metadata.m_id = jsonMap["id"].toString(); + metadata.m_name = jsonMap["name"].toString(); + metadata.m_sourceSystem = jsonMap["sourceSystem"].toString(); + metadata.m_utmZone = jsonMap["utmZone"].toString(); + metadata.m_updateUser = jsonMap["updateUser"].toString(); + metadata.m_surveyType = jsonMap["surveyType"].toString(); + + // Convert updateDate from the following format: + // "Number of milliseconds elapsed since midnight Coordinated Universal Time (UTC) + // of January 1, 1970, not counting leap seconds" + QString updateDateStr = jsonMap["updateDate"].toString().trimmed(); + uint updateDateUint = updateDateStr.toULongLong() / 1000; // Should be within 32 bit, maximum number is 4294967295 which corresponds to year 2106 + metadata.m_updateDate.setTime_t(updateDateUint); + + return metadata; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifWellPathImporter::WellData RifWellPathImporter::readJsonWellData(const QString& filePath) +{ + ResInsightInternalJson::JsonReader jsonReader; + QMap jsonMap = jsonReader.decodeFile(filePath); + + double datumElevation = jsonMap["datumElevation"].toDouble(); + QList pathList = jsonMap["path"].toList(); + WellData wellData; + wellData.m_wellPathGeometry->setDatumElevation(datumElevation); + wellData.m_name = jsonMap["name"].toString(); + + foreach(QVariant point, pathList) + { + QMap coordinateMap = point.toMap(); + cvf::Vec3d vec3d(coordinateMap["east"].toDouble(), coordinateMap["north"].toDouble(), -(coordinateMap["tvd"].toDouble() - datumElevation)); + wellData.m_wellPathGeometry->m_wellPathPoints.push_back(vec3d); + double measuredDepth = coordinateMap["md"].toDouble(); + wellData.m_wellPathGeometry->m_measuredDepths.push_back(measuredDepth); + } + return wellData; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifWellPathImporter::readAllAsciiWellData(const QString& filePath) +{ + std::map >::iterator it = m_fileNameToWellDataGroupMap.find(filePath); + + // If we have the file in the map, assume it is already read. + if (it != m_fileNameToWellDataGroupMap.end()) + { + return; + } + + // Create the data container + std::vector& fileWellDataArray = m_fileNameToWellDataGroupMap[filePath]; + + std::ifstream stream(filePath.toLatin1().data()); + double x(HUGE_VAL), y(HUGE_VAL), tvd(HUGE_VAL), md(HUGE_VAL); + + bool hasReadWellPointInCurrentWell = false; + + while (stream.good()) + { + // First check if we can read a number + stream >> x; + if (stream.good()) // If we can, assume this line is a well point entry + { + stream >> y >> tvd >> md; + if (!stream.good()) + { + // -999 or otherwise to few numbers before some word + if (x != -999) + { + // Error in file: missing numbers at this line + + } + stream.clear(); + } + else + { + if (!fileWellDataArray.size()) + { + fileWellDataArray.push_back(RifWellPathImporter::WellData()); + fileWellDataArray.back().m_wellPathGeometry = new RigWellPath(); + } + + cvf::Vec3d wellPoint(x, y, -tvd); + fileWellDataArray.back().m_wellPathGeometry->m_wellPathPoints.push_back(wellPoint); + fileWellDataArray.back().m_wellPathGeometry->m_measuredDepths.push_back(md); + + x = HUGE_VAL; + y = HUGE_VAL; + tvd = HUGE_VAL; + md = HUGE_VAL; + + hasReadWellPointInCurrentWell = true; + } + } + else + { + // Could not read one double. + // we assume there is a comment line or a well path description + stream.clear(); + + std::string line; + std::getline(stream, line, '\n'); + // Skip possible comment lines (-- is used in eclipse, so Haakon Høgstøl considered it smart to skip these here as well) + // The first "-" is eaten by the stream >> x above + if (line.find("-") == 0 || line.find("#") == 0) + { + // Comment line, just ignore + } + else + { + // Find the first and the last position of any quotes (and do not care to match quotes) + size_t quoteStartIdx = line.find_first_of("'`´’‘"); + size_t quoteEndIdx = line.find_last_of("'`´’‘"); + + std::string wellName; + bool haveAPossibleWellStart = false; + + if (quoteStartIdx < line.size() -1) + { + // Extract the text between the quotes + wellName = line.substr(quoteStartIdx + 1, quoteEndIdx - 1 - quoteStartIdx); + haveAPossibleWellStart = true; + } + else if (quoteStartIdx > line.length()) + { + // We did not find any quotes + + // Supported alternatives are + // name + // wellname: + std::string lineLowerCase = line; + transform(lineLowerCase.begin(), lineLowerCase.end(), lineLowerCase.begin(), ::tolower); + + std::string tokenName = "name"; + std::size_t foundNameIdx = lineLowerCase.find(tokenName); + if (foundNameIdx != std::string::npos) + { + std::string tokenColon = ":"; + std::size_t foundColonIdx = lineLowerCase.find(tokenColon, foundNameIdx); + if (foundColonIdx != std::string::npos) + { + wellName = line.substr(foundColonIdx + tokenColon.length()); + } + else + { + wellName = line.substr(foundNameIdx + tokenName.length()); + } + + haveAPossibleWellStart = true; + } + else + { + // Interpret the whole line as the well name. + + QString name = line.c_str(); + if (!name.trimmed().isEmpty()) + { + wellName = name.trimmed().toStdString(); + haveAPossibleWellStart = true; + } + } + } + + if (haveAPossibleWellStart) + { + // Create a new Well data if we have read some data into the previous one. + // if not, just overwrite the name + if (hasReadWellPointInCurrentWell || fileWellDataArray.size() == 0) + { + fileWellDataArray.push_back(RifWellPathImporter::WellData()); + fileWellDataArray.back().m_wellPathGeometry = new RigWellPath(); + } + + QString name = wellName.c_str(); + if (!name.trimmed().isEmpty()) + { + // Do not overwrite the name aquired from a line above, if this line is empty + fileWellDataArray.back().m_name = name.trimmed(); + } + hasReadWellPointInCurrentWell = false; + } + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifWellPathImporter::WellData RifWellPathImporter::readAsciiWellData(const QString& filePath, size_t indexInFile) +{ + readAllAsciiWellData(filePath); + + std::map >::iterator it = m_fileNameToWellDataGroupMap.find(filePath); + + CVF_ASSERT(it != m_fileNameToWellDataGroupMap.end()); + + if (indexInFile < it->second.size()) + { + return it->second[indexInFile]; + } + else + { + // Error : The ascii well path file does not contain that many well paths + return RifWellPathImporter::WellData(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifWellPathImporter::WellMetaData RifWellPathImporter::readAsciiWellMetaData(const QString & filePath, size_t indexInFile) +{ + // No metadata in ASCII files + return WellMetaData(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifWellPathImporter::clear() +{ + m_fileNameToWellDataGroupMap.clear(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifWellPathImporter::removeFilePath(const QString& filePath) +{ + m_fileNameToWellDataGroupMap.erase(filePath); +} diff --git a/ApplicationCode/FileInterface/RifWellPathImporter.h b/ApplicationCode/FileInterface/RifWellPathImporter.h new file mode 100644 index 0000000000..dc24e90778 --- /dev/null +++ b/ApplicationCode/FileInterface/RifWellPathImporter.h @@ -0,0 +1,77 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigWellPath.h" + +#include "cvfObject.h" + +#include +#include +#include +#include + +//================================================================================================== +/// +/// +//================================================================================================== +class RifWellPathImporter +{ +public: + struct WellData + { + QString m_name; + cvf::ref m_wellPathGeometry; + }; + + struct WellMetaData + { + QString m_name; + QString m_id; + QString m_sourceSystem; + QString m_utmZone; + QString m_updateUser; + QString m_surveyType; + QDateTime m_updateDate; + }; + + WellData readWellData(const QString& filePath, size_t indexInFile); + WellData readWellData(const QString& filePath); + WellMetaData readWellMetaData(const QString& filePath, size_t indexInFile); + WellMetaData readWellMetaData(const QString& filePath); + size_t wellDataCount(const QString& filePath); + + static bool canReadFile(const QString& filePath); + + void clear(); + void removeFilePath(const QString& filePath); + +private: + WellData readJsonWellData(const QString& filePath); + WellMetaData readJsonWellMetaData(const QString& filePath); + WellData readAsciiWellData(const QString& filePath, size_t indexInFile); + WellMetaData readAsciiWellMetaData(const QString& filePath, size_t indexInFile); + void readAllAsciiWellData(const QString& filePath); + + inline bool isJsonFile(const QString& filePath); + + std::map > m_fileNameToWellDataGroupMap; +}; diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index fea8f08a74..73820fa281 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -20,13 +20,12 @@ #include "RimWellPath.h" -#include "RifJsonEncodeDecode.h" +#include "RifWellPathImporter.h" #include "RigWellPath.h" #include "RimMainPlotCollection.h" #include "RimProject.h" -#include "RimProject.h" #include "RimTools.h" #include "RimWellLogFile.h" #include "RimWellLogPlotCollection.h" @@ -203,27 +202,28 @@ caf::PdmFieldHandle* RimWellPath::objectToggleField() //-------------------------------------------------------------------------------------------------- /// Read JSON or ascii file containing well path data //-------------------------------------------------------------------------------------------------- -bool RimWellPath::readWellPathFile(QString* errorMessage, RifWellPathAsciiFileReader* asciiReader) +bool RimWellPath::readWellPathFile(QString* errorMessage, RifWellPathImporter* wellPathImporter) { - QFileInfo fileInf(filepath()); - - if (fileInf.isFile() && fileInf.exists()) + if (wellPathImporter->canReadFile(filepath())) { - if (fileInf.suffix().compare("json") == 0) - { - this->readJsonWellPathFile(); - } - else - { - this->readAsciiWellPathFile(asciiReader); - } + RifWellPathImporter::WellData wellData = wellPathImporter->readWellData(filepath()); + RifWellPathImporter::WellMetaData wellMetaData = wellPathImporter->readWellMetaData(filepath()); + // General well info + name = wellData.m_name; + id = wellMetaData.m_id; + sourceSystem = wellMetaData.m_sourceSystem; + utmZone = wellMetaData.m_utmZone; + updateUser = wellMetaData.m_updateUser; + setSurveyType(wellMetaData.m_surveyType); + updateDate = wellMetaData.m_updateDate.toString("d MMMM yyyy"); + + m_wellPath = wellData.m_wellPathGeometry; return true; } else { if (errorMessage) (*errorMessage) = "Could not find the well path file: " + filepath(); - return false; } } @@ -236,69 +236,6 @@ void RimWellPath::setWellPathGeometry(RigWellPath* wellPathModel) m_wellPath = wellPathModel; } -//-------------------------------------------------------------------------------------------------- -/// Read JSON file containing well path data -//-------------------------------------------------------------------------------------------------- -void RimWellPath::readJsonWellPathFile() -{ - RigWellPath* wellPathGeom = new RigWellPath(); - ResInsightInternalJson::JsonReader jsonReader; - QMap jsonMap = jsonReader.decodeFile(filepath); - - // General well info - - name = jsonMap["name"].toString(); - id = jsonMap["id"].toString(); - sourceSystem = jsonMap["sourceSystem"].toString(); - utmZone = jsonMap["utmZone"].toString(); - updateUser = jsonMap["updateUser"].toString(); - - setSurveyType(jsonMap["surveyType"].toString()); - - // Convert updateDate from the following format: - // "Number of milliseconds elapsed since midnight Coordinated Universal Time (UTC) - // of January 1, 1970, not counting leap seconds" - - QString updateDateStr = jsonMap["updateDate"].toString().trimmed(); - uint updateDateUint = updateDateStr.toULongLong() / 1000; // should be within 32 bit, maximum number is 4294967295 which corresponds to year 2106 - QDateTime updateDateTime; - updateDateTime.setTime_t(updateDateUint); - - updateDate = updateDateTime.toString("d MMMM yyyy"); - - // Well path points - - double datumElevation = jsonMap["datumElevation"].toDouble(); - wellPathGeom->setDatumElevation(datumElevation); - - QList pathList = jsonMap["path"].toList(); - foreach (QVariant point, pathList) - { - QMap coordinateMap = point.toMap(); - cvf::Vec3d vec3d(coordinateMap["east"].toDouble(), coordinateMap["north"].toDouble(), -(coordinateMap["tvd"].toDouble() - datumElevation)); - wellPathGeom->m_wellPathPoints.push_back(vec3d); - - double measuredDepth = coordinateMap["md"].toDouble(); - wellPathGeom->m_measuredDepths.push_back(measuredDepth); - } - - //jsonReader.dumpToFile(wellPathGeom->m_wellPathPoints, "c:\\temp\\jsonpoints.txt"); - setWellPathGeometry(wellPathGeom); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellPath::readAsciiWellPathFile(RifWellPathAsciiFileReader* asciiReader) -{ - CVF_ASSERT(asciiReader); - - RifWellPathAsciiFileReader::WellData wpData = asciiReader->readWellData(filepath(), wellPathIndexInFile()); - this->name = wpData.m_name; - - setWellPathGeometry(wpData.m_wellPathGeometry.p()); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index e9aa47fd93..6becb12a4b 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -32,7 +32,7 @@ #include "cafPdmChildArrayField.h" #include "cvfObject.h" -class RifWellPathAsciiFileReader; +class RifWellPathImporter; class RigWellPath; class RimProject; class RimWellLogFile; @@ -77,7 +77,7 @@ public: RivWellPathPartMgr* partMgr(); - bool readWellPathFile(QString * errorMessage, RifWellPathAsciiFileReader* asciiReader); + bool readWellPathFile(QString * errorMessage, RifWellPathImporter* wellPathImporter); void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath); double combinedScaleFactor() const; @@ -85,8 +85,6 @@ public: private: void setWellPathGeometry(RigWellPath* wellPathModel); - void readJsonWellPathFile(); - void readAsciiWellPathFile(RifWellPathAsciiFileReader* asciiReader); QString surveyType() { return m_surveyType; } void setSurveyType(QString surveyType); diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp index 2b3d3082e4..e243bdccbd 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp @@ -33,6 +33,8 @@ #include "RivWellPathCollectionPartMgr.h" +#include "RifWellPathImporter.h" + #include "cafPdmUiEditorHandle.h" #include "cafProgressInfo.h" @@ -87,7 +89,7 @@ RimWellPathCollection::RimWellPathCollection() m_wellPathCollectionPartManager = new RivWellPathCollectionPartMgr(this); - m_asciiFileReader = new RifWellPathAsciiFileReader; + m_wellPathImporter = new RifWellPathImporter; } @@ -97,7 +99,7 @@ RimWellPathCollection::RimWellPathCollection() RimWellPathCollection::~RimWellPathCollection() { wellPaths.deleteAllChildObjects(); - delete m_asciiFileReader; + delete m_wellPathImporter; } @@ -122,7 +124,7 @@ void RimWellPathCollection::readWellPathFiles() if (!wellPaths[wpIdx]->filepath().isEmpty()) { QString errorMessage; - if (!wellPaths[wpIdx]->readWellPathFile(&errorMessage, this->asciiFileReader())) + if (!wellPaths[wpIdx]->readWellPathFile(&errorMessage, m_wellPathImporter)) { QMessageBox::warning(RiuMainWindow::instance(), "File open error", @@ -198,7 +200,7 @@ void RimWellPathCollection::addWellPaths( QStringList filePaths ) else { // Create Well path objects for all the paths in the assumed ascii file - size_t wellPathCount = this->m_asciiFileReader->wellDataCount(filePath); + size_t wellPathCount = m_wellPathImporter->wellDataCount(filePath); for (size_t i = 0; i < wellPathCount; ++i) { RimWellPath* wellPath = new RimWellPath(); @@ -224,7 +226,7 @@ void RimWellPathCollection::readAndAddWellPaths(std::vector& wellP for (size_t wpIdx = 0; wpIdx < wellPathArray.size(); wpIdx++) { RimWellPath* wellPath = wellPathArray[wpIdx]; - wellPath->readWellPathFile(NULL, this->asciiFileReader()); + wellPath->readWellPathFile(NULL, m_wellPathImporter); progress.setProgressDescription(QString("Reading file %1").arg(wellPath->name)); @@ -234,7 +236,7 @@ void RimWellPathCollection::readAndAddWellPaths(std::vector& wellP { existingWellPath->filepath = wellPath->filepath; existingWellPath->wellPathIndexInFile = wellPath->wellPathIndexInFile; - existingWellPath->readWellPathFile(NULL, this->asciiFileReader()); + existingWellPath->readWellPathFile(NULL, m_wellPathImporter); delete wellPath; } @@ -345,7 +347,7 @@ void RimWellPathCollection::deleteAllWellPaths() { wellPaths.deleteAllChildObjects(); - m_asciiFileReader->clear(); + m_wellPathImporter->clear(); } //-------------------------------------------------------------------------------------------------- @@ -369,7 +371,7 @@ void RimWellPathCollection::removeWellPath(RimWellPath* wellPath) { // One file can have multiple well paths // If no other well paths are referencing the filepath, remove cached data from the file reader - m_asciiFileReader->removeFilePath(wellPath->filepath); + m_wellPathImporter->removeFilePath(wellPath->filepath); } } @@ -390,211 +392,3 @@ void RimWellPathCollection::sortWellsByName() { std::sort(wellPaths.begin(), wellPaths.end(), lessWellPath); } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RifWellPathAsciiFileReader::readAllWellData(QString filePath) -{ - std::map >::iterator it = m_fileNameToWellDataGroupMap.find(filePath); - - // If we have the file in the map, assume it is already read. - if (it != m_fileNameToWellDataGroupMap.end()) - { - return; - } - - // Create the data container - std::vector& fileWellDataArray = m_fileNameToWellDataGroupMap[filePath]; - - std::ifstream stream(filePath.toLatin1().data()); - double x(HUGE_VAL), y(HUGE_VAL), tvd(HUGE_VAL), md(HUGE_VAL); - - bool hasReadWellPointInCurrentWell = false; - - while (stream.good()) - { - // First check if we can read a number - stream >> x; - if (stream.good()) // If we can, assume this line is a well point entry - { - stream >> y >> tvd >> md; - if (!stream.good()) - { - // -999 or otherwise to few numbers before some word - if (x != -999) - { - // Error in file: missing numbers at this line - - } - stream.clear(); - } - else - { - if (!fileWellDataArray.size()) - { - fileWellDataArray.push_back(WellData()); - fileWellDataArray.back().m_wellPathGeometry = new RigWellPath(); - } - - cvf::Vec3d wellPoint(x, y, -tvd); - fileWellDataArray.back().m_wellPathGeometry->m_wellPathPoints.push_back(wellPoint); - fileWellDataArray.back().m_wellPathGeometry->m_measuredDepths.push_back(md); - - x = HUGE_VAL; - y = HUGE_VAL; - tvd = HUGE_VAL; - md = HUGE_VAL; - - hasReadWellPointInCurrentWell = true; - } - } - else - { - // Could not read one double. - // we assume there is a comment line or a well path description - stream.clear(); - - std::string line; - std::getline(stream, line, '\n'); - // Skip possible comment lines (-- is used in eclipse, so Haakon Høgstøl considered it smart to skip these here as well) - // The first "-" is eaten by the stream >> x above - if (line.find("-") == 0 || line.find("#") == 0) - { - // Comment line, just ignore - } - else - { - // Find the first and the last position of any quotes (and do not care to match quotes) - size_t quoteStartIdx = line.find_first_of("'`´’‘"); - size_t quoteEndIdx = line.find_last_of("'`´’‘"); - - std::string wellName; - bool haveAPossibleWellStart = false; - - if (quoteStartIdx < line.size() -1) - { - // Extract the text between the quotes - wellName = line.substr(quoteStartIdx + 1, quoteEndIdx - 1 - quoteStartIdx); - haveAPossibleWellStart = true; - } - else if (quoteStartIdx > line.length()) - { - // We did not find any quotes - - // Supported alternatives are - // name - // wellname: - std::string lineLowerCase = line; - transform(lineLowerCase.begin(), lineLowerCase.end(), lineLowerCase.begin(), ::tolower); - - std::string tokenName = "name"; - std::size_t foundNameIdx = lineLowerCase.find(tokenName); - if (foundNameIdx != std::string::npos) - { - std::string tokenColon = ":"; - std::size_t foundColonIdx = lineLowerCase.find(tokenColon, foundNameIdx); - if (foundColonIdx != std::string::npos) - { - wellName = line.substr(foundColonIdx + tokenColon.length()); - } - else - { - wellName = line.substr(foundNameIdx + tokenName.length()); - } - - haveAPossibleWellStart = true; - } - else - { - // Interpret the whole line as the well name. - - QString name = line.c_str(); - if (!name.trimmed().isEmpty()) - { - wellName = name.trimmed().toStdString(); - haveAPossibleWellStart = true; - } - } - } - - if (haveAPossibleWellStart) - { - // Create a new Well data if we have read some data into the previous one. - // if not, just overwrite the name - if (hasReadWellPointInCurrentWell || fileWellDataArray.size() == 0) - { - fileWellDataArray.push_back(WellData()); - fileWellDataArray.back().m_wellPathGeometry = new RigWellPath(); - } - - QString name = wellName.c_str(); - if (!name.trimmed().isEmpty()) - { - // Do not overwrite the name aquired from a line above, if this line is empty - fileWellDataArray.back().m_name = name.trimmed(); - } - hasReadWellPointInCurrentWell = false; - } - } - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RifWellPathAsciiFileReader::WellData RifWellPathAsciiFileReader::readWellData(QString filePath, int indexInFile) -{ - this->readAllWellData(filePath); - - std::map >::iterator it = m_fileNameToWellDataGroupMap.find(filePath); - - CVF_ASSERT(it != m_fileNameToWellDataGroupMap.end()); - - if (indexInFile < static_cast(it->second.size())) - { - return it->second[indexInFile]; - } - else - { - // Error : The ascii well path file does not contain that many well paths - return WellData(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -size_t RifWellPathAsciiFileReader::wellDataCount(QString filePath) -{ - std::map >::iterator it = m_fileNameToWellDataGroupMap.find(filePath); - - // If we have the file in the map, assume it is already read. - if (it != m_fileNameToWellDataGroupMap.end()) - { - return it->second.size(); - } - - this->readAllWellData(filePath); - it = m_fileNameToWellDataGroupMap.find(filePath); - CVF_ASSERT(it != m_fileNameToWellDataGroupMap.end()); - - return it->second.size();; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RifWellPathAsciiFileReader::clear() -{ - m_fileNameToWellDataGroupMap.clear(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RifWellPathAsciiFileReader::removeFilePath(const QString& filePath) -{ - m_fileNameToWellDataGroupMap.erase(filePath); -} diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.h b/ApplicationCode/ProjectDataModel/RimWellPathCollection.h index 279b56d00a..b6281759de 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.h @@ -34,7 +34,7 @@ #include class RivWellPathCollectionPartMgr; -class RifWellPathAsciiFileReader; +class RifWellPathImporter; class RimWellPath; class RimProject; class RigWellPath; @@ -84,8 +84,6 @@ public: void removeWellPath(RimWellPath* wellPath); void deleteAllWellPaths(); - RifWellPathAsciiFileReader* asciiFileReader() {return m_asciiFileReader;} - RimWellPath* wellPathByName(const QString& wellPathName) const; void addWellLogs(const QStringList& filePaths); @@ -104,31 +102,5 @@ private: cvf::ref m_wellPathCollectionPartManager; - RifWellPathAsciiFileReader* m_asciiFileReader; -}; - - -//================================================================================================== -/// -/// -//================================================================================================== -class RifWellPathAsciiFileReader -{ -public: - struct WellData - { - QString m_name; - cvf::ref m_wellPathGeometry; - }; - - WellData readWellData(QString filePath, int indexInFile); - size_t wellDataCount(QString filePath); - - void clear(); - void removeFilePath(const QString& filePath); - -private: - void readAllWellData(QString filePath); - - std::map > m_fileNameToWellDataGroupMap; + RifWellPathImporter* m_wellPathImporter; }; From 34f00b07ef2f5c896ce1c1ea40cd86f1fbeb63c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 10 May 2017 16:52:51 +0200 Subject: [PATCH 088/157] #1467 Data structure for completions --- .../ProjectDataModel/CMakeLists_files.cmake | 4 + .../RimWellPathCompletion.cpp | 82 +++++++++++++ .../ProjectDataModel/RimWellPathCompletion.h | 62 ++++++++++ .../RimWellPathCompletionCollection.cpp | 108 ++++++++++++++++++ .../RimWellPathCompletionCollection.h | 48 ++++++++ 5 files changed, 304 insertions(+) create mode 100644 ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimWellPathCompletion.h create mode 100644 ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.h diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 397883b2ab..8241efe4f1 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -31,6 +31,8 @@ ${CEE_CURRENT_LIST_DIR}RimEclipseWell.h ${CEE_CURRENT_LIST_DIR}RimEclipseWellCollection.h ${CEE_CURRENT_LIST_DIR}RimWellPath.h ${CEE_CURRENT_LIST_DIR}RimWellPathCollection.h +${CEE_CURRENT_LIST_DIR}RimWellPathCompletion.h +${CEE_CURRENT_LIST_DIR}RimWellPathCompletionCollection.h ${CEE_CURRENT_LIST_DIR}RimScriptCollection.h ${CEE_CURRENT_LIST_DIR}RimEclipseStatisticsCase.h ${CEE_CURRENT_LIST_DIR}RimEclipseStatisticsCaseCollection.h @@ -119,6 +121,8 @@ ${CEE_CURRENT_LIST_DIR}RimEclipseWell.cpp ${CEE_CURRENT_LIST_DIR}RimEclipseWellCollection.cpp ${CEE_CURRENT_LIST_DIR}RimWellPath.cpp ${CEE_CURRENT_LIST_DIR}RimWellPathCollection.cpp +${CEE_CURRENT_LIST_DIR}RimWellPathCompletion.cpp +${CEE_CURRENT_LIST_DIR}RimWellPathCompletionCollection.cpp ${CEE_CURRENT_LIST_DIR}RimScriptCollection.cpp ${CEE_CURRENT_LIST_DIR}RimEclipseStatisticsCase.cpp ${CEE_CURRENT_LIST_DIR}RimEclipseStatisticsCaseCollection.cpp diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp new file mode 100644 index 0000000000..28ca580f16 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp @@ -0,0 +1,82 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimWellPathCompletion.h" + +#include "RimProject.h" + +#include "cafPdmUiListEditor.h" + +CAF_PDM_SOURCE_INIT(RimWellPathCompletion, "WellPathCompletion"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPathCompletion::RimWellPathCompletion() +{ + CAF_PDM_InitObject("WellPathCompletion", ":/Well.png", "", ""); + CAF_PDM_InitFieldNoDefault(&m_coordinates, "Coordinates", "Coordinates", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_measuredDepths, "MeasuredDepth", "MeasuredDepth", "", "", ""); + m_measuredDepths.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName()); + m_name.uiCapability()->setUiHidden(true); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPathCompletion::~RimWellPathCompletion() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathCompletion::setCoordinates(std::vector< cvf::Vec3d > coordinates) +{ + m_coordinates = coordinates; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathCompletion::setMeasuredDepths(std::vector< double > measuredDepths) +{ + m_measuredDepths = measuredDepths; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathCompletion::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + RimProject* proj; + this->firstAncestorOrThisOfType(proj); + if (proj) proj->createDisplayModelAndRedrawAllViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathCompletion::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + caf::PdmUiGroup* geometryGroup = uiOrdering.addNewGroup("Geometry"); + geometryGroup->add(&m_coordinates); + geometryGroup->add(&m_measuredDepths); +} diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h new file mode 100644 index 0000000000..60fe5f6177 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h @@ -0,0 +1,62 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimCheckableNamedObject.h" + +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPointer.h" +#include "cafPdmChildField.h" +#include "cafAppEnum.h" + +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" +#include "cafPdmChildArrayField.h" +#include "cafPdmFieldCvfVec3d.h" + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfVector3.h" + +//================================================================================================== +/// +/// +//================================================================================================== +class RimWellPathCompletion : public RimCheckableNamedObject +{ + CAF_PDM_HEADER_INIT; +public: + + RimWellPathCompletion(); + virtual ~RimWellPathCompletion(); + + virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + virtual void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + + void setCoordinates(std::vector< cvf::Vec3d > coordinates); + void setMeasuredDepths(std::vector< double > measuredDepths); + + std::vector< cvf::Vec3d > coordinates() { return m_coordinates(); } + std::vector< double > measuredDepths() { return m_measuredDepths(); } +private: + caf::PdmField< std::vector< cvf::Vec3d> > m_coordinates; + caf::PdmField< std::vector< double > > m_measuredDepths; +}; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.cpp new file mode 100644 index 0000000000..7ad44f309f --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.cpp @@ -0,0 +1,108 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimWellPathCompletionCollection.h" + +#include "RimEclipseWell.h" +#include "RimWellPathCompletion.h" +#include "RimView.h" +#include "RimProject.h" + +#include "RigWellPath.h" + +#include "RifWellPathImporter.h" + +#include "RiuMainWindow.h" + + +CAF_PDM_SOURCE_INIT(RimWellPathCompletionCollection, "WellPathCompletionCollection"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPathCompletionCollection::RimWellPathCompletionCollection() +{ + CAF_PDM_InitObject("WellPathCompletions", ":/WellCollection.png", "", ""); + + m_name.uiCapability()->setUiHidden(true); + m_name = "Completions"; + + CAF_PDM_InitFieldNoDefault(&m_completions, "Completions", "WellPathCompletions", "", "", ""); + m_completions.uiCapability()->setUiHidden(true); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPathCompletionCollection::~RimWellPathCompletionCollection() +{ + m_completions.deleteAllChildObjects(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathCompletionCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + RimProject* proj; + this->firstAncestorOrThisOfTypeAsserted(proj); + proj->createDisplayModelAndRedrawAllViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathCompletionCollection::appendCompletion(RimWellPathCompletion* completion) +{ + m_completions.push_back(completion); + + updateConnectedEditors(); + RiuMainWindow::instance()->selectAsCurrentItem(completion); + + RimView* rimView = NULL; + firstAncestorOrThisOfType(rimView); + if (rimView) + { + rimView->scheduleCreateDisplayModelAndRedraw(); + } + + uiCapability()->setUiHidden(!m_completions.empty()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPathCompletionCollection::importCompletionsFromFile(const QList filePaths) +{ + RifWellPathImporter wellPathImporter; + + foreach(const QString& filePath, filePaths) { + size_t wellDataCount = wellPathImporter.wellDataCount(filePath); + + for (size_t i = 0; i < wellDataCount; ++i) + { + RifWellPathImporter::WellData wellData = wellPathImporter.readWellData(filePath, i); + RimWellPathCompletion* wellCompletion = new RimWellPathCompletion(); + wellCompletion->setName(wellData.m_name); + wellCompletion->setCoordinates(wellData.m_wellPathGeometry->m_wellPathPoints); + wellCompletion->setMeasuredDepths(wellData.m_wellPathGeometry->m_measuredDepths); + appendCompletion(wellCompletion); + } + } +} diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.h b/ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.h new file mode 100644 index 0000000000..48c562e70b --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.h @@ -0,0 +1,48 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimCheckableNamedObject.h" +#include "RimWellPathCompletion.h" + +#include "cafPdmObject.h" +#include "cafPdmChildArrayField.h" +#include "cafPdmField.h" + +//================================================================================================== +// +// +// +//================================================================================================== +class RimWellPathCompletionCollection : public RimCheckableNamedObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimWellPathCompletionCollection(); + ~RimWellPathCompletionCollection(); + + void appendCompletion(RimWellPathCompletion* completion); + void importCompletionsFromFile(const QList filePaths); + + void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); + + caf::PdmChildArrayField m_completions; +}; From 15bac1b050c50f9d58d7e2fe0771ad147a599b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 10 May 2017 17:09:54 +0200 Subject: [PATCH 089/157] #1468 New feature 'Import Completions' --- .../WellPathCommands/CMakeLists_files.cmake | 2 + ...icWellPathImportCompletionsFileFeature.cpp | 92 +++++++++++++++++++ .../RicWellPathImportCompletionsFileFeature.h | 43 +++++++++ .../RimContextCommandBuilder.cpp | 1 + .../ProjectDataModel/RimWellPath.cpp | 21 +++++ .../ProjectDataModel/RimWellPath.h | 3 + 6 files changed, 162 insertions(+) create mode 100644 ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp create mode 100644 ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h diff --git a/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake index b249623bc5..063a266700 100644 --- a/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake @@ -6,6 +6,7 @@ endif() set (SOURCE_GROUP_HEADER_FILES ${CEE_CURRENT_LIST_DIR}RicWellPathDeleteFeature.h +${CEE_CURRENT_LIST_DIR}RicWellPathImportCompletionsFileFeature.h ${CEE_CURRENT_LIST_DIR}RicWellPathsImportFileFeature.h ${CEE_CURRENT_LIST_DIR}RicWellPathsImportSsihubFeature.h ${CEE_CURRENT_LIST_DIR}RicWellPathViewerEventHandler.h @@ -13,6 +14,7 @@ ${CEE_CURRENT_LIST_DIR}RicWellPathViewerEventHandler.h set (SOURCE_GROUP_SOURCE_FILES ${CEE_CURRENT_LIST_DIR}RicWellPathDeleteFeature.cpp +${CEE_CURRENT_LIST_DIR}RicWellPathImportCompletionsFileFeature.cpp ${CEE_CURRENT_LIST_DIR}RicWellPathsImportFileFeature.cpp ${CEE_CURRENT_LIST_DIR}RicWellPathsImportSsihubFeature.cpp ${CEE_CURRENT_LIST_DIR}RicWellPathViewerEventHandler.cpp diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp new file mode 100644 index 0000000000..d1e319471f --- /dev/null +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp @@ -0,0 +1,92 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicWellPathImportCompletionsFileFeature.h" + +#include "RiaApplication.h" + +#include "RimProject.h" +#include "RimWellPath.h" +#include "RimWellPathCompletionCollection.h" + +#include "RiuMainWindow.h" + +#include "cafSelectionManager.h" + +#include +#include + +namespace caf +{ + CAF_CMD_SOURCE_INIT(RicWellPathImportCompletionsFileFeature, "RicWellPathImportCompletionsFileFeature"); + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicWellPathImportCompletionsFileFeature::isCommandEnabled() +{ + std::vector objects; + caf::SelectionManager::instance()->objectsByType(&objects); + + if (objects.size() == 1) { + return true; + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathImportCompletionsFileFeature::onActionTriggered(bool isChecked) +{ + std::vector objects; + caf::SelectionManager::instance()->objectsByType(&objects); + + CVF_ASSERT(objects.size() == 1); + + // Open dialog box to select well path files + RiaApplication* app = RiaApplication::instance(); + QString defaultDir = app->lastUsedDialogDirectory("WELLPATH_DIR"); + QStringList wellPathFilePaths = QFileDialog::getOpenFileNames(RiuMainWindow::instance(), "Import Well Path Completions", defaultDir, "Well Path Completions (*.json *.asc *.asci *.ascii *.dev);;All Files (*.*)"); + + if (wellPathFilePaths.size() < 1) return; + + // Remember the path to next time + app->setLastUsedDialogDirectory("WELLPATH_DIR", QFileInfo(wellPathFilePaths.last()).absolutePath()); + + objects[0]->m_completionCollection()->importCompletionsFromFile(wellPathFilePaths); + + if (app->project()) + { + app->project()->createDisplayModelAndRedrawAllViews(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathImportCompletionsFileFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("Import Completions from File"); + actionToSetup->setIcon(QIcon(":/Well.png")); +} + +} // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h new file mode 100644 index 0000000000..1967c04d89 --- /dev/null +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +namespace caf +{ + +//================================================================================================== +/// +//================================================================================================== +class RicWellPathImportCompletionsFileFeature : public CmdFeature +{ + CAF_CMD_HEADER_INIT; +protected: + + // Overrides + virtual bool isCommandEnabled(); + virtual void onActionTriggered( bool isChecked ); + virtual void setupActionLook( QAction* actionToSetup ); +}; + + + +} // end namespace caf diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 29e3f8564e..045956893a 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -397,6 +397,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection() commandIds << "RicNewFishbonesSubsFeature"; commandIds << "RicExportFishbonesLateralsFeature"; + commandIds << "RicWellPathImportCompletionsFileFeature"; // Work in progress -- End diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index 73820fa281..d29ac75678 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -30,6 +30,7 @@ #include "RimWellLogFile.h" #include "RimWellLogPlotCollection.h" #include "RimWellPathCollection.h" +#include "RimWellPathCompletionCollection.h" #include "RimFishbonesMultipleSubs.h" @@ -37,6 +38,8 @@ #include "RivWellPathPartMgr.h" +#include "cafPdmUiTreeOrdering.h" + #include #include #include @@ -98,6 +101,10 @@ RimWellPath::RimWellPath() CAF_PDM_InitField(&wellPathRadiusScaleFactor, "WellPathRadiusScale", 1.0, "Well path radius scale", "", "", ""); CAF_PDM_InitField(&wellPathColor, "WellPathColor", cvf::Color3f(0.999f, 0.333f, 0.999f), "Well path color", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&m_completionCollection, "Completions", "Completions", "", "", ""); + m_completionCollection = new RimWellPathCompletionCollection; + m_completionCollection.uiCapability()->setUiHidden(true); CAF_PDM_InitFieldNoDefault(&m_wellLogFile, "WellLogFile", "Well Log File", "", "", ""); m_wellLogFile.uiCapability()->setUiHidden(true); @@ -270,6 +277,20 @@ void RimWellPath::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiO } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPath::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName) +{ + uiTreeOrdering.skipRemainingChildren(true); + uiTreeOrdering.add(&m_wellLogFile); + if (!m_completionCollection->m_completions.empty()) + { + uiTreeOrdering.add(&m_completionCollection); + } + uiTreeOrdering.add(&fishbonesSubs); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index 6becb12a4b..4c33bb802a 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -36,6 +36,7 @@ class RifWellPathImporter; class RigWellPath; class RimProject; class RimWellLogFile; +class RimWellPathCompletionCollection; class RivWellPathPartMgr; class RimFishbonesMultipleSubs; @@ -71,6 +72,7 @@ public: caf::PdmField wellPathRadiusScaleFactor; caf::PdmChildField m_wellLogFile; + caf::PdmChildField m_completionCollection; RigWellPath* wellPathGeometry(); caf::PdmChildArrayField fishbonesSubs; @@ -89,6 +91,7 @@ private: void setSurveyType(QString surveyType); virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ); + virtual void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName) override; bool isStoredInCache(); QString getCacheFileName(); From b81150829a2eb2c1d31736d100075ee35c6be998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 10 May 2017 17:10:23 +0200 Subject: [PATCH 090/157] #1471 Completions visualization --- .../RivFishbonesSubsPartMgr.cpp | 50 ++----------------- .../RivFishbonesSubsPartMgr.h | 1 - .../RivPipeGeometryGenerator.cpp | 42 ++++++++++++++++ .../RivPipeGeometryGenerator.h | 4 ++ .../ModelVisualization/RivWellPathPartMgr.cpp | 36 +++++++++++++ .../ModelVisualization/RivWellPathPartMgr.h | 1 + 6 files changed, 87 insertions(+), 47 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp index b3bf2ebb56..f8ccac44e2 100644 --- a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp @@ -102,56 +102,14 @@ void RivFishbonesSubsPartMgr::buildParts(caf::DisplayCoordTransform* displayCoor displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(domainCoord)); } - cylinderWithCenterLineParts(&m_parts, displayCoords, wellPath->wellPathColor(), wellPath->combinedScaleFactor() * characteristicCellSize * 0.5); - - cvf::ref objectSourceInfo = new RivObjectSourceInfo(m_rimFishbonesSubs); - - for (auto p : m_parts) - { - p->setSourceInfo(objectSourceInfo.p()); - } + geoGenerator.cylinderWithCenterLineParts(&m_parts, displayCoords, wellPath->wellPathColor(), wellPath->combinedScaleFactor() * characteristicCellSize * 0.5); } } -} -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivFishbonesSubsPartMgr::cylinderWithCenterLineParts(cvf::Collection* destinationParts, const std::vector& centerCoords, const cvf::Color3f& color, double radius) -{ - cvf::ref geoGenerator = new RivPipeGeometryGenerator; - geoGenerator->setRadius(radius); - geoGenerator->setCrossSectionVertexCount(12); - - cvf::ref cvfCoords = new cvf::Vec3dArray(centerCoords); - geoGenerator->setPipeCenterCoords(cvfCoords.p()); - - cvf::ref surfaceGeo = geoGenerator->createPipeSurface(); - if (surfaceGeo.notNull()) + cvf::ref objectSourceInfo = new RivObjectSourceInfo(m_rimFishbonesSubs); + for (auto part : m_parts) { - cvf::Part* part = new cvf::Part; - part->setDrawable(surfaceGeo.p()); - - caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(color), caf::PO_1); - cvf::ref eff = surfaceGen.generateCachedEffect(); - - part->setEffect(eff.p()); - - destinationParts->push_back(part); - } - - cvf::ref centerLineGeo = geoGenerator->createCenterLine(); - if (centerLineGeo.notNull()) - { - cvf::Part* part = new cvf::Part; - part->setDrawable(centerLineGeo.p()); - - caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(color), caf::PO_1); - cvf::ref eff = surfaceGen.generateCachedEffect(); - - part->setEffect(eff.p()); - - destinationParts->push_back(part); + part->setSourceInfo(objectSourceInfo.p()); } } diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h index 3a01ce97be..9481ba5e1e 100644 --- a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h @@ -59,7 +59,6 @@ public: private: void buildParts(caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize); - static void cylinderWithCenterLineParts(cvf::Collection* destinationParts, const std::vector& centerCoords, const cvf::Color3f& color, double radius); private: caf::PdmPointer m_rimFishbonesSubs; diff --git a/ApplicationCode/ModelVisualization/RivPipeGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivPipeGeometryGenerator.cpp index fb3472b98f..aedbb49527 100644 --- a/ApplicationCode/ModelVisualization/RivPipeGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivPipeGeometryGenerator.cpp @@ -21,6 +21,8 @@ #include "RivPipeGeometryGenerator.h" +#include "RivObjectSourceInfo.h" + #include "cafEffectGenerator.h" #include "cvfDrawableGeo.h" #include "cvfPlane.h" @@ -603,3 +605,43 @@ void RivPipeGeometryGenerator::setFirstSegmentIndex(size_t segmentIndex) m_firstSegmentIndex = segmentIndex; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivPipeGeometryGenerator::cylinderWithCenterLineParts(cvf::Collection* destinationParts, const std::vector& centerCoords, const cvf::Color3f& color, double radius) +{ + setRadius(radius); + setCrossSectionVertexCount(12); + + cvf::ref cvfCoords = new cvf::Vec3dArray(centerCoords); + setPipeCenterCoords(cvfCoords.p()); + + cvf::ref surfaceGeo = createPipeSurface(); + if (surfaceGeo.notNull()) + { + cvf::Part* part = new cvf::Part; + part->setDrawable(surfaceGeo.p()); + + caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(color), caf::PO_1); + cvf::ref eff = surfaceGen.generateCachedEffect(); + + part->setEffect(eff.p()); + + destinationParts->push_back(part); + } + + cvf::ref centerLineGeo = createCenterLine(); + if (centerLineGeo.notNull()) + { + cvf::Part* part = new cvf::Part; + part->setDrawable(centerLineGeo.p()); + + caf::SurfaceEffectGenerator surfaceGen(cvf::Color4f(color), caf::PO_1); + cvf::ref eff = surfaceGen.generateCachedEffect(); + + part->setEffect(eff.p()); + + destinationParts->push_back(part); + } +} + diff --git a/ApplicationCode/ModelVisualization/RivPipeGeometryGenerator.h b/ApplicationCode/ModelVisualization/RivPipeGeometryGenerator.h index c0aa640f30..47e7fb3ae3 100644 --- a/ApplicationCode/ModelVisualization/RivPipeGeometryGenerator.h +++ b/ApplicationCode/ModelVisualization/RivPipeGeometryGenerator.h @@ -23,12 +23,15 @@ #include "cvfBase.h" #include "cvfObject.h" #include "cvfArray.h" +#include "cvfPart.h" namespace cvf { class DrawableGeo; class ScalarMapper; } +class RivObjectSourceInfo; + class RivPipeGeometryGenerator : public cvf::Object { public: @@ -59,6 +62,7 @@ public: void setFirstSegmentIndex(size_t segmentIndex); size_t segmentIndexFromTriangleIndex(size_t triangleIndex) const; + void cylinderWithCenterLineParts(cvf::Collection* destinationParts, const std::vector& centerCoords, const cvf::Color3f& color, double radius); private: void clearComputedData(); void updateFilteredPipeCenterCoords(); diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 14e4bb3b13..2214432e37 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -28,13 +28,17 @@ #include "RimFishbonesMultipleSubs.h" #include "RimWellPath.h" #include "RimWellPathCollection.h" +#include "RimWellPathCompletion.h" +#include "RimWellPathCompletionCollection.h" #include "RivFishbonesSubsPartMgr.h" #include "RivPartPriority.h" #include "RivPipeGeometryGenerator.h" #include "RivWellPathSourceInfo.h" +#include "RivObjectSourceInfo.h" #include "cafEffectGenerator.h" +#include "cafDisplayCoordTransform.h" #include "cvfDrawableGeo.h" #include "cvfDrawableText.h" @@ -109,6 +113,37 @@ void RivWellPathPartMgr::appendFishbonesPartsToModel(cvf::ModelBasicList* model, } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivWellPathPartMgr::appendCompletionsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize) +{ + if (!m_rimWellPath || !m_rimWellPath->m_completionCollection->isChecked()) return; + + RivPipeGeometryGenerator geoGenerator; + for (RimWellPathCompletion* completion : m_rimWellPath->m_completionCollection()->m_completions()) + { + if (!completion->isChecked()) continue; + + std::vector displayCoords; + for (auto lateralDomainCoords : completion->coordinates()) + { + displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(lateralDomainCoords)); + } + + cvf::ref objectSourceInfo = new RivObjectSourceInfo(completion); + + cvf::Collection parts; + geoGenerator.cylinderWithCenterLineParts(&parts, displayCoords, m_rimWellPath->wellPathColor(), m_rimWellPath->combinedScaleFactor() * characteristicCellSize * 0.5); + for (auto part : parts) + { + part->setSourceInfo(objectSourceInfo.p()); + model->addPart(part.p()); + } + } + +} + //-------------------------------------------------------------------------------------------------- /// The pipe geometry needs to be rebuilt on scale change to keep the pipes round //-------------------------------------------------------------------------------------------------- @@ -296,6 +331,7 @@ void RivWellPathPartMgr::appendStaticGeometryPartsToModel(cvf::ModelBasicList* m } appendFishbonesPartsToModel(model, displayCoordTransform, characteristicCellSize); + appendCompletionsToModel(model, displayCoordTransform, characteristicCellSize); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h index df60feadb6..00aeba7a52 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h @@ -61,6 +61,7 @@ public: private: void appendFishbonesPartsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize); + void appendCompletionsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize); void buildWellPathParts(cvf::Vec3d displayModelOffset, double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox); void clearAllBranchData(); From f78b4db16c91284a9375bbb854b65e152c404f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Wed, 10 May 2017 17:37:50 +0200 Subject: [PATCH 091/157] #1467 Fix how coordinates are displayed in property editor for well path completions --- .../RimWellPathCompletion.cpp | 30 +++++++++++++++++-- .../ProjectDataModel/RimWellPathCompletion.h | 4 +++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp index 28ca580f16..4ba3abc570 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp @@ -32,9 +32,14 @@ RimWellPathCompletion::RimWellPathCompletion() { CAF_PDM_InitObject("WellPathCompletion", ":/Well.png", "", ""); CAF_PDM_InitFieldNoDefault(&m_coordinates, "Coordinates", "Coordinates", "", "", ""); + m_coordinates.uiCapability()->setUiHidden(true); CAF_PDM_InitFieldNoDefault(&m_measuredDepths, "MeasuredDepth", "MeasuredDepth", "", "", ""); - m_measuredDepths.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName()); + m_measuredDepths.uiCapability()->setUiHidden(true); m_name.uiCapability()->setUiHidden(true); + + CAF_PDM_InitFieldNoDefault(&m_displayCoordinates, "DisplayCoordinates", "Coordinates", "", "", ""); + m_displayCoordinates.registerGetMethod(this, &RimWellPathCompletion::displayCoordinates); + m_displayCoordinates.uiCapability()->setUiReadOnly(true); } @@ -77,6 +82,25 @@ void RimWellPathCompletion::fieldChangedByUi(const caf::PdmFieldHandle* changedF void RimWellPathCompletion::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { caf::PdmUiGroup* geometryGroup = uiOrdering.addNewGroup("Geometry"); - geometryGroup->add(&m_coordinates); - geometryGroup->add(&m_measuredDepths); + geometryGroup->add(&m_displayCoordinates); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimWellPathCompletion::displayCoordinates() const +{ + CVF_ASSERT(m_coordinates().size() == m_measuredDepths().size()); + + std::vector displayValues; + + displayValues.push_back(QString("X\tY\tZ\tMD")); + for (size_t i = 0; i < m_coordinates().size(); i++) + { + const cvf::Vec3d& coords = m_coordinates()[i]; + const double& measuredDepth = m_measuredDepths()[i]; + displayValues.push_back(QString("%1\t%2\t%3\t%4\t").arg(coords.x()).arg(coords.y()).arg(coords.z()).arg(measuredDepth)); + } + + return displayValues; } diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h index 60fe5f6177..38309cfeb4 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h @@ -31,6 +31,7 @@ #include "cafPdmFieldCvfColor.h" #include "cafPdmChildArrayField.h" #include "cafPdmFieldCvfVec3d.h" +#include "cafPdmProxyValueField.h" #include "cvfBase.h" #include "cvfObject.h" @@ -57,6 +58,9 @@ public: std::vector< cvf::Vec3d > coordinates() { return m_coordinates(); } std::vector< double > measuredDepths() { return m_measuredDepths(); } private: + std::vector displayCoordinates() const; + caf::PdmField< std::vector< cvf::Vec3d> > m_coordinates; caf::PdmField< std::vector< double > > m_measuredDepths; + caf::PdmProxyValueField< std::vector > m_displayCoordinates; }; From e1e75a4fad1c2d006b812c2728fe3e9ad6101869 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 11 May 2017 07:45:55 +0200 Subject: [PATCH 092/157] #1476 Add helper method fileExists() which includes isFile() --- Fwk/AppFwk/CommonCode/cafUtils.cpp | 18 ++++++++++++++++++ Fwk/AppFwk/CommonCode/cafUtils.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/Fwk/AppFwk/CommonCode/cafUtils.cpp b/Fwk/AppFwk/CommonCode/cafUtils.cpp index f8fb68f254..679170b94b 100644 --- a/Fwk/AppFwk/CommonCode/cafUtils.cpp +++ b/Fwk/AppFwk/CommonCode/cafUtils.cpp @@ -223,4 +223,22 @@ bool Utils::getSaveDirectoryAndCheckOverwriteFiles(const QString& defaultDir, st } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool Utils::fileExists(const QString& fileName) +{ + QFileInfo fi(fileName); + + // QFileInfo::exists returns true for both files and folders + // Also check if the path points to a file + + if (fi.exists() && fi.isFile()) + { + return true; + } + + return false; +} + } // namespace caf diff --git a/Fwk/AppFwk/CommonCode/cafUtils.h b/Fwk/AppFwk/CommonCode/cafUtils.h index 8cbdde125c..cb92cee651 100644 --- a/Fwk/AppFwk/CommonCode/cafUtils.h +++ b/Fwk/AppFwk/CommonCode/cafUtils.h @@ -63,6 +63,8 @@ public: static QString indentString(int numSpacesToIndent, const QString& str); static bool getSaveDirectoryAndCheckOverwriteFiles(const QString& defaultDir, std::vector fileNames, QString* saveDir); + + static bool fileExists(const QString& fileName); }; } From 84b922ba8231bcb71fd5960f8631c448a41b4788 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 11 May 2017 09:23:13 +0200 Subject: [PATCH 093/157] #1476 Include isFile() when checking if a file exists --- ApplicationCode/Application/RiaApplication.cpp | 14 +++++++------- .../OctaveScriptCommands/RicNewScriptFeature.cpp | 4 +++- .../RicWellPathsImportSsihubFeature.cpp | 6 ++++-- .../ProjectDataModel/RimEclipseResultCase.cpp | 5 +++-- .../ProjectDataModel/RimGeoMechCase.cpp | 4 +++- .../RimReservoirCellResultsStorage.cpp | 6 +++--- .../ProjectDataModel/RimScriptCollection.cpp | 5 +++-- ApplicationCode/ProjectDataModel/RimTools.cpp | 9 +++++---- ApplicationCode/ProjectDataModel/RimWellPath.cpp | 6 ++++-- .../ReservoirDataModel/RigLasFileExporter.cpp | 3 ++- ApplicationCode/UserInterface/RiuMainWindow.cpp | 3 ++- .../WellPathImportSsihub/RiuWellImportWizard.cpp | 11 ++++++----- 12 files changed, 45 insertions(+), 31 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 2436e0b9e8..15e26fd1a6 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -348,7 +348,7 @@ bool RiaApplication::loadProject(const QString& projectFileName, ProjectLoadActi // Open the project file and read the serialized data. // Will initialize itself. - if (!QFile::exists(projectFileName)) + if (!caf::Utils::fileExists(projectFileName)) { RiaLogging::info(QString("File does not exist : '%1'").arg(projectFileName)); return false; @@ -714,7 +714,7 @@ bool RiaApplication::saveProject() { CVF_ASSERT(m_project.notNull()); - if (!QFile::exists(m_project->fileName())) + if (!caf::Utils::fileExists(m_project->fileName())) { return saveProjectPromptForFileName(); } @@ -940,7 +940,7 @@ QString RiaApplication::createAbsolutePathFromProjectRelativePath(QString projec //-------------------------------------------------------------------------------------------------- bool RiaApplication::openEclipseCaseFromFile(const QString& fileName) { - if (!QFile::exists(fileName)) return false; + if (!caf::Utils::fileExists(fileName)) return false; QFileInfo gridFileName(fileName); QString caseName = gridFileName.completeBaseName(); @@ -1113,7 +1113,7 @@ bool RiaApplication::openInputEclipseCaseFromFileNames(const QStringList& fileNa //-------------------------------------------------------------------------------------------------- bool RiaApplication::openOdbCaseFromFile(const QString& fileName) { - if (!QFile::exists(fileName)) return false; + if (!caf::Utils::fileExists(fileName)) return false; QFileInfo gridFileName(fileName); QString caseName = gridFileName.completeBaseName(); @@ -1479,14 +1479,14 @@ bool RiaApplication::parseArguments() foreach (QString caseName, caseNames) { QString caseFileNameWithExt = caseName + ".EGRID"; - if (QFile::exists(caseFileNameWithExt)) + if (!caf::Utils::fileExists(caseFileNameWithExt)) { openEclipseCaseFromFile(caseFileNameWithExt); } else { caseFileNameWithExt = caseName + ".GRID"; - if (QFile::exists(caseFileNameWithExt)) + if (!caf::Utils::fileExists(caseFileNameWithExt)) { openEclipseCaseFromFile(caseFileNameWithExt); } @@ -2135,7 +2135,7 @@ void RiaApplication::setLastUsedDialogDirectory(const QString& dialogName, const //-------------------------------------------------------------------------------------------------- bool RiaApplication::openFile(const QString& fileName) { - if (!QFile::exists(fileName)) return false; + if (!caf::Utils::fileExists(fileName)) return false; bool loadingSucceded = false; diff --git a/ApplicationCode/Commands/OctaveScriptCommands/RicNewScriptFeature.cpp b/ApplicationCode/Commands/OctaveScriptCommands/RicNewScriptFeature.cpp index dd011f9825..5febff7db3 100644 --- a/ApplicationCode/Commands/OctaveScriptCommands/RicNewScriptFeature.cpp +++ b/ApplicationCode/Commands/OctaveScriptCommands/RicNewScriptFeature.cpp @@ -29,6 +29,8 @@ #include "RiuMainWindow.h" +#include "cafUtils.h" + #include #include #include @@ -76,7 +78,7 @@ void RicNewScriptFeature::onActionTriggered(bool isChecked) fullPathFilenameNewScript = fullPathNewScript + "/untitled.m"; int num= 1; - while (QFileInfo(fullPathFilenameNewScript).exists()) + while (caf::Utils::fileExists(fullPathFilenameNewScript)) { fullPathFilenameNewScript = fullPathNewScript + "/untitled" + QString::number(num) + ".m"; num++; diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp index b30c57449b..e4be65a2b6 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp @@ -27,6 +27,8 @@ #include "RiuMainWindow.h" #include "RiuWellImportWizard.h" +#include "cafUtils.h" + #include #include #include @@ -47,7 +49,7 @@ bool RicWellPathsImportSsihubFeature::isCommandEnabled() return false; } - if (!QFile::exists(app->project()->fileName())) + if (!caf::Utils::fileExists(app->project()->fileName())) { return false; } @@ -66,7 +68,7 @@ void RicWellPathsImportSsihubFeature::onActionTriggered(bool isChecked) return; } - if (!QFile::exists(app->project()->fileName())) + if (!caf::Utils::fileExists(app->project()->fileName())) { return; } diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp index 3432d203e7..35a552fa18 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp @@ -41,6 +41,7 @@ #include "cafPdmSettings.h" #include "cafPdmUiPropertyViewDialog.h" #include "cafProgressInfo.h" +#include "cafUtils.h" #include #include @@ -100,7 +101,7 @@ bool RimEclipseResultCase::openEclipseGridFile() } else { - if (!QFile::exists(caseFileName())) + if (!caf::Utils::fileExists(caseFileName())) { return false; } @@ -174,7 +175,7 @@ bool RimEclipseResultCase::openAndReadActiveCellData(RigEclipseCaseData* mainEcl } else { - if (!QFile::exists(caseFileName())) + if (!caf::Utils::fileExists(caseFileName())) { return false; } diff --git a/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp b/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp index f8c21398ea..47759350be 100644 --- a/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp @@ -40,6 +40,8 @@ #include "RimGeoMechResultDefinition.h" #include "RimGeoMechPropertyFilter.h" +#include "cafUtils.h" + #include CAF_PDM_SOURCE_INIT(RimGeoMechCase, "ResInsightGeoMechCase"); @@ -110,7 +112,7 @@ bool RimGeoMechCase::openGeoMechCase(std::string* errorMessage) // If read already, return if (this->m_geoMechCaseData.notNull()) return true; - if (!QFile::exists(m_caseFileName())) + if (!caf::Utils::fileExists(m_caseFileName())) { return false; } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 04a502ffe2..0beded7277 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -29,6 +29,7 @@ #include "RimTools.h" #include "cafProgressInfo.h" +#include "cafUtils.h" #include "cvfGeometryTools.h" @@ -1394,16 +1395,15 @@ void RimReservoirCellResultsStorage::setCellResults(RigCaseCellResultsData* cell // Get the name of the cache name relative to the current project file position QString newValidCacheFileName = getValidCacheFileName(); - QFile storageFile(newValidCacheFileName); - // Warn if we thought we were to find some data on the storage file - if (!storageFile.exists() && m_resultCacheMetaData.size()) + if (!caf::Utils::fileExists(newValidCacheFileName) && m_resultCacheMetaData.size()) { qWarning() << "Reading stored results: Missing the storage file : " + newValidCacheFileName; return; } + QFile storageFile(newValidCacheFileName); if (!storageFile.open(QIODevice::ReadOnly)) { qWarning() << "Reading stored results: Can't open the file : " + newValidCacheFileName; diff --git a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp index 80acea1865..2ed6cc2778 100644 --- a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp @@ -87,11 +87,12 @@ void RimScriptCollection::readContentFromDisc() { QString fileName = fileList.at(i); - QFileInfo fi(fileName); - if (fi.exists()) + if (caf::Utils::fileExists(fileName)) { RimCalcScript* calcScript = new RimCalcScript; calcScript->absolutePath = fileName; + + QFileInfo fi(fileName); calcScript->setUiName(fi.baseName()); calcScripts.push_back(calcScript); diff --git a/ApplicationCode/ProjectDataModel/RimTools.cpp b/ApplicationCode/ProjectDataModel/RimTools.cpp index 85396c40a9..2d47f7c43a 100644 --- a/ApplicationCode/ProjectDataModel/RimTools.cpp +++ b/ApplicationCode/ProjectDataModel/RimTools.cpp @@ -30,6 +30,7 @@ #include "RimWellPathCollection.h" #include "cafPdmUiItem.h" +#include "cafUtils.h" #include #include @@ -81,7 +82,7 @@ QString RimTools::relocateFile(const QString& orgFileName, const QString& orgNew bool isWindowsPath = false; if (orgFileName.count("/")) isWindowsPath = false; // "/" are not allowed in a windows path else if (orgFileName.count("\\") - && !QFile::exists(orgFileName)) // To make sure we do not convert single linux files containing "\" + && !caf::Utils::fileExists(orgFileName)) // To make sure we do not convert single linux files containing "\" { isWindowsPath = true; } @@ -93,7 +94,7 @@ QString RimTools::relocateFile(const QString& orgFileName, const QString& orgNew } if (searchedPaths) searchedPaths->push_back(fileName); - if (QFile::exists(fileName)) + if (caf::Utils::fileExists(fileName)) { return fileName; } @@ -104,7 +105,7 @@ QString RimTools::relocateFile(const QString& orgFileName, const QString& orgNew QString candidate = QDir::fromNativeSeparators(newProjectPath + QDir::separator() + fileNameWithoutPath); if (searchedPaths) searchedPaths->push_back(candidate); - if (QFile::exists(candidate)) + if (caf::Utils::fileExists(candidate)) { return candidate; } @@ -199,7 +200,7 @@ QString RimTools::relocateFile(const QString& orgFileName, const QString& orgNew if (searchedPaths) searchedPaths->push_back(relocatedFileName); - if (QFile::exists(relocatedFileName)) + if (caf::Utils::fileExists(relocatedFileName)) { return relocatedFileName; } diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index b64df06551..f55b9af141 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -36,6 +36,8 @@ #include "RivWellPathPartMgr.h" +#include "cafUtils.h" + #include #include #include @@ -202,7 +204,7 @@ bool RimWellPath::readWellPathFile(QString* errorMessage, RifWellPathAsciiFileRe { QFileInfo fileInf(filepath()); - if (fileInf.isFile() && fileInf.exists()) + if (caf::Utils::fileExists(filepath())) { if (fileInf.suffix().compare("json") == 0) { @@ -410,7 +412,7 @@ void RimWellPath::updateFilePathsFromProjectPath(const QString& newProjectPath, { QString newCacheFileName = getCacheFileName(); - if (QFile::exists(newCacheFileName)) + if (caf::Utils::fileExists(newCacheFileName)) { filepath = newCacheFileName; } diff --git a/ApplicationCode/ReservoirDataModel/RigLasFileExporter.cpp b/ApplicationCode/ReservoirDataModel/RigLasFileExporter.cpp index 180288a83a..c93b0bc4d7 100644 --- a/ApplicationCode/ReservoirDataModel/RigLasFileExporter.cpp +++ b/ApplicationCode/ReservoirDataModel/RigLasFileExporter.cpp @@ -25,6 +25,7 @@ #include "RimWellLogExtractionCurve.h" #include "cafUtils.h" + #include "cvfAssert.h" #include "laswell.hpp" @@ -390,7 +391,7 @@ bool RigLasFileExporter::writeToFolder(const QString& exportFolder) QDir dir(exportFolder); QString fileName = dir.absoluteFilePath(QString::fromStdString(lasFileDescr.generateFilename())); - if (QFile::exists(fileName)) + if (caf::Utils::fileExists(fileName)) { QString txt = QString("File %1 exists.\n\nDo you want to overwrite the file?").arg(fileName); int ret = QMessageBox::question(NULL, "LAS File Export", diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index be0be55803..21149dbee1 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -56,6 +56,7 @@ #include "cafPdmUiPropertyViewDialog.h" #include "cafPdmUiTreeView.h" #include "cafSelectionManager.h" +#include "cafUtils.h" #include "cvfTimer.h" @@ -637,7 +638,7 @@ void RiuMainWindow::slotRefreshFileActions() { RiaApplication* app = RiaApplication::instance(); - bool projectFileExists = QFile::exists(app->project()->fileName()); + bool projectFileExists = caf::Utils::fileExists(app->project()->fileName()); caf::CmdFeatureManager* cmdFeatureMgr = caf::CmdFeatureManager::instance(); CVF_ASSERT(cmdFeatureMgr); diff --git a/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.cpp b/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.cpp index 296c6f2d24..e44f32c6f5 100644 --- a/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.cpp +++ b/ApplicationCode/WellPathImportSsihub/RiuWellImportWizard.cpp @@ -32,6 +32,7 @@ #include "cafPdmUiPropertyView.h" #include "cafPdmUiTreeView.h" #include "cafPdmUiTreeViewEditor.h" +#include "cafUtils.h" #include #include @@ -99,7 +100,7 @@ QString RiuWellImportWizard::jsonWellsFilePath() void RiuWellImportWizard::downloadFields() { QString wellFileName = jsonWellsFilePath(); - if (QFile::exists(wellFileName)) + if (caf::Utils::fileExists(wellFileName)) { QFile::remove(wellFileName); } @@ -355,7 +356,7 @@ void RiuWellImportWizard::updateFieldsModel() { QString fileName = jsonFieldsFilePath(); - if (QFile::exists(fileName)) + if (caf::Utils::fileExists(fileName)) { ResInsightInternalJson::JsonReader jsonReader; QMap jsonMap = jsonReader.decodeFile(fileName); @@ -540,7 +541,7 @@ QStringList RiuWellImportWizard::absoluteFilePathsToWellPaths() const for (size_t i = 0; i < downloadEntities.size(); i++) { - if (QFile::exists(downloadEntities[i].responseFilename)) + if (caf::Utils::fileExists(downloadEntities[i].responseFilename)) { filePaths.push_back(downloadEntities[i].responseFilename); } @@ -582,7 +583,7 @@ void RiuWellImportWizard::parseWellsResponse(RimOilFieldEntry* oilFieldEntry) QStringList surveyNames; QStringList planNames; - if (QFile::exists(oilFieldEntry->wellsFilePath)) + if (caf::Utils::fileExists(oilFieldEntry->wellsFilePath)) { ResInsightInternalJson::JsonReader jsonReader; QMap jsonMap = jsonReader.decodeFile(oilFieldEntry->wellsFilePath); @@ -1056,7 +1057,7 @@ void WellSummaryPage::updateSummaryPage() for (size_t i = 0; i < downloadEntities.size(); i++) { - if (QFile::exists(downloadEntities[i].responseFilename)) + if (caf::Utils::fileExists(downloadEntities[i].responseFilename)) { wellPathCount++; } From d1e25738d3e0dfe8b4b4b55b228f03df8d3d6fa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 11 May 2017 11:12:49 +0200 Subject: [PATCH 094/157] Make well path completions deleteable --- ApplicationCode/Commands/RicDeleteItemExec.cpp | 1 + ApplicationCode/Commands/RicDeleteItemFeature.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Commands/RicDeleteItemExec.cpp b/ApplicationCode/Commands/RicDeleteItemExec.cpp index 0b0f36c09f..a8fa3ec22e 100644 --- a/ApplicationCode/Commands/RicDeleteItemExec.cpp +++ b/ApplicationCode/Commands/RicDeleteItemExec.cpp @@ -129,6 +129,7 @@ void RicDeleteItemExec::redo() if (wellPathColl) { wellPathColl->scheduleGeometryRegenAndRedrawViews(); + wellPathColl->uiCapability()->updateConnectedEditors(); } // Update due to deletion of curves (not tracks, handled separatly) diff --git a/ApplicationCode/Commands/RicDeleteItemFeature.cpp b/ApplicationCode/Commands/RicDeleteItemFeature.cpp index a982baf470..5f6ab643ae 100644 --- a/ApplicationCode/Commands/RicDeleteItemFeature.cpp +++ b/ApplicationCode/Commands/RicDeleteItemFeature.cpp @@ -43,6 +43,7 @@ #include "RimWellLogCurve.h" #include "RimWellLogPlot.h" #include "RimWellLogTrack.h" +#include "RimWellPathCompletion.h" #include "cafCmdExecCommandManager.h" #include "cafCmdSelectionHelper.h" @@ -87,13 +88,14 @@ bool isDeletable(PdmUiItem * uiItem) if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; - if (dynamic_cast(uiItem)) return true; + if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; - if (dynamic_cast(uiItem)) return true; + if (dynamic_cast(uiItem)) return true; + if (dynamic_cast(uiItem)) return true; return false; } From 0bc423a0d1c16e66bdb900b36f12e208501b5ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 11 May 2017 11:15:13 +0200 Subject: [PATCH 095/157] Remove unused code --- ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp index f8ccac44e2..9cea3c5bca 100644 --- a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp @@ -88,7 +88,6 @@ void RivFishbonesSubsPartMgr::buildParts(caf::DisplayCoordTransform* displayCoor m_rimFishbonesSubs->firstAncestorOrThisOfTypeAsserted(wellPath); RivPipeGeometryGenerator geoGenerator; - geoGenerator.setRadius(m_rimFishbonesSubs->tubingRadius()); for (size_t subIndex = 0; subIndex < m_rimFishbonesSubs->locationOfSubs().size(); subIndex++) { From 265969f246cdf3f07b180897e3df9cd3e83f7450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 11 May 2017 11:19:55 +0200 Subject: [PATCH 096/157] Improve property editor for well path completions --- .../ProjectDataModel/RimWellPathCompletion.cpp | 10 ++++++---- .../ProjectDataModel/RimWellPathCompletion.h | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp index 4ba3abc570..3bba18e062 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp @@ -22,6 +22,7 @@ #include "RimProject.h" #include "cafPdmUiListEditor.h" +#include "cafPdmUiTextEditor.h" CAF_PDM_SOURCE_INIT(RimWellPathCompletion, "WellPathCompletion"); @@ -40,6 +41,7 @@ RimWellPathCompletion::RimWellPathCompletion() CAF_PDM_InitFieldNoDefault(&m_displayCoordinates, "DisplayCoordinates", "Coordinates", "", "", ""); m_displayCoordinates.registerGetMethod(this, &RimWellPathCompletion::displayCoordinates); m_displayCoordinates.uiCapability()->setUiReadOnly(true); + m_displayCoordinates.uiCapability()->setUiEditorTypeName(caf::PdmUiTextEditor::uiEditorTypeName()); } @@ -88,19 +90,19 @@ void RimWellPathCompletion::defineUiOrdering(QString uiConfigName, caf::PdmUiOrd //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellPathCompletion::displayCoordinates() const +QString RimWellPathCompletion::displayCoordinates() const { CVF_ASSERT(m_coordinates().size() == m_measuredDepths().size()); - std::vector displayValues; + QStringList displayValues; displayValues.push_back(QString("X\tY\tZ\tMD")); for (size_t i = 0; i < m_coordinates().size(); i++) { const cvf::Vec3d& coords = m_coordinates()[i]; const double& measuredDepth = m_measuredDepths()[i]; - displayValues.push_back(QString("%1\t%2\t%3\t%4\t").arg(coords.x()).arg(coords.y()).arg(coords.z()).arg(measuredDepth)); + displayValues.push_back(QString("%1\t%2\t%3\t%4").arg(coords.x()).arg(coords.y()).arg(coords.z()).arg(measuredDepth)); } - return displayValues; + return displayValues.join("\n"); } diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h index 38309cfeb4..73abd53b72 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h @@ -58,9 +58,9 @@ public: std::vector< cvf::Vec3d > coordinates() { return m_coordinates(); } std::vector< double > measuredDepths() { return m_measuredDepths(); } private: - std::vector displayCoordinates() const; + QString displayCoordinates() const; caf::PdmField< std::vector< cvf::Vec3d> > m_coordinates; caf::PdmField< std::vector< double > > m_measuredDepths; - caf::PdmProxyValueField< std::vector > m_displayCoordinates; + caf::PdmProxyValueField< QString > m_displayCoordinates; }; From 0c0c21e495f69cd2414121184c0e29253d767095 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 11 May 2017 11:43:15 +0200 Subject: [PATCH 097/157] #1469 Reorder includes and fix comments and whitespace --- .../RiuFlowCharacteristicsPlot.cpp | 56 +++++++++---------- .../RiuFlowCharacteristicsPlot.h | 12 ++-- 2 files changed, 30 insertions(+), 38 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp index 4e1324f05b..bbd5dc2f7f 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp @@ -17,27 +17,30 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiuFlowCharacteristicsPlot.h" -#include "RimFlowCharacteristicsPlot.h" -#include "RiuResultQwtPlot.h" -#include "qwt_plot.h" +#include "RiaColorTables.h" + +#include "RimFlowCharacteristicsPlot.h" + +#include "RiuLineSegmentQwtPlotCurve.h" +#include "RiuQwtPlotWheelZoomer.h" +#include "RiuQwtPlotZoomer.h" +#include "RiuResultQwtPlot.h" +#include "RiuSummaryQwtPlot.h" + #include "cvfBase.h" #include "cvfColor3.h" +#include "qwt_date.h" +#include "qwt_plot.h" +#include "qwt_plot_zoneitem.h" +#include "qwt_plot_zoomer.h" + #include #include +#include #include #include -#include "RiuLineSegmentQwtPlotCurve.h" -#include -#include "RiuSummaryQwtPlot.h" -#include "RiuQwtPlotWheelZoomer.h" -#include "qwt_plot_zoomer.h" -#include "RiaColorTables.h" -#include "qwt_plot_zoneitem.h" -#include "qwt_date.h" -#include "RiuQwtPlotZoomer.h" - //-------------------------------------------------------------------------------------------------- @@ -85,6 +88,9 @@ RiuFlowCharacteristicsPlot::RiuFlowCharacteristicsPlot(RimFlowCharacteristicsPlo m_flowCapVsStorageCapPlot->setTitle("Flow Capacity vs Storage Capacity"); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- void RiuFlowCharacteristicsPlot::addWindowZoom(QwtPlot* plot) { auto zoomer = new RiuQwtPlotZoomer(plot->canvas()); @@ -114,22 +120,6 @@ void RiuFlowCharacteristicsPlot::setLorenzCurve(const std::vector& da m_lorenzPlot->detachItems(QwtPlotItem::Rtti_PlotCurve, true); auto curve = createEmptyCurve(m_lorenzPlot, "Lorenz Coefficient", QColor(0, 0, 0)); curve->setSamplesFromDateAndValues(dateTimes, timeHistoryValues, false); - //curve->setSymbol(QwtSymbol ) - - //size_t tsIdx = 0; - //for ( const QDateTime& dateTime: dateTimes ) - //{ - // auto curve = createEmptyCurve(m_lorenzPlot, dateTime.toString(), m_dateToColorMap[dateTime]); - // std::vector timeStep; - // timeStep.push_back(dateTime); - // std::vector lorCoeff; - // lorCoeff.push_back(timeHistoryValues[tsIdx]); - // - // curve->setSamplesFromDateAndValues(timeStep, lorCoeff, false); - // - // ++tsIdx; - //} - //double milliSecSinceEpoch = QwtDate::toDouble(filteredDateTimes[i]); for ( size_t tsIdx = 0; tsIdx < dateTimes.size(); ++tsIdx ) { @@ -151,6 +141,9 @@ void RiuFlowCharacteristicsPlot::setLorenzCurve(const std::vector& da m_lorenzPlot->replot(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- RiuLineSegmentQwtPlotCurve* RiuFlowCharacteristicsPlot::createEmptyCurve(QwtPlot* plot, const QString& curveName, const QColor& curveColor ) { RiuLineSegmentQwtPlotCurve* plotCurve = new RiuLineSegmentQwtPlotCurve(curveName); @@ -200,6 +193,9 @@ void RiuFlowCharacteristicsPlot::removeAllCurves() m_dateToColorMap.clear(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- void zoomAllInPlot(QwtPlot * plot) { plot->setAxisAutoScale(QwtPlot::xBottom, true); @@ -225,7 +221,6 @@ RimFlowCharacteristicsPlot* RiuFlowCharacteristicsPlot::ownerPlotDefinition() return m_plotDefinition; } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -242,7 +237,6 @@ QSize RiuFlowCharacteristicsPlot::minimumSizeHint() const return QSize(0, 100); } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h index 79980e0a42..0520c18a48 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h @@ -18,13 +18,14 @@ #pragma once -#include "qwt_plot.h" +#include "RiuInterfaceToViewWindow.h" #include "cafPdmPointer.h" -#include +#include "qwt_plot.h" + #include -#include "RiuInterfaceToViewWindow.h" +#include class RimFlowCharacteristicsPlot; class RiuNightchartsWidget; @@ -68,9 +69,7 @@ protected: private: void setDefaults(); - - - void initializeColors(const std::vector& dateTimes); + void initializeColors(const std::vector& dateTimes); private: caf::PdmPointer m_plotDefinition; @@ -78,7 +77,6 @@ private: QPointer m_flowCapVsStorageCapPlot; QPointer m_sweepEffPlot; - std::map m_dateToColorMap; }; From 764a68c032bfd637d5b24047c9cd3997583b3cf9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 11 May 2017 14:04:29 +0200 Subject: [PATCH 098/157] #1469 Add large symbols for each value in Lorenz plot + legend --- .../RiuFlowCharacteristicsPlot.cpp | 55 ++++++++++++++----- .../RiuFlowCharacteristicsPlot.h | 2 + 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp index bbd5dc2f7f..f46a8fed1b 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp @@ -32,9 +32,10 @@ #include "cvfColor3.h" #include "qwt_date.h" +#include "qwt_legend.h" #include "qwt_plot.h" -#include "qwt_plot_zoneitem.h" #include "qwt_plot_zoomer.h" +#include "qwt_symbol.h" #include #include @@ -64,6 +65,9 @@ RiuFlowCharacteristicsPlot::RiuFlowCharacteristicsPlot(RimFlowCharacteristicsPlo this->setPalette(pal); m_lorenzPlot = new QwtPlot(this); + QwtLegend* legend = new QwtLegend(this); + m_lorenzPlot->insertLegend(legend, QwtPlot::BottomLegend); + m_flowCapVsStorageCapPlot = new QwtPlot(this); m_sweepEffPlot = new QwtPlot(this); @@ -118,29 +122,50 @@ void RiuFlowCharacteristicsPlot::setLorenzCurve(const std::vector& da initializeColors(dateTimes); m_lorenzPlot->detachItems(QwtPlotItem::Rtti_PlotCurve, true); - auto curve = createEmptyCurve(m_lorenzPlot, "Lorenz Coefficient", QColor(0, 0, 0)); - curve->setSamplesFromDateAndValues(dateTimes, timeHistoryValues, false); - for ( size_t tsIdx = 0; tsIdx < dateTimes.size(); ++tsIdx ) + for (size_t tsIdx = 0; tsIdx < dateTimes.size(); ++tsIdx) { - double currentTsValue = QwtDate::toDouble(dateTimes[tsIdx]); + if (timeHistoryValues[tsIdx] == HUGE_VAL) continue; - double minTsValue = currentTsValue; - if ( tsIdx > 0 ) minTsValue = 0.5 * (currentTsValue + QwtDate::toDouble(dateTimes[tsIdx-1])); - - double maxTsValue = currentTsValue; - if ( tsIdx < dateTimes.size()-1 ) maxTsValue = 0.5 * (currentTsValue + QwtDate::toDouble(dateTimes[tsIdx+1])); + QDateTime dateTime = dateTimes[tsIdx]; + double timeHistoryValue = timeHistoryValues[tsIdx]; - auto plotZone = new QwtPlotZoneItem(); - plotZone->setOrientation(Qt::Vertical); - plotZone->setInterval(minTsValue, maxTsValue); - plotZone->setBrush(QBrush(m_dateToColorMap[dateTimes[tsIdx]])); - plotZone->attach(m_lorenzPlot); + QString curveName = dateTime.toString(); + + RiuFlowCharacteristicsPlot::addCurveWithLargeSymbol(m_lorenzPlot, curveName, m_dateToColorMap[dateTime], dateTime, timeHistoryValue); } m_lorenzPlot->replot(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuFlowCharacteristicsPlot::addCurveWithLargeSymbol(QwtPlot* plot, const QString& curveName, const QColor& color, const QDateTime& dateTime, double timeHistoryValue) +{ + auto curve = createEmptyCurve(plot, curveName, color); + + QwtSymbol::Style style = QwtSymbol::Diamond; + QwtSymbol* symbol = new QwtSymbol(style); + + symbol->setSize(20, 20); + symbol->setColor(color); + + curve->setSymbol(symbol); + + // Add date and value twice to avoid a cross as symbol generated by RiuLineSegmentQwtPlotCurve + + std::vector dateTimes; + dateTimes.push_back(dateTime); + dateTimes.push_back(dateTime); + + std::vector timeHistoryValues; + timeHistoryValues.push_back(timeHistoryValue); + timeHistoryValues.push_back(timeHistoryValue); + + curve->setSamplesFromDateAndValues(dateTimes, timeHistoryValues, false); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h index 0520c18a48..67797a1d9d 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h @@ -70,6 +70,8 @@ protected: private: void setDefaults(); void initializeColors(const std::vector& dateTimes); + + static void addCurveWithLargeSymbol(QwtPlot* plot, const QString& curveName, const QColor& color, const QDateTime& dateTime, double timeHistoryValue); private: caf::PdmPointer m_plotDefinition; From 4204d49f3032ce3739b8fb7023cfb1682bdd4bf5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 11 May 2017 21:44:44 +0200 Subject: [PATCH 099/157] #1469 Add checkbox for legend visibility --- .../Flow/RimFlowCharacteristicsPlot.cpp | 11 ++++++---- .../Flow/RimFlowCharacteristicsPlot.h | 1 + .../RiuFlowCharacteristicsPlot.cpp | 20 ++++++++++++++++--- .../RiuFlowCharacteristicsPlot.h | 2 ++ 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp index 09bfa0ffab..2f6f2768ce 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp @@ -26,6 +26,8 @@ #include "RiuFlowCharacteristicsPlot.h" +#include "cafPdmUiCheckBoxEditor.h" + #include // Needed for HUGE_VAL on Linux @@ -57,6 +59,8 @@ RimFlowCharacteristicsPlot::RimFlowCharacteristicsPlot() CAF_PDM_InitFieldNoDefault(&m_timeStepSelectionType, "TimeSelectionType", "Time Steps", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_selectedTimeSteps, "SelectedTimeSteps", "", "", "", ""); + CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Legend", "", "", ""); + this->m_showWindow = false; setAsPlotMdiWindow(); } @@ -191,6 +195,8 @@ void RimFlowCharacteristicsPlot::defineUiOrdering(QString uiConfigName, caf::Pdm if (m_timeStepSelectionType == SELECT_AVAILABLE) uiOrdering.add(&m_selectedTimeSteps); + uiOrdering.add(&m_showLegend); + uiOrdering.skipRemainingFields(); } @@ -210,7 +216,6 @@ void RimFlowCharacteristicsPlot::zoomAll() if (m_flowCharPlotWidget) m_flowCharPlotWidget->zoomAll(); } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -229,7 +234,6 @@ void RimFlowCharacteristicsPlot::fieldChangedByUi(const caf::PdmFieldHandle* cha this->loadDataAndUpdate(); } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -246,8 +250,6 @@ QImage RimFlowCharacteristicsPlot::snapshotWindowContent() return image; } - - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -299,6 +301,7 @@ void RimFlowCharacteristicsPlot::loadDataAndUpdate() flowCharResults.m_sweepEfficiencyCurve.second); } + m_flowCharPlotWidget->showLegend(m_showLegend()); } } diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h index c68ea74e19..d8bfafd664 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h @@ -86,6 +86,7 @@ private: caf::PdmPtrField m_flowDiagSolution; caf::PdmField > m_timeStepSelectionType; caf::PdmField > m_selectedTimeSteps; + caf::PdmField m_showLegend; std::vector m_currentlyPlottedTimeSteps; diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp index f46a8fed1b..ef40b5b283 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp @@ -65,9 +65,6 @@ RiuFlowCharacteristicsPlot::RiuFlowCharacteristicsPlot(RimFlowCharacteristicsPlo this->setPalette(pal); m_lorenzPlot = new QwtPlot(this); - QwtLegend* legend = new QwtLegend(this); - m_lorenzPlot->insertLegend(legend, QwtPlot::BottomLegend); - m_flowCapVsStorageCapPlot = new QwtPlot(this); m_sweepEffPlot = new QwtPlot(this); @@ -238,6 +235,23 @@ void RiuFlowCharacteristicsPlot::zoomAll() zoomAllInPlot(m_flowCapVsStorageCapPlot); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuFlowCharacteristicsPlot::showLegend(bool show) +{ + if (show) + { + // Will be released in plot destructor or when a new legend is set + QwtLegend* legend = new QwtLegend(m_lorenzPlot); + m_lorenzPlot->insertLegend(legend, QwtPlot::BottomLegend); + } + else + { + m_lorenzPlot->insertLegend(nullptr); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h index 67797a1d9d..794f2e1ea2 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h @@ -57,6 +57,8 @@ public: void removeAllCurves(); void zoomAll(); + void showLegend(bool show); + RimFlowCharacteristicsPlot* ownerPlotDefinition(); virtual RimViewWindow* ownerViewWindow() const override; From e3e35bcc3c8d9f74e937f874ea3a19ee6aa59ee5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 12 May 2017 08:26:36 +0200 Subject: [PATCH 100/157] Rename to RifWellPathImporter in unit test --- .../UnitTests/WellPathAsciiFileReader-Test.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/UnitTests/WellPathAsciiFileReader-Test.cpp b/ApplicationCode/UnitTests/WellPathAsciiFileReader-Test.cpp index 9c974b49be..8577105cac 100644 --- a/ApplicationCode/UnitTests/WellPathAsciiFileReader-Test.cpp +++ b/ApplicationCode/UnitTests/WellPathAsciiFileReader-Test.cpp @@ -1,7 +1,6 @@ #include "gtest/gtest.h" -#include "RimWellPathCollection.h" -#include "RigWellPath.h" +#include "RifWellPathImporter.h" #include #include @@ -21,8 +20,8 @@ TEST(RimWellPathAsciiFileReaderTest, TestWellNameNoColon) out << "1 2 3"; } - RifWellPathAsciiFileReader reader; - RifWellPathAsciiFileReader::WellData wpData = reader.readWellData(file.fileName(), 0); + RifWellPathImporter reader; + RifWellPathImporter::WellData wpData = reader.readWellData(file.fileName(), 0); EXPECT_TRUE(wpData.m_name == wellName); } } @@ -42,8 +41,8 @@ TEST(RimWellPathAsciiFileReaderTest, TestWellNameWithColon) out << "1 2 3"; } - RifWellPathAsciiFileReader reader; - RifWellPathAsciiFileReader::WellData wpData = reader.readWellData(file.fileName(), 0); + RifWellPathImporter reader; + RifWellPathImporter::WellData wpData = reader.readWellData(file.fileName(), 0); EXPECT_TRUE(wpData.m_name == wellName); } } @@ -63,8 +62,8 @@ TEST(RimWellPathAsciiFileReaderTest, TestWellNameWithColonAndSpace) out << "1 2 3"; } - RifWellPathAsciiFileReader reader; - RifWellPathAsciiFileReader::WellData wpData = reader.readWellData(file.fileName(), 0); + RifWellPathImporter reader; + RifWellPathImporter::WellData wpData = reader.readWellData(file.fileName(), 0); EXPECT_TRUE(wpData.m_name == wellName); } } From d3bcc1644cf682e21be667751e569eb17d91a7e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 11 May 2017 13:33:18 +0200 Subject: [PATCH 101/157] #1451 Add data structures for perforation intervals --- .../ProjectDataModel/CMakeLists_files.cmake | 4 + .../RimPerforationCollection.cpp | 85 +++++++++++++++++++ .../RimPerforationCollection.h | 48 +++++++++++ .../RimPerforationInterval.cpp | 72 ++++++++++++++++ .../ProjectDataModel/RimPerforationInterval.h | 47 ++++++++++ .../ProjectDataModel/RimWellPath.cpp | 9 ++ .../ProjectDataModel/RimWellPath.h | 2 + 7 files changed, 267 insertions(+) create mode 100644 ApplicationCode/ProjectDataModel/RimPerforationCollection.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimPerforationCollection.h create mode 100644 ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimPerforationInterval.h diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 8241efe4f1..fafdfbc7b4 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -16,6 +16,8 @@ ${CEE_CURRENT_LIST_DIR}RimCellRangeFilterCollection.h ${CEE_CURRENT_LIST_DIR}RimDefines.h ${CEE_CURRENT_LIST_DIR}RimLegendConfig.h ${CEE_CURRENT_LIST_DIR}RimOilField.h +${CEE_CURRENT_LIST_DIR}RimPerforationCollection.h +${CEE_CURRENT_LIST_DIR}RimPerforationInterval.h ${CEE_CURRENT_LIST_DIR}RimProject.h ${CEE_CURRENT_LIST_DIR}RimEclipseCase.h ${CEE_CURRENT_LIST_DIR}RimIdenticalGridCaseGroup.h @@ -106,6 +108,8 @@ ${CEE_CURRENT_LIST_DIR}RimCellRangeFilterCollection.cpp ${CEE_CURRENT_LIST_DIR}RimDefines.cpp ${CEE_CURRENT_LIST_DIR}RimLegendConfig.cpp ${CEE_CURRENT_LIST_DIR}RimOilField.cpp +${CEE_CURRENT_LIST_DIR}RimPerforationCollection.cpp +${CEE_CURRENT_LIST_DIR}RimPerforationInterval.cpp ${CEE_CURRENT_LIST_DIR}RimProject.cpp ${CEE_CURRENT_LIST_DIR}RimEclipseCase.cpp ${CEE_CURRENT_LIST_DIR}RimIdenticalGridCaseGroup.cpp diff --git a/ApplicationCode/ProjectDataModel/RimPerforationCollection.cpp b/ApplicationCode/ProjectDataModel/RimPerforationCollection.cpp new file mode 100644 index 0000000000..b1012729e7 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimPerforationCollection.cpp @@ -0,0 +1,85 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimPerforationCollection.h" + +#include "RimEclipseWell.h" +#include "RimPerforationInterval.h" +#include "RimView.h" +#include "RimProject.h" + +#include "RigWellPath.h" + +#include "RifWellPathImporter.h" + +#include "RiuMainWindow.h" + + +CAF_PDM_SOURCE_INIT(RimPerforationCollection, "PerforationCollection"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPerforationCollection::RimPerforationCollection() +{ + CAF_PDM_InitObject("Perforations", ":/Folder.png", "", ""); + + m_name.uiCapability()->setUiHidden(true); + m_name = "Perforations"; + + CAF_PDM_InitFieldNoDefault(&m_perforations, "Perforations", "Perforations", "", "", ""); + m_perforations.uiCapability()->setUiHidden(true); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPerforationCollection::~RimPerforationCollection() +{ + m_perforations.deleteAllChildObjects(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPerforationCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + RimProject* proj; + this->firstAncestorOrThisOfTypeAsserted(proj); + proj->createDisplayModelAndRedrawAllViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPerforationCollection::appendPerforation(RimPerforationInterval* perforation) +{ + m_perforations.push_back(perforation); + + updateConnectedEditors(); + RiuMainWindow::instance()->selectAsCurrentItem(perforation); + + RimView* rimView = NULL; + firstAncestorOrThisOfType(rimView); + if (rimView) + { + rimView->scheduleCreateDisplayModelAndRedraw(); + } +} + diff --git a/ApplicationCode/ProjectDataModel/RimPerforationCollection.h b/ApplicationCode/ProjectDataModel/RimPerforationCollection.h new file mode 100644 index 0000000000..df612c31bb --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimPerforationCollection.h @@ -0,0 +1,48 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimCheckableNamedObject.h" + +#include "cafPdmObject.h" +#include "cafPdmChildArrayField.h" +#include "cafPdmField.h" + +class RimPerforationInterval; + +//================================================================================================== +// +// +// +//================================================================================================== +class RimPerforationCollection : public RimCheckableNamedObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimPerforationCollection(); + ~RimPerforationCollection(); + + void appendPerforation(RimPerforationInterval* perforation); + + void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); + + caf::PdmChildArrayField m_perforations; +}; diff --git a/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp b/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp new file mode 100644 index 0000000000..121213575f --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimPerforationInterval.h" + +#include "RimProject.h" + +#include "cafPdmUiListEditor.h" +#include "cafPdmUiTextEditor.h" + +CAF_PDM_SOURCE_INIT(RimPerforationInterval, "Perforation"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPerforationInterval::RimPerforationInterval() +{ + CAF_PDM_InitObject("Perforation", ":/Default.png", "", ""); + m_name = "Perforation"; + CAF_PDM_InitField(&m_startMD, "StartMeasuredDepth", 0.0, "Start MD [m]", "", "", ""); + CAF_PDM_InitField(&m_endMD, "EndMeasuredDepth", 0.0, "End MD [m]", "", "", ""); + CAF_PDM_InitField(&m_radius, "Radius", 0.0, "Radius [m]", "", "", ""); + CAF_PDM_InitField(&m_skinFactor, "SkinFactor", 0.0, "Skin Factor", "", "", ""); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPerforationInterval::~RimPerforationInterval() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPerforationInterval::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + RimProject* proj; + this->firstAncestorOrThisOfType(proj); + if (proj) proj->createDisplayModelAndRedrawAllViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPerforationInterval::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + uiOrdering.add(&m_name); + + uiOrdering.add(&m_startMD); + uiOrdering.add(&m_endMD); + uiOrdering.add(&m_radius); + uiOrdering.add(&m_skinFactor); +} + diff --git a/ApplicationCode/ProjectDataModel/RimPerforationInterval.h b/ApplicationCode/ProjectDataModel/RimPerforationInterval.h new file mode 100644 index 0000000000..1ba761c90b --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimPerforationInterval.h @@ -0,0 +1,47 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimCheckableNamedObject.h" + +#include "cafPdmField.h" +#include "cafPdmObject.h" + +//================================================================================================== +/// +/// +//================================================================================================== +class RimPerforationInterval : public RimCheckableNamedObject +{ + CAF_PDM_HEADER_INIT; +public: + + RimPerforationInterval(); + virtual ~RimPerforationInterval(); + + virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + virtual void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + +private: + caf::PdmField< double > m_startMD; + caf::PdmField< double > m_endMD; + caf::PdmField< double > m_radius; + caf::PdmField< double > m_skinFactor; +}; diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index d29ac75678..5197da21ed 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -31,6 +31,7 @@ #include "RimWellLogPlotCollection.h" #include "RimWellPathCollection.h" #include "RimWellPathCompletionCollection.h" +#include "RimPerforationCollection.h" #include "RimFishbonesMultipleSubs.h" @@ -105,6 +106,10 @@ RimWellPath::RimWellPath() CAF_PDM_InitFieldNoDefault(&m_completionCollection, "Completions", "Completions", "", "", ""); m_completionCollection = new RimWellPathCompletionCollection; m_completionCollection.uiCapability()->setUiHidden(true); + + CAF_PDM_InitFieldNoDefault(&m_perforationCollection, "Perforations", "Perforations", "", "", ""); + m_perforationCollection = new RimPerforationCollection; + m_perforationCollection.uiCapability()->setUiHidden(true); CAF_PDM_InitFieldNoDefault(&m_wellLogFile, "WellLogFile", "Well Log File", "", "", ""); m_wellLogFile.uiCapability()->setUiHidden(true); @@ -288,6 +293,10 @@ void RimWellPath::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, Q { uiTreeOrdering.add(&m_completionCollection); } + if (!m_perforationCollection->m_perforations.empty()) + { + uiTreeOrdering.add(&m_perforationCollection); + } uiTreeOrdering.add(&fishbonesSubs); } diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index 4c33bb802a..be5a31c372 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -40,6 +40,7 @@ class RimWellPathCompletionCollection; class RivWellPathPartMgr; class RimFishbonesMultipleSubs; +class RimPerforationCollection; //================================================================================================== /// @@ -73,6 +74,7 @@ public: caf::PdmChildField m_wellLogFile; caf::PdmChildField m_completionCollection; + caf::PdmChildField m_perforationCollection; RigWellPath* wellPathGeometry(); caf::PdmChildArrayField fishbonesSubs; From 5a8a632082bbeb58de752ac2f546e917c047a39c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 11 May 2017 13:34:00 +0200 Subject: [PATCH 102/157] #1451 Add command for adding new perforation interval --- ApplicationCode/CMakeLists.txt | 1 + .../CMakeLists_files.cmake | 23 +++++ .../RicNewPerforationIntervalFeature.cpp | 96 +++++++++++++++++++ .../RicNewPerforationIntervalFeature.h | 48 ++++++++++ .../Commands/RicDeleteItemFeature.cpp | 2 + .../RimContextCommandBuilder.cpp | 1 + 6 files changed, 171 insertions(+) create mode 100644 ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake create mode 100644 ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp create mode 100644 ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index de25a61c04..c9cf21a3b8 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -124,6 +124,7 @@ list( APPEND REFERENCED_CMAKE_FILES Commands/EclipseCommands/CMakeLists_files.cmake Commands/EclipseCommands/EclipseWell/CMakeLists_files.cmake Commands/FishbonesCommands/CMakeLists_files.cmake + Commands/PerforationCommands/CMakeLists_files.cmake Commands/FlowCommands/CMakeLists_files.cmake Commands/IntersectionBoxCommands/CMakeLists_files.cmake Commands/OctaveScriptCommands/CMakeLists_files.cmake diff --git a/ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake new file mode 100644 index 0000000000..a68b40ff71 --- /dev/null +++ b/ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake @@ -0,0 +1,23 @@ + +# Use this workaround until we're on 2.8.3 on all platforms and can use CMAKE_CURRENT_LIST_DIR directly +if (${CMAKE_VERSION} VERSION_GREATER "2.8.2") + set(CEE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_DIR}/) +endif() + +set (SOURCE_GROUP_HEADER_FILES +${CEE_CURRENT_LIST_DIR}RicNewPerforationIntervalFeature.h +) + +set (SOURCE_GROUP_SOURCE_FILES +${CEE_CURRENT_LIST_DIR}RicNewPerforationIntervalFeature.cpp +) + +list(APPEND CODE_HEADER_FILES +${SOURCE_GROUP_HEADER_FILES} +) + +list(APPEND CODE_SOURCE_FILES +${SOURCE_GROUP_SOURCE_FILES} +) + +source_group( "CommandFeature\\Perforations" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CEE_CURRENT_LIST_DIR}CMakeLists_files.cmake ) diff --git a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp new file mode 100644 index 0000000000..cb0b5e780c --- /dev/null +++ b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp @@ -0,0 +1,96 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicNewPerforationIntervalFeature.h" + +#include "RiuMainWindow.h" + +#include "RimPerforationInterval.h" +#include "RimPerforationCollection.h" +#include "RimWellPath.h" +#include "RimWellPathCollection.h" + +#include "cafSelectionManager.h" + +#include + +namespace caf +{ + + +CAF_CMD_SOURCE_INIT(RicNewPerforationIntervalFeature, "RicNewPerforationIntervalFeature"); + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewPerforationIntervalFeature::isCommandEnabled() +{ + return selectedWellPath() != nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewPerforationIntervalFeature::onActionTriggered(bool isChecked) +{ + RimWellPath* wellPath = selectedWellPath(); + if (wellPath == nullptr) return; + + RimPerforationInterval* perforationInterval = new RimPerforationInterval; + + wellPath->m_perforationCollection()->appendPerforation(perforationInterval); + + RimWellPathCollection* wellPathCollection = nullptr; + wellPath->firstAncestorOrThisOfType(wellPathCollection); + if (!wellPathCollection) return; + + wellPathCollection->uiCapability()->updateConnectedEditors(); + wellPathCollection->scheduleGeometryRegenAndRedrawViews(); + + RiuMainWindow::instance()->selectAsCurrentItem(perforationInterval); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewPerforationIntervalFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("New Perforation Interval"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPath * RicNewPerforationIntervalFeature::selectedWellPath() +{ + RimWellPath* wellPath = nullptr; + + caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem(); + + caf::PdmObjectHandle* objHandle = dynamic_cast(pdmUiItem); + if (objHandle) + { + objHandle->firstAncestorOrThisOfType(wellPath); + } + + return wellPath; +} + +} // end namespace caf diff --git a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h new file mode 100644 index 0000000000..573349e0f7 --- /dev/null +++ b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h @@ -0,0 +1,48 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +class RimWellPath; + +namespace caf +{ + +//================================================================================================== +/// +//================================================================================================== +class RicNewPerforationIntervalFeature : public CmdFeature +{ + CAF_CMD_HEADER_INIT; +protected: + + // Overrides + virtual bool isCommandEnabled(); + virtual void onActionTriggered( bool isChecked ); + virtual void setupActionLook( QAction* actionToSetup ); + +private: + RimWellPath* selectedWellPath(); +}; + + + +} // end namespace caf diff --git a/ApplicationCode/Commands/RicDeleteItemFeature.cpp b/ApplicationCode/Commands/RicDeleteItemFeature.cpp index 5f6ab643ae..6cf56c7118 100644 --- a/ApplicationCode/Commands/RicDeleteItemFeature.cpp +++ b/ApplicationCode/Commands/RicDeleteItemFeature.cpp @@ -44,6 +44,7 @@ #include "RimWellLogPlot.h" #include "RimWellLogTrack.h" #include "RimWellPathCompletion.h" +#include "RimPerforationInterval.h" #include "cafCmdExecCommandManager.h" #include "cafCmdSelectionHelper.h" @@ -96,6 +97,7 @@ bool isDeletable(PdmUiItem * uiItem) if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; + if (dynamic_cast(uiItem)) return true; return false; } diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 045956893a..649928022b 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -396,6 +396,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection() commandIds << "RicSummaryCurveSwitchAxisFeature"; commandIds << "RicNewFishbonesSubsFeature"; + commandIds << "RicNewPerforationIntervalFeature"; commandIds << "RicExportFishbonesLateralsFeature"; commandIds << "RicWellPathImportCompletionsFileFeature"; From dc4e7e0773db4e4f96e8ad4a8fbf66f27435563d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Thu, 11 May 2017 15:07:31 +0200 Subject: [PATCH 103/157] #1451 Add table editor for perforation intervals --- .../CMakeLists_files.cmake | 2 + .../RicEditPerforationCollectionFeature.cpp | 82 ++++++++++++++ .../RicEditPerforationCollectionFeature.h | 40 +++++++ .../RimContextCommandBuilder.cpp | 1 + .../UserInterface/CMakeLists_files.cmake | 3 + .../RiuEditPerforationCollectionWidget.cpp | 100 ++++++++++++++++++ .../RiuEditPerforationCollectionWidget.h | 47 ++++++++ 7 files changed, 275 insertions(+) create mode 100644 ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp create mode 100644 ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.h create mode 100644 ApplicationCode/UserInterface/RiuEditPerforationCollectionWidget.cpp create mode 100644 ApplicationCode/UserInterface/RiuEditPerforationCollectionWidget.h diff --git a/ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake index a68b40ff71..ee9864e76f 100644 --- a/ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake @@ -5,10 +5,12 @@ if (${CMAKE_VERSION} VERSION_GREATER "2.8.2") endif() set (SOURCE_GROUP_HEADER_FILES +${CEE_CURRENT_LIST_DIR}RicEditPerforationCollectionFeature.h ${CEE_CURRENT_LIST_DIR}RicNewPerforationIntervalFeature.h ) set (SOURCE_GROUP_SOURCE_FILES +${CEE_CURRENT_LIST_DIR}RicEditPerforationCollectionFeature.cpp ${CEE_CURRENT_LIST_DIR}RicNewPerforationIntervalFeature.cpp ) diff --git a/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp b/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp new file mode 100644 index 0000000000..97abed587c --- /dev/null +++ b/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp @@ -0,0 +1,82 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016- Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicEditPerforationCollectionFeature.h" + +#include "RiuEditPerforationCollectionWidget.h" + +#include "RimPerforationCollection.h" +#include "RimWellPath.h" + +#include "cafSelectionManager.h" + +#include + + +CAF_CMD_SOURCE_INIT(RicEditPerforationCollectionFeature, "RicEditPerforationCollectionFeature"); + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicEditPerforationCollectionFeature::isCommandEnabled() +{ + return selectedWellPath() != nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicEditPerforationCollectionFeature::onActionTriggered(bool isChecked) +{ + this->disableModelChangeContribution(); + + RimWellPath* wellPath = selectedWellPath(); + + if (wellPath == nullptr) return; + + RiuEditPerforationCollectionWidget dlg(nullptr, wellPath->m_perforationCollection); + dlg.exec(); + wellPath->updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicEditPerforationCollectionFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("Edit Perforations"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPath* RicEditPerforationCollectionFeature::selectedWellPath() const +{ + RimWellPath* wellPath = nullptr; + + caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem(); + + caf::PdmObjectHandle* objHandle = dynamic_cast(pdmUiItem); + if (objHandle) + { + objHandle->firstAncestorOrThisOfType(wellPath); + } + + return wellPath; +} diff --git a/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.h b/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.h new file mode 100644 index 0000000000..b0deea2c70 --- /dev/null +++ b/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016- Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +class RimWellPath; + +//================================================================================================== +/// +//================================================================================================== +class RicEditPerforationCollectionFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook(QAction* actionToSetup) override; + +private: + RimWellPath* selectedWellPath() const; +}; + diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 649928022b..0e8d012ed1 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -397,6 +397,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection() commandIds << "RicNewFishbonesSubsFeature"; commandIds << "RicNewPerforationIntervalFeature"; + commandIds << "RicEditPerforationCollectionFeature"; commandIds << "RicExportFishbonesLateralsFeature"; commandIds << "RicWellPathImportCompletionsFileFeature"; diff --git a/ApplicationCode/UserInterface/CMakeLists_files.cmake b/ApplicationCode/UserInterface/CMakeLists_files.cmake index a3b595d0d1..8658fd36fb 100644 --- a/ApplicationCode/UserInterface/CMakeLists_files.cmake +++ b/ApplicationCode/UserInterface/CMakeLists_files.cmake @@ -41,6 +41,7 @@ ${CEE_CURRENT_LIST_DIR}RiuWellLogPlot.h ${CEE_CURRENT_LIST_DIR}RiuWellLogTrack.h ${CEE_CURRENT_LIST_DIR}RiuGeoMechXfTensorResultAccessor.h ${CEE_CURRENT_LIST_DIR}RiuFemTimeHistoryResultAccessor.h +${CEE_CURRENT_LIST_DIR}RiuEditPerforationCollectionWidget.h ${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.h ${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.h ${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.h @@ -86,6 +87,7 @@ ${CEE_CURRENT_LIST_DIR}RiuWellLogPlot.cpp ${CEE_CURRENT_LIST_DIR}RiuWellLogTrack.cpp ${CEE_CURRENT_LIST_DIR}RiuGeoMechXfTensorResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RiuFemTimeHistoryResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RiuEditPerforationCollectionWidget.cpp ${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.cpp ${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.cpp ${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.cpp @@ -119,6 +121,7 @@ ${CEE_CURRENT_LIST_DIR}RiuRecentFileActionProvider.h ${CEE_CURRENT_LIST_DIR}RiuSummaryQwtPlot.h ${CEE_CURRENT_LIST_DIR}RiuQwtScalePicker.h ${CEE_CURRENT_LIST_DIR}RiuQwtPlotWheelZoomer.h +${CEE_CURRENT_LIST_DIR}RiuEditPerforationCollectionWidget.h ${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.h ${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.h ${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.h diff --git a/ApplicationCode/UserInterface/RiuEditPerforationCollectionWidget.cpp b/ApplicationCode/UserInterface/RiuEditPerforationCollectionWidget.cpp new file mode 100644 index 0000000000..7c43178a04 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuEditPerforationCollectionWidget.cpp @@ -0,0 +1,100 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RiuEditPerforationCollectionWidget.h" + +#include "RimPerforationCollection.h" + +#include "cafCmdFeatureManager.h" +#include "cafPdmUiTableView.h" +#include "cafSelectionManager.h" + +#include +#include +#include +#include +#include +#include +#include + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuEditPerforationCollectionWidget::RiuEditPerforationCollectionWidget(QWidget* parent, RimPerforationCollection* perforationCollection) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint), + m_perforationCollection(perforationCollection) +{ + setWindowTitle("Edit Perforation Intervals"); + + QVBoxLayout* dialogLayout = new QVBoxLayout; + setLayout(dialogLayout); + + m_pdmTableView = new caf::PdmUiTableView(this); + m_pdmTableView->tableView()->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_pdmTableView->tableView()->setContextMenuPolicy(Qt::CustomContextMenu); + m_pdmTableView->enableHeaderText(false); + + connect(m_pdmTableView->tableView(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint))); + + m_pdmTableView->setListField(&(m_perforationCollection->m_perforations)); + + QHeaderView* verticalHeader = m_pdmTableView->tableView()->verticalHeader(); + verticalHeader->setResizeMode(QHeaderView::Interactive); + + m_pdmTableView->tableView()->resizeColumnsToContents(); + + // Set active child array to be able to use generic delete + caf::SelectionManager::instance()->setActiveChildArrayFieldHandle(&(m_perforationCollection->m_perforations)); + + dialogLayout->addWidget(m_pdmTableView); + + // Buttons + QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + dialogLayout->addWidget(buttonBox); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuEditPerforationCollectionWidget::~RiuEditPerforationCollectionWidget() +{ + m_pdmTableView->setListField(nullptr); + + caf::SelectionManager::instance()->setActiveChildArrayFieldHandle(nullptr); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuEditPerforationCollectionWidget::customMenuRequested(QPoint pos) +{ + caf::CmdFeatureManager* commandManager = caf::CmdFeatureManager::instance(); + + QMenu menu; + menu.addAction(commandManager->action("PdmListField_AddItem","New row")); + menu.addAction(commandManager->action("PdmListField_DeleteItem","Delete row")); + + // Qt doc: QAbstractScrollArea and its subclasses that map the context menu event to coordinates of the viewport(). + QPoint globalPos = m_pdmTableView->tableView()->viewport()->mapToGlobal(pos); + + menu.exec(globalPos); +} diff --git a/ApplicationCode/UserInterface/RiuEditPerforationCollectionWidget.h b/ApplicationCode/UserInterface/RiuEditPerforationCollectionWidget.h new file mode 100644 index 0000000000..24aa05e04d --- /dev/null +++ b/ApplicationCode/UserInterface/RiuEditPerforationCollectionWidget.h @@ -0,0 +1,47 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +class RimProject; + +class RimPerforationCollection; + +namespace caf { + class PdmUiTableView; +} + +class QWidget; +class QLineEdit; + +class RiuEditPerforationCollectionWidget : public QDialog +{ + Q_OBJECT +public: + RiuEditPerforationCollectionWidget(QWidget* parent, RimPerforationCollection* perforationCollection); + ~RiuEditPerforationCollectionWidget(); + +private slots: + void customMenuRequested(QPoint pos); + +private: + RimPerforationCollection* m_perforationCollection; + caf::PdmUiTableView* m_pdmTableView; +}; From 1d14971bee3912b33b978c6648063f159f9f6028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Fri, 12 May 2017 09:28:21 +0200 Subject: [PATCH 104/157] Consistent formatting in well path completions property editor --- ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp index 3bba18e062..942d08757d 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp @@ -101,7 +101,7 @@ QString RimWellPathCompletion::displayCoordinates() const { const cvf::Vec3d& coords = m_coordinates()[i]; const double& measuredDepth = m_measuredDepths()[i]; - displayValues.push_back(QString("%1\t%2\t%3\t%4").arg(coords.x()).arg(coords.y()).arg(coords.z()).arg(measuredDepth)); + displayValues.push_back(QString("%1\t%2\t%3\t%4").arg(coords.x(), 0, 'f', 2).arg(coords.y(), 0, 'f', 2).arg(coords.z(), 0, 'f', 2).arg(measuredDepth, 0, 'f', 2)); } return displayValues.join("\n"); From a399f54ed76856f81de9036a7dcb8c428370f889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Fri, 12 May 2017 10:01:37 +0200 Subject: [PATCH 105/157] #1470 Fishbones : Perforation intervals visualization --- .../ModelVisualization/RivWellPathPartMgr.cpp | 79 +++++++++++++++++-- .../ModelVisualization/RivWellPathPartMgr.h | 4 + .../ProjectDataModel/RimPerforationInterval.h | 3 + 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 2214432e37..59010fe6ea 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -30,6 +30,8 @@ #include "RimWellPathCollection.h" #include "RimWellPathCompletion.h" #include "RimWellPathCompletionCollection.h" +#include "RimPerforationInterval.h" +#include "RimPerforationCollection.h" #include "RivFishbonesSubsPartMgr.h" #include "RivPartPriority.h" @@ -144,14 +146,60 @@ void RivWellPathPartMgr::appendCompletionsToModel(cvf::ModelBasicList* model, ca } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivWellPathPartMgr::appendPerforationsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize) +{ + if (!m_rimWellPath || !m_rimWellPath->m_perforationCollection->isChecked()) return; + + RimWellPathCollection* wellPathCollection = this->wellPathCollection(); + if (!wellPathCollection) return; + + RigWellPath* wellPathGeometry = m_rimWellPath->wellPathGeometry(); + if (!wellPathGeometry) return; + + // Since we're using the index of measured depths to find the index of a point, ensure they're equal + CVF_ASSERT(wellPathGeometry->m_measuredDepths.size() == wellPathGeometry->m_wellPathPoints.size()); + + double wellPathRadius = this->wellPathRadius(characteristicCellSize, wellPathCollection); + double perforationRadius = wellPathRadius * 1.1; + + RivPipeGeometryGenerator geoGenerator; + for (RimPerforationInterval* perforation : m_rimWellPath->m_perforationCollection->m_perforations()) + { + if (!perforation->isChecked()) continue; + + std::vector displayCoords; + for (size_t i = 0; i < wellPathGeometry->m_measuredDepths.size(); ++i) + { + double measuredDepth = wellPathGeometry->m_measuredDepths[i]; + if (measuredDepth < perforation->startMD()) continue; + if (measuredDepth > perforation->endMD()) break; + displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(wellPathGeometry->m_wellPathPoints[i])); + } + + if (displayCoords.size() < 2) continue; + + cvf::ref objectSourceInfo = new RivObjectSourceInfo(perforation); + + cvf::Collection parts; + geoGenerator.cylinderWithCenterLineParts(&parts, displayCoords, cvf::Color3f::GREEN, perforationRadius); + for (auto part : parts) + { + part->setSourceInfo(objectSourceInfo.p()); + model->addPart(part.p()); + } + } +} + //-------------------------------------------------------------------------------------------------- /// The pipe geometry needs to be rebuilt on scale change to keep the pipes round //-------------------------------------------------------------------------------------------------- void RivWellPathPartMgr::buildWellPathParts(cvf::Vec3d displayModelOffset, double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox) { - RimWellPathCollection* wellPathCollection = NULL; - m_rimWellPath->firstAncestorOrThisOfType(wellPathCollection); + RimWellPathCollection* wellPathCollection = this->wellPathCollection(); if (!wellPathCollection) return; RigWellPath* wellPathGeometry = m_rimWellPath->wellPathGeometry(); @@ -160,7 +208,7 @@ void RivWellPathPartMgr::buildWellPathParts(cvf::Vec3d displayModelOffset, doubl if (wellPathGeometry->m_wellPathPoints.size() < 2) return; clearAllBranchData(); - double wellPathRadius = wellPathCollection->wellPathRadiusScaleFactor() * m_rimWellPath->wellPathRadiusScaleFactor() * characteristicCellSize; + double wellPathRadius = this->wellPathRadius(characteristicCellSize, wellPathCollection); cvf::Vec3d textPosition = wellPathGeometry->m_wellPathPoints[0]; @@ -297,8 +345,7 @@ void RivWellPathPartMgr::appendStaticGeometryPartsToModel(cvf::ModelBasicList* m double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox, caf::DisplayCoordTransform* displayCoordTransform) { - RimWellPathCollection* wellPathCollection = NULL; - m_rimWellPath->firstAncestorOrThisOfType(wellPathCollection); + RimWellPathCollection* wellPathCollection = this->wellPathCollection(); if (!wellPathCollection) return; if (m_rimWellPath.isNull()) return; @@ -332,6 +379,7 @@ void RivWellPathPartMgr::appendStaticGeometryPartsToModel(cvf::ModelBasicList* m appendFishbonesPartsToModel(model, displayCoordTransform, characteristicCellSize); appendCompletionsToModel(model, displayCoordTransform, characteristicCellSize); + appendPerforationsToModel(model, displayCoordTransform, characteristicCellSize); } //-------------------------------------------------------------------------------------------------- @@ -375,3 +423,24 @@ size_t RivWellPathPartMgr::segmentIndexFromTriangleIndex(size_t triangleIndex) { return m_pipeBranchData.m_pipeGeomGenerator->segmentIndexFromTriangleIndex(triangleIndex); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPathCollection* RivWellPathPartMgr::wellPathCollection() +{ + if (!m_rimWellPath) return nullptr; + + RimWellPathCollection* wellPathCollection = nullptr; + m_rimWellPath->firstAncestorOrThisOfType(wellPathCollection); + + return wellPathCollection; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RivWellPathPartMgr::wellPathRadius(double characteristicCellSize, RimWellPathCollection* wellPathCollection) +{ + return wellPathCollection->wellPathRadiusScaleFactor() * m_rimWellPath->wellPathRadiusScaleFactor() * characteristicCellSize; +} diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h index 00aeba7a52..25769008da 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h @@ -42,6 +42,7 @@ class RivPipeGeometryGenerator; class RimProject; class RimWellPath; class RivFishbonesSubsPartMgr; +class RimWellPathCollection; class RivWellPathPartMgr : public cvf::Object { @@ -62,8 +63,11 @@ public: private: void appendFishbonesPartsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize); void appendCompletionsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize); + void appendPerforationsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize); void buildWellPathParts(cvf::Vec3d displayModelOffset, double characteristicCellSize, cvf::BoundingBox wellPathClipBoundingBox); void clearAllBranchData(); + inline RimWellPathCollection* wellPathCollection(); + inline double wellPathRadius(double characteristicCellSize, RimWellPathCollection* wellPathCollection); private: caf::PdmPointer m_rimWellPath; diff --git a/ApplicationCode/ProjectDataModel/RimPerforationInterval.h b/ApplicationCode/ProjectDataModel/RimPerforationInterval.h index 1ba761c90b..159c847556 100644 --- a/ApplicationCode/ProjectDataModel/RimPerforationInterval.h +++ b/ApplicationCode/ProjectDataModel/RimPerforationInterval.h @@ -39,6 +39,9 @@ public: virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; virtual void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + double startMD() { return m_startMD(); } + double endMD() { return m_endMD(); } + private: caf::PdmField< double > m_startMD; caf::PdmField< double > m_endMD; From 813b8ecad27f17e11bcea1c8f117b1f613a0e830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Fri, 12 May 2017 10:44:34 +0200 Subject: [PATCH 106/157] #1470 Interpolate perforation visualization between well path points --- .../ModelVisualization/RivWellPathPartMgr.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 59010fe6ea..3a22bcaf5b 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -169,15 +169,19 @@ void RivWellPathPartMgr::appendPerforationsToModel(cvf::ModelBasicList* model, c for (RimPerforationInterval* perforation : m_rimWellPath->m_perforationCollection->m_perforations()) { if (!perforation->isChecked()) continue; + if (perforation->startMD() > perforation->endMD()) continue; std::vector displayCoords; + displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(wellPathGeometry->interpolatedPointAlongWellPath(perforation->startMD()))); for (size_t i = 0; i < wellPathGeometry->m_measuredDepths.size(); ++i) { double measuredDepth = wellPathGeometry->m_measuredDepths[i]; - if (measuredDepth < perforation->startMD()) continue; - if (measuredDepth > perforation->endMD()) break; - displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(wellPathGeometry->m_wellPathPoints[i])); + if (measuredDepth > perforation->startMD() && measuredDepth < perforation->endMD()) + { + displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(wellPathGeometry->m_wellPathPoints[i])); + } } + displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(wellPathGeometry->interpolatedPointAlongWellPath(perforation->endMD()))); if (displayCoords.size() < 2) continue; From 59f55f0c062f6b29a3ec2d816080ed67d3382462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Fri, 12 May 2017 10:49:48 +0200 Subject: [PATCH 107/157] Move well path completion property editor label to top --- ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp index 942d08757d..bbc5fec08c 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp @@ -42,6 +42,7 @@ RimWellPathCompletion::RimWellPathCompletion() m_displayCoordinates.registerGetMethod(this, &RimWellPathCompletion::displayCoordinates); m_displayCoordinates.uiCapability()->setUiReadOnly(true); m_displayCoordinates.uiCapability()->setUiEditorTypeName(caf::PdmUiTextEditor::uiEditorTypeName()); + m_displayCoordinates.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::LabelPosType::TOP); } @@ -83,8 +84,7 @@ void RimWellPathCompletion::fieldChangedByUi(const caf::PdmFieldHandle* changedF //-------------------------------------------------------------------------------------------------- void RimWellPathCompletion::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { - caf::PdmUiGroup* geometryGroup = uiOrdering.addNewGroup("Geometry"); - geometryGroup->add(&m_displayCoordinates); + uiOrdering.add(&m_displayCoordinates); } //-------------------------------------------------------------------------------------------------- From 3c07eafab29ad56af5e9d58f736b51b4510fc839 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 12 May 2017 12:17:11 +0200 Subject: [PATCH 108/157] #1372 Update flow diagnostics and flow diagnostics applications --- ResInsightVersion.cmake | 4 +- .../CMakeLists_files.cmake | 1 + .../examples/computeFlowStorageCurve.cpp | 79 ++ .../examples/computeLocalSolutions.cpp | 4 +- .../examples/exampleSetup.hpp | 108 +- .../examples/extractFromRestart.cpp | 7 +- .../opm/utility/ECLFluxCalc.cpp | 10 +- .../opm/utility/ECLFluxCalc.hpp | 5 +- .../opm/utility/ECLGraph.cpp | 547 +++++---- .../opm/utility/ECLGraph.hpp | 63 +- .../opm/utility/ECLResultData.cpp | 1031 ++++++++++++++--- .../opm/utility/ECLResultData.hpp | 185 ++- .../opm/utility/ECLUnitHandling.cpp | 1 - .../opm/utility/ECLUnitHandling.hpp | 1 - .../opm/utility/ECLWellSolution.cpp | 47 +- .../opm/utility/ECLWellSolution.hpp | 14 +- .../tests/runAcceptanceTest.cpp | 4 +- .../tests/runLinearisedCellDataTest.cpp | 19 +- .../tests/runTransTest.cpp | 6 +- .../opm/flowdiagnostics/DerivedQuantities.cpp | 30 +- .../opm/flowdiagnostics/DerivedQuantities.hpp | 8 + .../opm/flowdiagnostics/Solution.cpp | 1 + .../opm/flowdiagnostics/TracerTofSolver.cpp | 2 +- .../graph/AssembledConnectionsIteration.hpp | 1 + .../tests/test_derivedquantities.cpp | 26 + 25 files changed, 1674 insertions(+), 530 deletions(-) create mode 100644 ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/computeFlowStorageCurve.cpp diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 2f00b8f1e8..7d3d69bfb6 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -11,10 +11,10 @@ set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f") set(ERT_GITHUB_SHA "06a39878636af0bc52582430ad0431450e51139c") # https://github.com/OPM/opm-flowdiagnostics -set(OPM_FLOWDIAGNOSTICS_SHA "a14dc4ba1302bcc1e0aeb35c5de6b4bd39bce98") +set(OPM_FLOWDIAGNOSTICS_SHA "2c5fb55db4c4ded49c14161dd16463e1207da049") # https://github.com/OPM/opm-flowdiagnostics-applications -set(OPM_FLOWDIAGNOSTICS_APPLICATIONS_SHA "1b521494ce9c09a1286dd0a81a1333caa123c680") +set(OPM_FLOWDIAGNOSTICS_APPLICATIONS_SHA "570601718e7197b751bc3cba60c1e5fb7d842842") # https://github.com/OPM/opm-parser/blob/master/opm/parser/eclipse/Units/Units.hpp # This file was moved from opm-core to opm-parser october 2016 diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/CMakeLists_files.cmake b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/CMakeLists_files.cmake index 568ddf04b3..e30cdd67a1 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/CMakeLists_files.cmake +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/CMakeLists_files.cmake @@ -33,6 +33,7 @@ list (APPEND TEST_SOURCE_FILES ) list (APPEND EXAMPLE_SOURCE_FILES + examples/computeFlowStorageCurve.cpp examples/computeLocalSolutions.cpp examples/computeToFandTracers.cpp examples/computeTracers.cpp diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/computeFlowStorageCurve.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/computeFlowStorageCurve.cpp new file mode 100644 index 0000000000..f29df16e8b --- /dev/null +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/computeFlowStorageCurve.cpp @@ -0,0 +1,79 @@ +/* + Copyright 2016 SINTEF ICT, Applied Mathematics. + Copyright 2016, 2017 Statoil 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 . +*/ + +#if HAVE_CONFIG_H +#include +#endif + +#include "exampleSetup.hpp" + +#include +#include + +// Syntax (typical): +// computeFlowStorageCurve case= step= +int main(int argc, char* argv[]) +try { + example::Setup setup(argc, argv); + auto& fdTool = setup.toolbox; + + // Solve for forward and reverse time of flight. + std::vector start; + auto fwd = fdTool.computeInjectionDiagnostics(start); + auto rev = fdTool.computeProductionDiagnostics(start); + + // Give disconnected cells zero pore volume. + std::vector nbcount(setup.graph.numCells(), 0); + for (int nb : setup.graph.neighbours()) { + if (nb >= 0) { + ++nbcount[nb]; + } + } + auto pv = setup.graph.poreVolume(); + for (size_t i = 0; i < pv.size(); ++i) { + if (nbcount[i] == 0) { + pv[i] = 0.0; + } + } + + // Cells that have more than 100 times the average pore volume are + // probably aquifers, we ignore them (again by setting pore volume + // to zero). If this is the correct thing to do or not could + // depend on what you want to use the diagnostic for. + const double average_pv = std::accumulate(pv.begin(), pv.end(), 0.0) / double(pv.size()); + for (double& pvval : pv) { + if (pvval > 100.0 * average_pv) { + pvval = 0.0; + } + } + + // Compute graph. + auto fphi = Opm::FlowDiagnostics::flowCapacityStorageCapacityCurve(fwd, rev, pv); + + // Write it to standard out. + std::cout.precision(16); + const int sz = fphi.first.size(); + for (int i = 0; i < sz; ++i) { + std::cout << fphi.first[i] << " " << fphi.second[i] << '\n'; + } +} +catch (const std::exception& e) { + std::cerr << "Caught exception: " << e.what() << '\n'; +} diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/computeLocalSolutions.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/computeLocalSolutions.cpp index 8b5e2b7152..50a2a5598d 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/computeLocalSolutions.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/computeLocalSolutions.cpp @@ -42,9 +42,9 @@ try { std::vector completion_cells; completion_cells.reserve(well.completions.size()); for (const auto& completion : well.completions) { - const int grid_index = completion.grid_index; + const auto& gridName = completion.gridName; const auto& ijk = completion.ijk; - const int cell_index = setup.graph.activeCell(ijk, grid_index); + const int cell_index = setup.graph.activeCell(ijk, gridName); if (cell_index >= 0) { completion_cells.push_back(cell_index); } diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/exampleSetup.hpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/exampleSetup.hpp index 5d2f64b4c0..a536c2730e 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/exampleSetup.hpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/exampleSetup.hpp @@ -31,10 +31,10 @@ #include #include +#include #include #include -#include #include #include #include @@ -80,38 +80,66 @@ namespace example { throw std::invalid_argument(os.str()); } + + template inline Opm::FlowDiagnostics::ConnectionValues - extractFluxField(const Opm::ECLGraph& G, const bool compute_fluxes) + extractFluxField(const Opm::ECLGraph& G, + FluxCalc&& getFlux) { using ConnVals = Opm::FlowDiagnostics::ConnectionValues; + + const auto actPh = G.activePhases(); + auto flux = ConnVals(ConnVals::NumConnections{G.numConnections()}, - ConnVals::NumPhases{3}); + ConnVals::NumPhases{actPh.size()}); auto phas = ConnVals::PhaseID{0}; - Opm::ECLFluxCalc calc(G); + for (const auto& p : actPh) { + const auto pflux = getFlux(p); - const auto phases = { Opm::ECLGraph::PhaseIndex::Aqua , - Opm::ECLGraph::PhaseIndex::Liquid , - Opm::ECLGraph::PhaseIndex::Vapour }; - - for (const auto& p : phases) - { - const auto pflux = compute_fluxes ? calc.flux(p) : G.flux(p); if (! pflux.empty()) { assert (pflux.size() == flux.numConnections()); + auto conn = ConnVals::ConnID{0}; for (const auto& v : pflux) { flux(conn, phas) = v; conn.id += 1; } } + phas.id += 1; } return flux; } + inline Opm::FlowDiagnostics::ConnectionValues + extractFluxField(const Opm::ECLGraph& G, + const Opm::ECLRestartData& rstrt, + const bool compute_fluxes) + { + if (compute_fluxes) { + Opm::ECLFluxCalc calc(G); + + auto getFlux = [&calc, &rstrt] + (const Opm::ECLGraph::PhaseIndex p) + { + return calc.flux(rstrt, p); + }; + + return extractFluxField(G, getFlux); + } + + auto getFlux = [&G, &rstrt] + (const Opm::ECLGraph::PhaseIndex p) + { + return G.flux(rstrt, p); + }; + + return extractFluxField(G, getFlux); + } + template Opm::FlowDiagnostics::CellSetValues extractWellFlows(const Opm::ECLGraph& G, @@ -120,9 +148,9 @@ namespace example { Opm::FlowDiagnostics::CellSetValues inflow; for (const auto& well : well_fluxes) { for (const auto& completion : well.completions) { - const int grid_index = completion.grid_index; + const auto& gridName = completion.gridName; const auto& ijk = completion.ijk; - const int cell_index = G.activeCell(ijk, grid_index); + const int cell_index = G.activeCell(ijk, gridName); if (cell_index >= 0) { // Since inflow is a std::map, if the key was not // already present operator[] will insert a @@ -142,7 +170,7 @@ namespace example { struct FilePaths { - FilePaths(const Opm::parameter::ParameterGroup& param) + FilePaths(const Opm::ParameterGroup& param) { const string casename = param.getDefault("case", "DEFAULT_CASE_NAME"); grid = param.has("grid") ? param.get("grid") @@ -164,13 +192,13 @@ namespace example { - inline Opm::parameter::ParameterGroup + inline Opm::ParameterGroup initParam(int argc, char** argv) { // Obtain parameters from command line (possibly specifying a parameter file). const bool verify_commandline_syntax = true; const bool parameter_output = false; - Opm::parameter::ParameterGroup param(argc, argv, verify_commandline_syntax, parameter_output); + Opm::ParameterGroup param(argc, argv, verify_commandline_syntax, parameter_output); return param; } @@ -180,10 +208,9 @@ namespace example { inline Opm::ECLGraph initGraph(const FilePaths& file_paths) { - // Read graph and assign restart file. - auto graph = Opm::ECLGraph::load(file_paths.grid, file_paths.init); - graph.assignFluxDataSource(file_paths.restart); - return graph; + const auto I = Opm::ECLInitFileData(file_paths.init); + + return Opm::ECLGraph::load(file_paths.grid, I); } @@ -209,38 +236,47 @@ namespace example { struct Setup { Setup(int argc, char** argv) - : param(initParam(argc, argv)) - , file_paths(param) - , graph(initGraph(file_paths)) - , well_fluxes() - , toolbox(initToolbox(graph)) + : param (initParam(argc, argv)) + , file_paths (param) + , rstrt (file_paths.restart) + , graph (initGraph(file_paths)) + , well_fluxes () + , toolbox (initToolbox(graph)) , compute_fluxes_(param.getDefault("compute_fluxes", false)) { const int step = param.getDefault("step", 0); - if (!selectReportStep(step)) { + + if (! this->selectReportStep(step)) { std::ostringstream os; + os << "Report Step " << step - << " is Not Available in Result Set '" - << file_paths.grid.stem() << '\''; + << " is Not Available in Result Set " + << file_paths.grid.stem(); + throw std::domain_error(os.str()); } } bool selectReportStep(const int step) { - if (graph.selectReportStep(step)) { - auto wsol = Opm::ECLWellSolution{}; - well_fluxes = wsol.solution(graph.rawResultData(), graph.numGrids());; - toolbox.assignConnectionFlux(extractFluxField(graph, compute_fluxes_)); - toolbox.assignInflowFlux(extractWellFlows(graph, well_fluxes)); - return true; - } else { + if (! rstrt.selectReportStep(step)) { return false; } + + { + auto wsol = Opm::ECLWellSolution{}; + well_fluxes = wsol.solution(rstrt, graph.activeGrids()); + } + + toolbox.assignConnectionFlux(extractFluxField(graph, rstrt, compute_fluxes_)); + toolbox.assignInflowFlux(extractWellFlows(graph, well_fluxes)); + + return true; } - Opm::parameter::ParameterGroup param; + Opm::ParameterGroup param; FilePaths file_paths; + Opm::ECLRestartData rstrt; Opm::ECLGraph graph; std::vector well_fluxes; Opm::FlowDiagnostics::Toolbox toolbox; diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/extractFromRestart.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/extractFromRestart.cpp index 4d38286871..060fba34f7 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/extractFromRestart.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/examples/extractFromRestart.cpp @@ -25,20 +25,21 @@ #include #include +#include // Syntax (typical): // extractFromRestart unrst= step= keyword= grid_id= int main(int argc, char* argv[]) { try { - Opm::parameter::ParameterGroup param(argc, argv, + Opm::ParameterGroup param(argc, argv, /*verify_commandline_syntax=*/ true, /*parameter_output=*/ false); const std::string unrst_file = param.get("unrst"); const int report_step = param.getDefault("step", int(0)); - const int grid_id = param.getDefault("grid_id", int(0)); + const std::string grid_id = param.getDefault("grid_id", std::string("")); const std::string keyword = param.get("keyword"); - Opm::ECLResultData restart_file(unrst_file); + Opm::ECLRestartData restart_file(unrst_file); if (!restart_file.selectReportStep(report_step)) { std::cerr << "Could not find report step " << report_step << "." << std::endl; diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.cpp index 91a6e3d3f0..1e597a4064 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.cpp @@ -18,6 +18,8 @@ */ #include +#include + #include namespace Opm @@ -34,11 +36,15 @@ namespace Opm - std::vector ECLFluxCalc::flux(const PhaseIndex /* phase */) const + std::vector + ECLFluxCalc::flux(const ECLRestartData& rstrt, + const PhaseIndex /* phase */) const { // Obtain dynamic data. DynamicData dyn_data; - dyn_data.pressure = graph_.linearisedCellData("PRESSURE", &ECLUnits::UnitSystem::pressure); + dyn_data.pressure = graph_ + .linearisedCellData(rstrt, "PRESSURE", + &ECLUnits::UnitSystem::pressure); // Compute fluxes per connection. const int num_conn = transmissibility_.size(); diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.hpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.hpp index 340b1974b0..3f230ab23f 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.hpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLFluxCalc.hpp @@ -25,6 +25,7 @@ namespace Opm { + class ECLRestartData; /// Class for computing connection fluxes in the absence of flux output. class ECLFluxCalc @@ -45,7 +46,9 @@ namespace Opm /// \return Flux values corresponding to selected phase. /// Empty if required data is missing. /// Numerical values in SI units (rm^3/s). - std::vector flux(const PhaseIndex phase) const; + std::vector + flux(const ECLRestartData& rstrt, + const PhaseIndex phase) const; private: struct DynamicData diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp index d06645c93d..0e3ee28afd 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp @@ -1,6 +1,5 @@ /* - Copyright 2016 SINTEF ICT, Applied Mathematics. - Copyright 2016 Statoil ASA. + Copyright 2016, 2017 Statoil ASA. This file is part of the Open Porous Media Project (OPM). @@ -39,6 +38,7 @@ #include #include #include +#include #include #include @@ -86,6 +86,17 @@ namespace { const ecl_grid_type* getGrid(const ecl_grid_type* G, const int gridID); + /// Retrieve grid name. + /// + /// \param[in] ERT Grid representation. + /// + /// \param[in] gridID Numeric index of requested grid. Zero for the + /// main grid or positive for one of the LGRs. + /// + /// \return Name of grid \p G. Empty for the main grid. + std::string + getGridName(const ecl_grid_type* G, const int gridID); + /// Extract Cartesian dimensions of an ECL grid. /// /// \param[in] G ERT grid instance corresponding to the model's main @@ -99,14 +110,20 @@ namespace { /// Access unit conventions pertaining to single grid in result set. /// + /// \tparam ResultSet Type representing a result set. Must + /// implement methods \code haveKeywordData() \endcode and \code + /// keywordData<>() \endcode. Typically \code Opm::ECLRestartData + /// \endcode or \code Opm::ECLInitFileData \endcode. + /// /// \param[in] rset Result set. /// - /// \param[in] grid_ID Numerical ID of grid. Non-negative. Zero - /// for the main grid and positive for LGRs. + /// \param[in] gridID ID (name) of particular grid. Empty for the + /// main grid. /// - /// \return Unit system convention for \p grid_ID in result set. - auto getUnitSystem(const ::Opm::ECLResultData& rset, - const int grid_ID) + /// \return Unit system convention for \p gridID in result set. + template + auto getUnitSystem(const ResultSet& rset, + const std::string& gridID) -> decltype(::Opm::ECLUnits::createUnitSystem(0)); /// Retrieve global pore-volume vector from INIT source. @@ -117,15 +134,15 @@ namespace { /// /// \param[in] init ERT representation of INIT source. /// - /// \param[in] grid_ID Numerical ID of grid. Non-negative. Zero - /// for the main grid and positive in the case of an LGR. + /// \param[in] gridID ID (name) of grid. Empty for the main grid + /// and non-empty in the case of an LGR. /// /// \return Vector of pore-volumes for all global cells of \p G in /// SI unit conventions (rm^3). std::vector - getPVolVector(const ecl_grid_type* G, - const ::Opm::ECLResultData& init, - const int grid_ID = 0); + getPVolVector(const ecl_grid_type* G, + const ::Opm::ECLInitFileData& init, + const std::string& gridID = ""); /// Extract non-neighbouring connections from ECLIPSE model /// @@ -137,9 +154,10 @@ namespace { /// \return Model's non-neighbouring connections, including those /// between main and local grids. std::vector - loadNNC(const ecl_grid_type* G, - const ::Opm::ECLResultData& init); + loadNNC(const ecl_grid_type* G, + const ecl_file_type* init); + /// Cartesian connections in a model grid. class CartesianGridData { public: @@ -153,15 +171,17 @@ namespace { /// /// \param[in] gridID Numeric identifier of this grid. Zero for /// main grid, positive for LGRs. - CartesianGridData(const ecl_grid_type* G, - const ::Opm::ECLResultData& init, - const int gridID); + CartesianGridData(const ecl_grid_type* G, + const ::Opm::ECLInitFileData& init, + const int gridID); /// Retrieve non-negative numeric ID of grid instance. /// /// \return Constructor's \c gridID parameter. int gridID() const; + const std::string& gridName() const; + /// Retrieve number of active cells in graph. std::size_t numCells() const; @@ -218,14 +238,15 @@ namespace { /// /// \return Numerical values of result set vector, relative to /// global cell numbering of this grid. + template std::vector - cellData(const ::Opm::ECLResultData& src, - const std::string& vector) const; + cellData(const ResultSet& rset, + const std::string& vector) const; - template + template std::vector - activeCellData(const ::Opm::ECLResultData& src, - const std::string& vector) const; + activeCellData(const ResultSet& rset, + const std::string& vector) const; /// Retrieve values of result set vector for all Cartesian /// connections in grid. @@ -238,9 +259,9 @@ namespace { /// \return Numerical values of result set vector attributed to /// all of the grid's Cartesian connections. std::vector - connectionData(const ::Opm::ECLResultData& src, - const std::string& vector, - const double unit) const; + connectionData(const ::Opm::ECLRestartData& rstrt, + const std::string& vector, + const double unit) const; private: /// Facility for deriving Cartesian neighbourship in a grid @@ -424,6 +445,9 @@ namespace { /// than zero for LGRs. const int gridID_; + /// Grid name. Mostly for querying properties in local grids. + const std::string gridName_; + /// Map results from active to global cells. CartesianCells cells_; @@ -445,14 +469,19 @@ namespace { /// Predicate for whether or not a particular result vector is /// defined on the grid's cells. /// - /// \param[in] src Result set. + /// \tparam ResultSet Representation of an ECLIPSE result set. + /// Typically \code Opm::ECLInitFileData \endcode or \code + /// Opm::ECLRestartData \endcode. + /// + /// \param[in] rset Result set. /// /// \param[in] vector Name of result vector. /// - /// \return Whether or not \p vector is defined on model's - /// cells and part of the result set \p src. - bool haveCellData(const ::Opm::ECLResultData& src, - const std::string& keyword) const; + /// \return Whether or not \p vector is defined on model's cells + /// and part of the result set \p src. + template + bool haveCellData(const ResultSet& rset, + const std::string& keyword) const; /// Predicate for whether or not a particular result vector is /// defined on the grid's Cartesian connections. @@ -462,10 +491,10 @@ namespace { /// \param[in] vector Prefix of result vector name. /// /// \return Whether or not all vectors formed by \p vector plus - /// known directional suffixes are defined on model's cells and - /// part of the result set \p src. - bool haveConnData(const ::Opm::ECLResultData& src, - const std::string& keyword) const; + /// known directional suffixes are defined on model's cells + /// and part of the result set \p src. + bool haveConnData(const ::Opm::ECLRestartData& rstrt, + const std::string& keyword) const; /// Append directional cell data to global collection of /// connection data identified by vector name prefix. @@ -480,7 +509,7 @@ namespace { /// input, collection of values corresponding to any previous /// directions (preserved), and on output additionally contains /// the data corresponding to the Cartesian direction \p d. - void connectionData(const ::Opm::ECLResultData& src, + void connectionData(const ::Opm::ECLRestartData& rstrt, const CartesianCells::Direction d, const std::string& vector, const double unit, @@ -510,7 +539,7 @@ namespace { /// /// \param[in] init Internalised void deriveNeighbours(const std::vector& gcells, - const ::Opm::ECLResultData& init, + const ::Opm::ECLInitFileData& init, const CartesianCells::Direction d); }; } // namespace ECL @@ -535,10 +564,20 @@ ECL::getGrid(const ecl_grid_type* G, const int gridID) return ecl_grid_iget_lgr(G, gridID - 1); } +std::string +ECL::getGridName(const ecl_grid_type* G, const int gridID) +{ + if (gridID == ECL_GRID_MAINGRID_LGR_NR) { + return ""; // Empty for main grid. + } + + return ecl_grid_get_name(G); +} + std::vector -ECL::getPVolVector(const ecl_grid_type* G, - const ::Opm::ECLResultData& init, - const int gridID) +ECL::getPVolVector(const ecl_grid_type* G, + const ::Opm::ECLInitFileData& init, + const std::string& gridID) { auto make_szt = [](const int i) { @@ -578,8 +617,8 @@ ECL::loadCase(const boost::filesystem::path& grid) if (! G) { std::ostringstream os; - os << "Failed to load ECL Grid from '" - << grid.generic_string() << '\''; + os << "Failed to load ECL Grid from " + << grid.generic_string(); throw std::invalid_argument(os.str()); } @@ -600,21 +639,40 @@ ECL::cartesianDimensions(const ecl_grid_type* G) make_szt(ecl_grid_get_nz(G)) } }; } -auto ECL::getUnitSystem(const ::Opm::ECLResultData& rset, - const int grid_ID) +template +auto ECL::getUnitSystem(const ResultSet& rset, + const std::string& grid_ID) -> decltype(::Opm::ECLUnits::createUnitSystem(0)) { assert (rset.haveKeywordData(INTEHEAD_KW, grid_ID) && "Result Set Does Not Provide Grid Header"); - const auto ih = rset.keywordData(INTEHEAD_KW, grid_ID); + const auto ih = rset.template keywordData(INTEHEAD_KW, grid_ID); - return ::Opm::ECLUnits::createUnitSystem(ih[INTEHEAD_UNIT_INDEX]); + const auto usys = ih[INTEHEAD_UNIT_INDEX]; + const auto validUsys = (usys >= 1) && (usys <= 4); + + if (! validUsys) { + if (! grid_ID.empty()) { + // Unity system not provided in local grid. Fall back to + // querying the main grid instead. + + const auto mainGrid = std::string{ "" }; + + return getUnitSystem(rset, mainGrid); + } + + throw std::out_of_range { + "No Valid Unit System Key in Result-Set" + }; + } + + return ::Opm::ECLUnits::createUnitSystem(usys); } std::vector -ECL::loadNNC(const ecl_grid_type* G, - const ::Opm::ECLResultData& init) +ECL::loadNNC(const ecl_grid_type* G, + const ecl_file_type* init) { auto make_szt = [](const int n) { @@ -628,7 +686,7 @@ ECL::loadNNC(const ecl_grid_type* G, if (numNNC > 0) { nncData.resize(numNNC); - ecl_nnc_export(G, init.getRawFilePtr(), nncData.data()); + ecl_nnc_export(G, init, nncData.data()); } return nncData; @@ -853,7 +911,7 @@ ECL::CartesianGridData::CartesianCells::numActiveCells() const { return this->rsMap_.subset.size(); } - + std::size_t ECL::CartesianGridData:: CartesianCells::globIdx(const IndexTuple& ijk) const @@ -890,11 +948,12 @@ CartesianCells::ind2sub(const std::size_t globalCell) const // ====================================================================== ECL::CartesianGridData:: -CartesianGridData(const ecl_grid_type* G, - const ::Opm::ECLResultData& init, - const int gridID) - : gridID_(gridID) - , cells_ (G, ::ECL::getPVolVector(G, init, gridID_)) +CartesianGridData(const ecl_grid_type* G, + const ::Opm::ECLInitFileData& init, + const int gridID) + : gridID_ (gridID) + , gridName_(::ECL::getGridName(G, gridID)) + , cells_ (G, ::ECL::getPVolVector(G, init, gridName_)) { { using VT = DirectionSuffix::value_type; @@ -923,6 +982,12 @@ int ECL::CartesianGridData::gridID() const return this->gridID_; } +const std::string& +ECL::CartesianGridData::gridName() const +{ + return this->gridName_; +} + std::size_t ECL::CartesianGridData::numCells() const { @@ -973,48 +1038,51 @@ ECL::CartesianGridData::isSubdivided(const int cellID) const return this->cells_.isSubdivided(cellID); } +template std::vector ECL::CartesianGridData:: -cellData(const ::Opm::ECLResultData& src, - const std::string& vector) const +cellData(const ResultSet& rset, + const std::string& vector) const { - if (! this->haveCellData(src, vector)) { + if (! this->haveCellData(rset, vector)) { return {}; } - auto x = src.keywordData(vector, this->gridID_); + const auto x = + rset.template keywordData(vector, this->gridName()); return this->cells_.scatterToGlobal(x); } namespace { namespace ECL { - template + template std::vector - CartesianGridData::activeCellData(const ::Opm::ECLResultData& src, - const std::string& vector) const + CartesianGridData::activeCellData(const ResultSet& rset, + const std::string& vector) const { - if (! this->haveCellData(src, vector)) { + if (! this->haveCellData(rset, vector)) { return {}; } - auto x = src.keywordData(vector, this->gridID_); + auto x = rset.template keywordData(vector, this->gridName()); return this->cells_.gatherToActive(std::move(x)); } }} // namespace Anonymous::ECL +template bool ECL::CartesianGridData:: -haveCellData(const ::Opm::ECLResultData& src, - const std::string& vector) const +haveCellData(const ResultSet& rset, + const std::string& vector) const { - return src.haveKeywordData(vector, this->gridID_); + return rset.template haveKeywordData(vector, this->gridName()); } bool ECL::CartesianGridData:: -haveConnData(const ::Opm::ECLResultData& src, - const std::string& vector) const +haveConnData(const ::Opm::ECLRestartData& rstrt, + const std::string& vector) const { auto have_data = true; @@ -1024,7 +1092,7 @@ haveConnData(const ::Opm::ECLResultData& src, { const auto vname = this->vectorName(vector, d); - have_data = this->haveCellData(src, vname); + have_data = this->haveCellData(rstrt, vname); if (! have_data) { break; } } @@ -1034,11 +1102,11 @@ haveConnData(const ::Opm::ECLResultData& src, std::vector ECL::CartesianGridData:: -connectionData(const ::Opm::ECLResultData& src, - const std::string& vector, - const double unit) const +connectionData(const ::Opm::ECLRestartData& rstrt, + const std::string& vector, + const double unit) const { - if (! this->haveConnData(src, vector)) { + if (! this->haveConnData(rstrt, vector)) { return {}; } @@ -1048,7 +1116,9 @@ connectionData(const ::Opm::ECLResultData& src, CartesianCells::Direction::J , CartesianCells::Direction::K }) { - this->connectionData(src, d, this->vectorName(vector, d), unit, x); + const auto vname = this->vectorName(vector, d); + + this->connectionData(rstrt, d, vname, unit, x); } return x; @@ -1056,13 +1126,13 @@ connectionData(const ::Opm::ECLResultData& src, void ECL::CartesianGridData:: -connectionData(const ::Opm::ECLResultData& src, +connectionData(const ::Opm::ECLRestartData& rstrt, const CartesianCells::Direction d, const std::string& vector, const double unit, std::vector& x) const { - const auto v = this->cellData(src, vector); + const auto v = this->cellData(rstrt, vector); const auto& cells = this->outCell_.find(d); @@ -1090,7 +1160,7 @@ vectorName(const std::string& vector, void ECL::CartesianGridData:: deriveNeighbours(const std::vector& gcells, - const ::Opm::ECLResultData& init, + const ::Opm::ECLInitFileData& init, const CartesianCells::Direction d) { auto tran = std::string{"TRAN"}; @@ -1112,12 +1182,12 @@ deriveNeighbours(const std::vector& gcells, throw std::invalid_argument("Input direction must be (I,J,K)"); } - const auto& T = init.haveKeywordData(tran, this->gridID_) + const auto& T = init.haveKeywordData(tran, this->gridName()) ? this->cellData(init, tran) : std::vector(this->cells_.numGlobalCells(), 1.0); const auto trans_unit = - ECL::getUnitSystem(init, this->gridID_)->transmissibility(); + ECL::getUnitSystem(init, this->gridName())->transmissibility(); auto SI_trans = [trans_unit](const double trans) { @@ -1166,7 +1236,7 @@ public: /// \param[in] grid Name or prefix of ECL grid (i.e., .GRID or /// .EGRID) file. /// - /// \param[in] init Name of ECL INIT file corresponding to \p grid + /// \param[in] init ECL INIT result set corresponding to \p grid /// input. Assumed to provide at least a complete set /// of pore-volume values (i.e., for all global cells /// defined in the \p grid). @@ -1174,13 +1244,8 @@ public: /// If available in the INIT file, the constructor will /// also leverage the transmissibility data when /// constructing the active cell neighbourship table. - Impl(const Path& grid, const Path& init); - - /// Assign source object for phase flux calculation. - /// - /// \param[in] src Name of ECL restart file, possibly unified, from - /// which next set of phase fluxes should be retrieved. - void assignDataSource(const Path& src); + Impl(const boost::filesystem::path& grid, + const ECLInitFileData& init); /// Retrieve number of grids. /// @@ -1200,7 +1265,7 @@ public: /// ijk from specified grid. Negative one (-1) if (I,J,K) outside /// valid range or if the specific cell identified by \p ijk and \p /// gridID is not actually active. - int activeCell(const int gridID, + int activeCell(const std::string& gridID, const std::array& ijk) const; /// Retrieve number of active cells in graph. @@ -1215,6 +1280,11 @@ public: /// flux() may return non-zero values. const std::vector& activePhases() const; + /// Retrieve the simulation scenario's set of active grids. + /// + /// Mostly for canonical lookup of result data in LGRs. + const std::vector& activeGrids() const; + /// Retrieve neighbourship relations between active cells. /// /// The \c i-th connection is between active cells \code @@ -1238,24 +1308,6 @@ public: /// \endcode. std::vector transmissibility() const; - /// Restrict dynamic result set data to single report step. - /// - /// This method must be called before calling either flux() or - /// rawResultData(). - /// - /// \param[in] rptstep Selected temporal vector. Report-step ID. - /// - /// \return Whether or not dynamic data for the requested report step - /// exists in the underlying result set identified in method - /// assignDataSource(). - bool selectReportStep(const int rptstep) const; - - /// Access underlying result set. - /// - /// The result set dynamic data corresponds to the most recent call to - /// method selectReportStep(). - const ::Opm::ECLResultData& rawResultData() const; - /// Retrieve phase flux on all connections defined by \code neighbours() /// \endcode. /// @@ -1269,15 +1321,56 @@ public: /// reported due to report frequencies or no flux values are output at /// all). std::vector - flux(const PhaseIndex phase) const; + flux(const ECLRestartData& rstrt, + const PhaseIndex phase) const; - template + /// Retrieve result set vector from current view linearised on active + /// cells. + /// + /// \tparam T Element type of result set vector. + /// + /// \tparam ResultSet Implementation of an ECL Result Set. Typically + /// \code Opm::ECLRestartData \endcode or \code Opm::ECLInitFileData + /// \endcode. + /// + /// \param[in] rset ECL Result set. Typically an instance of \code + /// Opm::ECLRestartData \endcode or \code Opm::ECLInitFileData + /// \endcode. + /// + /// \param[in] vector Name of result set vector. + /// + /// \return Result set vector linearised on active cells. + template std::vector - rawLinearisedCellData(const std::string& vector) const; + rawLinearisedCellData(const ResultSet& rset, + const std::string& vector) const; + /// Retrieve floating-point result set vector from current view + /// (e.g., particular report step) linearised on active cells and + /// converted to strict SI unit conventions. + /// + /// Typical call: + /// \code + /// const auto press = + /// lCD(rstrt, "PRESSURE", &ECLUnits::UnitSystem::pressure); + /// \endcode + /// + /// \param[in] rstrt ECL Restart dataset. It is the responsibility of + /// the caller to ensure that the restart data is correctly + /// positioned on a particular report step. + /// + /// \param[in] vector Name of result set vector. + /// + /// \param[in] unit Call-back hook in \c UnitSystem implementation + /// that enables converting the raw result data to strict SI unit + /// conventions. Hook is called for each grid in the result set. + /// + /// \return Result set vector linearised on active cells, converted + /// to strict SI unit conventions. std::vector - linearisedCellData(const std::string& vector, - UnitConvention unit) const; + linearisedCellData(const ECLRestartData& rstrt, + const std::string& vector, + UnitConvention unit) const; private: /// Collection of non-Cartesian neighbourship relations attributed to a @@ -1518,8 +1611,10 @@ private: /// the simulation run. std::vector activePhases_; - /// Current result set. - std::unique_ptr src_; + /// Set of active grids in result set. + std::vector activeGrids_; + + std::unordered_map gridID_; /// Extract explicit non-neighbouring connections from ECL output. /// @@ -1528,15 +1623,13 @@ private: /// \param[in] G ERT Grid representation. /// /// \param[in] init ERT representation of INIT source. - /// - /// \param[in] coll Backing data for neighbourship extraction. - void defineNNCs(const ecl_grid_type* G, - const ::Opm::ECLResultData& init); + void defineNNCs(const ecl_grid_type* G, + const ECLInitFileData& init); /// Extract scenario's set of active phases. /// /// Writes to activePhases_. - void defineActivePhases(const ::Opm::ECLResultData& init); + void defineActivePhases(const ::Opm::ECLInitFileData& init); /// Compute ECL vector basename for particular phase flux. /// @@ -1554,6 +1647,8 @@ private: /// \tparam[in] GetFluxUnit Type of function object for computing the /// grid-dependent flux unit. /// + /// \param[in] rstrt ECL Restart data result set. + /// /// \param[in] vector Result set vector prefix. Typically computed by /// method flowVector(). /// @@ -1572,9 +1667,10 @@ private: /// contains those values that correspond to the non-neighbouring /// connections (appended onto \p flux). template - void fluxNNC(const std::string& vector, - GetFluxUnit&& fluxUnit, - std::vector& flux) const; + void fluxNNC(const ECLRestartData& rstrt, + const std::string& vector, + GetFluxUnit&& fluxUnit, + std::vector& flux) const; }; // ====================================================================== @@ -1763,12 +1859,10 @@ isViable(const std::vector& grids, // ====================================================================== -Opm::ECLGraph::Impl::Impl(const Path& grid, const Path& init) +Opm::ECLGraph::Impl::Impl(const boost::filesystem::path& grid, + const ECLInitFileData& init) { const auto G = ECL::loadCase(grid); - auto I = ::Opm::ECLResultData{ init }; - - I.selectGlobalView(); const auto numGrids = ECL::numGrids(G.get()); @@ -1779,41 +1873,42 @@ Opm::ECLGraph::Impl::Impl(const Path& grid, const Path& init) for (auto gridID = 0*numGrids; gridID < numGrids; ++gridID) { this->grid_.emplace_back(ECL::getGrid(G.get(), gridID), - I, gridID); + init, gridID); this->activeOffset_.push_back(this->activeOffset_.back() + this->grid_.back().numCells()); + + this->activeGrids_.push_back(this->grid_.back().gridName()); + + this->gridID_[this->activeGrids_.back()] = gridID; } - this->defineNNCs(G.get(), I); - this->defineActivePhases(I); -} - -void -Opm::ECLGraph::Impl::assignDataSource(const Path& src) -{ - this->src_.reset(new ECLResultData(src)); + this->defineNNCs(G.get(), init); + this->defineActivePhases(init); } int -Opm::ECLGraph::Impl:: -numGrids() const +Opm::ECLGraph::Impl::numGrids() const { return grid_.size(); } int Opm::ECLGraph::Impl:: -activeCell(const int gridID, +activeCell(const std::string& gridID, const std::array& ijk) const { - const auto gIdx = - static_castgrid_.size())>(gridID); - - if (gIdx >= this->grid_.size()) { + const auto gID = this->gridID_.find(gridID); + if (gID == std::end(this->gridID_)) { return -1; } + const auto gIdx = + static_castgrid_.size())>(gID->second); + + assert ((gIdx <= this->grid_.size()) && + "Logic Error in ECLGraph::Impl::Impl()"); + const auto& grid = this->grid_[gIdx]; const auto active = grid.activeCell(ijk[0], ijk[1], ijk[2]); @@ -1851,6 +1946,12 @@ Opm::ECLGraph::Impl::activePhases() const return this->activePhases_; } +const std::vector& +Opm::ECLGraph::Impl::activeGrids() const +{ + return this->activeGrids_; +} + std::vector Opm::ECLGraph::Impl::neighbours() const { @@ -1925,24 +2026,13 @@ Opm::ECLGraph::Impl::transmissibility() const return trans; } -const ::Opm::ECLResultData& -Opm::ECLGraph::Impl::rawResultData() const -{ - return *this->src_; -} - -bool Opm::ECLGraph::Impl::selectReportStep(const int rptstep) const -{ - return this->src_->selectReportStep(rptstep); -} - std::vector -Opm::ECLGraph::Impl:: -flux(const PhaseIndex phase) const +Opm::ECLGraph::Impl::flux(const ECLRestartData& rstrt, + const PhaseIndex phase) const { - auto fluxUnit = [this](const int gridID) + auto fluxUnit = [&rstrt](const std::string& gridID) { - return ::ECL::getUnitSystem(*this->src_, gridID)->reservoirRate(); + return ::ECL::getUnitSystem(rstrt, gridID)->reservoirRate(); }; const auto vector = this->flowVector(phase); @@ -1956,7 +2046,7 @@ flux(const PhaseIndex phase) const for (const auto& G : this->grid_) { const auto& q = - G.connectionData(*this->src_, vector, fluxUnit(G.gridID())); + G.connectionData(rstrt, vector, fluxUnit(G.gridName())); if (q.empty()) { // Flux vector invalid unless all grids provide this result @@ -1971,7 +2061,7 @@ flux(const PhaseIndex phase) const // Model includes non-neighbouring connections such as faults and/or // local grid refinement. Extract pertinent flux values for these // connections. - this->fluxNNC(vector, std::move(fluxUnit), v); + this->fluxNNC(rstrt, vector, std::move(fluxUnit), v); } if (v.size() < totconn) { @@ -1985,14 +2075,15 @@ flux(const PhaseIndex phase) const namespace Opm { - template + template std::vector - ECLGraph::Impl::rawLinearisedCellData(const std::string& vector) const + ECLGraph::Impl::rawLinearisedCellData(const ResultSet& rset, + const std::string& vector) const { auto x = std::vector{}; x.reserve(this->numCells()); for (const auto& G : this->grid_) { - const auto xi = G.activeCellData(*this->src_, vector); + const auto xi = G.activeCellData(rset, vector); x.insert(x.end(), std::begin(xi), std::end(xi)); } @@ -2006,19 +2097,20 @@ namespace Opm { } // namespace Opm std::vector -Opm::ECLGraph::Impl::linearisedCellData(const std::string& vector, - UnitConvention unit) const +Opm::ECLGraph::Impl::linearisedCellData(const ECLRestartData& rstrt, + const std::string& vector, + UnitConvention unit) const { auto x = std::vector{}; x.reserve(this->numCells()); for (const auto& G : this->grid_) { - const auto xi = G.activeCellData(*this->src_, vector); + const auto xi = G.activeCellData(rstrt, vector); if (xi.empty()) { continue; } // Note: Compensate for incrementing Grid ID above. const auto usys = - ECL::getUnitSystem(*this->src_, G.gridID()); + ECL::getUnitSystem(rstrt, G.gridName()); // Note: 'usys' (generally, std::unique_ptr<>) does not support // regular PMF syntax (i.e., operator->*()). @@ -2040,25 +2132,28 @@ Opm::ECLGraph::Impl::linearisedCellData(const std::string& vector, } void -Opm::ECLGraph::Impl::defineNNCs(const ecl_grid_type* G, - const ::Opm::ECLResultData& init) +Opm::ECLGraph::Impl::defineNNCs(const ecl_grid_type* G, + const ECLInitFileData& init) { // Assume all transmissibilites in the result set follow the same unit // conventions. - const auto trans_unit = - ECL::getUnitSystem(init, 0)->transmissibility(); + const auto gridID = std::string{ "" }; // Empty in main grid. - for (const auto& nnc : ECL::loadNNC(G, init)) { + const auto trans_unit = + ECL::getUnitSystem(init, gridID)->transmissibility(); + + for (const auto& nnc : ECL::loadNNC(G, init.getRawFilePtr())) { this->nnc_.add(this->grid_, this->activeOffset_, trans_unit, nnc); } } template void -Opm::ECLGraph::Impl::fluxNNC(const std::string& vector, - GetFluxUnit&& fluxUnit, - std::vector& flux) const +Opm::ECLGraph::Impl::fluxNNC(const ECLRestartData& rstrt, + const std::string& vector, + GetFluxUnit&& fluxUnit, + std::vector& flux) const { auto v = std::vector(this->nnc_.numConnections(), 0.0); auto assigned = std::vector(v.size(), false); @@ -2068,28 +2163,31 @@ Opm::ECLGraph::Impl::fluxNNC(const std::string& vector, const auto fluxID = rel.makeKeyword(vector); for (const auto& G : this->grid_) { - const auto gridID = G.gridID(); + const auto& gridName = G.gridName(); const auto& iset = - rel.indexSet().getGridCollection(gridID); + rel.indexSet().getGridCollection(G.gridID()); - if (iset.empty()) { - // No NNCs for this category in this grid. Skip. + if (iset.empty() || + ! rstrt.haveKeywordData(fluxID, gridName)) + { + // No NNCs for this category in this grid or corresponding + // flux vector does not exist. Skip. continue; } - // Note: Method name is confusing, but does actually do what we - // want here. - const auto q = G.cellData(*this->src_, fluxID); + const auto q = rstrt.keywordData(fluxID, gridName); if (q.empty()) { - // No flux data for this category in this grid. Skip. + // Empty flux data for this category in this grid. Not + // really supposed to happen if the above check fires, but + // skip this (category,gridID) pair nonetheless. continue; } - const auto flux_unit = fluxUnit(gridID); + const auto flux_unit = fluxUnit(gridName); - // Data fully available for (category,gridID). Assign + // Data fully available for (category,gridName). Assign // approriate subset of NNC flux vector. for (const auto& ix : iset) { assert (ix.neighIdx < v.size()); @@ -2118,10 +2216,12 @@ Opm::ECLGraph::Impl::fluxNNC(const std::string& vector, void Opm::ECLGraph::Impl:: -defineActivePhases(const ::Opm::ECLResultData& init) +defineActivePhases(const ::Opm::ECLInitFileData& init) { + const auto gridID = std::string{ "" }; // Empty in main grid. + const auto ih = - init.keywordData(INTEHEAD_KW, ECL_GRID_MAINGRID_LGR_NR); + init.keywordData(INTEHEAD_KW, gridID); const auto phaseMask = static_cast(ih[INTEHEAD_PHASE_INDEX]); @@ -2143,8 +2243,7 @@ defineActivePhases(const ::Opm::ECLResultData& init) } std::string -Opm::ECLGraph::Impl:: -flowVector(const PhaseIndex phase) const +Opm::ECLGraph::Impl::flowVector(const PhaseIndex phase) const { const auto vector = std::string("FLR"); // Flow-rate, reservoir @@ -2193,40 +2292,32 @@ Opm::ECLGraph::operator=(ECLGraph&& rhs) } Opm::ECLGraph -Opm::ECLGraph::load(const Path& grid, const Path& init) +Opm::ECLGraph::load(const boost::filesystem::path& grid, + const ECLInitFileData& init) { auto pImpl = ImplPtr{new Impl(grid, init)}; return { std::move(pImpl) }; } -int -Opm::ECLGraph::numGrids() const +int Opm::ECLGraph::numGrids() const { return this->pImpl_->numGrids(); } int Opm::ECLGraph::activeCell(const std::array& ijk, - const int gridID) const + const std::string& gridID) const { return this->pImpl_->activeCell(gridID, ijk); } -void -Opm::ECLGraph::assignFluxDataSource(const Path& src) -{ - this->pImpl_->assignDataSource(src); -} - -std::size_t -Opm::ECLGraph::numCells() const +std::size_t Opm::ECLGraph::numCells() const { return this->pImpl_->numCells(); } -std::size_t -Opm::ECLGraph::numConnections() const +std::size_t Opm::ECLGraph::numConnections() const { return this->pImpl_->numConnections(); } @@ -2237,6 +2328,12 @@ Opm::ECLGraph::activePhases() const return this->pImpl_->activePhases(); } +const std::vector& +Opm::ECLGraph::activeGrids() const +{ + return this->pImpl_->activeGrids(); +} + std::vector Opm::ECLGraph::neighbours() const { return this->pImpl_->neighbours(); @@ -2252,45 +2349,47 @@ std::vector Opm::ECLGraph::transmissibility() const return this->pImpl_->transmissibility(); } -bool Opm::ECLGraph::selectReportStep(const int rptstep) const -{ - return this->pImpl_->selectReportStep(rptstep); -} - -const Opm::ECLResultData& -Opm::ECLGraph::rawResultData() const -{ - return this->pImpl_->rawResultData(); -} - std::vector -Opm::ECLGraph:: -flux(const PhaseIndex phase) const +Opm::ECLGraph::flux(const ECLRestartData& rstrt, + const PhaseIndex phase) const { - return this->pImpl_->flux(phase); + return this->pImpl_->flux(rstrt, phase); } namespace Opm { - template + template std::vector - ECLGraph::rawLinearisedCellData(const std::string& vector) const + ECLGraph::rawLinearisedCellData(const ResultSet& rset, + const std::string& vector) const { - return this->pImpl_->rawLinearisedCellData(vector); + return this->pImpl_->rawLinearisedCellData(rset, vector); } - // Explicit instantiations for the element types we care about. + // Explicit instantiations of method rawLinearisedCellData() for the + // element and result set types we care about. template std::vector - ECLGraph::rawLinearisedCellData(const std::string& vector) const; + ECLGraph::rawLinearisedCellData(const ECLInitFileData& rset, + const std::string& vector) const; + + template std::vector + ECLGraph::rawLinearisedCellData(const ECLRestartData& rset, + const std::string& vector) const; template std::vector - ECLGraph::rawLinearisedCellData(const std::string& vector) const; + ECLGraph::rawLinearisedCellData(const ECLInitFileData& rset, + const std::string& vector) const; + + template std::vector + ECLGraph::rawLinearisedCellData(const ECLRestartData& rset, + const std::string& vector) const; } // namespace Opm std::vector -Opm::ECLGraph::linearisedCellData(const std::string& vector, - UnitConvention unit) const +Opm::ECLGraph::linearisedCellData(const ECLRestartData& rstrt, + const std::string& vector, + UnitConvention unit) const { - return this->pImpl_->linearisedCellData(vector, unit); + return this->pImpl_->linearisedCellData(rstrt, vector, unit); } diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.hpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.hpp index 62204e5722..ff60cf67dc 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.hpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.hpp @@ -1,6 +1,5 @@ /* - Copyright 2016 SINTEF ICT, Applied Mathematics. - Copyright 2016 Statoil ASA. + Copyright 2016, 2017 Statoil ASA. This file is part of the Open Porous Media Project (OPM). @@ -27,6 +26,7 @@ #include #include #include +#include #include #include @@ -45,8 +45,6 @@ namespace Opm { class ECLGraph { public: - using Path = boost::filesystem::path; - /// Enum for indicating requested phase from the flux() method. enum class PhaseIndex { Aqua = 0, Liquid = 1, Vapour = 2 }; @@ -93,17 +91,12 @@ namespace Opm { /// \return Fully formed ECLIPSE connection graph with property /// associations. static ECLGraph - load(const Path& grid, const Path& init); + load(const boost::filesystem::path& gridFile, + const ECLInitFileData& init); - /// Assign source object for phase flux calculation. + /// Retrieve number of grids in model. /// - /// \param[in] src Name of ECL restart file, possibly unified, from - /// which next set of phase fluxes should be retrieved. - void assignFluxDataSource(const Path& src); - - /// Retrieve number of grids. - /// - /// \return The number of LGR grids plus one (the main grid). + /// \return The number of LGR grids plus one (the main grid). int numGrids() const; /// Retrieve active cell ID from (I,J,K) tuple in particular grid. @@ -120,7 +113,7 @@ namespace Opm { /// outside valid range or if the specific cell identified by \p /// ijk and \p gridID is not actually active. int activeCell(const std::array& ijk, - const int gridID = 0) const; + const std::string& gridID = 0) const; /// Retrieve number of active cells in graph. std::size_t numCells() const; @@ -134,6 +127,11 @@ namespace Opm { /// which flux() will return non-zero values if data available. const std::vector& activePhases() const; + /// Retrieve the simulation scenario's set of active grids. + /// + /// Mostly for canonical lookup of result data in LGRs. + const std::vector& activeGrids() const; + /// Retrieve neighbourship relations between active cells. /// /// The \c i-th connection is between active cells \code @@ -157,24 +155,6 @@ namespace Opm { /// \endcode. std::vector transmissibility() const; - /// Restrict dynamic result set data to single report step. - /// - /// This method must be called before calling either flux() or - /// rawResultData(). - /// - /// \param[in] rptstep Selected temporal vector. Report-step ID. - /// - /// \return Whether or not dynamic data for the requested report - /// step exists in the underlying result set identified in method - /// assignFluxDataSource(). - bool selectReportStep(const int rptstep) const; - - /// Access underlying result set. - /// - /// The result set dynamic data corresponds to the most recent call - /// to method selectReportStep(). - const ::Opm::ECLResultData& rawResultData() const; - /// Retrieve phase flux on all connections defined by \code /// neighbours() \endcode. /// @@ -186,7 +166,8 @@ namespace Opm { /// output to the restart file). Numerical values in SI units /// (rm^3/s). std::vector - flux(const PhaseIndex phase) const; + flux(const ECLRestartData& rstrt, + const PhaseIndex phase) const; /// Retrieve result set vector from current view (e.g., particular /// report step) linearised on active cells. @@ -196,9 +177,10 @@ namespace Opm { /// \param[in] vector Name of result set vector. /// /// \return Result set vector linearised on active cells. - template + template std::vector - rawLinearisedCellData(const std::string& vector) const; + rawLinearisedCellData(const ResultSet& rset, + const std::string& vector) const; /// Convenience type alias for \c UnitSystem PMFs (pointer to member /// function). @@ -211,9 +193,13 @@ namespace Opm { /// Typical call: /// \code /// const auto press = - /// lCD("PRESSURE", &ECLUnits::UnitSystem::pressure); + /// lCD(rstrt, "PRESSURE", &ECLUnits::UnitSystem::pressure); /// \endcode /// + /// \param[in] rstrt ECL Restart dataset. It is the responsibility + /// of the caller to ensure that the restart data is correctly + /// positioned on a particular report step. + /// /// \param[in] vector Name of result set vector. /// /// \param[in] unit Call-back hook in \c UnitSystem implementation @@ -223,8 +209,9 @@ namespace Opm { /// \return Result set vector linearised on active cells, converted /// to strict SI unit conventions. std::vector - linearisedCellData(const std::string& vector, - UnitConvention unit) const; + linearisedCellData(const ECLRestartData& rstrt, + const std::string& vector, + UnitConvention unit) const; private: /// Implementation class. diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.cpp index 9677d7b180..2add62a4e6 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.cpp @@ -1,6 +1,5 @@ /* - Copyright 2016 SINTEF ICT, Applied Mathematics. - Copyright 2016 Statoil ASA. + Copyright 2016, 2017 Statoil ASA. This file is part of the Open Porous Media Project (OPM). @@ -28,9 +27,15 @@ #include #include #include +#include +#include +#include #include #include +#include +#include #include +#include #include #include @@ -68,9 +73,16 @@ namespace { } namespace ECLImpl { - using FilePtr = ::ERT::ert_unique_ptr; + using FilePtr = std::shared_ptr; namespace Details { + + inline std::string + firstBlockKeyword(const ecl_file_view_type* block) + { + return ecl_kw_get_header(ecl_file_view_iget_kw(block, 0)); + } + /// Convert vector of elements from one element type to another. /// /// \tparam Input Element type of input collection. @@ -378,11 +390,122 @@ namespace { i < nkw; ++i) { result.emplace_back(ecl_kw_iget_char_ptr(kw, i)); + + // Trim trailing white-space. + auto& s = result.back(); + + const auto e = s.find_last_not_of(" \t"); + if (e != std::string::npos) { + s = s.substr(0, e + 1); + } } return result; } }; + + /// Translate grid names to (local) numeric IDs within a + /// section/view of an ECL result set. + /// + /// Provides a caching mechanism to accelerate repeated lookup. + class GridIDCache + { + public: + /// Constructor + /// + /// \param[in] block View relative to which to interpret grid + /// names. + explicit GridIDCache(const ecl_file_view_type* block); + + /// Get integral grid ID of particular grid relative to cache's + /// view. + /// + /// \param[in] gridName Name of particular grid. Empty for the + /// main grid (grid ID 0). + /// + /// \return Numeric grid ID of \p gridName. Negative if \p + /// gridName does not correspond to a grdi in the cache's + /// view. + int getGridID(const std::string& gridName) const; + + private: + /// View into ECL result set. + const ecl_file_view_type* block_; + + /// Cache of name->ID map. + mutable std::unordered_map cache_; + }; + + /// Partition INIT file into sections + class InitFileSections + { + public: + explicit InitFileSections(const ecl_file_type* init); + + struct Section { + Section(const ecl_file_view_type* blk) + : block (blk) + , first_kw(Details::firstBlockKeyword(block)) + {} + + const ecl_file_view_type* block; + std::string first_kw; + }; + + const std::vector

& sections() const + { + return this->sect_; + } + + using SectionID = std::vector
::size_type; + + SectionID numSections() const + { + return this->sections().size(); + } + + const Section& operator[](const SectionID i) const + { + assert ((i < this->numSections()) && "Internal Error"); + + return this->sect_[i]; + } + + private: + const ecl_file_view_type* init_; + + std::vector
sect_; + }; + + template + std::vector getKeywordData(const ecl_kw_type* kw) + { + // Whether or not caller requests a vector. + const auto makeStringVector = + typename std::is_same::type{}; + + switch (getKeywordElementType(kw)) { + case ECL_CHAR_TYPE: + return GetKeywordData:: + as(kw, makeStringVector); + + case ECL_INT_TYPE: + return GetKeywordData:: + as(kw, makeStringVector); + + case ECL_FLOAT_TYPE: + return GetKeywordData:: + as(kw, makeStringVector); + + case ECL_DOUBLE_TYPE: + return GetKeywordData:: + as(kw, makeStringVector); + + default: + // No operator exists for this type. Return empty. + return {}; + } + } } // namespace ECLImpl /// Predicate for whether or not a particular path represents a regular @@ -418,18 +541,22 @@ namespace { /// /// \param[in] file Filename or casename prefix. /// + /// \param[in] ext Set of possible filename extensions. + /// /// \return Filesystem element corresponding to result-set. Either the - /// input \p file itself or, in the case of a casename prefix, the - /// path to a restart file (unified format only). + /// input \p file itself or, in the case of a filename prefix, the + /// first possible match amongst the set generated by the prefix and + /// the input extensions. boost::filesystem::path - deriveResultPath(boost::filesystem::path file) + deriveResultPath(boost::filesystem::path file, + const std::vector& ext) { if (isFile(file)) { return file; } - for (const auto* ext : { ".UNRST", ".FUNRST" }) { - file.replace_extension(ext); + for (const auto& e : ext) { + file.replace_extension(e); if (isFile(file)) { return file; @@ -446,30 +573,72 @@ namespace { throw std::invalid_argument(os.str()); } - /// Load result-set represented by filesystem element. + /// Derive filesystem element from prefix or filename. + /// + /// Pass-through if the input already is a regular file in order to + /// support accessing result-sets other than restart files (e.g., the + /// INIT vectors). /// /// Fails (throws an exception of type \code std::invalid_argument - /// \endcode) if the input filesystem element does not represent a valid - /// result-set resource or if the resource could not be opened (e.g., - /// due to lack of permission). + /// \endcode) if no valid filesystem element can be derived from the + /// input argument /// - /// \param[in] rset Fileystem element representing a result-set. + /// \param[in] file Filename or casename prefix. /// - /// \return Accessor handle of result-set. - ECLImpl::FilePtr openResultSet(const boost::filesystem::path& rset) + /// \return Filesystem element corresponding to result-set. Either the + /// input \p file itself or, in the case of a casename prefix, the + /// path to a restart file (unified format only). + boost::filesystem::path + deriveRestartPath(boost::filesystem::path file) + { + return deriveResultPath(std::move(file), { ".UNRST", ".FUNRST" }); + } + + /// Derive filesystem element from prefix or filename. + /// + /// Pass-through if the input already is a regular file in order to + /// support accessing result-sets other than restart files (e.g., the + /// INIT vectors). + /// + /// Fails (throws an exception of type \code std::invalid_argument + /// \endcode) if no valid filesystem element can be derived from the + /// input argument + /// + /// \param[in] file Filename or casename prefix. + /// + /// \return Filesystem element corresponding to result-set. Either the + /// input \p file itself or, in the case of a casename prefix, the + /// path to an INIT file (unformatted or formatted). + boost::filesystem::path + deriveInitPath(boost::filesystem::path file) + { + return deriveResultPath(std::move(file), { ".INIT", ".FINIT" }); + } + + /// Open ECL result set from pathname. + /// + /// Fails (throws an exception of type \code std::invalid_argument + /// \endcode) if the input argument does not refer to a valid filesystem + /// element. + /// + /// \param[in] file Filename. + /// + /// \return Open stream corresponding to result-set. + ECLImpl::FilePtr openResultSet(const boost::filesystem::path& fname) { // Read-only, keep open between requests const auto open_flags = 0; - auto F = ECLImpl::FilePtr{ - ecl_file_open(rset.generic_string().c_str(), open_flags) + auto F = ECLImpl::FilePtr { + ecl_file_open(fname.generic_string().c_str(), open_flags), + ecl_file_close }; if (! F) { std::ostringstream os; - os << "Failed to load ECL Result object from '" - << rset.generic_string() << '\''; + os << "Failed to load ECL Result object from " + << fname.generic_string(); throw std::invalid_argument(os.str()); } @@ -491,19 +660,160 @@ namespace { auto* globView = ecl_file_get_global_view(const_cast(file)); - return ecl_kw_get_header(ecl_file_view_iget_kw(globView, 0)); + return ECLImpl::Details::firstBlockKeyword(globView); + } + + std::string paddedGridName(const std::string& gridName) + { + if (gridName.empty()) { + return gridName; + } + + std::ostringstream os; + + os << std::setw(8) << std::left << gridName; + + return os.str(); } } // namespace Anonymous -/// Engine powering implementation of \c ECLResultData interface -class Opm::ECLResultData::Impl +// ====================================================================== +// Class (Anonymous)::ECLImpl::GridIDCache +// ====================================================================== + +ECLImpl::GridIDCache::GridIDCache(const ecl_file_view_type* block) + : block_(block) +{} + +int ECLImpl::GridIDCache::getGridID(const std::string& gridName) const +{ + if (gridName.empty()) { + return ECL_GRID_MAINGRID_LGR_NR; + } + + { + auto i = this->cache_.find(gridName); + if (i != std::end(this->cache_)) { + return i->second; + } + } + + const auto nLGR = ecl_file_view_get_num_named_kw + (this->block_, LGR_KW); + + auto lgrID = 0 * nLGR; + for (; lgrID < nLGR; ++lgrID) + { + const auto* kw = ecl_file_view_iget_named_kw + (this->block_, LGR_KW, lgrID); + + if ((getKeywordElementType(kw) != ECL_CHAR_TYPE) || + (ecl_kw_get_size(kw) != 1)) + { + // Huh !?! + continue; + } + + const auto kwname = GetKeywordData + ::as(kw, std::true_type()); + + if (kwname[0] == gridName) { + break; + } + } + + if (lgrID == nLGR) { + // No such LGR in block. Somewhat surprising. + return -1; + } + + return this->cache_[gridName] = + ECL_GRID_MAINGRID_LGR_NR + 1 + lgrID; +} + +// ====================================================================== +// Class (Anonymous)::ECLImpl::InitFileSections +// ====================================================================== + +ECLImpl::InitFileSections::InitFileSections(const ecl_file_type* init) + // Note: ecl_file_get_global_view() does not modify input arg + : init_(ecl_file_get_global_view(const_cast(init))) +{ + const auto* endLGR_kw = "LGRSGONE"; + const auto nEndLGR = + ecl_file_view_get_num_named_kw(this->init_, endLGR_kw); + + if (nEndLGR == 0) { + // No LGRs in model. INIT file consists of global section only, + // meaning that the only available section is equal to the global + // view (i.e., this->init_). + this->sect_.push_back(Section{ this->init_ }); + } + else { + const auto* start_kw = INTEHEAD_KW; + const auto* end_kw = endLGR_kw; + + this->sect_.reserve(2 * nEndLGR); + + for (auto sectID = 0*nEndLGR; sectID < nEndLGR; ++sectID) { + // Note: Start keyword occurrence lags one behind section ID + // when creating sections *between* LGRSGONE keywords. + const auto start_kw_occurrence = (sectID > 0) + ? sectID - 1 : 0*sectID; + + // Main section 'sectID': [ start_kw, LGRSGONE ] + const auto* sect = + ecl_file_view_add_blockview2(this->init_, start_kw, + end_kw, start_kw_occurrence); + + if (sect == nullptr) { + continue; + } + + const auto firstkw = Details::firstBlockKeyword(sect); + const auto occurrence = 0; + + // Main grid sub-section of 'sectID': [ start_kw, LGR ] + const auto* main_grid_sect = + ecl_file_view_add_blockview2(sect, firstkw.c_str(), + LGR_KW, occurrence); + + // LGR sub-section of 'sectID': [ LGR, LGRSGONE ] + const auto* lgr_sect = + ecl_file_view_add_blockview2(sect, LGR_KW, + end_kw, occurrence); + + // Note: main_grid_sect or lgr_sect *may* (in rare cases) be + // nullptr, but we'll deal with that in the calling context. + this->sect_.push_back(Section { main_grid_sect }); + this->sect_.push_back(Section { lgr_sect }); + + // start_kw == end_kw for all but first section. + start_kw = end_kw; + } + } +} + +// ====================================================================== +// Class Opm::ECLRestartData::Impl +// ====================================================================== + +/// Engine powering implementation of \c ECLRestartData interface +class Opm::ECLRestartData::Impl { public: + using Path = boost::filesystem::path; + /// Constructor /// - /// \param[in] rset Filesystem element or casename prefix representing + /// \param[in] rstrt Filesystem element or casename prefix representing /// an ECL result-set. - Impl(Path rset); + Impl(Path rstrt); + + /// Constructor + /// + /// \param[in] rstrt ECL restart result set + Impl(std::shared_ptr rstrt); /// Copy constructor. /// @@ -516,27 +826,6 @@ public: /// instance. Underlying result-set accessor is null upon return. Impl(Impl&& rhs); - /// Access the underlying ERT representation of the result-set. - /// - /// This is a hole in the interface that exists to be able to access - /// ERT's internal data structures for non-neighbouring connections - /// (i.e., faults and/or connections between main grid and LGRs). See - /// function ecl_nnc_export() in the ERT. - /// - /// Handle with care. - /// - /// \return Handle to underlying ERT representation of result-set. - const ecl_file_type* getRawFilePtr() const; - - /// Reset the object's internal view of the result-set to encompass the - /// entirety of the underlying file's result vectors. - /// - /// This is mostly useful in the case of accessing static result-sets - /// such as INIT files. - /// - /// \return Whether or not generating the global view succeeded. - bool selectGlobalView(); - /// Select a result-set view that corresponds to a single report step. /// /// This is needed when working with dynamic restart data. @@ -560,7 +849,7 @@ public: /// \return Whether or not keyword data for the named result vector is /// available in the specific grid. bool haveKeywordData(const std::string& vector, - const int gridID) const; + const std::string& gridName) const; /// Retrieve current result-set view's data values for particular named /// result vector in particular enumerated grid. @@ -588,7 +877,7 @@ public: template std::vector keywordData(const std::string& vector, - const int gridID) const; + const std::string& gridName) const; private: /// RAII class to select a sub-block pertaining to a particular grid @@ -642,7 +931,7 @@ private: /// Saved original active view from host (prior to restricting view /// to single grid ID). - ecl_file_view_type* save_; + const ecl_file_view_type* save_; }; /// Casename prefix. Mostly to implement copy ctor. @@ -655,8 +944,11 @@ private: /// of main grid's section within a view. std::string firstKeyword_; + /// Map LGR names to integral grid IDs. + std::unique_ptr gridIDCache_; + /// Current active result-set view. - mutable ecl_file_view_type* activeBlock_{ nullptr }; + mutable const ecl_file_view_type* activeBlock_{ nullptr }; /// Support for passing \code *this \endcode to ERT functions that /// require an \c ecl_file_type, particularly the function that selects @@ -673,45 +965,42 @@ private: /// Retrieve result-set keyword that identifies beginning of main grid's /// result vectors. const std::string& mainGridStart() const; + + int gridID(const std::string& gridName) const; }; -Opm::ECLResultData::Impl::Impl(Path prefix) +Opm::ECLRestartData::Impl::Impl(Path prefix) : prefix_ (std::move(prefix)) - , result_ (openResultSet(deriveResultPath(prefix_))) + , result_ (openResultSet(deriveRestartPath(prefix_))) , firstKeyword_(firstFileKeyword(result_.get())) {} -Opm::ECLResultData::Impl::Impl(const Impl& rhs) +Opm::ECLRestartData::Impl::Impl(std::shared_ptr rstrt) + : prefix_ (ecl_file_get_src_file(rstrt.get())) + , result_ (std::move(rstrt)) + , firstKeyword_(firstFileKeyword(result_.get())) +{} + +Opm::ECLRestartData::Impl::Impl(const Impl& rhs) : prefix_ (rhs.prefix_) - , result_ (openResultSet(deriveResultPath(prefix_))) + , result_ (openResultSet(deriveRestartPath(prefix_))) , firstKeyword_(firstFileKeyword(result_.get())) {} -Opm::ECLResultData::Impl::Impl(Impl&& rhs) +Opm::ECLRestartData::Impl::Impl(Impl&& rhs) : prefix_ (std::move(rhs.prefix_)) , result_ (std::move(rhs.result_)) , firstKeyword_(std::move(rhs.firstKeyword_)) {} -const ecl_file_type* -Opm::ECLResultData::Impl::getRawFilePtr() const -{ - return this->result_.get(); -} - -bool Opm::ECLResultData::Impl::selectGlobalView() -{ - this->activeBlock_ = ecl_file_get_global_view(*this); - - return this->activeBlock_ != nullptr; -} - -bool Opm::ECLResultData::Impl::selectReportStep(const int step) +bool Opm::ECLRestartData::Impl::selectReportStep(const int step) { if (! ecl_file_has_report_step(*this, step)) { return false; } + this->gridIDCache_.reset(); + if (auto* globView = ecl_file_get_global_view(*this)) { // Ignore sequence numbers, dates, and simulation time. const auto seqnum = -1; @@ -722,16 +1011,26 @@ bool Opm::ECLResultData::Impl::selectReportStep(const int step) ecl_file_view_add_restart_view(globView, seqnum, step, dates, simdays); - return this->activeBlock_ != nullptr; + if (this->activeBlock_ != nullptr) { + this->gridIDCache_ + .reset(new ECLImpl::GridIDCache(this->activeBlock_)); + + return true; + } } return false; } -bool Opm::ECLResultData::Impl:: -haveKeywordData(const std::string& vector, const int gridID) const +bool Opm::ECLRestartData::Impl:: +haveKeywordData(const std::string& vector, + const std::string& gridName) const { - assert ((gridID >= 0) && "Grid IDs must be non-negative"); + const auto gridID = this->gridIDCache_->getGridID(gridName); + + if (gridID < 0) { + return false; + } // Note: Non-trivial dtor. Compiler can't ignore object. const auto block = Restrict{ *this, gridID }; @@ -746,18 +1045,22 @@ namespace Opm { template std::vector - ECLResultData::Impl::keywordData(const std::string& vector, - const int gridID) const + ECLRestartData::Impl::keywordData(const std::string& vector, + const std::string& gridName) const { - if (! this->haveKeywordData(vector, gridID)) { + if (! this->haveKeywordData(vector, gridName)) { std::ostringstream os; - os << "Cannot Access Non-Existent Keyword Data Pair (" - << vector << ", " << gridID << ')'; + os << "RESTART: Cannot Access Non-Existent Keyword Data Pair (" + << vector << ", " + << (gridName.empty() ? "Main Grid" : gridName) + << ')'; throw std::invalid_argument(os.str()); } + const auto gridID = this->gridIDCache_->getGridID(gridName); + // Note: Non-trivial dtor. Compiler can't ignore object. const auto block = Restrict{ *this, gridID }; @@ -770,105 +1073,483 @@ namespace Opm { assert ((kw != nullptr) && "Logic Error In Data Availability Check"); - // Whether or not caller requests a vector. - const auto makeStringVector = - typename std::is_same::type{}; - - switch (getKeywordElementType(kw)) { - case ECL_CHAR_TYPE: - return ECLImpl::GetKeywordData:: - as(kw, makeStringVector); - - case ECL_INT_TYPE: - return ECLImpl::GetKeywordData:: - as(kw, makeStringVector); - - case ECL_FLOAT_TYPE: - return ECLImpl::GetKeywordData:: - as(kw, makeStringVector); - - case ECL_DOUBLE_TYPE: - return ECLImpl::GetKeywordData:: - as(kw, makeStringVector); - - default: - // No operator exists for this type. Return empty. - return {}; - } + return ECLImpl::getKeywordData(kw); } } // namespace Opm -Opm::ECLResultData::Impl::operator ecl_file_type*() const +Opm::ECLRestartData::Impl::operator ecl_file_type*() const { return this->result_.get(); } -Opm::ECLResultData::Impl::operator const ecl_file_view_type*() const +Opm::ECLRestartData::Impl::operator const ecl_file_view_type*() const { return this->activeBlock_; } const std::string& -Opm::ECLResultData::Impl::mainGridStart() const +Opm::ECLRestartData::Impl::mainGridStart() const { return this->firstKeyword_; } +int +Opm::ECLRestartData::Impl::gridID(const std::string& gridName) const +{ + return this->gridIDCache_->getGridID(gridName); +} + // ====================================================================== -// Implementation of class Opm::ECLResultData Below Separator +// Class Opm::ECLInitFileData::Impl // ====================================================================== -Opm::ECLResultData::ECLResultData(const Path& prefix) - : pImpl_(new Impl(prefix)) +class Opm::ECLInitFileData::Impl +{ +public: + using Path = boost::filesystem::path; + + /// Constructor. + /// + /// Construct from filename. Owning semantics. + /// + /// \param[in] casePrefix Name or prefix of ECL result data. + Impl(Path initFile); + + /// Constructor. + /// + /// Construct from dataset already input through other means. + /// + /// Non-owning semantics. + Impl(std::shared_ptr initFile); + + /// Copy constructor. + /// + /// \param[in] rhs Object from which to construct new \c Impl instance. + Impl(const Impl& rhs); + + /// Move constructor. + /// + /// \param[in,out] rhs Object from which to constructo new \c Impl + /// instance. Underlying result-set accessor is null upon return. + Impl(Impl&& rhs); + + const ecl_file_type* getRawFilePtr() const; + + /// Query current result-set view for availability of particular named + /// result vector in particular enumerated grid. + /// + /// \param[in] vector Named result vector for which to query data + /// availability. + /// + /// \param[in] gridID Identity of specific grid for which to query data + /// availability. + /// + /// \return Whether or not keyword data for the named result vector is + /// available in the specific grid. + bool haveKeywordData(const std::string& vector, + const std::string& gridName) const; + + /// Retrieve current result-set view's data values for particular named + /// result vector in particular enumerated grid. + /// + /// Will fail (throw an exception of type std::invalid_argument) unless + /// the requested keyword data is available in the specific grid in the + /// current active view. + /// + /// \tparam T Element type of return value. The underlying keyword data + /// will be converted to this type if needed and possible. Note that + /// some type combinations do not make sense. It is, for instance, + /// not possible to retrieve keyword values of an underlying + /// arithmetic type in the form of a \code std::vector + /// \endcode. Similarly, we cannot access underlying character data + /// through elements of an arithmetic type (e.g., \code + /// std::vector \endcode.) + /// + /// \param[in] vector Named result vector for which to retrieve + /// keyword data. + /// + /// \param[in] gridID Identity of specific grid for which to + /// retrieve keyword data. + /// + /// \return Keyword data values. Empty if type conversion fails. + template + std::vector + keywordData(const std::string& vector, + const std::string& gridName) const; + +private: + using SectionID = + ECLImpl::InitFileSections::SectionID; + + /// Result of searching for a particular pairing of (vector,gridName) in + /// INIT. + struct LookupResult + { + /// In what INIT file section the KW was located (-1 if not found). + SectionID sectID; + + /// Local ID, within sectID, of grid section data section that hosts + /// the 'vector' (-1 if not found). + int gridSectID; + }; + + /// Pairing of kw vector and grid name. + struct KWKey { + /// Keyword/result set vector + std::string vector; + + /// ID of grid for which to look up 'vector'. + std::string gridName; + }; + + /// Comparator (std::set<> and std::map<>) for KWKeys. + struct CompareKWKey { + bool operator()(const KWKey& k1, const KWKey& k2) const + { + return std::tie(k1.vector, k1.gridName) + < std::tie(k2.vector, k2.gridName); + } + }; + + /// Negative look-up cache. + using MissingKW = std::set; + + /// Keyword-to-section cache to accelerate repeated look-up. + using KWSection = std::map; + + /// Casename prefix. Mostly to implement copy ctor. + const Path prefix_; + + /// Raw result set. + ECLImpl::FilePtr initFile_; + + /// Sections of the INIT result set. + ECLImpl::InitFileSections sections_; + + mutable const ecl_file_view_type* activeBlock_{ nullptr }; + + /// Negative look-up cache for haveKeywordData() queries. + mutable MissingKW missing_kw_; + + /// Keyword-to-section map for successful haveKeywordData() and + /// keywordData() queries. Accelerates repeated look-up queries. + mutable KWSection kw_section_; + + operator const ecl_file_view_type*() const; + + LookupResult + lookup(const std::string& vector, + const std::string& gridName) const; + + LookupResult lookupMainGrid(const KWKey& key) const; + + LookupResult lookupLGR(const KWKey& key) const; + + void setActiveBlock(const SectionID sect) const; + + const ECLImpl::InitFileSections::Section& + getSection(const SectionID sect) const; +}; + +Opm::ECLInitFileData::Impl::Impl(Path initFile) + : prefix_ (initFile.stem()) + , initFile_(openResultSet(deriveInitPath(std::move(initFile)))) + , sections_(initFile_.get()) {} -Opm::ECLResultData::ECLResultData(const ECLResultData& rhs) +Opm::ECLInitFileData::Impl::Impl(std::shared_ptr initFile) + : prefix_ (Path(ecl_file_get_src_file(initFile.get())).stem()) + , initFile_(std::move(initFile)) + , sections_(initFile_.get()) +{} + +Opm::ECLInitFileData::Impl::Impl(const Impl& rhs) + : prefix_ (rhs.prefix_) + , initFile_(rhs.initFile_) + , sections_(initFile_.get()) +{} + +Opm::ECLInitFileData::Impl::Impl(Impl&& rhs) + : prefix_ (std::move(rhs.prefix_)) + , initFile_(std::move(rhs.initFile_)) + , sections_(std::move(rhs.sections_)) +{} + +const ecl_file_type* +Opm::ECLInitFileData::Impl::getRawFilePtr() const +{ + return this->initFile_.get(); +} + +bool +Opm::ECLInitFileData::Impl:: +haveKeywordData(const std::string& vector, + const std::string& gridName) const +{ + const auto kwloc = this->lookup(vector, gridName); + + return (kwloc.sectID < this->sections_.numSections()) + && (kwloc.gridSectID >= 0); +} + +namespace Opm { + + template + std::vector + ECLInitFileData::Impl:: + keywordData(const std::string& vector, + const std::string& gridName) const + { + if (! this->haveKeywordData(vector, gridName)) { + std::ostringstream os; + + os << "INIT: Cannot Access Non-Existent Keyword Data Pair (" + << vector << ", " + << (gridName.empty() ? "Main Grid" : gridName) + << ')'; + + throw std::invalid_argument(os.str()); + }; + + const auto kwloc = this->lookup(vector, gridName); + + this->setActiveBlock(kwloc.sectID); + + if (! gridName.empty()) { + // We're cons + this->activeBlock_ = + ecl_file_view_add_blockview(this->activeBlock_, LGR_KW, + kwloc.gridSectID); + } + + const auto occurrence = 0; + + const auto* kw = + ecl_file_view_iget_named_kw(*this, vector.c_str(), + occurrence); + + assert ((kw != nullptr) && + "Logic Error In Data Availability Check"); + + return ECLImpl::getKeywordData(kw); + } + +} + +Opm::ECLInitFileData::Impl::operator const ecl_file_view_type*() const +{ + return this->activeBlock_; +} + +Opm::ECLInitFileData::Impl::LookupResult +Opm::ECLInitFileData::Impl:: +lookup(const std::string& vector, const std::string& gridName) const +{ + const auto key = KWKey{ vector, gridName }; + + { + auto m = this->missing_kw_.find(key); + + if (m != std::end(this->missing_kw_)) { + // 'vector' known to be mssing for 'gridName'. Report as such. + return { SectionID(-1), -1 }; + } + } + + { + auto i = this->kw_section_.find(key); + + if (i != std::end(this->kw_section_)) { + // 'vector' previously located for 'gridName'. Return it. + return i->second; + } + } + + if (gridName.empty()) { + return this->lookupMainGrid(key); + } + + return this->lookupLGR(key); +} + +Opm::ECLInitFileData::Impl::LookupResult +Opm::ECLInitFileData::Impl::lookupMainGrid(const KWKey& key) const +{ + assert (key.gridName.empty() && "Logic Error"); + + const auto* kwheader = key.vector.c_str(); + + // Main grid sections are even numbered. + for (auto nSect = this->sections_.numSections(), sectID = 0*nSect; + sectID < nSect; sectID += 2) + { + const auto& s = this->getSection(sectID); + + // Skip empty sections + if (s.block == nullptr) { continue; } + + const auto count = + ecl_file_view_get_num_named_kw(s.block, kwheader); + + if (count > 0) { + // Result-set 'vector' present in main grid. Record and return. + + // Assume that keyword does not occur multiple times in main + // grid section. + const auto gridSectID = 0; + + return this->kw_section_[key] = + LookupResult { sectID, gridSectID }; + } + } + + // No result-set 'vector' in main grid. Record as missing and return + // "not found". + this->missing_kw_.insert(key); + + return { SectionID(-1), -1 }; +} + +Opm::ECLInitFileData::Impl::LookupResult +Opm::ECLInitFileData::Impl::lookupLGR(const KWKey& key) const +{ + assert ((! key.gridName.empty()) && "Logic Error"); + + const auto gridID = paddedGridName(key.gridName); + const auto* kwheader = key.vector.c_str(); + const auto* gridName = gridID.c_str(); + + // LGR sections are odd numbered. + for (auto nSect = this->sections_.numSections(), sectID = 0*nSect + 1; + sectID < nSect; sectID += 2) + { + const auto& s = this->getSection(sectID); + + // Skip empty sections. + if (s.block == nullptr) { continue; } + + const auto nLGR = + ecl_file_view_get_num_named_kw(s.block, LGR_KW); + + assert ((nLGR > 0) && "Logic Error"); + + for (auto lgrID = 0*nLGR; lgrID < nLGR; ++lgrID) { + const auto* kw = + ecl_file_view_iget_named_kw(s.block, LGR_KW, lgrID); + + if (! ecl_kw_data_equal(kw, gridName)) { + // This is not the grid you're looking for. + continue; + } + + // This LGR section pertains to key.gridName. Look for + // key.vector between this occurrence of LGR_KW and the next. + // Continue searching if we don't find that vector however, + // because there may be multiple relevant LGR instances for + // key.gridName. + + const auto* lgrSect = + ecl_file_view_add_blockview(s.block, LGR_KW, lgrID); + + const auto kwCount = + ecl_file_view_get_num_named_kw(lgrSect, kwheader); + + if (kwCount > 0) { + // We found the key.vector in this LGR data section. Record + // position and return it to caller. + + return this->kw_section_[key] = + LookupResult { SectionID(sectID), lgrID }; + } + + // Did not find 'key.vector' in this LGR data section. Continue + // searching nonetheless because there may be more LGR sections + // that pertain to 'key.gridName'. + } + } + + // key.vector not found for key.gridName in any of the LGR sections. + // Record as missing and return "not found". + + this->missing_kw_.insert(key); + + return { SectionID(-1), -1 }; +} + +void +Opm::ECLInitFileData::Impl::setActiveBlock(const SectionID sect) const +{ + this->activeBlock_ = this->getSection(sect).block; +} + +const ECLImpl::InitFileSections::Section& +Opm::ECLInitFileData::Impl::getSection(const SectionID sect) const +{ + assert (sect < this->sections_.numSections()); + + return this->sections_[sect]; +} + +// ###################################################################### +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// Public Interfaces Follow +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// ###################################################################### + +// ====================================================================== +// Implementation of class Opm::ECLRestartData Below Separator +// ====================================================================== + +Opm::ECLRestartData::ECLRestartData(boost::filesystem::path rstrt) + : pImpl_(new Impl(std::move(rstrt))) +{} + +Opm::ECLRestartData::ECLRestartData(std::shared_ptr rstrt) + : pImpl_(new Impl(std::move(rstrt))) +{} + +Opm::ECLRestartData::ECLRestartData(const ECLRestartData& rhs) : pImpl_(new Impl(*rhs.pImpl_)) {} -Opm::ECLResultData::ECLResultData(ECLResultData&& rhs) +Opm::ECLRestartData::ECLRestartData(ECLRestartData&& rhs) : pImpl_(std::move(rhs.pImpl_)) {} -Opm::ECLResultData& -Opm::ECLResultData::operator=(const ECLResultData& rhs) +Opm::ECLRestartData& +Opm::ECLRestartData::operator=(const ECLRestartData& rhs) { this->pImpl_.reset(new Impl(*rhs.pImpl_)); return *this; } -Opm::ECLResultData& -Opm::ECLResultData::operator=(ECLResultData&& rhs) +Opm::ECLRestartData& +Opm::ECLRestartData::operator=(ECLRestartData&& rhs) { this->pImpl_ = std::move(rhs.pImpl_); return *this; } -Opm::ECLResultData::~ECLResultData() +Opm::ECLRestartData::~ECLRestartData() {} -const ecl_file_type* -Opm::ECLResultData::getRawFilePtr() const +bool Opm::ECLRestartData::selectReportStep(const int step) const { - return this->pImpl_->getRawFilePtr(); -} + // selectReportStep() const is a bit of a lie. pImpl_ is a const + // pointer to modifiable Impl. -bool Opm::ECLResultData::selectGlobalView() -{ - return this->pImpl_->selectGlobalView(); -} - -bool Opm::ECLResultData::selectReportStep(const int step) -{ return this->pImpl_->selectReportStep(step); } bool -Opm::ECLResultData:: -haveKeywordData(const std::string& vector, const int gridID) const +Opm::ECLRestartData:: +haveKeywordData(const std::string& vector, + const std::string& gridID) const { return this->pImpl_->haveKeywordData(vector, gridID); } @@ -877,23 +1558,101 @@ namespace Opm { template std::vector - ECLResultData::keywordData(const std::string& vector, - const int gridID) const + ECLRestartData::keywordData(const std::string& vector, + const std::string& gridID) const { return this->pImpl_->template keywordData(vector, gridID); } // Explicit instantiations for those types we care about. template std::vector - ECLResultData::keywordData(const std::string& vector, - const int gridID) const; + ECLRestartData::keywordData(const std::string& vector, + const std::string& gridID) const; template std::vector - ECLResultData::keywordData(const std::string& vector, - const int gridID) const; + ECLRestartData::keywordData(const std::string& vector, + const std::string& gridID) const; template std::vector - ECLResultData::keywordData(const std::string& vector, - const int gridID) const; + ECLRestartData::keywordData(const std::string& vector, + const std::string& gridID) const; + +} // namespace Opm::ECL + +// ====================================================================== +// Implementation of class Opm::ECLInitFileData Below Separator +// ====================================================================== + +Opm::ECLInitFileData::ECLInitFileData(boost::filesystem::path init) + : pImpl_(new Impl(std::move(init))) +{} + +Opm::ECLInitFileData::ECLInitFileData(std::shared_ptr init) + : pImpl_(new Impl(std::move(init))) +{} + +Opm::ECLInitFileData::ECLInitFileData(const ECLInitFileData& rhs) + : pImpl_(new Impl(*rhs.pImpl_)) +{} + +Opm::ECLInitFileData::ECLInitFileData(ECLInitFileData&& rhs) + : pImpl_(std::move(rhs.pImpl_)) +{} + +Opm::ECLInitFileData& +Opm::ECLInitFileData::operator=(const ECLInitFileData& rhs) +{ + this->pImpl_.reset(new Impl(*rhs.pImpl_)); + + return *this; +} + +Opm::ECLInitFileData& +Opm::ECLInitFileData::operator=(ECLInitFileData&& rhs) +{ + this->pImpl_ = std::move(rhs.pImpl_); + + return *this; +} + +Opm::ECLInitFileData::~ECLInitFileData() +{} + +bool +Opm::ECLInitFileData:: +haveKeywordData(const std::string& vector, + const std::string& gridID) const +{ + return this->pImpl_->haveKeywordData(vector, gridID); +} + +const ecl_file_type* +Opm::ECLInitFileData::getRawFilePtr() const +{ + return this->pImpl_->getRawFilePtr(); +} + +namespace Opm { + + template + std::vector + ECLInitFileData::keywordData(const std::string& vector, + const std::string& gridID) const + { + return this->pImpl_->template keywordData(vector, gridID); + } + + // Explicit instantiations for those types we care about. + template std::vector + ECLInitFileData::keywordData(const std::string& vector, + const std::string& gridID) const; + + template std::vector + ECLInitFileData::keywordData(const std::string& vector, + const std::string& gridID) const; + + template std::vector + ECLInitFileData::keywordData(const std::string& vector, + const std::string& gridID) const; } // namespace Opm::ECL diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.hpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.hpp index a804e4baf8..c48b6a4645 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.hpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLResultData.hpp @@ -1,6 +1,5 @@ /* - Copyright 2016 SINTEF ICT, Applied Mathematics. - Copyright 2016 Statoil ASA. + Copyright 2016, 2017 Statoil ASA. This file is part of the Open Porous Media Project (OPM). @@ -18,8 +17,8 @@ along with OPM. If not, see . */ -#ifndef OPM_ECLRESTARTDATA_HEADER_INCLUDED -#define OPM_ECLRESTARTDATA_HEADER_INCLUDED +#ifndef OPM_ECLRESULTDATA_HEADER_INCLUDED +#define OPM_ECLRESULTDATA_HEADER_INCLUDED #include #include @@ -34,14 +33,17 @@ /// Forward-declaration of ERT's representation of an ECLIPSE result file. /// /// This is a hole in the insulation between the interface and the -/// underlying implementation of class ECLResultData. +/// underlying implementation of class ECLInitFileData and furthermore +/// enables constructing wrapper objects from separately parsed result sets. extern "C" { typedef struct ecl_file_struct ecl_file_type; } // extern "C" namespace Opm { - /// Representation of an ECLIPSE result-set. + class ECLGraph; + + /// Representation of an ECLIPSE Restart result-set. /// /// This class is aware of the internal structure of ECLIPSE restart /// files and may restrict its operation to a single report step. The @@ -51,30 +53,37 @@ namespace Opm { /// /// Note: The client must select a view of the result-set before /// accessing any vectors within the set. - class ECLResultData + class ECLRestartData { public: - using Path = boost::filesystem::path; - /// Default constructor disabled. - ECLResultData() = delete; + ECLRestartData() = delete; /// Constructor. /// - /// \param[in] casePrefix Name or prefix of ECL result data. - explicit ECLResultData(const Path& casePrefix); + /// Owning semantics. + /// + /// \param[in] rstrt Name or prefix of ECL result data. + explicit ECLRestartData(boost::filesystem::path rstrt); + + /// Constructor + /// + /// Shared ownership of result set. + /// + /// \param[in] rstrt ECL restart result set. + explicit ECLRestartData(std::shared_ptr rstrt); /// Copy constructor. /// /// \param[in] rhs Object from which to construct new instance. - ECLResultData(const ECLResultData& rhs); + ECLRestartData(const ECLRestartData& rhs); /// Move constructor. /// /// \param[in,out] rhs Object from which to construct new instance. /// Its internal implementation will be subsumed into the new /// object. - ECLResultData(ECLResultData&& rhs); + ECLRestartData(ECLRestartData&& rhs); /// Assignment operator. /// @@ -82,7 +91,7 @@ namespace Opm { /// instance. /// /// \return \code *this \endcode. - ECLResultData& operator=(const ECLResultData& rhs); + ECLRestartData& operator=(const ECLRestartData& rhs); /// Move assignment operator. /// @@ -91,27 +100,10 @@ namespace Opm { /// instance. /// /// \return \code *this \endcode. - ECLResultData& operator=(ECLResultData&& rhs); + ECLRestartData& operator=(ECLRestartData&& rhs); /// Destructor. - ~ECLResultData(); - - /// Access the underlying ERT representation of the result-set. - /// - /// This is essentially a hole in the interface that is intended to - /// support a few very specialised uses. Handle with care. - /// - /// \return Handle to underlying ERT representation of result-set. - const ecl_file_type* getRawFilePtr() const; - - /// Reset the object's internal view of the result-set to encompass - /// the entirety of the underlying file's result vectors. - /// - /// This is mostly useful in the case of accessing static result - /// sets such as INIT files. - /// - /// \return Whether or not generating the global view succeeded. - bool selectGlobalView(); + ~ECLRestartData(); /// Select a result-set view that corresponds to a single report /// step. @@ -123,7 +115,7 @@ namespace Opm { /// \return Whether or not selecting the report step succeeded. The /// typical failure case is the report step not being available /// in the result-set. - bool selectReportStep(const int step); + bool selectReportStep(const int step) const; /// Query current result-set view for availability of particular /// named result vector in particular enumerated grid. @@ -132,12 +124,12 @@ namespace Opm { /// availability. /// /// \param[in] gridID Identity of specific grid for which to query - /// data availability. + /// data availability. Empty for the main grid. /// /// \return Whether or not keyword data for the named result vector /// is available in the specific grid. bool haveKeywordData(const std::string& vector, - const int gridID) const; + const std::string& gridID = "") const; /// Retrieve current result-set view's data values for particular /// named result vector in particular enumerated grid. @@ -159,13 +151,13 @@ namespace Opm { /// keyword data. /// /// \param[in] gridID Identity of specific grid for which to - /// retrieve keyword data. + /// retrieve keyword data. Empty for the main grid. /// /// \return Keyword data values. Empty if type conversion fails. template std::vector keywordData(const std::string& vector, - const int gridID) const; + const std::string& gridID = "") const; private: class Impl; @@ -173,6 +165,119 @@ namespace Opm { std::unique_ptr pImpl_; }; + /// Representation of an ECLIPSE Initialization result-set. + /// + /// This class is aware of the internal structure of ECLIPSE INIT files + /// and queries only those objects that pertain to a single grid. + class ECLInitFileData + { + public: + ECLInitFileData() = delete; + + /// Constructor. + /// + /// Construct from filename. Owning semantics. + /// + /// \param[in] casePrefix Name or prefix of ECL result data. + explicit ECLInitFileData(boost::filesystem::path initFile); + + /// Constructor. + /// + /// Construct from dataset already input through other means. + /// + /// Non-owning/shared ownership semantics. + explicit ECLInitFileData(std::shared_ptr initFile); + + /// Copy constructor. + /// + /// \param[in] rhs Object from which to construct new instance. + ECLInitFileData(const ECLInitFileData& rhs); + + /// Move constructor. + /// + /// \param[in,out] rhs Object from which to construct new instance. + /// Its internal implementation will be subsumed into the new + /// object. + ECLInitFileData(ECLInitFileData&& rhs); + + /// Assignment operator. + /// + /// \param[in] rhs Object from which to assign new values to current + /// instance. + /// + /// \return \code *this \endcode. + ECLInitFileData& operator=(const ECLInitFileData& rhs); + + /// Move assignment operator. + /// + /// \param[in,out] Object from which to assign new instance values. + /// Its internal implementation will be subsumed into this + /// instance. + /// + /// \return \code *this \endcode. + ECLInitFileData& operator=(ECLInitFileData&& rhs); + + /// Destructor. + ~ECLInitFileData(); + + /// Query current result-set view for availability of particular + /// named result vector in particular enumerated grid. + /// + /// \param[in] vector Named result vector for which to query data + /// availability. + /// + /// \param[in] gridID Identity of specific grid for which to query + /// data availability. Empty for the main grid. + /// + /// \return Whether or not keyword data for the named result vector + /// is available in the specific grid. + bool haveKeywordData(const std::string& vector, + const std::string& gridID = "") const; + + /// Retrieve current result-set view's data values for particular + /// named result vector in particular enumerated grid. + /// + /// Will fail (throw an exception of type std::invalid_argument) + /// unless the requested keyword data is available in the specific + /// grid in the current active view. + /// + /// \tparam T Element type of return value. The underlying keyword + /// data will be converted to this type if needed and possible. + /// Note that some type combinations do not make sense. It is, + /// for instance, not possible to retrieve keyword values of an + /// underlying arithmetic type in the form of a \code + /// std::vector \endcode. Similarly, we cannot + /// access underlying character data through elements of an + /// arithmetic type (e.g., \code std::vector \endcode.) + /// + /// \param[in] vector Named result vector for which to retrieve + /// keyword data. + /// + /// \param[in] gridID Identity of specific grid for which to + /// retrieve keyword data. Empty for the main grid. + /// + /// \return Keyword data values. Empty if type conversion fails. + template + std::vector + keywordData(const std::string& vector, + const std::string& gridID = "") const; + + // Grant class ECLGraph privileged access to getRawFilePtr(). + friend class ECLGraph; + + private: + class Impl; + + std::unique_ptr pImpl_; + + /// Access the underlying ERT representation of the result-set. + /// + /// This is essentially a hole in the interface that is intended to + /// support a few very specialised uses. Handle with care. + /// + /// \return Handle to underlying ERT representation of result-set. + const ecl_file_type* getRawFilePtr() const; + }; } // namespace Opm -#endif // OPM_ECLRESTARTDATA_HEADER_INCLUDED +#endif // OPM_ECLRESULTDATA_HEADER_INCLUDED diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLUnitHandling.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLUnitHandling.cpp index 4a3b77b1c1..4f29ba1ae6 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLUnitHandling.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLUnitHandling.cpp @@ -1,5 +1,4 @@ /* - Copyright 2017 SINTEF ICT, Applied Mathematics. Copyright 2017 Statoil ASA. This file is part of the Open Porous Media Project (OPM). diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLUnitHandling.hpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLUnitHandling.hpp index ee11974fe0..87fe95d75b 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLUnitHandling.hpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLUnitHandling.hpp @@ -1,5 +1,4 @@ /* - Copyright 2017 SINTEF ICT, Applied Mathematics. Copyright 2017 Statoil ASA. This file is part of the Open Porous Media Project (OPM). diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLWellSolution.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLWellSolution.cpp index 20b611a4a0..f1c17fbc52 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLWellSolution.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLWellSolution.cpp @@ -1,6 +1,6 @@ /* Copyright 2016 SINTEF ICT, Applied Mathematics. - Copyright 2016 Statoil ASA. + Copyright 2016, 2017 Statoil ASA. This file is part of the Open Porous Media project (OPM). @@ -146,13 +146,16 @@ namespace Opm std::vector - ECLWellSolution::solution(const ECLResultData& restart, - const int num_grids) const + ECLWellSolution::solution(const ECLRestartData& restart, + const std::vector& grids) const { + // Note: this function expects to be called with the correct restart + // block--e.g., a report step--selected in the caller. + // Read well data for global grid. std::vector all_wd{}; - for (int grid_index = 0; grid_index < num_grids; ++grid_index) { - std::vector wd = readWellData(restart, grid_index); + for (const auto& gridName : grids) { + std::vector wd = readWellData(restart, gridName); // Append to set of all well data. all_wd.insert(all_wd.end(), wd.begin(), wd.end()); } @@ -163,24 +166,34 @@ namespace Opm std::vector - ECLWellSolution::readWellData(const ECLResultData& restart, const int grid_index) const + ECLWellSolution::readWellData(const ECLRestartData& restart, + const std::string& gridName) const { - // Note: this function is expected to be called in a context - // where the correct restart block using the ert block mechanisms. + // Check if result set provides complete set of well solution data. + if (! (restart.haveKeywordData(ZWEL_KW, gridName) && + restart.haveKeywordData(IWEL_KW, gridName) && + restart.haveKeywordData("XWEL" , gridName) && + restart.haveKeywordData(ICON_KW, gridName) && + restart.haveKeywordData("XCON" , gridName))) + { + // Not all requisite keywords present in this grid. Can't + // create a well solution. + return {}; + } // Read header, return if trivial. - INTEHEAD ih(restart.keywordData(INTEHEAD_KW, grid_index)); + INTEHEAD ih(restart.keywordData(INTEHEAD_KW, gridName)); if (ih.nwell == 0) { return {}; } const double qr_unit = resRateUnit(ih.unit); - // Read necessary keywords. - auto zwel = restart.keywordData(ZWEL_KW, grid_index); - auto iwel = restart.keywordData (IWEL_KW, grid_index); - auto xwel = restart.keywordData ("XWEL" , grid_index); - auto icon = restart.keywordData (ICON_KW, grid_index); - auto xcon = restart.keywordData ("XCON" , grid_index); + // Load well topology and flow rates. + auto zwel = restart.keywordData(ZWEL_KW, gridName); + auto iwel = restart.keywordData (IWEL_KW, gridName); + auto xwel = restart.keywordData ("XWEL" , gridName); + auto icon = restart.keywordData (ICON_KW, gridName); + auto xcon = restart.keywordData ("XCON" , gridName); // Create well data. std::vector wd_vec; @@ -204,7 +217,7 @@ namespace Opm const int xcon_offset = (well*ih.ncwma + comp_index) * ih.nxcon; WellData::Completion completion; // Note: subtracting 1 from indices (Fortran -> C convention). - completion.grid_index = grid_index; + completion.gridName = gridName; completion.ijk = { icon[icon_offset + ICON_I_INDEX] - 1, icon[icon_offset + ICON_J_INDEX] - 1, icon[icon_offset + ICON_K_INDEX] - 1 }; @@ -212,7 +225,7 @@ namespace Opm completion.reservoir_inflow_rate = -unit::convert::from(xcon[xcon_offset + XCON_QR_INDEX], qr_unit); if (disallow_crossflow_) { // Add completion only if not cross-flowing (injecting producer or producing injector). - if (completion.reservoir_inflow_rate < 0.0 == is_producer) { + if ((completion.reservoir_inflow_rate < 0.0) == is_producer) { wd.completions.push_back(completion); } } else { diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLWellSolution.hpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLWellSolution.hpp index e6ab682b2a..94e24c65ec 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLWellSolution.hpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLWellSolution.hpp @@ -1,6 +1,6 @@ /* Copyright 2016 SINTEF ICT, Applied Mathematics. - Copyright 2016 Statoil ASA. + Copyright 2016, 2017 Statoil ASA. This file is part of the Open Porous Media project (OPM). @@ -29,7 +29,7 @@ namespace Opm { - class ECLResultData; + class ECLRestartData; class ECLWellSolution { @@ -47,7 +47,7 @@ namespace Opm bool is_injector_well; struct Completion { - int grid_index; // 0 for main grid, otherwise LGR grid. + std::string gridName; // empty for main grid, otherwise LGR grid. std::array ijk; // Cartesian location in grid. double reservoir_inflow_rate; // Total fluid rate in SI (m^3/s). }; @@ -58,8 +58,8 @@ namespace Opm /// /// Will throw if required data is not available for the /// requested step. - std::vector solution(const ECLResultData& restart, - const int num_grids) const; + std::vector solution(const ECLRestartData& restart, + const std::vector& grids) const; private: // Data members. @@ -67,8 +67,8 @@ namespace Opm bool disallow_crossflow_; // Methods. - std::vector readWellData(const ECLResultData& restart, - const int grid_index) const; + std::vector readWellData(const ECLRestartData& restart, + const std::string& gridName) const; }; diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runAcceptanceTest.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runAcceptanceTest.cpp index 3b799a11fb..bb8108d72d 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runAcceptanceTest.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runAcceptanceTest.cpp @@ -250,7 +250,7 @@ namespace { } ErrorTolerance - testTolerances(const ::Opm::parameter::ParameterGroup& param) + testTolerances(const ::Opm::ParameterGroup& param) { const auto atol = param.getDefault("atol", 1.0e-8); const auto rtol = param.getDefault("rtol", 5.0e-12); @@ -277,7 +277,7 @@ namespace { } ReferenceToF - loadReference(const ::Opm::parameter::ParameterGroup& param, + loadReference(const ::Opm::ParameterGroup& param, const int step, const int nDigits) { diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runLinearisedCellDataTest.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runLinearisedCellDataTest.cpp index 89500d9b8e..1811f8a3ed 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runLinearisedCellDataTest.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runLinearisedCellDataTest.cpp @@ -377,7 +377,7 @@ namespace { } ErrorTolerance - testTolerances(const ::Opm::parameter::ParameterGroup& param) + testTolerances(const ::Opm::ParameterGroup& param) { const auto atol = param.getDefault("atol", 1.0e-8); const auto rtol = param.getDefault("rtol", 5.0e-12); @@ -386,7 +386,7 @@ namespace { } std::vector - testQuantities(const ::Opm::parameter::ParameterGroup& param) + testQuantities(const ::Opm::ParameterGroup& param) { return StringUtils::VectorValue:: get(param.get("quant")); @@ -411,7 +411,7 @@ namespace { } ReferenceSolution - loadReference(const ::Opm::parameter::ParameterGroup& param, + loadReference(const ::Opm::ParameterGroup& param, const std::string& quant, const int step, const int nDigits) @@ -493,7 +493,8 @@ namespace { std::array sampleDifferences(const ::Opm::ECLGraph& graph, - const ::Opm::parameter::ParameterGroup& param, + const ::Opm::ECLRestartData& rstrt, + const ::Opm::ParameterGroup& param, const std::string& quant, const std::vector& steps) { @@ -510,7 +511,7 @@ namespace { auto E = std::array{}; for (const auto& step : steps) { - if (! graph.selectReportStep(step)) { + if (! rstrt.selectReportStep(step)) { continue; } @@ -518,7 +519,7 @@ namespace { { const auto raw = Calculated { - graph.rawLinearisedCellData(ECLquant) + graph.rawLinearisedCellData(rstrt, ECLquant) }; computeErrors(Reference{ ref.raw }, raw, E[0]); @@ -526,7 +527,7 @@ namespace { { const auto SI = Calculated { - graph.linearisedCellData(ECLquant, unit) + graph.linearisedCellData(rstrt, ECLquant, unit) }; computeErrors(Reference{ ref.SI }, SI, E[1]); @@ -561,12 +562,14 @@ try { const auto pth = example::FilePaths(prm); const auto tol = testTolerances(prm); + const auto rstrt = ::Opm::ECLRestartData(pth.restart); const auto steps = availableReportSteps(pth); const auto graph = example::initGraph(pth); auto all_ok = true; for (const auto& quant : testQuantities(prm)) { - const auto E = sampleDifferences(graph, prm, quant, steps); + const auto E = + sampleDifferences(graph, rstrt, prm, quant, steps); const auto ok = everythingFine(E[0], tol) && everythingFine(E[1], tol); diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runTransTest.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runTransTest.cpp index e705cfede4..766a11048c 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runTransTest.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/tests/runTransTest.cpp @@ -152,7 +152,7 @@ namespace { } ErrorTolerance - testTolerances(const ::Opm::parameter::ParameterGroup& param) + testTolerances(const ::Opm::ParameterGroup& param) { const auto atol = param.getDefault("atol", 1.0e-8); const auto rtol = param.getDefault("rtol", 5.0e-12); @@ -161,7 +161,7 @@ namespace { } std::vector - loadReference(const ::Opm::parameter::ParameterGroup& param) + loadReference(const ::Opm::ParameterGroup& param) { namespace fs = boost::filesystem; @@ -185,7 +185,7 @@ namespace { }; } - bool transfieldAcceptable(const ::Opm::parameter::ParameterGroup& param, + bool transfieldAcceptable(const ::Opm::ParameterGroup& param, const std::vector& trans) { const auto Tref = loadReference(param); diff --git a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/DerivedQuantities.cpp b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/DerivedQuantities.cpp index 3ad859a0ef..dca1df6d21 100644 --- a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/DerivedQuantities.cpp +++ b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/DerivedQuantities.cpp @@ -1,5 +1,6 @@ /* - Copyright 2015, 2016 SINTEF ICT, Applied Mathematics. + Copyright 2015, 2016, 2017 SINTEF ICT, Applied Mathematics. + Copyright 2017 Statoil ASA. This file is part of the Open Porous Media project (OPM). @@ -70,9 +71,26 @@ namespace FlowDiagnostics const Toolbox::Reverse& producer_solution, const std::vector& pv) { - const auto& ftof = injector_solution.fd.timeOfFlight(); - const auto& rtof = producer_solution.fd.timeOfFlight(); - if (pv.size() != ftof.size() || pv.size() != rtof.size()) { + return flowCapacityStorageCapacityCurve(injector_solution.fd.timeOfFlight(), + producer_solution.fd.timeOfFlight(), + pv); + } + + + + + /// The F-Phi curve. + /// + /// The F-Phi curve is an analogue to the fractional flow + /// curve in a 1D displacement. It can be used to compute + /// other interesting diagnostic quantities such as the Lorenz + /// coefficient. For a technical description see Shavali et + /// al. (SPE 146446), Shook and Mitchell (SPE 124625). + Graph flowCapacityStorageCapacityCurve(const std::vector& injector_tof, + const std::vector& producer_tof, + const std::vector& pv) + { + if (pv.size() != injector_tof.size() || pv.size() != producer_tof.size()) { throw std::runtime_error("flowCapacityStorageCapacityCurve(): " "Input solutions must have same size."); } @@ -82,12 +100,12 @@ namespace FlowDiagnostics typedef std::pair D2; std::vector time_and_pv(n); for (int ii = 0; ii < n; ++ii) { - time_and_pv[ii].first = ftof[ii] + rtof[ii]; // Total travel time. + time_and_pv[ii].first = injector_tof[ii] + producer_tof[ii]; // Total travel time. time_and_pv[ii].second = pv[ii]; } std::sort(time_and_pv.begin(), time_and_pv.end()); - auto Phi = cumulativeNormalized(time_and_pv, [](const D2& i) { return i.first; }); + auto Phi = cumulativeNormalized(time_and_pv, [](const D2& i) { return i.second; }); auto F = cumulativeNormalized(time_and_pv, [](const D2& i) { return i.second / i.first; }); return Graph{std::move(Phi), std::move(F)}; diff --git a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/DerivedQuantities.hpp b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/DerivedQuantities.hpp index 0f3642bec1..22023ab708 100644 --- a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/DerivedQuantities.hpp +++ b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/DerivedQuantities.hpp @@ -50,6 +50,14 @@ namespace FlowDiagnostics const Toolbox::Reverse& producer_solution, const std::vector& pore_volume); + /// This overload gets the injector and producer time-of-flight + /// directly instead of extracting it from the solution + /// objects. It otherwise behaves identically to the other + /// overload. + Graph flowCapacityStorageCapacityCurve(const std::vector& injector_tof, + const std::vector& producer_tof, + const std::vector& pore_volume); + /// The Lorenz coefficient from the F-Phi curve. /// /// The Lorenz coefficient is a measure of heterogeneity. It diff --git a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/Solution.cpp b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/Solution.cpp index ee88861d39..d31e65bc7e 100644 --- a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/Solution.cpp +++ b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/Solution.cpp @@ -1,5 +1,6 @@ /* Copyright 2016 SINTEF ICT, Applied Mathematics. + Copyright 2016 Statoil ASA. This file is part of the Open Porous Media project (OPM). diff --git a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/TracerTofSolver.cpp b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/TracerTofSolver.cpp index 064f8c61e7..dc1994df86 100644 --- a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/TracerTofSolver.cpp +++ b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/flowdiagnostics/TracerTofSolver.cpp @@ -1,6 +1,6 @@ /* Copyright 2016 SINTEF ICT, Applied Mathematics. - Copyright 2016 Statoil ASA. + Copyright 2016, 2017 Statoil ASA. This file is part of the Open Porous Media project (OPM). diff --git a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/utility/graph/AssembledConnectionsIteration.hpp b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/utility/graph/AssembledConnectionsIteration.hpp index b949242505..d91baeaeff 100644 --- a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/utility/graph/AssembledConnectionsIteration.hpp +++ b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/opm/utility/graph/AssembledConnectionsIteration.hpp @@ -1,5 +1,6 @@ /* Copyright 2016 SINTEF ICT, Applied Mathematics. + Copyright 2016 Statoil ASA. This file is part of the Open Porous Media project (OPM). diff --git a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/tests/test_derivedquantities.cpp b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/tests/test_derivedquantities.cpp index bab38628a1..6c14694949 100644 --- a/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/tests/test_derivedquantities.cpp +++ b/ThirdParty/custom-opm-flowdiagnostics/opm-flowdiagnostics/tests/test_derivedquantities.cpp @@ -247,6 +247,8 @@ BOOST_AUTO_TEST_CASE (OneDimCase) BOOST_CHECK_THROW(flowCapacityStorageCapacityCurve(fwd, rev, {}), std::runtime_error); const auto fcapscap = flowCapacityStorageCapacityCurve(fwd, rev, pv); check_is_close(fcapscap, expectedFPhi); + const auto fcapscap2 = flowCapacityStorageCapacityCurve(fwd.fd.timeOfFlight(), rev.fd.timeOfFlight(), pv); + check_is_close(fcapscap2, expectedFPhi); BOOST_TEST_MESSAGE("==== Lorenz coefficient"); const double expectedLorenz = 0.0; @@ -296,4 +298,28 @@ BOOST_AUTO_TEST_CASE (OneDimCase) } + + + + +BOOST_AUTO_TEST_CASE (GeneralCase) +{ + BOOST_TEST_MESSAGE("==== F-Phi graph"); + + std::vector pv { 1.0, 2.0, 1.0 }; + std::vector ftof { 0.0, 2.0, 1.0 }; + std::vector rtof { 1.0, 2.0, 0.0 }; + const Graph expectedFPhi{ + { 0.0, 0.25, 0.5, 1.0 }, + { 0.0, 0.4, 0.8, 1.0 } + }; + const auto fcapscap = flowCapacityStorageCapacityCurve(ftof, rtof, pv); + check_is_close(fcapscap, expectedFPhi); + + BOOST_TEST_MESSAGE("==== Lorenz coefficient"); + const double expectedLorenz = 0.3; + BOOST_CHECK_CLOSE(lorenzCoefficient(fcapscap), expectedLorenz, 1e-10); +} + + BOOST_AUTO_TEST_SUITE_END() From 776e0ff1c4c89127a1e3b6cc0ef614ccb4baf7d4 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 12 May 2017 12:19:03 +0200 Subject: [PATCH 109/157] #1372 Fix compile error on Windows --- .../opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp index 0e3ee28afd..52d94ced43 100644 --- a/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp +++ b/ThirdParty/custom-opm-flowdiag-app/opm-flowdiagnostics-applications/opm/utility/ECLGraph.cpp @@ -1076,7 +1076,7 @@ ECL::CartesianGridData:: haveCellData(const ResultSet& rset, const std::string& vector) const { - return rset.template haveKeywordData(vector, this->gridName()); + return rset.haveKeywordData(vector, this->gridName()); } bool From 54c6e1c60057e13d93bf6f526ef31fc573834af0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 12 May 2017 12:22:50 +0200 Subject: [PATCH 110/157] #1372 Update solver interface due to API changes in flow diagnostics --- .../RigFlowDiagInterfaceTools.h | 82 ++++++++++------ .../RigFlowDiagSolverInterface.cpp | 93 ++++++++++++------- .../RigFlowDiagSolverInterface.h | 4 +- .../UnitTests/opm-flowdiagnostics-Test.cpp | 12 ++- 4 files changed, 123 insertions(+), 68 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagInterfaceTools.h b/ApplicationCode/ReservoirDataModel/RigFlowDiagInterfaceTools.h index 8942f7beae..b5292e26eb 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagInterfaceTools.h +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagInterfaceTools.h @@ -18,56 +18,83 @@ namespace RigFlowDiagInterfaceTools { + template inline Opm::FlowDiagnostics::ConnectionValues - extractFluxField(const Opm::ECLGraph& G, const bool compute_fluxes) + extractFluxField(const Opm::ECLGraph& G, + FluxCalc&& getFlux) { using ConnVals = Opm::FlowDiagnostics::ConnectionValues; + + const auto actPh = G.activePhases(); + auto flux = ConnVals(ConnVals::NumConnections{ G.numConnections() }, - ConnVals::NumPhases{ 3 }); - + ConnVals::NumPhases{ actPh.size() }); + auto phas = ConnVals::PhaseID{ 0 }; - - Opm::ECLFluxCalc calc(G); - - const auto phases = { Opm::ECLGraph::PhaseIndex::Aqua , - Opm::ECLGraph::PhaseIndex::Liquid , - Opm::ECLGraph::PhaseIndex::Vapour }; - - for ( const auto& p : phases ) - { - const auto pflux = compute_fluxes ? calc.flux(p) : G.flux(p); - if ( ! pflux.empty() ) - { - assert (pflux.size() == flux.numConnections()); + + for (const auto& p : actPh) { + const auto pflux = getFlux(p); + + if (!pflux.empty()) { + assert(pflux.size() == flux.numConnections()); + auto conn = ConnVals::ConnID{ 0 }; - for ( const auto& v : pflux ) - { + for (const auto& v : pflux) { flux(conn, phas) = v; conn.id += 1; } } + phas.id += 1; } - + return flux; } + inline Opm::FlowDiagnostics::ConnectionValues + extractFluxField(const Opm::ECLGraph& G, + const Opm::ECLRestartData& rstrt, + const bool compute_fluxes) + { + if (compute_fluxes) { + Opm::ECLFluxCalc calc(G); + + auto getFlux = [&calc, &rstrt] + (const Opm::ECLGraph::PhaseIndex p) + { + return calc.flux(rstrt, p); + }; + + return extractFluxField(G, getFlux); + } + + auto getFlux = [&G, &rstrt] + (const Opm::ECLGraph::PhaseIndex p) + { + return G.flux(rstrt, p); + }; + + return extractFluxField(G, getFlux); + } + template Opm::FlowDiagnostics::CellSetValues - extractWellFlows(const Opm::ECLGraph& G, - const WellFluxes& well_fluxes) + extractWellFlows(const Opm::ECLGraph& G, + const WellFluxes& well_fluxes) { Opm::FlowDiagnostics::CellSetValues inflow; for (const auto& well : well_fluxes) { for (const auto& completion : well.completions) { - const int grid_index = completion.grid_index; + const auto& gridName = completion.gridName; const auto& ijk = completion.ijk; - const int cell_index = G.activeCell(ijk, grid_index); + const int cell_index = G.activeCell(ijk, gridName); if (cell_index >= 0) { - auto iterIsInsertedPair = inflow.emplace(cell_index, completion.reservoir_inflow_rate); - if (!iterIsInsertedPair.second){ // Not inserted, We had something there already - iterIsInsertedPair.first->second += completion.reservoir_inflow_rate; // Accumulate the flow at this connection - } + // Since inflow is a std::map, if the key was not + // already present operator[] will insert a + // value-initialized value (as in T() for a type + // T), which is zero for built-in numerical types, + // including double. + inflow[cell_index] += completion.reservoir_inflow_rate; } } } @@ -75,7 +102,6 @@ namespace RigFlowDiagInterfaceTools { return inflow; } - } diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp index 9fd5b6dfa1..b9e34ea5c5 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.cpp @@ -104,19 +104,25 @@ void RigFlowDiagTimeStepResult::addResult(const RigFlowDiagResultAddress& resAdd } -class RigOpmFldStaticData : public cvf::Object +class RigOpmFlowDiagStaticData : public cvf::Object { public: - RigOpmFldStaticData(const std::string& grid, const std::string& init) : m_eclGraph(Opm::ECLGraph::load(grid, init)), m_hasUnifiedRestartFile(false) + RigOpmFlowDiagStaticData(const std::string& grid, const std::string& init) { - m_poreVolume = m_eclGraph.poreVolume(); + Opm::ECLInitFileData initData(init); + + m_eclGraph.reset(new Opm::ECLGraph(Opm::ECLGraph::load(grid, initData))); + + m_hasUnifiedRestartFile = false; + m_poreVolume = m_eclGraph->poreVolume(); } - Opm::ECLGraph m_eclGraph; + std::unique_ptr m_eclGraph; std::vector m_poreVolume; std::unique_ptr m_fldToolbox; bool m_hasUnifiedRestartFile; - QStringList m_restartFileNames; + std::vector m_singleRestartDataTimeSteps; + std::unique_ptr m_unifiedRestartData; }; @@ -150,9 +156,8 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI RigFlowDiagTimeStepResult result(m_eclipseCase->eclipseCaseData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->reservoirActiveCellCount()); caf::ProgressInfo progressInfo(8, "Calculating Flow Diagnostics"); - - if ( m_opmFldData.isNull() ) + if ( m_opmFlowDiagStaticData.isNull() ) { progressInfo.setProgressDescription("Grid access"); @@ -165,66 +170,77 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI QString initFileName = RifEclipseOutputFileTools::firstFileNameOfType(m_filesWithSameBaseName, ECL_INIT_FILE); - m_opmFldData = new RigOpmFldStaticData(gridFileName.toStdString(), + m_opmFlowDiagStaticData = new RigOpmFlowDiagStaticData(gridFileName.toStdString(), initFileName.toStdString()); progressInfo.incrementProgress(); progressInfo.setProgressDescription("Calculating Connectivities"); const Opm::FlowDiagnostics::ConnectivityGraph connGraph = - Opm::FlowDiagnostics::ConnectivityGraph{ static_cast(m_opmFldData->m_eclGraph.numCells()), - m_opmFldData->m_eclGraph.neighbours() }; + Opm::FlowDiagnostics::ConnectivityGraph{ static_cast(m_opmFlowDiagStaticData->m_eclGraph->numCells()), + m_opmFlowDiagStaticData->m_eclGraph->neighbours() }; progressInfo.incrementProgress(); progressInfo.setProgressDescription("Initialize Solver"); // Create the Toolbox. - m_opmFldData->m_fldToolbox.reset(new Opm::FlowDiagnostics::Toolbox{ connGraph }); - m_opmFldData->m_fldToolbox->assignPoreVolume( m_opmFldData->m_poreVolume); + m_opmFlowDiagStaticData->m_fldToolbox.reset(new Opm::FlowDiagnostics::Toolbox{ connGraph }); + m_opmFlowDiagStaticData->m_fldToolbox->assignPoreVolume( m_opmFlowDiagStaticData->m_poreVolume); // Look for unified restart file QString restartFileName = RifEclipseOutputFileTools::firstFileNameOfType(m_filesWithSameBaseName, ECL_UNIFIED_RESTART_FILE); if ( !restartFileName.isEmpty() ) { - m_opmFldData->m_eclGraph.assignFluxDataSource(restartFileName.toStdString()); - m_opmFldData->m_hasUnifiedRestartFile = true; + m_opmFlowDiagStaticData->m_unifiedRestartData.reset(new Opm::ECLRestartData(Opm::ECLRestartData(restartFileName.toStdString()))); + m_opmFlowDiagStaticData->m_hasUnifiedRestartFile = true; } else { + QStringList restartFileNames = RifEclipseOutputFileTools::filterFileNamesOfType(m_filesWithSameBaseName, ECL_RESTART_FILE); - m_opmFldData->m_restartFileNames = RifEclipseOutputFileTools::filterFileNamesOfType(m_filesWithSameBaseName, ECL_RESTART_FILE); - - size_t restartFileCount = static_cast(m_opmFldData->m_restartFileNames.size()); + size_t restartFileCount = static_cast(restartFileNames.size()); size_t maxTimeStepCount = m_eclipseCase->eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS)->maxTimeStepCount(); - if (restartFileCount <= timeStepIndex && restartFileCount != maxTimeStepCount ) + if (restartFileCount <= timeStepIndex && restartFileCount != maxTimeStepCount ) { QMessageBox::critical(nullptr, "ResInsight", "Flow Diagnostics: Could not find all the restart files. Results will not be loaded."); return result; } - m_opmFldData->m_restartFileNames.sort(); // To make sure they are sorted in increasing *.X000N order. Hack. Should probably be actual time stored on file. - m_opmFldData->m_hasUnifiedRestartFile = false; + restartFileNames.sort(); // To make sure they are sorted in increasing *.X000N order. Hack. Should probably be actual time stored on file. + m_opmFlowDiagStaticData->m_hasUnifiedRestartFile = false; + + for (auto restartFileName : restartFileNames) + { + m_opmFlowDiagStaticData->m_singleRestartDataTimeSteps.push_back(Opm::ECLRestartData(restartFileName.toStdString())); + } } } progressInfo.setProgress(3); progressInfo.setProgressDescription("Assigning Flux Field"); - if ( ! m_opmFldData->m_hasUnifiedRestartFile ) + Opm::ECLRestartData* currentRestartData = nullptr; + + if ( ! m_opmFlowDiagStaticData->m_hasUnifiedRestartFile ) { - QString restartFileName = m_opmFldData->m_restartFileNames[static_cast(timeStepIndex)]; - m_opmFldData->m_eclGraph.assignFluxDataSource(restartFileName.toStdString()); + currentRestartData = &(m_opmFlowDiagStaticData->m_singleRestartDataTimeSteps[timeStepIndex]); } + else + { + currentRestartData = m_opmFlowDiagStaticData->m_unifiedRestartData.get(); + } + + CVF_ASSERT(currentRestartData); size_t resultIndexWithMaxTimeSteps = cvf::UNDEFINED_SIZE_T; m_eclipseCase->eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS)->maxTimeStepCount(&resultIndexWithMaxTimeSteps); int reportStepNumber = m_eclipseCase->eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS)->reportStepNumber(resultIndexWithMaxTimeSteps, timeStepIndex); - if ( ! m_opmFldData->m_eclGraph.selectReportStep(reportStepNumber) ) + if ( !currentRestartData->selectReportStep(reportStepNumber) ) { QMessageBox::critical(nullptr, "ResInsight", "Flow Diagnostics: Could not find the requested timestep in the result file. Results will not be loaded."); return result; @@ -235,22 +251,25 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI Opm::FlowDiagnostics::CellSetValues sumWellFluxPrCell; { - Opm::FlowDiagnostics::ConnectionValues connectionsVals = RigFlowDiagInterfaceTools::extractFluxField(m_opmFldData->m_eclGraph, false); + Opm::FlowDiagnostics::ConnectionValues connectionsVals = RigFlowDiagInterfaceTools::extractFluxField(*(m_opmFlowDiagStaticData->m_eclGraph), + *currentRestartData, + false); - m_opmFldData->m_fldToolbox->assignConnectionFlux(connectionsVals); + m_opmFlowDiagStaticData->m_fldToolbox->assignConnectionFlux(connectionsVals); progressInfo.incrementProgress(); Opm::ECLWellSolution wsol = Opm::ECLWellSolution{-1.0 , false}; - const std::vector well_fluxes = - wsol.solution(m_opmFldData->m_eclGraph.rawResultData(), m_opmFldData->m_eclGraph.numGrids()); + std::vector gridNames = m_opmFlowDiagStaticData->m_eclGraph->activeGrids(); - sumWellFluxPrCell = RigFlowDiagInterfaceTools::extractWellFlows(m_opmFldData->m_eclGraph, well_fluxes); + const std::vector well_fluxes = wsol.solution(*currentRestartData, gridNames); - m_opmFldData->m_fldToolbox->assignInflowFlux(sumWellFluxPrCell); + sumWellFluxPrCell = RigFlowDiagInterfaceTools::extractWellFlows(*(m_opmFlowDiagStaticData->m_eclGraph), well_fluxes); - // Filter connection cells with inconsistent well in flow direction (Hack, we should do something better) + m_opmFlowDiagStaticData->m_fldToolbox->assignInflowFlux(sumWellFluxPrCell); + + // Start Hack: Filter connection cells with inconsistent well in flow direction (Hack, we should do something better) for ( auto& tracerCellIdxsPair: injectorTracers ) { @@ -259,6 +278,8 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI for (int activeCellIdx : tracerCellIdxsPair.second) { auto activeCellIdxFluxPair = sumWellFluxPrCell.find(activeCellIdx); + CVF_TIGHT_ASSERT(activeCellIdxFluxPair != sumWellFluxPrCell.end()); + if (activeCellIdxFluxPair->second > 0 ) { filteredCellIndices.push_back(activeCellIdx); @@ -275,6 +296,8 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI for (int activeCellIdx : tracerCellIdxsPair.second) { auto activeCellIdxFluxPair = sumWellFluxPrCell.find(activeCellIdx); + CVF_TIGHT_ASSERT(activeCellIdxFluxPair != sumWellFluxPrCell.end()); + if (activeCellIdxFluxPair->second < 0 ) { filteredCellIndices.push_back(activeCellIdx); @@ -282,6 +305,8 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI } if (tracerCellIdxsPair.second.size() != filteredCellIndices.size()) tracerCellIdxsPair.second = filteredCellIndices; } + + // End Hack } progressInfo.incrementProgress(); @@ -299,7 +324,7 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI std::unique_ptr injectorSolution; try { - injectorSolution.reset(new Toolbox::Forward( m_opmFldData->m_fldToolbox->computeInjectionDiagnostics(injectorCellSets))); + injectorSolution.reset(new Toolbox::Forward( m_opmFlowDiagStaticData->m_fldToolbox->computeInjectionDiagnostics(injectorCellSets))); } catch (const std::exception& e) { @@ -329,7 +354,7 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI std::unique_ptr producerSolution; try { - producerSolution.reset(new Toolbox::Reverse(m_opmFldData->m_fldToolbox->computeProductionDiagnostics(prodjCellSets))); + producerSolution.reset(new Toolbox::Reverse(m_opmFlowDiagStaticData->m_fldToolbox->computeProductionDiagnostics(prodjCellSets))); } catch ( const std::exception& e ) { @@ -375,7 +400,7 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI { Graph flowCapStorCapCurve = flowCapacityStorageCapacityCurve(*(injectorSolution.get()), *(producerSolution.get()), - m_opmFldData->m_poreVolume); + m_opmFlowDiagStaticData->m_poreVolume); result.setFlowCapStorageCapCurve(flowCapStorCapCurve); result.setSweepEfficiencyCurve(sweepEfficiency(flowCapStorCapCurve)); diff --git a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.h b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.h index 653d9e54d2..81a154b715 100644 --- a/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.h +++ b/ApplicationCode/ReservoirDataModel/RigFlowDiagSolverInterface.h @@ -70,7 +70,7 @@ private: class RigEclipseCaseData; -class RigOpmFldStaticData; +class RigOpmFlowDiagStaticData; class RigFlowDiagSolverInterface : public cvf::Object { @@ -85,7 +85,7 @@ public: private: RimEclipseResultCase * m_eclipseCase; - cvf::ref m_opmFldData; + cvf::ref m_opmFlowDiagStaticData; }; diff --git a/ApplicationCode/UnitTests/opm-flowdiagnostics-Test.cpp b/ApplicationCode/UnitTests/opm-flowdiagnostics-Test.cpp index 4810098233..5279eff299 100644 --- a/ApplicationCode/UnitTests/opm-flowdiagnostics-Test.cpp +++ b/ApplicationCode/UnitTests/opm-flowdiagnostics-Test.cpp @@ -2,6 +2,7 @@ const std::string casePath = "\\\\csfiles\\Store\\ProjectData\\StatoilReservoir\\ReferenceCases\\simple_FlowDiag_Model\\"; +/* #include "exampleSetup.hpp" TEST(opm_flowdiagnostics_test, basic_construction) @@ -9,12 +10,14 @@ TEST(opm_flowdiagnostics_test, basic_construction) try { - + Opm::ECLRestartData rstrt(casePath + "SIMPLE.UNRST"); + Opm::ECLInitFileData initData(casePath + "SIMPLE.INIT"); + Opm::ECLGraph graph = Opm::ECLGraph::load(casePath + "SIMPLE.EGRID", - casePath + "SIMPLE.INIT"); - graph.assignFluxDataSource(casePath + "SIMPLE.UNRST"); + initData); + int step = 2; - if ( ! graph.selectReportStep(step) ) + if ( ! rstrt.selectReportStep(step) ) { std::ostringstream os; @@ -44,3 +47,4 @@ TEST(opm_flowdiagnostics_test, basic_construction) std::cerr << "Caught exception: " << e.what() << '\n'; } } +*/ From 7c1f9b90bad4fd2ff7f9897fc5b3faec1bdbe8ca Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 15 May 2017 07:56:11 +0200 Subject: [PATCH 111/157] #1425 Do not show Time History Curve command for flow diag results --- .../RicNewGridTimeHistoryCurveFeature.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicNewGridTimeHistoryCurveFeature.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicNewGridTimeHistoryCurveFeature.cpp index 788aba473b..f588f5a4d6 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicNewGridTimeHistoryCurveFeature.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicNewGridTimeHistoryCurveFeature.cpp @@ -216,6 +216,15 @@ bool RicNewGridTimeHistoryCurveFeature::isCommandEnabled() if (items.size() > 0) { + const RiuEclipseSelectionItem* eclSelectionItem = dynamic_cast(items[0]); + if (eclSelectionItem) + { + if (eclSelectionItem->m_view->cellResult()->resultType() == RimDefines::FLOW_DIAGNOSTICS) + { + return false; + } + } + return true; } From e38b7329d1bad6ed06ea380b4e79c3dd285733da Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 15 May 2017 09:17:06 +0200 Subject: [PATCH 112/157] #1469 Use time step strings from case --- .../ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp | 7 ++++--- .../UserInterface/RiuFlowCharacteristicsPlot.cpp | 6 +++--- ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp index 2f6f2768ce..db3622ec06 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp @@ -171,11 +171,11 @@ QList RimFlowCharacteristicsPlot::calculateValueOptions( RigFlowDiagResults* flowResult = m_flowDiagSolution->flowDiagResults(); std::vector calculatedTimesteps = flowResult->calculatedTimeSteps(); - std::vector timeStepDates = m_case->timeStepDates(); + QStringList timeStepDates = m_case->timeStepStrings(); for ( int tsIdx : calculatedTimesteps ) { - options.push_back(caf::PdmOptionItemInfo(timeStepDates[tsIdx].toString(), tsIdx)); + options.push_back(caf::PdmOptionItemInfo(timeStepDates[tsIdx], tsIdx)); } } } @@ -279,6 +279,7 @@ void RimFlowCharacteristicsPlot::loadDataAndUpdate() m_currentlyPlottedTimeSteps = calculatedTimesteps; std::vector timeStepDates = m_case->timeStepDates(); + QStringList timeStepStrings = m_case->timeStepStrings(); std::vector lorenzVals(timeStepDates.size(), HUGE_VAL); m_flowCharPlotWidget->removeAllCurves(); @@ -287,7 +288,7 @@ void RimFlowCharacteristicsPlot::loadDataAndUpdate() { lorenzVals[timeStepIdx] = flowResult->flowCharacteristicsResults(timeStepIdx).m_lorenzCoefficient; } - m_flowCharPlotWidget->setLorenzCurve(timeStepDates, lorenzVals); + m_flowCharPlotWidget->setLorenzCurve(timeStepStrings, timeStepDates, lorenzVals); for ( int timeStepIdx: calculatedTimesteps ) { diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp index ef40b5b283..09a39eaa13 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp @@ -114,7 +114,7 @@ RiuFlowCharacteristicsPlot::~RiuFlowCharacteristicsPlot() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuFlowCharacteristicsPlot::setLorenzCurve(const std::vector& dateTimes, const std::vector& timeHistoryValues) +void RiuFlowCharacteristicsPlot::setLorenzCurve(const QStringList& dateTimeStrings, const std::vector& dateTimes, const std::vector& timeHistoryValues) { initializeColors(dateTimes); @@ -127,7 +127,7 @@ void RiuFlowCharacteristicsPlot::setLorenzCurve(const std::vector& da QDateTime dateTime = dateTimes[tsIdx]; double timeHistoryValue = timeHistoryValues[tsIdx]; - QString curveName = dateTime.toString(); + QString curveName = dateTimeStrings[static_cast(tsIdx)]; RiuFlowCharacteristicsPlot::addCurveWithLargeSymbol(m_lorenzPlot, curveName, m_dateToColorMap[dateTime], dateTime, timeHistoryValue); } @@ -145,7 +145,7 @@ void RiuFlowCharacteristicsPlot::addCurveWithLargeSymbol(QwtPlot* plot, const QS QwtSymbol::Style style = QwtSymbol::Diamond; QwtSymbol* symbol = new QwtSymbol(style); - symbol->setSize(20, 20); + symbol->setSize(15, 15); symbol->setColor(color); curve->setSymbol(symbol); diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h index 794f2e1ea2..b2f763df59 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h @@ -50,7 +50,7 @@ public: RiuFlowCharacteristicsPlot(RimFlowCharacteristicsPlot* plotDefinition, QWidget* parent = NULL); virtual ~RiuFlowCharacteristicsPlot(); - void setLorenzCurve(const std::vector& dateTimes, const std::vector& timeHistoryValues); + void setLorenzCurve(const QStringList& dateTimeStrings, const std::vector& dateTimes, const std::vector& timeHistoryValues); void addFlowCapStorageCapCurve(const QDateTime& dateTime, const std::vector& xVals, const std::vector& yVals); void addSweepEfficiencyCurve(const QDateTime& dateTime, const std::vector& xVals, const std::vector& yVals); From 4d41f43a992b237332095037f5c11c7e42670da6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 15 May 2017 09:42:01 +0200 Subject: [PATCH 113/157] Upped to version 2016.11.flow.14 --- ResInsightVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 7d3d69bfb6..ca98751bcc 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -1,7 +1,7 @@ set(RESINSIGHT_MAJOR_VERSION 2016) set(RESINSIGHT_MINOR_VERSION 11) -set(RESINSIGHT_INCREMENT_VERSION "flow.13") +set(RESINSIGHT_INCREMENT_VERSION "flow.14") # https://github.com/CRAVA/crava/tree/master/libs/nrlib From 886f4ce3abb87cdaf47c0b14fe020d32c9218f84 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 15 May 2017 13:39:20 +0200 Subject: [PATCH 114/157] #1475 Use wellPathIndexInFile to be able to import multiple wells pr file --- ApplicationCode/ProjectDataModel/RimWellPath.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index 2fdf0005f1..90db7225ac 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -220,8 +220,8 @@ bool RimWellPath::readWellPathFile(QString* errorMessage, RifWellPathImporter* w { if (wellPathImporter->canReadFile(filepath())) { - RifWellPathImporter::WellData wellData = wellPathImporter->readWellData(filepath()); - RifWellPathImporter::WellMetaData wellMetaData = wellPathImporter->readWellMetaData(filepath()); + RifWellPathImporter::WellData wellData = wellPathImporter->readWellData(filepath(), wellPathIndexInFile()); + RifWellPathImporter::WellMetaData wellMetaData = wellPathImporter->readWellMetaData(filepath(), wellPathIndexInFile()); // General well info name = wellData.m_name; From 1a075470cf8b9629267a216f41780a34ff7faff9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 15 May 2017 13:40:13 +0200 Subject: [PATCH 115/157] #1475 Use caf::Utils::fileExists --- .../FileInterface/RifWellPathImporter.cpp | 19 ++++--------------- .../FileInterface/RifWellPathImporter.h | 2 -- .../ProjectDataModel/RimWellPath.cpp | 5 ++--- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/ApplicationCode/FileInterface/RifWellPathImporter.cpp b/ApplicationCode/FileInterface/RifWellPathImporter.cpp index ebefc05b18..f4b1afedbf 100644 --- a/ApplicationCode/FileInterface/RifWellPathImporter.cpp +++ b/ApplicationCode/FileInterface/RifWellPathImporter.cpp @@ -24,30 +24,19 @@ #include +#include "cafUtils.h" + #include #define ASCII_FILE_DEFAULT_START_INDEX 0 -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RifWellPathImporter::canReadFile(const QString& filePath) -{ - QFileInfo fileInfo(filePath); - if (fileInfo.isFile() && fileInfo.exists()) - { - return true; - } - return false; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RifWellPathImporter::WellData RifWellPathImporter::readWellData(const QString& filePath, size_t indexInFile) { - CVF_ASSERT(canReadFile(filePath)); + CVF_ASSERT(caf::Utils::fileExists(filePath)); if (isJsonFile(filePath)) { @@ -72,7 +61,7 @@ RifWellPathImporter::WellData RifWellPathImporter::readWellData(const QString& f //-------------------------------------------------------------------------------------------------- RifWellPathImporter::WellMetaData RifWellPathImporter::readWellMetaData(const QString& filePath, size_t indexInFile) { - CVF_ASSERT(canReadFile(filePath)); + CVF_ASSERT(caf::Utils::fileExists(filePath)); if (isJsonFile(filePath)) { diff --git a/ApplicationCode/FileInterface/RifWellPathImporter.h b/ApplicationCode/FileInterface/RifWellPathImporter.h index dc24e90778..fc1db746a3 100644 --- a/ApplicationCode/FileInterface/RifWellPathImporter.h +++ b/ApplicationCode/FileInterface/RifWellPathImporter.h @@ -59,8 +59,6 @@ public: WellMetaData readWellMetaData(const QString& filePath); size_t wellDataCount(const QString& filePath); - static bool canReadFile(const QString& filePath); - void clear(); void removeFilePath(const QString& filePath); diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index 90db7225ac..b8e0686fc0 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -39,9 +39,8 @@ #include "RivWellPathPartMgr.h" -#include "cafUtils.h" - #include "cafPdmUiTreeOrdering.h" +#include "cafUtils.h" #include #include @@ -218,7 +217,7 @@ caf::PdmFieldHandle* RimWellPath::objectToggleField() //-------------------------------------------------------------------------------------------------- bool RimWellPath::readWellPathFile(QString* errorMessage, RifWellPathImporter* wellPathImporter) { - if (wellPathImporter->canReadFile(filepath())) + if (caf::Utils::fileExists(filepath())) { RifWellPathImporter::WellData wellData = wellPathImporter->readWellData(filepath(), wellPathIndexInFile()); RifWellPathImporter::WellMetaData wellMetaData = wellPathImporter->readWellMetaData(filepath(), wellPathIndexInFile()); From 57a521f59da31107f9719a902fe4d02160a23b5f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 15 May 2017 14:06:40 +0200 Subject: [PATCH 116/157] #1475 Add missing includes for Linux --- ApplicationCode/FileInterface/RifWellPathImporter.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ApplicationCode/FileInterface/RifWellPathImporter.cpp b/ApplicationCode/FileInterface/RifWellPathImporter.cpp index f4b1afedbf..de8199efa0 100644 --- a/ApplicationCode/FileInterface/RifWellPathImporter.cpp +++ b/ApplicationCode/FileInterface/RifWellPathImporter.cpp @@ -28,6 +28,9 @@ #include +#include +#include + #define ASCII_FILE_DEFAULT_START_INDEX 0 From acb050e9fbc06e033747d863f29f80d03bb5c2fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Mon, 15 May 2017 15:46:28 +0200 Subject: [PATCH 117/157] #1489 Create Eclipse output file formatter --- .../FileInterface/CMakeLists_files.cmake | 2 + .../RifEclipseOutputTableFormatter.cpp | 258 ++++++++++++++++++ .../RifEclipseOutputTableFormatter.h | 107 ++++++++ 3 files changed, 367 insertions(+) create mode 100644 ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp create mode 100644 ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h diff --git a/ApplicationCode/FileInterface/CMakeLists_files.cmake b/ApplicationCode/FileInterface/CMakeLists_files.cmake index 95fd893e9e..de87bab30a 100644 --- a/ApplicationCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/FileInterface/CMakeLists_files.cmake @@ -7,6 +7,7 @@ endif() set (SOURCE_GROUP_HEADER_FILES ${CEE_CURRENT_LIST_DIR}RifEclipseInputFileTools.h ${CEE_CURRENT_LIST_DIR}RifEclipseOutputFileTools.h +${CEE_CURRENT_LIST_DIR}RifEclipseOutputTableFormatter.h ${CEE_CURRENT_LIST_DIR}RifEclipseRestartDataAccess.h ${CEE_CURRENT_LIST_DIR}RifEclipseRestartFilesetAccess.h ${CEE_CURRENT_LIST_DIR}RifEclipseSummaryTools.h @@ -25,6 +26,7 @@ ${CEE_CURRENT_LIST_DIR}RifWellPathImporter.h set (SOURCE_GROUP_SOURCE_FILES ${CEE_CURRENT_LIST_DIR}RifEclipseInputFileTools.cpp ${CEE_CURRENT_LIST_DIR}RifEclipseOutputFileTools.cpp +${CEE_CURRENT_LIST_DIR}RifEclipseOutputTableFormatter.cpp ${CEE_CURRENT_LIST_DIR}RifEclipseRestartDataAccess.cpp ${CEE_CURRENT_LIST_DIR}RifEclipseRestartFilesetAccess.cpp ${CEE_CURRENT_LIST_DIR}RifEclipseUnifiedRestartFileAccess.cpp diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp new file mode 100644 index 0000000000..27d8347a5b --- /dev/null +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp @@ -0,0 +1,258 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RifEclipseOutputTableFormatter.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifEclipseOutputTableFormatter::RifEclipseOutputTableFormatter(QTextStream& out) : m_out(out) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifEclipseOutputTableFormatter::~RifEclipseOutputTableFormatter() +{ + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifEclipseOutputTableFormatter::flush() +{ + if (!m_lineBuffer.empty()) rowCompleted(); + outputBuffer(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifEclipseOutputTableFormatter::outputBuffer() +{ + m_out << "-- "; + for (RifEclipseOutputTableColumn& column : m_columns) + { + m_out << formatColumn(column.title, column); + } + m_out << "\n"; + + for (auto line : m_buffer) + { + if (line.lineType == COMMENT) + { + m_out << "-- " << line.data[0] << "\n"; + } + else if (line.lineType == CONTENTS) + { + m_out << " "; + for (size_t i = 0; i < line.data.size(); ++i) + { + m_out << formatColumn(line.data[i], m_columns[i]); + } + m_out << " /" << "\n"; + } + } + m_buffer.clear(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifEclipseOutputTableFormatter& RifEclipseOutputTableFormatter::keyword(const QString keyword) +{ + flush(); + m_out << keyword << "\n"; + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifEclipseOutputTableFormatter& RifEclipseOutputTableFormatter::header(const std::vector header) +{ + outputBuffer(); + m_columns = header; + for (RifEclipseOutputTableColumn& column : m_columns) + { + column.width = measure(column.title); + } + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifEclipseOutputTableFormatter& RifEclipseOutputTableFormatter::comment(const QString comment) +{ + RifEclipseOutputTableLine line; + line.data.push_back(comment); + line.lineType = COMMENT; + m_buffer.push_back(line); + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifEclipseOutputTableFormatter& RifEclipseOutputTableFormatter::add(const QString str) +{ + size_t column = m_lineBuffer.size(); + CVF_ASSERT(column < m_columns.size()); + m_columns[column].width = std::max(measure(str), m_columns[column].width); + m_lineBuffer.push_back(str); + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifEclipseOutputTableFormatter& RifEclipseOutputTableFormatter::add(double num) +{ + size_t column = m_lineBuffer.size(); + CVF_ASSERT(column < m_columns.size()); + m_columns[column].width = std::max(measure(num), m_columns[column].width); + m_lineBuffer.push_back(format(num)); + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifEclipseOutputTableFormatter& RifEclipseOutputTableFormatter::add(int num) +{ + size_t column = m_lineBuffer.size(); + CVF_ASSERT(column < m_columns.size()); + m_columns[column].width = std::max(measure(num), m_columns[column].width); + m_lineBuffer.push_back(format(num)); + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifEclipseOutputTableFormatter& RifEclipseOutputTableFormatter::add(size_t num) +{ + size_t column = m_lineBuffer.size(); + CVF_ASSERT(column < m_columns.size()); + m_columns[column].width = std::max(measure(num), m_columns[column].width); + m_lineBuffer.push_back(format(num)); + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifEclipseOutputTableFormatter& RifEclipseOutputTableFormatter::addZeroBasedCellIndex(size_t index) +{ + size_t column = m_lineBuffer.size(); + CVF_ASSERT(column < m_columns.size()); + + // Increase index by 1 to use Eclipse 1-based cell index instead of ResInsight 0-based + index++; + + m_columns[column].width = std::max(measure(index), m_columns[column].width); + m_lineBuffer.push_back(format(index)); + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifEclipseOutputTableFormatter::rowCompleted() +{ + RifEclipseOutputTableLine line; + line.data = m_lineBuffer; + line.lineType = CONTENTS; + m_buffer.push_back(line); + m_lineBuffer.clear(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RifEclipseOutputTableFormatter::measure(const QString str) +{ + return str.length(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RifEclipseOutputTableFormatter::measure(double num) +{ + return format(num).length(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RifEclipseOutputTableFormatter::measure(int num) +{ + return format(num).length(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RifEclipseOutputTableFormatter::measure(size_t num) +{ + return format(num).length(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RifEclipseOutputTableFormatter::format(double num) +{ + return QString("%1").arg(num, 0, 'f', m_doubleDecimals); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RifEclipseOutputTableFormatter::format(int num) +{ + return QString("%1").arg(num); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RifEclipseOutputTableFormatter::format(size_t num) +{ + return QString("%1").arg(num); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RifEclipseOutputTableFormatter::formatColumn(const QString str, RifEclipseOutputTableColumn column) +{ + if (column.alignment == LEFT) + { + return str.leftJustified(column.width + m_colSpacing, ' '); + } + else + { + return str.rightJustified(column.width + m_colSpacing, ' '); + } +} diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h new file mode 100644 index 0000000000..7d8dd6e8e9 --- /dev/null +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h @@ -0,0 +1,107 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfObject.h" + +#include +#include + +#include + +//================================================================================================== +// +//================================================================================================== +enum RifEclipseOutputTableLineType +{ + COMMENT, + CONTENTS +}; + +//================================================================================================== +// +//================================================================================================== +enum RifEclipseOutputTableAlignment +{ + LEFT, + RIGHT +}; + +//================================================================================================== +// +//================================================================================================== +struct RifEclipseOutputTableLine +{ + RifEclipseOutputTableLineType lineType; + std::vector< QString > data; +}; + +//================================================================================================== +// +//================================================================================================== +struct RifEclipseOutputTableColumn +{ + QString title; + RifEclipseOutputTableAlignment alignment; + int width = -1; +}; + + +//================================================================================================== +// +//================================================================================================== +class RifEclipseOutputTableFormatter : public cvf::Object +{ +public: + RifEclipseOutputTableFormatter(QTextStream& out); + virtual ~RifEclipseOutputTableFormatter(); + + RifEclipseOutputTableFormatter& keyword(const QString keyword); + RifEclipseOutputTableFormatter& header(std::vector tableHeader); + RifEclipseOutputTableFormatter& add(const QString str); + RifEclipseOutputTableFormatter& add(double num); + RifEclipseOutputTableFormatter& add(int num); + RifEclipseOutputTableFormatter& add(size_t num); + RifEclipseOutputTableFormatter& addZeroBasedCellIndex(size_t index); + RifEclipseOutputTableFormatter& comment(const QString str); + void rowCompleted(); + void flush(); + +private: + int measure(const QString str); + int measure(double num); + int measure(int num); + int measure(size_t num); + + QString format(double num); + QString format(int num); + QString format(size_t num); + QString formatColumn(const QString str, RifEclipseOutputTableColumn column); + + void outputBuffer(); + +private: + std::vector m_columns; + std::vector m_buffer; + std::vector m_lineBuffer; + QTextStream& m_out; + int m_doubleDecimals = 5; + int m_colSpacing = 5; +}; From 9bf361ed643b8b0bb0ae38d770012dbcd5ca7073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Mon, 15 May 2017 15:48:24 +0200 Subject: [PATCH 118/157] #1462 Create generic select file and eclipse case to export model --- .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../RimCaseAndFileExportSettings.cpp | 69 +++++++++++++++++++ .../RimCaseAndFileExportSettings.h | 45 ++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.h diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index fafdfbc7b4..be2d6a1cd9 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -7,6 +7,7 @@ endif() set (SOURCE_GROUP_HEADER_FILES ${CEE_CURRENT_LIST_DIR}RimEclipseCaseCollection.h ${CEE_CURRENT_LIST_DIR}RimCaseCollection.h +${CEE_CURRENT_LIST_DIR}RimCaseAndFileExportSettings.h ${CEE_CURRENT_LIST_DIR}RimCellFilter.h ${CEE_CURRENT_LIST_DIR}RimEclipsePropertyFilter.h ${CEE_CURRENT_LIST_DIR}RimPropertyFilterCollection.h @@ -99,6 +100,7 @@ ${CEE_CURRENT_LIST_DIR}RimEclipseGeometrySelectionItem.h set (SOURCE_GROUP_SOURCE_FILES ${CEE_CURRENT_LIST_DIR}RimEclipseCaseCollection.cpp ${CEE_CURRENT_LIST_DIR}RimCaseCollection.cpp +${CEE_CURRENT_LIST_DIR}RimCaseAndFileExportSettings.cpp ${CEE_CURRENT_LIST_DIR}RimCellFilter.cpp ${CEE_CURRENT_LIST_DIR}RimEclipsePropertyFilter.cpp ${CEE_CURRENT_LIST_DIR}RimPropertyFilterCollection.cpp diff --git a/ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.cpp b/ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.cpp new file mode 100644 index 0000000000..c6a41657c5 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.cpp @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimCaseAndFileExportSettings.h" + +#include "RimTools.h" + +#include "cafPdmUiFilePathEditor.h" + +CAF_PDM_SOURCE_INIT(RimCaseAndFileExportSettings, "RimCaseAndFileExportSettings"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimCaseAndFileExportSettings::RimCaseAndFileExportSettings() +{ + CAF_PDM_InitObject("RimCaseAndFileExportSettings", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&fileName, "Filename", "Export filename", "", "", ""); + fileName.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); + + CAF_PDM_InitFieldNoDefault(&caseToApply, "CaseToApply", "Case to Apply", "", "", ""); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimCaseAndFileExportSettings::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) +{ + QList options; + + if (fieldNeedingOptions == &caseToApply) + { + RimTools::caseOptionItems(&options); + } + + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCaseAndFileExportSettings::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) +{ + if (field == &fileName) + { + caf::PdmUiFilePathEditorAttribute* myAttr = static_cast(attribute); + if (myAttr) + { + myAttr->m_selectSaveFileName = true; + } + } +} diff --git a/ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.h b/ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.h new file mode 100644 index 0000000000..686e075068 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.h @@ -0,0 +1,45 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimEclipseCase.h" + +#include "cafPdmObject.h" +#include "cafPdmField.h" +#include "cafPdmPtrField.h" + +//================================================================================================== +/// +/// +//================================================================================================== +class RimCaseAndFileExportSettings : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; +public: + + RimCaseAndFileExportSettings(); + + caf::PdmField fileName; + caf::PdmPtrField caseToApply; + + virtual QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override; +protected: + virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override; +}; From d0833adb4cb66b65606b0095f9eb54255e5d64e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Mon, 15 May 2017 15:49:49 +0200 Subject: [PATCH 119/157] #1462 Add functionality to check if a given coordinate is within a cell --- .../RigWellLogExtractionTools.h | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ApplicationCode/ReservoirDataModel/RigWellLogExtractionTools.h b/ApplicationCode/ReservoirDataModel/RigWellLogExtractionTools.h index 4232183bf6..ec0b6d5b97 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellLogExtractionTools.h +++ b/ApplicationCode/ReservoirDataModel/RigWellLogExtractionTools.h @@ -21,6 +21,7 @@ #include "cvfBoundingBox.h" #include "cvfGeometryTools.h" #include "cvfStructGrid.h" +#include "cvfRay.h" //================================================================================================== /// Internal class for intersection point info @@ -90,6 +91,28 @@ struct RigHexIntersector return intersectionCount; } + static bool isPointInCell(const cvf::Vec3d point, const cvf::Vec3d hexCorners[8], const size_t hexIndex) + { + cvf::Ray ray; + ray.setOrigin(point); + for (int face = 0; face < 6; ++face) + { + cvf::ubyte faceVertexIndices[4]; + cvf::StructGridInterface::cellFaceVertexIndices(static_cast(face), faceVertexIndices); + cvf::Vec3d faceCenter = cvf::GeometryTools::computeFaceCenter(hexCorners[faceVertexIndices[0]], hexCorners[faceVertexIndices[1]], hexCorners[faceVertexIndices[2]], hexCorners[faceVertexIndices[3]]); + + for (int i = 0; i < 4; ++i) + { + int next = i < 3 ? i + 1 : 0; + if (ray.triangleIntersect(hexCorners[faceVertexIndices[i]], hexCorners[faceVertexIndices[next]], faceCenter)) + { + return true; + } + } + } + return false; + } + static bool isEqualDepth(double d1, double d2) { double depthDiff = d1 - d2; From 46d8f83424b3ac2838d5382f98d1455486f73049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Mon, 15 May 2017 16:04:11 +0200 Subject: [PATCH 120/157] #1462 Export completion data for laterals --- .../WellPathCommands/CMakeLists_files.cmake | 2 + ...RicWellPathExportCompletionDataFeature.cpp | 354 ++++++++++++++++++ .../RicWellPathExportCompletionDataFeature.h | 71 ++++ .../RifEclipseOutputTableFormatter.cpp | 13 +- .../RimContextCommandBuilder.cpp | 1 + 5 files changed, 436 insertions(+), 5 deletions(-) create mode 100644 ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp create mode 100644 ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h diff --git a/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake index 063a266700..587e6a7b83 100644 --- a/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/WellPathCommands/CMakeLists_files.cmake @@ -6,6 +6,7 @@ endif() set (SOURCE_GROUP_HEADER_FILES ${CEE_CURRENT_LIST_DIR}RicWellPathDeleteFeature.h +${CEE_CURRENT_LIST_DIR}RicWellPathExportCompletionDataFeature.h ${CEE_CURRENT_LIST_DIR}RicWellPathImportCompletionsFileFeature.h ${CEE_CURRENT_LIST_DIR}RicWellPathsImportFileFeature.h ${CEE_CURRENT_LIST_DIR}RicWellPathsImportSsihubFeature.h @@ -14,6 +15,7 @@ ${CEE_CURRENT_LIST_DIR}RicWellPathViewerEventHandler.h set (SOURCE_GROUP_SOURCE_FILES ${CEE_CURRENT_LIST_DIR}RicWellPathDeleteFeature.cpp +${CEE_CURRENT_LIST_DIR}RicWellPathExportCompletionDataFeature.cpp ${CEE_CURRENT_LIST_DIR}RicWellPathImportCompletionsFileFeature.cpp ${CEE_CURRENT_LIST_DIR}RicWellPathsImportFileFeature.cpp ${CEE_CURRENT_LIST_DIR}RicWellPathsImportSsihubFeature.cpp diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp new file mode 100644 index 0000000000..4e6ed3d9ba --- /dev/null +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -0,0 +1,354 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicWellPathExportCompletionDataFeature.h" + +#include "RiaApplication.h" +#include "RiaLogging.h" + +#include "RimProject.h" +#include "RimWellPath.h" +#include "RimFishbonesMultipleSubs.h" +#include "RimCaseAndFileExportSettings.h" + +#include "RiuMainWindow.h" + +#include "RifEclipseOutputTableFormatter.h" + +#include "RigWellLogExtractionTools.h" +#include "RigEclipseCaseData.h" +#include "RigMainGrid.h" +#include "RigWellPath.h" + +#include "cafSelectionManager.h" +#include "cafPdmUiPropertyViewDialog.h" + +#include +#include +#include + +namespace caf +{ + CAF_CMD_SOURCE_INIT(RicWellPathExportCompletionDataFeature, "RicWellPathExportCompletionDataFeature"); + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicWellPathExportCompletionDataFeature::isCommandEnabled() +{ + std::vector objects; + caf::SelectionManager::instance()->objectsByType(&objects); + + if (objects.size() == 1) { + return true; + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked) +{ + std::vector objects; + caf::SelectionManager::instance()->objectsByType(&objects); + + CVF_ASSERT(objects.size() == 1); + + RiaApplication* app = RiaApplication::instance(); + + QString projectFolder = app->currentProjectPath(); + QString defaultDir = RiaApplication::instance()->lastUsedDialogDirectoryWithFallback("COMPLETIONS", projectFolder); + + RimCaseAndFileExportSettings exportSettings; + + exportSettings.fileName = QDir(defaultDir).filePath("Completions"); + + RimEclipseCase* caseToApply; + objects[0]->firstAncestorOrThisOfType(caseToApply); + exportSettings.caseToApply = caseToApply; + + caf::PdmUiPropertyViewDialog propertyDialog(RiuMainWindow::instance(), &exportSettings, "Export Completion Data", ""); + if (propertyDialog.exec() == QDialog::Accepted) + { + RiaApplication::instance()->setLastUsedDialogDirectory("COMPLETIONS", QFileInfo(exportSettings.fileName).absolutePath()); + + exportToFolder(objects[0], exportSettings.fileName, exportSettings.caseToApply); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("Export Completion Data"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply) +{ + QFile exportFile(fileName); + + if (!exportFile.open(QIODevice::WriteOnly)) + { + RiaLogging::error(QString("Export Completions Data: Could not open the file: %1").arg(fileName)); + return; + } + + QTextStream stream(&exportFile); + + const RigEclipseCaseData* caseData = caseToApply->eclipseCaseData(); + std::vector wellPathCells = findIntersectingCells(caseData, wellPath->wellPathGeometry()->m_wellPathPoints); + + RifEclipseOutputTableFormatter formatter(stream); + std::vector header = { + RifEclipseOutputTableColumn{"Well", LEFT}, + RifEclipseOutputTableColumn{"I", LEFT}, + RifEclipseOutputTableColumn{"J", LEFT}, + RifEclipseOutputTableColumn{"K1", LEFT}, + RifEclipseOutputTableColumn{"K2", LEFT}, + RifEclipseOutputTableColumn{"Status", LEFT}, + RifEclipseOutputTableColumn{"SAT", LEFT}, + RifEclipseOutputTableColumn{"TR", LEFT}, + RifEclipseOutputTableColumn{"DIAM", LEFT}, + RifEclipseOutputTableColumn{"KH", LEFT}, + RifEclipseOutputTableColumn{"S", LEFT}, + RifEclipseOutputTableColumn{"Df", LEFT}, + RifEclipseOutputTableColumn{"DIR", LEFT}, + RifEclipseOutputTableColumn{"r0", LEFT} + }; + + formatter.keyword("COMPDAT"); + formatter.header(header); + + for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesSubs) + { + for (size_t subIndex = 0; subIndex < subs->locationOfSubs().size(); ++subIndex) + { + for (size_t lateralIndex = 0; lateralIndex < subs->lateralLengths().size(); ++lateralIndex) + { + std::vector lateralCoords = subs->coordsForLateral(subIndex, lateralIndex); + + std::vector lateralCells = findIntersectingCells(caseData, lateralCoords); + + std::vector cellsUniqueToLateral = filterWellPathCells(lateralCells, wellPathCells); + + std::vector cellRanges = getCellIndexRange(caseData->mainGrid(), cellsUniqueToLateral); + + formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(subs->name()).arg(subIndex).arg(lateralIndex)); + for (auto cellRange : cellRanges) + { + // Add cell indices + formatter.add(wellPath->name()).addZeroBasedCellIndex(cellRange.i).addZeroBasedCellIndex(cellRange.j).addZeroBasedCellIndex(cellRange.k1).addZeroBasedCellIndex(cellRange.k2); + // Remaining data, to be computed + formatter.add("'OPEN'").add("1*").add("1*").add(0.0).add("1*").add("1*").add("1*").add("'Z'").add("1*"); + formatter.rowCompleted(); + } + } + } + } + formatter.flush(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RicWellPathExportCompletionDataFeature::findCloseCells(const RigEclipseCaseData* caseData, const cvf::BoundingBox& bb) +{ + std::vector closeCells; + caseData->mainGrid()->findIntersectingCells(bb, &closeCells); + return closeCells; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RicWellPathExportCompletionDataFeature::getCellIndexRange(const RigMainGrid* grid, const std::vector& cellIndices) +{ + // Retrieve I, J, K indices + std::vector eclipseCellIndices; + for (auto cellIndex : cellIndices) + { + size_t i, j, k; + if (!grid->ijkFromCellIndex(cellIndex, &i, &j, &k)) continue; + eclipseCellIndices.push_back(std::make_tuple(i, j, k)); + } + + // Remove any duplicate cells + { + std::set uniqueCellIndices(eclipseCellIndices.begin(), eclipseCellIndices.end()); + eclipseCellIndices.assign(uniqueCellIndices.begin(), uniqueCellIndices.end()); + } + + // Group cell indices in K-ranges + std::sort(eclipseCellIndices.begin(), eclipseCellIndices.end(), RicWellPathExportCompletionDataFeature::cellOrdering); + std::vector eclipseCellRanges; + size_t lastI = std::numeric_limits::max(); + size_t lastJ = std::numeric_limits::max(); + size_t lastK = std::numeric_limits::max(); + size_t startK = std::numeric_limits::max(); + for (EclipseCellIndex cell : eclipseCellIndices) + { + size_t i, j, k; + std::tie(i, j, k) = cell; + if (i != lastI || j != lastJ || k != lastK + 1) + { + if (startK != std::numeric_limits::max()) + { + EclipseCellIndexRange cellRange = {lastI, lastJ, startK, lastK}; + eclipseCellRanges.push_back(cellRange); + } + lastI = i; + lastJ = j; + lastK = k; + startK = k; + } + else + { + lastK = k; + } + } + // Append last cell range + if (startK != std::numeric_limits::max()) + { + EclipseCellIndexRange cellRange = {lastI, lastJ, startK, lastK}; + eclipseCellRanges.push_back(cellRange); + } + return eclipseCellRanges; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicWellPathExportCompletionDataFeature::cellOrdering(const EclipseCellIndex& cell1, const EclipseCellIndex& cell2) +{ + size_t i1, i2, j1, j2, k1, k2; + std::tie(i1, j1, k1) = cell1; + std::tie(i2, j2, k2) = cell2; + if (i1 == i2) + { + if (j1 == j2) + { + return k1 < k2; + } + else + { + return j1 < j2; + } + } + else + { + return i1 < i2; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RicWellPathExportCompletionDataFeature::findIntersectingCells(const RigEclipseCaseData* caseData, const std::vector& coords) +{ + const std::vector& nodeCoords = caseData->mainGrid()->nodes(); + std::vector cells; + + // Find starting cell + if (coords.size() > 0) + { + cvf::BoundingBox bb; + bb.add(coords[0]); + std::vector closeCells = findCloseCells(caseData, bb); + cvf::Vec3d hexCorners[8]; + + for (size_t closeCell : closeCells) + { + const RigCell& cell = caseData->mainGrid()->globalCellArray()[closeCell]; + if (cell.isInvalid()) continue; + + setHexCorners(cell, nodeCoords, hexCorners); + + if (RigHexIntersector::isPointInCell(coords[0], hexCorners, closeCell)) + { + cells.push_back(closeCell); + break; + } + } + } + + for (size_t i = 0; i < coords.size() - 1; ++i) + { + cvf::BoundingBox bb; + bb.add(coords[i]); + bb.add(coords[i + 1]); + + std::vector closeCells = findCloseCells(caseData, bb); + + cvf::Vec3d hexCorners[8]; + std::vector intersections; + + for (size_t closeCell : closeCells) + { + const RigCell& cell = caseData->mainGrid()->globalCellArray()[closeCell]; + if (cell.isInvalid()) continue; + + setHexCorners(cell, nodeCoords, hexCorners); + + RigHexIntersector::lineHexCellIntersection(coords[i], coords[i + 1], hexCorners, closeCell, &intersections); + } + + for (auto intersection : intersections) + { + cells.push_back(intersection.m_hexIndex); + } + } + std::sort(cells.begin(), cells.end()); + return cells; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::setHexCorners(const RigCell& cell, const std::vector& nodeCoords, cvf::Vec3d* hexCorners) +{ + const caf::SizeTArray8& cornerIndices = cell.cornerIndices(); + + hexCorners[0] = nodeCoords[cornerIndices[0]]; + hexCorners[1] = nodeCoords[cornerIndices[1]]; + hexCorners[2] = nodeCoords[cornerIndices[2]]; + hexCorners[3] = nodeCoords[cornerIndices[3]]; + hexCorners[4] = nodeCoords[cornerIndices[4]]; + hexCorners[5] = nodeCoords[cornerIndices[5]]; + hexCorners[6] = nodeCoords[cornerIndices[6]]; + hexCorners[7] = nodeCoords[cornerIndices[7]]; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RicWellPathExportCompletionDataFeature::filterWellPathCells(const std::vector& completionCells, const std::vector& wellPathCells) +{ + std::vector filteredCells; + std::set_difference(completionCells.begin(), completionCells.end(), wellPathCells.begin(), wellPathCells.end(), std::back_inserter(filteredCells)); + return filteredCells; +} + +} // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h new file mode 100644 index 0000000000..cba7d2507e --- /dev/null +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h @@ -0,0 +1,71 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigWellLogExtractionTools.h" + +#include "cafCmdFeature.h" + +#include "cvfBoundingBox.h" + +class RimWellPath; +class RimEclipseCase; +class RigEclipseCaseData; +class RigMainGrid; +class RigCell; + +namespace caf +{ + +struct EclipseCellIndexRange { + size_t i; + size_t j; + size_t k1; + size_t k2; +}; + +typedef std::tuple EclipseCellIndex; + +//================================================================================================== +/// +//================================================================================================== +class RicWellPathExportCompletionDataFeature : public CmdFeature +{ + CAF_CMD_HEADER_INIT; +protected: + + // Overrides + virtual bool isCommandEnabled() override; + virtual void onActionTriggered(bool isChecked) override; + virtual void setupActionLook(QAction* actionToSetup) override; + +private: + static void exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply); + static std::vector findCloseCells(const RigEclipseCaseData* caseData, const cvf::BoundingBox& bb); + static std::vector getCellIndexRange(const RigMainGrid* grid, const std::vector& cellIndices); + static bool cellOrdering(const EclipseCellIndex& cell1, const EclipseCellIndex& cell2); + static std::vector findIntersectingCells(const RigEclipseCaseData* grid, const std::vector& coords); + static void setHexCorners(const RigCell& cell, const std::vector& nodeCoords, cvf::Vec3d* hexCorners); + static std::vector filterWellPathCells(const std::vector& completionCells, const std::vector& wellPathCells); +}; + + + +} // end namespace caf diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp index 27d8347a5b..c1fc5e076b 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp @@ -48,12 +48,15 @@ void RifEclipseOutputTableFormatter::flush() //-------------------------------------------------------------------------------------------------- void RifEclipseOutputTableFormatter::outputBuffer() { - m_out << "-- "; - for (RifEclipseOutputTableColumn& column : m_columns) + if (m_columns.size() > 0) { - m_out << formatColumn(column.title, column); + m_out << "-- "; + for (RifEclipseOutputTableColumn& column : m_columns) + { + m_out << formatColumn(column.title, column); + } + m_out << "\n"; } - m_out << "\n"; for (auto line : m_buffer) { @@ -253,6 +256,6 @@ QString RifEclipseOutputTableFormatter::formatColumn(const QString str, RifEclip } else { - return str.rightJustified(column.width + m_colSpacing, ' '); + return str.rightJustified(column.width, ' ').leftJustified(m_colSpacing, ' '); } } diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 0e8d012ed1..d2aeb22561 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -399,6 +399,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection() commandIds << "RicNewPerforationIntervalFeature"; commandIds << "RicEditPerforationCollectionFeature"; commandIds << "RicExportFishbonesLateralsFeature"; + commandIds << "RicWellPathExportCompletionDataFeature"; commandIds << "RicWellPathImportCompletionsFileFeature"; // Work in progress -- End From 0b872dbf3ac4b6a53e3b6df8bdf36394533242b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Tue, 16 May 2017 09:43:41 +0200 Subject: [PATCH 121/157] #1462 Add support for exporting WPIMULT --- ...RicWellPathExportCompletionDataFeature.cpp | 144 +++++++++++++----- .../RicWellPathExportCompletionDataFeature.h | 3 +- .../RifEclipseOutputTableFormatter.cpp | 3 + .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../RimExportCompletionDataSettings.cpp | 32 ++++ .../RimExportCompletionDataSettings.h | 38 +++++ 6 files changed, 179 insertions(+), 43 deletions(-) create mode 100644 ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.h diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index 4e6ed3d9ba..768818d63e 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -25,7 +25,7 @@ #include "RimProject.h" #include "RimWellPath.h" #include "RimFishbonesMultipleSubs.h" -#include "RimCaseAndFileExportSettings.h" +#include "RimExportCompletionDataSettings.h" #include "RiuMainWindow.h" @@ -78,7 +78,7 @@ void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked) QString projectFolder = app->currentProjectPath(); QString defaultDir = RiaApplication::instance()->lastUsedDialogDirectoryWithFallback("COMPLETIONS", projectFolder); - RimCaseAndFileExportSettings exportSettings; + RimExportCompletionDataSettings exportSettings; exportSettings.fileName = QDir(defaultDir).filePath("Completions"); @@ -91,7 +91,7 @@ void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked) { RiaApplication::instance()->setLastUsedDialogDirectory("COMPLETIONS", QFileInfo(exportSettings.fileName).absolutePath()); - exportToFolder(objects[0], exportSettings.fileName, exportSettings.caseToApply); + exportToFolder(objects[0], exportSettings.fileName, exportSettings.caseToApply, exportSettings.includeWpimult()); } } @@ -106,9 +106,15 @@ void RicWellPathExportCompletionDataFeature::setupActionLook(QAction* actionToSe //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply) +void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply, bool includeWpimult) { QFile exportFile(fileName); + + if (caseToApply == nullptr) + { + RiaLogging::error("Export Completions Data: Cannot export completions data without specified eclipse case"); + return; + } if (!exportFile.open(QIODevice::WriteOnly)) { @@ -120,55 +126,90 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat const RigEclipseCaseData* caseData = caseToApply->eclipseCaseData(); std::vector wellPathCells = findIntersectingCells(caseData, wellPath->wellPathGeometry()->m_wellPathPoints); + std::map lateralsPerCell; RifEclipseOutputTableFormatter formatter(stream); - std::vector header = { - RifEclipseOutputTableColumn{"Well", LEFT}, - RifEclipseOutputTableColumn{"I", LEFT}, - RifEclipseOutputTableColumn{"J", LEFT}, - RifEclipseOutputTableColumn{"K1", LEFT}, - RifEclipseOutputTableColumn{"K2", LEFT}, - RifEclipseOutputTableColumn{"Status", LEFT}, - RifEclipseOutputTableColumn{"SAT", LEFT}, - RifEclipseOutputTableColumn{"TR", LEFT}, - RifEclipseOutputTableColumn{"DIAM", LEFT}, - RifEclipseOutputTableColumn{"KH", LEFT}, - RifEclipseOutputTableColumn{"S", LEFT}, - RifEclipseOutputTableColumn{"Df", LEFT}, - RifEclipseOutputTableColumn{"DIR", LEFT}, - RifEclipseOutputTableColumn{"r0", LEFT} - }; - formatter.keyword("COMPDAT"); - formatter.header(header); - - for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesSubs) + // COMPDAT { - for (size_t subIndex = 0; subIndex < subs->locationOfSubs().size(); ++subIndex) + std::vector header = { + RifEclipseOutputTableColumn{"Well", LEFT}, + RifEclipseOutputTableColumn{"I", LEFT}, + RifEclipseOutputTableColumn{"J", LEFT}, + RifEclipseOutputTableColumn{"K1", LEFT}, + RifEclipseOutputTableColumn{"K2", LEFT}, + RifEclipseOutputTableColumn{"Status", LEFT}, + RifEclipseOutputTableColumn{"SAT", LEFT}, + RifEclipseOutputTableColumn{"TR", LEFT}, + RifEclipseOutputTableColumn{"DIAM", LEFT}, + RifEclipseOutputTableColumn{"KH", LEFT}, + RifEclipseOutputTableColumn{"S", LEFT}, + RifEclipseOutputTableColumn{"Df", LEFT}, + RifEclipseOutputTableColumn{"DIR", LEFT}, + RifEclipseOutputTableColumn{"r0", LEFT} + }; + + formatter.keyword("COMPDAT"); + formatter.header(header); + + for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesSubs) { - for (size_t lateralIndex = 0; lateralIndex < subs->lateralLengths().size(); ++lateralIndex) + for (size_t subIndex = 0; subIndex < subs->locationOfSubs().size(); ++subIndex) { - std::vector lateralCoords = subs->coordsForLateral(subIndex, lateralIndex); - - std::vector lateralCells = findIntersectingCells(caseData, lateralCoords); - - std::vector cellsUniqueToLateral = filterWellPathCells(lateralCells, wellPathCells); - - std::vector cellRanges = getCellIndexRange(caseData->mainGrid(), cellsUniqueToLateral); - - formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(subs->name()).arg(subIndex).arg(lateralIndex)); - for (auto cellRange : cellRanges) + for (size_t lateralIndex = 0; lateralIndex < subs->lateralLengths().size(); ++lateralIndex) { - // Add cell indices - formatter.add(wellPath->name()).addZeroBasedCellIndex(cellRange.i).addZeroBasedCellIndex(cellRange.j).addZeroBasedCellIndex(cellRange.k1).addZeroBasedCellIndex(cellRange.k2); - // Remaining data, to be computed - formatter.add("'OPEN'").add("1*").add("1*").add(0.0).add("1*").add("1*").add("1*").add("'Z'").add("1*"); - formatter.rowCompleted(); + std::vector lateralCoords = subs->coordsForLateral(subIndex, lateralIndex); + + std::vector lateralCells = findIntersectingCells(caseData, lateralCoords); + + if (includeWpimult) + { + // Only need this data if WPIMULT should be included in file + addLateralToCells(&lateralsPerCell, lateralCells); + } + + std::vector cellsUniqueToLateral = filterWellPathCells(lateralCells, wellPathCells); + + std::vector cellRanges = getCellIndexRange(caseData->mainGrid(), cellsUniqueToLateral); + + formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(subs->name()).arg(subIndex).arg(lateralIndex)); + for (auto cellRange : cellRanges) + { + // Add cell indices + formatter.add(wellPath->name()).addZeroBasedCellIndex(cellRange.i).addZeroBasedCellIndex(cellRange.j).addZeroBasedCellIndex(cellRange.k1).addZeroBasedCellIndex(cellRange.k2); + // Remaining data, to be computed + formatter.add("'OPEN'").add("1*").add("1*").add(0.0).add("1*").add("1*").add("1*").add("'Z'").add("1*"); + formatter.rowCompleted(); + } } } } + formatter.flush(); + } + + // WPIMULT + if (includeWpimult) + { + std::vector header = { + RifEclipseOutputTableColumn{"Well", LEFT}, + RifEclipseOutputTableColumn{"Mult", LEFT}, + RifEclipseOutputTableColumn{"I", LEFT}, + RifEclipseOutputTableColumn{"J", LEFT}, + RifEclipseOutputTableColumn{"K", LEFT}, + }; + formatter.keyword("WPIMULT"); + formatter.header(header); + + for (auto lateralsInCell : lateralsPerCell) + { + size_t i, j, k; + caseData->mainGrid()->ijkFromCellIndex(lateralsInCell.first, &i, &j, &k); + formatter.add(wellPath->name()).add(lateralsInCell.second).addZeroBasedCellIndex(i).addZeroBasedCellIndex(j).addZeroBasedCellIndex(k); + formatter.rowCompleted(); + } + + formatter.flush(); } - formatter.flush(); } //-------------------------------------------------------------------------------------------------- @@ -351,4 +392,23 @@ std::vector RicWellPathExportCompletionDataFeature::filterWellPathCells( return filteredCells; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::addLateralToCells(std::map* lateralsPerCell, const std::vector& lateralCells) +{ + for (size_t cell : lateralCells) + { + std::map::iterator it = lateralsPerCell->find(cell); + if (it == lateralsPerCell->end()) + { + (*lateralsPerCell)[cell] = 1; + } + else + { + (*lateralsPerCell)[cell] = it->second + 1; + } + } +} + } // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h index cba7d2507e..230304f8bf 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h @@ -57,13 +57,14 @@ protected: virtual void setupActionLook(QAction* actionToSetup) override; private: - static void exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply); + static void exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply, bool includeWpimult); static std::vector findCloseCells(const RigEclipseCaseData* caseData, const cvf::BoundingBox& bb); static std::vector getCellIndexRange(const RigMainGrid* grid, const std::vector& cellIndices); static bool cellOrdering(const EclipseCellIndex& cell1, const EclipseCellIndex& cell2); static std::vector findIntersectingCells(const RigEclipseCaseData* grid, const std::vector& coords); static void setHexCorners(const RigCell& cell, const std::vector& nodeCoords, cvf::Vec3d* hexCorners); static std::vector filterWellPathCells(const std::vector& completionCells, const std::vector& wellPathCells); + static void addLateralToCells(std::map* lateralsPerCell, const std::vector& lateralCells); }; diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp index c1fc5e076b..4168f948db 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp @@ -74,6 +74,9 @@ void RifEclipseOutputTableFormatter::outputBuffer() m_out << " /" << "\n"; } } + // If we finished a table, output an "empty" line after it + if (!m_columns.empty()) m_out << "/\n"; + m_columns.clear(); m_buffer.clear(); } diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index be2d6a1cd9..ba156e920a 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -8,6 +8,7 @@ set (SOURCE_GROUP_HEADER_FILES ${CEE_CURRENT_LIST_DIR}RimEclipseCaseCollection.h ${CEE_CURRENT_LIST_DIR}RimCaseCollection.h ${CEE_CURRENT_LIST_DIR}RimCaseAndFileExportSettings.h +${CEE_CURRENT_LIST_DIR}RimExportCompletionDataSettings.h ${CEE_CURRENT_LIST_DIR}RimCellFilter.h ${CEE_CURRENT_LIST_DIR}RimEclipsePropertyFilter.h ${CEE_CURRENT_LIST_DIR}RimPropertyFilterCollection.h @@ -101,6 +102,7 @@ set (SOURCE_GROUP_SOURCE_FILES ${CEE_CURRENT_LIST_DIR}RimEclipseCaseCollection.cpp ${CEE_CURRENT_LIST_DIR}RimCaseCollection.cpp ${CEE_CURRENT_LIST_DIR}RimCaseAndFileExportSettings.cpp +${CEE_CURRENT_LIST_DIR}RimExportCompletionDataSettings.cpp ${CEE_CURRENT_LIST_DIR}RimCellFilter.cpp ${CEE_CURRENT_LIST_DIR}RimEclipsePropertyFilter.cpp ${CEE_CURRENT_LIST_DIR}RimPropertyFilterCollection.cpp diff --git a/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp new file mode 100644 index 0000000000..656e0680bf --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp @@ -0,0 +1,32 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimExportCompletionDataSettings.h" + +CAF_PDM_SOURCE_INIT(RimExportCompletionDataSettings, "RimExportCompletionDataSettings"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimExportCompletionDataSettings::RimExportCompletionDataSettings() +{ + CAF_PDM_InitObject("RimExportCompletionDataSettings", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&includeWpimult, "IncludeWPIMULT", "Include WPIMLUT", "", "", ""); +} diff --git a/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.h b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.h new file mode 100644 index 0000000000..3728ab04e3 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.h @@ -0,0 +1,38 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017- Ceetron Solutions AS +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimCaseAndFileExportSettings.h" + +#include "cafPdmField.h" + +//================================================================================================== +/// +/// +//================================================================================================== +class RimExportCompletionDataSettings : public RimCaseAndFileExportSettings +{ + CAF_PDM_HEADER_INIT; +public: + + RimExportCompletionDataSettings(); + + caf::PdmField includeWpimult; +}; From d0ab85453466c7c893f0ccaeaa3cb69243adc015 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 16 May 2017 10:21:36 +0200 Subject: [PATCH 122/157] #1486 Add 'New Fishbone' to context menu when clicking on well path --- .../FishbonesCommands/CMakeLists_files.cmake | 2 + ...NewFishbonesSubsAtMeasuredDepthFeature.cpp | 94 ++++++++++++++++++ ...icNewFishbonesSubsAtMeasuredDepthFeature.h | 39 ++++++++ .../Fishbones/RimFishbonesMultipleSubs.cpp | 95 ++++++++++++++----- .../Fishbones/RimFishbonesMultipleSubs.h | 4 + 5 files changed, 209 insertions(+), 25 deletions(-) create mode 100644 ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp create mode 100644 ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.h diff --git a/ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake index 52f320aeda..5e0d83996b 100644 --- a/ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/FishbonesCommands/CMakeLists_files.cmake @@ -7,11 +7,13 @@ endif() set (SOURCE_GROUP_HEADER_FILES ${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsFeature.h ${CEE_CURRENT_LIST_DIR}RicExportFishbonesLateralsFeature.h +${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsAtMeasuredDepthFeature.h ) set (SOURCE_GROUP_SOURCE_FILES ${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsFeature.cpp ${CEE_CURRENT_LIST_DIR}RicExportFishbonesLateralsFeature.cpp +${CEE_CURRENT_LIST_DIR}RicNewFishbonesSubsAtMeasuredDepthFeature.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp new file mode 100644 index 0000000000..da59e806f9 --- /dev/null +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp @@ -0,0 +1,94 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicNewFishbonesSubsAtMeasuredDepthFeature.h" + +#include "RimFishbonesMultipleSubs.h" +#include "RimProject.h" +#include "RimWellPath.h" + +#include "RiuMainWindow.h" +#include "RiuSelectionManager.h" + +#include "cafSelectionManager.h" + +#include + + +CAF_CMD_SOURCE_INIT(RicNewFishbonesSubsAtMeasuredDepthFeature, "RicNewFishbonesSubsAtMeasuredDepthFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewFishbonesSubsAtMeasuredDepthFeature::onActionTriggered(bool isChecked) +{ + RiuWellPathSelectionItem* wellPathSelItem = wellPathSelectionItem(); + CVF_ASSERT(wellPathSelItem); + + RimWellPath* wellPath = wellPathSelItem->m_wellpath; + CVF_ASSERT(wellPath); + + RimFishbonesMultipleSubs* obj = new RimFishbonesMultipleSubs; + wellPath->fishbonesSubs.push_back(obj); + + obj->setName(QString("Fishbones Subs (%1)").arg(wellPath->fishbonesSubs.size())); + int integerValue = wellPathSelItem->m_measuredDepth; + obj->setMeasuredDepthAndCount(integerValue, 24, 5); + + wellPath->updateConnectedEditors(); + RiuMainWindow::instance()->selectAsCurrentItem(obj); + + RimProject* proj; + wellPath->firstAncestorOrThisOfTypeAsserted(proj); + proj->createDisplayModelAndRedrawAllViews(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuWellPathSelectionItem* RicNewFishbonesSubsAtMeasuredDepthFeature::wellPathSelectionItem() +{ + RiuSelectionManager* riuSelManager = RiuSelectionManager::instance(); + RiuSelectionItem* selItem = riuSelManager->selectedItem(RiuSelectionManager::RUI_TEMPORARY); + + RiuWellPathSelectionItem* wellPathItem = dynamic_cast(selItem); + + return wellPathItem; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewFishbonesSubsAtMeasuredDepthFeature::setupActionLook(QAction* actionToSetup) +{ + //actionToSetup->setIcon(QIcon(":/FractureSymbol16x16.png")); + actionToSetup->setText("New Fishbones Subs Definition"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewFishbonesSubsAtMeasuredDepthFeature::isCommandEnabled() +{ + if (wellPathSelectionItem()) + { + return true; + } + + return false; +} diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.h b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.h new file mode 100644 index 0000000000..42ffc4d909 --- /dev/null +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.h @@ -0,0 +1,39 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +class RiuWellPathSelectionItem; + +//================================================================================================== +/// +//================================================================================================== +class RicNewFishbonesSubsAtMeasuredDepthFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; +protected: + + virtual void onActionTriggered(bool isChecked) override; + virtual void setupActionLook(QAction* actionToSetup) override; + virtual bool isCommandEnabled() override; + +private: + static RiuWellPathSelectionItem* wellPathSelectionItem(); +}; diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp index 7270290b45..8ca23f6dc9 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp @@ -18,8 +18,10 @@ #include "RimFishbonesMultipleSubs.h" -#include "RimProject.h" #include "RigFishbonesGeometry.h" +#include "RigWellPath.h" +#include "RimProject.h" +#include "RimWellPath.h" #include "cafPdmUiListEditor.h" @@ -37,7 +39,7 @@ namespace caf { addItem(RimFishbonesMultipleSubs::FB_SUB_COUNT_END, "FB_SUB_COUNT", "Start/End/Number of Subs"); addItem(RimFishbonesMultipleSubs::FB_SUB_SPACING_END, "FB_SUB_SPACING", "Start/End/Spacing"); addItem(RimFishbonesMultipleSubs::FB_SUB_USER_DEFINED, "FB_SUB_CUSTOM", "User Specification"); - setDefault(RimFishbonesMultipleSubs::FB_SUB_USER_DEFINED); + setDefault(RimFishbonesMultipleSubs::FB_SUB_COUNT_END); } template<> @@ -79,7 +81,7 @@ RimFishbonesMultipleSubs::RimFishbonesMultipleSubs() CAF_PDM_InitFieldNoDefault(&m_locationOfSubs, "LocationOfSubs", "Measured Depths [m]", "", "", ""); m_locationOfSubs.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName()); - CAF_PDM_InitField(&m_subsLocationMode, "SubsLocationMode", caf::AppEnum(FB_SUB_USER_DEFINED), "Location Defined By", "", "", ""); + CAF_PDM_InitField(&m_subsLocationMode, "SubsLocationMode", caf::AppEnum(FB_SUB_COUNT_END), "Location Defined By", "", "", ""); CAF_PDM_InitField(&m_rangeStart, "RangeStart", 100.0, "Start MD [m]", "", "", ""); CAF_PDM_InitField(&m_rangeEnd, "RangeEnd", 250.0, "End MD [m]", "", "", ""); CAF_PDM_InitField(&m_rangeSubSpacing, "RangeSubSpacing", 40.0, "Spacing [m]", "", "", ""); @@ -102,6 +104,21 @@ RimFishbonesMultipleSubs::~RimFishbonesMultipleSubs() } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFishbonesMultipleSubs::setMeasuredDepthAndCount(double measuredDepth, double spacing, int subCount) +{ + m_subsLocationMode = FB_SUB_SPACING_END; + + m_rangeStart = measuredDepth; + m_rangeEnd = measuredDepth + spacing * subCount; + m_rangeSubCount = subCount; + + computeRangesAndLocations(); + computeRotationAngles(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -235,28 +252,7 @@ void RimFishbonesMultipleSubs::fieldChangedByUi(const caf::PdmFieldHandle* chang if (recomputeLocations) { - if (m_subsLocationMode == FB_SUB_COUNT_END) - { - size_t divisor = 1; - if (m_rangeSubCount > 2) divisor = m_rangeSubCount - 1; - - m_rangeSubSpacing = fabs(m_rangeStart - m_rangeEnd) / divisor; - } - else if (m_subsLocationMode == FB_SUB_SPACING_END) - { - m_rangeSubCount = (fabs(m_rangeStart - m_rangeEnd) / m_rangeSubSpacing) + 1; - - if (m_rangeSubCount < 1) - { - m_rangeSubCount = 1; - } - } - - if (m_subsLocationMode == FB_SUB_COUNT_END || m_subsLocationMode == FB_SUB_SPACING_END) - { - std::vector measuredDepths = locationsFromStartSpacingAndCount(m_rangeStart, m_rangeSubSpacing, m_rangeSubCount); - m_locationOfSubs = measuredDepths; - } + computeRangesAndLocations(); } if (recomputeLocations || @@ -271,6 +267,55 @@ void RimFishbonesMultipleSubs::fieldChangedByUi(const caf::PdmFieldHandle* chang proj->createDisplayModelAndRedrawAllViews(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFishbonesMultipleSubs::computeRangesAndLocations() +{ + if (m_subsLocationMode == FB_SUB_COUNT_END) + { + size_t divisor = 1; + if (m_rangeSubCount > 2) divisor = m_rangeSubCount - 1; + + m_rangeSubSpacing = fabs(m_rangeStart - m_rangeEnd) / divisor; + } + else if (m_subsLocationMode == FB_SUB_SPACING_END) + { + m_rangeSubCount = (fabs(m_rangeStart - m_rangeEnd) / m_rangeSubSpacing) + 1; + + if (m_rangeSubCount < 1) + { + m_rangeSubCount = 1; + } + } + + if (m_subsLocationMode == FB_SUB_COUNT_END || m_subsLocationMode == FB_SUB_SPACING_END) + { + std::vector validMeasuredDepths; + { + RimWellPath* wellPath = nullptr; + this->firstAncestorOrThisOfTypeAsserted(wellPath); + + RigWellPath* rigWellPathGeo = wellPath->wellPathGeometry(); + if (rigWellPathGeo && rigWellPathGeo->m_measuredDepths.size() > 1) + { + double firstWellPathMD = rigWellPathGeo->m_measuredDepths.front(); + double lastWellPathMD = rigWellPathGeo->m_measuredDepths.back(); + + for (auto md : locationsFromStartSpacingAndCount(m_rangeStart, m_rangeSubSpacing, m_rangeSubCount)) + { + if (md > firstWellPathMD && md < lastWellPathMD) + { + validMeasuredDepths.push_back(md); + } + } + } + } + + m_locationOfSubs = validMeasuredDepths; + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h index 250ad35a63..c57737469e 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -54,6 +54,8 @@ public: RimFishbonesMultipleSubs(); virtual ~RimFishbonesMultipleSubs(); + void setMeasuredDepthAndCount(double measuredDepth, double spacing, int subCount); + std::vector locationOfSubs() const; double rotationAngle(size_t index) const; @@ -69,10 +71,12 @@ public: protected: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; virtual void initAfterRead() override; private: + void computeRangesAndLocations(); void computeRotationAngles(); static std::vector locationsFromStartSpacingAndCount(double start, double spacing, size_t count); From f81ef5b2fef1a19eae29dea1d82e30f94afaf7dd Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 16 May 2017 10:22:10 +0200 Subject: [PATCH 123/157] #1486 Use RiuWellPathSelectionItem to communicate data to feature --- ApplicationCode/UserInterface/RiuViewerCommands.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ApplicationCode/UserInterface/RiuViewerCommands.cpp b/ApplicationCode/UserInterface/RiuViewerCommands.cpp index ce48b92831..97fff149ba 100644 --- a/ApplicationCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationCode/UserInterface/RiuViewerCommands.cpp @@ -293,12 +293,18 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event) RimWellPath* wellPath = wellPathSourceInfo->wellPath(); if (wellPath) { + double measuredDepth = wellPathSourceInfo->measuredDepth(firstPartTriangleIndex, m_currentPickPositionInDomainCoords); + cvf::Vec3d trueVerticalDepth = wellPathSourceInfo->trueVerticalDepth(firstPartTriangleIndex, globalIntersectionPoint); + RiuSelectionItem* selItem = new RiuWellPathSelectionItem(wellPathSourceInfo, trueVerticalDepth, measuredDepth); + RiuSelectionManager::instance()->setSelectedItem(selItem, RiuSelectionManager::RUI_TEMPORARY); + caf::SelectionManager::instance()->setSelectedItem(wellPath); commandIds << "RicNewWellLogCurveExtractionFeature"; commandIds << "RicNewWellLogFileCurveFeature"; commandIds << "Separator"; commandIds << "RicNewWellPathIntersectionFeature"; + commandIds << "RicNewFishbonesSubsAtMeasuredDepthFeature"; } } From 43e50bd8d2bb864edd12dadad4a4f5d8f734d418 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 16 May 2017 12:49:36 +0200 Subject: [PATCH 124/157] Updated copyright headers --- .../FishbonesCommands/RicExportFishbonesLateralsFeature.cpp | 2 +- .../FishbonesCommands/RicExportFishbonesLateralsFeature.h | 2 +- .../RicNewFishbonesSubsAtMeasuredDepthFeature.cpp | 2 +- .../RicNewFishbonesSubsAtMeasuredDepthFeature.h | 2 +- .../Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp | 2 +- .../Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h | 2 +- .../FileInterface/RifEclipseOutputTableFormatter.cpp | 3 +-- ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h | 3 +-- ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp | 2 +- ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h | 2 +- .../ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp | 2 +- .../ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h | 2 +- .../ProjectDataModel/RimCaseAndFileExportSettings.cpp | 1 - ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp | 2 +- ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.h | 2 +- 15 files changed, 14 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp index 569489f4a2..7b42466127 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h index d0ad4caa46..8715f4cfdc 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp index da59e806f9..a312a0d80b 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.h b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.h index 42ffc4d909..dc58ed094b 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.h +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp index e8ec34a36d..6a70137236 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h index fc47d45cfc..b0aff04b67 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017- Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp index 4168f948db..dce671233e 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017- Statoil ASA -// Copyright (C) 2017- Ceetron Solutions AS +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h index 7d8dd6e8e9..d387f88190 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017- Statoil ASA -// Copyright (C) 2017- Ceetron Solutions AS +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp index 9cea3c5bca..30a7ebab8f 100644 --- a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h index 9481ba5e1e..a5d16a53fc 100644 --- a/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivFishbonesSubsPartMgr.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp index 8ca23f6dc9..413d0a7632 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h index c57737469e..182df38faa 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.cpp b/ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.cpp index c6a41657c5..e67f947fe9 100644 --- a/ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimCaseAndFileExportSettings.cpp @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017- Statoil ASA -// Copyright (C) 2017- Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp index 968cb4b6e0..0801838dfb 100644 --- a/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.h b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.h index 7a32137be9..1cdd5653fa 100644 --- a/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.h +++ b/ApplicationCode/ReservoirDataModel/RigFishbonesGeometry.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2017 Statoil ASA +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by From 7b4b13906f362f457fa75e8e28ff05db79018e97 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 16 May 2017 13:35:05 +0200 Subject: [PATCH 125/157] Remove obsolete include --- .../WellPathCommands/RicWellPathExportCompletionDataFeature.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h index 230304f8bf..668e26db6f 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h @@ -19,7 +19,6 @@ #pragma once -#include "RigWellLogExtractionTools.h" #include "cafCmdFeature.h" From 69116784ff342ba72e74945997b9f2ef07b28e3e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 16 May 2017 13:36:14 +0200 Subject: [PATCH 126/157] Refactoring to be able to compile on Linux --- ...RicWellPathExportCompletionDataFeature.cpp | 31 +++++++++---------- .../RifEclipseOutputTableFormatter.cpp | 2 ++ .../RifEclipseOutputTableFormatter.h | 13 +++++--- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index 768818d63e..c70d278d8a 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -132,22 +132,21 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat // COMPDAT { - std::vector header = { - RifEclipseOutputTableColumn{"Well", LEFT}, - RifEclipseOutputTableColumn{"I", LEFT}, - RifEclipseOutputTableColumn{"J", LEFT}, - RifEclipseOutputTableColumn{"K1", LEFT}, - RifEclipseOutputTableColumn{"K2", LEFT}, - RifEclipseOutputTableColumn{"Status", LEFT}, - RifEclipseOutputTableColumn{"SAT", LEFT}, - RifEclipseOutputTableColumn{"TR", LEFT}, - RifEclipseOutputTableColumn{"DIAM", LEFT}, - RifEclipseOutputTableColumn{"KH", LEFT}, - RifEclipseOutputTableColumn{"S", LEFT}, - RifEclipseOutputTableColumn{"Df", LEFT}, - RifEclipseOutputTableColumn{"DIR", LEFT}, - RifEclipseOutputTableColumn{"r0", LEFT} - }; + std::vector header; + header.push_back(RifEclipseOutputTableColumn("Well", LEFT)); + header.push_back(RifEclipseOutputTableColumn("I", LEFT)); + header.push_back(RifEclipseOutputTableColumn("J", LEFT)); + header.push_back(RifEclipseOutputTableColumn("K1", LEFT)); + header.push_back(RifEclipseOutputTableColumn("K2", LEFT)); + header.push_back(RifEclipseOutputTableColumn("Status", LEFT)); + header.push_back(RifEclipseOutputTableColumn("SAT", LEFT)); + header.push_back(RifEclipseOutputTableColumn("TR", LEFT)); + header.push_back(RifEclipseOutputTableColumn("DIAM", LEFT)); + header.push_back(RifEclipseOutputTableColumn("KH", LEFT)); + header.push_back(RifEclipseOutputTableColumn("S", LEFT)); + header.push_back(RifEclipseOutputTableColumn("Df", LEFT)); + header.push_back(RifEclipseOutputTableColumn("DIR", LEFT)); + header.push_back(RifEclipseOutputTableColumn("r0", LEFT)); formatter.keyword("COMPDAT"); formatter.header(header); diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp index dce671233e..d7ed079af4 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp @@ -18,6 +18,8 @@ #include "RifEclipseOutputTableFormatter.h" +#include "cvfAssert.h" + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h index d387f88190..217e10a58e 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h @@ -18,8 +18,6 @@ #pragma once -#include "cvfObject.h" - #include #include @@ -57,16 +55,23 @@ struct RifEclipseOutputTableLine //================================================================================================== struct RifEclipseOutputTableColumn { + RifEclipseOutputTableColumn(const QString& title, RifEclipseOutputTableAlignment alignment) + : title(title), + alignment(alignment), + width(-1) + { + } + QString title; RifEclipseOutputTableAlignment alignment; - int width = -1; + int width; }; //================================================================================================== // //================================================================================================== -class RifEclipseOutputTableFormatter : public cvf::Object +class RifEclipseOutputTableFormatter { public: RifEclipseOutputTableFormatter(QTextStream& out); From c6202bb14e1c8526ba9b435c80de5e9d0848e644 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 16 May 2017 13:51:10 +0200 Subject: [PATCH 127/157] Use brace-init of vector --- ...RicWellPathExportCompletionDataFeature.cpp | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index c70d278d8a..e5cbfabf14 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -132,21 +132,22 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat // COMPDAT { - std::vector header; - header.push_back(RifEclipseOutputTableColumn("Well", LEFT)); - header.push_back(RifEclipseOutputTableColumn("I", LEFT)); - header.push_back(RifEclipseOutputTableColumn("J", LEFT)); - header.push_back(RifEclipseOutputTableColumn("K1", LEFT)); - header.push_back(RifEclipseOutputTableColumn("K2", LEFT)); - header.push_back(RifEclipseOutputTableColumn("Status", LEFT)); - header.push_back(RifEclipseOutputTableColumn("SAT", LEFT)); - header.push_back(RifEclipseOutputTableColumn("TR", LEFT)); - header.push_back(RifEclipseOutputTableColumn("DIAM", LEFT)); - header.push_back(RifEclipseOutputTableColumn("KH", LEFT)); - header.push_back(RifEclipseOutputTableColumn("S", LEFT)); - header.push_back(RifEclipseOutputTableColumn("Df", LEFT)); - header.push_back(RifEclipseOutputTableColumn("DIR", LEFT)); - header.push_back(RifEclipseOutputTableColumn("r0", LEFT)); + std::vector header = { + RifEclipseOutputTableColumn{"Well", LEFT}, + RifEclipseOutputTableColumn{"I", LEFT}, + RifEclipseOutputTableColumn{"J", LEFT}, + RifEclipseOutputTableColumn{"K1", LEFT}, + RifEclipseOutputTableColumn{"K2", LEFT}, + RifEclipseOutputTableColumn{"Status", LEFT}, + RifEclipseOutputTableColumn{"SAT", LEFT}, + RifEclipseOutputTableColumn{"TR", LEFT}, + RifEclipseOutputTableColumn{"DIAM", LEFT}, + RifEclipseOutputTableColumn{"KH", LEFT}, + RifEclipseOutputTableColumn{"S", LEFT}, + RifEclipseOutputTableColumn{"Df", LEFT}, + RifEclipseOutputTableColumn{"DIR", LEFT}, + RifEclipseOutputTableColumn{"r0", LEFT} + }; formatter.keyword("COMPDAT"); formatter.header(header); From e83759a3a464ee82d5fe85d6b0522374837c4e01 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 08:01:03 +0200 Subject: [PATCH 128/157] #1496 Fishbones : Collapse groups MSW and Success factors by default --- .../ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp index 413d0a7632..0d489fa92a 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp @@ -371,6 +371,8 @@ void RimFishbonesMultipleSubs::defineUiOrdering(QString uiConfigName, caf::PdmUi { caf::PdmUiGroup* successGroup = lateralConfigGroup->addNewGroup("Installation Success Fractions"); + successGroup->setCollapsedByDefault(true); + successGroup->add(&m_lateralLengthFraction); successGroup->add(&m_lateralInstallFraction); } From f6946e7130e6a2b5155cb2e52b15769a39e95325 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 08:19:53 +0200 Subject: [PATCH 129/157] #1504 Fishbones : Use start and end MD as perforation name --- .../ProjectDataModel/RimPerforationInterval.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp b/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp index 121213575f..16093557f2 100644 --- a/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp +++ b/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp @@ -32,13 +32,14 @@ CAF_PDM_SOURCE_INIT(RimPerforationInterval, "Perforation"); RimPerforationInterval::RimPerforationInterval() { CAF_PDM_InitObject("Perforation", ":/Default.png", "", ""); - m_name = "Perforation"; + CAF_PDM_InitField(&m_startMD, "StartMeasuredDepth", 0.0, "Start MD [m]", "", "", ""); CAF_PDM_InitField(&m_endMD, "EndMeasuredDepth", 0.0, "End MD [m]", "", "", ""); CAF_PDM_InitField(&m_radius, "Radius", 0.0, "Radius [m]", "", "", ""); CAF_PDM_InitField(&m_skinFactor, "SkinFactor", 0.0, "Skin Factor", "", "", ""); -} + m_name.uiCapability()->setUiReadOnly(true); +} //-------------------------------------------------------------------------------------------------- /// @@ -53,8 +54,8 @@ RimPerforationInterval::~RimPerforationInterval() void RimPerforationInterval::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { RimProject* proj; - this->firstAncestorOrThisOfType(proj); - if (proj) proj->createDisplayModelAndRedrawAllViews(); + this->firstAncestorOrThisOfTypeAsserted(proj); + proj->createDisplayModelAndRedrawAllViews(); } //-------------------------------------------------------------------------------------------------- @@ -62,6 +63,7 @@ void RimPerforationInterval::fieldChangedByUi(const caf::PdmFieldHandle* changed //-------------------------------------------------------------------------------------------------- void RimPerforationInterval::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { + m_name = QString("%1 - %2").arg(m_startMD).arg(m_endMD); uiOrdering.add(&m_name); uiOrdering.add(&m_startMD); From ac6d9b9d55e17d14784fae8f96eb415c5f467a03 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 08:38:55 +0200 Subject: [PATCH 130/157] #1494 Fishbones : When creating new fishbone, create only one sub --- .../RicNewFishbonesSubsAtMeasuredDepthFeature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp index a312a0d80b..fa10044935 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp @@ -48,7 +48,7 @@ void RicNewFishbonesSubsAtMeasuredDepthFeature::onActionTriggered(bool isChecked obj->setName(QString("Fishbones Subs (%1)").arg(wellPath->fishbonesSubs.size())); int integerValue = wellPathSelItem->m_measuredDepth; - obj->setMeasuredDepthAndCount(integerValue, 24, 5); + obj->setMeasuredDepthAndCount(integerValue, 24, 1); wellPath->updateConnectedEditors(); RiuMainWindow::instance()->selectAsCurrentItem(obj); From 8dd0df79016b375c11edeef090212e030c7665cc Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 09:13:22 +0200 Subject: [PATCH 131/157] #1501 Fishbones : Increase number of coordinate digits when exporting laterals --- .../RicExportFishbonesLateralsFeature.cpp | 15 ++++++++++++++- .../RicExportFishbonesLateralsFeature.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp index 7b42466127..458dc70047 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp @@ -96,8 +96,13 @@ void RicExportFishbonesLateralsFeature::onActionTriggered(bool isChecked) for (auto coordMD : coordsAndMD) { + int numberOfDecimals = 2; + // Export X and Y unchanged, invert sign of Z to get TVD, export MD unchanged - stream << coordMD.first.x() << " " << coordMD.first.y() << " " << -coordMD.first.z() << " " << coordMD.second << endl; + stream << formatNumber( coordMD.first.x(), numberOfDecimals); + stream << " " << formatNumber( coordMD.first.y(), numberOfDecimals); + stream << " " << formatNumber(-coordMD.first.z(), numberOfDecimals); + stream << " " << formatNumber( coordMD.second, numberOfDecimals) << endl; } stream << -999 << endl << endl; } @@ -107,6 +112,14 @@ void RicExportFishbonesLateralsFeature::onActionTriggered(bool isChecked) RiaLogging::info("Completed export of Fishbones well path laterals to : " + completeFilename); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RicExportFishbonesLateralsFeature::formatNumber(double val, int numberOfDecimals) +{ + return QString("%1").arg(val, 0, 'f', numberOfDecimals); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h index 8715f4cfdc..1fa1472b84 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h @@ -35,5 +35,6 @@ protected: virtual bool isCommandEnabled() override; private: + static QString formatNumber(double val, int numberOfDecimals); static RimWellPath* selectedWellPath(); }; From 2b8b703258766251bf25406320c4bf7c2c33381f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 09:51:19 +0200 Subject: [PATCH 132/157] #1500 Fishbones : Use global index to subs when exporting lateral geometry --- .../FishbonesCommands/RicExportFishbonesLateralsFeature.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp index 458dc70047..40191c862e 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp @@ -74,6 +74,8 @@ void RicExportFishbonesLateralsFeature::onActionTriggered(bool isChecked) // x y TVD MD // separate laterals using -999 on a single line + size_t fishboneSubIndex = 0; + QTextStream stream(&exportFile); for (RimFishbonesMultipleSubs* fishbone : wellPath->fishbonesSubs()) { @@ -86,9 +88,9 @@ void RicExportFishbonesLateralsFeature::onActionTriggered(bool isChecked) std::vector> coordsAndMD = fishbone->coordsAndMDForLateral(subIndex, lateralIndex); // Pad with "0" to get a total of two characters defining the sub index text - QString subIndexText = QString("%1").arg(subIndex, 2, 10, QChar('0')); + QString subIndexText = QString("%1").arg(fishboneSubIndex++, 2, 10, QChar('0')); - QString lateralNameCandidate = QString("%1__%2_%3_%4").arg(wellPath->name()).arg(fishbone->name()).arg(subIndexText).arg(lateralIndex); + QString lateralNameCandidate = QString("%1_%2_%3_%4").arg(wellPath->name()).arg("fishbone").arg(subIndexText).arg(lateralIndex); QString lateralName = caf::Utils::makeValidFileBasename(lateralNameCandidate); From b5f6185deaa652f946b4d59a9c9f2a0feab689d2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 10:14:51 +0200 Subject: [PATCH 133/157] #1504 Fishbones : Hide name from property editor --- .../Fishbones/RimFishbonesMultipleSubs.h | 1 + .../ProjectDataModel/RimPerforationInterval.cpp | 11 +++++++++-- .../ProjectDataModel/RimPerforationInterval.h | 8 ++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h index 182df38faa..a99e9b137d 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -73,6 +73,7 @@ protected: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; + virtual void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override; virtual void initAfterRead() override; private: diff --git a/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp b/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp index 16093557f2..8aca567485 100644 --- a/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp +++ b/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp @@ -61,14 +61,21 @@ void RimPerforationInterval::fieldChangedByUi(const caf::PdmFieldHandle* changed //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimPerforationInterval::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +void RimPerforationInterval::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/) { m_name = QString("%1 - %2").arg(m_startMD).arg(m_endMD); - uiOrdering.add(&m_name); +} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPerforationInterval::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ uiOrdering.add(&m_startMD); uiOrdering.add(&m_endMD); uiOrdering.add(&m_radius); uiOrdering.add(&m_skinFactor); + + uiOrdering.skipRemainingFields(); } diff --git a/ApplicationCode/ProjectDataModel/RimPerforationInterval.h b/ApplicationCode/ProjectDataModel/RimPerforationInterval.h index 159c847556..298c4bd9ce 100644 --- a/ApplicationCode/ProjectDataModel/RimPerforationInterval.h +++ b/ApplicationCode/ProjectDataModel/RimPerforationInterval.h @@ -36,15 +36,19 @@ public: RimPerforationInterval(); virtual ~RimPerforationInterval(); - virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; - virtual void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; double startMD() { return m_startMD(); } double endMD() { return m_endMD(); } +protected: + virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + virtual void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + virtual void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override; + private: caf::PdmField< double > m_startMD; caf::PdmField< double > m_endMD; caf::PdmField< double > m_radius; caf::PdmField< double > m_skinFactor; + }; From e67979bd23eb8557c03a32acf056335351ca5ba3 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 10:36:25 +0200 Subject: [PATCH 134/157] #1499 Use naming based on index "Fishbones 1" --- .../Fishbones/RimFishbonesMultipleSubs.cpp | 16 ++++++++++++++-- .../Fishbones/RimFishbonesMultipleSubs.h | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp index 0d489fa92a..238d2a6dd9 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp @@ -93,6 +93,8 @@ RimFishbonesMultipleSubs::RimFishbonesMultipleSubs() m_installationRotationAngles.uiCapability()->setUiHidden(true); CAF_PDM_InitField(&m_fixedInstallationRotationAngle, "FixedInstallationRotationAngle", 0.0, " Fixed Angle [deg]", "", "", ""); + m_name.uiCapability()->setUiReadOnly(true); + m_rigFishbonesGeometry = std::unique_ptr(new RigFisbonesGeometry(this)); } @@ -321,8 +323,6 @@ void RimFishbonesMultipleSubs::computeRangesAndLocations() //-------------------------------------------------------------------------------------------------- void RimFishbonesMultipleSubs::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { - uiOrdering.add(&m_name); // From RimNamedObject - { caf::PdmUiGroup* group = uiOrdering.addNewGroup("Location"); @@ -434,6 +434,18 @@ void RimFishbonesMultipleSubs::initAfterRead() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFishbonesMultipleSubs::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/) +{ + caf::PdmChildArrayField* container = dynamic_cast*>(this->parentField()); + CVF_ASSERT(container); + + size_t index = container->index(this); + m_name = QString("Fishbone %1").arg(index); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h index a99e9b137d..fef7765f4e 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -72,8 +72,8 @@ public: protected: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; - virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; virtual void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override; + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; virtual void initAfterRead() override; private: From 829df457ffee403efcee67250c402601bb5db0aa Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 11:03:22 +0200 Subject: [PATCH 135/157] #1502 Fishbones : Add "New Perforation" to context menu when clicking on well path --- .../CMakeLists_files.cmake | 2 + ...forationIntervalAtMeasuredDepthFeature.cpp | 97 +++++++++++++++++++ ...erforationIntervalAtMeasuredDepthFeature.h | 39 ++++++++ .../RimPerforationInterval.cpp | 9 ++ .../ProjectDataModel/RimPerforationInterval.h | 3 +- .../UserInterface/RiuViewerCommands.cpp | 1 + 6 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.cpp create mode 100644 ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.h diff --git a/ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake index ee9864e76f..8f272175c2 100644 --- a/ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/PerforationCommands/CMakeLists_files.cmake @@ -7,11 +7,13 @@ endif() set (SOURCE_GROUP_HEADER_FILES ${CEE_CURRENT_LIST_DIR}RicEditPerforationCollectionFeature.h ${CEE_CURRENT_LIST_DIR}RicNewPerforationIntervalFeature.h +${CEE_CURRENT_LIST_DIR}RicNewPerforationIntervalAtMeasuredDepthFeature.h ) set (SOURCE_GROUP_SOURCE_FILES ${CEE_CURRENT_LIST_DIR}RicEditPerforationCollectionFeature.cpp ${CEE_CURRENT_LIST_DIR}RicNewPerforationIntervalFeature.cpp +${CEE_CURRENT_LIST_DIR}RicNewPerforationIntervalAtMeasuredDepthFeature.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.cpp b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.cpp new file mode 100644 index 0000000000..53b9440750 --- /dev/null +++ b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.cpp @@ -0,0 +1,97 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicNewPerforationIntervalAtMeasuredDepthFeature.h" + +#include "RimFishbonesMultipleSubs.h" +#include "RimPerforationCollection.h" +#include "RimPerforationInterval.h" +#include "RimProject.h" +#include "RimWellPath.h" +#include "RimWellPathCollection.h" + +#include "RiuMainWindow.h" +#include "RiuSelectionManager.h" + +#include "cafSelectionManager.h" + +#include + + +CAF_CMD_SOURCE_INIT(RicNewPerforationIntervalAtMeasuredDepthFeature, "RicNewPerforationIntervalAtMeasuredDepthFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewPerforationIntervalAtMeasuredDepthFeature::onActionTriggered(bool isChecked) +{ + RiuWellPathSelectionItem* wellPathSelItem = wellPathSelectionItem(); + CVF_ASSERT(wellPathSelItem); + + RimWellPath* wellPath = wellPathSelItem->m_wellpath; + CVF_ASSERT(wellPath); + + RimPerforationInterval* perforationInterval = new RimPerforationInterval; + int measuredDepth = wellPathSelItem->m_measuredDepth; + perforationInterval->setStartAndEndMD(measuredDepth, measuredDepth + 50); + + wellPath->m_perforationCollection()->appendPerforation(perforationInterval); + + RimWellPathCollection* wellPathCollection = nullptr; + wellPath->firstAncestorOrThisOfTypeAsserted(wellPathCollection); + + wellPathCollection->uiCapability()->updateConnectedEditors(); + wellPathCollection->scheduleGeometryRegenAndRedrawViews(); + + RiuMainWindow::instance()->selectAsCurrentItem(perforationInterval); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuWellPathSelectionItem* RicNewPerforationIntervalAtMeasuredDepthFeature::wellPathSelectionItem() +{ + RiuSelectionManager* riuSelManager = RiuSelectionManager::instance(); + RiuSelectionItem* selItem = riuSelManager->selectedItem(RiuSelectionManager::RUI_TEMPORARY); + + RiuWellPathSelectionItem* wellPathItem = dynamic_cast(selItem); + + return wellPathItem; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewPerforationIntervalAtMeasuredDepthFeature::setupActionLook(QAction* actionToSetup) +{ + //actionToSetup->setIcon(QIcon(":/FractureSymbol16x16.png")); + actionToSetup->setText("New Perforation Interval"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewPerforationIntervalAtMeasuredDepthFeature::isCommandEnabled() +{ + if (wellPathSelectionItem()) + { + return true; + } + + return false; +} diff --git a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.h b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.h new file mode 100644 index 0000000000..ae77586bf5 --- /dev/null +++ b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.h @@ -0,0 +1,39 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +class RiuWellPathSelectionItem; + +//================================================================================================== +/// +//================================================================================================== +class RicNewPerforationIntervalAtMeasuredDepthFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + virtual void onActionTriggered(bool isChecked) override; + virtual void setupActionLook(QAction* actionToSetup) override; + virtual bool isCommandEnabled() override; + +private: + static RiuWellPathSelectionItem* wellPathSelectionItem(); +}; diff --git a/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp b/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp index 8aca567485..1e4c9ead04 100644 --- a/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp +++ b/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp @@ -48,6 +48,15 @@ RimPerforationInterval::~RimPerforationInterval() { } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPerforationInterval::setStartAndEndMD(double startMD, double endMD) +{ + m_startMD = startMD; + m_endMD = endMD; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimPerforationInterval.h b/ApplicationCode/ProjectDataModel/RimPerforationInterval.h index 298c4bd9ce..23b07fa08b 100644 --- a/ApplicationCode/ProjectDataModel/RimPerforationInterval.h +++ b/ApplicationCode/ProjectDataModel/RimPerforationInterval.h @@ -36,7 +36,7 @@ public: RimPerforationInterval(); virtual ~RimPerforationInterval(); - + void setStartAndEndMD(double startMD, double endMD); double startMD() { return m_startMD(); } double endMD() { return m_endMD(); } @@ -50,5 +50,4 @@ private: caf::PdmField< double > m_endMD; caf::PdmField< double > m_radius; caf::PdmField< double > m_skinFactor; - }; diff --git a/ApplicationCode/UserInterface/RiuViewerCommands.cpp b/ApplicationCode/UserInterface/RiuViewerCommands.cpp index 97fff149ba..b75b865a2b 100644 --- a/ApplicationCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationCode/UserInterface/RiuViewerCommands.cpp @@ -305,6 +305,7 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event) commandIds << "Separator"; commandIds << "RicNewWellPathIntersectionFeature"; commandIds << "RicNewFishbonesSubsAtMeasuredDepthFeature"; + commandIds << "RicNewPerforationIntervalAtMeasuredDepthFeature"; } } From f4223435f6d13efda1d7323dcbc1b510e6aa78fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Tue, 16 May 2017 14:50:54 +0200 Subject: [PATCH 136/157] Clean up export completion data feature --- ...RicWellPathExportCompletionDataFeature.cpp | 38 +++++++++---------- .../RicWellPathExportCompletionDataFeature.h | 12 +----- .../Fishbones/RimFishbonesMultipleSubs.h | 1 + 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index e5cbfabf14..c19a87db40 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -43,9 +42,7 @@ #include #include -namespace caf -{ - CAF_CMD_SOURCE_INIT(RicWellPathExportCompletionDataFeature, "RicWellPathExportCompletionDataFeature"); +CAF_CMD_SOURCE_INIT(RicWellPathExportCompletionDataFeature, "RicWellPathExportCompletionDataFeature"); //-------------------------------------------------------------------------------------------------- @@ -178,7 +175,10 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat // Add cell indices formatter.add(wellPath->name()).addZeroBasedCellIndex(cellRange.i).addZeroBasedCellIndex(cellRange.j).addZeroBasedCellIndex(cellRange.k1).addZeroBasedCellIndex(cellRange.k2); // Remaining data, to be computed - formatter.add("'OPEN'").add("1*").add("1*").add(0.0).add("1*").add("1*").add("1*").add("'Z'").add("1*"); + formatter.add("'OPEN'").add("1*").add("1*"); + // Diameter (originally in mm) in m + formatter.add(subs->holeRadius() / 1000); + formatter.add("1*").add("1*").add("1*").add("'Z'").add("1*"); formatter.rowCompleted(); } } @@ -236,12 +236,6 @@ std::vector RicWellPathExportCompletionDataFeature::getCe eclipseCellIndices.push_back(std::make_tuple(i, j, k)); } - // Remove any duplicate cells - { - std::set uniqueCellIndices(eclipseCellIndices.begin(), eclipseCellIndices.end()); - eclipseCellIndices.assign(uniqueCellIndices.begin(), uniqueCellIndices.end()); - } - // Group cell indices in K-ranges std::sort(eclipseCellIndices.begin(), eclipseCellIndices.end(), RicWellPathExportCompletionDataFeature::cellOrdering); std::vector eclipseCellRanges; @@ -309,8 +303,8 @@ bool RicWellPathExportCompletionDataFeature::cellOrdering(const EclipseCellIndex //-------------------------------------------------------------------------------------------------- std::vector RicWellPathExportCompletionDataFeature::findIntersectingCells(const RigEclipseCaseData* caseData, const std::vector& coords) { - const std::vector& nodeCoords = caseData->mainGrid()->nodes(); - std::vector cells; + const std::vector& nodeCoords = caseData->mainGrid()->nodes(); + std::set cells; // Find starting cell if (coords.size() > 0) @@ -329,7 +323,7 @@ std::vector RicWellPathExportCompletionDataFeature::findIntersectingCell if (RigHexIntersector::isPointInCell(coords[0], hexCorners, closeCell)) { - cells.push_back(closeCell); + cells.insert(closeCell); break; } } @@ -358,11 +352,15 @@ std::vector RicWellPathExportCompletionDataFeature::findIntersectingCell for (auto intersection : intersections) { - cells.push_back(intersection.m_hexIndex); + cells.insert(intersection.m_hexIndex); } } - std::sort(cells.begin(), cells.end()); - return cells; + // Ensure only unique cells are included + std::vector cellsVector; + cellsVector.assign(cells.begin(), cells.end()); + // Sort cells + std::sort(cellsVector.begin(), cellsVector.end()); + return cellsVector; } //-------------------------------------------------------------------------------------------------- @@ -383,7 +381,7 @@ void RicWellPathExportCompletionDataFeature::setHexCorners(const RigCell& cell, } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- std::vector RicWellPathExportCompletionDataFeature::filterWellPathCells(const std::vector& completionCells, const std::vector& wellPathCells) { @@ -410,5 +408,3 @@ void RicWellPathExportCompletionDataFeature::addLateralToCells(std::map EclipseCellIndex; //================================================================================================== /// //================================================================================================== -class RicWellPathExportCompletionDataFeature : public CmdFeature +class RicWellPathExportCompletionDataFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: @@ -65,7 +61,3 @@ private: static std::vector filterWellPathCells(const std::vector& completionCells, const std::vector& wellPathCells); static void addLateralToCells(std::map* lateralsPerCell, const std::vector& lateralCells); }; - - - -} // end namespace caf diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h index fef7765f4e..74797de1d4 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -63,6 +63,7 @@ public: double buildAngle() const; double tubingRadius() const; + double holeRadius() const { return m_lateralHoleRadius(); } double lateralCountPerSub() const; std::vector lateralLengths() const; From f280835f9e124fb252b865a3e893bcff01e1f1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Tue, 16 May 2017 15:17:19 +0200 Subject: [PATCH 137/157] #1462 Add checkbox to decide whether laterals in cells with the main well path are exported --- ...RicWellPathExportCompletionDataFeature.cpp | 21 +++++++++++++------ .../RicWellPathExportCompletionDataFeature.h | 2 +- .../RimExportCompletionDataSettings.cpp | 2 +- .../RimExportCompletionDataSettings.h | 2 +- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index c19a87db40..ea35fecfb3 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -88,7 +88,7 @@ void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked) { RiaApplication::instance()->setLastUsedDialogDirectory("COMPLETIONS", QFileInfo(exportSettings.fileName).absolutePath()); - exportToFolder(objects[0], exportSettings.fileName, exportSettings.caseToApply, exportSettings.includeWpimult()); + exportToFolder(objects[0], exportSettings.fileName, exportSettings.caseToApply, exportSettings.includeWpimult(), exportSettings.removeLateralsInMainBoreCells()); } } @@ -103,7 +103,7 @@ void RicWellPathExportCompletionDataFeature::setupActionLook(QAction* actionToSe //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply, bool includeWpimult) +void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply, bool includeWpimult, bool removeLateralsInMainBoreCells) { QFile exportFile(fileName); @@ -112,7 +112,7 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat RiaLogging::error("Export Completions Data: Cannot export completions data without specified eclipse case"); return; } - + if (!exportFile.open(QIODevice::WriteOnly)) { RiaLogging::error(QString("Export Completions Data: Could not open the file: %1").arg(fileName)); @@ -122,7 +122,13 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat QTextStream stream(&exportFile); const RigEclipseCaseData* caseData = caseToApply->eclipseCaseData(); - std::vector wellPathCells = findIntersectingCells(caseData, wellPath->wellPathGeometry()->m_wellPathPoints); + + std::vector wellPathCells; + if (removeLateralsInMainBoreCells) + { + wellPathCells = findIntersectingCells(caseData, wellPath->wellPathGeometry()->m_wellPathPoints); + } + std::map lateralsPerCell; RifEclipseOutputTableFormatter formatter(stream); @@ -165,9 +171,12 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat addLateralToCells(&lateralsPerCell, lateralCells); } - std::vector cellsUniqueToLateral = filterWellPathCells(lateralCells, wellPathCells); + if (removeLateralsInMainBoreCells) + { + lateralCells = filterWellPathCells(lateralCells, wellPathCells); + } - std::vector cellRanges = getCellIndexRange(caseData->mainGrid(), cellsUniqueToLateral); + std::vector cellRanges = getCellIndexRange(caseData->mainGrid(), lateralCells); formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(subs->name()).arg(subIndex).arg(lateralIndex)); for (auto cellRange : cellRanges) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h index eea5037640..36f507d562 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h @@ -52,7 +52,7 @@ protected: virtual void setupActionLook(QAction* actionToSetup) override; private: - static void exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply, bool includeWpimult); + static void exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply, bool includeWpimult, bool removeLateralsInMainBoreCells); static std::vector findCloseCells(const RigEclipseCaseData* caseData, const cvf::BoundingBox& bb); static std::vector getCellIndexRange(const RigMainGrid* grid, const std::vector& cellIndices); static bool cellOrdering(const EclipseCellIndex& cell1, const EclipseCellIndex& cell2); diff --git a/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp index 656e0680bf..eb342e1f38 100644 --- a/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017- Statoil ASA -// Copyright (C) 2017- Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -29,4 +28,5 @@ RimExportCompletionDataSettings::RimExportCompletionDataSettings() CAF_PDM_InitObject("RimExportCompletionDataSettings", "", "", ""); CAF_PDM_InitFieldNoDefault(&includeWpimult, "IncludeWPIMULT", "Include WPIMLUT", "", "", ""); + CAF_PDM_InitFieldNoDefault(&removeLateralsInMainBoreCells, "RemoveLateralsInMainBoreCells", "Remove Laterals in Main Bore Cells", "", "", ""); } diff --git a/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.h b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.h index 3728ab04e3..37594a18b2 100644 --- a/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.h +++ b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.h @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017- Statoil ASA -// Copyright (C) 2017- Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -35,4 +34,5 @@ public: RimExportCompletionDataSettings(); caf::PdmField includeWpimult; + caf::PdmField removeLateralsInMainBoreCells; }; From a71eace12466fbcd620509eb167b6048ad02f073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Fri, 19 May 2017 11:09:36 +0200 Subject: [PATCH 138/157] #1462 Set first eclipse case in project to default selected eclipse case --- .../RicWellPathExportCompletionDataFeature.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index ea35fecfb3..26e883fbe7 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -76,13 +76,20 @@ void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked) QString defaultDir = RiaApplication::instance()->lastUsedDialogDirectoryWithFallback("COMPLETIONS", projectFolder); RimExportCompletionDataSettings exportSettings; + std::vector cases; + app->project()->allCases(cases); + for (auto c : cases) + { + RimEclipseCase* eclipseCase = dynamic_cast(c); + if (eclipseCase != nullptr) + { + exportSettings.caseToApply = eclipseCase; + break; + } + } exportSettings.fileName = QDir(defaultDir).filePath("Completions"); - RimEclipseCase* caseToApply; - objects[0]->firstAncestorOrThisOfType(caseToApply); - exportSettings.caseToApply = caseToApply; - caf::PdmUiPropertyViewDialog propertyDialog(RiuMainWindow::instance(), &exportSettings, "Export Completion Data", ""); if (propertyDialog.exec() == QDialog::Accepted) { From b23996a75f07fb71a315c2f36198ffe74e81065f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Fri, 19 May 2017 11:28:02 +0200 Subject: [PATCH 139/157] #1464 Fishbones MSW : Export well segments --- ...RicWellPathExportCompletionDataFeature.cpp | 234 ++++++++++++++++-- .../RicWellPathExportCompletionDataFeature.h | 49 ++++ .../RifEclipseOutputTableFormatter.cpp | 46 ++-- .../RifEclipseOutputTableFormatter.h | 3 +- .../Fishbones/RimFishbonesMultipleSubs.h | 1 + 5 files changed, 300 insertions(+), 33 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index 26e883fbe7..ff3cbed1d9 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -28,8 +28,6 @@ #include "RiuMainWindow.h" -#include "RifEclipseOutputTableFormatter.h" - #include "RigWellLogExtractionTools.h" #include "RigEclipseCaseData.h" #include "RigMainGrid.h" @@ -38,13 +36,14 @@ #include "cafSelectionManager.h" #include "cafPdmUiPropertyViewDialog.h" +#include "cvfPlane.h" + #include #include #include CAF_CMD_SOURCE_INIT(RicWellPathExportCompletionDataFeature, "RicWellPathExportCompletionDataFeature"); - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -200,7 +199,7 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat } } } - formatter.flush(); + formatter.tableCompleted(); } // WPIMULT @@ -224,8 +223,10 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat formatter.rowCompleted(); } - formatter.flush(); + formatter.tableCompleted(); } + + computeWellSegments(formatter, wellPath, caseToApply); } //-------------------------------------------------------------------------------------------------- @@ -345,6 +346,27 @@ std::vector RicWellPathExportCompletionDataFeature::findIntersectingCell } } + std::vector intersections = findIntersections(caseData, coords); + for (auto intersection : intersections) + { + cells.insert(intersection.m_hexIndex); + } + + // Ensure only unique cells are included + std::vector cellsVector; + cellsVector.assign(cells.begin(), cells.end()); + // Sort cells + std::sort(cellsVector.begin(), cellsVector.end()); + return cellsVector; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RicWellPathExportCompletionDataFeature::findIntersections(const RigEclipseCaseData* caseData, const std::vector& coords) +{ + const std::vector& nodeCoords = caseData->mainGrid()->nodes(); + std::vector intersections; for (size_t i = 0; i < coords.size() - 1; ++i) { cvf::BoundingBox bb; @@ -354,7 +376,6 @@ std::vector RicWellPathExportCompletionDataFeature::findIntersectingCell std::vector closeCells = findCloseCells(caseData, bb); cvf::Vec3d hexCorners[8]; - std::vector intersections; for (size_t closeCell : closeCells) { @@ -365,18 +386,9 @@ std::vector RicWellPathExportCompletionDataFeature::findIntersectingCell RigHexIntersector::lineHexCellIntersection(coords[i], coords[i + 1], hexCorners, closeCell, &intersections); } - - for (auto intersection : intersections) - { - cells.insert(intersection.m_hexIndex); - } } - // Ensure only unique cells are included - std::vector cellsVector; - cellsVector.assign(cells.begin(), cells.end()); - // Sort cells - std::sort(cellsVector.begin(), cellsVector.end()); - return cellsVector; + + return intersections; } //-------------------------------------------------------------------------------------------------- @@ -424,3 +436,191 @@ void RicWellPathExportCompletionDataFeature::addLateralToCells(std::map wellSegmentLocations = findWellSegmentLocations(wellPath); + if (wellSegmentLocations.empty()) return; + formatter.keyword("WELSEGS"); + + WellSegmentLocation& firstLocation = wellSegmentLocations[0]; + + { + std::vector header = { + RifEclipseOutputTableColumn{"Name", LEFT}, + RifEclipseOutputTableColumn{"Dep 1", LEFT}, + RifEclipseOutputTableColumn{"Tlen 1", LEFT}, + RifEclipseOutputTableColumn{"Vol 1", LEFT}, + RifEclipseOutputTableColumn{"Len&Dep", LEFT}, + RifEclipseOutputTableColumn{"PresDrop", LEFT}, + }; + formatter.header(header); + + formatter.add(wellPath->name()); + formatter.add(firstLocation.trueVerticalDepth); + formatter.add(firstLocation.measuredDepth); + formatter.add("1*"); + formatter.add("INC"); + formatter.add("H--"); + + formatter.rowCompleted(); + } + + { + std::vector header = { + RifEclipseOutputTableColumn{"First Seg", LEFT}, + RifEclipseOutputTableColumn{"Last Seg", LEFT}, + RifEclipseOutputTableColumn{"Branch Num", LEFT}, + RifEclipseOutputTableColumn{"Outlet Seg", LEFT}, + RifEclipseOutputTableColumn{"Length", LEFT}, + RifEclipseOutputTableColumn{"Depth Change", LEFT}, + RifEclipseOutputTableColumn{"Diam", LEFT}, + RifEclipseOutputTableColumn{"Rough", LEFT}, + }; + formatter.header(header); + } + + size_t segmentNumber = 1; + { + WellSegmentLocation previousLocation = firstLocation; + formatter.comment("Main stem"); + for (size_t i = 0; i < wellSegmentLocations.size(); ++i) + { + WellSegmentLocation& location = wellSegmentLocations[i]; + location.segmentNumber = static_cast(segmentNumber + 1); + + formatter.comment(QString("Segment for sub %1").arg(location.subIndex)); + formatter.add(location.segmentNumber).add(location.segmentNumber); + formatter.add(1); // All segments on main stem are branch 1 + formatter.add(segmentNumber); + formatter.add(location.fishbonesSubs->locationOfSubs()[location.subIndex] - previousLocation.fishbonesSubs->locationOfSubs()[previousLocation.subIndex]); + formatter.add(location.trueVerticalDepth - previousLocation.trueVerticalDepth); + formatter.add(-1.0); // FIXME : Diam of main stem? + formatter.add(-1.0); // FIXME : Rough of main stem? + formatter.rowCompleted(); + + ++segmentNumber; + previousLocation = location; + } + } + + { + int branchNum = 1; + formatter.comment("Laterals"); + formatter.comment("Diam: MSW - Tubing Radius"); + formatter.comment("Rough: MSW - Open Hole Roughness Factor"); + for (WellSegmentLocation& location : wellSegmentLocations) + { + for (WellSegmentLateral& lateral : location.laterals) + { + formatter.comment(QString("%1 : Sub index %2 - Lateral %3").arg(location.fishbonesSubs->name()).arg(location.subIndex).arg(lateral.lateralIndex)); + + lateral.branchNumber = ++branchNum; + std::vector& coords = location.fishbonesSubs->coordsForLateral(location.subIndex, lateral.lateralIndex); + std::vector intersections = findIntersections(caseToApply->eclipseCaseData(), coords); + filterIntersections(&intersections); + + double length = 0; + double depth = 0; + cvf::Vec3d& startPoint = coords[0]; + auto intersection = intersections.cbegin(); + + for (size_t i = 1; i < coords.size() && intersection != intersections.cend(); i++) + { + if (isPointBetween(startPoint, coords[i], intersection->m_intersectionPoint)) + { + cvf::Vec3d between = intersection->m_intersectionPoint - startPoint; + length += between.length(); + depth += intersection->m_intersectionPoint.z() - startPoint.z(); + segmentNumber++; + formatter.add(segmentNumber).add(segmentNumber); + formatter.add(lateral.branchNumber); + formatter.add(location.segmentNumber); + formatter.add(length); + formatter.add(depth); + formatter.add(location.fishbonesSubs->tubingRadius()); + formatter.add(location.fishbonesSubs->openHoleRoughnessFactor()); + formatter.rowCompleted(); + + length = 0; + depth = 0; + startPoint = intersection->m_intersectionPoint; + ++intersection; + } + else + { + cvf::Vec3d between = coords[i] - startPoint; + length += between.length(); + depth += coords[i].z() - startPoint.z(); + startPoint = coords[i]; + } + } + } + } + } + + formatter.tableCompleted(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicWellPathExportCompletionDataFeature::wellSegmentLocationOrdering(const WellSegmentLocation& first, const WellSegmentLocation& second) +{ + return first.measuredDepth < second.measuredDepth; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicWellPathExportCompletionDataFeature::isPointBetween(const cvf::Vec3d& pointA, const cvf::Vec3d& pointB, const cvf::Vec3d& needle) +{ + cvf::Plane plane; + plane.setFromPointAndNormal(needle, pointB - pointA); + return plane.side(pointA) != plane.side(pointB); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::filterIntersections(std::vector* intersections) +{ + // Erase intersections that are marked as entering + for (auto it = intersections->begin(); it != intersections->end();) + { + if (it->m_isIntersectionEntering) + { + it = intersections->erase(it); + } + else + { + ++it; + } + } +} + +std::vector RicWellPathExportCompletionDataFeature::findWellSegmentLocations(RimWellPath* wellPath) +{ + std::vector wellSegmentLocations; + for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesSubs) + { + for (size_t subIndex = 0; subIndex < subs->locationOfSubs().size(); ++subIndex) + { + double measuredDepth = subs->locationOfSubs()[subIndex]; + cvf::Vec3d position = wellPath->wellPathGeometry()->interpolatedPointAlongWellPath(measuredDepth); + WellSegmentLocation location = WellSegmentLocation(subs, measuredDepth, -position.z(), subIndex); + for (size_t lateralIndex = 0; lateralIndex < subs->lateralLengths().size(); ++lateralIndex) + { + location.laterals.push_back(WellSegmentLateral(lateralIndex)); + } + wellSegmentLocations.push_back(location); + } + } + std::sort(wellSegmentLocations.begin(), wellSegmentLocations.end(), wellSegmentLocationOrdering); + + return wellSegmentLocations; +} + diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h index 36f507d562..20d4cca44b 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h @@ -18,17 +18,57 @@ #pragma once +#include "RifEclipseOutputTableFormatter.h" + +#include "RigWellLogExtractionTools.h" #include "cafCmdFeature.h" #include "cvfBoundingBox.h" + class RimWellPath; class RimEclipseCase; class RigEclipseCaseData; class RigMainGrid; class RigCell; +class RimFishbonesMultipleSubs; + +//================================================================================================== +/// +//================================================================================================== +struct WellSegmentLateral { + WellSegmentLateral(size_t lateralIndex) : lateralIndex(lateralIndex) {} + + size_t lateralIndex; + int branchNumber; +}; + +//================================================================================================== +/// +//================================================================================================== +struct WellSegmentLocation { + WellSegmentLocation(const RimFishbonesMultipleSubs* subs, double measuredDepth, double trueVerticalDepth, size_t subIndex) + : fishbonesSubs(subs), + measuredDepth(measuredDepth), + trueVerticalDepth(trueVerticalDepth), + subIndex(subIndex), + segmentNumber(-1) + { + } + + const RimFishbonesMultipleSubs* fishbonesSubs; + double measuredDepth; + double trueVerticalDepth; + size_t subIndex; + int segmentNumber; + std::vector laterals; +}; + +//================================================================================================== +/// +//================================================================================================== struct EclipseCellIndexRange { size_t i; size_t j; @@ -36,6 +76,9 @@ struct EclipseCellIndexRange { size_t k2; }; +//================================================================================================== +/// +//================================================================================================== typedef std::tuple EclipseCellIndex; //================================================================================================== @@ -60,4 +103,10 @@ private: static void setHexCorners(const RigCell& cell, const std::vector& nodeCoords, cvf::Vec3d* hexCorners); static std::vector filterWellPathCells(const std::vector& completionCells, const std::vector& wellPathCells); static void addLateralToCells(std::map* lateralsPerCell, const std::vector& lateralCells); + static void computeWellSegments(RifEclipseOutputTableFormatter& formatter, RimWellPath* wellPath, const RimEclipseCase* caseToApply); + static bool wellSegmentLocationOrdering(const WellSegmentLocation& first, const WellSegmentLocation& second); + static std::vector findIntersections(const RigEclipseCaseData* caseData, const std::vector& coords); + static bool isPointBetween(const cvf::Vec3d& pointA, const cvf::Vec3d& pointB, const cvf::Vec3d& needle); + static void filterIntersections(std::vector* intersections); + static std::vector findWellSegmentLocations(RimWellPath* wellPath); }; diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp index d7ed079af4..454b974f7a 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.cpp @@ -32,16 +32,8 @@ RifEclipseOutputTableFormatter::RifEclipseOutputTableFormatter(QTextStream& out) //-------------------------------------------------------------------------------------------------- RifEclipseOutputTableFormatter::~RifEclipseOutputTableFormatter() { - -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RifEclipseOutputTableFormatter::flush() -{ - if (!m_lineBuffer.empty()) rowCompleted(); - outputBuffer(); + CVF_ASSERT(m_buffer.empty()); + CVF_ASSERT(m_columns.empty()); } //-------------------------------------------------------------------------------------------------- @@ -63,7 +55,7 @@ void RifEclipseOutputTableFormatter::outputBuffer() { if (line.lineType == COMMENT) { - m_out << "-- " << line.data[0] << "\n"; + outputComment(line); } else if (line.lineType == CONTENTS) { @@ -75,18 +67,35 @@ void RifEclipseOutputTableFormatter::outputBuffer() m_out << " /" << "\n"; } } - // If we finished a table, output an "empty" line after it - if (!m_columns.empty()) m_out << "/\n"; m_columns.clear(); m_buffer.clear(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifEclipseOutputTableFormatter::outputComment(RifEclipseOutputTableLine& comment) +{ + m_out << "-- " << comment.data[0] << "\n"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifEclipseOutputTableFormatter::tableCompleted() +{ + outputBuffer(); + // Output an "empty" line after a finished table + m_out << "/\n"; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RifEclipseOutputTableFormatter& RifEclipseOutputTableFormatter::keyword(const QString keyword) { - flush(); + CVF_ASSERT(m_buffer.empty()); + CVF_ASSERT(m_columns.empty()); m_out << keyword << "\n"; return *this; } @@ -113,7 +122,14 @@ RifEclipseOutputTableFormatter& RifEclipseOutputTableFormatter::comment(const QS RifEclipseOutputTableLine line; line.data.push_back(comment); line.lineType = COMMENT; - m_buffer.push_back(line); + if (m_columns.empty()) + { + outputComment(line); + } + else + { + m_buffer.push_back(line); + } return *this; } diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h index 217e10a58e..89b08dd700 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h @@ -86,7 +86,7 @@ public: RifEclipseOutputTableFormatter& addZeroBasedCellIndex(size_t index); RifEclipseOutputTableFormatter& comment(const QString str); void rowCompleted(); - void flush(); + void tableCompleted(); private: int measure(const QString str); @@ -100,6 +100,7 @@ private: QString formatColumn(const QString str, RifEclipseOutputTableColumn column); void outputBuffer(); + void outputComment(RifEclipseOutputTableLine& comment); private: std::vector m_columns; diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h index 74797de1d4..f5fccaf5a0 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -64,6 +64,7 @@ public: double tubingRadius() const; double holeRadius() const { return m_lateralHoleRadius(); } + double openHoleRoughnessFactor() const { return m_lateralOpenHoleRoghnessFactor(); } double lateralCountPerSub() const; std::vector lateralLengths() const; From d67d5ec3305dd8eda6f2053eb18cadbc60179990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Fri, 19 May 2017 11:43:47 +0200 Subject: [PATCH 140/157] Fix error assigning return value to reference --- .../WellPathCommands/RicWellPathExportCompletionDataFeature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index ff3cbed1d9..a04197f861 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -519,7 +519,7 @@ void RicWellPathExportCompletionDataFeature::computeWellSegments(RifEclipseOutpu formatter.comment(QString("%1 : Sub index %2 - Lateral %3").arg(location.fishbonesSubs->name()).arg(location.subIndex).arg(lateral.lateralIndex)); lateral.branchNumber = ++branchNum; - std::vector& coords = location.fishbonesSubs->coordsForLateral(location.subIndex, lateral.lateralIndex); + std::vector coords = location.fishbonesSubs->coordsForLateral(location.subIndex, lateral.lateralIndex); std::vector intersections = findIntersections(caseToApply->eclipseCaseData(), coords); filterIntersections(&intersections); From d8dc62c5a7e2b2800cccb58c535c25ad7b779deb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 13:40:38 +0200 Subject: [PATCH 141/157] #1510 Remove invalid usage of namespace caf for features Also add override keyword --- .../RicCopyReferencesToClipboardFeature.cpp | 19 ++++--------- .../RicCopyReferencesToClipboardFeature.h | 20 ++++++------- .../RicPasteEclipseCasesFeature.cpp | 14 ++++------ .../RicPasteEclipseCasesFeature.h | 13 ++++----- .../RicPasteEclipseViewsFeature.cpp | 15 ++++------ .../RicPasteEclipseViewsFeature.h | 11 ++------ .../RicPasteGeoMechViewsFeature.cpp | 15 ++++------ .../RicPasteGeoMechViewsFeature.h | 14 ++-------- .../RicNewPerforationIntervalFeature.cpp | 5 ---- .../RicNewPerforationIntervalFeature.h | 15 +++------- .../Commands/RicDeleteItemExec.cpp | 25 +++++++---------- ApplicationCode/Commands/RicDeleteItemExec.h | 11 ++------ .../Commands/RicDeleteItemExecData.cpp | 5 ---- .../Commands/RicDeleteItemExecData.h | 12 ++------ .../Commands/RicDeleteItemFeature.cpp | 28 ++++++++----------- .../Commands/RicDeleteItemFeature.h | 15 +++------- .../ToggleCommands/RicToggleItemsFeature.cpp | 9 ++---- .../ToggleCommands/RicToggleItemsFeature.h | 15 +++------- .../RicToggleItemsOffFeature.cpp | 9 ++---- .../ToggleCommands/RicToggleItemsOffFeature.h | 15 +++------- .../RicToggleItemsOnFeature.cpp | 9 ++---- .../ToggleCommands/RicToggleItemsOnFeature.h | 15 +++------- .../RicAddWellLogToPlotFeature.cpp | 6 +--- .../RicAddWellLogToPlotFeature.h | 14 +++------- .../RicWellLogsImportFileFeature.cpp | 7 +---- .../RicWellLogsImportFileFeature.h | 16 ++++------- .../RicWellPathDeleteFeature.cpp | 9 +----- .../RicWellPathDeleteFeature.h | 15 +++------- ...icWellPathImportCompletionsFileFeature.cpp | 7 +---- .../RicWellPathImportCompletionsFileFeature.h | 14 +++------- .../RicWellPathsImportFileFeature.cpp | 6 +--- .../RicWellPathsImportFileFeature.h | 15 +++------- .../RicWellPathsImportSsihubFeature.cpp | 6 +--- .../RicWellPathsImportSsihubFeature.h | 15 +++------- ApplicationCode/UserInterface/RiuDragDrop.cpp | 4 +-- 35 files changed, 125 insertions(+), 318 deletions(-) diff --git a/ApplicationCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.cpp b/ApplicationCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.cpp index ac8ff487fd..150fc76b89 100644 --- a/ApplicationCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.cpp +++ b/ApplicationCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.cpp @@ -38,8 +38,6 @@ #include -namespace caf -{ CAF_CMD_SOURCE_INIT(RicCopyReferencesToClipboardFeature, "RicCopyReferencesToClipboardFeature"); @@ -63,14 +61,14 @@ void RicCopyReferencesToClipboardFeature::onActionTriggered(bool isChecked) std::vector referenceList; - std::vector selectedFormationNamesCollObjs; + std::vector selectedFormationNamesCollObjs; caf::SelectionManager::instance()->objectsByType(&selectedFormationNamesCollObjs); - for (PdmObject* pdmObject : selectedFormationNamesCollObjs) + for (caf::PdmObject* pdmObject : selectedFormationNamesCollObjs) { if (RicCopyReferencesToClipboardFeature::isCopyOfObjectSupported(pdmObject)) { - QString itemRef = PdmReferenceHelper::referenceFromRootToObject(SelectionManager::instance()->pdmRootObject(), pdmObject); + QString itemRef = caf::PdmReferenceHelper::referenceFromRootToObject(caf::SelectionManager::instance()->pdmRootObject(), pdmObject); referenceList.push_back(itemRef); } @@ -96,16 +94,15 @@ void RicCopyReferencesToClipboardFeature::setupActionLook(QAction* actionToSetup actionToSetup->setShortcuts(QKeySequence::Copy); } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RicCopyReferencesToClipboardFeature::isAnyCopyableObjectSelected() { - std::vector selectedFormationNamesCollObjs; + std::vector selectedFormationNamesCollObjs; caf::SelectionManager::instance()->objectsByType(&selectedFormationNamesCollObjs); - for (PdmObject* pdmObject : selectedFormationNamesCollObjs) + for (caf::PdmObject* pdmObject : selectedFormationNamesCollObjs) { if (RicCopyReferencesToClipboardFeature::isCopyOfObjectSupported(pdmObject)) { @@ -116,12 +113,10 @@ bool RicCopyReferencesToClipboardFeature::isAnyCopyableObjectSelected() return false; } - - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RicCopyReferencesToClipboardFeature::isCopyOfObjectSupported(PdmObject* pdmObject) +bool RicCopyReferencesToClipboardFeature::isCopyOfObjectSupported(caf::PdmObject* pdmObject) { RimWellAllocationPlot* wellAllocPlot = nullptr; pdmObject->firstAncestorOrThisOfType(wellAllocPlot); @@ -161,5 +156,3 @@ bool RicCopyReferencesToClipboardFeature::isCopyOfObjectSupported(PdmObject* pdm return false; } - -} // end namespace caf diff --git a/ApplicationCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.h b/ApplicationCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.h index 477eba8a15..ff1b55f966 100644 --- a/ApplicationCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.h +++ b/ApplicationCode/Commands/OperationsUsingObjReferences/RicCopyReferencesToClipboardFeature.h @@ -22,29 +22,25 @@ #include "cafCmdFeature.h" -namespace caf +namespace caf { - -class PdmObject; + class PdmObject; +} //================================================================================================== /// //================================================================================================== -class RicCopyReferencesToClipboardFeature : public CmdFeature +class RicCopyReferencesToClipboardFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; private: static bool isAnyCopyableObjectSelected(); - static bool isCopyOfObjectSupported(PdmObject* pdmObject); + static bool isCopyOfObjectSupported(caf::PdmObject* pdmObject); }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseCasesFeature.cpp b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseCasesFeature.cpp index 1ef1447676..596c28adbc 100644 --- a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseCasesFeature.cpp +++ b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseCasesFeature.cpp @@ -42,8 +42,6 @@ #include #include -namespace caf -{ CAF_CMD_SOURCE_INIT(RicPasteEclipseCasesFeature, "RicPasteEclipseCasesFeature"); @@ -53,7 +51,7 @@ CAF_CMD_SOURCE_INIT(RicPasteEclipseCasesFeature, "RicPasteEclipseCasesFeature"); //-------------------------------------------------------------------------------------------------- bool RicPasteEclipseCasesFeature::isCommandEnabled() { - PdmObjectGroup objectGroup; + caf::PdmObjectGroup objectGroup; RicPasteFeatureImpl::findObjectsFromClipboardRefs(&objectGroup); std::vector > typedObjects; @@ -64,7 +62,7 @@ bool RicPasteEclipseCasesFeature::isCommandEnabled() return false; } - PdmObjectHandle* destinationObject = dynamic_cast(SelectionManager::instance()->selectedItem()); + caf::PdmObjectHandle* destinationObject = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); RimIdenticalGridCaseGroup* gridCaseGroup = RicPasteFeatureImpl::findGridCaseGroup(destinationObject); if (gridCaseGroup) return true; @@ -77,12 +75,12 @@ bool RicPasteEclipseCasesFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicPasteEclipseCasesFeature::onActionTriggered(bool isChecked) { - PdmObjectHandle* destinationObject = dynamic_cast(SelectionManager::instance()->selectedItem()); + caf::PdmObjectHandle* destinationObject = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); RimIdenticalGridCaseGroup* gridCaseGroup = RicPasteFeatureImpl::findGridCaseGroup(destinationObject); if (!gridCaseGroup) return; - PdmObjectGroup objectGroup; + caf::PdmObjectGroup objectGroup; RicPasteFeatureImpl::findObjectsFromClipboardRefs(&objectGroup); if (objectGroup.objects.size() == 0) return; @@ -105,7 +103,7 @@ void RicPasteEclipseCasesFeature::setupActionLook(QAction* actionToSetup) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicPasteEclipseCasesFeature::addCasesToGridCaseGroup(PdmObjectGroup& objectGroup, RimIdenticalGridCaseGroup* gridCaseGroup) +void RicPasteEclipseCasesFeature::addCasesToGridCaseGroup(caf::PdmObjectGroup& objectGroup, RimIdenticalGridCaseGroup* gridCaseGroup) { RimProject* proj = RiaApplication::instance()->project(); CVF_ASSERT(proj); @@ -202,5 +200,3 @@ void RicPasteEclipseCasesFeature::addCasesToGridCaseGroup(PdmObjectGroup& object } } - -} // end namespace caf diff --git a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseCasesFeature.h b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseCasesFeature.h index 648f62c5ed..5a1ed65387 100644 --- a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseCasesFeature.h +++ b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseCasesFeature.h @@ -28,6 +28,7 @@ class RimIdenticalGridCaseGroup; namespace caf { class PdmObjectGroup; +} //================================================================================================== /// @@ -37,15 +38,11 @@ class RicPasteEclipseCasesFeature : public caf::CmdFeature CAF_CMD_HEADER_INIT; public: - static void addCasesToGridCaseGroup(PdmObjectGroup& objectGroup, RimIdenticalGridCaseGroup* gridCaseGroup); + static void addCasesToGridCaseGroup(caf::PdmObjectGroup& objectGroup, RimIdenticalGridCaseGroup* gridCaseGroup); protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered(bool isChecked); - virtual void setupActionLook(QAction* actionToSetup); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered(bool isChecked) override; + virtual void setupActionLook(QAction* actionToSetup) override; }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseViewsFeature.cpp b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseViewsFeature.cpp index 97fb22d65a..aecc75ee64 100644 --- a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseViewsFeature.cpp +++ b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseViewsFeature.cpp @@ -35,8 +35,6 @@ #include -namespace caf -{ CAF_CMD_SOURCE_INIT(RicPasteEclipseViewsFeature, "RicPasteEclipseViewsFeature"); @@ -45,7 +43,7 @@ CAF_CMD_SOURCE_INIT(RicPasteEclipseViewsFeature, "RicPasteEclipseViewsFeature"); //-------------------------------------------------------------------------------------------------- bool RicPasteEclipseViewsFeature::isCommandEnabled() { - PdmObjectGroup objectGroup; + caf::PdmObjectGroup objectGroup; RicPasteFeatureImpl::findObjectsFromClipboardRefs(&objectGroup); std::vector > typedObjects; @@ -56,7 +54,7 @@ bool RicPasteEclipseViewsFeature::isCommandEnabled() return false; } - PdmObjectHandle* destinationObject = dynamic_cast(SelectionManager::instance()->selectedItem()); + caf::PdmObjectHandle* destinationObject = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); RimIdenticalGridCaseGroup* gridCaseGroup = RicPasteFeatureImpl::findGridCaseGroup(destinationObject); if (gridCaseGroup) return false; @@ -72,12 +70,12 @@ bool RicPasteEclipseViewsFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicPasteEclipseViewsFeature::onActionTriggered(bool isChecked) { - PdmObjectHandle* destinationObject = dynamic_cast(SelectionManager::instance()->selectedItem()); + caf::PdmObjectHandle* destinationObject = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); RimEclipseCase* eclipseCase = RicPasteFeatureImpl::findEclipseCase(destinationObject); assert(eclipseCase); - PdmObjectGroup objectGroup; + caf::PdmObjectGroup objectGroup; RicPasteFeatureImpl::findObjectsFromClipboardRefs(&objectGroup); if (objectGroup.objects.size() == 0) return; @@ -90,7 +88,7 @@ void RicPasteEclipseViewsFeature::onActionTriggered(bool isChecked) // Add cases to case group for (size_t i = 0; i < eclipseViews.size(); i++) { - RimEclipseView* rimReservoirView = dynamic_cast(eclipseViews[i]->xmlCapability()->copyByXmlSerialization(PdmDefaultObjectFactory::instance())); + RimEclipseView* rimReservoirView = dynamic_cast(eclipseViews[i]->xmlCapability()->copyByXmlSerialization(caf::PdmDefaultObjectFactory::instance())); CVF_ASSERT(rimReservoirView); QString nameOfCopy = QString("Copy of ") + rimReservoirView->name; @@ -124,6 +122,3 @@ void RicPasteEclipseViewsFeature::setupActionLook(QAction* actionToSetup) RicPasteFeatureImpl::setIconAndShortcuts(actionToSetup); } - - -} // end namespace caf diff --git a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseViewsFeature.h b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseViewsFeature.h index 8ddd2ea5f7..3f0b0ca454 100644 --- a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseViewsFeature.h +++ b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteEclipseViewsFeature.h @@ -23,8 +23,6 @@ #include "cafCmdFeature.h" -namespace caf -{ //================================================================================================== /// @@ -35,11 +33,8 @@ CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered(bool isChecked); - virtual void setupActionLook(QAction* actionToSetup); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered(bool isChecked) override; + virtual void setupActionLook(QAction* actionToSetup) override; }; - - -} // end namespace caf diff --git a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteGeoMechViewsFeature.cpp b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteGeoMechViewsFeature.cpp index b5c6505452..cf1b63151f 100644 --- a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteGeoMechViewsFeature.cpp +++ b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteGeoMechViewsFeature.cpp @@ -32,8 +32,6 @@ #include -namespace caf -{ CAF_CMD_SOURCE_INIT(RicPasteGeoMechViewsFeature, "RicPasteGeoMechViewsFeature"); @@ -42,7 +40,7 @@ CAF_CMD_SOURCE_INIT(RicPasteGeoMechViewsFeature, "RicPasteGeoMechViewsFeature"); //-------------------------------------------------------------------------------------------------- bool RicPasteGeoMechViewsFeature::isCommandEnabled() { - PdmObjectGroup objectGroup; + caf::PdmObjectGroup objectGroup; RicPasteFeatureImpl::findObjectsFromClipboardRefs(&objectGroup); std::vector > typedObjects; @@ -53,7 +51,7 @@ bool RicPasteGeoMechViewsFeature::isCommandEnabled() return false; } - PdmObjectHandle* destinationObject = dynamic_cast(SelectionManager::instance()->selectedItem()); + caf::PdmObjectHandle* destinationObject = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); RimGeoMechCase* geoMechCase = RicPasteFeatureImpl::findGeoMechCase(destinationObject); if (geoMechCase) return true; @@ -66,12 +64,12 @@ bool RicPasteGeoMechViewsFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicPasteGeoMechViewsFeature::onActionTriggered(bool isChecked) { - PdmObjectHandle* destinationObject = dynamic_cast(SelectionManager::instance()->selectedItem()); + caf::PdmObjectHandle* destinationObject = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); RimGeoMechCase* geomCase = RicPasteFeatureImpl::findGeoMechCase(destinationObject); assert(geomCase); - PdmObjectGroup objectGroup; + caf::PdmObjectGroup objectGroup; RicPasteFeatureImpl::findObjectsFromClipboardRefs(&objectGroup); if (objectGroup.objects.size() == 0) return; @@ -84,7 +82,7 @@ void RicPasteGeoMechViewsFeature::onActionTriggered(bool isChecked) // Add cases to case group for (size_t i = 0; i < geomViews.size(); i++) { - RimGeoMechView* rimReservoirView = dynamic_cast(geomViews[i]->xmlCapability()->copyByXmlSerialization(PdmDefaultObjectFactory::instance())); + RimGeoMechView* rimReservoirView = dynamic_cast(geomViews[i]->xmlCapability()->copyByXmlSerialization(caf::PdmDefaultObjectFactory::instance())); QString nameOfCopy = QString("Copy of ") + rimReservoirView->name; rimReservoirView->name = nameOfCopy; geomCase->geoMechViews().push_back(rimReservoirView); @@ -117,6 +115,3 @@ void RicPasteGeoMechViewsFeature::setupActionLook(QAction* actionToSetup) RicPasteFeatureImpl::setIconAndShortcuts(actionToSetup); } - - -} // end namespace caf diff --git a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteGeoMechViewsFeature.h b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteGeoMechViewsFeature.h index 98c991b722..143534f8e6 100644 --- a/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteGeoMechViewsFeature.h +++ b/ApplicationCode/Commands/OperationsUsingObjReferences/RicPasteGeoMechViewsFeature.h @@ -22,10 +22,6 @@ #include "cafCmdFeature.h" - -namespace caf -{ - //================================================================================================== /// //================================================================================================== @@ -35,11 +31,7 @@ CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered(bool isChecked); - virtual void setupActionLook(QAction* actionToSetup); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered(bool isChecked) override; + virtual void setupActionLook(QAction* actionToSetup) override; }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp index cb0b5e780c..2682a634bc 100644 --- a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp +++ b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp @@ -30,9 +30,6 @@ #include -namespace caf -{ - CAF_CMD_SOURCE_INIT(RicNewPerforationIntervalFeature, "RicNewPerforationIntervalFeature"); @@ -92,5 +89,3 @@ RimWellPath * RicNewPerforationIntervalFeature::selectedWellPath() return wellPath; } - -} // end namespace caf diff --git a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h index 573349e0f7..9c72ebaafe 100644 --- a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h +++ b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h @@ -23,26 +23,19 @@ class RimWellPath; -namespace caf -{ - //================================================================================================== /// //================================================================================================== -class RicNewPerforationIntervalFeature : public CmdFeature +class RicNewPerforationIntervalFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; private: RimWellPath* selectedWellPath(); }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/RicDeleteItemExec.cpp b/ApplicationCode/Commands/RicDeleteItemExec.cpp index a8fa3ec22e..c6a31d6a50 100644 --- a/ApplicationCode/Commands/RicDeleteItemExec.cpp +++ b/ApplicationCode/Commands/RicDeleteItemExec.cpp @@ -21,8 +21,10 @@ #include "RicDeleteItemExec.h" #include "RicDeleteItemExecData.h" +#include "RimCase.h" #include "RimCellRangeFilterCollection.h" #include "RimEclipsePropertyFilterCollection.h" +#include "RimFormationNamesCollection.h" #include "RimGeoMechPropertyFilterCollection.h" #include "RimIntersectionCollection.h" #include "RimProject.h" @@ -39,13 +41,8 @@ #include "cafPdmReferenceHelper.h" #include "cafPdmUiFieldHandle.h" #include "cafSelectionManager.h" -#include "RimFormationNamesCollection.h" -#include "RimCase.h" -namespace caf -{ - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -59,15 +56,15 @@ QString RicDeleteItemExec::name() //-------------------------------------------------------------------------------------------------- void RicDeleteItemExec::redo() { - PdmFieldHandle* field = PdmReferenceHelper::fieldFromReference(m_commandData->m_rootObject, m_commandData->m_pathToField); + caf::PdmFieldHandle* field = caf::PdmReferenceHelper::fieldFromReference(m_commandData->m_rootObject, m_commandData->m_pathToField); - PdmChildArrayFieldHandle* listField = dynamic_cast(field); + caf::PdmChildArrayFieldHandle* listField = dynamic_cast(field); if (listField) { - std::vector children; + std::vector children; listField->childObjects(&children); - PdmObjectHandle* obj = children[m_commandData->m_indexToObject]; + caf::PdmObjectHandle* obj = children[m_commandData->m_indexToObject]; caf::SelectionManager::instance()->removeObjectFromAllSelections(obj); std::vector referringObjects; @@ -204,12 +201,12 @@ void RicDeleteItemExec::redo() //-------------------------------------------------------------------------------------------------- void RicDeleteItemExec::undo() { - PdmFieldHandle* field = PdmReferenceHelper::fieldFromReference(m_commandData->m_rootObject, m_commandData->m_pathToField); + caf::PdmFieldHandle* field = caf::PdmReferenceHelper::fieldFromReference(m_commandData->m_rootObject, m_commandData->m_pathToField); - PdmChildArrayFieldHandle* listField = dynamic_cast(field); + caf::PdmChildArrayFieldHandle* listField = dynamic_cast(field); if (listField) { - PdmObjectHandle* obj = PdmXmlObjectHandle::readUnknownObjectFromXmlString(m_commandData->m_deletedObjectAsXml(), PdmDefaultObjectFactory::instance()); + caf::PdmObjectHandle* obj = caf::PdmXmlObjectHandle::readUnknownObjectFromXmlString(m_commandData->m_deletedObjectAsXml(), caf::PdmDefaultObjectFactory::instance()); listField->insertAt(m_commandData->m_indexToObject, obj); @@ -225,7 +222,7 @@ void RicDeleteItemExec::undo() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RicDeleteItemExec::RicDeleteItemExec(NotificationCenter* notificationCenter) +RicDeleteItemExec::RicDeleteItemExec(caf::NotificationCenter* notificationCenter) : CmdExecuteCommand(notificationCenter) { m_commandData = new RicDeleteItemExecData; @@ -238,5 +235,3 @@ RicDeleteItemExecData* RicDeleteItemExec::commandData() { return m_commandData; } - -} // end namespace caf diff --git a/ApplicationCode/Commands/RicDeleteItemExec.h b/ApplicationCode/Commands/RicDeleteItemExec.h index e733702f45..38bef07d1e 100644 --- a/ApplicationCode/Commands/RicDeleteItemExec.h +++ b/ApplicationCode/Commands/RicDeleteItemExec.h @@ -22,18 +22,15 @@ #include "cafCmdExecuteCommand.h" -namespace caf -{ - class RicDeleteItemExecData; //================================================================================================== /// //================================================================================================== -class RicDeleteItemExec : public CmdExecuteCommand +class RicDeleteItemExec : public caf::CmdExecuteCommand { public: - explicit RicDeleteItemExec(NotificationCenter* notificationCenter); + explicit RicDeleteItemExec(caf::NotificationCenter* notificationCenter); RicDeleteItemExecData* commandData(); @@ -44,7 +41,3 @@ public: private: RicDeleteItemExecData* m_commandData; }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/RicDeleteItemExecData.cpp b/ApplicationCode/Commands/RicDeleteItemExecData.cpp index 6f0a20bb6a..0a00e9752e 100644 --- a/ApplicationCode/Commands/RicDeleteItemExecData.cpp +++ b/ApplicationCode/Commands/RicDeleteItemExecData.cpp @@ -21,9 +21,4 @@ #include "RicDeleteItemExecData.h" -namespace caf -{ - CAF_PDM_SOURCE_INIT(RicDeleteItemExecData, "RicDeleteItemExecData"); - -} // end namespace caf diff --git a/ApplicationCode/Commands/RicDeleteItemExecData.h b/ApplicationCode/Commands/RicDeleteItemExecData.h index e8000233b4..f5af3a7874 100644 --- a/ApplicationCode/Commands/RicDeleteItemExecData.h +++ b/ApplicationCode/Commands/RicDeleteItemExecData.h @@ -23,14 +23,10 @@ #include "cafPdmObject.h" #include "cafPdmField.h" -namespace caf -{ - - //================================================================================================== /// //================================================================================================== -class RicDeleteItemExecData : public PdmObject +class RicDeleteItemExecData : public caf::PdmObject { CAF_PDM_HEADER_INIT; @@ -44,13 +40,9 @@ public: CAF_PDM_InitField(&m_deletedObjectAsXml, "deletedObjectAsXml", QString(), "deletedObjectAsXml", "", "deletedObjectAsXml tooltip", "deletedObjectAsXml whatsthis"); } - caf::PdmPointer m_rootObject; + caf::PdmPointer m_rootObject; caf::PdmField m_pathToField; caf::PdmField m_indexToObject; caf::PdmField m_deletedObjectAsXml; }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/RicDeleteItemFeature.cpp b/ApplicationCode/Commands/RicDeleteItemFeature.cpp index 6cf56c7118..e92f40bbe4 100644 --- a/ApplicationCode/Commands/RicDeleteItemFeature.cpp +++ b/ApplicationCode/Commands/RicDeleteItemFeature.cpp @@ -55,11 +55,9 @@ #include -namespace caf -{ - CAF_CMD_SOURCE_INIT(RicDeleteItemFeature, "RicDeleteItemFeature"); +CAF_CMD_SOURCE_INIT(RicDeleteItemFeature, "RicDeleteItemFeature"); -bool isDeletable(PdmUiItem * uiItem) +bool isDeletable(caf::PdmUiItem* uiItem) { // Enable delete of well allocation plots if (dynamic_cast(uiItem)) return true; @@ -107,12 +105,12 @@ bool isDeletable(PdmUiItem * uiItem) //-------------------------------------------------------------------------------------------------- bool RicDeleteItemFeature::isCommandEnabled() { - std::vector items; + std::vector items; caf::SelectionManager::instance()->selectedItems(items); if (items.empty() ) return false; - for (PdmUiItem* item : items) + for (caf::PdmUiItem* item : items) { if (!isDeletable(item)) return false; @@ -131,11 +129,11 @@ bool RicDeleteItemFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicDeleteItemFeature::onActionTriggered(bool isChecked) { - std::vector items; - SelectionManager::instance()->selectedItems(items); + std::vector items; + caf::SelectionManager::instance()->selectedItems(items); assert(items.size() > 0); - for (PdmUiItem* item: items) + for (caf::PdmUiItem* item: items) { if (!isDeletable(item)) continue; @@ -147,7 +145,7 @@ void RicDeleteItemFeature::onActionTriggered(bool isChecked) int indexAfter = -1; - std::vector childObjects; + std::vector childObjects; childArrayFieldHandle->childObjects(&childObjects); for ( size_t i = 0; i < childObjects.size(); i++ ) @@ -161,15 +159,15 @@ void RicDeleteItemFeature::onActionTriggered(bool isChecked) // Did not find currently selected pdm object in the current list field assert(indexAfter != -1); - RicDeleteItemExec* executeCmd = new RicDeleteItemExec(SelectionManager::instance()->notificationCenter()); + RicDeleteItemExec* executeCmd = new RicDeleteItemExec(caf::SelectionManager::instance()->notificationCenter()); RicDeleteItemExecData* data = executeCmd->commandData(); - data->m_rootObject = PdmReferenceHelper::findRoot(childArrayFieldHandle); - data->m_pathToField = PdmReferenceHelper::referenceFromRootToField(data->m_rootObject, childArrayFieldHandle); + data->m_rootObject = caf::PdmReferenceHelper::findRoot(childArrayFieldHandle); + data->m_pathToField = caf::PdmReferenceHelper::referenceFromRootToField(data->m_rootObject, childArrayFieldHandle); data->m_indexToObject = indexAfter; - CmdExecCommandManager::instance()->processExecuteCommand(executeCmd); + caf::CmdExecCommandManager::instance()->processExecuteCommand(executeCmd); } } @@ -181,5 +179,3 @@ void RicDeleteItemFeature::setupActionLook(QAction* actionToSetup) actionToSetup->setText("Delete"); actionToSetup->setIcon(QIcon(":/Erase.png")); } - -} // end namespace caf diff --git a/ApplicationCode/Commands/RicDeleteItemFeature.h b/ApplicationCode/Commands/RicDeleteItemFeature.h index 5cde0517ef..466b2bcf17 100644 --- a/ApplicationCode/Commands/RicDeleteItemFeature.h +++ b/ApplicationCode/Commands/RicDeleteItemFeature.h @@ -21,23 +21,16 @@ #include "cafCmdFeature.h" -namespace caf -{ - //================================================================================================== /// //================================================================================================== -class RicDeleteItemFeature : public CmdFeature +class RicDeleteItemFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeature.cpp b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeature.cpp index 75e5e7be2f..24023e0790 100644 --- a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeature.cpp +++ b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeature.cpp @@ -19,14 +19,11 @@ #include "RicToggleItemsFeature.h" -#include "cafSelectionManager.h" - #include "RicToggleItemsFeatureImpl.h" -#include +#include "cafSelectionManager.h" -namespace caf -{ +#include CAF_CMD_SOURCE_INIT(RicToggleItemsFeature, "RicToggleItemsFeature"); @@ -56,5 +53,3 @@ void RicToggleItemsFeature::setupActionLook(QAction* actionToSetup) else actionToSetup->setText("Toggle"); } - -} // end namespace caf diff --git a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeature.h b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeature.h index 8698dc3237..13aac4e39d 100644 --- a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeature.h +++ b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsFeature.h @@ -21,23 +21,16 @@ #include "cafCmdFeature.h" -namespace caf -{ - //================================================================================================== /// //================================================================================================== -class RicToggleItemsFeature : public CmdFeature +class RicToggleItemsFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOffFeature.cpp b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOffFeature.cpp index 0d61886c90..027e33d5ca 100644 --- a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOffFeature.cpp +++ b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOffFeature.cpp @@ -19,14 +19,11 @@ #include "RicToggleItemsOffFeature.h" -#include "cafSelectionManager.h" - #include "RicToggleItemsFeatureImpl.h" -#include +#include "cafSelectionManager.h" -namespace caf -{ +#include CAF_CMD_SOURCE_INIT(RicToggleItemsOffFeature, "RicToggleItemsOffFeature"); @@ -56,5 +53,3 @@ void RicToggleItemsOffFeature::setupActionLook(QAction* actionToSetup) else actionToSetup->setText("Off"); } - -} // end namespace caf diff --git a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOffFeature.h b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOffFeature.h index 2ae4f4a0fe..0f9b77f87a 100644 --- a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOffFeature.h +++ b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOffFeature.h @@ -21,23 +21,16 @@ #include "cafCmdFeature.h" -namespace caf -{ - //================================================================================================== /// //================================================================================================== -class RicToggleItemsOffFeature : public CmdFeature +class RicToggleItemsOffFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOnFeature.cpp b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOnFeature.cpp index ecb20cb108..0f2467c5ff 100644 --- a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOnFeature.cpp +++ b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOnFeature.cpp @@ -19,14 +19,11 @@ #include "RicToggleItemsOnFeature.h" -#include "cafSelectionManager.h" - #include "RicToggleItemsFeatureImpl.h" -#include +#include "cafSelectionManager.h" -namespace caf -{ +#include CAF_CMD_SOURCE_INIT(RicToggleItemsOnFeature, "RicToggleItemsOnFeature"); @@ -56,5 +53,3 @@ void RicToggleItemsOnFeature::setupActionLook(QAction* actionToSetup) else actionToSetup->setText("On"); } - -} // end namespace caf diff --git a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOnFeature.h b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOnFeature.h index e92b543e26..97d8c3fed1 100644 --- a/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOnFeature.h +++ b/ApplicationCode/Commands/ToggleCommands/RicToggleItemsOnFeature.h @@ -21,23 +21,16 @@ #include "cafCmdFeature.h" -namespace caf -{ - //================================================================================================== /// //================================================================================================== -class RicToggleItemsOnFeature : public CmdFeature +class RicToggleItemsOnFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.cpp index 45bb637df2..4f040b8252 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.cpp @@ -43,9 +43,7 @@ #include -namespace caf -{ - CAF_CMD_SOURCE_INIT(RicAddWellLogToPlotFeature, "RicAddWellLogToPlotFeature"); +CAF_CMD_SOURCE_INIT(RicAddWellLogToPlotFeature, "RicAddWellLogToPlotFeature"); //-------------------------------------------------------------------------------------------------- @@ -135,5 +133,3 @@ std::vector RicAddWellLogToPlotFeature::selectedWellLogs caf::SelectionManager::instance()->objectsByType(&selection); return selection; } - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.h b/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.h index 987000abb8..cd47047e75 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.h +++ b/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.h @@ -28,26 +28,20 @@ class RimWellLogPlotCollection; class RimWellLogPlot; class RimWellLogFileChannel; -namespace caf -{ //================================================================================================== /// //================================================================================================== -class RicAddWellLogToPlotFeature : public CmdFeature +class RicAddWellLogToPlotFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; private: std::vector selectedWellLogs(); }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellLogCommands/RicWellLogsImportFileFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicWellLogsImportFileFeature.cpp index bdbdef20ef..0cc2aebcc7 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicWellLogsImportFileFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicWellLogsImportFileFeature.cpp @@ -26,10 +26,7 @@ #include #include -namespace caf -{ - CAF_CMD_SOURCE_INIT(RicWellLogsImportFileFeature, "RicWellLogsImportFileFeature"); - +CAF_CMD_SOURCE_INIT(RicWellLogsImportFileFeature, "RicWellLogsImportFileFeature"); //-------------------------------------------------------------------------------------------------- /// @@ -65,5 +62,3 @@ void RicWellLogsImportFileFeature::setupActionLook(QAction* actionToSetup) actionToSetup->setText("Import Well &Logs from File"); actionToSetup->setIcon(QIcon(":/LasFile16x16.png")); } - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellLogCommands/RicWellLogsImportFileFeature.h b/ApplicationCode/Commands/WellLogCommands/RicWellLogsImportFileFeature.h index c82e9bf70e..11eaec4b12 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicWellLogsImportFileFeature.h +++ b/ApplicationCode/Commands/WellLogCommands/RicWellLogsImportFileFeature.h @@ -21,23 +21,17 @@ #include "cafCmdFeature.h" -namespace caf -{ - //================================================================================================== /// //================================================================================================== -class RicWellLogsImportFileFeature : public CmdFeature +class RicWellLogsImportFileFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; + protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathDeleteFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathDeleteFeature.cpp index 9ee57e1033..d419766521 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathDeleteFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathDeleteFeature.cpp @@ -20,19 +20,14 @@ #include "RicWellPathDeleteFeature.h" #include "RimWellPathCollection.h" +#include "RimWellPath.h" #include "cafSelectionManager.h" #include -#include "RimWellPath.h" - -namespace caf -{ - CAF_CMD_SOURCE_INIT(RicWellPathDeleteFeature, "RicWellPathDeleteFeature"); - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -83,5 +78,3 @@ void RicWellPathDeleteFeature::setupActionLook(QAction* actionToSetup) actionToSetup->setText("Delete Well Path(s)"); actionToSetup->setIcon(QIcon(":/Erase.png")); } - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathDeleteFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathDeleteFeature.h index 7f39370eaa..6f8e0bc97b 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathDeleteFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathDeleteFeature.h @@ -21,23 +21,16 @@ #include "cafCmdFeature.h" -namespace caf -{ - //================================================================================================== /// //================================================================================================== -class RicWellPathDeleteFeature : public CmdFeature +class RicWellPathDeleteFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp index d1e319471f..d658b54d2b 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp @@ -32,10 +32,7 @@ #include #include -namespace caf -{ - CAF_CMD_SOURCE_INIT(RicWellPathImportCompletionsFileFeature, "RicWellPathImportCompletionsFileFeature"); - +CAF_CMD_SOURCE_INIT(RicWellPathImportCompletionsFileFeature, "RicWellPathImportCompletionsFileFeature"); //-------------------------------------------------------------------------------------------------- /// @@ -88,5 +85,3 @@ void RicWellPathImportCompletionsFileFeature::setupActionLook(QAction* actionToS actionToSetup->setText("Import Completions from File"); actionToSetup->setIcon(QIcon(":/Well.png")); } - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h index 1967c04d89..dc26985bb0 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h @@ -21,23 +21,17 @@ #include "cafCmdFeature.h" -namespace caf -{ - //================================================================================================== /// //================================================================================================== -class RicWellPathImportCompletionsFileFeature : public CmdFeature +class RicWellPathImportCompletionsFileFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; }; - - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportFileFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportFileFeature.cpp index f94a3c0a4d..fc313108fd 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportFileFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportFileFeature.cpp @@ -26,9 +26,7 @@ #include #include -namespace caf -{ - CAF_CMD_SOURCE_INIT(RicWellPathsImportFileFeature, "RicWellPathsImportFileFeature"); +CAF_CMD_SOURCE_INIT(RicWellPathsImportFileFeature, "RicWellPathsImportFileFeature"); //-------------------------------------------------------------------------------------------------- @@ -69,5 +67,3 @@ void RicWellPathsImportFileFeature::setupActionLook(QAction* actionToSetup) actionToSetup->setText("Import &Well Paths from File"); actionToSetup->setIcon(QIcon(":/Well.png")); } - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportFileFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportFileFeature.h index 40bf0afa2f..08d3650e0d 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportFileFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportFileFeature.h @@ -21,23 +21,16 @@ #include "cafCmdFeature.h" -namespace caf -{ - //================================================================================================== /// //================================================================================================== -class RicWellPathsImportFileFeature : public CmdFeature +class RicWellPathsImportFileFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; }; - - - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp index e4be65a2b6..f33403840b 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.cpp @@ -33,9 +33,7 @@ #include #include -namespace caf -{ - CAF_CMD_SOURCE_INIT(RicWellPathsImportSsihubFeature, "RicWellPathsImportSsihubFeature"); +CAF_CMD_SOURCE_INIT(RicWellPathsImportSsihubFeature, "RicWellPathsImportSsihubFeature"); //-------------------------------------------------------------------------------------------------- @@ -125,5 +123,3 @@ void RicWellPathsImportSsihubFeature::setupActionLook(QAction* actionToSetup) actionToSetup->setText("Import Well Paths from &SSI-hub"); actionToSetup->setIcon(QIcon(":/WellCollection.png")); } - -} // end namespace caf diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.h index 46bfc99c33..ae107e2571 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathsImportSsihubFeature.h @@ -21,23 +21,16 @@ #include "cafCmdFeature.h" -namespace caf -{ - //================================================================================================== /// //================================================================================================== -class RicWellPathsImportSsihubFeature : public CmdFeature +class RicWellPathsImportSsihubFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; protected: // Overrides - virtual bool isCommandEnabled(); - virtual void onActionTriggered( bool isChecked ); - virtual void setupActionLook( QAction* actionToSetup ); + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; }; - - - -} // end namespace caf diff --git a/ApplicationCode/UserInterface/RiuDragDrop.cpp b/ApplicationCode/UserInterface/RiuDragDrop.cpp index d0e54b3007..bca4bf933f 100644 --- a/ApplicationCode/UserInterface/RiuDragDrop.cpp +++ b/ApplicationCode/UserInterface/RiuDragDrop.cpp @@ -312,7 +312,7 @@ void RiuDragDrop::moveCasesToGridGroup(caf::PdmObjectGroup& objectGroup, RimIden if (RicCloseCaseFeature::userConfirmedGridCaseGroupChange(casesToBeDeleted)) { - caf::RicPasteEclipseCasesFeature::addCasesToGridCaseGroup(objectGroup, gridCaseGroup); + RicPasteEclipseCasesFeature::addCasesToGridCaseGroup(objectGroup, gridCaseGroup); for (size_t i = 0; i < casesToBeDeleted.size(); i++) { @@ -328,7 +328,7 @@ bool RiuDragDrop::handleGridCaseGroupDrop(Qt::DropAction action, caf::PdmObjectG { if (action == Qt::CopyAction) { - caf::RicPasteEclipseCasesFeature::addCasesToGridCaseGroup(objectGroup, gridCaseGroup); + RicPasteEclipseCasesFeature::addCasesToGridCaseGroup(objectGroup, gridCaseGroup); } else if (action == Qt::MoveAction) { From fd254565e60f2f710564fa74e3523cc0ad769010 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 13:47:44 +0200 Subject: [PATCH 142/157] #1495 Rename to FishboneWellPath and FishboneWellPathCollection --- .../Commands/RicDeleteItemFeature.cpp | 4 ++-- ...icWellPathImportCompletionsFileFeature.cpp | 2 +- .../ModelVisualization/RivWellPathPartMgr.cpp | 6 +++--- ...Completion.cpp => RimFishboneWellPath.cpp} | 20 +++++++++---------- ...PathCompletion.h => RimFishboneWellPath.h} | 6 +++--- ....cpp => RimFishboneWellPathCollection.cpp} | 18 ++++++++--------- ...tion.h => RimFishboneWellPathCollection.h} | 12 +++++------ .../ProjectDataModel/RimWellPath.cpp | 4 ++-- .../ProjectDataModel/RimWellPath.h | 4 ++-- 9 files changed, 38 insertions(+), 38 deletions(-) rename ApplicationCode/ProjectDataModel/{RimWellPathCompletion.cpp => RimFishboneWellPath.cpp} (84%) rename ApplicationCode/ProjectDataModel/{RimWellPathCompletion.h => RimFishboneWellPath.h} (94%) rename ApplicationCode/ProjectDataModel/{RimWellPathCompletionCollection.cpp => RimFishboneWellPathCollection.cpp} (82%) rename ApplicationCode/ProjectDataModel/{RimWellPathCompletionCollection.h => RimFishboneWellPathCollection.h} (81%) diff --git a/ApplicationCode/Commands/RicDeleteItemFeature.cpp b/ApplicationCode/Commands/RicDeleteItemFeature.cpp index e92f40bbe4..57cd3d45d9 100644 --- a/ApplicationCode/Commands/RicDeleteItemFeature.cpp +++ b/ApplicationCode/Commands/RicDeleteItemFeature.cpp @@ -43,7 +43,7 @@ #include "RimWellLogCurve.h" #include "RimWellLogPlot.h" #include "RimWellLogTrack.h" -#include "RimWellPathCompletion.h" +#include "RimFishboneWellPath.h" #include "RimPerforationInterval.h" #include "cafCmdExecCommandManager.h" @@ -93,7 +93,7 @@ bool isDeletable(caf::PdmUiItem* uiItem) if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; - if (dynamic_cast(uiItem)) return true; + if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; if (dynamic_cast(uiItem)) return true; diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp index d658b54d2b..93153eb424 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp @@ -23,7 +23,7 @@ #include "RimProject.h" #include "RimWellPath.h" -#include "RimWellPathCompletionCollection.h" +#include "RimFishboneWellPathCollection.h" #include "RiuMainWindow.h" diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 3a22bcaf5b..d44d0d70ce 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -28,8 +28,8 @@ #include "RimFishbonesMultipleSubs.h" #include "RimWellPath.h" #include "RimWellPathCollection.h" -#include "RimWellPathCompletion.h" -#include "RimWellPathCompletionCollection.h" +#include "RimFishboneWellPath.h" +#include "RimFishboneWellPathCollection.h" #include "RimPerforationInterval.h" #include "RimPerforationCollection.h" @@ -123,7 +123,7 @@ void RivWellPathPartMgr::appendCompletionsToModel(cvf::ModelBasicList* model, ca if (!m_rimWellPath || !m_rimWellPath->m_completionCollection->isChecked()) return; RivPipeGeometryGenerator geoGenerator; - for (RimWellPathCompletion* completion : m_rimWellPath->m_completionCollection()->m_completions()) + for (RimFishboneWellPath* completion : m_rimWellPath->m_completionCollection()->m_completions()) { if (!completion->isChecked()) continue; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp b/ApplicationCode/ProjectDataModel/RimFishboneWellPath.cpp similarity index 84% rename from ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp rename to ApplicationCode/ProjectDataModel/RimFishboneWellPath.cpp index bbc5fec08c..9915e8e372 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.cpp +++ b/ApplicationCode/ProjectDataModel/RimFishboneWellPath.cpp @@ -17,19 +17,19 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RimWellPathCompletion.h" +#include "RimFishboneWellPath.h" #include "RimProject.h" #include "cafPdmUiListEditor.h" #include "cafPdmUiTextEditor.h" -CAF_PDM_SOURCE_INIT(RimWellPathCompletion, "WellPathCompletion"); +CAF_PDM_SOURCE_INIT(RimFishboneWellPath, "WellPathCompletion"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPathCompletion::RimWellPathCompletion() +RimFishboneWellPath::RimFishboneWellPath() { CAF_PDM_InitObject("WellPathCompletion", ":/Well.png", "", ""); CAF_PDM_InitFieldNoDefault(&m_coordinates, "Coordinates", "Coordinates", "", "", ""); @@ -39,7 +39,7 @@ RimWellPathCompletion::RimWellPathCompletion() m_name.uiCapability()->setUiHidden(true); CAF_PDM_InitFieldNoDefault(&m_displayCoordinates, "DisplayCoordinates", "Coordinates", "", "", ""); - m_displayCoordinates.registerGetMethod(this, &RimWellPathCompletion::displayCoordinates); + m_displayCoordinates.registerGetMethod(this, &RimFishboneWellPath::displayCoordinates); m_displayCoordinates.uiCapability()->setUiReadOnly(true); m_displayCoordinates.uiCapability()->setUiEditorTypeName(caf::PdmUiTextEditor::uiEditorTypeName()); m_displayCoordinates.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::LabelPosType::TOP); @@ -49,14 +49,14 @@ RimWellPathCompletion::RimWellPathCompletion() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPathCompletion::~RimWellPathCompletion() +RimFishboneWellPath::~RimFishboneWellPath() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellPathCompletion::setCoordinates(std::vector< cvf::Vec3d > coordinates) +void RimFishboneWellPath::setCoordinates(std::vector< cvf::Vec3d > coordinates) { m_coordinates = coordinates; } @@ -64,7 +64,7 @@ void RimWellPathCompletion::setCoordinates(std::vector< cvf::Vec3d > coordinates //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellPathCompletion::setMeasuredDepths(std::vector< double > measuredDepths) +void RimFishboneWellPath::setMeasuredDepths(std::vector< double > measuredDepths) { m_measuredDepths = measuredDepths; } @@ -72,7 +72,7 @@ void RimWellPathCompletion::setMeasuredDepths(std::vector< double > measuredDept //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellPathCompletion::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +void RimFishboneWellPath::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { RimProject* proj; this->firstAncestorOrThisOfType(proj); @@ -82,7 +82,7 @@ void RimWellPathCompletion::fieldChangedByUi(const caf::PdmFieldHandle* changedF //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellPathCompletion::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +void RimFishboneWellPath::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { uiOrdering.add(&m_displayCoordinates); } @@ -90,7 +90,7 @@ void RimWellPathCompletion::defineUiOrdering(QString uiConfigName, caf::PdmUiOrd //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RimWellPathCompletion::displayCoordinates() const +QString RimFishboneWellPath::displayCoordinates() const { CVF_ASSERT(m_coordinates().size() == m_measuredDepths().size()); diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h b/ApplicationCode/ProjectDataModel/RimFishboneWellPath.h similarity index 94% rename from ApplicationCode/ProjectDataModel/RimWellPathCompletion.h rename to ApplicationCode/ProjectDataModel/RimFishboneWellPath.h index 73abd53b72..768755d024 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletion.h +++ b/ApplicationCode/ProjectDataModel/RimFishboneWellPath.h @@ -41,13 +41,13 @@ /// /// //================================================================================================== -class RimWellPathCompletion : public RimCheckableNamedObject +class RimFishboneWellPath : public RimCheckableNamedObject { CAF_PDM_HEADER_INIT; public: - RimWellPathCompletion(); - virtual ~RimWellPathCompletion(); + RimFishboneWellPath(); + virtual ~RimFishboneWellPath(); virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; virtual void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.cpp b/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.cpp similarity index 82% rename from ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.cpp rename to ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.cpp index 7ad44f309f..62896cd987 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.cpp @@ -17,10 +17,10 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RimWellPathCompletionCollection.h" +#include "RimFishboneWellPathCollection.h" #include "RimEclipseWell.h" -#include "RimWellPathCompletion.h" +#include "RimFishboneWellPath.h" #include "RimView.h" #include "RimProject.h" @@ -31,12 +31,12 @@ #include "RiuMainWindow.h" -CAF_PDM_SOURCE_INIT(RimWellPathCompletionCollection, "WellPathCompletionCollection"); +CAF_PDM_SOURCE_INIT(RimFishboneWellPathCollection, "WellPathCompletionCollection"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPathCompletionCollection::RimWellPathCompletionCollection() +RimFishboneWellPathCollection::RimFishboneWellPathCollection() { CAF_PDM_InitObject("WellPathCompletions", ":/WellCollection.png", "", ""); @@ -50,7 +50,7 @@ RimWellPathCompletionCollection::RimWellPathCompletionCollection() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPathCompletionCollection::~RimWellPathCompletionCollection() +RimFishboneWellPathCollection::~RimFishboneWellPathCollection() { m_completions.deleteAllChildObjects(); } @@ -58,7 +58,7 @@ RimWellPathCompletionCollection::~RimWellPathCompletionCollection() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellPathCompletionCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +void RimFishboneWellPathCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { RimProject* proj; this->firstAncestorOrThisOfTypeAsserted(proj); @@ -68,7 +68,7 @@ void RimWellPathCompletionCollection::fieldChangedByUi(const caf::PdmFieldHandle //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellPathCompletionCollection::appendCompletion(RimWellPathCompletion* completion) +void RimFishboneWellPathCollection::appendCompletion(RimFishboneWellPath* completion) { m_completions.push_back(completion); @@ -88,7 +88,7 @@ void RimWellPathCompletionCollection::appendCompletion(RimWellPathCompletion* co //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellPathCompletionCollection::importCompletionsFromFile(const QList filePaths) +void RimFishboneWellPathCollection::importCompletionsFromFile(const QList filePaths) { RifWellPathImporter wellPathImporter; @@ -98,7 +98,7 @@ void RimWellPathCompletionCollection::importCompletionsFromFile(const QListsetName(wellData.m_name); wellCompletion->setCoordinates(wellData.m_wellPathGeometry->m_wellPathPoints); wellCompletion->setMeasuredDepths(wellData.m_wellPathGeometry->m_measuredDepths); diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.h b/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.h similarity index 81% rename from ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.h rename to ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.h index 48c562e70b..fa18876b32 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletionCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.h @@ -20,7 +20,7 @@ #pragma once #include "RimCheckableNamedObject.h" -#include "RimWellPathCompletion.h" +#include "RimFishboneWellPath.h" #include "cafPdmObject.h" #include "cafPdmChildArrayField.h" @@ -31,18 +31,18 @@ // // //================================================================================================== -class RimWellPathCompletionCollection : public RimCheckableNamedObject +class RimFishboneWellPathCollection : public RimCheckableNamedObject { CAF_PDM_HEADER_INIT; public: - RimWellPathCompletionCollection(); - ~RimWellPathCompletionCollection(); + RimFishboneWellPathCollection(); + ~RimFishboneWellPathCollection(); - void appendCompletion(RimWellPathCompletion* completion); + void appendCompletion(RimFishboneWellPath* completion); void importCompletionsFromFile(const QList filePaths); void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); - caf::PdmChildArrayField m_completions; + caf::PdmChildArrayField m_completions; }; diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index b8e0686fc0..bda535141b 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -30,7 +30,7 @@ #include "RimWellLogFile.h" #include "RimWellLogPlotCollection.h" #include "RimWellPathCollection.h" -#include "RimWellPathCompletionCollection.h" +#include "RimFishboneWellPathCollection.h" #include "RimPerforationCollection.h" #include "RimFishbonesMultipleSubs.h" @@ -105,7 +105,7 @@ RimWellPath::RimWellPath() CAF_PDM_InitField(&wellPathColor, "WellPathColor", cvf::Color3f(0.999f, 0.333f, 0.999f), "Well path color", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_completionCollection, "Completions", "Completions", "", "", ""); - m_completionCollection = new RimWellPathCompletionCollection; + m_completionCollection = new RimFishboneWellPathCollection; m_completionCollection.uiCapability()->setUiHidden(true); CAF_PDM_InitFieldNoDefault(&m_perforationCollection, "Perforations", "Perforations", "", "", ""); diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index be5a31c372..ddbe26aab9 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -36,7 +36,7 @@ class RifWellPathImporter; class RigWellPath; class RimProject; class RimWellLogFile; -class RimWellPathCompletionCollection; +class RimFishboneWellPathCollection; class RivWellPathPartMgr; class RimFishbonesMultipleSubs; @@ -73,7 +73,7 @@ public: caf::PdmField wellPathRadiusScaleFactor; caf::PdmChildField m_wellLogFile; - caf::PdmChildField m_completionCollection; + caf::PdmChildField m_completionCollection; caf::PdmChildField m_perforationCollection; RigWellPath* wellPathGeometry(); From 1853f97bbcb19a978815dc533467af1da8b1261b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 14:04:01 +0200 Subject: [PATCH 143/157] #1495 Add WellPathCompletions --- .../ProjectDataModel/CMakeLists_files.cmake | 11 +++--- .../ProjectDataModel/RimWellPath.cpp | 9 ++++- .../ProjectDataModel/RimWellPath.h | 2 ++ .../RimWellPathCompletions.cpp | 32 +++++++++++++++++ .../ProjectDataModel/RimWellPathCompletions.h | 34 +++++++++++++++++++ 5 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimWellPathCompletions.h diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index ba156e920a..a473ce2ec1 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -35,8 +35,8 @@ ${CEE_CURRENT_LIST_DIR}RimEclipseWell.h ${CEE_CURRENT_LIST_DIR}RimEclipseWellCollection.h ${CEE_CURRENT_LIST_DIR}RimWellPath.h ${CEE_CURRENT_LIST_DIR}RimWellPathCollection.h -${CEE_CURRENT_LIST_DIR}RimWellPathCompletion.h -${CEE_CURRENT_LIST_DIR}RimWellPathCompletionCollection.h +${CEE_CURRENT_LIST_DIR}RimFishboneWellPath.h +${CEE_CURRENT_LIST_DIR}RimFishboneWellPathCollection.h ${CEE_CURRENT_LIST_DIR}RimScriptCollection.h ${CEE_CURRENT_LIST_DIR}RimEclipseStatisticsCase.h ${CEE_CURRENT_LIST_DIR}RimEclipseStatisticsCaseCollection.h @@ -96,6 +96,7 @@ ${CEE_CURRENT_LIST_DIR}RimCheckableNamedObject.h ${CEE_CURRENT_LIST_DIR}RimGridTimeHistoryCurve.h ${CEE_CURRENT_LIST_DIR}RimGeometrySelectionItem.h ${CEE_CURRENT_LIST_DIR}RimEclipseGeometrySelectionItem.h +${CEE_CURRENT_LIST_DIR}RimWellPathCompletions.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -129,8 +130,8 @@ ${CEE_CURRENT_LIST_DIR}RimEclipseWell.cpp ${CEE_CURRENT_LIST_DIR}RimEclipseWellCollection.cpp ${CEE_CURRENT_LIST_DIR}RimWellPath.cpp ${CEE_CURRENT_LIST_DIR}RimWellPathCollection.cpp -${CEE_CURRENT_LIST_DIR}RimWellPathCompletion.cpp -${CEE_CURRENT_LIST_DIR}RimWellPathCompletionCollection.cpp +${CEE_CURRENT_LIST_DIR}RimFishboneWellPath.cpp +${CEE_CURRENT_LIST_DIR}RimFishboneWellPathCollection.cpp ${CEE_CURRENT_LIST_DIR}RimScriptCollection.cpp ${CEE_CURRENT_LIST_DIR}RimEclipseStatisticsCase.cpp ${CEE_CURRENT_LIST_DIR}RimEclipseStatisticsCaseCollection.cpp @@ -190,6 +191,7 @@ ${CEE_CURRENT_LIST_DIR}RimCheckableNamedObject.cpp ${CEE_CURRENT_LIST_DIR}RimGridTimeHistoryCurve.cpp ${CEE_CURRENT_LIST_DIR}RimGeometrySelectionItem.cpp ${CEE_CURRENT_LIST_DIR}RimEclipseGeometrySelectionItem.cpp +${CEE_CURRENT_LIST_DIR}RimWellPathCompletions.cpp ) list(APPEND CODE_HEADER_FILES @@ -200,4 +202,5 @@ list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES} ) + source_group( "ProjectDataModel" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CEE_CURRENT_LIST_DIR}CMakeLists_files.cmake ) diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index bda535141b..cc973bd500 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -34,6 +34,7 @@ #include "RimPerforationCollection.h" #include "RimFishbonesMultipleSubs.h" +#include "RimWellPathCompletions.h" #include "RiuMainWindow.h" @@ -104,7 +105,7 @@ RimWellPath::RimWellPath() CAF_PDM_InitField(&wellPathRadiusScaleFactor, "WellPathRadiusScale", 1.0, "Well path radius scale", "", "", ""); CAF_PDM_InitField(&wellPathColor, "WellPathColor", cvf::Color3f(0.999f, 0.333f, 0.999f), "Well path color", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_completionCollection, "Completions", "Completions", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_completionCollection, "Completions_to_be_moved", "Completions", "", "", ""); m_completionCollection = new RimFishboneWellPathCollection; m_completionCollection.uiCapability()->setUiHidden(true); @@ -112,6 +113,10 @@ RimWellPath::RimWellPath() m_perforationCollection = new RimPerforationCollection; m_perforationCollection.uiCapability()->setUiHidden(true); + CAF_PDM_InitFieldNoDefault(&m_completions, "Completions", "Completions", "", "", ""); + m_completions = new RimWellPathCompletions; + m_completions.uiCapability()->setUiTreeHidden(true); + CAF_PDM_InitFieldNoDefault(&m_wellLogFile, "WellLogFile", "Well Log File", "", "", ""); m_wellLogFile.uiCapability()->setUiHidden(true); @@ -290,6 +295,8 @@ void RimWellPath::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, Q { uiTreeOrdering.skipRemainingChildren(true); uiTreeOrdering.add(&m_wellLogFile); + uiTreeOrdering.add(&m_completions); + if (!m_completionCollection->m_completions.empty()) { uiTreeOrdering.add(&m_completionCollection); diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index ddbe26aab9..b3777d2c5a 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -41,6 +41,7 @@ class RivWellPathPartMgr; class RimFishbonesMultipleSubs; class RimPerforationCollection; +class RimWellPathCompletions; //================================================================================================== /// @@ -75,6 +76,7 @@ public: caf::PdmChildField m_wellLogFile; caf::PdmChildField m_completionCollection; caf::PdmChildField m_perforationCollection; + caf::PdmChildField m_completions; RigWellPath* wellPathGeometry(); caf::PdmChildArrayField fishbonesSubs; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp new file mode 100644 index 0000000000..2631cc3846 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp @@ -0,0 +1,32 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimWellPathCompletions.h" + + +CAF_PDM_SOURCE_INIT(RimWellPathCompletions, "WellPathCompletions"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPathCompletions::RimWellPathCompletions() +{ + CAF_PDM_InitObject("WellPathCompletions", ":/WellCollection.png", "", ""); +} + + diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletions.h b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.h new file mode 100644 index 0000000000..18f1764fa8 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmObject.h" + + +//================================================================================================== +/// +/// +//================================================================================================== +class RimWellPathCompletions : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimWellPathCompletions(); +}; From 5ec2764c168ae3a14df2a174849d61fa13cd5b23 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 May 2017 15:44:32 +0200 Subject: [PATCH 144/157] #1495 Add 'Completions' folder to RimWellPath Move perforation intervals into folder Move fishbone definitions and fishbone well paths into folder --- .../RicExportFishbonesLateralsFeature.cpp | 3 +- ...NewFishbonesSubsAtMeasuredDepthFeature.cpp | 5 +- .../RicNewFishbonesSubsFeature.cpp | 5 +- .../RicEditPerforationCollectionFeature.cpp | 2 +- ...forationIntervalAtMeasuredDepthFeature.cpp | 2 +- .../RicNewPerforationIntervalFeature.cpp | 2 +- ...RicWellPathExportCompletionDataFeature.cpp | 5 +- ...icWellPathImportCompletionsFileFeature.cpp | 3 +- .../ModelVisualization/RivWellPathPartMgr.cpp | 23 ++++--- .../Fishbones/CMakeLists_files.cmake | 2 + .../Fishbones/RimFishbonesCollection.cpp | 63 +++++++++++++++++++ .../Fishbones/RimFishbonesCollection.h | 49 +++++++++++++++ .../RimFishboneWellPathCollection.cpp | 20 ++---- .../RimFishboneWellPathCollection.h | 10 +-- .../ProjectDataModel/RimWellPath.cpp | 43 ++++++------- .../ProjectDataModel/RimWellPath.h | 12 ++-- .../RimWellPathCompletions.cpp | 26 ++++++++ .../ProjectDataModel/RimWellPathCompletions.h | 10 +++ 18 files changed, 218 insertions(+), 67 deletions(-) create mode 100644 ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp create mode 100644 ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp index 40191c862e..148d3a545f 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp @@ -21,6 +21,7 @@ #include "RiaApplication.h" #include "RiaLogging.h" +#include "RimFishbonesCollection.h" #include "RimFishbonesMultipleSubs.h" #include "RimWellPath.h" @@ -77,7 +78,7 @@ void RicExportFishbonesLateralsFeature::onActionTriggered(bool isChecked) size_t fishboneSubIndex = 0; QTextStream stream(&exportFile); - for (RimFishbonesMultipleSubs* fishbone : wellPath->fishbonesSubs()) + for (RimFishbonesMultipleSubs* fishbone : wellPath->fishbonesCollection()->fishbonesSubs()) { if (!fishbone->isChecked()) continue; diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp index fa10044935..3d81b0cc37 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp @@ -18,6 +18,7 @@ #include "RicNewFishbonesSubsAtMeasuredDepthFeature.h" +#include "RimFishbonesCollection.h" #include "RimFishbonesMultipleSubs.h" #include "RimProject.h" #include "RimWellPath.h" @@ -44,9 +45,9 @@ void RicNewFishbonesSubsAtMeasuredDepthFeature::onActionTriggered(bool isChecked CVF_ASSERT(wellPath); RimFishbonesMultipleSubs* obj = new RimFishbonesMultipleSubs; - wellPath->fishbonesSubs.push_back(obj); + wellPath->fishbonesCollection()->fishbonesSubs.push_back(obj); - obj->setName(QString("Fishbones Subs (%1)").arg(wellPath->fishbonesSubs.size())); + obj->setName(QString("Fishbones Subs (%1)").arg(wellPath->fishbonesCollection()->fishbonesSubs.size())); int integerValue = wellPathSelItem->m_measuredDepth; obj->setMeasuredDepthAndCount(integerValue, 24, 1); diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp index 6a70137236..26980a6d9d 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp @@ -19,6 +19,7 @@ #include "RicNewFishbonesSubsFeature.h" #include "RimFishbonesMultipleSubs.h" +#include "RimFishbonesCollection.h" #include "RimWellPath.h" #include "RiuMainWindow.h" @@ -39,8 +40,8 @@ void RicNewFishbonesSubsFeature::onActionTriggered(bool isChecked) CVF_ASSERT(wellPath); RimFishbonesMultipleSubs* obj = new RimFishbonesMultipleSubs; - obj->setName(QString("Fishbones Subs (%1)").arg(wellPath->fishbonesSubs.size())); - wellPath->fishbonesSubs.push_back(obj); + obj->setName(QString("Fishbones Subs (%1)").arg(wellPath->fishbonesCollection()->fishbonesSubs.size())); + wellPath->fishbonesCollection()->fishbonesSubs.push_back(obj); wellPath->updateConnectedEditors(); RiuMainWindow::instance()->selectAsCurrentItem(obj); diff --git a/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp b/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp index 97abed587c..1546f2c7bf 100644 --- a/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp +++ b/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp @@ -50,7 +50,7 @@ void RicEditPerforationCollectionFeature::onActionTriggered(bool isChecked) if (wellPath == nullptr) return; - RiuEditPerforationCollectionWidget dlg(nullptr, wellPath->m_perforationCollection); + RiuEditPerforationCollectionWidget dlg(nullptr, wellPath->perforationIntervalCollection()); dlg.exec(); wellPath->updateConnectedEditors(); } diff --git a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.cpp b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.cpp index 53b9440750..e29b86ff44 100644 --- a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.cpp +++ b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalAtMeasuredDepthFeature.cpp @@ -50,7 +50,7 @@ void RicNewPerforationIntervalAtMeasuredDepthFeature::onActionTriggered(bool isC int measuredDepth = wellPathSelItem->m_measuredDepth; perforationInterval->setStartAndEndMD(measuredDepth, measuredDepth + 50); - wellPath->m_perforationCollection()->appendPerforation(perforationInterval); + wellPath->perforationIntervalCollection()->appendPerforation(perforationInterval); RimWellPathCollection* wellPathCollection = nullptr; wellPath->firstAncestorOrThisOfTypeAsserted(wellPathCollection); diff --git a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp index 2682a634bc..ecac031874 100644 --- a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp +++ b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp @@ -52,7 +52,7 @@ void RicNewPerforationIntervalFeature::onActionTriggered(bool isChecked) RimPerforationInterval* perforationInterval = new RimPerforationInterval; - wellPath->m_perforationCollection()->appendPerforation(perforationInterval); + wellPath->perforationIntervalCollection()->appendPerforation(perforationInterval); RimWellPathCollection* wellPathCollection = nullptr; wellPath->firstAncestorOrThisOfType(wellPathCollection); diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index a04197f861..d637ededbc 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -24,6 +24,7 @@ #include "RimProject.h" #include "RimWellPath.h" #include "RimFishbonesMultipleSubs.h" +#include "RimFishbonesCollection.h" #include "RimExportCompletionDataSettings.h" #include "RiuMainWindow.h" @@ -161,7 +162,7 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat formatter.keyword("COMPDAT"); formatter.header(header); - for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesSubs) + for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesCollection()->fishbonesSubs()) { for (size_t subIndex = 0; subIndex < subs->locationOfSubs().size(); ++subIndex) { @@ -605,7 +606,7 @@ void RicWellPathExportCompletionDataFeature::filterIntersections(std::vector RicWellPathExportCompletionDataFeature::findWellSegmentLocations(RimWellPath* wellPath) { std::vector wellSegmentLocations; - for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesSubs) + for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesCollection()->fishbonesSubs()) { for (size_t subIndex = 0; subIndex < subs->locationOfSubs().size(); ++subIndex) { diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp index 93153eb424..ade523098e 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp @@ -24,6 +24,7 @@ #include "RimProject.h" #include "RimWellPath.h" #include "RimFishboneWellPathCollection.h" +#include "RimFishbonesCollection.h" #include "RiuMainWindow.h" @@ -69,7 +70,7 @@ void RicWellPathImportCompletionsFileFeature::onActionTriggered(bool isChecked) // Remember the path to next time app->setLastUsedDialogDirectory("WELLPATH_DIR", QFileInfo(wellPathFilePaths.last()).absolutePath()); - objects[0]->m_completionCollection()->importCompletionsFromFile(wellPathFilePaths); + objects[0]->fishbonesCollection()->wellPathCollection()->importCompletionsFromFile(wellPathFilePaths); if (app->project()) { diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index d44d0d70ce..6156caf17a 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -29,6 +29,7 @@ #include "RimWellPath.h" #include "RimWellPathCollection.h" #include "RimFishboneWellPath.h" +#include "RimFishbonesCollection.h" #include "RimFishboneWellPathCollection.h" #include "RimPerforationInterval.h" #include "RimPerforationCollection.h" @@ -99,11 +100,11 @@ void RivWellPathPartMgr::appendFishbonesPartsToModel(cvf::ModelBasicList* model, // This concept is taken from RivReservoirSimWellsPartMgr, and is required to be able to have // separate part managers for each view - if (m_fishbonesPartMgrs.size() != m_rimWellPath->fishbonesSubs().size()) + if (m_fishbonesPartMgrs.size() != m_rimWellPath->fishbonesCollection()->fishbonesSubs.size()) { m_fishbonesPartMgrs.clear(); - for (auto rimFishboneSubs : m_rimWellPath->fishbonesSubs()) + for (auto rimFishboneSubs : m_rimWellPath->fishbonesCollection()->fishbonesSubs()) { m_fishbonesPartMgrs.push_back(new RivFishbonesSubsPartMgr(rimFishboneSubs)); } @@ -120,20 +121,22 @@ void RivWellPathPartMgr::appendFishbonesPartsToModel(cvf::ModelBasicList* model, //-------------------------------------------------------------------------------------------------- void RivWellPathPartMgr::appendCompletionsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize) { - if (!m_rimWellPath || !m_rimWellPath->m_completionCollection->isChecked()) return; + if (!m_rimWellPath || !m_rimWellPath->fishbonesCollection()->wellPathCollection()->isChecked()) return; RivPipeGeometryGenerator geoGenerator; - for (RimFishboneWellPath* completion : m_rimWellPath->m_completionCollection()->m_completions()) + std::vector fishbonesWellPaths; + m_rimWellPath->descendantsIncludingThisOfType(fishbonesWellPaths); + for (RimFishboneWellPath* fbWellPath : fishbonesWellPaths) { - if (!completion->isChecked()) continue; + if (!fbWellPath->isChecked()) continue; std::vector displayCoords; - for (auto lateralDomainCoords : completion->coordinates()) + for (auto lateralDomainCoords : fbWellPath->coordinates()) { displayCoords.push_back(displayCoordTransform->transformToDisplayCoord(lateralDomainCoords)); } - cvf::ref objectSourceInfo = new RivObjectSourceInfo(completion); + cvf::ref objectSourceInfo = new RivObjectSourceInfo(fbWellPath); cvf::Collection parts; geoGenerator.cylinderWithCenterLineParts(&parts, displayCoords, m_rimWellPath->wellPathColor(), m_rimWellPath->combinedScaleFactor() * characteristicCellSize * 0.5); @@ -151,7 +154,7 @@ void RivWellPathPartMgr::appendCompletionsToModel(cvf::ModelBasicList* model, ca //-------------------------------------------------------------------------------------------------- void RivWellPathPartMgr::appendPerforationsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize) { - if (!m_rimWellPath || !m_rimWellPath->m_perforationCollection->isChecked()) return; + if (!m_rimWellPath || !m_rimWellPath->perforationIntervalCollection()->isChecked()) return; RimWellPathCollection* wellPathCollection = this->wellPathCollection(); if (!wellPathCollection) return; @@ -166,7 +169,9 @@ void RivWellPathPartMgr::appendPerforationsToModel(cvf::ModelBasicList* model, c double perforationRadius = wellPathRadius * 1.1; RivPipeGeometryGenerator geoGenerator; - for (RimPerforationInterval* perforation : m_rimWellPath->m_perforationCollection->m_perforations()) + std::vector perforations; + m_rimWellPath->descendantsIncludingThisOfType(perforations); + for (RimPerforationInterval* perforation : perforations) { if (!perforation->isChecked()) continue; if (perforation->startMD() > perforation->endMD()) continue; diff --git a/ApplicationCode/ProjectDataModel/Fishbones/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/Fishbones/CMakeLists_files.cmake index 3487f95ce0..85c55ab09f 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/Fishbones/CMakeLists_files.cmake @@ -6,10 +6,12 @@ endif() set (SOURCE_GROUP_HEADER_FILES ${CEE_CURRENT_LIST_DIR}RimFishbonesMultipleSubs.h +${CEE_CURRENT_LIST_DIR}RimFishbonesCollection.h ) set (SOURCE_GROUP_SOURCE_FILES ${CEE_CURRENT_LIST_DIR}RimFishbonesMultipleSubs.cpp +${CEE_CURRENT_LIST_DIR}RimFishbonesCollection.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp new file mode 100644 index 0000000000..fac550c28c --- /dev/null +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp @@ -0,0 +1,63 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimFishbonesCollection.h" + +#include "RimEclipseWell.h" +#include "RimPerforationInterval.h" +#include "RimView.h" +#include "RimProject.h" + +#include "RigWellPath.h" + +#include "RifWellPathImporter.h" + +#include "RiuMainWindow.h" +#include "RimFishboneWellPathCollection.h" +#include "RimFishbonesMultipleSubs.h" + + +CAF_PDM_SOURCE_INIT(RimFishbonesCollection, "FishbonesCollection"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFishbonesCollection::RimFishbonesCollection() +{ + CAF_PDM_InitObject("Fishbones", ":/Folder.png", "", ""); + + m_name.uiCapability()->setUiHidden(true); + m_name = "Fishbones"; + + CAF_PDM_InitFieldNoDefault(&fishbonesSubs, "FishbonesSubs", "fishbonesSubs", "", "", ""); + + fishbonesSubs.uiCapability()->setUiHidden(true); + + CAF_PDM_InitFieldNoDefault(&m_wellPathCollection, "WellPathCollection", "Well Paths", "", "", ""); + m_wellPathCollection = new RimFishboneWellPathCollection; + m_wellPathCollection.uiCapability()->setUiHidden(true); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFishboneWellPathCollection* RimFishbonesCollection::wellPathCollection() const +{ + return m_wellPathCollection(); +} + diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h new file mode 100644 index 0000000000..7de17d9bd4 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h @@ -0,0 +1,49 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimCheckableNamedObject.h" + +#include "cafPdmObject.h" +#include "cafPdmChildArrayField.h" +#include "cafPdmField.h" +#include "cafPdmChildField.h" + +class RimFishbonesMultipleSubs; +class RimFishboneWellPathCollection; + +//================================================================================================== +// +// +// +//================================================================================================== +class RimFishbonesCollection : public RimCheckableNamedObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimFishbonesCollection(); + + RimFishboneWellPathCollection* wellPathCollection() const; + + caf::PdmChildArrayField fishbonesSubs; + +private: + caf::PdmChildField m_wellPathCollection; +}; diff --git a/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.cpp b/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.cpp index 62896cd987..db73648f46 100644 --- a/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.cpp @@ -41,18 +41,10 @@ RimFishboneWellPathCollection::RimFishboneWellPathCollection() CAF_PDM_InitObject("WellPathCompletions", ":/WellCollection.png", "", ""); m_name.uiCapability()->setUiHidden(true); - m_name = "Completions"; + m_name = "Well Paths"; - CAF_PDM_InitFieldNoDefault(&m_completions, "Completions", "WellPathCompletions", "", "", ""); - m_completions.uiCapability()->setUiHidden(true); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimFishboneWellPathCollection::~RimFishboneWellPathCollection() -{ - m_completions.deleteAllChildObjects(); + CAF_PDM_InitFieldNoDefault(&m_wellPaths, "WellPaths", "Well Paths", "", "", ""); + m_wellPaths.uiCapability()->setUiHidden(true); } //-------------------------------------------------------------------------------------------------- @@ -70,7 +62,7 @@ void RimFishboneWellPathCollection::fieldChangedByUi(const caf::PdmFieldHandle* //-------------------------------------------------------------------------------------------------- void RimFishboneWellPathCollection::appendCompletion(RimFishboneWellPath* completion) { - m_completions.push_back(completion); + m_wellPaths.push_back(completion); updateConnectedEditors(); RiuMainWindow::instance()->selectAsCurrentItem(completion); @@ -82,13 +74,13 @@ void RimFishboneWellPathCollection::appendCompletion(RimFishboneWellPath* comple rimView->scheduleCreateDisplayModelAndRedraw(); } - uiCapability()->setUiHidden(!m_completions.empty()); + uiCapability()->setUiHidden(!m_wellPaths.empty()); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFishboneWellPathCollection::importCompletionsFromFile(const QList filePaths) +void RimFishboneWellPathCollection::importCompletionsFromFile(const QStringList& filePaths) { RifWellPathImporter wellPathImporter; diff --git a/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.h b/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.h index fa18876b32..ae19205905 100644 --- a/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFishboneWellPathCollection.h @@ -37,12 +37,14 @@ class RimFishboneWellPathCollection : public RimCheckableNamedObject public: RimFishboneWellPathCollection(); - ~RimFishboneWellPathCollection(); - void appendCompletion(RimFishboneWellPath* completion); - void importCompletionsFromFile(const QList filePaths); + void importCompletionsFromFile(const QStringList& filePaths); void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); - caf::PdmChildArrayField m_completions; +private: + void appendCompletion(RimFishboneWellPath* completion); + +private: + caf::PdmChildArrayField m_wellPaths; }; diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index cc973bd500..9e9ab26e2b 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -30,8 +30,6 @@ #include "RimWellLogFile.h" #include "RimWellLogPlotCollection.h" #include "RimWellPathCollection.h" -#include "RimFishboneWellPathCollection.h" -#include "RimPerforationCollection.h" #include "RimFishbonesMultipleSubs.h" #include "RimWellPathCompletions.h" @@ -105,14 +103,6 @@ RimWellPath::RimWellPath() CAF_PDM_InitField(&wellPathRadiusScaleFactor, "WellPathRadiusScale", 1.0, "Well path radius scale", "", "", ""); CAF_PDM_InitField(&wellPathColor, "WellPathColor", cvf::Color3f(0.999f, 0.333f, 0.999f), "Well path color", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_completionCollection, "Completions_to_be_moved", "Completions", "", "", ""); - m_completionCollection = new RimFishboneWellPathCollection; - m_completionCollection.uiCapability()->setUiHidden(true); - - CAF_PDM_InitFieldNoDefault(&m_perforationCollection, "Perforations", "Perforations", "", "", ""); - m_perforationCollection = new RimPerforationCollection; - m_perforationCollection.uiCapability()->setUiHidden(true); - CAF_PDM_InitFieldNoDefault(&m_completions, "Completions", "Completions", "", "", ""); m_completions = new RimWellPathCompletions; m_completions.uiCapability()->setUiTreeHidden(true); @@ -120,9 +110,6 @@ RimWellPath::RimWellPath() CAF_PDM_InitFieldNoDefault(&m_wellLogFile, "WellLogFile", "Well Log File", "", "", ""); m_wellLogFile.uiCapability()->setUiHidden(true); - CAF_PDM_InitFieldNoDefault(&fishbonesSubs, "FishbonesSubs", "fishbonesSubs", "", "", ""); - fishbonesSubs.uiCapability()->setUiHidden(true); - m_wellPath = NULL; } @@ -174,6 +161,26 @@ void RimWellPath::setSurveyType(QString surveyType) wellPathColor = cvf::Color3f(0.0f, 0.333f, 0.999f); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFishbonesCollection* RimWellPath::fishbonesCollection() +{ + CVF_ASSERT(m_completions); + + return m_completions->fishbonesCollection(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPerforationCollection* RimWellPath::perforationIntervalCollection() +{ + CVF_ASSERT(m_completions); + + return m_completions->perforationCollection(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -296,16 +303,6 @@ void RimWellPath::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, Q uiTreeOrdering.skipRemainingChildren(true); uiTreeOrdering.add(&m_wellLogFile); uiTreeOrdering.add(&m_completions); - - if (!m_completionCollection->m_completions.empty()) - { - uiTreeOrdering.add(&m_completionCollection); - } - if (!m_perforationCollection->m_perforations.empty()) - { - uiTreeOrdering.add(&m_perforationCollection); - } - uiTreeOrdering.add(&fishbonesSubs); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index b3777d2c5a..239c3f800a 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -39,7 +39,7 @@ class RimWellLogFile; class RimFishboneWellPathCollection; class RivWellPathPartMgr; -class RimFishbonesMultipleSubs; +class RimFishbonesCollection; class RimPerforationCollection; class RimWellPathCompletions; @@ -74,13 +74,11 @@ public: caf::PdmField wellPathRadiusScaleFactor; caf::PdmChildField m_wellLogFile; - caf::PdmChildField m_completionCollection; - caf::PdmChildField m_perforationCollection; - caf::PdmChildField m_completions; + + RimFishbonesCollection* fishbonesCollection(); + RimPerforationCollection* perforationIntervalCollection(); RigWellPath* wellPathGeometry(); - caf::PdmChildArrayField fishbonesSubs; - RivWellPathPartMgr* partMgr(); bool readWellPathFile(QString * errorMessage, RifWellPathImporter* wellPathImporter); @@ -110,6 +108,8 @@ private: caf::PdmField m_surveyType; caf::PdmField m_datumElevation; + + caf::PdmChildField m_completions; cvf::ref m_wellPath; cvf::ref m_wellPathPartMgr; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp index 2631cc3846..8f4f3e65bd 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp @@ -18,6 +18,9 @@ #include "RimWellPathCompletions.h" +#include "RimFishbonesCollection.h" +#include "RimPerforationCollection.h" + CAF_PDM_SOURCE_INIT(RimWellPathCompletions, "WellPathCompletions"); @@ -27,6 +30,29 @@ CAF_PDM_SOURCE_INIT(RimWellPathCompletions, "WellPathCompletions"); RimWellPathCompletions::RimWellPathCompletions() { CAF_PDM_InitObject("WellPathCompletions", ":/WellCollection.png", "", ""); + + CAF_PDM_InitFieldNoDefault(&m_perforationCollection, "Perforations", "Perforations", "", "", ""); + m_perforationCollection = new RimPerforationCollection; + m_perforationCollection.uiCapability()->setUiHidden(true); + + CAF_PDM_InitFieldNoDefault(&m_fishbonesCollection, "Fishbones", "Fishbones", "", "", ""); + m_fishbonesCollection = new RimFishbonesCollection; + m_fishbonesCollection.uiCapability()->setUiHidden(true); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFishbonesCollection* RimWellPathCompletions::fishbonesCollection() const +{ + return m_fishbonesCollection; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPerforationCollection* RimWellPathCompletions::perforationCollection() const +{ + return m_perforationCollection; +} diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletions.h b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.h index 18f1764fa8..3a26299cd7 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletions.h +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.h @@ -19,7 +19,10 @@ #pragma once #include "cafPdmObject.h" +#include "cafPdmChildField.h" +class RimFishbonesCollection; +class RimPerforationCollection; //================================================================================================== /// @@ -31,4 +34,11 @@ class RimWellPathCompletions : public caf::PdmObject public: RimWellPathCompletions(); + + RimFishbonesCollection* fishbonesCollection() const; + RimPerforationCollection* perforationCollection() const; + +private: + caf::PdmChildField m_fishbonesCollection; + caf::PdmChildField m_perforationCollection; }; From ecddaffeb44e2e0d75095fff1dc2f433d3381e22 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 20 May 2017 14:31:25 +0200 Subject: [PATCH 145/157] #1495 Move features from well path to sub objects --- .../RicExportFishbonesLateralsFeature.cpp | 18 +++++---- .../RicExportFishbonesLateralsFeature.h | 4 +- ...icWellPathImportCompletionsFileFeature.cpp | 38 ++++++++++++------- .../RicWellPathImportCompletionsFileFeature.h | 8 +++- .../Fishbones/RimFishbonesCollection.cpp | 10 ++--- .../Fishbones/RimFishbonesCollection.h | 2 - .../RimWellPathCompletions.cpp | 6 +++ 7 files changed, 53 insertions(+), 33 deletions(-) diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp index 148d3a545f..7fd77802ce 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.cpp @@ -41,7 +41,11 @@ CAF_CMD_SOURCE_INIT(RicExportFishbonesLateralsFeature, "RicExportFishbonesLatera //-------------------------------------------------------------------------------------------------- void RicExportFishbonesLateralsFeature::onActionTriggered(bool isChecked) { - RimWellPath* wellPath = selectedWellPath(); + RimFishbonesCollection* fishbonesCollection = selectedFishbonesCollection(); + CVF_ASSERT(fishbonesCollection); + + RimWellPath* wellPath = nullptr; + fishbonesCollection->firstAncestorOrThisOfType(wellPath); CVF_ASSERT(wellPath); RiaApplication* app = RiaApplication::instance(); @@ -78,7 +82,7 @@ void RicExportFishbonesLateralsFeature::onActionTriggered(bool isChecked) size_t fishboneSubIndex = 0; QTextStream stream(&exportFile); - for (RimFishbonesMultipleSubs* fishbone : wellPath->fishbonesCollection()->fishbonesSubs()) + for (RimFishbonesMultipleSubs* fishbone : fishbonesCollection->fishbonesSubs()) { if (!fishbone->isChecked()) continue; @@ -126,19 +130,19 @@ QString RicExportFishbonesLateralsFeature::formatNumber(double val, int numberOf //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPath* RicExportFishbonesLateralsFeature::selectedWellPath() +RimFishbonesCollection* RicExportFishbonesLateralsFeature::selectedFishbonesCollection() { - RimWellPath* wellPath = nullptr; + RimFishbonesCollection* objToFind = nullptr; caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem(); caf::PdmObjectHandle* objHandle = dynamic_cast(pdmUiItem); if (objHandle) { - objHandle->firstAncestorOrThisOfType(wellPath); + objHandle->firstAncestorOrThisOfType(objToFind); } - return wellPath; + return objToFind; } //-------------------------------------------------------------------------------------------------- @@ -155,7 +159,7 @@ void RicExportFishbonesLateralsFeature::setupActionLook(QAction* actionToSetup) //-------------------------------------------------------------------------------------------------- bool RicExportFishbonesLateralsFeature::isCommandEnabled() { - if (selectedWellPath()) + if (selectedFishbonesCollection()) { return true; } diff --git a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h index 1fa1472b84..8422c11694 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h +++ b/ApplicationCode/Commands/FishbonesCommands/RicExportFishbonesLateralsFeature.h @@ -20,7 +20,7 @@ #include "cafCmdFeature.h" -class RimWellPath; +class RimFishbonesCollection; //================================================================================================== /// @@ -36,5 +36,5 @@ protected: private: static QString formatNumber(double val, int numberOfDecimals); - static RimWellPath* selectedWellPath(); + static RimFishbonesCollection* selectedFishbonesCollection(); }; diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp index ade523098e..761e871ec6 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -21,10 +20,11 @@ #include "RiaApplication.h" -#include "RimProject.h" -#include "RimWellPath.h" #include "RimFishboneWellPathCollection.h" #include "RimFishbonesCollection.h" +#include "RimProject.h" +#include "RimWellPath.h" +#include "RimWellPathCompletions.h" #include "RiuMainWindow.h" @@ -40,10 +40,8 @@ CAF_CMD_SOURCE_INIT(RicWellPathImportCompletionsFileFeature, "RicWellPathImportC //-------------------------------------------------------------------------------------------------- bool RicWellPathImportCompletionsFileFeature::isCommandEnabled() { - std::vector objects; - caf::SelectionManager::instance()->objectsByType(&objects); - - if (objects.size() == 1) { + if (RicWellPathImportCompletionsFileFeature::selectedWellPathCompletions() != nullptr) + { return true; } @@ -55,10 +53,8 @@ bool RicWellPathImportCompletionsFileFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicWellPathImportCompletionsFileFeature::onActionTriggered(bool isChecked) { - std::vector objects; - caf::SelectionManager::instance()->objectsByType(&objects); - - CVF_ASSERT(objects.size() == 1); + RimWellPathCompletions* wellPathCompletions = RicWellPathImportCompletionsFileFeature::selectedWellPathCompletions(); + CVF_ASSERT(wellPathCompletions); // Open dialog box to select well path files RiaApplication* app = RiaApplication::instance(); @@ -70,7 +66,7 @@ void RicWellPathImportCompletionsFileFeature::onActionTriggered(bool isChecked) // Remember the path to next time app->setLastUsedDialogDirectory("WELLPATH_DIR", QFileInfo(wellPathFilePaths.last()).absolutePath()); - objects[0]->fishbonesCollection()->wellPathCollection()->importCompletionsFromFile(wellPathFilePaths); + wellPathCompletions->fishbonesCollection()->wellPathCollection()->importCompletionsFromFile(wellPathFilePaths); if (app->project()) { @@ -86,3 +82,19 @@ void RicWellPathImportCompletionsFileFeature::setupActionLook(QAction* actionToS actionToSetup->setText("Import Completions from File"); actionToSetup->setIcon(QIcon(":/Well.png")); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPathCompletions* RicWellPathImportCompletionsFileFeature::selectedWellPathCompletions() +{ + std::vector objects; + caf::SelectionManager::instance()->objectsByType(&objects); + + if (objects.size() > 0) + { + return objects[0]; + } + + return nullptr; +} diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h index dc26985bb0..7755260aae 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS +// Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -21,6 +20,8 @@ #include "cafCmdFeature.h" +class RimWellPathCompletions; + //================================================================================================== /// //================================================================================================== @@ -33,5 +34,8 @@ protected: virtual bool isCommandEnabled() override; virtual void onActionTriggered( bool isChecked ) override; virtual void setupActionLook( QAction* actionToSetup ) override; + +private: + static RimWellPathCompletions* selectedWellPathCompletions(); }; diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp index fac550c28c..f5c6c77b52 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp @@ -18,16 +18,10 @@ #include "RimFishbonesCollection.h" -#include "RimEclipseWell.h" -#include "RimPerforationInterval.h" -#include "RimView.h" -#include "RimProject.h" +#include "RifWellPathImporter.h" #include "RigWellPath.h" -#include "RifWellPathImporter.h" - -#include "RiuMainWindow.h" #include "RimFishboneWellPathCollection.h" #include "RimFishbonesMultipleSubs.h" @@ -58,6 +52,8 @@ RimFishbonesCollection::RimFishbonesCollection() //-------------------------------------------------------------------------------------------------- RimFishboneWellPathCollection* RimFishbonesCollection::wellPathCollection() const { + CVF_ASSERT(m_wellPathCollection); + return m_wellPathCollection(); } diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h index 7de17d9bd4..dbb8b8b58c 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h @@ -20,9 +20,7 @@ #include "RimCheckableNamedObject.h" -#include "cafPdmObject.h" #include "cafPdmChildArrayField.h" -#include "cafPdmField.h" #include "cafPdmChildField.h" class RimFishbonesMultipleSubs; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp index 8f4f3e65bd..de60a4a1ea 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp @@ -21,6 +21,8 @@ #include "RimFishbonesCollection.h" #include "RimPerforationCollection.h" +#include "cvfAssert.h" + CAF_PDM_SOURCE_INIT(RimWellPathCompletions, "WellPathCompletions"); @@ -45,6 +47,8 @@ RimWellPathCompletions::RimWellPathCompletions() //-------------------------------------------------------------------------------------------------- RimFishbonesCollection* RimWellPathCompletions::fishbonesCollection() const { + CVF_ASSERT(m_fishbonesCollection); + return m_fishbonesCollection; } @@ -53,6 +57,8 @@ RimFishbonesCollection* RimWellPathCompletions::fishbonesCollection() const //-------------------------------------------------------------------------------------------------- RimPerforationCollection* RimWellPathCompletions::perforationCollection() const { + CVF_ASSERT(m_perforationCollection); + return m_perforationCollection; } From 123b40480988c7a93174518eebf614d1c0fb6480 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 20 May 2017 14:47:13 +0200 Subject: [PATCH 146/157] #1495 Move features from well path to sub objects --- .../RicNewFishbonesSubsFeature.cpp | 21 +++++++++---------- .../RicNewFishbonesSubsFeature.h | 4 ++-- .../RicEditPerforationCollectionFeature.cpp | 20 +++++++++--------- .../RicEditPerforationCollectionFeature.h | 4 ++-- .../RicNewPerforationIntervalFeature.cpp | 19 ++++++++--------- .../RicNewPerforationIntervalFeature.h | 4 ++-- 6 files changed, 35 insertions(+), 37 deletions(-) diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp index 26980a6d9d..5ec3dc0e9f 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp @@ -20,7 +20,6 @@ #include "RimFishbonesMultipleSubs.h" #include "RimFishbonesCollection.h" -#include "RimWellPath.h" #include "RiuMainWindow.h" @@ -36,33 +35,33 @@ CAF_CMD_SOURCE_INIT(RicNewFishbonesSubsFeature, "RicNewFishbonesSubsFeature"); //-------------------------------------------------------------------------------------------------- void RicNewFishbonesSubsFeature::onActionTriggered(bool isChecked) { - RimWellPath* wellPath = selectedWellPath(); - CVF_ASSERT(wellPath); + RimFishbonesCollection* fishbonesCollection = selectedFishbonesCollection(); + CVF_ASSERT(fishbonesCollection); RimFishbonesMultipleSubs* obj = new RimFishbonesMultipleSubs; - obj->setName(QString("Fishbones Subs (%1)").arg(wellPath->fishbonesCollection()->fishbonesSubs.size())); - wellPath->fishbonesCollection()->fishbonesSubs.push_back(obj); + obj->setName(QString("Fishbones Subs (%1)").arg(fishbonesCollection->fishbonesSubs.size())); + fishbonesCollection->fishbonesSubs.push_back(obj); - wellPath->updateConnectedEditors(); + fishbonesCollection->updateConnectedEditors(); RiuMainWindow::instance()->selectAsCurrentItem(obj); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPath* RicNewFishbonesSubsFeature::selectedWellPath() +RimFishbonesCollection* RicNewFishbonesSubsFeature::selectedFishbonesCollection() { - RimWellPath* wellPath = nullptr; + RimFishbonesCollection* objToFind = nullptr; caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem(); caf::PdmObjectHandle* objHandle = dynamic_cast(pdmUiItem); if (objHandle) { - objHandle->firstAncestorOrThisOfType(wellPath); + objHandle->firstAncestorOrThisOfType(objToFind); } - return wellPath; + return objToFind; } //-------------------------------------------------------------------------------------------------- @@ -79,7 +78,7 @@ void RicNewFishbonesSubsFeature::setupActionLook(QAction* actionToSetup) //-------------------------------------------------------------------------------------------------- bool RicNewFishbonesSubsFeature::isCommandEnabled() { - if (selectedWellPath()) + if (selectedFishbonesCollection()) { return true; } diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h index b0aff04b67..4579990dea 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h @@ -20,7 +20,7 @@ #include "cafCmdFeature.h" -class RimWellPath; +class RimFishbonesCollection; //================================================================================================== /// @@ -35,5 +35,5 @@ protected: virtual bool isCommandEnabled() override; private: - static RimWellPath* selectedWellPath(); + static RimFishbonesCollection* selectedFishbonesCollection(); }; diff --git a/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp b/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp index 1546f2c7bf..018b3f4ffb 100644 --- a/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp +++ b/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.cpp @@ -21,7 +21,6 @@ #include "RiuEditPerforationCollectionWidget.h" #include "RimPerforationCollection.h" -#include "RimWellPath.h" #include "cafSelectionManager.h" @@ -36,7 +35,7 @@ CAF_CMD_SOURCE_INIT(RicEditPerforationCollectionFeature, "RicEditPerforationColl //-------------------------------------------------------------------------------------------------- bool RicEditPerforationCollectionFeature::isCommandEnabled() { - return selectedWellPath() != nullptr; + return selectedPerforationCollection() != nullptr; } //-------------------------------------------------------------------------------------------------- @@ -46,13 +45,14 @@ void RicEditPerforationCollectionFeature::onActionTriggered(bool isChecked) { this->disableModelChangeContribution(); - RimWellPath* wellPath = selectedWellPath(); + RimPerforationCollection* perforationCollection = selectedPerforationCollection(); - if (wellPath == nullptr) return; + if (perforationCollection == nullptr) return; - RiuEditPerforationCollectionWidget dlg(nullptr, wellPath->perforationIntervalCollection()); + RiuEditPerforationCollectionWidget dlg(nullptr, perforationCollection); dlg.exec(); - wellPath->updateConnectedEditors(); + + perforationCollection->updateConnectedEditors(); } //-------------------------------------------------------------------------------------------------- @@ -66,17 +66,17 @@ void RicEditPerforationCollectionFeature::setupActionLook(QAction* actionToSetup //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPath* RicEditPerforationCollectionFeature::selectedWellPath() const +RimPerforationCollection* RicEditPerforationCollectionFeature::selectedPerforationCollection() { - RimWellPath* wellPath = nullptr; + RimPerforationCollection* objToFind = nullptr; caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem(); caf::PdmObjectHandle* objHandle = dynamic_cast(pdmUiItem); if (objHandle) { - objHandle->firstAncestorOrThisOfType(wellPath); + objHandle->firstAncestorOrThisOfType(objToFind); } - return wellPath; + return objToFind; } diff --git a/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.h b/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.h index b0deea2c70..170fa535b9 100644 --- a/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.h +++ b/ApplicationCode/Commands/PerforationCommands/RicEditPerforationCollectionFeature.h @@ -20,7 +20,7 @@ #include "cafCmdFeature.h" -class RimWellPath; +class RimPerforationCollection; //================================================================================================== /// @@ -35,6 +35,6 @@ protected: virtual void setupActionLook(QAction* actionToSetup) override; private: - RimWellPath* selectedWellPath() const; + static RimPerforationCollection* selectedPerforationCollection(); }; diff --git a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp index ecac031874..bbf4a6b184 100644 --- a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp +++ b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.cpp @@ -23,7 +23,6 @@ #include "RimPerforationInterval.h" #include "RimPerforationCollection.h" -#include "RimWellPath.h" #include "RimWellPathCollection.h" #include "cafSelectionManager.h" @@ -39,7 +38,7 @@ CAF_CMD_SOURCE_INIT(RicNewPerforationIntervalFeature, "RicNewPerforationInterval //-------------------------------------------------------------------------------------------------- bool RicNewPerforationIntervalFeature::isCommandEnabled() { - return selectedWellPath() != nullptr; + return selectedPerforationCollection() != nullptr; } //-------------------------------------------------------------------------------------------------- @@ -47,15 +46,15 @@ bool RicNewPerforationIntervalFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicNewPerforationIntervalFeature::onActionTriggered(bool isChecked) { - RimWellPath* wellPath = selectedWellPath(); - if (wellPath == nullptr) return; + RimPerforationCollection* perforationCollection = selectedPerforationCollection(); + if (perforationCollection == nullptr) return; RimPerforationInterval* perforationInterval = new RimPerforationInterval; - wellPath->perforationIntervalCollection()->appendPerforation(perforationInterval); + perforationCollection->appendPerforation(perforationInterval); RimWellPathCollection* wellPathCollection = nullptr; - wellPath->firstAncestorOrThisOfType(wellPathCollection); + perforationCollection->firstAncestorOrThisOfType(wellPathCollection); if (!wellPathCollection) return; wellPathCollection->uiCapability()->updateConnectedEditors(); @@ -75,17 +74,17 @@ void RicNewPerforationIntervalFeature::setupActionLook(QAction* actionToSetup) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPath * RicNewPerforationIntervalFeature::selectedWellPath() +RimPerforationCollection* RicNewPerforationIntervalFeature::selectedPerforationCollection() { - RimWellPath* wellPath = nullptr; + RimPerforationCollection* objToFind = nullptr; caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem(); caf::PdmObjectHandle* objHandle = dynamic_cast(pdmUiItem); if (objHandle) { - objHandle->firstAncestorOrThisOfType(wellPath); + objHandle->firstAncestorOrThisOfType(objToFind); } - return wellPath; + return objToFind; } diff --git a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h index 9c72ebaafe..162ad9c390 100644 --- a/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h +++ b/ApplicationCode/Commands/PerforationCommands/RicNewPerforationIntervalFeature.h @@ -21,7 +21,7 @@ #include "cafCmdFeature.h" -class RimWellPath; +class RimPerforationCollection; //================================================================================================== /// @@ -37,5 +37,5 @@ protected: virtual void setupActionLook( QAction* actionToSetup ) override; private: - RimWellPath* selectedWellPath(); + RimPerforationCollection* selectedPerforationCollection(); }; From 6e78c0b2cc370599924b66ba2908d3bea74b0303 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 20 May 2017 20:10:03 +0200 Subject: [PATCH 147/157] Fix computation of measured depth when picking in 3D --- ApplicationCode/UserInterface/RiuViewerCommands.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuViewerCommands.cpp b/ApplicationCode/UserInterface/RiuViewerCommands.cpp index b75b865a2b..4b047e068f 100644 --- a/ApplicationCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationCode/UserInterface/RiuViewerCommands.cpp @@ -71,6 +71,7 @@ #include "cafCmdExecCommandManager.h" #include "cafCmdFeatureManager.h" +#include "cafDisplayCoordTransform.h" #include "cafSelectionManager.h" #include "cvfDrawableGeo.h" @@ -164,14 +165,8 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event) RimView* activeView = RiaApplication::instance()->activeReservoirView(); CVF_ASSERT(activeView); - RimCase* rimCase = NULL; - activeView->firstAncestorOrThisOfType(rimCase); - if (rimCase) - { - displayModelOffset = rimCase->displayModelOffset(); - } - - m_currentPickPositionInDomainCoords = localIntersectionPoint + displayModelOffset; + cvf::ref transForm = activeView->displayCoordTransform(); + m_currentPickPositionInDomainCoords = transForm->transformToDomainCoord(globalIntersectionPoint); } if (firstHitPart && firstPartTriangleIndex != cvf::UNDEFINED_UINT) @@ -847,7 +842,6 @@ void RiuViewerCommands::ijkFromCellIndex(size_t gridIdx, size_t cellIndex, size RimEclipseView* eclipseView = dynamic_cast(m_reservoirView.p()); RimGeoMechView* geomView = dynamic_cast(m_reservoirView.p()); - if (eclipseView && eclipseView->eclipseCase()) { eclipseView->eclipseCase()->eclipseCaseData()->grid(gridIdx)->ijkFromCellIndex(cellIndex, i, j, k); From 1acc54d059462d384667541aa0cf78779ece5b41 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 20 May 2017 20:21:19 +0200 Subject: [PATCH 148/157] #1474 Ask user to automatically set scale to 1 for fishbones --- ...NewFishbonesSubsAtMeasuredDepthFeature.cpp | 4 ++ .../RicNewFishbonesSubsFeature.cpp | 66 ++++++++++++++++++- .../RicNewFishbonesSubsFeature.h | 5 +- .../RimWellPathCompletions.cpp | 2 +- 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp index 3d81b0cc37..f5813e7377 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsAtMeasuredDepthFeature.cpp @@ -18,6 +18,8 @@ #include "RicNewFishbonesSubsAtMeasuredDepthFeature.h" +#include "RicNewFishbonesSubsFeature.h" + #include "RimFishbonesCollection.h" #include "RimFishbonesMultipleSubs.h" #include "RimProject.h" @@ -51,6 +53,8 @@ void RicNewFishbonesSubsAtMeasuredDepthFeature::onActionTriggered(bool isChecked int integerValue = wellPathSelItem->m_measuredDepth; obj->setMeasuredDepthAndCount(integerValue, 24, 1); + RicNewFishbonesSubsFeature::askUserToSetUsefulScaling(wellPath->fishbonesCollection()); + wellPath->updateConnectedEditors(); RiuMainWindow::instance()->selectAsCurrentItem(obj); diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp index 5ec3dc0e9f..2eb4748bec 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.cpp @@ -18,14 +18,20 @@ #include "RicNewFishbonesSubsFeature.h" -#include "RimFishbonesMultipleSubs.h" +#include "RiaApplication.h" + +#include "RimFishboneWellPathCollection.h" #include "RimFishbonesCollection.h" +#include "RimFishbonesMultipleSubs.h" +#include "RimView.h" +#include "RimWellPathCollection.h" #include "RiuMainWindow.h" #include "cafSelectionManager.h" #include +#include CAF_CMD_SOURCE_INIT(RicNewFishbonesSubsFeature, "RicNewFishbonesSubsFeature"); @@ -42,6 +48,8 @@ void RicNewFishbonesSubsFeature::onActionTriggered(bool isChecked) obj->setName(QString("Fishbones Subs (%1)").arg(fishbonesCollection->fishbonesSubs.size())); fishbonesCollection->fishbonesSubs.push_back(obj); + RicNewFishbonesSubsFeature::askUserToSetUsefulScaling(fishbonesCollection); + fishbonesCollection->updateConnectedEditors(); RiuMainWindow::instance()->selectAsCurrentItem(obj); } @@ -85,3 +93,59 @@ bool RicNewFishbonesSubsFeature::isCommandEnabled() return false; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewFishbonesSubsFeature::askUserToSetUsefulScaling(RimFishbonesCollection* fishboneCollection) +{ + // Always reset well path collection scale factor + CVF_ASSERT(fishboneCollection); + RimWellPathCollection* wellPathColl = nullptr; + fishboneCollection->firstAncestorOrThisOfTypeAsserted(wellPathColl); + wellPathColl->wellPathRadiusScaleFactor = 0.01; + + RimView* activeView = RiaApplication::instance()->activeReservoirView(); + if (!activeView) return; + + RiaApplication* app = RiaApplication::instance(); + QString sessionKey = "AutoAdjustSettingsForFishbones"; + + bool autoAdjustSettings = false; + QVariant v = app->cacheDataObject(sessionKey); + if (!v.isValid()) + { + double currentScaleFactor = activeView->scaleZ(); + if (fabs(currentScaleFactor - 1.0) < 0.1) return; + + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Question); + + QString questionText; + questionText = QString("When displaying Fishbones structures, the view scaling should be set to 1.\n\nDo you want ResInsight to automatically set view scaling to 1?"); + + msgBox.setText(questionText); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + { + autoAdjustSettings = true; + } + + app->setCacheDataObject(sessionKey, autoAdjustSettings); + } + else + { + autoAdjustSettings = v.toBool(); + } + + if (autoAdjustSettings) + { + activeView->setScaleZAndUpdate(1.0); + + wellPathColl->scheduleGeometryRegenAndRedrawViews(); + + RiuMainWindow::instance()->updateScaleValue(); + } +} diff --git a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h index 4579990dea..a10a71bec2 100644 --- a/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h +++ b/ApplicationCode/Commands/FishbonesCommands/RicNewFishbonesSubsFeature.h @@ -28,8 +28,11 @@ class RimFishbonesCollection; class RicNewFishbonesSubsFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; -protected: +public: + static void askUserToSetUsefulScaling(RimFishbonesCollection* fishboneCollection); + +protected: virtual void onActionTriggered(bool isChecked) override; virtual void setupActionLook(QAction* actionToSetup) override; virtual bool isCommandEnabled() override; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp index de60a4a1ea..0cf4c93386 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCompletions.cpp @@ -31,7 +31,7 @@ CAF_PDM_SOURCE_INIT(RimWellPathCompletions, "WellPathCompletions"); //-------------------------------------------------------------------------------------------------- RimWellPathCompletions::RimWellPathCompletions() { - CAF_PDM_InitObject("WellPathCompletions", ":/WellCollection.png", "", ""); + CAF_PDM_InitObject("Completions", ":/WellCollection.png", "", ""); CAF_PDM_InitFieldNoDefault(&m_perforationCollection, "Perforations", "Perforations", "", "", ""); m_perforationCollection = new RimPerforationCollection; From 4c19123b2dbe55d870f9669d0757def8daa7ddab Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 20 May 2017 20:34:07 +0200 Subject: [PATCH 149/157] #1495 Move feature to leaf object --- .../RicWellPathImportCompletionsFileFeature.cpp | 17 ++++++++++------- .../RicWellPathImportCompletionsFileFeature.h | 4 ++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp index 761e871ec6..3d11812a51 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.cpp @@ -40,7 +40,7 @@ CAF_CMD_SOURCE_INIT(RicWellPathImportCompletionsFileFeature, "RicWellPathImportC //-------------------------------------------------------------------------------------------------- bool RicWellPathImportCompletionsFileFeature::isCommandEnabled() { - if (RicWellPathImportCompletionsFileFeature::selectedWellPathCompletions() != nullptr) + if (RicWellPathImportCompletionsFileFeature::selectedWellPathCollection() != nullptr) { return true; } @@ -53,8 +53,8 @@ bool RicWellPathImportCompletionsFileFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicWellPathImportCompletionsFileFeature::onActionTriggered(bool isChecked) { - RimWellPathCompletions* wellPathCompletions = RicWellPathImportCompletionsFileFeature::selectedWellPathCompletions(); - CVF_ASSERT(wellPathCompletions); + RimFishboneWellPathCollection* wellPathCollection = RicWellPathImportCompletionsFileFeature::selectedWellPathCollection(); + CVF_ASSERT(wellPathCollection); // Open dialog box to select well path files RiaApplication* app = RiaApplication::instance(); @@ -66,7 +66,7 @@ void RicWellPathImportCompletionsFileFeature::onActionTriggered(bool isChecked) // Remember the path to next time app->setLastUsedDialogDirectory("WELLPATH_DIR", QFileInfo(wellPathFilePaths.last()).absolutePath()); - wellPathCompletions->fishbonesCollection()->wellPathCollection()->importCompletionsFromFile(wellPathFilePaths); + wellPathCollection->importCompletionsFromFile(wellPathFilePaths); if (app->project()) { @@ -86,14 +86,17 @@ void RicWellPathImportCompletionsFileFeature::setupActionLook(QAction* actionToS //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPathCompletions* RicWellPathImportCompletionsFileFeature::selectedWellPathCompletions() +RimFishboneWellPathCollection* RicWellPathImportCompletionsFileFeature::selectedWellPathCollection() { - std::vector objects; + std::vector objects; caf::SelectionManager::instance()->objectsByType(&objects); if (objects.size() > 0) { - return objects[0]; + RimFishboneWellPathCollection* fbWellColl = nullptr; + objects[0]->firstAncestorOrThisOfType(fbWellColl); + + return fbWellColl; } return nullptr; diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h index 7755260aae..cc98eed860 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathImportCompletionsFileFeature.h @@ -20,7 +20,7 @@ #include "cafCmdFeature.h" -class RimWellPathCompletions; +class RimFishboneWellPathCollection; //================================================================================================== /// @@ -36,6 +36,6 @@ protected: virtual void setupActionLook( QAction* actionToSetup ) override; private: - static RimWellPathCompletions* selectedWellPathCompletions(); + static RimFishboneWellPathCollection* selectedWellPathCollection(); }; From 29bf25c56be2e8618ab4b014eab96a5c9310911c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 21 May 2017 09:15:54 +0200 Subject: [PATCH 150/157] #1513 Fishbones : Add 'Fly to Object' for fishbones and perforations --- .../Commands/CMakeLists_files.cmake | 2 + .../Commands/RicFlyToObjectFeature.cpp | 111 ++++++++++++++++++ .../Commands/RicFlyToObjectFeature.h | 44 +++++++ .../Fishbones/RimFishbonesMultipleSubs.cpp | 25 +++- .../Fishbones/RimFishbonesMultipleSubs.h | 7 +- .../Rim3dPropertiesInterface.h | 27 +++++ .../RimContextCommandBuilder.cpp | 1 + .../RimPerforationInterval.cpp | 23 ++++ .../ProjectDataModel/RimPerforationInterval.h | 5 +- 9 files changed, 242 insertions(+), 3 deletions(-) create mode 100644 ApplicationCode/Commands/RicFlyToObjectFeature.cpp create mode 100644 ApplicationCode/Commands/RicFlyToObjectFeature.h create mode 100644 ApplicationCode/ProjectDataModel/Rim3dPropertiesInterface.h diff --git a/ApplicationCode/Commands/CMakeLists_files.cmake b/ApplicationCode/Commands/CMakeLists_files.cmake index 806e5bc397..7d7d2a237c 100644 --- a/ApplicationCode/Commands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/CMakeLists_files.cmake @@ -47,6 +47,7 @@ ${CEE_CURRENT_LIST_DIR}RicDeleteSubItemsFeature.h ${CEE_CURRENT_LIST_DIR}RicCommandFeature.h ${CEE_CURRENT_LIST_DIR}RicReloadCaseFeature.h +${CEE_CURRENT_LIST_DIR}RicFlyToObjectFeature.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -87,6 +88,7 @@ ${CEE_CURRENT_LIST_DIR}RicDeleteItemFeature.cpp ${CEE_CURRENT_LIST_DIR}RicDeleteSubItemsFeature.cpp ${CEE_CURRENT_LIST_DIR}RicReloadCaseFeature.cpp +${CEE_CURRENT_LIST_DIR}RicFlyToObjectFeature.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Commands/RicFlyToObjectFeature.cpp b/ApplicationCode/Commands/RicFlyToObjectFeature.cpp new file mode 100644 index 0000000000..cc205b2875 --- /dev/null +++ b/ApplicationCode/Commands/RicFlyToObjectFeature.cpp @@ -0,0 +1,111 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicFlyToObjectFeature.h" + +#include "RiaApplication.h" + +#include "Rim3dPropertiesInterface.h" +#include "RimView.h" + +#include "RiuViewer.h" + +#include "cafDisplayCoordTransform.h" +#include "cafPdmObject.h" +#include "cafSelectionManager.h" + +#include "cvfCamera.h" + +#include + +CAF_CMD_SOURCE_INIT(RicFlyToObjectFeature, "RicFlyToObjectFeature"); + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicFlyToObjectFeature::isCommandEnabled() +{ + if (RicFlyToObjectFeature::boundingBoxForSelectedObjects().isValid()) + { + return true; + } + else + { + return false; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicFlyToObjectFeature::onActionTriggered(bool isChecked) +{ + RimView* activeView = RiaApplication::instance()->activeReservoirView(); + if (!activeView) return; + + RiuViewer* destinationViewer = activeView->viewer(); + if (!destinationViewer) return; + + cvf::BoundingBox bb = RicFlyToObjectFeature::boundingBoxForSelectedObjects(); + CVF_ASSERT(bb.isValid()); + + cvf::ref transForm = activeView->displayCoordTransform(); + + cvf::Vec3d centerInDisplayCoords = transForm->transformToDisplayCoord(bb.center()); + + cvf::Vec3d cameraEye = centerInDisplayCoords + cvf::Vec3d::X_AXIS * 50.0; + cvf::Vec3d cameraViewRefPoint = centerInDisplayCoords; + cvf::Vec3d cameraUp = cvf::Vec3d::Z_AXIS; + + destinationViewer->mainCamera()->setFromLookAt(cameraEye, cameraViewRefPoint, cameraUp); + + activeView->updateCurrentTimeStepAndRedraw(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicFlyToObjectFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("Fly to Object"); + //actionToSetup->setIcon(QIcon(":/3DView16x16.png")); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::BoundingBox RicFlyToObjectFeature::boundingBoxForSelectedObjects() +{ + cvf::BoundingBox bb; + + std::vector objects; + caf::SelectionManager::instance()->objectsByType(&objects); + + for (auto o : objects) + { + Rim3dPropertiesInterface* rim3dProperties = dynamic_cast(o); + if (rim3dProperties) + { + bb.add(rim3dProperties->boundingBoxInDomainCoords()); + } + } + + return bb; +} + diff --git a/ApplicationCode/Commands/RicFlyToObjectFeature.h b/ApplicationCode/Commands/RicFlyToObjectFeature.h new file mode 100644 index 0000000000..f8028c44d9 --- /dev/null +++ b/ApplicationCode/Commands/RicFlyToObjectFeature.h @@ -0,0 +1,44 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +#include "cvfBoundingBox.h" + +namespace caf { + class PdmObject; +} + + +//================================================================================================== +/// +//================================================================================================== +class RicFlyToObjectFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + virtual void onActionTriggered( bool isChecked ) override; + virtual bool isCommandEnabled() override; + virtual void setupActionLook( QAction* actionToSetup ) override; + +private: + static cvf::BoundingBox boundingBoxForSelectedObjects(); +}; diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp index 238d2a6dd9..e3743ba9c4 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.cpp @@ -26,6 +26,7 @@ #include "cafPdmUiListEditor.h" #include "cvfAssert.h" +#include "cvfBoundingBox.h" #include @@ -51,7 +52,6 @@ namespace caf { } } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -446,6 +446,29 @@ void RimFishbonesMultipleSubs::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTr m_name = QString("Fishbone %1").arg(index); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::BoundingBox RimFishbonesMultipleSubs::boundingBoxInDomainCoords() +{ + cvf::BoundingBox bb; + + for (size_t i = 0; i < m_locationOfSubs().size(); i++) + { + for (size_t lateralIndex = 0; lateralIndex < m_lateralCountPerSub; lateralIndex++) + { + std::vector coords = coordsForLateral(i, lateralIndex); + + for (auto c : coords) + { + bb.add(c); + } + } + } + + return bb; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h index f5fccaf5a0..de8c8eff03 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesMultipleSubs.h @@ -19,6 +19,7 @@ #pragma once #include "RimCheckableNamedObject.h" +#include "Rim3dPropertiesInterface.h" #include "cvfBase.h" #include "cvfVector3.h" @@ -32,7 +33,7 @@ class RigFisbonesGeometry; /// /// //================================================================================================== -class RimFishbonesMultipleSubs : public RimCheckableNamedObject +class RimFishbonesMultipleSubs : public RimCheckableNamedObject, public Rim3dPropertiesInterface { CAF_PDM_HEADER_INIT; @@ -54,6 +55,7 @@ public: RimFishbonesMultipleSubs(); virtual ~RimFishbonesMultipleSubs(); + void setMeasuredDepthAndCount(double measuredDepth, double spacing, int subCount); std::vector locationOfSubs() const; @@ -70,6 +72,9 @@ public: std::vector coordsForLateral(size_t subIndex, size_t lateralIndex) const; std::vector> coordsAndMDForLateral(size_t subIndex, size_t lateralIndex) const; + + // Override from Rim3dPropertiesInterface + virtual cvf::BoundingBox boundingBoxInDomainCoords() override; protected: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; diff --git a/ApplicationCode/ProjectDataModel/Rim3dPropertiesInterface.h b/ApplicationCode/ProjectDataModel/Rim3dPropertiesInterface.h new file mode 100644 index 0000000000..694b89ea7a --- /dev/null +++ b/ApplicationCode/ProjectDataModel/Rim3dPropertiesInterface.h @@ -0,0 +1,27 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 Statoil ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfBoundingBox.h" + +class Rim3dPropertiesInterface +{ +public: + virtual cvf::BoundingBox boundingBoxInDomainCoords() = 0; +}; diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index d2aeb22561..122fe09190 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -401,6 +401,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection() commandIds << "RicExportFishbonesLateralsFeature"; commandIds << "RicWellPathExportCompletionDataFeature"; commandIds << "RicWellPathImportCompletionsFileFeature"; + commandIds << "RicFlyToObjectFeature"; // Work in progress -- End diff --git a/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp b/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp index 1e4c9ead04..8a6a8ad40b 100644 --- a/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp +++ b/ApplicationCode/ProjectDataModel/RimPerforationInterval.cpp @@ -19,7 +19,10 @@ #include "RimPerforationInterval.h" +#include "RigWellPath.h" + #include "RimProject.h" +#include "RimWellPath.h" #include "cafPdmUiListEditor.h" #include "cafPdmUiTextEditor.h" @@ -57,6 +60,26 @@ void RimPerforationInterval::setStartAndEndMD(double startMD, double endMD) m_endMD = endMD; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::BoundingBox RimPerforationInterval::boundingBoxInDomainCoords() +{ + cvf::BoundingBox bb; + + RimWellPath* wellPath = nullptr; + this->firstAncestorOrThisOfTypeAsserted(wellPath); + + RigWellPath* rigWellPath = wellPath->wellPathGeometry(); + if (rigWellPath) + { + bb.add(rigWellPath->interpolatedPointAlongWellPath(startMD())); + bb.add(rigWellPath->interpolatedPointAlongWellPath(endMD())); + } + + return bb; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimPerforationInterval.h b/ApplicationCode/ProjectDataModel/RimPerforationInterval.h index 23b07fa08b..e73d8a7852 100644 --- a/ApplicationCode/ProjectDataModel/RimPerforationInterval.h +++ b/ApplicationCode/ProjectDataModel/RimPerforationInterval.h @@ -20,6 +20,7 @@ #pragma once #include "RimCheckableNamedObject.h" +#include "Rim3dPropertiesInterface.h" #include "cafPdmField.h" #include "cafPdmObject.h" @@ -28,7 +29,7 @@ /// /// //================================================================================================== -class RimPerforationInterval : public RimCheckableNamedObject +class RimPerforationInterval : public RimCheckableNamedObject, public Rim3dPropertiesInterface { CAF_PDM_HEADER_INIT; public: @@ -40,6 +41,8 @@ public: double startMD() { return m_startMD(); } double endMD() { return m_endMD(); } + virtual cvf::BoundingBox boundingBoxInDomainCoords() override; + protected: virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; virtual void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; From f05728e76de5187904fc47c498d93163103e8817 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 22 May 2017 07:59:49 +0200 Subject: [PATCH 151/157] #1513 Improve placement of camera based on bb dir and extent --- ApplicationCode/Commands/RicFlyToObjectFeature.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/RicFlyToObjectFeature.cpp b/ApplicationCode/Commands/RicFlyToObjectFeature.cpp index cc205b2875..d295840e65 100644 --- a/ApplicationCode/Commands/RicFlyToObjectFeature.cpp +++ b/ApplicationCode/Commands/RicFlyToObjectFeature.cpp @@ -33,6 +33,8 @@ #include +#include + CAF_CMD_SOURCE_INIT(RicFlyToObjectFeature, "RicFlyToObjectFeature"); @@ -69,7 +71,15 @@ void RicFlyToObjectFeature::onActionTriggered(bool isChecked) cvf::Vec3d centerInDisplayCoords = transForm->transformToDisplayCoord(bb.center()); - cvf::Vec3d cameraEye = centerInDisplayCoords + cvf::Vec3d::X_AXIS * 50.0; + cvf::Vec3d directionNormalToLargesExtent = cvf::Vec3d::X_AXIS; + double largesExtent = fabs(bb.extent().y()); + if (fabs(bb.extent().x()) > largesExtent) + { + largesExtent = fabs(bb.extent().x()); + directionNormalToLargesExtent = cvf::Vec3d::Y_AXIS; + } + + cvf::Vec3d cameraEye = centerInDisplayCoords + directionNormalToLargesExtent * std::max(largesExtent, 30.0); cvf::Vec3d cameraViewRefPoint = centerInDisplayCoords; cvf::Vec3d cameraUp = cvf::Vec3d::Z_AXIS; From 276f81a20e1630d5e7315df85698721e24eb647e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 22 May 2017 08:08:45 +0200 Subject: [PATCH 152/157] #1513 Avoid double dynamic_cast --- ApplicationCode/Commands/RicFlyToObjectFeature.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/Commands/RicFlyToObjectFeature.cpp b/ApplicationCode/Commands/RicFlyToObjectFeature.cpp index d295840e65..6ead54ec77 100644 --- a/ApplicationCode/Commands/RicFlyToObjectFeature.cpp +++ b/ApplicationCode/Commands/RicFlyToObjectFeature.cpp @@ -104,15 +104,14 @@ cvf::BoundingBox RicFlyToObjectFeature::boundingBoxForSelectedObjects() { cvf::BoundingBox bb; - std::vector objects; + std::vector objects; caf::SelectionManager::instance()->objectsByType(&objects); - for (auto o : objects) + for (auto obj : objects) { - Rim3dPropertiesInterface* rim3dProperties = dynamic_cast(o); - if (rim3dProperties) + if (obj) { - bb.add(rim3dProperties->boundingBoxInDomainCoords()); + bb.add(obj->boundingBoxInDomainCoords()); } } From a72658a88de0b048b5c0c1ecfbd552f92dd717ea Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 22 May 2017 11:29:13 +0200 Subject: [PATCH 153/157] Trigger redraw when fishbone collection checkbox is manipulated --- .../ModelVisualization/RivWellPathPartMgr.cpp | 2 +- .../Fishbones/RimFishbonesCollection.cpp | 11 +++++++++++ .../Fishbones/RimFishbonesCollection.h | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 6156caf17a..a94073fb73 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -96,7 +96,7 @@ RivWellPathPartMgr::~RivWellPathPartMgr() //-------------------------------------------------------------------------------------------------- void RivWellPathPartMgr::appendFishbonesPartsToModel(cvf::ModelBasicList* model, caf::DisplayCoordTransform* displayCoordTransform, double characteristicCellSize) { - if (!m_rimWellPath) return; + if (!m_rimWellPath || !m_rimWellPath->fishbonesCollection()->isChecked()) return; // This concept is taken from RivReservoirSimWellsPartMgr, and is required to be able to have // separate part managers for each view diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp index f5c6c77b52..f1bf07844b 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.cpp @@ -24,6 +24,7 @@ #include "RimFishboneWellPathCollection.h" #include "RimFishbonesMultipleSubs.h" +#include "RimProject.h" CAF_PDM_SOURCE_INIT(RimFishbonesCollection, "FishbonesCollection"); @@ -57,3 +58,13 @@ RimFishboneWellPathCollection* RimFishbonesCollection::wellPathCollection() cons return m_wellPathCollection(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFishbonesCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + RimProject* proj; + this->firstAncestorOrThisOfTypeAsserted(proj); + proj->createDisplayModelAndRedrawAllViews(); +} + diff --git a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h index dbb8b8b58c..3ad0e84eee 100644 --- a/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h +++ b/ApplicationCode/ProjectDataModel/Fishbones/RimFishbonesCollection.h @@ -42,6 +42,9 @@ public: caf::PdmChildArrayField fishbonesSubs; +protected: + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; + private: caf::PdmChildField m_wellPathCollection; }; From ee81f49ab1aae8c359ca33b939a3ea21c9a98b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Fri, 19 May 2017 16:45:07 +0200 Subject: [PATCH 154/157] #1465 Export location of completions, with necessary restructuring --- ...RicWellPathExportCompletionDataFeature.cpp | 577 +++++++++++------- .../RicWellPathExportCompletionDataFeature.h | 49 +- .../RifEclipseOutputTableFormatter.h | 4 +- .../RimExportCompletionDataSettings.cpp | 4 +- 4 files changed, 397 insertions(+), 237 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index d637ededbc..6032d4b059 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -95,7 +95,7 @@ void RicWellPathExportCompletionDataFeature::onActionTriggered(bool isChecked) { RiaApplication::instance()->setLastUsedDialogDirectory("COMPLETIONS", QFileInfo(exportSettings.fileName).absolutePath()); - exportToFolder(objects[0], exportSettings.fileName, exportSettings.caseToApply, exportSettings.includeWpimult(), exportSettings.removeLateralsInMainBoreCells()); + exportToFolder(objects[0], exportSettings); } } @@ -110,11 +110,11 @@ void RicWellPathExportCompletionDataFeature::setupActionLook(QAction* actionToSe //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply, bool includeWpimult, bool removeLateralsInMainBoreCells) +void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPath, const RimExportCompletionDataSettings& exportSettings) { - QFile exportFile(fileName); + QFile exportFile(exportSettings.fileName()); - if (caseToApply == nullptr) + if (exportSettings.caseToApply() == nullptr) { RiaLogging::error("Export Completions Data: Cannot export completions data without specified eclipse case"); return; @@ -122,112 +122,279 @@ void RicWellPathExportCompletionDataFeature::exportToFolder(RimWellPath* wellPat if (!exportFile.open(QIODevice::WriteOnly)) { - RiaLogging::error(QString("Export Completions Data: Could not open the file: %1").arg(fileName)); + RiaLogging::error(QString("Export Completions Data: Could not open the file: %1").arg(exportSettings.fileName())); return; } - QTextStream stream(&exportFile); + RiaLogging::debug(QString("Exporting completion data for well path %1 to %2 [WPIMULT: %3, REM BORE CELLS: %4]").arg(wellPath->name).arg(exportSettings.fileName()).arg(exportSettings.includeWpimult()).arg(exportSettings.removeLateralsInMainBoreCells())); - const RigEclipseCaseData* caseData = caseToApply->eclipseCaseData(); - std::vector wellPathCells; - if (removeLateralsInMainBoreCells) + // Generate data + const RigEclipseCaseData* caseData = exportSettings.caseToApply()->eclipseCaseData(); + std::vector wellSegmentLocations = findWellSegmentLocations(exportSettings.caseToApply, wellPath); + + // Filter out cells where main bore is present + if (exportSettings.removeLateralsInMainBoreCells()) { - wellPathCells = findIntersectingCells(caseData, wellPath->wellPathGeometry()->m_wellPathPoints); + std::vector wellPathCells = findIntersectingCells(caseData, wellPath->wellPathGeometry()->m_wellPathPoints); + markWellPathCells(wellPathCells, &wellSegmentLocations); } - std::map lateralsPerCell; - + // Print data + QTextStream stream(&exportFile); RifEclipseOutputTableFormatter formatter(stream); - // COMPDAT + generateCompdatTable(formatter, wellPath, exportSettings, wellSegmentLocations); + + if (exportSettings.includeWpimult()) + { + std::map lateralsPerCell = computeLateralsPerCell(wellSegmentLocations, exportSettings.removeLateralsInMainBoreCells()); + generateWpimultTable(formatter, wellPath, exportSettings, lateralsPerCell); + } + + generateWelsegsTable(formatter, wellPath, exportSettings, wellSegmentLocations); + generateCompsegsTable(formatter, wellPath, exportSettings, wellSegmentLocations); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::generateCompdatTable(RifEclipseOutputTableFormatter& formatter, const RimWellPath* wellPath, const RimExportCompletionDataSettings& settings, const std::vector& locations) +{ + RigMainGrid* grid = settings.caseToApply->eclipseCaseData()->mainGrid(); + std::vector header = { + RifEclipseOutputTableColumn("Well"), + RifEclipseOutputTableColumn("I"), + RifEclipseOutputTableColumn("J"), + RifEclipseOutputTableColumn("K1"), + RifEclipseOutputTableColumn("K2"), + RifEclipseOutputTableColumn("Status"), + RifEclipseOutputTableColumn("SAT"), + RifEclipseOutputTableColumn("TR"), + RifEclipseOutputTableColumn("DIAM"), + RifEclipseOutputTableColumn("KH"), + RifEclipseOutputTableColumn("S"), + RifEclipseOutputTableColumn("Df"), + RifEclipseOutputTableColumn("DIR"), + RifEclipseOutputTableColumn("r0") + }; + + formatter.keyword("COMPDAT"); + formatter.header(header); + + for (const WellSegmentLocation& location : locations) + { + for (const WellSegmentLateral& lateral : location.laterals) + { + std::vector cellIndices; + for (const WellSegmentLateralIntersection& intersection : lateral.intersections) + { + if (settings.removeLateralsInMainBoreCells && intersection.mainBoreCell) continue; + + cellIndices.push_back(intersection.cellIndex); + } + std::vector cellRanges = getCellIndexRange(grid, cellIndices); + + formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(location.fishbonesSubs->name()).arg(location.subIndex).arg(lateral.lateralIndex)); + for (auto cellRange : cellRanges) + { + // Add cell indices + formatter.add(wellPath->name()).addZeroBasedCellIndex(cellRange.i).addZeroBasedCellIndex(cellRange.j).addZeroBasedCellIndex(cellRange.k1).addZeroBasedCellIndex(cellRange.k2); + // Remaining data, to be computed + formatter.add("'OPEN'").add("1*").add("1*"); + // Diameter (originally in mm) in m + formatter.add(location.fishbonesSubs->holeRadius() / 1000); + formatter.add("1*").add("1*").add("1*"); + formatter.add("'Z'"); // TODO - Calculate direction + formatter.add("1*"); + formatter.rowCompleted(); + } + } + } + + formatter.tableCompleted(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::generateWpimultTable(RifEclipseOutputTableFormatter& formatter, const RimWellPath* wellPath, const RimExportCompletionDataSettings& settings, const std::map& lateralsPerCell) +{ + RigMainGrid* grid = settings.caseToApply->eclipseCaseData()->mainGrid(); + std::vector header = { + RifEclipseOutputTableColumn("Well"), + RifEclipseOutputTableColumn("Mult"), + RifEclipseOutputTableColumn("I"), + RifEclipseOutputTableColumn("J"), + RifEclipseOutputTableColumn("K"), + }; + formatter.keyword("WPIMULT"); + formatter.header(header); + + for (auto lateralsInCell : lateralsPerCell) + { + size_t i, j, k; + grid->ijkFromCellIndex(lateralsInCell.first, &i, &j, &k); + formatter.add(wellPath->name()); + formatter.add(lateralsInCell.second); + formatter.addZeroBasedCellIndex(i).addZeroBasedCellIndex(j).addZeroBasedCellIndex(k); + formatter.rowCompleted(); + } + + formatter.tableCompleted(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::generateWelsegsTable(RifEclipseOutputTableFormatter& formatter, const RimWellPath* wellPath, const RimExportCompletionDataSettings& settings, const std::vector& locations) +{ + formatter.keyword("WELSEGS"); + + const WellSegmentLocation& firstLocation = locations[0]; + { std::vector header = { - RifEclipseOutputTableColumn{"Well", LEFT}, - RifEclipseOutputTableColumn{"I", LEFT}, - RifEclipseOutputTableColumn{"J", LEFT}, - RifEclipseOutputTableColumn{"K1", LEFT}, - RifEclipseOutputTableColumn{"K2", LEFT}, - RifEclipseOutputTableColumn{"Status", LEFT}, - RifEclipseOutputTableColumn{"SAT", LEFT}, - RifEclipseOutputTableColumn{"TR", LEFT}, - RifEclipseOutputTableColumn{"DIAM", LEFT}, - RifEclipseOutputTableColumn{"KH", LEFT}, - RifEclipseOutputTableColumn{"S", LEFT}, - RifEclipseOutputTableColumn{"Df", LEFT}, - RifEclipseOutputTableColumn{"DIR", LEFT}, - RifEclipseOutputTableColumn{"r0", LEFT} + RifEclipseOutputTableColumn("Name"), + RifEclipseOutputTableColumn("Dep 1"), + RifEclipseOutputTableColumn("Tlen 1"), + RifEclipseOutputTableColumn("Vol 1"), + RifEclipseOutputTableColumn("Len&Dep"), + RifEclipseOutputTableColumn("PresDrop"), }; - - formatter.keyword("COMPDAT"); formatter.header(header); - for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesCollection()->fishbonesSubs()) + formatter.add(wellPath->name()); + formatter.add(firstLocation.trueVerticalDepth); + formatter.add(firstLocation.measuredDepth); + formatter.add("1*"); + formatter.add("INC"); + formatter.add("H--"); + + formatter.rowCompleted(); + } + + { + std::vector header = { + RifEclipseOutputTableColumn("First Seg"), + RifEclipseOutputTableColumn("Last Seg"), + RifEclipseOutputTableColumn("Branch Num"), + RifEclipseOutputTableColumn("Outlet Seg"), + RifEclipseOutputTableColumn("Length"), + RifEclipseOutputTableColumn("Depth Change"), + RifEclipseOutputTableColumn("Diam"), + RifEclipseOutputTableColumn("Rough"), + }; + formatter.header(header); + } + + { + WellSegmentLocation previousLocation = firstLocation; + formatter.comment("Main stem"); + for (size_t i = 0; i < locations.size(); ++i) { - for (size_t subIndex = 0; subIndex < subs->locationOfSubs().size(); ++subIndex) + const WellSegmentLocation& location = locations[i]; + + formatter.comment(QString("Segment for sub %1").arg(location.subIndex)); + formatter.add(location.segmentNumber).add(location.segmentNumber); + formatter.add(1); // All segments on main stem are branch 1 + formatter.add(location.segmentNumber - 1); // All main stem segments are connected to the segment below them + formatter.add(location.fishbonesSubs->locationOfSubs()[location.subIndex] - previousLocation.fishbonesSubs->locationOfSubs()[previousLocation.subIndex]); + formatter.add(location.trueVerticalDepth - previousLocation.trueVerticalDepth); + formatter.add(-1.0); // FIXME : Diam of main stem? + formatter.add(-1.0); // FIXME : Rough of main stem? + formatter.rowCompleted(); + + previousLocation = location; + } + } + + { + formatter.comment("Laterals"); + formatter.comment("Diam: MSW - Tubing Radius"); + formatter.comment("Rough: MSW - Open Hole Roughness Factor"); + for (const WellSegmentLocation& location : locations) + { + for (const WellSegmentLateral& lateral : location.laterals) { - for (size_t lateralIndex = 0; lateralIndex < subs->lateralLengths().size(); ++lateralIndex) + formatter.comment(QString("%1 : Sub index %2 - Lateral %3").arg(location.fishbonesSubs->name()).arg(location.subIndex).arg(lateral.lateralIndex)); + + for (const WellSegmentLateralIntersection& intersection : lateral.intersections) { - std::vector lateralCoords = subs->coordsForLateral(subIndex, lateralIndex); - - std::vector lateralCells = findIntersectingCells(caseData, lateralCoords); - - if (includeWpimult) - { - // Only need this data if WPIMULT should be included in file - addLateralToCells(&lateralsPerCell, lateralCells); - } - - if (removeLateralsInMainBoreCells) - { - lateralCells = filterWellPathCells(lateralCells, wellPathCells); - } - - std::vector cellRanges = getCellIndexRange(caseData->mainGrid(), lateralCells); - - formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(subs->name()).arg(subIndex).arg(lateralIndex)); - for (auto cellRange : cellRanges) - { - // Add cell indices - formatter.add(wellPath->name()).addZeroBasedCellIndex(cellRange.i).addZeroBasedCellIndex(cellRange.j).addZeroBasedCellIndex(cellRange.k1).addZeroBasedCellIndex(cellRange.k2); - // Remaining data, to be computed - formatter.add("'OPEN'").add("1*").add("1*"); - // Diameter (originally in mm) in m - formatter.add(subs->holeRadius() / 1000); - formatter.add("1*").add("1*").add("1*").add("'Z'").add("1*"); - formatter.rowCompleted(); - } + formatter.add(intersection.segmentNumber); + formatter.add(intersection.segmentNumber); + formatter.add(lateral.branchNumber); + formatter.add(intersection.attachedSegmentNumber); + formatter.add(intersection.length); + formatter.add(intersection.depth); + formatter.add(location.fishbonesSubs->tubingRadius()); + formatter.add(location.fishbonesSubs->openHoleRoughnessFactor()); + formatter.rowCompleted(); } } } - formatter.tableCompleted(); } - // WPIMULT - if (includeWpimult) + formatter.tableCompleted(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::generateCompsegsTable(RifEclipseOutputTableFormatter& formatter, const RimWellPath* wellPath, const RimExportCompletionDataSettings& settings, const std::vector& locations) +{ + RigMainGrid* grid = settings.caseToApply->eclipseCaseData()->mainGrid(); + formatter.keyword("COMPSEGS"); { std::vector header = { - RifEclipseOutputTableColumn{"Well", LEFT}, - RifEclipseOutputTableColumn{"Mult", LEFT}, - RifEclipseOutputTableColumn{"I", LEFT}, - RifEclipseOutputTableColumn{"J", LEFT}, - RifEclipseOutputTableColumn{"K", LEFT}, + RifEclipseOutputTableColumn("Name") }; - formatter.keyword("WPIMULT"); formatter.header(header); - - for (auto lateralsInCell : lateralsPerCell) - { - size_t i, j, k; - caseData->mainGrid()->ijkFromCellIndex(lateralsInCell.first, &i, &j, &k); - formatter.add(wellPath->name()).add(lateralsInCell.second).addZeroBasedCellIndex(i).addZeroBasedCellIndex(j).addZeroBasedCellIndex(k); - formatter.rowCompleted(); - } - - formatter.tableCompleted(); + formatter.add(wellPath->name()); + formatter.rowCompleted(); } - computeWellSegments(formatter, wellPath, caseToApply); + { + std::vector header = { + RifEclipseOutputTableColumn("I"), + RifEclipseOutputTableColumn("J"), + RifEclipseOutputTableColumn("K"), + RifEclipseOutputTableColumn("Branch no"), + RifEclipseOutputTableColumn("Start Length"), + RifEclipseOutputTableColumn("End Length"), + RifEclipseOutputTableColumn("Dir Pen"), + RifEclipseOutputTableColumn("End Range"), + RifEclipseOutputTableColumn("Connection Depth") + }; + formatter.header(header); + } + + for (const WellSegmentLocation& location : locations) + { + for (const WellSegmentLateral& lateral : location.laterals) + { + double length = 0; + for (const WellSegmentLateralIntersection& intersection : lateral.intersections) + { + length += intersection.length; + + if (settings.removeLateralsInMainBoreCells && intersection.mainBoreCell) continue; + + size_t i, j, k; + grid->ijkFromCellIndex(intersection.cellIndex, &i, &j, &k); + + formatter.addZeroBasedCellIndex(i).addZeroBasedCellIndex(j).addZeroBasedCellIndex(k); + formatter.add(lateral.branchNumber); + formatter.add(length); + formatter.add("1*"); + formatter.add("X"); // TODO - Calculate direction + formatter.add(-1); + formatter.rowCompleted(); + } + } + } + + formatter.tableCompleted(); } //-------------------------------------------------------------------------------------------------- @@ -412,158 +579,51 @@ void RicWellPathExportCompletionDataFeature::setHexCorners(const RigCell& cell, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RicWellPathExportCompletionDataFeature::filterWellPathCells(const std::vector& completionCells, const std::vector& wellPathCells) +void RicWellPathExportCompletionDataFeature::markWellPathCells(const std::vector& wellPathCells, std::vector* locations) { - std::vector filteredCells; - std::set_difference(completionCells.begin(), completionCells.end(), wellPathCells.begin(), wellPathCells.end(), std::back_inserter(filteredCells)); - return filteredCells; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RicWellPathExportCompletionDataFeature::addLateralToCells(std::map* lateralsPerCell, const std::vector& lateralCells) -{ - for (size_t cell : lateralCells) + std::set wellPathCellSet(wellPathCells.begin(), wellPathCells.end()); + for (WellSegmentLocation& location : *locations) { - std::map::iterator it = lateralsPerCell->find(cell); - if (it == lateralsPerCell->end()) + for (WellSegmentLateral& lateral : location.laterals) { - (*lateralsPerCell)[cell] = 1; - } - else - { - (*lateralsPerCell)[cell] = it->second + 1; - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RicWellPathExportCompletionDataFeature::computeWellSegments(RifEclipseOutputTableFormatter& formatter, RimWellPath* wellPath, const RimEclipseCase* caseToApply) -{ - std::vector wellSegmentLocations = findWellSegmentLocations(wellPath); - if (wellSegmentLocations.empty()) return; - formatter.keyword("WELSEGS"); - - WellSegmentLocation& firstLocation = wellSegmentLocations[0]; - - { - std::vector header = { - RifEclipseOutputTableColumn{"Name", LEFT}, - RifEclipseOutputTableColumn{"Dep 1", LEFT}, - RifEclipseOutputTableColumn{"Tlen 1", LEFT}, - RifEclipseOutputTableColumn{"Vol 1", LEFT}, - RifEclipseOutputTableColumn{"Len&Dep", LEFT}, - RifEclipseOutputTableColumn{"PresDrop", LEFT}, - }; - formatter.header(header); - - formatter.add(wellPath->name()); - formatter.add(firstLocation.trueVerticalDepth); - formatter.add(firstLocation.measuredDepth); - formatter.add("1*"); - formatter.add("INC"); - formatter.add("H--"); - - formatter.rowCompleted(); - } - - { - std::vector header = { - RifEclipseOutputTableColumn{"First Seg", LEFT}, - RifEclipseOutputTableColumn{"Last Seg", LEFT}, - RifEclipseOutputTableColumn{"Branch Num", LEFT}, - RifEclipseOutputTableColumn{"Outlet Seg", LEFT}, - RifEclipseOutputTableColumn{"Length", LEFT}, - RifEclipseOutputTableColumn{"Depth Change", LEFT}, - RifEclipseOutputTableColumn{"Diam", LEFT}, - RifEclipseOutputTableColumn{"Rough", LEFT}, - }; - formatter.header(header); - } - - size_t segmentNumber = 1; - { - WellSegmentLocation previousLocation = firstLocation; - formatter.comment("Main stem"); - for (size_t i = 0; i < wellSegmentLocations.size(); ++i) - { - WellSegmentLocation& location = wellSegmentLocations[i]; - location.segmentNumber = static_cast(segmentNumber + 1); - - formatter.comment(QString("Segment for sub %1").arg(location.subIndex)); - formatter.add(location.segmentNumber).add(location.segmentNumber); - formatter.add(1); // All segments on main stem are branch 1 - formatter.add(segmentNumber); - formatter.add(location.fishbonesSubs->locationOfSubs()[location.subIndex] - previousLocation.fishbonesSubs->locationOfSubs()[previousLocation.subIndex]); - formatter.add(location.trueVerticalDepth - previousLocation.trueVerticalDepth); - formatter.add(-1.0); // FIXME : Diam of main stem? - formatter.add(-1.0); // FIXME : Rough of main stem? - formatter.rowCompleted(); - - ++segmentNumber; - previousLocation = location; - } - } - - { - int branchNum = 1; - formatter.comment("Laterals"); - formatter.comment("Diam: MSW - Tubing Radius"); - formatter.comment("Rough: MSW - Open Hole Roughness Factor"); - for (WellSegmentLocation& location : wellSegmentLocations) - { - for (WellSegmentLateral& lateral : location.laterals) + for (WellSegmentLateralIntersection& intersection : lateral.intersections) { - formatter.comment(QString("%1 : Sub index %2 - Lateral %3").arg(location.fishbonesSubs->name()).arg(location.subIndex).arg(lateral.lateralIndex)); - - lateral.branchNumber = ++branchNum; - std::vector coords = location.fishbonesSubs->coordsForLateral(location.subIndex, lateral.lateralIndex); - std::vector intersections = findIntersections(caseToApply->eclipseCaseData(), coords); - filterIntersections(&intersections); - - double length = 0; - double depth = 0; - cvf::Vec3d& startPoint = coords[0]; - auto intersection = intersections.cbegin(); - - for (size_t i = 1; i < coords.size() && intersection != intersections.cend(); i++) + if (wellPathCellSet.find(intersection.cellIndex) != wellPathCellSet.end()) { - if (isPointBetween(startPoint, coords[i], intersection->m_intersectionPoint)) - { - cvf::Vec3d between = intersection->m_intersectionPoint - startPoint; - length += between.length(); - depth += intersection->m_intersectionPoint.z() - startPoint.z(); - segmentNumber++; - formatter.add(segmentNumber).add(segmentNumber); - formatter.add(lateral.branchNumber); - formatter.add(location.segmentNumber); - formatter.add(length); - formatter.add(depth); - formatter.add(location.fishbonesSubs->tubingRadius()); - formatter.add(location.fishbonesSubs->openHoleRoughnessFactor()); - formatter.rowCompleted(); - - length = 0; - depth = 0; - startPoint = intersection->m_intersectionPoint; - ++intersection; - } - else - { - cvf::Vec3d between = coords[i] - startPoint; - length += between.length(); - depth += coords[i].z() - startPoint.z(); - startPoint = coords[i]; - } + intersection.mainBoreCell = true; } } } } +} - formatter.tableCompleted(); +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::map RicWellPathExportCompletionDataFeature::computeLateralsPerCell(const std::vector& segmentLocations, bool removeMainBoreCells) +{ + std::map lateralsPerCell; + for (const WellSegmentLocation& location : segmentLocations) + { + for (const WellSegmentLateral& lateral : location.laterals) + { + for (const WellSegmentLateralIntersection& intersection : lateral.intersections) + { + if (removeMainBoreCells && intersection.mainBoreCell) continue; + + auto match = lateralsPerCell.find(intersection.cellIndex); + if (match == lateralsPerCell.end()) + { + lateralsPerCell[intersection.cellIndex] = 1; + } + else + { + lateralsPerCell[intersection.cellIndex] = match->second + 1; + } + } + } + } + return lateralsPerCell; } //-------------------------------------------------------------------------------------------------- @@ -603,7 +663,10 @@ void RicWellPathExportCompletionDataFeature::filterIntersections(std::vector RicWellPathExportCompletionDataFeature::findWellSegmentLocations(RimWellPath* wellPath) +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RicWellPathExportCompletionDataFeature::findWellSegmentLocations(const RimEclipseCase* caseToApply, RimWellPath* wellPath) { std::vector wellSegmentLocations; for (RimFishbonesMultipleSubs* subs : wellPath->fishbonesCollection()->fishbonesSubs()) @@ -622,6 +685,72 @@ std::vector RicWellPathExportCompletionDataFeature::findWel } std::sort(wellSegmentLocations.begin(), wellSegmentLocations.end(), wellSegmentLocationOrdering); + assignBranchAndSegmentNumbers(caseToApply, &wellSegmentLocations); + return wellSegmentLocations; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::calculateLateralIntersections(const RimEclipseCase* caseToApply, WellSegmentLocation* location, int* branchNum, int* segmentNum) +{ + for (WellSegmentLateral& lateral : location->laterals) + { + lateral.branchNumber = ++(*branchNum); + std::vector coords = location->fishbonesSubs->coordsForLateral(location->subIndex, lateral.lateralIndex); + std::vector intersections = findIntersections(caseToApply->eclipseCaseData(), coords); + filterIntersections(&intersections); + + double length = 0; + double depth = 0; + cvf::Vec3d& startPoint = coords[0]; + auto intersection = intersections.cbegin(); + int attachedSegmentNumber = location->segmentNumber; + + for (size_t i = 1; i < coords.size() && intersection != intersections.cend(); i++) + { + if (isPointBetween(startPoint, coords[i], intersection->m_intersectionPoint)) + { + cvf::Vec3d between = intersection->m_intersectionPoint - startPoint; + length += between.length(); + depth += intersection->m_intersectionPoint.z() - startPoint.z(); + + lateral.intersections.push_back(WellSegmentLateralIntersection(++(*segmentNum), attachedSegmentNumber, intersection->m_hexIndex, length, depth)); + + length = 0; + depth = 0; + startPoint = intersection->m_intersectionPoint; + attachedSegmentNumber = *segmentNum; + ++intersection; + } + else + { + cvf::Vec3d between = coords[i] - startPoint; + length += between.length(); + depth += coords[i].z() - startPoint.z(); + startPoint = coords[i]; + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::assignBranchAndSegmentNumbers(const RimEclipseCase* caseToApply, std::vector* locations) +{ + int segmentNumber = 1; + int branchNumber = 1; + // First loop over the locations so that each segment on the main stem is an incremental number + for (WellSegmentLocation& location : *locations) + { + location.segmentNumber = ++segmentNumber; + } + // Then assign branch and segment numbers to each lateral parts + for (WellSegmentLocation& location : *locations) + { + calculateLateralIntersections(caseToApply, &location, &branchNumber, &segmentNumber); + } +} + diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h index 20d4cca44b..e0f9050458 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h @@ -22,6 +22,8 @@ #include "RigWellLogExtractionTools.h" +#include "RimExportCompletionDataSettings.h" + #include "cafCmdFeature.h" #include "cvfBoundingBox.h" @@ -34,6 +36,26 @@ class RigMainGrid; class RigCell; class RimFishbonesMultipleSubs; +//================================================================================================== +/// +//================================================================================================== +struct WellSegmentLateralIntersection { + WellSegmentLateralIntersection(int segmentNumber, int attachedSegmentNumber, size_t cellIndex, double length, double depth) + : segmentNumber(segmentNumber), + attachedSegmentNumber(attachedSegmentNumber), + cellIndex(cellIndex), + length(length), + depth(depth), + mainBoreCell(false) + {} + + int segmentNumber; + int attachedSegmentNumber; + size_t cellIndex; + bool mainBoreCell; + double length; + double depth; +}; //================================================================================================== /// @@ -41,20 +63,21 @@ class RimFishbonesMultipleSubs; struct WellSegmentLateral { WellSegmentLateral(size_t lateralIndex) : lateralIndex(lateralIndex) {} - size_t lateralIndex; - int branchNumber; + size_t lateralIndex; + int branchNumber; + std::vector intersections; }; //================================================================================================== /// //================================================================================================== struct WellSegmentLocation { - WellSegmentLocation(const RimFishbonesMultipleSubs* subs, double measuredDepth, double trueVerticalDepth, size_t subIndex) + WellSegmentLocation(const RimFishbonesMultipleSubs* subs, double measuredDepth, double trueVerticalDepth, size_t subIndex, int segmentNumber = -1) : fishbonesSubs(subs), measuredDepth(measuredDepth), trueVerticalDepth(trueVerticalDepth), subIndex(subIndex), - segmentNumber(-1) + segmentNumber(segmentNumber) { } @@ -95,18 +118,26 @@ protected: virtual void setupActionLook(QAction* actionToSetup) override; private: - static void exportToFolder(RimWellPath* wellPath, const QString& fileName, const RimEclipseCase* caseToApply, bool includeWpimult, bool removeLateralsInMainBoreCells); + static void exportToFolder(RimWellPath* wellPath, const RimExportCompletionDataSettings& exportSettings); + + static void generateCompdatTable(RifEclipseOutputTableFormatter& formatter, const RimWellPath* wellPath, const RimExportCompletionDataSettings& settings, const std::vector& locations); + static void generateWpimultTable(RifEclipseOutputTableFormatter& formatter, const RimWellPath* wellPath, const RimExportCompletionDataSettings& settings, const std::map& lateralsPerCell); + static void generateWelsegsTable(RifEclipseOutputTableFormatter& formatter, const RimWellPath* wellPath, const RimExportCompletionDataSettings& settings, const std::vector& locations); + static void generateCompsegsTable(RifEclipseOutputTableFormatter& formatter, const RimWellPath* wellPath, const RimExportCompletionDataSettings& settings, const std::vector& locations); + + static std::map computeLateralsPerCell(const std::vector& segmentLocations, bool removeMainBoreCells); + static std::vector findCloseCells(const RigEclipseCaseData* caseData, const cvf::BoundingBox& bb); static std::vector getCellIndexRange(const RigMainGrid* grid, const std::vector& cellIndices); static bool cellOrdering(const EclipseCellIndex& cell1, const EclipseCellIndex& cell2); static std::vector findIntersectingCells(const RigEclipseCaseData* grid, const std::vector& coords); static void setHexCorners(const RigCell& cell, const std::vector& nodeCoords, cvf::Vec3d* hexCorners); - static std::vector filterWellPathCells(const std::vector& completionCells, const std::vector& wellPathCells); - static void addLateralToCells(std::map* lateralsPerCell, const std::vector& lateralCells); - static void computeWellSegments(RifEclipseOutputTableFormatter& formatter, RimWellPath* wellPath, const RimEclipseCase* caseToApply); + static void markWellPathCells(const std::vector& wellPathCells, std::vector* locations); static bool wellSegmentLocationOrdering(const WellSegmentLocation& first, const WellSegmentLocation& second); static std::vector findIntersections(const RigEclipseCaseData* caseData, const std::vector& coords); static bool isPointBetween(const cvf::Vec3d& pointA, const cvf::Vec3d& pointB, const cvf::Vec3d& needle); static void filterIntersections(std::vector* intersections); - static std::vector findWellSegmentLocations(RimWellPath* wellPath); + static std::vector findWellSegmentLocations(const RimEclipseCase* caseToApply, RimWellPath* wellPath); + static void calculateLateralIntersections(const RimEclipseCase* caseToApply, WellSegmentLocation* location, int* branchNum, int* segmentNum); + static void assignBranchAndSegmentNumbers(const RimEclipseCase* caseToApply, std::vector* locations); }; diff --git a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h index 89b08dd700..0c0215c564 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h +++ b/ApplicationCode/FileInterface/RifEclipseOutputTableFormatter.h @@ -55,10 +55,10 @@ struct RifEclipseOutputTableLine //================================================================================================== struct RifEclipseOutputTableColumn { - RifEclipseOutputTableColumn(const QString& title, RifEclipseOutputTableAlignment alignment) + RifEclipseOutputTableColumn(const QString& title, RifEclipseOutputTableAlignment alignment = LEFT, int width = -1) : title(title), alignment(alignment), - width(-1) + width(width) { } diff --git a/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp index eb342e1f38..ec0f14f726 100644 --- a/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimExportCompletionDataSettings.cpp @@ -27,6 +27,6 @@ RimExportCompletionDataSettings::RimExportCompletionDataSettings() { CAF_PDM_InitObject("RimExportCompletionDataSettings", "", "", ""); - CAF_PDM_InitFieldNoDefault(&includeWpimult, "IncludeWPIMULT", "Include WPIMLUT", "", "", ""); - CAF_PDM_InitFieldNoDefault(&removeLateralsInMainBoreCells, "RemoveLateralsInMainBoreCells", "Remove Laterals in Main Bore Cells", "", "", ""); + CAF_PDM_InitField(&includeWpimult, "IncludeWPIMULT", true, "Include WPIMLUT", "", "", ""); + CAF_PDM_InitField(&removeLateralsInMainBoreCells, "RemoveLateralsInMainBoreCells", false, "Remove Laterals in Main Bore Cells", "", "", ""); } From b8557c8132efe26c82112bc10bec5e7d417cc733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Mon, 22 May 2017 13:23:48 +0200 Subject: [PATCH 155/157] #1505 Fishbones : Calculate direction of a completion --- ...RicWellPathExportCompletionDataFeature.cpp | 250 ++++++++++++++---- .../RicWellPathExportCompletionDataFeature.h | 35 ++- 2 files changed, 225 insertions(+), 60 deletions(-) diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp index 6032d4b059..e3aa639ef4 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.cpp @@ -186,26 +186,33 @@ void RicWellPathExportCompletionDataFeature::generateCompdatTable(RifEclipseOutp { for (const WellSegmentLateral& lateral : location.laterals) { - std::vector cellIndices; + formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(location.fishbonesSubs->name()).arg(location.subIndex).arg(lateral.lateralIndex)); for (const WellSegmentLateralIntersection& intersection : lateral.intersections) { if (settings.removeLateralsInMainBoreCells && intersection.mainBoreCell) continue; - cellIndices.push_back(intersection.cellIndex); - } - std::vector cellRanges = getCellIndexRange(grid, cellIndices); - - formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(location.fishbonesSubs->name()).arg(location.subIndex).arg(lateral.lateralIndex)); - for (auto cellRange : cellRanges) - { - // Add cell indices - formatter.add(wellPath->name()).addZeroBasedCellIndex(cellRange.i).addZeroBasedCellIndex(cellRange.j).addZeroBasedCellIndex(cellRange.k1).addZeroBasedCellIndex(cellRange.k2); - // Remaining data, to be computed + size_t i, j, k; + grid->ijkFromCellIndex(intersection.cellIndex, &i, &j, &k); + formatter.add(wellPath->name()); + formatter.addZeroBasedCellIndex(i).addZeroBasedCellIndex(j).addZeroBasedCellIndex(k).addZeroBasedCellIndex(k); formatter.add("'OPEN'").add("1*").add("1*"); - // Diameter (originally in mm) in m formatter.add(location.fishbonesSubs->holeRadius() / 1000); formatter.add("1*").add("1*").add("1*"); - formatter.add("'Z'"); // TODO - Calculate direction + switch (intersection.direction) + { + case POS_I: + case NEG_I: + formatter.add("'X'"); + break; + case POS_J: + case NEG_J: + formatter.add("'Y'"); + break; + case POS_K: + case NEG_K: + formatter.add("'Z'"); + break; + } formatter.add("1*"); formatter.rowCompleted(); } @@ -387,7 +394,21 @@ void RicWellPathExportCompletionDataFeature::generateCompsegsTable(RifEclipseOut formatter.add(lateral.branchNumber); formatter.add(length); formatter.add("1*"); - formatter.add("X"); // TODO - Calculate direction + switch (intersection.direction) + { + case POS_I: + case NEG_I: + formatter.add("I"); + break; + case POS_J: + case NEG_J: + formatter.add("J"); + break; + case POS_K: + case NEG_K: + formatter.add("K"); + break; + } formatter.add(-1); formatter.rowCompleted(); } @@ -483,6 +504,36 @@ bool RicWellPathExportCompletionDataFeature::cellOrdering(const EclipseCellIndex } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RicWellPathExportCompletionDataFeature::findCellFromCoords(const RigEclipseCaseData* caseData, const cvf::Vec3d& coords) +{ + const std::vector& nodeCoords = caseData->mainGrid()->nodes(); + + cvf::BoundingBox bb; + bb.add(coords); + std::vector closeCells = findCloseCells(caseData, bb); + cvf::Vec3d hexCorners[8]; + + for (size_t closeCell : closeCells) + { + const RigCell& cell = caseData->mainGrid()->globalCellArray()[closeCell]; + if (cell.isInvalid()) continue; + + setHexCorners(cell, nodeCoords, hexCorners); + + if (RigHexIntersector::isPointInCell(coords, hexCorners, closeCell)) + { + return closeCell; + } + } + + // Coordinate is outside any cells? + CVF_ASSERT(false); + return 0; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -494,23 +545,10 @@ std::vector RicWellPathExportCompletionDataFeature::findIntersectingCell // Find starting cell if (coords.size() > 0) { - cvf::BoundingBox bb; - bb.add(coords[0]); - std::vector closeCells = findCloseCells(caseData, bb); - cvf::Vec3d hexCorners[8]; - - for (size_t closeCell : closeCells) + size_t startCell = findCellFromCoords(caseData, coords[0]); + if (startCell > 0) { - const RigCell& cell = caseData->mainGrid()->globalCellArray()[closeCell]; - if (cell.isInvalid()) continue; - - setHexCorners(cell, nodeCoords, hexCorners); - - if (RigHexIntersector::isPointInCell(coords[0], hexCorners, closeCell)) - { - cells.insert(closeCell); - break; - } + cells.insert(startCell); } } @@ -702,36 +740,59 @@ void RicWellPathExportCompletionDataFeature::calculateLateralIntersections(const std::vector intersections = findIntersections(caseToApply->eclipseCaseData(), coords); filterIntersections(&intersections); - double length = 0; - double depth = 0; - cvf::Vec3d& startPoint = coords[0]; - auto intersection = intersections.cbegin(); - int attachedSegmentNumber = location->segmentNumber; + const HexIntersectionInfo* prevIntersection = nullptr; - for (size_t i = 1; i < coords.size() && intersection != intersections.cend(); i++) { - if (isPointBetween(startPoint, coords[i], intersection->m_intersectionPoint)) - { - cvf::Vec3d between = intersection->m_intersectionPoint - startPoint; - length += between.length(); - depth += intersection->m_intersectionPoint.z() - startPoint.z(); + double length = 0; + double depth = 0; + cvf::Vec3d startPoint = coords[0]; + auto intersection = intersections.cbegin(); + int attachedSegmentNumber = location->segmentNumber; - lateral.intersections.push_back(WellSegmentLateralIntersection(++(*segmentNum), attachedSegmentNumber, intersection->m_hexIndex, length, depth)); - - length = 0; - depth = 0; - startPoint = intersection->m_intersectionPoint; - attachedSegmentNumber = *segmentNum; - ++intersection; - } - else + for (size_t i = 1; i < coords.size() && intersection != intersections.cend(); i++) { - cvf::Vec3d between = coords[i] - startPoint; - length += between.length(); - depth += coords[i].z() - startPoint.z(); - startPoint = coords[i]; + if (isPointBetween(startPoint, coords[i], intersection->m_intersectionPoint)) + { + cvf::Vec3d between = intersection->m_intersectionPoint - startPoint; + length += between.length(); + depth += intersection->m_intersectionPoint.z() - startPoint.z(); + + // Find the direction of the previous cell + if (prevIntersection != nullptr) + { + std::pair direction = calculateDirectionAndDistanceInCell(caseToApply->eclipseCaseData()->mainGrid(), prevIntersection->m_hexIndex, prevIntersection->m_intersectionPoint, intersection->m_intersectionPoint); + WellSegmentLateralIntersection& lateralIntersection = lateral.intersections[lateral.intersections.size() - 1]; + lateralIntersection.direction = direction.first; + lateralIntersection.directionLength = direction.second; + } + + lateral.intersections.push_back(WellSegmentLateralIntersection(++(*segmentNum), attachedSegmentNumber, intersection->m_hexIndex, length, depth)); + + length = 0; + depth = 0; + startPoint = intersection->m_intersectionPoint; + attachedSegmentNumber = *segmentNum; + ++intersection; + prevIntersection = &*intersection; + } + else + { + const cvf::Vec3d between = coords[i] - startPoint; + length += between.length(); + depth += coords[i].z() - startPoint.z(); + startPoint = coords[i]; + } } } + + // Find the direction of the last cell + if (prevIntersection != nullptr && !coords.empty()) + { + std::pair direction = calculateDirectionAndDistanceInCell(caseToApply->eclipseCaseData()->mainGrid(), prevIntersection->m_hexIndex, prevIntersection->m_intersectionPoint, coords[coords.size()-1]); + WellSegmentLateralIntersection& lateralIntersection = lateral.intersections[lateral.intersections.size() - 1]; + lateralIntersection.direction = direction.first; + lateralIntersection.directionLength = direction.second; + } } } @@ -754,3 +815,84 @@ void RicWellPathExportCompletionDataFeature::assignBranchAndSegmentNumbers(const } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeature::calculateCellMainAxisDirections(const RigMainGrid* grid, size_t cellIndex, cvf::Vec3d* iAxisDirection, cvf::Vec3d* jAxisDirection, cvf::Vec3d* kAxisDirection) +{ + const std::vector& nodeCoords = grid->nodes(); + cvf::Vec3d hexCorners[8]; + const RigCell& cell = grid->globalCellArray()[cellIndex]; + setHexCorners(cell, nodeCoords, hexCorners); + + *iAxisDirection = calculateCellMainAxisDirection(hexCorners, cvf::StructGridInterface::FaceType::NEG_I, cvf::StructGridInterface::POS_I); + *jAxisDirection = calculateCellMainAxisDirection(hexCorners, cvf::StructGridInterface::FaceType::NEG_J, cvf::StructGridInterface::POS_J); + *kAxisDirection = calculateCellMainAxisDirection(hexCorners, cvf::StructGridInterface::FaceType::NEG_K, cvf::StructGridInterface::POS_K); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RicWellPathExportCompletionDataFeature::calculateCellMainAxisDirection(const cvf::Vec3d* hexCorners, cvf::StructGridInterface::FaceType startFace, cvf::StructGridInterface::FaceType endFace) +{ + cvf::ubyte faceVertexIndices[4]; + + cvf::StructGridInterface::cellFaceVertexIndices(startFace, faceVertexIndices); + + cvf::Vec3d startFaceCenter = cvf::GeometryTools::computeFaceCenter(hexCorners[faceVertexIndices[0]], hexCorners[faceVertexIndices[1]], hexCorners[faceVertexIndices[2]], hexCorners[faceVertexIndices[3]]); + + cvf::StructGridInterface::cellFaceVertexIndices(endFace, faceVertexIndices); + + cvf::Vec3d endFaceCenter = cvf::GeometryTools::computeFaceCenter(hexCorners[faceVertexIndices[0]], hexCorners[faceVertexIndices[1]], hexCorners[faceVertexIndices[2]], hexCorners[faceVertexIndices[3]]); + + return endFaceCenter - startFaceCenter; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RicWellPathExportCompletionDataFeature::calculateDirectionAndDistanceInCell(const RigMainGrid* grid, size_t cellIndex, const cvf::Vec3d& startPoint, const cvf::Vec3d& endPoint) +{ + cvf::Vec3d vec = endPoint - startPoint; + + cvf::Vec3d iAxisDirection; + cvf::Vec3d jAxisDirection; + cvf::Vec3d kAxisDirection; + calculateCellMainAxisDirections(grid, cellIndex, &iAxisDirection, &jAxisDirection, &kAxisDirection); + + double iLength = iAxisDirection.dot(vec); + double jLength = jAxisDirection.dot(vec); + double kLength = kAxisDirection.dot(vec); + + double iNormalizedLength = abs(iLength / iAxisDirection.length()); + double jNormalizedLength = abs(jLength / jAxisDirection.length()); + double kNormalizedLength = abs(kLength / kAxisDirection.length()); + + if (iNormalizedLength > jNormalizedLength && iNormalizedLength > kNormalizedLength) + { + WellSegmentCellDirection direction = POS_I; + if (iLength < 0) + { + direction = NEG_I; + } + return std::make_pair(direction, iLength); + } + else if (jNormalizedLength > iNormalizedLength && jNormalizedLength > kNormalizedLength) + { + WellSegmentCellDirection direction = POS_J; + if (jLength < 0) + { + direction = NEG_J; + } + return std::make_pair(direction, jLength); + } + else + { + WellSegmentCellDirection direction = POS_K; + if (kLength < 0) + { + direction = NEG_K; + } + return std::make_pair(direction, kLength); + } +} diff --git a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h index e0f9050458..844e053453 100644 --- a/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h +++ b/ApplicationCode/Commands/WellPathCommands/RicWellPathExportCompletionDataFeature.h @@ -36,6 +36,18 @@ class RigMainGrid; class RigCell; class RimFishbonesMultipleSubs; +//================================================================================================== +/// +//================================================================================================== +enum WellSegmentCellDirection { + POS_I, + NEG_I, + POS_J, + NEG_J, + POS_K, + NEG_K +}; + //================================================================================================== /// //================================================================================================== @@ -46,15 +58,19 @@ struct WellSegmentLateralIntersection { cellIndex(cellIndex), length(length), depth(depth), + direction(POS_I), + directionLength(-1.0), mainBoreCell(false) {} - int segmentNumber; - int attachedSegmentNumber; - size_t cellIndex; - bool mainBoreCell; - double length; - double depth; + int segmentNumber; + int attachedSegmentNumber; + size_t cellIndex; + bool mainBoreCell; + double length; + double depth; + WellSegmentCellDirection direction; + double directionLength; }; //================================================================================================== @@ -128,6 +144,8 @@ private: static std::map computeLateralsPerCell(const std::vector& segmentLocations, bool removeMainBoreCells); static std::vector findCloseCells(const RigEclipseCaseData* caseData, const cvf::BoundingBox& bb); + static size_t findCellFromCoords(const RigEclipseCaseData* caseData, const cvf::Vec3d& coords); + static std::vector getCellIndexRange(const RigMainGrid* grid, const std::vector& cellIndices); static bool cellOrdering(const EclipseCellIndex& cell1, const EclipseCellIndex& cell2); static std::vector findIntersectingCells(const RigEclipseCaseData* grid, const std::vector& coords); @@ -140,4 +158,9 @@ private: static std::vector findWellSegmentLocations(const RimEclipseCase* caseToApply, RimWellPath* wellPath); static void calculateLateralIntersections(const RimEclipseCase* caseToApply, WellSegmentLocation* location, int* branchNum, int* segmentNum); static void assignBranchAndSegmentNumbers(const RimEclipseCase* caseToApply, std::vector* locations); + + // Calculate direction + static void calculateCellMainAxisDirections(const RigMainGrid* grid, size_t cellIndex, cvf::Vec3d* iAxisDirection, cvf::Vec3d* jAxisDirection, cvf::Vec3d* kAxisDirection); + static cvf::Vec3d calculateCellMainAxisDirection(const cvf::Vec3d* hexCorners, cvf::StructGridInterface::FaceType startFace, cvf::StructGridInterface::FaceType endFace); + static std::pair calculateDirectionAndDistanceInCell(const RigMainGrid* grid, size_t cellIndex, const cvf::Vec3d& startPoint, const cvf::Vec3d& endPoint); }; From 8781e1362772029a861ed25f06eb567e6309a1ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Grip=20Fj=C3=A6r?= Date: Mon, 22 May 2017 15:52:32 +0200 Subject: [PATCH 156/157] #1497 Assign individual colors to well paths when importing well paths --- .../ProjectDataModel/RimWellPathCollection.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp index e243bdccbd..abc22c9d85 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp @@ -22,6 +22,7 @@ #include "RiaApplication.h" #include "RiaPreferences.h" +#include "RiaColorTables.h" #include "RigWellPath.h" @@ -223,6 +224,15 @@ void RimWellPathCollection::readAndAddWellPaths(std::vector& wellP { caf::ProgressInfo progress(wellPathArray.size(), "Reading well paths from file"); + const caf::ColorTable& colorTable = RiaColorTables::wellLogPlotPaletteColors(); + cvf::Color3ubArray wellColors = colorTable.color3ubArray(); + cvf::Color3ubArray interpolatedWellColors = wellColors; + + if (wellPathArray.size() > 1) + { + interpolatedWellColors = caf::ColorTable::interpolateColorArray(wellColors, wellPathArray.size()); + } + for (size_t wpIdx = 0; wpIdx < wellPathArray.size(); wpIdx++) { RimWellPath* wellPath = wellPathArray[wpIdx]; @@ -242,6 +252,7 @@ void RimWellPathCollection::readAndAddWellPaths(std::vector& wellP } else { + wellPath->wellPathColor = cvf::Color3f(interpolatedWellColors[wpIdx]); wellPaths.push_back(wellPath); } From 2898884c0b7fca86bd678ba478f0e6b144d11bed Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 23 May 2017 09:24:03 +0200 Subject: [PATCH 157/157] #1513 Update point of interest --- ApplicationCode/Commands/RicFlyToObjectFeature.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/Commands/RicFlyToObjectFeature.cpp b/ApplicationCode/Commands/RicFlyToObjectFeature.cpp index 6ead54ec77..db3b311e96 100644 --- a/ApplicationCode/Commands/RicFlyToObjectFeature.cpp +++ b/ApplicationCode/Commands/RicFlyToObjectFeature.cpp @@ -84,6 +84,8 @@ void RicFlyToObjectFeature::onActionTriggered(bool isChecked) cvf::Vec3d cameraUp = cvf::Vec3d::Z_AXIS; destinationViewer->mainCamera()->setFromLookAt(cameraEye, cameraViewRefPoint, cameraUp); + + destinationViewer->setPointOfInterest(cameraViewRefPoint); activeView->updateCurrentTimeStepAndRedraw(); }

u@f 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_18/FORECAST.index deleted file mode 100644 index d3ad129f4dcf4a4d7f57ea21c5535e3c31f376b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZ{lKWJ1z5XQ$Q3dSZjDhUV{@y~g9<|0X|m&DxVQ13m?XRZ*u*jc5svRMKFJ0V1{ zNR`gY&PId>c6N4Fc6N4xVCOeGnVsEieBoH`<(F^1`DS-h?#<8{BI>@ozJ-Nu;WLfT zcwCJ(SIX*cyR$@3@HAie*F?<}(Hz!ote3Gq96-Nf=~QRUZbmhS}cr^gccvv^ex9&IQi1d&7OOZdVTnCbP)kuvVKP%$I@NWsug z@k_ua>gSvntLn|5);Be7mMfmeI!47f96B^^_LviARd7aEj8XUAS$QJq;-i44I2#3L zG&Hr;S(Q3_W1KpZ4m@Z1zs@-y2fNcaXw@Js>RUh@>1O#MVBCVQid~iDwrhgw&Q~2{ zTA}I-gS2WSW-YujE)|O>S{tNdep2W&6ue-JPD%={*NOZ0#%V#>YckQ`j6Mq(#}Vgd z;P)K#?vO`t*R`tZjyth~h*t80=ubIOvmgg?AFC)web490QQyI(J2FoDP90#(nS-J$ zS3!Y$fUkl-H;81`@eX@x(#d%GRS3XcG)4oM!7B@3SZ%fMXkP9>>N+6T@Zlyo{55RF z#TI@Pq~CapC!UgTA9*HM)sAoumw~qLr^!bp0Y3;B3(D9}f?spcSC(tWf`6M=_7U>= z(>C05gET@9mGLoH$srA;(^_aPsao^*Kh`9aaGlai6HG$Ee}&{~D8A)_#~aZmeAUEs R!k$43YK+t8hgW6z`# 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/FORECAST.index deleted file mode 100644 index 8006b4ea6a0a8a28bc3c5d69db16a1c58a95eae9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZ{lFKiT15XJ`sB!DRf2qYwkHsxqIXn|I3x%Q3=aJxB{u0ULIs5%s8LqdWAMS?&P z3<_6AvPoSX4pmo&AVJ~y=FQH`+k0V~m)Gw7?wfD^yx08A0-YeD)sIU%*yuXeX{_O> zm_AtPuhUaJG~thk>XSqlvF~C(i@joKBQN?2)`yG{H2|()XYdqusFlW?XF|j-U}uI! zpG-C%ZqM@Zqgh@|XItap5Z_q0Zv~f7zC*MO`W^OQp&FE33&;2rPZL>Kz~3%EDRx$F zs&4j$vxgh3Ygmg|!EqHizKWN4YDlVMi9MG-eHSo}eFm>8WP~!^(xCKGI2OE&Uw5$w zZj>|U<@}IxY_1$X-Zm{kI_5$HxiAL3aG|(?_u;GGyWP8|VDneNB!ens;LcvTpk^Qw zk%x(}RGXtzFa}MLex_hMI#YE=mprOABC4AOrBBYOyTC~n&b>}KHpgXI>*2=&{}C`Q zOE8DV8gtIYI_9MLmT0}_oSKt{72dGAbVwT}V>z&cM61qdKp9Ip5|(E6OTgHDd&Z-P zBUjUi0m@@r8!5!FA1+ilIlI|iIb-qJm39ou&bWVeb*)UqSw8eN<)k=KHx`}I;dFWZowpH+LN5K_P+YP*50cqkV(_CR62AJBh$Uqz6lt2PzHbQ zSiW^Ztzax@CCv6yL75$iY+!Scf}z$ZkxqVn!=q}g1B1~q23H(E_52;${tK~y*$)B# Pld5s_UN{!iRQb(6QveId diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/PARAMETER.data_0 deleted file mode 100644 index 487f09c68fb880ade5d1a67cc9b61a338bd44399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|{eDcCV`|Z}Y(KGm&4>XF+pMQ$XqhPe}?}I07YRqs{jB1 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_19/PARAMETER.index deleted file mode 100644 index 97668fe2ba950099154b54eb1f9205e8c0f8056e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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

ee=^Kh08M|7sxk}?T$d~K07WtZpmhku7x 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 ACjbBd diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/FORECAST.index deleted file mode 100644 index c9cabd67fe130bcf2244a7eba6673464c57b6c35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZ{kKWG$D5XQ$w1+|HdibB95qUY(E9GFxaHFqBB?Q*W!!r~M}tkOuTG)q9Rvl2wC z>{6w(6Bg|3?5wP`v$L}En>TOXyyxTgcns|Q?wfD^yenTV(GenAdv|FYfv(^j#~F>Q z+1>tNl^)@tDSt)O9wj=9_yqA7;%HpXlxeRrAW= z(*h8EW5ob=KXNc?Uf}4>0*gGYq?WI_pzBLhg^AIMiD_SWx(}zD_qOKcrDkmxevb3`}4rmDljw6$ZB`T4Dipm7fQ*_p?4#;8YWOvzhijrm}l z&dzbDH{tekF0C0q$Z9TzQgd-lYW~^x`;VGKUzSZ-oyOY}tQNloj8`_YY8PeC1hu5p zDlS82wRN`{<5?4{FA+uEEqic52f4b~{cn@#b8gpxe&vE<@hu1aV%Wu|$Cg(ANgPzh z+q1C%;)|&LrWZNHzHVXQgWhWIrh?sH0potVHA6~eTKs+R!!a42zo=m-^j*MMOtTJq z_^2ZN$w4;<3@y2+JHl~how9F8)U{26v};Zb_7btT#;F*WT2CHq1!ICFr7q!}-TG;@ z-M_AQ@m^NH1#%H*1;=#{vrvYxWBkP3^BtZA=2Xr^{Rmq`yT)k=@m>b7`yyaG34Zer D05S^A diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/PARAMETER.data_0 deleted file mode 100644 index 0f77feb6135979019ff9db48537a5f8faf5d3330..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|0N=zmPyhe` diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_13/PARAMETER.index deleted file mode 100644 index 28e06a2b12467603445ec4f81b8814115ebdba7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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 z 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 P+}vF6ivI8U_x^tX86Try diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_14/FORECAST.index deleted file mode 100644 index b0f52d506775c1e99a3c774afcae19d7ababab27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 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 DS=`){ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/FORECAST.index deleted file mode 100644 index 2852e1d32ff2a47995c511044ecfa5a89c865372..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZ{kF=!M~5QfJl3dSZjDh33L1ic)dCXl4M7_*l{y1?GO3F3?!Bo z8m9^8@u;e{%iXxL{+WO^k}cvdC-o};*b@9UORyNX1nZwO1P4==d`bl)>ue>jXK)@v#{XHM7;6=OPzf!R2leNH=0y&%!HAGq< zYT>x|f2V5vfejq^oDLj6q=3Ow9ymvxFmS?t;?#U`RKLYbIoGy>PXvs;T)-nMVN~pQ z@2OGlqYOI-E9GG(TQ!aL!3c{;Xy z8wT;Y8yKW*@M1U#twa3TI2DUVTPTjcr(BaXIt(L&&Pi%wUyakG{y<;_!R)KXw3^r) O<BVcSBKlu;QUJD`s diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/PARAMETER.data_0 deleted file mode 100644 index 30b22bb3264f94937060fd05ca211467bc157539..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|Nojh!L+-rUugAzbJ+qhjz)x;Vslb;P?WcS#|8B|j oV!!*vKdS>Te%QY+^6YAtc~9*3eL3`|c0J<(khx@n{|x^b07-Q?HUIzs diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_1/Ensemble/mod_15/PARAMETER.index deleted file mode 100644 index d72eca18318217b61054e96bf0df4555250a6c28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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%0ARgQp#Xg8@X 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�Uakd-OGGd7; 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_13/PARAMETER.data_0 deleted file mode 100644 index e81f2dac3ad113b9f8610dfab4a1b06001b709bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 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 sVk3n{<12jw{|dyfU}fcC8JeH&&{vqh z_!iuxw|3-K>y_O4xlj#lH4`?pKhof3c(Qo9={g17bj#G5;GS?{mQE1KMe9Nr{}Gh3 z`SQ}Ye+#alx{ca=?X^~Fc$*5k&a-EQ=%cCWc!c43x5LX+Ei8nHx7oC!CqQyS45!5G0yQ=MUQyjoWwAQh!p8RofQYHAu_hf+~Wbo*Sb004=(Ic)#{ diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_14/PARAMETER.index deleted file mode 100644 index 5e147e8afa38d37d1fb4ed52c400af6dcb53d361..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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 J=lFm7{|Bhh`_%vd diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/FORECAST.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/FORECAST.index deleted file mode 100644 index fa19a420df35bcf86573af78fb573f48d2d0ec8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmZ{kKTK3X5XQ$wOq2#2HA+ZK)aZHP)Z{Hk~-MsM3O(ul7g`F9vm5pibJ1o+=fuj=K7J@!g z!PRpCM-aMK3p%h|FBr7!{-mIb3^3xp2p3i%+*pQ(Dd(y!^MNKu4~@}kXK=LLUwgGV z%zCef{d}i6uXuIJZANpj?qfZ`svBsMcW{W0(^JW?F;?$a0mH^z!%-*8i!C2$^;!jZ zA|^AQl8ZDVr}h$_wj21-hS0ysV5{-Gv83SWG6gvWvlf#&+~{>W&DQd={#WHL60k+0 z$Jl->MB{J$J`i>GCF(a%wTjW6L0WyB0!A@SVX+=Egys}xu{)Q#Xl&^D=(os+E`^}k z`6~t4&Z75b)8{HkG`2F@nIG-ysX$z`S{}}i@6PCZ8Zfw`o}&*Ys9lr_#s;$bnF`84 z1~1o~iD`Dh`(Z)PjMJb_3-?aD!4>kCRw|E{7hC-+VCX??F(y5+nD%3f+d5_PV0(2s z7IjWTQw?svH@G@Ux%w%wyGUyW=`=d144;T%A`~dSn*i~x))rDfh3YmBJTq;KTE-{; E0UmA&tN;K2 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/FORECAST.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/FORECAST.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/PARAMETER.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/PARAMETER.data_0 deleted file mode 100644 index d5a3cc93ac1708db1029ba0e19d8d848513f07b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmWFy4Gk4xU|8@VWi7tW}b~bRXFB`OmjkU&L^reg6T?E%Lwicj_MEoHt?me!Cfx>`BiL o?~i9LIQU8DjQ#g4U;fK;pWAPHvdXY)$&39UbIAn%8U8Z>0GggO8UO$Q diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_15/PARAMETER.index deleted file mode 100644 index 3e91b0686693d0eeaa22edcae360f6c6cefc509e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmeZo6=GmyU|`rkT_X%gf!QKJI@r(A+cn(xwVtI(?$u{KG;G+gp$}uMLG@aG`3n_eDkfv{?|(1m{{BymJ8b^nGL~7mm@!`gSXok4@~q}rixl-pQ{Rgld2tgjZtle`NiIp*hSY6I z+m7TNNZFCpoxJ+aUVT@uzMEIy-K!7u>U)v}dy$czy?Rres1LctvuB^1Tu zJ+FD@96{v+Jx_S18cF4yJ@gRht^(--l%Ex!5c((8y?YY78lIKs)tg~sknw~+Pi#(5bzVu8s zhuW9%Z0|YQbBE_G&**cheO}K7o6vv2EmzYs$a9hB5zm*N$(B<4 zGUOljhy5LXF#c4jQ@6o?9Dhu#Qp~MS9B-cp>-CAA+R0}o&E(Wker1D+8su@xA9D*j z*`ag3uz0KDPTSePw3DA%THdLq7ODsbL{xV2jccnq&4r^iV61Gl;kJi$ovQkc0H=ua zv4NA-E!-H^o72>(Qm1d>G#O8}a_X38q?7qoZtIk%&$M&e7#%tw?iH^S;=u6EPF`ee zSEty}2;>UTi$eYmA$%}EpTpbK;z2h`aTuh8{L1b@6BB>SA)iAyPhqtXnLM z7kXT7XxI2d<<;?8!?7rv4r9U zyT~ySkVk(EZJb}^`J@a=mGhq(a@w{NaX=rDVE16E_566{qM;~ zJ{X70jC9bNf=~~vOrC2@^^skvesnO!U#CG?dO76fc2K>~F{tKWrSgkUDL(KGnwoLu zx$8g+UxFeN^^nfa&Kjf*0LpEp}6wjtX({?_U|Ihdn@E^w?Su5SC^6t2=egyT| zvS(au3S^0Jswy=iQ6F*qJmLrAFG4ZtvXkpmS5beX!VRZx@#+>#c=E1OZR&E*X^OK4 zh;yxa=(N|HK1R7;>ZeXN^uaUK`|f<<)bl62Li|R)q4I@qo#y87cTO>``FoT%&HuqE zYyE`w$f1ueW=qs3Si8h$r|x?Yc|wZ8bY=&E|sTVP1|v# z0yF_fv3=%uc_=#^#P;jem7#oQuwU#cZ+s^x*g&Xj%!8`^Mv6OxL6hYN6!-nH9(lSw)LF`qH6Ky? zuPq@jet`C8-V5v}yIK&6;1C=K-ZT=&McFuXobu4|6*1r8c(V4x$ubF{Dn9;^JN_c^ zN8FDpT4yNR{-pbK!z##^)`O-y-M?mE$bGjQ+gzLcnj7jqsiCRIsr+dciVMUhQ{6*9 zpf{a?EbCs1Z_l9qAwg4$w`GKK$RUgE3u{j9`GEdJ&#MHj@A^Bg-hTCkyz0)|E>_#y zLKzt!@~X?IKU&ccstqTQWFgR@Ca`Lzdp?KBqBFgVXT!0&LLs@(x`ca;NB={ViG%IBP8h@((=ln(tPYEhs0l-c)^W0u4eB}N+^F@PeCEjpPStU3Bd1BTyopm+-`)&ytXs&7 zbgHziQGRl_bjpS=+c;TRZsbK~VxRUdmT3-maO%csJ2`pU!IU5MyVC{bhpTpTvZ*_} zBaWK`d6KBTu&0ad`tiM-Dt_hOu-hNV3+?OUV*7kRUz9&C8swB&K0)1SXFnIS5&io+ zZLJam;HmGBr9C*%#j^NFF-cg z>52S_2R$VFH$%Rpew>G9GUZE(A4h&bTnf-LhAsK(u<^1JC~xZ`5Vw}9&LLdgEyq;f^i$87GFl&AdTJn%O(SyDIA}lZfvnzh zC>o|+gm&lrp_n-YvYzXpEq#ql8e_3*CzBS2BDaKk$TVo%gi-yU*H8`0u*9_&F>6EF zD;Qe7fh>I;vK7&mx^{e9ZYY-3hPHn%sM^hdvc^`5FP?+^{YxtE9bLQSZMr0or{mB( z%1`m|a*z$F4Q)UxiYxViYS}O-$4;a2Gn!1j4f0#z(C)eb)s}nEjnAcnF@DRLcQBrt%3WyOSE(@{&|RKke!%4gnn!HBfO!Tx{F3G;5lJwg z;ls*cp2NCz$Nb3d(3odw-)l4vOPB=nG&{65=D)K26q@%=J@u^o-}A@z{(0_HrLtpw zC{LEfyis)b$Glw0+L)({GnwC_-KTlb9FI!#dfp1^mFpqD_nO?22YCQ%(gwjQF;vG!LMG~w z^DP6njFewBssOokO(7B>9$M zh~@1-@{FYVpe9gNX-ILFw$OeY5BZTjR3CDKJbaz(eUR$^SpmiHiDd7-kezDg(Dr}DN%NdI(X;7vMStqaoe;*D@T*^N~=Z*uei z$g2lYyx~30yJ?pd>fOz7eb}rIaNV+J$LKn~a+$8<;LjB2k4e{2tS5*~rX!HOenj;{ zDUUX9`qTQ>c-LLPI>ctlT`F&r2A?a67NzTNa}tV!u2Q?=hpFAXqfnkY2F1c{Pz@SG zX08HFwU79GS$8_L@6$ok=^owBX>(E>zJb~`Ooiq2p{$Ut{Y~Yw8Df4b22|PZQ+dsP zke^(N^|87V{fM0q8~u!#9{Ivux8nB-^hb7nEb5mYBtSo99y~$+rPxL4&jv;(v%f+9 zX(v3S_)tyCUz>Koa(3J#s1w$L{C5}>^JZcF{BBG7+_%S}UD1o;GR0{-@@%9$IK=>b zzR2PO?TYL8Jk}@=G@Y7YJ5-!Q=y&<-6;RlxP<6kPvifb z|LDQ_nD~4AY_I%@oGMkdR8CW~Fh|_7VpgYE&>*K%R_&4(HWme)W?U`gL8eoSA}+Ss z1B*FD=gx zij#+YK>nnr#i@=sN#+_(8(Pxesr~99pJL@Z*K)DxKCHHrub74WN}j7<*To{%ZK!*7 zsOMty{3Wzw`UarB+c&5;53BEDTQ6Dzr)n_{nj3K%qCDnQD3>N~6-+sNY$+xl`|c3;FM5EnF;rH)-kQ1yi(gnyc3# zi@vh8i*1im(#eBYk*iX)ak2O{k=z`ut&8nd1x59!$P4w|anPJj+}_peQW~02-wrMo z;b)-P(XFG4<*`J_8?D+8&D$QxA5EN`UC@5+6KET6?27hX1|gr6bNnfvJd`ESmGf~? zdN@_QhtNDeh5VAeYSzn@8@~&X_4ez^}^)HPuaUcP;|Ex@Ake|a(vrp*WR4Wfc(@hnG8kM zpHS}(M4oDvS*X%CM4qa)oQ85{W#p-LNtkCDfM#KprYm4S+0X7-@WFyXDl8x={FrK>hjw zWMA^larL~(KxlFuhB7e0Tvu+BH-kF%D#)w7hvrmxY8*okKLkp^h?MpeSvz)XDTo97OHL3P7OScSoo}m zHunUIpSPlTY7wZf(DPGv=?1osh3qB6=h1c#97N7<21Q^+s1uZd>Q6Vw2cCi~b{$%O zuXm7z8sw9_^(K0L+iMTH3z>@p8Dz~ zJtzP59r-F-k&&LeXUju*>y0x|H629H>9=G<{>nc@K>e!+{oP=10-8V7*#hmV>X<*V z!#40Zj&RQ{?Q#X0LhC3{mGe+4wn9zt=a z1oCh3V+G~mT?!))x3MlkmT4@_lcQHhKF%jZ$NX8QYeh!g2ifX$m|v^QBcV-6^LJUN z7|p+|bu&wJTuaMD@@7TI+A-{hVs{0)Ik%$-$t-eh8 zQkOKypH!SdP%n8!Ms1Bei}gNBzRQCAO$_fzd0gB>P%cRL-5pOhqb}4wK~TLLP9B{D zZOZkKXFdY;f-BH;en#ad=DsH0B_L}Q2yNo6&=h)2WO_hsO{y55S z?DxO|Q1f~e`}Tz5$Yf~Gt%mB+5i0+653-pt|6o6o6dM?xn4 zZl7M78`|=fpvvBi;`@D|{51`lzztNM=>+6|9#T9xS`@b)*^NV%z7*7x>OwW9J;iT> zpcy#=iX9WE{QhM4@A0Q!e(1KHp}x?lR`gr@r~+(+WzaNJj> z@^!i&6V!z4?it+IDsdCKzpFi`{^8q5D7xi_Y{>)kBc{qaXvg-0T2+FwL2}58y+S|4 zN}Pgb#3ra$E~Nfx{ZuH2kAQ4-PiQVm$V&%6JFXH`yGudcwg429l0zBvh5Eq)l$Yw_ zhY|Byo2k6pe5gZ5QF*dn!4&iK11Y|^1e#h$pe_1}jGB!;_f<#Qo}t?y zE0T!zd&wZE0`^gS=Nq)b564e7-2!byNjl!cs6S;<22#IxD=qbdQ};lAWDNC#8$#*) zZOu;o-MIJE|IJ^H{*HfZO8s1DCG=-vOLg>PdSV;&TXJ7j^i%3WH0qartc2pGKRpLZ zTZsCh50j{WsF#TDXa7RDPxa!fP^2D(`;Pyti2KPNOp5z~?W+OxEzb?P5SwrJ&`wV7 z1NG)AbRUMagFJT|Dj%N_iuie`e$-wnpGNnoc-fKeyJNk{4qc%L>;0_Ap2ZD>NLLN@0f#cxXB{+B(dUtm!WBIZM1K=nFBRP--#+Ch_NJrtZYs}*8- zGXUxx)u9^M8uF$6pdCAl%1dsCdeJ5F#8)T>7mp^`-+58)(NH8g2wDBBQ1$o)WrEhx zT{~X>ER@%>#c;7ITO0CmZOA*bs66roIk9?7*G|Tm3-yvPC^8wyPA~E52T*-PCGtxR zs_%IW+DF}e+vs>k%V=VEy9TXMC>Nmp-ohd=c~- zF@Mz$F<%rA&z0-&YVlD&mL-5cA0f6YZlPZK_d$EzsU()yiNdgc9)AFRj_)$s{)202 zJ9oXtc8Tt*XggQ!g7VG-+TOfrXnS|~QTv6BA^Ug!Q|Z5c|JwdoaMO*yJhB%#Ixn3bpORqGoVpReD&?qstrVjgX;*S(76qTIafRJ{jb9&Te7pm}-tPt4nO>-&+eUS~Xf z4(+19KkH=mYn?%PfeWXcw#mSgPWij+3DghCd>l^Z$DFD{;iFFdsreBnkG15mQ~G}h zciJ2QP)8m-=^HlI^H|=uI-H7uLfM703E*yu$cAJ-Z>cLj+gGc8TUs zARo7sw!2aj+8E2T!G6oLspvQiOpfDX66eHm(sgs{!+gK%C=)}A=ec3O)oSYP$p zIRBzZWn2%6*TVIoI`zTz!sji%>Dt-K>ux#aa&_CO{OjLwYL@6OjIkfe?@6tTZHl~5 z?kGs{k(^McP6#2|t+8xPhJw+2x z{E$>BXgiD_$=-N>ube>3v5UTFuZ}jM<(7_vvi^3+3*DjeD>0BCir)F4+C|^*lKV#? z)~T10zPliwa|7C036V$2L^UB#G7Yk-SD~JhANi%7J|61nmh4&)c_zEFg!0Xo^!(oH zyp(TF>k4h+l~DJ62vw$Rk8xgdw}SGl!F` zM?iD_2gP0UVBV)DH6mjUg*vTeD)&DF+5Z`TV*R~&-TOb){^J+0mFYJS9l@mm>zsVQJ?3QN zJD>y6>+aG4Z&w}@URkntRN?Ap^rrzj-i9g_|Po^H?Q}^mS#hxsU zoTmHOCQel`c5|ofwZ5g(ek&@SV(-c}PLn57JEsg;hd*@i9HJxQbGDO{^_C#_=AGE^$xP3xA6xBKJ;X;t2aG%4nw;06A zMdDDX`{f(qVzYNCwErX;>0)_nIOOqPK^22uNY#7HC|7T5<-i{bWcVa#V!VbTL+vrH zUc}n~)d8QeXg{zGp;C#LZy09TyHqVMW#SjBLteQt0G8hVF3NH5Zw z?e7t@)<4PXG3XC0rxVg2SURSGEF>EgtqM^*uPoK)sX-=eO!dXuLpioLRF8*2TiScE zYS042X2mMVBDO=F`w$dgBPb5KO>yK)DD(b;EWn5Uz_Tn7IV=s7H?l&pssNSWE=A>o zs!)0F0BE+-7aC2*Zitm00Cm#Q6gQa;d4omJzFkdb+fF_|08Qx=kfpo;`H-7rr-#tq zp%=l_^N-YS`cJ4XN1NfUH@hzm)D`GOG21aE#f8&T{f5jG-^xMpN$&;aVTGtXN--#! zmV#21gQ{mmXwy}Jf8U&hdR9$n8r6aPWIbqK)u-~)4Wa7V7_tlW!kUfSjOsHtCo|F) zK27YF)b259_OwDQ$FzpFwuJvP{sjEj@yAv?+Z^N0jTgh5y4t51PFXFlh7&uib(+2Y z+nlQY)jcR5lg*%fL@i9rMZ?=CT+H8}L4qTGOu&R%#%+iRv|e8k6K1`j7AD9hL2pcm zW!wgsFv{v*Xd<|jz6fU%&=)W4im#Z6Nxm8rA3m-=#zT?v7bX-u#|k`PlB+7=L80{z zqz6mweBZh4(RbdFzgFP^lT96f2TUsL16gJQ9yGC%iSeL`O`8B!@wbq_uS5^XM~SMKmB6T6Cdj7!Y+1Ll6tk;{|l^C+UD{23B6oBH)LF~VYs1I%2 zM>sAvEC`DI^u;G8=ivD1>Di$wdyVLVitfAO6!l79cB;JdFFI|b=og%F-`z;3Ss#vs({8>=_s52>r(L<| z?R(0pFU-LGBdy2p#{8D|IE?)?KP#Se+h+=Yq~q}7$QkTU!No|_MMMr9 zKYRQ!9mn3Y&!av{89Kf>u0#G+;<&Rl;ZQ#O0!3Sf{>KJgK&%?{h5GIbEGN48lW8>8 zD}A2Q=j_i*pS$-iwu9$ygYzc4-Nkv+_2>`Xwnq-y{;e;tKlb!~?4Qax5&J8f2H?2y zyIJYD?oUGJFMcWAaK}OAli5bijiXJ--R>Ow)M2 z(^l9q*QxJJn1k}}VY8j)Wo5{hrGWn$fBwGz^Iyjwed=;=tiMowY?my!AIC#oNq)(d z+j(IRoFZ>V>R%d_{NZB$xlVNPSKZ-mJf~Q35P6V#nFo209PyaDa%-DqbF$_`b34_w zTm@l^AYUhI%8MhORG_relv+{VDGQdX=oAsRD?3%-ma0y^ZD$R{UtZR7vNh}KI_=*6 z0Zx9XX#>P70+1KkQWAL)Z!w~oD`&fRv_O5eudSTo!%E7JA}=C8((imIKiVwXyLuB4 z+`*}n9YCIBQv5-lWLi~3o@CKpV>**AK0(&{tr-Z%X zg{_dCu8+Kl75of&!v)BnM8&empX}><(6kwcJWB1zM|o7#%TN{z9)R_g%8q=BrHzEv zX9)5tRx1bPRn;y-Q+EvVDzT@H$rwe1@bGFWdsy!UP7IxDe@~e>KNpkiXgwTn^!=D&yXs|vZ0Kk+Uhlt&$oOZiguV5r`_rg-z; zug?A5P8oIq@*0#M$+~+e5Bet$@)+}b3DhZ*Ab&6iM?>}KGnC6a)BHX54YFxA%!5Um zme3TN4cVzvQ2k_>H|nL{{B}?`#HQa;Xt&T8xJ;WEGu`%y#l^|MF3{czq4?`*sPFxR zGJXD8u08jakOj^nkJAq!$TYtwUh6yCwNvZ6K@g2PyjCwLh-;`(59ysjsE^YXuewy3tS3i&%4mX z&bYvpn|!UHeNI1wqq^NhtY4%KarJUz6Eb2R)cLPM(>KLJS8ww+ge=W0s8dBklP2CG zSFf^Hg|_?%$cu)OSKpB-axQl5WR#XrpPWwKJPhsF&tyc-C0JizGbsK{gsgceG<}~^ zeU0QxT|50+K-Q`ov^i!&`8gDtYj??IQ8dzmE|>(l-vX*%zY6Mu+sXch%CDY*?Cmuwk9bJsed)y^e(wijk=bXN+b&)s3H+b& z=fCGa$Eq|a?~Y5n1^u0NY`{b~{lq+{4A{3E^+gh`cdFp-7-#j{s2GQB#tIm>P0=YB z*Hx(s82{}&`huM4+zs;wHKIGsFXkSkdB}?Fm^bQVi>_h4Dbr#e%4;s8yeK$@b>*yo z%X?0qd&PaHJ@^RYA#0!Ik&8u@W{;h+`8dpnSrW>VMEO0KFPo{Mm_O?e8!?~Oai(B? z%`eq?h4r5NLcSf3`MCP!gZVix)gNmA^U$7+`xfnsXMt*1J}5^Oghmvl`cEY(&R+(K zD5ao1OnHDBOzrjM0@UsdEoZ(~M$Al8$n#Pj$LlF-_h&Y=(KkZz>?oBFyh(A{w@}{o z!92kp$VT&piZvk@Ln+R;1Ii%E3q{gG?{OTf(u)pa`ys?OoL(@pmFR^f?K9&8+D#6J zcGy?Qz7+b1^7esH{a6F_@JAHa&Wb$ChS3)p*zg62*}daXefRRr%;`S6_2^PnAWz&4 zip1lf**%v`xq!?t8>-dQpq)6A;%JMY&c6z>51Xm{;%;)%ev%)BChH9-yMKhXQyk=x z_Cr!=3MGK*HszIi61~u5!%x!kUH3peeHr9sdr>S3Kr!&fTY-o(H?tG}H!^v9gn~TlPUXYhM2UV)<-%%bn5UP=j zAWyp)+UiT7Zrla3beW(GyNTu5>J7BsT@#?*+??W6`Jhb}2g(CKupK%{EQ%}Vp>}WT zkkwm2Td@q)C!!au)aQk?{kjC?%P(U8#2(sT9T|`If7uiq5A}f2d5i2z=cnyEIv-`G zLJ_M8w6BZM@x2xu>e8EV{LS}b(4N_i`$(TE3eDqPxbJLJLHA#(U39-TdyD>sO{j4*J}Xq=&!|6+djbAy{Q3L- z&wtK;lAiup&TWSJnB8rUXcJJ`sV9GJ0^b$s;#A`Y_D6mF`XimT_LoU0k5OZ`Q)a5M z$jSYZQ65z;G4ei^BI6dc&(nN|)71Cd>tq3UF>cB2v%^uJJkBvE?|tl~Q;i5ai}FJs zBAx7GmWznb4ZZBt4dP#eOsZ9i_0z3a@T`CEdF|3g5r1RbWK&e9(G{aR?WdbD z;I835PWie>Y$sb1J+4#ve4{+EXPSgAmPz&|a+(S;lQ^vyn$*eTWJ&In^`fRk94m8b zxPL-g=ik?(GB|CARotoKw8-oZd8f{qqk@wUpI*@^-^Z!!G-K!bIe8-A zs!rS3R&$zxOOUUcS%EcO%=*--?bK&8)OCuN8S23_IRc!jP4W6pd81APr`5e0I!*Y3 zMov-TbYsK~V>ETDfNIU0Ld|aOlbBAvQfl{QZMK1y4sS{w%T ztzqq4Yzmcc@8oG&2dAiUh+HzNql-=9YMq=sYNF0g_3bA4W&`qJv2IjXl)seSoF>q( zyVHgiLSD@Lv-fZ@f06}xvEG`zmy6A@C6Ld^*BkXs!=V%{`?y$^`wdm$fBL%EeySJb z)QzL}bBeV4$@GKzyO@=g46(gX$zGRS##s0p7oi@1U5U1XgbEwli@diT&UM4 zL!PTY&w{LZGUU1D)*NWtrkd=Q7q1sWwT>gtl{;5azMCpP@>_O$7gXN`@>|vY4CT2C z@=nL{Yx+XlW*=n7=k+eN-ykno4f(0+F%PmY^h11deX%)iIn`$@Ry1=zlrv!RXm5dP2j^WXEI^82p3@kh+g^TWw{ z)=A|0S=(Vq2B&KHKBtop*jm^rj$|q2lpBL8IN5$B}Y%E{*L#`wrb-WlX#-uPm$(~R~V;baxpj6%EfdB>tW^2K;3|FjX~C_5QA73I0q zbf@jQdWKW@u9)eR$vVz*^44$2jrlO{vgcKyUbY&_*LCN(c4kwnxmfv^#K=LJsn zt`o*-ovQUx7xUjEmpN_CeHgb@)F!LYu4+?^-?DPp1{aI3XRH=RV_N z@%0yt|NV}gLp;M^9>Aw9IPYRD`(ALe=yfnJkVA7_aq`MP)`$WzUQD#0aaA`}0{_6665BEbZT&(e!Q+@E2d zYfTBriuWM-{bSdnwwAt9EIxTdT4i!CtK1BLu_hsYIip&6xY2MgGSy*Kf*TB4`Z5kClSk9 zM~-np_s=$rhp)D0zPR z;Y-z^CG~rQr=s7pnY@1QmG^va7ySS%j}nXeyX?~-tD2Jfy9WP2J+mD8JNxuDWc>%D zpX06QIUBnZhW%``>&>MECdY-MDXgPI|FN z1%^g(_k|kTE1J_3T@}MA%a4!cRPXD=bMp9W6FJ4(G>H+X&q*#W4B4_WP)@5z4k$;~ z^@a9n9;o&dfP95N)gKEYlg^~_>Fc2Fa)!#|vn1~G%;mCB3(4BB2B zp?JLAhu>U=&o!ZQupPR_6576@5!hZ8z6;yWLeF7;SgkZr zEgXgY)Qdl2zxkP-P`3Y#i4^2snLhV6!|bv!z5JtZBt8;7CTwFmNKBO&9x zsQmE)Xu92``g$qx`F46iDB9(PGAujf7ji?Tvr>Jp=~zxJd4SJXB|hW)>QC=+{@J#K z&{Q9U>&E0yK-baTvAAya*!y^XBF=;*aL3>Lb0oggK92(VS8f4RIz=KRjxxXg0MB2GTrrxN0{ybj`~wHhP#t%Cf8`|d>Eq7!`XhVq6(k&np8 z34L5_uf^``RD(hwf15lA<*kDtd%Oec6UU(GFqi7@7Kc3L8Z0McC7|U~Ucq{Gr-X?0 zx&u%&Pu0(@SI18@0PDY3Y>?AL-#x_1mMtFUOYH|;zv#GuQ9C?tb{R^^)JIH(f{$Mlm7?!6f`MMgE{!O4d(3;A3cY-{_D2n~IL9O0; zmP7u-DuqCu?GKcVx>G(>&-=lL{0(WoQ0)}WAC6VTJVE3Sg*F$>r^ME!m@la0^n#21 z(3$29KlYPl>4g>k{_jupxcx8RAM#48$wHT*%tt@)AS%)eD*QzN<{RpK5acnZlbhE= zIf{Nr%pAFg*!27fb&~`yaXjZHhdL|`6rmX?ZjqVdLfIg%n**wpIiXokv2IRUzf>sK z`RMzr`pF&o{B!gJ<$A$V`rL&Is{%)9AB*Bm#jXNr3#!FJo2`5~KC4RZf>WVK;X#99DV zyzNweh+dT8dFX{3cIzq1S&P@u&inw))vr(|{0&9aXs_IHSKEA`z7ZFi^a&wrl$h#Q zC!yFsDHO{{^^nwYl2LgE(i9?fb5boPWuoNNZn>v#3W|4}vcH&T!kBu(OjOJmzwgYtWPbP2XyDRN9hD27NVQ?;e?lI^H` z4aFu)E5xR9eJX!U@7jrd1rX~Jsi3U$9iO98T!JFYN@&h@g?vgLD4V{Z?OnGC@`8P! zNR^-B7x%GWHr`AqKbC>w@_pLxVk4j(k`k)a|4^5jG&gmnd^H`v92uZJJrl>3myZoa zxiL82dW;Wb-_zZ7$Dbdi-@sP~>f!v@S3wvGM70$-Z|d;F8#qtH3qxCd6wa$Dc@F1U z_Q(a*k4+e2RNeYeAB_gZtBtrWSZHk;iaxx=(4=mSBooAgGRjz7M=HZ>3~BO86{vD9 z#dXF;#ew1wJwjwN{c#|{Pq$oeu1Czg*M^g6S$5}cYo+uH3Xv1^KB#dtIzU@1dWSof|+?JYqN6t@DF=!meE| zwmKd8ra$^;-Y;?o%8M3fhsKZXC}_@e_h;5eIzq&WUM^a$DfAkGh8#OVC~nn>5f zn3i_ZS zzv@PX(9hdASD@}s??#*L37@-mY{V*Pjuv@=IM)_v)6s8h+p_a9CE?;Tl;_G}YQRhM zf^zyasAK;_aqw2EPq_`6Xgi@@LjR_WZrYK`QzxSGmRqr2)w&X73D@EC<-Sy8s@B*( zzH;_6>=%!~ez1%wp$x5$@yTq6#D1$}G}X2{zT$Z3YI7m4o*t@F{czk&K6+Kgwxbk4 zW(~se<%g!@c(al8PQN)ChVx;Pha$C*TcSa`tQE}%vaZ2+BNzOG^JowF(m3;S55^S{ zyaeZ)&xsGki{ZEqY&81KbkTY<#t;7NFf<|cP_M#EQTxf`upa537whHr7CwhW+p8iJdoxnIH1wOn>U02IhyE#OeLbR+A}O>%1t^a1{YJs+8i;v^-jLl{OYPcj zg=)-Ls7urK$x5fNy|zUa$g|JGewe9Ip=`Gh`)S)GfO7Q&90&70Hyw|MAviwL?-8B9 z1i7J(D2d}|d*`D0!pW?3{%!~0ILlXaaDVa#^qVK_WOkefeWp9ki^}kY?&o`_$e*E5 zroBYxuh(73?(L=enG2yFvWLpsU4z0moZ=G0po~=(nq)iZx=5Z5>IxIlkJ#u@p~O3DeErjTcmJq8t0BKs1KKH{(Qn!N3!qAw3$mHpFrLdC zg~)teF|Mn%foIWAOr-JLK6{OERjBLe7j>BzCtSTe7!~Tk^5{2t+J@*y<)+R@UA?|I z=?HxC{IJuE?nGw$74BmD_nmzwt1<+N$*HKk^2tMJAKnVuvfgi}Bwb+8K5-k!cb0%A zC&{msM=W@2Dj&FzY-y?dXKt)d)fx)r!HZDu&xX(CL0#zcQ_h1b$-3}=k3Wt7KjlC6 zd!3Eg-{cJ;JJAyAq+O{z-C)SsR4A7IL*<_h8Q)U*`>31TdgPj1P$g?Xz8FES-v;fP zM^JoEv)Q%RmFhz|dkW;WPmp133+ivDgJx4n$O0Nc)v!0!=bb?1vlmnO?9I?_4x{p& z5#;FGkdJx}#b7VbTS()%T=922|GPbE&08}2D{7bYHMG&Gy|_Z{Ri4i%=i7clmM#tE z2`pC~$R90&rg8LbI4%cZjLDWxr6b3IHr0Z(aT)K|71=Dp?q8F}np1ccP|Lxl0 zelSrx;QkQz2he;o-W%sG7S{hX0b zyL^ zLYC|dlqHhU_?o33wD(`bzdtpBe%tQNhJIYsx(!uTFCRQL6#YFL)Q9F<--0n7h(U8` zoUh;5y5lFeJcO)F|9dW0zrBCUZQ zecNGvV$wb#%eBY6#SXp!)xPSO&#=I)kY`SW`Hl>02hH=fP`#tyuHhBpU|wYN(r?$O zwdD}&5&qDWs|$IiS`>>)P;4(s@y47`m*mj?Ob6xW^i=;d3zgR_1jX1YP!(%O^;^e4 zU3UY;(dbc|PW&4&&q9ybSd5mK$EmPc(C#}0MaDlAKP-xQpQzg(>H_bMKZ-1Lfv$Qt#n zt7n_jLN&M;lu_zYEILDzdngp=CqvdX1j?XQr2jT(ukI&Pdar8iKZTfWkASM&1*mUd zhCK2*G;!`gnc+UwuYN@3qn}dT|2b4;UcCLkjX(c2|4}8U(YQ8XCiPFRXnYfymLfLC zS3^B}D`ctmL)+#!6sss-HOKE!Johb>{eM%uHXiyr@i`6kds*_3!^=X`v_6#0X#BSu z2P4+$ra{|(1=(#QwOhQEyuKak4cnkOyc*gr^P##i6tWBw3coT?KBGL3Z+t}Cd1x=R zqsKurye%2C64meFko9L2Z@f$MgT}|HU*CBEs&{uNevldM)Lcc&`Msg#nvcNeTbmdC zzKnPY)hK#3TzsvF{-15U3hj(m7zbp;C#crV#&{t5*T8rn^S*>E8vWZ%;+5}dcm3Lp zKOpnJgYkg}>^+O}Vsj&$>R1>Ybg?+u5z4ak{K)<&h;c#=*aAg~Di|L`j`yU` z28;_lb$=QU8ka@C&u{*LEcH(G^YUCT^wXwNarDb<%m>I*Z$bYo&(@`WIqw-LGgig? zTUXl+)ulA(r+L)T&_sI*W%>-1cV(^(MYbVO=Gz9%$#>9(6hptxtF)o{e&^B9++PZ1 z%L7zj^C&s?Dmm&6WI1DEJka48pq*b8N}s`y2k(Gl!B486K!0-LL;BFTk@padBZE`k zbH|yr836glQ{+#|Uqr0p_g%f5(F5|vo1hwg8=AJCq4kOLz_qg(3PbsB7@6uBG(LV9 zcg*!kWR~5K4}1ab^qd%n#M)+1w_FI#u}B)9QoMj{jllTC)1HRbuNlTC@rAxhq~3PK z_#_Tog7$e6j7xk1jZ0EDq;Vl~9*ql!wn0&Y{sbe3a`gLpZfmH%O@`*uPRQ5^@{;#xjdf&o%7O1*kWnv!HrLvHiJ`%J*G_a{YHG633@;r$-vdie`re=Dh>IL{!Jx4KL7iFk3Uua zKjlBBoZjfx&uWHl!uGtawFU84z168wH^4ky%x%9D7-$DJ@_EXf4J-A5yRpJQhkGAYazaj&sp})`<=qFjs z{t@UWjEx{qCZhf!c~vO;_J(ZDG>RuIBcrT_JmD&626=Jg^;EukD`Xu*sebZNiW6Ui z^5K1`K7Ay;f2&vw&Pe@DDD_M1Qa!|CRUqVvCPDpXEtHu~kt1J_Z{njr5>@CGD80HN zV%}s3)a92$TaljYs7fCYvrOsHPq95!p?uJX`mG`Ko0g)Nj7Zc-?(yC%%Nn|0C2-zd_OJ7sc!7E7RsJ zDR2HkIqOURhPVieM*Z+f`bwu>K>zkN`+wMb^SBE~O!!{3hxb7JdywINMC$2c_)E z(Bg*~pxoRN6!dDoHzr#{b5YAE-4k2Vm+eT~t|r!_wdG}x_0Y-#5tN>92dnou0p*j2 zDZGtDym%hud((T6G%o_0)sLm{UkNp&H9_Un=g^8L^>4GJH_%cr4KNQXF0{CqhH?t4wxZm*zN0~9_ixk-X>H9=(7W@X`7uq2XJe?o zd9Nlq(o}UZ@-@}li+ez}iu|=;MSG45ahK^isI;Qz!&3tk9#DHgUN{ra7nl4S&#N5d z2TE&(fJ)p;YHxI23yMv&LDt+3_C{!Wh1xfHrPNN^GyxPnkHSt#dkbN=xCt{srEetc zne?C+C@wlr?Y0a9;@bz*uJf~_c3qG5#7)m&AGsX|K;bV7vX>U!LHX};v=8}t)K4mD zgj2sjGarzfwVvWXS`%N-Bw9@X#UrCZ?&647|IPpW)At``(aAW~?kgiRL9uM^UHFBi z>>k1gy#d8v>G7(TzqU$1xbfOVmAq3e_!D_*coM=BJ>XX)Z!7o}Q3`@zk+ugv!||77 z_!sWzSNIp9wKn{UFlH>SOTJG1A1suHI!Qqv$-nH^#eEU#ETQ(W;}N=l>*>1$XP1Ec zEVi;CKeCGYFO+=?$iBCF0SaG6lAX3c2#ULDs;`*Q4E0U)8&CD`DA{Y?g}&1(f8r3% zZa*iEPXQ&J*C6Lx0`eNv-!C6sN%cLWW=&#k`p%$urBVHF`V-{2+IUU`efmCAJwzFr zd;XY?zc?L~x4)#{>9iXZLYzTqy&WhIT?6v_>HCHf=?l%;q=I6=Mx00SrhXabQkS0B zr!*9tzp)CMYj&Eri^e<1Aw%f-Z|DrNg}X_=a{~Fv(13Y_1E}4-l!k(F!F$lo z7CT)4rMsCR3+P7e;cHW=ecYc1g_kWr=8#3{!V*Ab=T%Vr7y@#$<3XWWE2QVOSA+7} zE1(j65fmn^A!-_e;yea&4QX!@;n^`dzbExaNhT4~e`3>qfw~M~(35m;~**02IMD|;Q=Y>CJ zgy)G_PbE7y`5~S+srGMBy>o= zqq%rq`J8(AU2a+!C^ue5T=Et6nLk?>S~|KN6!aR9U2mud@-}4Gm4JAPKh_T9qxI-` z&m#PuwBrorW0wWl{iK?9=ATor1H5)!l!x@2fr8BpkdGpN!zJCO@MI%UG|0j4ODBEl zIubv_-t!{{!G0<0j>DcQ1$rR6OhY||TT5X7gsg9{i+r6<=$BA@`$7vo{a_dQ-}IfF z*-^i*l0j4D#Mut`9p&h2D(7jxP|hrq-t&dYU8%e}C(!j59mjRc$%#nM8v2s|$^8QR z%1Up7(sUZXBPaZ!{A&ClyZqu2@x2{|{~AmE-`hIlI_1Cb5f3!@KmCvCzZ(Dc52pZ$ zJ3r;BeuRrO!1Kj2F5$V7dm7R6TI&rxSN1haMT8qdGw)J*z6$OVANztzP))ndXd>xH zJwV}7Gf;G(cB!17MfS?HX07*SkH}6nl|e4&DkyX3NnfVDf;jIzll;z>h_Upa`v6KE=-Vo&XGp?@EQE6aO=vVJd6d_wVT=?G|P;tY_B zTn#GyeL-PpEXazANbfhq^>XRdK9yU1rt)Y>d+a%$9Bp?`=R6SqTf8oBn=793D+rL#Uc+k=}@^zY8sO+9yqJ}G>qe^j{g>D&+)2LStj`|5IX4w@; zcS5OD$&bD8MVhc@tb7ekX)wG13SA$9@{yMyf8zz|>CZtn_ZjKF z6fZSbNJr;T{LcbVJX{D$TKU8-w8x6{>>adV5CY1RoIq~k-^97oi49zdVYC+uuQbF| z3~`G+$OWep_t;_ThE&;~rgDsFiYXq-p0}Vpc@?IB@FSjp%#fq0PytIpWsd|315!YF z+gFg^{Ft;>5XC<{Ow74U^w7kV6XEX^&~#q5=! ze8+>hdMC(->>{nb1LST{I5*4{T4)IT5hP1KD9xivdU?_5A^ISk~#wFQ;-f2h7Z{t5~MQ$fWu8RTCl zHRk_g{9E<>)9Ufp|MdNb=W}6?q#pQci<#WYS?+13u>Tw()I-cpM8eD(K2kk_Mr9r?v$XmQC2P}pD7AJlXL zv{KRy&pcokj%3pVr9=smpAMB;@l{5vOjj4s>*~}rJc*T~^`|=tnoNj{r z33XP{b-X73$`-CfIq*IQK;gn!kljiKl|w_x5B+%!N=88_XMWCjls`9~`oE>_+i-v6 zW_Gw=eBEZauX4-<_#64befSyCkfzQnx=!#jf`0(~i!|Uj{EKw5W@`H*JMt@ibl_LS zeKfV4H>?N$B6$^n%rXvsg%!{qk6b4X{(`liP5xuOH!1^Kxi$QRdYKJv-0Yz2x-lZxTjdd~#qY>OgQ z^G}!J`nWq$k}C~CH)a!Au8`Yt3+N(A}U7C4?i@__vC`81H7i3OG3TR~YG z3Gz+qQuyL%9IrI5@#j%XsN9GAhQH_iG@zwbwje8hMDe}4<2W`YglOLb=i>tVfUK!M zh1(rMdOm=beCK>Zab9sq3p!s*J7{I`P`dwSjZhz|mp()N;7ct)WvvmymHawLCzzc8 zl_L*{-EM=jKkd<~Ol?Z}bcm+kVa<>qsk<%6P3cGFaOVvu?AOPAkVbU^xmgu-JvwHj zT}R=5NsiO#etP$y`#UNEWS%Wi-;@!}K+%Vmq?4c2qjazHaU8RFM(K2Hsh#6cjQYfE zLs0*u3FTBD_n$}oW5Ydb^VRi3+Mf-I5!XQZ&tt@MQQAn)&)`uHx#hI?B40k9>f1nn z;;S6wUofR53i!?M*8u)6#+L%~7hq2kYbfQffTfOlU5A@E2X*yfgIt z{TvAL`VOG{^F7Gv%|kljYZS1&X&$)`X{lg2xa#@3Jezka6_823epyIsp0M_q!l}%-<9FmiL9>I)us+TvxT7 z!}W^OY0o_Qj=qfi?rVVZVbk+LsdWy@jr}Y}If^?pseC`sxCYUBH_Dx>%uQ5}7iU{P zRH+!yUgrFr-MC-ufGO^u(8~9z8ZU)!!+jME*5W>kGZv@d_gmC#t>v$97!bha5T6%g59z*iX~Oj`Aa67Zlz-AVIi;y5 zG`kWAid$kRK0FPSdehWgv26#m@5J3k#1spV52JB(iXLqx!gaWaaOO^X#7Prq+=KKd zkJ68>Pwjb$rgXCB)V>#ca|mble^GqL9-uO+Hz>dE3-X2iiBI%F7B~>(j0O|khY-z& zf?{3`-3+1mdc#2B1d;K>p`|n;XKe&6KO=G-XsHx=ST+BP|M{oyKXT<4dY)Sz1O;vC zpOu%7r~X7~KJ0+JZYJ!5{PzIZ4e?AR?1}It9(INW9VEMxwhVTN%b5VX#LpS@LbU^2 z-+{1O+?TPiV@m9D*fptrAnY8wau0ToA8hjk_9eI5W0mrjiX@eSkMa=V!S5e{E6QO< zm7@M2d%gnpmBnAXkK-oQ0+rd8u*2NCyY~>@X9%c>XJDsUWoMA{rSX2O>99C8osyph zyDog%1hN)GNoy68{a^MFlp0?pedaF6-}yxx$s@fi9|pzmS~#!d6a&i6+wi-h0d1iq zWj8}Uh5KJXNrSF~O}c{XQko>ub-t^@^(%{XQ7%%-f=6n8#a-4YFUfQV%1`b{dz^}= zssEYPs*Cbw4`h(r1v~D6>)?JXpw!3=*T)~HCGV5~W4i8fr$A|AIVhYG zsN7;{yi4_xx6o3;aQH`|!UI%V#)8#*bi*Gi`{=u&Jn=5HXr}}JC$#be#haNRTRIN@ zPaYCTlrlhWpeFpG*mMN>#ex~2yjB3Y={57DkL)1*o0g(tO?)W5OAw`Ra2HfAy(CVj zC9tIBUEoKRz0}_!>4y(S)`pldZf+x42Af@PcSZ z-vgOjU-&U4)tvml~2(yqs9# z1}YObQ+zXTQ2f1@baSFohr;DoTM^DLp>cvjueH!Z)=CPmXAO$y7l6uqtDOJO|1_z7 z5Y_b$CjQS0kX*moVpsqF{cw*t)p2Z9_5Tmle^md8+waQ%JCE(20)x;ic$G?NM~at9 zzNhAXl}gscBP!W!{*+3&!^`t3r9XYc5Wm-kUI6+xk5IL+g^N*Hy+>KBN_o>I7<@kK z77QuZ;>$y%tKW|dr5#NeXWBF&LV|Bk>?|JvH&*iH@H@;q3)Ha8iy99x%QYtvSxuj=_T^9hgZE(y!N`5;++UfM^mz z977#=TrK(_#Lm#bE9n?5lpuVi59`AGz4QRY(+4MMcg?_^HtP_sbfx3idHNv48c@ff z;6Wdjn6@s`i2@Dy65m(h_a*n5g%6rPgJz~QP>eV6hE|@;rgWpVNS8dJ>-o3?6fO+` zt1B|DR~TRoazzCw5B8WAijdFtr1IJI80E!`)`1G&6%@*8&2>I}C(4yInNH>0uM@}{ z=aC`Y5CO7-ZlFA$?u!yxm*VSslR;fmj{7EGUj+(&G%!dxwvP<7%@B|U)U2&zK?AV` zZ7mphVKq%$mW>MGAe45q=*6njRjMa0twEu94>`^aU8tc{D+%?9ySN)vmY7rhiq!`t zqsCzM1Ti>ZwwWeU@-8Q!#r?XV61)}lQ}}U*>g&rl^kTRy6OLVInFUAx|JojO;+*Hv zc>eyH2g>UrZmU|+&yP|mx#@shZQV#!a}%`bxlaFa6UTKreM6-jHR3w-h4iZ`MXNL6 zD*4E)E6^Ly5M6>n*0Bs!O1zOyau;x%)Nm>6hy3a^oiDr!=jZ3ny``Q<7G3fC{7OgU zhn=xP{>0NmkZ<962`ES0!u9ZyDcPUw0Fdu{1>~|tP>!wxvTnvm&x*|G`e*TU-NUQ! zd!nI4zyGxtu3KJq7Wq@^bU}W(4R>)JLjGR5&Voa*htfLhP&MDe+|8Ge|D(PkD!Guj zV3ktI2-r^+mUR~To)m<1tyiB>$?vv5jqoXsr&O}XE+a`uHE6R*rMPSy z{1@xH=?HWuTFZ>vl}hE`q$BQ^=sXDbQ&}H^`>iZ=qk0iBITq*jskp0Bad>oJCF^?q z0odl+BXHJTyg11l9iBn&txI;GaRBUsplJwu!P?XeOdM*Hs-_d-i(s$h_nXsHt<-Az zUL}{lm+a&0%?iRl8p6Ix&9XqD%Wl|X*`4gQm=y!Nt!%8B*uEqY_Fe2fnC$*Z`Y^=m zJcDMZX<-63yB_?7kXJJh?Q#>+6KS9_Z#)uO4qguOYv@Cj9GObGg%0_v{#NAo9{Cf~ zQ$XPzEgZx(Ge*NscBO&4$`}`D!JuYft}zV&Q3|FZod41t6!i<~JikLgZgNcn)c7;y zYmFT!CKckkl%kEGxTgZwFO78~4$VgS$oI@a&fzY~PgymF%F%;fd|0d%mGhJ$l)I2} z02Fm-Vhy`ww7UTXZT{LjNm5TN7D?(xX zOQfHihk7C{sQn!G*`N~jh&!bushZpRDnX^Vk2*93OWHG3x@7}9DCahXJ(AvO!~SqD z5-+OhrM8D*XE>u?=T$8qsywGs$aMtS_<|r+^FwS;Bi#8~ph_vSyPrz#tm`(F;_7kp zRsO&B$BosuQ}d-XS?7)XdRoEmNyj&zRJCwm=UJ7!TVvQ=)_+nc!XqP5PSWxi_#NSh zNcMcePx3e3pJ3tEVCo#9s`A?li?TGu#G5xX`vqZouAa+6(;D)_?=ecVpX!b zj&UkEt3!98-}>A`{DJlHD#b9X`{3unxX;3&&!FNtKM~ z(sA$XaURx4!g(dfr}!OyenU_kHyOXrm(d<+!nY@sKc99WS40aEFh`R+_+6_6*gxgW z3|yb^IhC$=`Ep#pP*I=C#pE`XTfRTl!!n8NsADq9m*3h4y6RxO~Up~5~lAHB7P9&ZOlHZT5>ZkRH+zf*F!lBF4Cgw zuF_S>{9pG|DW?PuQ7OEP9R-dJF+up|rV~{vAO1{HDZcPARmtLCPDlJzM>CazqBj%q zF-fykN}W9{RPulMEkOKHBKVt@tSN3Ys`I>32R?~~aE9}A9;!2f*!F*eA;EClb z`MnO%Qr2_Cb3W!cPSR?H-xuPCx~b`;Kpjz~JmKmV=sH7Cf5hDjQLp5!?S0g6@%?br zKY7~g)TR*DgchZ7QlD6^*#|Lf7#Br%KaX{RD?K5=Q z*e@yt8(MRfdpJG|`dK6>Ev;DqaqWVyYPe{>3zQqtUR`p`Nz%7Zfr8O-O1EhbX&Y)k z@mrTcb3SIE{E8-0$sdeJx74Tj-`b#Lm5<+7Mm?nbJ`xIWL3sj&{h0aETU%lsfuA^CM|u0ekS* zH7r$j+q8>?_59@cAUcPB0=HxQ&86YK-x7EtUmN#|NS@r z^-tfwoMrjNhQyn>w$9FwA284L;Nt6%(k~N^p$VpRLVKZ zWR+spTT_)>%E}ok*{h$kK3h+h!}zat;eu!4Tm0se;t=PgvVaOaMoQd)m-kxF@> z1N@ShF=C0T`C?;hqx=O0Hn@W~3i^XRAtSP~#oYXSVNBDVx994efhN zi0d`|ysG8VyDzBZ;)*UJ-N&P$Dur8yS5%6Aap4GWvizD#zNIGo63e-R_Oa4+ZG;*w zFYXfsj!lDq67Ow`QMKSt3qnfk@?=$uo$kb{ly>fff8xt#z(27nUHBy?RDisg7O$pb zzwW?4Nh?n#K>xidQKhhT(F2vrN7~z$UC@AEV*6fz{P-h}kWSC?u}Z$Y^%LlEPeH!% z=44ef&DKvb?!#43UQ`9LBxCq3HqHs;V*EkbF&yOe5hDx9GzfnuI;@7j;|o^7-%0OR!rv*AXkiM$csl$Z zx4t9%9@lg~s3h0QP|w4g(ZUh3RvxtSVhQ{pclk9ab})q>l=2^d%2Qg1NaSy2s>e%L zxX&tu(=`KCx88%6I#d4xe_#y!B=746a#bfu&#Rdb?S6y8ACn)I2L6B+Gdhr82{8vH z`6zM92awy`_bYyP$2O4D{Q>g+3*krDcp4Zi?dqS6e7>Rq6v}{)(A@Hxwab6llmGC$ z4D#(WLBXv#{Dbm+Bq-G^AjI@|XaNQm zRY~cbiiwZDf$Z&TP`0f({^})YF5oaIrisMQwiMoL7N{&SCjCO6;&*ie*|H9#%e5)K zZ7T|wS`e$R<=_7OhySWx|KZ=fe+dH*k5$W)tN+_ZB{PU!uTmP*e}_u3Q&Y0T+qS{p zO0%P3UxiS+^J+Z5;{Iiog7_YGlkGVPd#N-&hxWTNCL4BT55OKM4o_eY_#L#ctGu@jo_{&E zBc6YLy%s(H84S-q=lTwmThl~3<;#HgxQ=hvL5cN&J>VzOf@IYL=Aea^?O_+>h6bR} zkiP54*`vvBc#om*^(G+yi3jB^G(b%_H~^Zx=?y9tHT`M=osa)c=VP`0rgXy>fl{&y zF^Br&lb;E-fW(cNyeXHG$pYYr7CHWP)tUe6nMf zKS0@n76Rq#H;26vuQ`+5n)3jZIRmm&rL=&$TvgK_nn2(Eq`seEhZJQP?2dSb2A=UL z^ub#)uMIoI>vt!6G?xaLDW~*FHz#tMqbc3nu@wHD2Bt}ISvapOM}geW8=$oN5hysO zl3w+J;&*0%a_C2p)us>b(jYyYmutKXlnPJK?_^&mj=u>C<}?9KI8A#&2!W*eX;&!z z6D^P{45EQ?tPL$7$7NG~q}t~wKND!8Ef+liS~(O=cDu_&P+a+w%5@w~RN&T%(42)i zC>=2ZXo z3CxOdJ~VqWj_m!{gP>#+4~kD|Kpc1I3x(eza&13R`cDeT1>K?apJ>2=_~-%om$cEK z5=;XCxu7GIuQQX0Nu`u;J`Ch4oJkwb0;PGgLGh>!#V>LsIxYs4ygs1N@hO$71@+Uj z#^zU;dv2l<3Y*S8x+2`0J)_! zu!tAJ>A8$5g#BQf*1*0n&yTP_>|{6CC2?6d*ehn#6YUtK_BMLIXI`*#%5v%_XR)@_ zF3S3d_7d-AM(rnUS}2S&YXLhcJ@GoMU49T0P)4=LGGm^D8^WT>QDXKzyIdH{^|RdU|D2>d~1%hQ7OOs zb5ga_%IQppUCoKq>jjJl+f`)&mPrDQ4B5&u_Wgi3jD4)r^I z`YRUc?%Ll~DfmB(NBlGWM1<=}C@=A<7L{x0J}U3>`nWHmKec;>o}Rdm%=S99Ydd_w z{g(Q*#Qhh1hoBuR-JXGZ!Jii3$GH0QP+zzcqo^Hwpb^@!LP!kA70*Nc63XcNjMCej z+OxYuwIGo~t8~uw`5S*lR>&iF(_(ik-vIv04kc3 zL6$oYl)kJ41^11hXtD>C8~cK+&k<1a3Z!t$OB5a#1#;;zpz`ZB#V3*$`qvBud`90J zx!cX?`F=+e@ugnNNw3%gDt9A6KBq41gZSK%?1UyQ+`%_bhUR>~QvBFfWLGxuAisAB zDC*HbaA7?y+@XA@1(m{Oy`?Hr{2>;++lnJua~&<;UVI zDBb8x*R^UHs8pQ>`5WzE&$&90)Lsdt{dT;KK>AzF0!MRDW zi_*j8px8Vg_EO0syD7JnU`K^*<*=*VJ7-Wl+8$&>X#sil7W~`4|MXwg`_KNH@rVC# z0gCFp{?B{kf2GtwAMGvaea*rV%6HTU=^*t#D|6DRevG2_p)#8&eM+NrrbJ;L^&{~0 z={Vsch4aEoq+>D-e3ddIpk;&8bl!nf54m6SpoPrAp!Amd%@wmU)JN_zjptK#)BA&P z)dS(u>4j8ZLuec#7f%Cwc~{abgxYm-|1Nagk8X5a z;{lZZC@r+f66ex!r(Hm4B#ran`cr?4P+m##BSzvnmc^T-NozE`}_ zrsvkm7gUDR!qB1<^`}UWXP{q%Z3{qu2-}rU{T`iq<9;e}w8yp({vcnq58~-V1+Wu` z#uTcQ#wsA2y7?F4$I=8;ap;TR&{<-UO699TG4$;BAa5gJRJ ze-_9dj4MYv2Y*m3Eg=?IRv>)XDNxb)3CjH!RI1_ZWy3!z#jgse^bD^;dhNlOuqm2* zg0kjqV%J|F<40nGqgb#NROUaR36CbZAk(S@g~Wli`Rem?n~s9~DGn1g`CG{}Vbe3P zt{Tq*U1`GRP#cg6cq|Mdp1(*F`6K_(#Q&o+uz-M6kx2^-=scqZ z2trR{K?44)E%qkmXKB)&w0F*eEN2?_GF6IDw}p@70^A!9a1^3EJy+lp)Bbr_o-uxBQV$q1dSd z^0oX3?N#emi0hG?n}N#s7+j}(&4jKuGX>YLM0(L4w(nPfvKT=6ZaHzyJf!FOS42ZQ zV$os5^SAP_=Peg=lJ@kyyN>q4-Ovx@^?Xt8f=4v&17Gr<_PCv0g8RfD&;W&fO>rNk zEycLMLhLG9cw=WF>VdR53-yEJPhtWuw>by(M$jJ%@+Xhcgx=SmX(Dg?4#cIiQ1AGJ z%czI4ZEsMxav$}R4RQy?==z}YvR7@CESx(9t%kb7rSyYA#ukQLK+2X5XYXeIj-$Pdt< z^JdU_*cLZvVK@0__MR4mV*R3!AEAW_UH8E>VyXxEyUx03xAI++L1q6=>i6O4`!d@% z3jR)Qf2MJ?g~xK<&cAk2Ut z6r6bYKjFJG{GZ^N0>8&a&4iy5pLT&ClP`I~U&$6cJx_)mYxC8WRm`J>lB6xG>G_`H zL=*Y1*~3oA<6FR<2rYh*{dy7w`@|i+LNq=_Jmf>%xEEBcJwWmHR8ZdE2xMF`*|inq zANa>dNWWeNN_BNXCGi#6y+`CvxRrCs-W_cPN)Hmr-*l(Fzy;??(EQAHAeZnJ_E6Y< zo$TU>jiB;zB!ydOf~>GRX_K`e*E+C9!KiJ%Z_EzuQ5PpNJ{|S_ugp)t1=L!EJ4H*D`!z~X1rE_VZ(2FR0q*8d^J*1as z7venZesi2(IY<76>#>*0%e*e~EuELiKR@B>1$Cb73aEkI<}1!P(g zwBV41JNb!dC(?Nbi5s4RTzLnim+Y5&ec~}H?`^B-I!x!IoaInslq+YZN#%X3rv9`TjCeuMj_Sp!5W4QdE+Ff0md<RFox1{2FMv_z|YEcuY=W(-oO6)5C5g^zy2@Yzl7ggZ;YzW0l%a! zjpNvUzb-mQZrkt6mPWXp^|@KK3t_#IC?zdKejSM z`0f|xDh0E33siC)jTeJ9kF8ZoM->~D;@{ntBm80}D4t#oDt7CZso}!pQc&)-*;dtx zX+1lYvQ4;yO4g^>8kJ&?XlIpt_h1)}ei^;PcER}tF?ub|(|Ig@my7d9KBTGr9My2;=FQbA z<^D6F`Nvg=7tUF&L-=YhoR?oY#Y@##6r;>&G98;;7oR$!t z|L(L(@w)vvm6GrD5S2px<)P3AzFz@P(>xpAj=PEYC-o!2XPVI}S+tI@MQnqVK5`mkqv;_@;pgi1#Z9LFh7LD6enimJKg?Ov#qJZb!&sJ;9p(wo)HzdHEqm8#_@Z(bwa zYFZFl`dqWIrC-QfHC$QY^$wgiG!5xGCxd+Gq;ypaH^V^XElmVw4umK zI}ud;mV8j-xz}ybkE6sM2HBE+=;u*fXn}j~3yl|K1ID7CPD!al{YP>f$j)t{c8C^@ ze^A^?zTkJmFJ$5T4^6+Sl#S{8o!EvJFyq_GXm1Esn$%AgYDw*lo3tRL_?i|#lg?-1B5mUi^}n@D>!$exUg9PZVyFMfy-S>AYN!-!seqd6iJqwzB z4J7JKpm_a6_yyLk4smQp5B%O=?cpaR+e(~INNWS~Zw2@twlmZX`4~PQ1NUn{O-AZ-YO-d8GCX5wr=|op7R`j zLy9&#q-wD$!bhcW=A$o|a18!L32%28dP)&-_wXao4quL{lrr;KWVHb7=shWkkk{>b_gOM&iJVd3ux&CF9;)F3_NLS}1{1VIReih-CFRrQN zd!Drg9f!Y?HvEoP!@0&Y z;IDYwX!t8(F8M1VCO8T4xm_QF!-AfGx~-n7WIdmQ@=IU%DgN#(_$Mi;CH#}vI*I&L zpDplH+?46?PqKB*282&X!Y>Jli_s6yM$)`wX^s9n_58{`n%69zN`haJx4SE9I3IQu zenhmZ1HT~zt$@D}ir&-vYLhwe4`NfAZ!VM_fR{hh-+xWzv}Ut&`Jv$r@t=!coOX1+mJ0H(n9u^*intA0=wVCO$I(Lctb#T;5uQAozPYv!<{hzu4y!?MZe_1T3KtB*$Q2=sw z3aGS70Od_*iP;{YxOqA#9MS=qy@LKEwjz*NJQo!FXd^KGW;Cvwy|V=+_g0|T@Gp60bk z0nMSs4)@9KjNb$b3+r;zXyY8Ev}OaR8QYLfY_=2> zy76RxyS4?DpSiHhT#s0ge|!j(zSDPjIhV#8h@-R-F4oC`J!fSy(bfl)uh@XfT|2$SRt3Fxe5G**;)F10*`a1U$dDBjKXn|1kLwKb zu_f>~lH+soJ0mZG^0BSNs)ZDOlE%MCy=dGF3w-wh{&9*AD8Hrg<3fohg`Z4=KNGH; zA-~qzj&$T;kbSKOitW?s{VOyA6zc_oyu*Id`*xGQPh_>cp}CD)K>7T7P_ncmX43a_ z`R{Si!t_3%lGqqzD{B00c_`lhup@0^5q_q`8QiU!9Yfa!sWp!Jyq zmF#EeeU;p?*m#xvxF`2iDl4AcRVg3JjswHGgRH_jR@H2yzpRpv3_`n7ZuM7;s>RsX zXm5%)1EN$d+!%^>s2Ci13+ZodzST04p+muk`9$u;xSEH5`S*YNFa16P`xyR1 z|D}8*|0VL|zgQjeU&6@y@J~|RAo5dg?x1jeDkzp|gNol9_$xls2jtdF0j1yy_$lSb zc~H)r4oU*O&&pMP@LR(0At2x51^F%O)gT{4?M9*TIruH*Fl|6B?aY9mVtc$mIi)M< zeF^YW+#h@LS57oPlha8ce|362s0PmD-|?FCbR0`QOUJzort~dBh$f++ zFh7iRYtl;EMQD~61ah_Mclb%$Ntdsp_!Lu6sq9DOTY|#MV)!#9PXXD+nhnQou0ity zY5bXdYd^FYxdD{2$uA01XG1Igqd+0I7bwqdO$@9e|7Y|aR4QJ8;^0V-`}+jQHgBZ( zDKy?tnKzKMMia35`#1cfcrpZ34%2u&*_|itN*k(+*J)iVVa5sgMb2tD(Z4VG$@kgt zgHri9kbQOlMbohqUcUp#z5fOOC+$okzqtJ_$W;+V|I5(gwha_Nh89j_W)bj*Qgd49 zmsOHK82MRj0ur+_)7WP~? zdKh+`moi|##qC2tX{KKa?3q>rP|;ikd(H^2{C7j|3L&>-$z1^X=@rt#F``SGyhicSpdxL{>N_WV;LP_j&cU6&`s zg3@+-(%hH($Zu*}kiFyMRjq8ax(9}AzN=Esegiu%Rn7&K8?^3)(q0#KU%BcktLd1d z`5l#Fa$vMdZsA$7_c!e#R4t`^x&anlA$z;@XBg7GW|vj6LBa)hr&LOP zUInP+N3=SklDjq92jSQI>{H3Iw{2A^-e}+qt%m*ofB&ci{>Oi{t3GPx-^NqMEi|1p zbz${FhzrL~8b7|D{;*-HGh;&;yH<_=Sq#y!I`vZx#uBROdfa}V+lW~o$`3zXaBbzx zz*&=R_sv+j@Y;UeR2Pf8O~Uu--@l#Er)Z;2%BeALuOHT}{Bh#T z@3KFIg~@L7oqk4S1r#37a=R0lwJ~So=n2ObSj!9Ej=He^@|W>9Hn-C@H%Kg6XOgz_ zPW5ua-?!SA_t%$Pmv1!gmb##Q*?yO_tzHQ|Cq;}-9Fnroy!$&}ua`3;H(8~(UHu}$ z-!|uo_<7;aB|7)n)uAKX8M^qNj=l4cF9->~xbt<} z2FF(nEQ(uOf6nhwR!^Nadp#b#@YR9>8-DK)iw*bt)_-;H@^kkuN#e`s=#ZH|25?;s zE!QUm*80@LJO6c^#Qe`4Dq3_*l&2lL)Mb-UKRk^8;?Sdx%MpW>zq+>lS~8>ZM9X;b z){_rT)B2P~e;ePm;K#tQnI$eoF=N-b7izjr?%AZG=&fDK@rUA*wEO34x3ANAX;Fto zHUzljxYWMVMq}QkGO`cw|3#~iYpv8;G>le=XdIcOieXzNAJHru|&QCgf zsKcEYw|ZB-z1o$W>0GhPE49su$3J7bmj{>L(#sxLXV{witxt7sQjs?`;L@-}`ToKW z!{fGVp9~dpJyRxVEwT%E+5goW-L`ez`ZPE`cgwev%U)@j_K&Og>iO31vvvvn%>T?= zw5X-cVEgq$msqsiv^MeR>z)Wel*!^GO(}r^rgL`3}4@9aCd&I-D$_Y^X$`y+kfgkZpU7w*tT3N_Tzys zrYRf74XDs@=LUy2NOH)kav2ibz~OGe{ozYn8wYpKu+ci*z%t}VQ$I)V>GN&68{IhD zU_$Y?eIwq?+45p#FZ*H1i64Cbj3}!-+u-Q@*+s8D?Al-Q*eLINi_#NaZ+vmvvsibH zG{L^mTF<|ESKr}T0~}ZVFpKKyeWXWP)QXK6EA%R61jO8UvFMaX^!K>IQU13s_9$N( zTTAcwS`*J69hQCkam8`Nvg1p2a}PGRPaUT>bzScTv+@_m#b&Ro>@`}?Zn4dcsg0I> zbe-wOvYU9$OBnm(VNU6%_^D6rZk*qk zV{>Z#eV6#CjZ9u-k3topLgDc-rrN(8AoCG2dG+iJnksA5j_Kw!?+OW6rnRURW_}UwqhMyAk0V z{YGT|n7_N@C*MISo4k$B&uy5gxyw=a`?I%h7V%FVBmPX7Wwm?5)#lFjJ^J5|*)nou z)KPE8p~HaF1w#+pEs2dg@0f9EWS_5JvgQX5T9Q#O zWwgzG+tx9cE?t=%BgYNDkZ&FPd&?tl`kRmSGk>JTC^$H-8fMIbC!7_n}wv3S9R@e${XMY+A83=-t*=ljC*Uev#le8x1y`SgjXcAm^#e&x7F4*`=3qwAC**>n@fTUpqa#Jp} z63mQplg_pp;puE-xO!PbzjNb%&mYv!c*Vl&_niw{wRo6bQ9P$x3kMy;Szo4adK!J_ z=A1}hX~UPVB^PzNN$bkDiLDa#(vDbYS!}8*`kr{?ufy_(?BY$AFSdG7)$IDCB?o_& zpD#_^xv+Ldm_r?twcXkdxfK{Q-)hscxLW7D4qM;R3_a#vHKTUrr>?I(E2b<6+|&Gg z+obwN*2&RM5ACL|7^t)AhPY?l%$cQEd#C!ZOm(piX{Hn0GG%2(U3=V z4!_)S@y(9I5t`SO+BzZjZIUZj`|eqvkTHDAXq|m~Cfu^$Wxb@?hl6<=7E1e1p zQ}a^J4AIp|FJD?=-#)eENSDGKtL{2)ukIby!!6?0-|3B}BrREgwP13-NAa5ry^MS6+Wd7tWo*!!q7}J8?;NHWR~h>M zReVmXp7xUW?lUq)&CyFrXU=Zsll;#9?b-O)jM0-v-ECqx_kwvu=^wLZT7IoRv>d)V z?4G_u+M$&l`mAid+{whS#9)1SK(66ic`?S}rHZv}s8zt76Z8QD-UYlme_gRcT zOCeG`& zF4<11$a#I|SE-!-MZ?^sZ>>&+G3~Q1*Zp<(ML(U38rj$H=N9UT9`8n^PkZN8Rd-Qo zzew3(epda~soV4<$5E--4n23xEv&NoxuL+V%R1)%vyF$7r*$cpla|L-vv** zesJjQu=rAQ_da)?Oc_wO&&XU;bDdfPJ^C;1^j72IEt@X|zZs`*I#byDVc4g$CgQ+HZxDmTG80F z`3C0}iPx8{4Aq^tKI!_SLE+j@q!D$VURV{BHtv0!_(5hJJhYZ~vO048U8}I=#Zz{V zY#Nr8-m&9KjoX38Pp*C*a9m@}P4~6zOZVo@pLBV*v0K9D^4zN84c{cQ9R{UU4ld`t z4t!`is=sndGjI9d-x{ANlpoK$tEb=pVBx{O-_0`XxA@z@)6m>2Q2X$^3l6of>EsOC z<|57x_0ib$v$or%AIlptzrLq*8@YYh`fOprX7R_a#Dl8~h8MSSO0VU)W~AwiW=-cF z4RhJ|aImoIMaix5e!TH`n#oQ?E zH_jtIxTn__3XlBSXk>n%XyEH{J!dy9v7F~r(A{=u@zh^BG1LBfo%`N&{hJCueqIk%sggB{kQ%4PkMKaC4P8j zSGDI_)Z&M^*(|iE>}l8ERW}!Gd^bGVv-|5sK4-&sHXr8MH7ezJhY_`27WG?`RmZY@ zdT^s>a?q1CD@P6wTj?_C%wX>hp?~uZO9v~*O>?e$Hc9)|@y4$tBRMTI!7Rv_&nUc} z>iIdMhvl`DCrfL$`M$RB*K^;99f7&7&Y#`;#myh;ZSpdr#7rLDDcsL{_ALLjN8^5b zh5yp(+OO!n$I$c_#~Y842G~4n*Uvf5@`uJk4?N>k7sTOycb_!BO-dY>JWRzE0S zF~Mm~yR)5ldQY?VTQq5X+0U>tgC?DWPc3{pv%YVT-@8E?4_B`(h<`s!)9ual?&XUr z7I(Ulvpi|ts|;hKlq=(t{kI?cRAjx~GC#~;s&xG{`Nq79(tXwyR~jtE*d>e;=3RjIPZWz4NqdcsT3spo3j!9FL!nUwFkNpm(XOqt%a9FV>A3 z)5|iZ$sVYD*bqW`#hzxYE@}LzH%(1z&FF)dRlH+#m`!uqs&hP zPQKjnOVcTrcV-kWDsU}6m)_U?&0h11_Ss)H-!IJ`ny=Hj&E~6vo@dteubBRGYq@o; zZ7<%xS~WvkDGism{PC^5CCW6qble27L#wrk-y17_UH=++nAtuVX415Ky&Wm$d6tX& zi+74|7v4#)CtaMCVlJMJ>o@J^fLe9?`DnBhj&_e9RM+3|NDt2$J^1A3#miP1vz41S z8~M+!ean2?-*2Al$%kET4*&ah3+bkd-cHwgZC%sbzseiOav!=Z?O9p-c4~0G%lpo? z#s`h>JfyAO*hOw}XD)T!k~n#zOL<1yE-x(S{R%K`p?iCL@k_x8%K_ ze0XW$mgS>MJlr1Wc3G3$t7w5`zq$@fA8(9UJErb-k9lTc#tlB{Hy%^8vawmVb%)ZK zQyRQ`lfK^I=$Juo?E1}K(EDE7ZO;RyglrXD2S*l%w)(i>-08{srJkQty@rPFPp)_8 z<+iu2Pikp2S~Sxx%j(XA9>0^u@RemBF3ubiJX$;Mk8S#&)U2%~g>M>dd@|;ENvPA^ z4^uKX%p1OUk7M^cCb5O=!^{TX2iitwIW#bfITz*hbi$72>s@*|{b+DsI?=kldF8Jyj-QxSpzt4IY_S=#Yt)aR1N4Kogx+_k0>~il!;j;Q} z*<)r^g_ra=uD2zP_!*+UH0JbJ!O?d)MB^d7E1fE-U=IR`#Pn&tcar#izmT+YNhIyT`UHz55jz zpV|$+z0CdiZx1Iot9G5Qnr!j>HKX*a{_%S|inEsN3~zGc+r5PPGaDVq*RNU`^zh9d zch_$*w%dAj&RpCrWcMeNRsk^w%V!L}Fs-~{^X)^W7(b+QS$uA5q2TYY%wzRsMS~(cU#X?`7Fi zYUM_U#7V!CIMa$Zb}%dvU|XL&Ie^qCC)c#}HeZde_J;oel*l4~Zk5Oyn2Nl}-opdH;`y_fpu+BK zIv*w2PLh5I=J&7gx4#I^5(purMixJ(984inEdEPA#}+pj*lQ@6k&_VgEH~XWS%IOJ ziwW?*dzB2eCUJ=LRy_Tt#>c6pT(qS_97$N3$xV*j!^Tk3fN(iaXfD#^ZiX znEY}Wtr8gH@nyo_<_;hCy&Ncct#W|>S|ag>8EK5i0FXR|NMF(750DSiz>gSThl#C+ z1m@3E=!@)q=K8iU5TQ@8+F{3L6GTmRv?a&sA_>h)cvo&b_GOf`f37@M^ksB6`R&%K zA=h}uWU*Xm5N(EiS`=37417?QAyTF9h_!4%X&xK;`=IF%iS!X@_^beH>K@qPj~QBB zruWj=uDuRK9Uc$iqBsgN+bzz_YcFm*Tlw~$Bdk4K^h7L-Trv16FJ~w|?s`)`?Js{d2yV*19M3 zHoB&)fd?&n8Xd*$|ITG(K>d`nen9kUN8uqGJpaXfEy#tNp%-#7@{oG(Rf`7c%o&z^ z;)z!IJMZ<0pj!;v{+ZbjdW)j;;JUN&&H3_!3Nj!1mK1T=|9~%0#elD_*k46$p#vN7AOZrSCnT)(j zH{U9?$3=cMyI8&X>f^R=(>IIqHq?-r6$kz8nTn$u1 zq3zw9)Sh9UUw-kwq$;O!kB{_=JIJCgU69wv4aK}=!Ga78mb~+dM&&ZJ1 zw+VJgipasDM|5OaGI1Nf`835$!A|ON!mn|GKq8?gwT(oG{-GPo)j15-$KwJ_wU#6OA@Hu@;p+3Z~c_4^KxC`$4O zT1XTfj##&?AWVcXCYi{mWlh5NEFd$=r%ZYYZzzOG>NF48jwdOnoAoKN*bjP}Y8L6V zFe+|N=q6_gvxv}_P};tW|Z_>r9m-LMNPJC&bGToXk5V z@Vm7KQ~XkXF&JwTHPYJfmrT4A?H5vwKM+B{ZQvhux zDa6;xRv|IS&{lNf_e0En1t!%&;#n!d)U@p^hBza^%ty%UVCP9y!TY1_X{SgjY(FJB z;@;j3wj1&@E<~W+GiY4#rORnh>fdxOUW;uL8~zv;mmSzZ1=kirIBo|FkH~5LbBE9l}f~ss*sfF`Wo&@)0e-wQLM6Wd74gIl*>=_HFN?kdQ>ji{_2SY z>?eXVr%(3e$|82lc{^?^S`hH@R)?D}m zwdixSENTBqnZn^gse~~L@jfB`??*KjlUcUZC*Q`5r+)MgS9Qo*& zzcVjqR{pB@D3Rq3KO$vbyEwA7Jfe!MIxHpG21>!;-A)nk(>(-P9~`SvrwkfJGP>%| z3f`ZO=o9zIt>^nf07JWo$s!$Lv(qBI5oXioKHea{wr;4A0OLM@!JYJr*AhPV-i54Q z0ucjphMm-jrupKe14o$iL~+PMUi+|S)y}1}4|2xLg^v2-4(vi)VsTl0JHP%XBHV{V zRq?Labe5pW3GeeEB2r(0H#qbTY(LRf{QQR)yl_}tY%VfEc$B2Jk-e-`Z%XX;F&j{{ zQ+ciXZy70UABweeTPgLfH$BtTm45(A(x4n}O=~$GXZXSm;OJQ1WVh<-3FF{*y}`mc z%JJC!ww2s`MOF^9c8PCT4$Etu9Im7{-So(6do=6x>@Vc1 zJI$`Gf5;u=upCfSpuDf>pSS(g?r@3_E$P?s2wj<@uu24$?QPiYe~Z$)@MzNRP%!1L z=LmJYTOrKZ{3YbD$HLBTiZ9;&`gQn7ytGk!mp6cC*l+V;9p{q-Q#`!lncII~uUl|u>n1$|ZM4A|b~NlVxZ6?4EVW$S z4M{PRs2m2<#9JFT(%G^&`WIepn_{&|C&^&r#5r5oxvHnEMJGfb5A(ys6XcBBt@TN9 zN0c!NDDWGu6}-#VLY7NneFHINGiEWptlR|Ag!8hq(N#Ag#PLPcYdT;#{3`OiIGb?} z#iZ zZOp%3N=CXi*J5H}nsXA>fP1PW1f-H!1in>Q?7!vFbJh}-uDZgxFsL3Ir2VOhE?YLCh&nk^s^~m*BErZ#yJw;c z9IT*TmL;@lJ1p)5;AP6!WC!^Be_Al7gv+j%{3g4p7j!w*TWcfur+R5rF~B&xvlJ+i?h3)@SRw#H-zt;o3Q0CQOBUt>2}nB~=$d!CaweX3*zC16JueEl_5^gUJu27TjsFxIvlcL^H|Hg1CpV9PiXbI{lR>V3dtmF zZ!guFkm4wzpfXQr3nQIvQ%z(+tN{iA_x%+aW;+>49u^Ay7`dy4udRMa52_9mbOkP!=uJMVWD` zau&AAQZ5>!xc_*uV#S=%=$Ojp4m$DhL+JZaa`2Etnok5a>96b~zIiL9L?;D#csJ^5 zbk%sSMD!yb6LHOm*?I{}pn;1Y8PJ4u-m8I2K3fA3=e_NonzZ^mmjRVzC|f_1;Q4aA zi@^n&C?~$Rw|`!YnE#pC4xEVBGf|&9?TxQI=;=-Y{eY!$lY67;pY94?V2ltw{X2D? zN{uFjI@};i1-I^F?4JE6YX{3P<8$#y*;h0})!;A7-Y-x69qnZ0X%hUWIV-GOG{f5q zK;KcBSVAfpr>KUn`ySf_8VQ|zGFo|7G|`Dq=k~Np2)n17?KD3MDpXz)Eq%~P1)MG3 zqiAc9Fvg)MQ7q%MQv-~=n=L4>SuCVQqCBV;Ww2wFj&E!;}VTC-;}8oSjHqt2=?*~ z#<$njBQ~ex`kLNb6co$<>spp03d6f`d;28jNEbwydi)Db^4^XBjAHtck4E#xw zWU^@fz>*|nw2How^rYu+S(Bew0nC?FOUrVd=qZPrt&e;&hw(@HO(w~o@e%k$mz@Zv z=C9WgOOuT*EaS=1SfnfAJ~GV)H&dFo18j9sE?f{wQTER=tvl z;`b!{85o)tjf^&S4rMzt7|C|LG^) zQ&U?cfRbS(M6o6NQW6Owls9j@_FoV`4#EkTw2KuBYE}dBsJ&VAl2@z==Tz@UoBbZ+ zAz8=RjR{ltE_)ZQ&<`$pqnA=8 zPuNk0|FFZHwYA9qQnXZoC(T0nR)= z_}2HBy4K-{d$pV=Iy?_8TU)q3tpxWy)nC)=bBK@guB=Py%_4XARc;<`8|-uhOK~$L zt4^=pc$?YO;>%$L@!drm=j*$!K~a;ooVt}#arp=x>6u;k9cxgH0<*rh3t<)J?PdZy zOJV*W^#~v;&)yJrIv4I%-)9b%FR0%L8%uLhtrx*=d{t@@r9Ae&IkUe?xJfmOz)7J7%&)Jz~R7}6>`n?rkYyg)g4c`L!ed7*S zLm;>LdM^yuS)11?uXIkyw1k|9fv#(O(Pc%xc^4iETqIjPIfbV`X&nboFyv3fzqcKBGIoS`~# zD#M++Y3|Cdfz5vzUUGe`4M!LKifajeWbRxU5uYeeAff+abv?%8k%1+$qdwe?_ zF3a%2w7bkfoHfe@(a)=DHD+tm29=BBV1u#g6_;fyqCBPL^`QZlEMn~Au?_ZMc~GCq zYb9i}49NcNvlfyOv;FwZXPtEX8>ldv!)ocMo2()+7ouFiJ~EunwpX&Em^9Bu+&43# zAHN*ZVqYF)iMGkkK#D(*0C8$b{SIcH769NlMKl*ItSz1ecyL+mfUYd4o z-+zCka#RkxXwk94zE>PPBv%wFtFflh%4?{FmR-*Fc1mG$=VB50y%1pwtQke{wF+r} zHbW@O6^GDmQd2pz5QUe$&CM@Gkx+h;J95CCLt*qVOWc~I4}A0VN;y1o;vpTS)4X0!9COPg1O8{;&hbyaW<*HGQX?)#Er^N|ce z`K4ip8o}35(Wo^zjj>X6dTvV+`^bvatuQ^AX~gd)kL7QR|5RG~Gy-jI_VN-aO7+Yt z4dF_m5=uxa>wG$DlcnB|f->DYDFillhCG&g>)*V*&3fl_wc;;SjqHOe(yjzcryKas zM@@FWO-3lsSEee`-hycqXd-%ktJW1AVvMO8bn}b7Uu%Z?d-l^nz|SDA=;=Z}{*L;+ zd{B8)IA=rpu1cPj$BLb|n!3xojs?V5fCc<|%Bd0+l0|8|r$u?^rD!trAt&5bWfD&s{VQmCPao?N{tLcTNw5qoex{jL0H_vNB(mY>@1Y*29b75-M)kWT=tCEFh2L;AKo5{lzkgw zHM-@w%rg4H*}_Tza5IhN6oY!=)fLia>1_8`UI>RFzlw) z7$y!3L6Y|c^j)JTB)=aceJ7D~Yx#7^%HSlCNY)Tn(Q*n4Y)AJ{jSNTe17x{)AfcUcfVm z`&|kYrJI|*4TNPmr;pMkQEK_W9J|ErHQr)m9!%Uzw0Mer!Pifzb_3R)bqNrHgh5E@ zcLHp83BH=X`^9R6ho8Ukhoe0*F59X6rj74DGp#Wv1da^lq_mDY83@T1HYP-dsLOhU z4nM+rK-knCBf;(R!#8cdyfLfSm3H@u;i~su!Dj#u4R*7=gmrB~D0Zc^z5ztZg2-@n zJ|0Yd%AF!l?}^Ct!}kTyY`5%R%9XuScg7Z}+!WBQU<%?%Ugm# zG;}B|eYVkE2iY0pPoy4+HS|#R+x)US*VW(k01U~XjPTVF4n}R)JA?homB%D}P!Bf* zQh4@hDDChKao|G3tA}@l5@v#%SmD<&y^jfDp&KG##Z=&_QR7ZA*C&8uEGM3SCBa;h z*yn~CN0l8Qdu%DRx8#$(h+4h6JQY6Y#>DG?U-F3jb6JW#?g#qca&5+5VXs6m5&eKY zl@>Fw?99jIqvGlx7fZ>QUr)$H{{JehL-Kw&lSOI;E;2xRxQ=*OBkB?jm4H1omht9l z&d!;dI6_&=%nW| zQ|eSpX2^t5erHH*$wHw@m!ByONoPe#5HOo1+A|%D3Fn#+^X-v>R_AW0Uko^qa@qC9fDW5_+Nd$p`qqI{!?2&z9#trw<@B?al?O=mz5FkpUQb z&l%Rln~K0bu-{4Mt>S-xJ6AwM&dOowJg8#@{1tDN$LMX9jWd}B^U*lZrPvr5iOaaA zgv+~0yqezfh|&pfm`LUqtsiyuY;E#F%83Vi1zvr?@YAtb#9!9l&++&(w}rmmq`>sQ zwBEhFfo>iTy(A&{eF9h-#(e(tgP7*OtJd8cQX3EaA9A6W{tXOFh4R`=<gKko`9i8mYwdD|OvH-(1Ftk2JpTk-0+PxIXi zCWg}=Jd)19r|g{_TQlfyr|bdi7VKY(Sdfzj4RE--?q-_rM#CPsPv&8)evC zz1Qk|R2PJ(>*(Aa5PA)h*AAFMJukGCt5{%`hB-REUOuxYTkF7M)X${n9tbP3bB%|J z9yf(Y>ypc25CYrEXLGz|8nfX-b#I}8Dy@?7yJ^X2F z;tme``C9jY`n)4+QFA3i2ckgrHGCC1bLeMuX9ExIC0)(Yz(9yoN2X6I)wN@T3UR^5 zYc)hNr${fvYk;;+kw%};D(42dA1~r$CD^r{nX`j62>b#T5}&N=K(<`|;Lia7nlw%V zSB`juy1!$IU7fQ$N%!<+Iybn3bYg-~!|5hK1ml#m&UvTfd0Gf@Uze^WdsEsEG|?YP z2abqucfE>YJ@}K?cSM$asF{S&Sw!bAcOH&!YoFq-?(3E^xhp)6y1>X)=ij=1^HT;A+l>NF^)b5H}vUOVO ze(~qb{cVF(33q@}b{cYsl8wyt{I`8T?0!$`G?{7N_W0Wf0cg$Q`X4rMZ7OXTj{Vw? zO6Em#THIvqfv5?L-Hs7)y_+`^VGXogO=xHna@mk|?GzkKzeD*^=93$%B`)0of@SY! zbA8QYGZIl!Tkjoyp;j46M38J($&A%}3^pI3t!L&mUU8N1WUqfx_?3t{DhVM>j_v8k zICJ9&`*8fiV2hd3%QoZGZR7?kXEOSFTO?ISJ8exoQwFijF1xObFKwW}WuzP<3G2h9 zvR4HG(3idbm#I&3bV1J4#`=EUEI@a_Ac{(W<%W%(af?*z`!JzZt9(4md?ZF2Yjy1PY zz6;QobnL2`zqnpwQd!r3-lone?Ijl)T2FXx014;!aA41?qj_Vs4aE0|3RTPrY`+ty zYc$_NI$JaeBr78`Hj=!DrOWuO*Njg+5VRVjB!gkxSzBo7YtGD|qu;V!)P`+1`Gc~c z4m(zz5}%fuYWOb)0N^7-?jQSlDfrL#_h>Sz)z1b>92GxP|SlvL;oe<5)jE9TCU6|ov9GZYuzQ28(BY| zbt*CwtstBVts$nAV~gT*fXM@Bpc9@?T0G{{`sOJ^WloMVfGA60N)6kqqak=P+p8s7{Q{!H0W~ zgtZT*-ArwwO8h3SKXwaHhnb+7*{A{iV(KsgJIjQdrQIn=f2#Wda8r_+1Eb=9SZ_a* z`q})~4sNubT96Ls2yjK)oAWo5(yIw>mP?+>+1v1Eh?Y8KtQyS^_iJDpdC&cx254jR zl^0+dha~@&ax!pw7<}P=`l`U;W5&Zm1jzDcP+R6YJ^&|2<4QmpW3E7W&1fR(@H^V{ ziI7xz*5(J$D_99cLt;nwVV@LnKB}blW;Epjjbi2Ifz^@>N`_`{ymD-@8kG% zX*~YkUm^H9-pU642a4=;KI4?OkyFET_Xu5h^bLwMhx&v)YrQJ$xd@g%wPK;s?g)HuLAXq8kkUh+paI zvy?nW$l$x?XLwO;A0zpf+vP-RYglZw)1z6T6X<6|rkAxN+Tj2rb5jQf`28n)DbF8N zouRVwa5`6$@_zcNo`;A)%|qL6>9v~^Rgd>jU1~t3+4T$|tY-(p9KiTXFTp278$B4> zK*gPghhKim{+HhPoUvhls!;d(uplopa&nue)M><+(oZ`DZ0_J_0@c4v5lq7v3Cs zQj9@sc1yBYYHh`;-gfTGyalbGeJla?wG8g$?)dHPoOg8+Ns7j5>-EADr$4W zvwsf8!(2vO3G;<2-1B^*w_V;Nf(ZBD@J+L-RmqVlpw$Ro%Y2EKBe#wCNF+CA!hK8Z zdZ5dw{85-5o?QAmD?+;R_;il9Q1WrKMeEyx>}N3)uE_?>j&ds7suUQEtQClDG66m$ ztj6=}_NatSVF`mUIxPAw-WMzNqn3{h#cYnKhx>7G%Lljoa_mqB_t>2&JZ^ZQPE>f- z0-G4+V~%LwgTPoXKhP){v&^ELMf1Gv8yVrB+oB{FZjAi;ROO~{@*NRw)o=VQmQ+g( zK9`bBZ%zc3#;t$y{H4aChqbr4x@T06EmVH9X>k?r6p6?T1nr5EhcTt3Le9TzAxU-r zf}}@g+MM{H&dz4F><$$(vg6i~M&5)+pY*$#3BcPrcp(pc$JgvA*h9}W2B&a7#Q47* z%J%g96x&m3i-VN}vJc8clGw{-M+KO1hxWIAz6W`l)eR4Rsv+UZda}^=tu`9HR;6r>u3d zY8=A%YEWKB<&$zyE-i{N?BEnFxiL#VxqA z--y>u4v96IwHL>Fm%MgE_VpFo>~XiTVV*u|_19vX7q@JW00v(GgqI-ub~ zVG8MEI+uqd-QUxzF#MSO!y|8}{1s(kmO}i~KM=pUR%ubdPIgD)s?8peoCI@7bO)ys zmqVRz=qP6X3=iGY;BLU!S&$ zu6-EPAb%&raAPq_HrFBp;YP|aD^uG{e7KvZ<~n(?5ICgn82P4$P@<0g$3rU)2kz=< z212>K#R)qf5Q{gGZ=G15{}fy;^STfg|9bFj-P_RGb*Dh$+mXli_V{2#Kl39m+<`a${Hx@<*C$VLdfoUb@Ne_5#RS83Q+rzj-)2pHM4u} z>P9Rp7S_FS&dE4>+Xr>39zMfSw518384tYIRJ5;*bB%5%Gzi{)zgf zUWGrtp|M>8eE&n#{*U_q^Kbt>qW*vQx9tCwf7A7L)lku2Yzn0!a-&@pqNRCa?uGcN zh^(lHj1I1dtb#5iEY;qD7ZS-MGFip^gGYh6j$G7+3FeWO0dAeum|NQFL*MvgdCevr0IQa zZ-Yz5_t*xr*}By#ZuG5Q`)>SANE+KwGzLVT-(7PB34M75{9PQF%o?30mmz0ZXWbxr zjhlF>FG!=0#{WbHW#Xs4pxzA)z&;J0i>z%}{k@?!WPwyu;ojccd|8{oueY@FrTED5A?lD1Q;>w?IeyAmT z4fYG4TKZ=1IZ|S3vhLWOxCX%9TGn_97K!wDZJh<)>^Gdz`MyX zl;f&NKX&?S8{nkQU_e7+3z*eK`HzA4Ql*D;K&!7IeIE^P&;W%BMS+Lc_A>amqs}{q z;w1la1?N>(D}UnL0h@}4H6tCzV5#SM#dF$o>}(aU+|e?n2X^T$KVJ`ACy#BSG^i`M$7Cr7VCg{+BZU{csq3^$>3hMmKB%J1B^I(?*Tz-()abl z7Wi%`n_`+0ubd6*i8*)p@!T7Bq;m5*r+CF>Uz%Eumd26av!4gtE1n!m-l|s54;F!1W5p`7tp7j!M_t+6)M-X=WgdSe~Etj~-@D#}_U5 z1!HQFfUhwVYts}@aq7D7V4btJze0zF4i)xGbl-)(gd6!sshb|X1J0t*v&c!hrUNDT zRW>AC_?KaCY|J&whxFB@ZEYOuH+Izu?+tBF`i~XLO}g({?Esh#&l2OeU$f^bY}Q@^ zKiNBGqB2QI1tkTuF7Lj;Ol(x`bIEA~&L^y;dz8oiZQ&{L3kHbke|6pCQUz=txP+TJ zfmL0VpfPFb1q^X85S$kg30@YFyGTQ7Gznjlmr(_*Nle{k219b9C%?(MNBl@rvqEAE z|26wk;3dwJ>Ls8qJ_e6P)a4#JS%(59^UkstHuvWz-8BAA7K_x6j{KmSHe-m^hn6EQ z`>G#3;I7Zlc#OUIVlwlGuwad#i|;Ap!XLNXz(cK6h?^$abwd`(A80j~Zt-Ja2`y%j z_N6d_!6%#`OE447ow+YA-GGxFGeP^(AJSjN7B;!$f}hG}`WdU0a zeVdItb-=Jd8+%X5g=O|-3WBPJ=)u{e82O3+{0pA*jURw8b_GeVI}NGqR@ZskxC1^5 z`m!D`-gDmP--e6Y6d=o7yh?^sAp5w8k;|EaW1jc8a);jpZpxb#j63+za=WVYOF}XJ zSXVD^sT3@0#=Rq@Nzb+T)rC%hj(P0h2&l0(8n}k+!s)E)7U=8DK?>fxjJt7s(6_knGUIbH`JdXFUtRPLM7|bLLbp-*8AKm-pAz;CmQOC!)iCaEpW3@@ zwYdS(SKAJU`>!5e)=o9<*Z^&gHoMk?k&zw>`U%}@pF>YJZa=r<1DBZ7*`xuVS+bl% zqp6XwB`mej%={?^}J!o^^@c$Vh&GUwps9 zZ+DHmdn|K#k!sFCV$N^33f&ufPlEzFoMWH|?c3mJS!ONA#Jtv1h0!@l`$MCP*OOn| zwQbm$%CBBCtPCEpOKBSbCuZ|Uo*qf}R+x?E*ZVsw263Dt6KLty2;F!0=L;nUyEDWs zx?Lv}iv{LSTVgCEj2Ya;V~0fT=S3On;Ary4=Kk$59T`6N#R9IdXnXlWU5vT7!UmR+N$ zfky8R+16b$zp z$sQFNwHez!LA-q%Rzu>DwsBgUXY16CiskXGZ5$)*8r9xYB}&>e`~~Zz1YGRqZz>(P z_|igq?U1V5yo?G}-{mq7J>sKdO#g}^fajt3@G#DbjbnQO-=!YgD=vsE{xEM{a>u)8 zSAs2`u=w!f>-QTRVZn81lvqG92ZuLcuC*8pbWKrbHzU&iZZR8^qeISb3H|om!B$|f z4=46KXuS(n9x?kmt-9^3uP?c^KkBUkpUTcieLS!I8er-c630LR>g)j}EX5a{}DpBA^fUw8Lh?qkX@{O!^tRs7Da zBkP#A;lqFrWy5#l42fmz!dmZk?p)w?RxMJ5gH`kHp}hh+Dzt=yi)m%@zcp06$6>I! zU8@+2hika9=BJB3H2RDeorpkZ_=WTjX}3Q}m2x0d;kB}O<>>pPp!&`UrN$$K2``)NiW5S^sn?4_rL8^lC6@++hRG>I ztvkABJ%)IOuZd#)=hou9*t&Bry)PQ+_KI|#C8`HghPO_u<MV{0w!{z4{L)>W z)rxNu`4eMB*}gtmfvx3X@i`R9t((t2DNk7~#BYp%r~zo(FYcgYiSG|Qqb$mg)M^2H z{h{51?j)3zDQpc-9Upz~8-eXpmXqcMvGD;q^RK#pMZ6=P{Lxf6GS@{J?ScDGAMr=Z zehZyEMON2&hUko0>z%lsk^5cWeTLt`z{_F?iGb;gDno_MXGZ(;^&v2}!N*A1#UhV_ zs{rrV#2>6)0L~kijvsGf8&nX;f_3JiJ-ejnwWny^Mvo$zCWt{f&?o@ z1(twi>)f&lHwg#a z4~wKliJ@~Sp}$}U5x%43Uwg_Z-KzdHInGP7uPEd!_vjuPy8v6PJ3DRuQP7Y&bF_uk zYw=NZjL`%J&uQkO*&`RARc87e--Gh7iZ|5ZdP0lK52G+`3?BAFF;A_B_etc(jJ~#X z>^dY9J#Ejy0(md9Wl#Z#M|p{|rxsZfAiTfxfJLHaDswmxDEvSJlQmmKG)Q$d;hHNF z^0KtUBJN*|982%qQ9lBAn|vS1;U9&33n#5#GF_PGp3_}hOg)$^dpLInevHZ(WYA&a;8=1gb-*goR*73KIu2$neWOhIIW2o5~$~6ZYszHzl z8l?{#G6}8M?t zYp6!Ewx!*G6)|tAZD*C|Xv&qbi1^O7~mgrHavMUQ2eG$kugC6v*srmI~LW~cMtBOQup7Y2&TP%Dk;Zl5+kPd2P%EmzZ_PEwUC;PkTcS4r}1xi3& zWQ=z6&@}Jg=ap<>=f=LTpXUoI(|Daci%Bpj3Ag)Qzd!kgMithA{q*>#z4qMSya(ew zdd&WgEbA4m`z!EOLTq@SoqbX^sW^r26up%m?(d4cbueoq7Ov2S&@;*uJxlUWlkgKu z?X>bLlwHg#!>WK<{=n?)F$1;Azy90uasYBG0L*K1Vv*;)uAkna$hKTP%&MX5iEKY% z6bM)8rACtHDTmMMnKA^ekrsc*4Ofn9-kJ?%D4JIHJ*6>rjBQ~sGcwC z+blpS{2}SJgS#^aJT}@8x}hy%WhdDNlK;gEUdHOjkH0`PL+4od(2+HKa5+=v+d*Effz!>-WX zV6#ler#c>-xh#MrU)QOnfzFz8=h+<96nz(KtSj!OPCY|JfkpqO%KU<-3{)j4BTedaUQ%1gNda_{Gpc#CG9kNmqY=~<^t8yqeAZ|7eVLXS zo6m7>nMX_@VMN`NuAJ-00s9Ry|LT??#-7-urIdL1y~od+fBC;8%;$rAeDJuWBJ3#&yz)XHkDH?WF__`k)6qx4ln1Kbt+-T(&5A>*6?7K7ax3meOJe)(=}57=ugZLR_lB6cx(Q4DBZJzkWJ9_>oRi#BR5UCv)eYbK zPUKMc(61a%YQ{ITtM8u)p(+0B^%0?WL;aL#(?kXGRL&k_q7WpAZoZ;;{ zVRzVK?^+~KyeXkD=0FJD@~)L1wQ>zJy1B*+a-KFNJ7Om&V4T&w&a6Vg$4H4H3rDVO zJvnT!sSTJ!Wf!|+P*(cM-4)B+A-@!~be;8rkMm5Gz>D25RlarG!~@h*b0m21AR;7d zznoe{en?y>r-#qI7*o;f%)gi#{5HXRtkeSyPg@r`x^6p!mO3^IC;UC}sa+60^qR7{ zfGPVbJ~peTSC8Pm7{#?ki4{NtN3`!|9K6E;9@zDu8O3~@zcmAd6=s$G*$7gXo?UIJ zado4YI-;Ch{+4FG8G0xxZ7-?&xO*NPx++nv45T zI)sgfYD`bt|MbHgO)1n<{uFt+SAr*;B*{~PkED@|{Z@`*?dayq<}QbqZa)T=(WdT| zhR+9bSF@xb+`r^kX+w!o_t6KxN#|mgRZ9Yps;Ly(HRzL)LHO0G~ zOn5s8a?KNLee6h%8!|n(0*5D@J~aK`oO`C7;D7yMwZ>Kcc|T3=dd7`03T&D3R3NuH(V&7ykti0 z$XiC{quwoc+9t!;#hLrV#7E@cpIF{RD4?Vyi=aZ17ZPSu1WC@R$Ik7D)}>+I3}wtU zW#TKM3|yTL*{VMbdN4cNf*QB>bK3)3!xjuPARS^LEN+y2xRUVg;O~)xf0t0(t?#WUDDRAJKC#u!zGnDlKuTg5)+X-f&c+pEjU{xuM2R!(FqSbyq>_BDII$dht; zX@u0x^E)qTU_BVD=}273%LVGvm0)1ixO%GUb!mTU+w#}R1!3oLC|9%px#=sM8`IGb zIvBr3GPg-GI8B4=fWn!3`~&Cx@P4qQcB@V1p(Lkw43r{b-^@DyCkwVD@)?>;cX~1j zF_qUrrtrZvQ07+)L1L`>sSZtE&RhX-T2urhC|Zdulm9O*gyW&BIF9kGf@AjEdyLxZ zP0H&o9D?n1@$7&2I;Y@Dm}m?CGtmT-Ol(^xwkFnzZJQ@N;h9Wq+jcUsZF^$dw(dON zx^*A=sh@ULSJ&>{Ypu^q*0F;)T$AF+>$mtHG_lqp@JM!o;q`;0k?;_OWqW>g;?L~5 zZqT})>dRU431vrd|V5f?e;b*{mQN50tAx=Q68>d{709sZu|5U;S2Gexsztw2#GCi^b{G> zIXPsf+vf`LI=M5B@N7JC%U0OQdO3tl2^b`|T1>*R$V(wc7;CQSzg5M5K%ND7V4OWa zFFs&90EbRD>8m?LZ=@H;m(!>A=f-HbED5W~sad%o@(=Jr^(gQq!}Bo{R(gkspKS0f z(L!YrcJ{v3XiYSN@8M+IK|Ul_aRf`=axL|$$81WNg~m!2Wto1ka1kWS%P@e`+sM)s zew{1UahW->L)3*T%HH$5kWpxi6vHVqpjh5q>h4JuX%PitouUe3IV3V*GponpJA@7N zC6HNk&bL3J@?e35QO9^1ndZjAcq+Nh{-(j0rf=mk`{cQID_&^89`!fs(7+zu$kObc zq*5LA2CE@jxGl`_GH?>ZA08gzDJ>NUv6~wtXZPU(6?o6hUYxzcwWvx*gxDC zMa7p^SRAuSWT1x(!jl{no-PF;K@l3V!#{G(GFs0{2~e%yUQ*WpKXT99^=2v3xH#v> zQG|L!esZ3^*jE0?O?C>bTgOB#^FD)&Zu}tq9k~7|X4s%AwJG^9mw&QwCvbW?`kI~V znN#pG#$Co`g@0Q84e=y?NI$Xgwc_3R<*CP*zmP`SDglS}fyq97`u(_7y;+}GF9PP0 zi-@OOxOz_7xiXV!5IA-BA{pK<;A+W2^m>u?$A9$BxG`4rR<*zkVx!0M)@hwpK3n`T zt$4e-8lm5GDK8n&fV2B?W?*T;GPgtwQD1U}}o z3L~}BHi1dH9ypYPy~XcB)lwM#zsZB+*jZd|h`<=8;a(>W#(OF2DP9d?5nE-dO*8Ws z*j#2zsue#>ZePS6agzt0JS-r-OB^gG*%>#WX3D`KIe;|vh2m!z@>55sZx$cux|V4k zBH!q;u>3Q^Pq|n6eNT5kT?c!>vK>d6mrD}K{*&o>NVybZ`sce6%S92LZKmjZ$;|kS zkNb~~4LjQ{MWGWe`C7`A4P$WU$3tilcL7&qo??h#GUHfFXir||1bdf40-6?!K9;z} zcgG*QNxfhM*Zv%m-(6P0IP}OIo14Zo5~auw1(g^ky~hI1P1f&+3Uh+V^@Ylxq1uFw zC7~~4=#O6{@dd-KPQG1cqBQvLyT@bi3H%UVQ7?R`weD`P%$Fsr2VeqtXmWgA%)^W{ zW4~#j?H7lYyffCm(Y$0zT!+OEB+SgqFP9`^0eVmDu#2#DfAow!)L0f|e^b{tcbBJrXpmZs)d8Fj~{&s z0wJj0RGMpqXcS*h6O)hLk?*~{-llj^O`V+Vkh4%pJ6O6lR>Yy}UPnRH(V;(dinKdd zg#&CD#szPPH=I23Y|4eZ9+eqxwdI7c`2sj#S7$cMy98To#4q{QXWF5?B4LMpb+12U*7_ zROMW2g8R|&B+qj4&1+vW=Vig$>)XFy5ZzIT{Jd@>Zp+VK_gSt}fTjU|X>KZ;O0y&c1l8*k9~DX~jfx-(4g}6e zfp)t0EedRJZISiGyf+1}#Ni9}vtrOF_&x=PwN$>Y*LbMYLBd#Ga<|mkig6^hR*ZCz z9B>=AM7k7s_`4{t$R2dJI8nfQ0X`AdtA#D%Px{K8#vPKR^DR(xa+jFh*6T&M59ElB zM^!67$>Y7(-a$bk#r)j;f`3v~;=XjWWXGM)|$WBFOXKtWt%;h+m=&wa}t2Rr+TOj~OLtMN) z3k_GuvAK4gr5#g7+^W#7M?bB*o{M*{e>3VlMEbk%lhVPSrW(Fj3&}OiE3E9{g=VkB7CcSv1Mf-pMUwY@wX2G)~v)l{8E*B^y(zH$5F;JiCo`olSy#&Y-L;qS_XVOq(43 z!vvqQ6H^R^dm2t!O<=)3Rh^tExwuJ#^Tf!1#kj$@f|sNgkS0irizBg>LDTkp%6V|8 z`bi7@jY?FktWLZ-f9g4q-6?xHo6jlCWh%2dc51H31*QNT)1r2my;4>X1#CI<0+A?LPBSK_69QA9qC3E9q+%;nHVBj&^IE^~<)h|1 z1?$wve=8n(n3`irvr5{f#GVs~<27}x@p4n8wa?V);%cCYMyygSw9%VLKehu2maW>2 zejVq7StA&OH|0n$#ghhhQ^i=#ZlNM8mMB=cnor~USyJa!zY9Fsxgo$$30SlXvIGvx zzwGEL{v!x)uj}62yL3wb_scloVk4k&)JVjo^pj$OTE=fcg$aWTzQO$)5<+4tf(Yre8L@7oQJ1SJ8|~<{gm+M(Nw^&?YIbXj$88q zkhJ@HylgvN!ri-nOTowCL~5C!Zk&J?uapE%qb?{#c8PAs3DL7F-OOUarA18s#87uu zpsR;;Czq*N{E??%*Jvc@KodE(&WJCR;D$QW=SQ$6@U>o|r6GU;xy{3kP$oo4k$7F! zk5WwgVo61$F@VBgDOW|L%E?&6A&H4p-;NyXSdfWo_PRIExOVqF$k)Rnd<1Q7d5p-G zflB7=Y3q+M+Q_%^2M{2xm*=wMqOx6Tsm!bTgzTn|ui&1EmaLdgZb_LDWNsB9L&}nj zw(_<1sc5AvE*56bVw|@PrssJt8MwMH_UygWQMMVN7VBXe=VHhbT~BB`@}UtU8{u<9 z(>F>v^=OZ)b59n0B#mFkQ;-tqj_5QTyI0wWuU#v>mb}P@sZuL_cwR0aFIP7r@Wtk6 z`Cqcu&P4TyR)I0)R6-L?cmiI7(1$O1yyA2sc#}PT9H?HF{>tmGTF3!eJB<;}V7Me; z^~#n%>j)pRTT7Ckwm-=dF$14gAUyv5q)Oal>i_pJ29A9mhFw*~Hv$lsG87Z2I;QQ;{24<`n z&ge{eO*F~+t*%i4>GsIUq+Rabb#Bn{XRrTAXIce{i~^K&#{T)nA=Wdx`$93LsLxb< zSY{fmsDT%%+yf`;;kU=#m-VPH`~JJtv_VCu-!4-Pgyh<<)Q|FA9x+Hld^_O$ILzZg zjlqDu&9D-mdp#gF+wEc;BhKj$%)iWbOlyNWYV7s`5mI_?KgMc`<@bM^Bqk0P`W8<= z-i~zf@3KvobALRdA2Pgw&kPIr-VjyJ-pB+Gt>;gOi~4ZKfB|Irme`4U=!=S4|6Kmz|ZS$ScA zML{0G=!_!U6Ha)xrGmgK*xK|IEjMr;DVhA9ixB)@@=%=)LB~S z6+6}O&mZm@SxQ7(_Z@#{ENy~kay|$1`#ZT>7A6)YQW^$)+5|mbce7o~;TYKGa~^?P zb{=k?&^r64WP&xVZh5Lhb#b{&H#03fNT9Ug_J~)6Q$9y_R5&Y5_qjraXUP{Zt!HnC{QK5i zQDd~{uCO#ZzS`VmeBNk7X{c^{f9CFH^v*WmwGK*3>qoumM!4yu7L5?MCl>a2xBNjt7*9 z5M1sZH}OShF<98f;T?b2AQoUQX{<&a2}Qm*yti{`*B)$^Q_^_vgG0jOR!g z!?6oUcW>g=NVBXoJ0oghQ;KuRoOr*FSP9&(vG*^bn8@~Ay>l4pC`!>)Sk#1&U{>K# zZCAq;8guh?-qOKL0bAUC!&SDbioEpE(th*s`4H1yN(&#qnM-Jp!wh)`hLd3`lepl{ zE2$($2ad-bf1$J6Dl>KAS*kbMZCQc%rX_j zajj@|W5u1lB9j?3>4O|pUdH8m95o(SU5*Ic>WyeFFbK7T%D8Dy6_eu5J+!Z|?>n&q ziQlGu&N7j*4L6r_Tkm{!n#RlD)1gb#H>G+3KIhnsxYAPdkgA>2*nol6rI9v@6j`{b zct=BMzM1TRedPh_JQ~p7pF;X%2MvGg;&K0&4QYv>)pVS#ZI^F{rp&JYC-zyJZ7UJD zu%+;qRVu&`Q|FtM*mc3`YRQyn?-&cen;@!_sA+wj8@2J-%*HD@J6f)2rRUxzbVd?Z zJz9)Qkz7%#P~ca=mPl_sUp}HobAz_FA{wHV2RP*w^c}C0uIpxw zVGEF-D1X`6az6ozPT0rZ{BCZ#TlB3K578+5YMER#+}H{BM2KV__iV#nK^s9^>7+>S+3$Kva}NDpI+p$!QD~j=R{O9v&JTZwzfErT?O5L{3lhse@55n@hTI$SufR)>iSBmfHG+&QnsPt< zjMDeq8zLjR&mV37L%d8qL=nwhJp2<_W)xF;o2f;FAI4FINgC!adVToZ5hB*~quCAV z$a4-O!g?a?&&w=H{m~!zm#@g}p7t$g&i?_bT8&cN2Z=?=7S~>uPQnGxnyUvrDAsXP zj~iC;9UN+*Lb9YVtc1qW-H^@Vg3wkwE({ftpP2aPRI+*DPuYC>hE91N$8(8Aua45V z;-RAN<`o{u?~4b}c8%1Z*rh5k%WMCs;pC_4F)RJ;9!X#`j& z9`-<~)3F1kR`v97#VvI6deq)fWba$xtTj?J%;dYrdkS0jv3E?@C~~I2o}FyH0R0qS z2-}DmX!k)e0BI+o;`s%Zq;NQPL7>2O_=MTV(IZ)=zhrV+eK%!cACL-Ni zTRlm+DfvNmShIWH(3!ipv~XU$za~1eMCnk(^oA-!HGHA$Uh|#Y!oWValsv-aFxhc- z>GG;(6IYe<+0@4tk(%gH{yocvK)CgF4b`;$Be7caP%Mr>Wh|52nM}HrbCo2Tj67|f zv(hD;?2%y;Mb06N?5v)L@*{xv+OF<&#+2he$nVxTB=s!pF#5*i8~%jQL=@%ZtniTL z?0QoeIoBfq*m_DNxq;P46#9WKseV+4nGALsa=>K*n|^IE0lW0V`+hB5Fmk7fZT@@g zm7S6#HW(D5|M8q8*7~Y35|EjtT_XQnS2KZwJ%y2HkNY0fE=8Kl(4mxc2Qm#7_TZtK!(Hss8u#5PA==lM8TUbqJQq7W%1LCG(b}5bvysD`D83;+|a?=xp zi=^Q$S*7rcgG$pr-Uy1CE%$!maNm&5ll$|z2W zV8Wt3)MHS*nnyvyQG)6520t02LDm#G;RQVn}k1Ch~ugsxqr5fIu;XHUdOxcfz)qrAVRl!DSUG<%qEr_C@Tt(AnS8 zq^SC5vZAu2sa<>p6ZWR0HOa{GSaBWl^g-`$sz3FsEvUs2hc^xu@`(`;q?Rz;lv{rx zxyiYH*0=rgHtq|M{}MafY6KI|@Pab&3~fdy@g@0Yq+98*0X13Sg`&OUj6Y4mxIL2# zq_Kzou-f^4BTdAo?m-#tGDUtETTtDH#;d*;n_agop#f+aRA`X-2?%Xq^lHyqf!dwq zbp&__FAX{&YmGnqI=hqXug*T#5IEJ@?W%?P_#U{eTLlK|R=#jc;oFHvm z5SR?ik!B+CG>|}Aw0O1bN$F2{ z`7>P}gJ-24LJ4)gde2EczRBPnAEcHRcx90%W;~Y|)qA+p9lz_^C8vqdwHzjGm&as_ zjMq85Ao*f69wVN7SaJCp7BTggFovtDTTxYs{{S23SRjW5IvfQR*gNDSZ)O4 zHx03kL$5s_VPez-8GO=FrdZE zrzyu_NQO;4tkiQmw$kjLjSoDwgm|7ek3_meoFcW6*u;K$NXW2~g>8KoK(}@8%!jB? zz4>5$C0Ig={qANhOHYMwuymcV%@acu-4f$pGwV01tLr($>ExW7=`%N4mUy%NyZuPR z%>$g-?(q_t>~UpuTn7^Le8Z{1(-4BT!6Yg1*cvRPh52LBRwasp(SZ zX6nrJpA>cANGRd_KMZoamHIRoNVt*0jN(oOS^_L#Wd%E+$G>>dV2W4kcd0@E#GNXc zhv8U1oD>ef^JQEGv~_pq$3sKV z;W_h8hD@e^5(3%S`PtN_1Vv5DvTa;e;9(KSie1-2ZxNx_KhPYN+G{tcOH*gk@Y;gI zAdoX0sH0J|k;)7xu)78Vh{QMEJ5`6p*D~eUl^ttljEDHni*-|?Q{#MULc{Hawt9Ex zF3QKeZgWP;H2mNm=B+2B^rv*0P%H|+!@OwmPEYkAPZoOc zzX@5E77PDBCb$1*>;Lw@N&YYYTlYWyo7TVefAinuyxessE?JFtvuDSQg!F?n0V1MtX`&}K;--7;4{&a;<%f&zPAu!o#{F^Vrql2E5qa)v? zajz@qM_Klr50o&+M$hj(8(Z%-))K`4!-a5n(d5dd6wHc0_akbYZstM!X)=!H&rRYd zNw)3f;Ii@c-;ofl=S76^Wy>~U8K>!pNT^VEkJE3gXI9wHurudgf;8Kcd99QKP z0zPFc#j=0$GET**n|{#NS+(fM7( zC#(BoB0cDWj+3Cd7`hB-<*!VE+7jts@afNV%GSOiBfSr+k~I&TZ~J#yEFTrtF!3dl z`*}hFSm=cm72~kH+%$VeJIQ&gs zh89=P{IGUUiwufWYB6wKmeRQ!9f;U^YN4Os$THrYXLz^JfEPT!{r8la_HeE7szt`{ zg7*PVQ_x(n&xrtg`PmL=xar!X~+iUWk#aH)lrQ?Z(2e2T~9Nv547}d5nnuLX@ydiNp6sO z-d`pB0$Sz!MC9)Y!s zYs%8Y_chp z8@Z+jtC&iNVR_S41I*rguNS)g9p2lb;Nl@&?sdWYLozZ?VEl)j_N8XCUql~p?5~D< z{W5q^!(y57JE#6d<|LNDNA zEuk5so4=S5trQkOM6e)S>0QWsZrBx6Im zrgYuXaQM_iSa$DVN{%So#8Az(*iOh>fe{uFCIc9&bLrIfwIMlh4UZ9J0e}UYm4qDb zJt#8i7rI`Jr-d`!|Jj&1BvN_}-yVX7rC-%%$x59acpp_ab-<#PVtN0xzmA0EMs0u6 zH>5^`yyjfAMsc=gg0So6o~woRPekHI@f>C-9^1yR&(jm>P`WP415ji{jckE2#s zV?+uRqC$38^ZBV9*2U$LZKX+HZ;pXW(ShqM(FhZ3rG{3@#RAA9gA#F3a#P0Jcv57s zQk1;VoI#iNd@IvrRAfD>#aEw-K^Mdh>Aj$5NQh_7cg3kw^gMVt4hGarOF1~1#-Sn- zj>4^+OvXQYzdKe>#PCDfHfui^5Y==KFFL(~0<}71WNZ}bn4Oc*x#WTa^{JnxB@p;%Eiw~80s<|(1&Iy_DRyrJ4;DNyv8*%L;>#3`bKBaL`_aU) zh{_FoE}sBcMU~nwgNjjss5kUlCpuDHf$pCPOT)cWUX!|Bok@YzoG&;_mB!nfd}i*{ zQZ+x?#VN*<|NOCj@`fCL#Trb)M4G}d$-VavL|2$JHYyHCpF6i=P?bCXBovAbBp1d$ zT7v-Dwbh%h_nD}&xRi8OZZkt~>uW&ZU!jq2!0R&mJ9*Vz2YCRx|FfkT|g)nm_g}z=!XFDfsRlD}ty+A+SCAVOp zXAE$q+9_PHU7moNC9`DPTP=9A+YfJ?*xGdVI);`e5l;5_dO7}vR~ImYUg_4o;H`jb zEb_Wybn)Jcoy#QQ^$P!*0U{_^^w;0XXwkj>aXnujH42FFHtV})Z&GNScO!xrX>=u4W>`M+bYalH*9|P=4?k7#L%?QG(V=8twmH*nQc~Dz z#hgSL(J6QFlLRT77bCsS;e>;Xk`4HU(+P(v>4$x?R6ZHIbSK0Pf9B!_?Fp#eqU>`d zuz`qoMGxPLf%7s}*)dA}{mHkBO~6qLvgM3$qS%MlGtaqy+U6M_U0FcpUES3)-omvh zznB3&@DAQ2FF|$TYmpH8W@NECZ>qv#8%iS&D+^7jYyVJCXnHZ@6Ys+B&^A_-B?>*$ zohzM;s^U}c;bognxcWn4+8gQws*)JBF(CeV@Jlx!>2w}eN%-b6%j!&WSku0PBB!=?J zFG3&f`Dsx&XnHOTOP9ds^Y)SIcWZXorg6tQO}nU7(iQB-R*;^qYQQpWyj?)OPKe}v z#?e%kGWD}(Qw|CErbh48oaLA7yLR`XJ<$#Ni%#XL&gwYv8!_q5*_0PTaFCT!g zgVK}_|L=Q7YN64%&s_xHDNKE4X}{ZM!BaQ*o`UJ z&!LXCZ?wBxZE^9jn3Y-Tft6(h=}q@_+*_C%mpX9`M-Bq}00TVua}noT6H{}D1*I}? zknwCc*)4#LbYy@u;^p(Wl&6vHxJ1JNVsygIYfriH^2UWn1e|Oqe2e;rE*TH3J*;Q>6cdeY;;a>- zw>oOpitemR2@N2+d|J2jiRQt%z^X=BIhMAmpRi;)&hl*O0UumsyE9dk6W zB!UtLQ>y?aDk4U<(GBm+g;5M>VMiDw+Qv}VV>q}dbRI5%22 zV}sD=8gA9m=Y26w@X~+w6)Yh)3_wEyWXHdU6_a+Tt&1h)>=P{Jm2u;Z5|~VMi7{KR zk5xK<3j?OQ*gqt&zq%k}%{% z^{RJwxln;E_?oF`;(hN-2C5UJ;P>M8ont9H-#;N2x6wI9MWYd(ZrtCgUBMM2i22*e zk%*mQfwRn9jaNH0Kk)u)YlZmuO7&TZ$GC8Z1o<9>SHZ%~Iw~CLj^IG>)H~ujt8v_cu*1uW*jR0Rp!n`;kB})#wTSNHGxzn*N|X56$F2qSJJiD%RYq;jb`sa<$*RLl z%=RDGx=y(7han$orPS}Rk{{Aq_!M@lj=kUc@>1qzXZspwOsQvZgcevGCB{`s8xju}i%Wuh+{qEbq`S7}XF@a9xYh>84E8Jd}5bAFDy1XU| zRD}qrnK0J$(L)DZ3w>?@`rR-INk2F~3UH|6e7wM^ZqJ<->d7OG-mgztWV z;w_cFZ|^ThAI%bnW_ec7UK`WFZ4!GF-5bNe9b#KXeYX4y#{1a#JN9>HEBOGEjSJ5lq0}BInoJr$G| z?w|_U-1H3!hut0v_q=a;Qe4rO+xQhuWI%1FX*E0`=JBFI)Kg-qQ(M1taJ(g6_o#R3TAitIUjcged|48gFsOH>zkDJXB5yd!HF8c9&MFkp5GYKO4vWOOhFA zIxx>cgGWG>^O}Ei?$9?=jq2@poJu4Tds+Y+SGHLWZK~O}yNhmJ!|fiUGjA1HdBFwZ z@?n|m(Il5;v!Wq$?a-4HXVAym^4P$`szK+LAoD3G$K7A#O zR)CE|M{CS_Vu*buC27_e`gM^Y-UYMl&(ioP`@^uEnx#t8bs#H|39GIiBLD7mvzp0e z9i*njfb6VpkP^!k^0My3gchFsTG0_EKd?2^=0-myA-Q`pd&41dna50Oqcu@#r}T6! zy)zx7Lt!3`O{oL;3daEO{A(ZDU2k=rP5l(Sdm6;5G{a zPaIaP5BEw*6|}Wy`MOLhEAnT~Vpgy4k6}jVwQ1ekY7?Oz(x?5Oo00Nw{6=WsuCH65w&`u27Wu&I-)NfYXPdXrG{Z58Tl z5ruaYx>KL?{oAmF@_9bN0!iHp53@koXlok5?#oksX$bSaYX7DAl2cY0^83Kc;VhH% z{vtY`i|C+&Y<2~oX)^&#G;q_KL#|5FjYw%0G%nD&HZ(T&+a?KmW5{{OAi~YIBU-nV zb*_#vt68-ZG}D`&)x2-oFO*rB^)x4MT`E=s$NKkVDG=qs1KzszrjMM?CR%#j zdgiHNR=BG-fE;#=`KZo~Jk;cSZ69zX6DL$$_pBxmfcL}e7Hz|HmW& zNIfRs_j?L$6 z^|(s}(Sv4ecm-8e5#pr1VGgoG+sc`k9+5gbO2Tc^;QdbMg5L-dE1@(hy_lO0X#wQC z)P4TCMBDOyMhb(^eVd6BwZyy2u1*e>*+qs!>KwTT2deX(kGkNYa&`=B=QQhkDnjh~ z#gF;3$)E3=2Se|xtV3W^tj-f0cGyT;+osPv8q+N zW5XP1ABIWcx7?Z@IY{rW8<-Bavy|HV@@;V>x6eft?OxlmF2*lXef5|XAE%kyw>AG2 z8J14Asw)SmSjlyE_I!_oL0Oh4@sw}5e0?#w>EhD7sh98&6xCWZTLIG#@ue{kUCLsKrnF&T{`f=ye#L*b9Yv5XB z43oU}DB*dzW__c(KJ%@7;5tBvh#;1IJZG1sYH~F~w^!koo)Mq!m7 zx&cP^1-Cc#^;RmK3ilw13dpx1f;=fZjpkR_Q0~`%FZ2K9jx>%$cd(|1Orn3opz3r` z(N6U63k_(mU9)FXdi0HsaQ=Z#-&T#phwg(nZAk@+J_3%864{v5-Qu8LVU`PfI?$iIs>xmV^pCa0fOJknA`=t%820s{ zmFPWM=qPjIIAP9|l%usNs_tr}G+A5#ZrGKMfow`73!U8Z9SFHS zfcE&|Atzf6@7dfPU;hSnt6VnaX-|J@p)6z93CqmqKtbQ!B6^2A8Gy?o#P8#}VJb0n zl5U!{{9~)9yHfweln(a@ye|fvV#sUjS4HkDDKs%zdFmS#qb_)x=QW3mkBHOt)DROESFdwPR_Ok+>HMkI?ky`B0d!vlD~G#7u6wEE9t$ zZT0L>(vZ>;aI+mJE8br2eAv^(WS2!Fu9=B+)N9_rP~CL_LetH4lC5`%lfB>QnXPJ) z!|<9$VxV&tv8{nGCE{@l<08H!D~p^#1*pb`s+A~Gnejc@Z@}4HR#JDY+wUBGj7d;o zs7qdjDx9WhHx}Zj9W63<^{OEAqc|^WB3@$~p>)aRah_P|5rbdghXVhmiT63poIJWu zM0&=(ZI=~ger)g9t{`c2Op6z1Y>D(!$Um{>2nEs@t*2;PLdY$hYly1sPre1#c!$rO z*n2MUn!^NmzP_XRCpQ~1%F^NMR2pHhmzWE>fSn1bcTbds8sGRz>!q6Qpl~LII^F`@ zK!w0HuKBLf%Jh%OSc`_9B)0Qa_$SBLXxt7=1X`4#3_>tKpO&B)klI*T$%B*~ggYPM z4&S#^2@0MhM(9JXyDM%p>;0qJc`4uy!s-0(gy5Qv8iXzR#$)jju;c4|4J8AWd$dN~ z0+Cgq0dx?_#oM6_d{H=^UvqQ+?Weqzh;mjqx`4F-dvuaW4>&`$UDoLBL)Tv#!Y>!%uBMerKhQ z12`K4Y>?mv3C?DlW7#8!_SwK=7AN*i-!c0n(QT9Fzc3(G4>6?f2@eM2*^OK=d)J%4 zV^e$LT#%hOIlJQ6Gh^&{`{D;73(_Yxi)>5Ph#8DH7UVf!3x9`7_PXd@xeW9Y-g)DJY7PPF4eq!!x>iq^Q;KKaJ~;;a!?p$&b}wffjN#`={5 zIRm$eoAxVpr_tv1E2dvnz(iCVUZ_yrY*S?>Mj-pd-GDuhQnUI9i~Ir~o%5p`{KGT%p5~KA!{M=QhX#th-tm^#fnoN zul7mZEhI>N;f`aHgPot*Y`-OWC?q>P+eNE7DC*P==7s=;^^eazKV5)-O{lm?u1*U0 zQd5tJG3mLh`LYE)Zvy1ykt6O+#H6dqvs{q>qAKTn9#>g=J^_&(i+u%q|e|o&fBU;uV z(`&G&?lcf8?MZA39tjQ(=At}nO~{1x(*p{Q4|A@}Uz-PKIu7+cC;mvp0DkYz>FOv^ z2!9X-#N4QAQrPpaJ!e`yy=Y4aZ(Fr#Cu{`G(5P^`9-f-pTXqJ(*>Pn?F%kA%Bj&z3=HX+;cs+~4M3Gw1ojpmY%iPr>qgehJbOGeV=j0~nFUcgE-oWjWylw&8jtLUCq+k38h+Hraho^OlcP9D z(c2J9kM>~#)J?4pw%0m0FrglAu2RK%YzAyRXl@HmPjoW*Bd*xg0PE7en~O8&Dd}8A zi_R<_zb~#MdUY|#%D`m?fQRElStleX(8lQkyjr>wD49e!F}#jvl=3j$`AYbtctJGU z>FVKwJd568pJZwx=W>09U=6@PTh_u4SH054-|#GbcV{m11RB~o)}5!YcBh;v4ZCD` zvQAs8@#z*HO{>TRx;R!!njF$2%X5y_x{e>_gw2#HUo#`G*xwOFG;QY$2Kp?N*YhmV znL;Q)_;7*dqgt}#yE&ImbE(ooOP17*PqyC1rDqdU7WsQU^3OTkoPx=@Xq~nM+CcHa zC8<)$mUvrRjkDz(DBCl;{zR0;T2RswFw(EZR`q?zM2~1nBKHA>iQ-j@MjyP``U-=X z`XT?_!CDjS`%sJ+9}}pG@%S||kP#(F&48-*j|END40%K#OlibikS~L-BiOYzk`M7x zFryQ&;1|ec9j(JyW3ny5NGB@iwsZ0<`pBqB0`w4Dj_0w`S;BudEgSEug$SOeu$^9o%y+2XMTEDQ{~am-k}G*EVWHhJJ7 zp4wbpTg^_0E);?Nj{D}_zO(L`XJ-6mWpJNBrzZD5mCLiZr850roDf}o({yYS4Hlo^ zk@c@gjC@U-3Lfc-y+gFDqQU_X^6dmH61@v8EybSiyP33m>n>3 z{GXoRnpR*e-B+`S>2-ebSn+=OzKh5_=pdV{=pzW&Ad6+E<|SSf)O@qe&=Lfs)X{Po z2ogtsC$MA9ii>u|rx_D{(7{Zkndm!X9R(d4Y1M?hWeRvKDM`T~+{VPrP-EG(q*TX) zOlfGb1z`D}CKsJ!N2@9|{(T^#t5S*p%2dh^Jdp8zl&8g{`A^Z{878w0HaRPflTw-w zwG-H$@i1jHw}GM~Rc1lFXn&)@;4%RIkaQ&e372_J^_h7KR)NMP+# zG&It@zl=MqCRXsa<+h58!Ipdd%8fcWaQ`$e!oj2VYMU@K^z%;hX@6B#<3r+~3Y^Ec z%!VJ)K@ECB-P&j;V{DmrlZb8R-nUGcX@+I;zA30N!_fG;E)bzwgXOyAy6=xfp8uY+ z{-E?Co8!PBNH9_wX`U%+cWD`Q9n8Sc8+SxMW0UzgT8v7#@9bQv215vEaM}vyo4F1t z+#MXyIeMBZ5|G`7`EJG+bzJF~yL}syoQ@ab`#o>ZTb^@;N0}`)lJ!JiK_(?&aa0-g z7I^0S=KUFzhJ@kNs)#)yD@i((yZu3J^>mqk@*Z|JU(@b_@KH3Y)$EAk_` z^jjezZ@ad;_wo?FC9{f8&B&S!n147D43q_4Tk`f#a^TNt6>;}{ET2}$pt}%PCwY8? z(^6?G_HKMl*GckBwb9HaAw+d0R0(Wj6l1N3O=if&F5s z^dFm#im>3#Da4pO5F%E~N|ahq%4Nz0M1IyzkdEw$-7jd_8S3k?*35bIh6#V=^tnqM z`YXhb-$~@k`^EIF#3yb;Ho#$1bK+EkHmoEet|0eV3v(xT9ld<~wl3pY3T?Jlcx?-> zpEyw+c=zbi96y4Hy+u&_9&RPiU3r5-%D$tG8@)5jD{&bQo z&VVlpf2U+nG-=s5>T4qG`}->m+W^D{+E_JFLBt51vpCVv#`yQ!HM}W|==q(H72*Hd zXHntKFy*@@W1-?Va-y9ll_IgCOkzH+FW{pN&Be(jV_%FU52w1Y8<^90nv#t=bxyfa zqycuLZnTMP_(+behSvli?T>!Pmh}x5#nG=?sAC4>k)N#gQ6^3t6dqL;tQ3NVT1ihV zRrEMX=kH1^a`y|wWS1F1gNPK_>1(P&EGf~xfMmU3Tgt~YFS}W81ONv+;w)n$A3Q>Z za`@jG<4<*q5GcqYV9>)iGyasOJpds|{}M~?`HjH8ih8v~%DE28^sQF=IOk3~;+do& z*Ja&Jq{wTN&_7$q=$L%^)RRi2moR+~A{t|29QloeXeGr=oRc@R{$Hn+KxEq>kF!?= z{6^i-^4Y#0=3uK{0um;lQ={l~z-9t$Lm$u%S_9uxC}_=nc7}PVaWj=k!h{?`c_n*& zQ?;x(m?TufE+6K#=4()uY^mi9p6Sq%P96s7O)b!ZYms?CHI^>sj5^j?ocsq#=$2%9J9eQL8Me4?tgPn^c1&Vo~I0dm>MUYxTCF?RYM z9=O-+=w@ATFT^6^h`4lXMa$w7~>hX3HO@$wK=#If}1|vo(GQr zDp`PvP9hhaiUL}*0%_wdWLxgEE{9T4Y?}^d7b#QFX(X1BLOH!iUFS5S2 z-n(GlmfnV}z3kTqF1+-lzAm%RIZG6;>*O;%(*V03+jHx5G zm8H|m0eyEEw{7ZihUz^8@989Ky2wtp=l?;~Y0Vru3_(O$r;Bp*L@O4+pT984Sud4P z?B;#3bDk;rr;dVnJDp<^5*>#d11`rOx<&uqK5rweL4oTBw+q@VL|=5bH!Oo2nI?xi z#SVY}N500xC;dQ(`*3Ack&ber z&EY~Mt6YSjj-C2(>lefolJ4FlmNQ8zr0|rX=588Ktwd8sTvEw&-|_W77MN>k@0$qY zPgY>UkgQ;j!|esUb~Ia(|B^EdKy$!5$0!Md!*JqC@KfxwLopVZVJ+KB7R<6-!U{Zw z1)`>XF#S`N;>~R{elx&nER)R*uVCS)`sM;fk=N=bZrh!3-kFhTF-NSYG$P96vjhcL zg7wS6$}}F*D0t5H#2JQSy~=Hu1qkl7QOl1AZnOoEG^t>|BM0$|pLqVUdn*5$ogY!I-#= zt#{B}d&7p}u-nt%oW0mDEWTL#vpK80S^n8RjY{^d_>I$)iq0=)!P@fIRt$V5%a(wV zN_}>7Y9jy%wE|Ez35!WdElE8nlVL=0%%}u3WR|LG3CyDdt`OT+4})$Va%=dyeQ{qV zn31e>vv7u$cHE8J~KcuaoN`X5pp$7gNkah=H=TQ(W@!4-0X=sAD1H48K0cbiHy zm`O>WUPTMklC1xom40g4r@v)e7Ud=`C63^|U@__AQ>=~79kJJt$5tXUEhS#hfSAqJ z!-M}tjbPh@>Yny%zgM9E5{X5R!DqTU)O~4#I7xYla2Wp!II+FHT#nbl2l-WgpoB+} zNWywo(*`=JDG+zE|B-8v@|g2zX5n++hro%>bben9vhWR%!D1AL@fq>`xt}SAbeisG(gk@g4uF2Nyv3r6qK-F7F-cf zb=1w>dPJHv?E~wWjmd1q)i=%Hxf$IHX?ZhX?W(O4znPTK%yPu9VYppoyGWPCaSx1b zKmn8rVDYP2pmYy!LUHe;#Cd>wsIW@gtg68sF9Z#$mn}yq4De zkQVGFg&;pO+ED2$o#>9F@h`ZPEkCy3XVdn9<=avUBXoLevow{(>~7>kOF zfZ0=4xg2)*2MRr!?X)?&ZIA%usEqPTx6DsC=n;d>an6=QM-7j8CbU%mVXmN+$rWJM zR6HXj4?#!PdHnjp?|3UjYU^}I@Uv4C$ysx92rvK@bGGvp)8Ix34hT16# zzoS+zVR9ZC$}}aKf{yb7Tr91l;>G&?RPJas84R>pq#0G^|20I1y(HKy5EQ!r4+_LW#k2Y@{68Ir{I>+fp zZ6xOtOFDY4J1*7YrTQjep-EjzTf!Y13}PP-pw zSJ$=${97heX4;lCsQY2fPl~G z7w-CH$+NQ1p@Bs*Gz|PU=1>(021>LT2XD&@_Wb>d-Yhi`I;G%bZ-MJRK)n*n(f8?~ zdf!`)!qf8Vqt{&uzGN@2ycHsqV(N3~g?QZfx#ot-h)zSIFnbS?34e840fj?eg~|iU zRzSYTZB;tqeKrTfnvx)?bA5n9zx7s#rll1r%l50A5eL%htV#|PCl)HkaYA(aOO4b) zh(wvu-|@jkNEuBDH;B1AluR3Nwrt~5N9TES5JJRNii_jFCosV`jDt@#rSorR1vm=HpV&5!Q6Ct;NCKtJ;@(J^K$iM@5U=)J?MQES_95~jp#{xE8T)X=biJY z9u_&O8t6ZF>@W1QmSi`e*%%? zKC}tM@T>~4yqp+tTRsB^u>0o6>f%l}!s-03`SJl)kAPbNr8rI(=i&V~3c%O?1=bzq zae#=1i{y3rhzob|#Mx&wccIl{s%U-UbS`%38P3!k>&G)D z6rOICX%T6880(` zPfd&SO!{13j5$h>iB;q@`Lt{S2<=uF&%66U8R=KH2VFJ<5ZfwtgyD9Je69#}{Po#z z33H;gF>~QYMxWWtrH{)W+VTXhsD*tP_(X~rNVJ8qP4&YtP3?uxZD3!_{W_Gi>X z#L})5oY0_>{zhM|u}DZ~YuW_TORE*reMab8k;CH;Q!Y>1nRh2${&2C@_)|B~&sihZ z-%7?E`l7|?uK~X<>RP7$!kkQQthLoa%SObz)%fu_*TvL#;wn4;V7uboL)YuGjQ?TvqO)OwE47^YPhsFO-32hsm1M- zr;0bMp!KP<;SbBYJK!iWTUPU7WF!}B@wiMMS#(teIr4F<;>rzLk$O&fRNtdpecS?q*&25{n) z=evyInseW2gV8I9DY8d`pPXi_zYx0QbHh+|S8yn!7*Jg3pvW>8>r+;kyaCzWZ-;vV zTFo7l_ss<T-4kN1|QF6v~bc{4~ zj0m}=Yg7MiYbSPvzVly&Nor6qgxWK8tRcIjYu|;+e7TPWVLi3Cq7&Hv z)V7l+?eG4T-|2K>i}v}MlSOm!iN(R``#705!3R&~Il}sM4}{?t!Iw@WOr|)&>aB?C z6LBh5MUPGr*NBKpx4Q({hoh!X^)Mq#8T?*Gn3sT7phhVd(|8+Dj5x`AGtCX5CY=mt+?qnvIvpXg4w#3ZL$9>TYBD;WIpqa zT#;Mc1XG(a%9~*+^C)e82q~T_&_&U8*sfl|IOS%xfWn=Xqs`Y3BDE3*jY_dfY738M zXdmMS2EKmUp(n{`A3=PCsUGP3-Bl}od^!QUYWAz=Bwm$fh*^X1nw)vE0-w*h?3-h9 zK!b#|E66{MQ%*6w%J7eOrKc;&O2AvjxeM+-GUe5998meS2(e+eJbN$ww-nn@UR3*Y zdKDp~@N%(012)n56w22(Yaa_Y%lhDH;;#Ub4n0^XjX_9+2EX$^WRxRyA>vF@bxLiQFwVH&;BjnsSa1MBr0g*)(P_ds~KoBui*Jz~l z?@vFm2v72tUkTcHPy4Dfn!#PpB8i(T97y%|s3jJobcj)ji}UYnH5|%4#9knqG-Ak$ zr>7t|`rtf25OkGtEd-UK%sot;ik)Wy^tsx0n=TASKo;``Vc$}J?hry>VV<(J2c@|@ z1)Iop7WN^%gSKkI`W50sSkve~F_IY?&&xh#>`%@hkM#^Cb#j+uU1a7UH7*z}PzrQs zn)UU0kJmb|=ld>j2k`ZuJBO5Pf+5D%yYmM6RyP|^Ro$HY!*GwXwmW1pK)@IN*wqSW z1DXCP-8U@AzjlbX&@lhj*in(8r5?V%o6B}|CQ&Dav~=s3q)2HM@^$)mr)34-z6TFZKNHfS$?tiu$F=B2#M|8`fYC%H#e>n91@2mgy@6p^pGtyVqQMWVD z(zVkEn+k#ig(dJ{_w5(=^}ohFf_qJIU&3Nyq7o8ZkbovMfIvc`AOd4yeiD+(!NiUQ_)g}?2~ik2s&rH|t4NXPs1Qvm z3M49;hz{u_Iy$;k>C&Z3l`d~~ZgzIFaMo$;^LMlJ-pp>XHAkn2=;+J*Is)CseI9pR zm(#W7qP*AbEznC`&2Rpjs5wn^4e<@)S;XO}tkx8ABSwfE{=AIH&^g3atSCUC$YB2h2_E*fdUMa$%2wJ?!A43F%P4SV81(5a2%kJ7LYfC6@g7PeQ5C z5`M@NwvL$Ei^ixUzF9mpu{(r87FCsP*R6V28Kl*7d@)&hx;iVy&t@ob_GCO9 zc6&=pT7ui)lZmKVB)Wz83NbP|bdKJ8EI%b!wBL0UrG-jJ=?6EHR>treE%wJu7n z)YiJaASa+H#B}6u`Lh@6wQudNOkhx@n{|x^b01(VO-v9sr diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/PARAMETER.index deleted file mode 100644 index 863806367a57fe62439d83026877b1579a2b9f99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmeZo6=GmyU|`rkT_X%gf!QKJI@r(A+cnVK#D-%01&GJ JaSRZH007GF3f=$! diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/PARAMETER.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/PARAMETER.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/STATIC.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/STATIC.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/STATIC.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/STATIC.index deleted file mode 100644 index 4377afdcd79e9bcdb445912d8aa2a302b61f9750..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|`rkT_X%g!2tj;Y683f diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/STATIC.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_16/STATIC.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/ANALYZED.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/ANALYZED.data_0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/ANALYZED.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/ANALYZED.index deleted file mode 100644 index 4377afdcd79e9bcdb445912d8aa2a302b61f9750..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 WcmeZo6=GmyU|`rkT_X%g!2tj;Y683f diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/ANALYZED.mnt b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/ANALYZED.mnt deleted file mode 100644 index 5280360395e2145158e2ef669e8927603c088738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 Mcmc~YYi9rf00;a5C;$Ke diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/FORECAST.data_0 b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/FORECAST.data_0 deleted file mode 100644 index 6cccb3e4dc074a2bbc2126f82d0b4dc678c5479d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108288 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�k={<>l9|G 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%0D>XUm{VQYq!7GZQ6vu#rTDe;R z!DcOyT+6zM@PF+I_UO4#;(LiMn)FXZid}qBUhXw^x}!>hMon_Epvb48kSWP%d{^}U zTRDJqEp{}CAU+s5CZHb`e${~uqhAvLN)-T3+|IZmM|Ukl{TD2VGd0owtwp)vweNaC zY!%|DVKw&K9v^}XxOvW;wn|QBla{zVgimf7cwN=+CpS#iXXm|4(`oE95jM_g+pwz zIf^gKJJ6{+jSrelYqRm!m$YMm)>W;mt()XWPYi0ejx92vCORiyw+}9a9a}=pLiBAi zOOlZGor!UoqJ&ukDiUO5t1uo(3DVDBvQ|8FrHjDWZW$vCn+s4kslf9tVlzN0Y;_dGlqO zmU$3hZ#jkpyE(7s7T`;n>-mmsm}1Ls_?x?~RJDn^*xBG7AESwXA4iFdt>0nNl@@^~ zMDbvQx*4W*zfktmkaD1X{nmPi-=xi5aN{8;QGQ}8j0yfJWc za(vFny*ACEzqs^nI>K=NGMFd`?5?9kB&$Dse|9S|B5=+!iq{zkVMU4M(4j&Ni)dEf zd$)6fVAsx`ypT%ib(NT&(a^I}xNnad6D#1j2`~^t^k-O{#<@sC6c+QqFB-C5w>*{1 zuwGT}q&emh;k!6v{^Bxqx$|Xada(1BmXxBvTL7Igv!4`}95}&TnON83UA6f%tXZU; z_*-@1H5E$9mCm>{J$r0P-$H}p=ZSRAbKm=M+&>&X9)4t`IS8&5Wx+q8j&ZYMISGkh zwJ7WDw(85rj&{3Q2O3PtBB&1{+A9B(>DcfejF+V&$cR^un}Ubhe+GUNSO4P04DFg_ z_4UHVyC;bqOJSItX$NKLhrph<%mJyww8neIet2-N$3~2+!HX%Fr+a|hqr7A(gHuPt ztic(e&SbwEM1I<0h_f>>R0Mv9H9w}x3fA*xOH9;K|0m$`vpxLWgIS(0BFcg!Hh=7ShBvgyU0K6(026yC49IduDdUXduKQ={u+%0D$Nym-3;lC`xgh|iI*%DhxH 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 diff --git a/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/PARAMETER.index b/ThirdParty/Ert/test-data/local/snake_oil/storage/snake_oil/ensemble/default_0/Ensemble/mod_17/PARAMETER.index deleted file mode 100644 index 796c562bd6559ee03e7219a4e5443fd10241f46d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 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