///////////////////////////////////////////////////////////////////////////////// // // 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 "RimIdenticalGridCaseGroup.h" #include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RigGridManager.h" #include "RimCase.h" #include "RimCaseCollection.h" #include "RimCellEdgeResultSlot.h" #include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultCase.h" #include "RimResultSlot.h" #include "RimStatisticsCase.h" #include "RigCaseCellResultsData.h" #include "cafProgressInfo.h" CAF_PDM_SOURCE_INIT(RimIdenticalGridCaseGroup, "RimIdenticalGridCaseGroup"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimIdenticalGridCaseGroup::RimIdenticalGridCaseGroup() { CAF_PDM_InitObject("Grid Case Group", ":/GridCaseGroup16x16.png", "", ""); CAF_PDM_InitField(&name, "UserDescription", QString("Grid Case Group"), "Name", "", "", ""); CAF_PDM_InitField(&groupId, "GroupId", -1, "Case Group ID", "", "" ,""); groupId.setUiReadOnly(true); CAF_PDM_InitFieldNoDefault(&statisticsCaseCollection, "StatisticsCaseCollection", "Derived Statistics", ":/Histograms16x16.png", "", ""); CAF_PDM_InitFieldNoDefault(&caseCollection, "CaseCollection", "Source Cases", ":/Cases16x16.png", "", ""); caseCollection = new RimCaseCollection; statisticsCaseCollection = new RimCaseCollection; m_mainGrid = NULL; m_unionOfMatrixActiveCells = new RigActiveCellInfo; m_unionOfFractureActiveCells = new RigActiveCellInfo; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimIdenticalGridCaseGroup::~RimIdenticalGridCaseGroup() { m_mainGrid = NULL; delete caseCollection; caseCollection = NULL; delete statisticsCaseCollection; statisticsCaseCollection = NULL; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimIdenticalGridCaseGroup::addCase(RimCase* reservoir) { CVF_ASSERT(reservoir); if (!reservoir) return; if (!m_mainGrid) { m_mainGrid = reservoir->reservoirData()->mainGrid(); } else { reservoir->reservoirData()->setMainGrid(m_mainGrid); } caseCollection()->reservoirs().push_back(reservoir); clearActiveCellUnions(); clearStatisticsResults(); updateMainGridAndActiveCellsForStatisticsCases(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimIdenticalGridCaseGroup::removeCase(RimCase* reservoir) { if (caseCollection()->reservoirs().count(reservoir) == 0) { return; } caseCollection()->reservoirs().removeChildObject(reservoir); if (caseCollection()->reservoirs().size() == 0) { m_mainGrid = NULL; } clearActiveCellUnions(); clearStatisticsResults(); updateMainGridAndActiveCellsForStatisticsCases(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigMainGrid* RimIdenticalGridCaseGroup::mainGrid() { if (m_mainGrid) return m_mainGrid; return NULL; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- caf::PdmFieldHandle* RimIdenticalGridCaseGroup::userDescriptionField() { return &name; } //-------------------------------------------------------------------------------------------------- /// Make sure changes in this functions is validated to RiaApplication::addEclipseCases() //-------------------------------------------------------------------------------------------------- void RimIdenticalGridCaseGroup::loadMainCaseAndActiveCellInfo() { if (caseCollection()->reservoirs().size() == 0) { return; } // Read the main case completely including grid. // The mainGrid from the first case is reused directly in for the other cases. // When reading active cell info, only the total cell count is tested for consistency RimCase* mainCase = caseCollection()->reservoirs[0]; mainCase->openEclipseGridFile(); RigCaseData* rigCaseData = mainCase->reservoirData(); if (rigCaseData) { RifReaderInterface::PorosityModelResultType poroModel = RifReaderInterface::MATRIX_RESULTS; RimReservoirCellResultsStorage* cellResultsStorage = mainCase->results(poroModel); cellResultsStorage->cellResults()->createPlaceholderResultEntries(); } else { // Error message return; } // Action A : Read active cell info // Read active cell info from all source cases. The file access is optimized for this purpose, and result meta data // is copied from main case to all other cases (see "Action B") caf::ProgressInfo info(caseCollection()->reservoirs.size(), "Case group - Reading Active Cell data"); for (size_t i = 1; i < caseCollection()->reservoirs.size(); i++) { RimResultCase* rimReservoir = dynamic_cast(caseCollection()->reservoirs[i]); if(!rimReservoir) continue; // Input reservoir if (!rimReservoir->openAndReadActiveCellData(rigCaseData)) { // Error message continue; } info.incrementProgress(); } m_mainGrid = rigCaseData->mainGrid(); // Check if we need to calculate the union of the active cells bool foundResultsInCache = false; for (size_t i = 0; i < statisticsCaseCollection()->reservoirs.size(); i++) { RimCase* rimReservoir = statisticsCaseCollection()->reservoirs[i]; // Check if any results are stored in cache if (rimReservoir->results(RifReaderInterface::MATRIX_RESULTS)->storedResultsCount() > 0 || rimReservoir->results(RifReaderInterface::FRACTURE_RESULTS)->storedResultsCount() > 0) { foundResultsInCache = true; break; } } if (foundResultsInCache) { computeUnionOfActiveCells(); } // Action B : Copy result meta data from main case to all other cases in grid case group // This code was originally part of RimStatisticsCaseEvaluator, but moved here to be a general solution // for all cases { RifReaderInterface::PorosityModelResultType poroModel = RifReaderInterface::MATRIX_RESULTS; std::vector timeStepDates = rigCaseData->results(poroModel)->timeStepDates(0); const std::vector resultInfos = rigCaseData->results(poroModel)->infoForEachResultIndex(); for (size_t i = 1; i < caseCollection()->reservoirs.size(); i++) { RimResultCase* rimReservoir = dynamic_cast(caseCollection()->reservoirs[i]); if (!rimReservoir) continue; // Input reservoir RimReservoirCellResultsStorage* cellResultsStorage = rimReservoir->results(poroModel); for (size_t resIdx = 0; resIdx < resultInfos.size(); resIdx++) { RimDefines::ResultCatType resultType = resultInfos[resIdx].m_resultType; QString resultName = resultInfos[resIdx].m_resultName; bool needsToBeStored = resultInfos[resIdx].m_needsToBeStored; size_t scalarResultIndex = cellResultsStorage->cellResults()->findScalarResultIndex(resultType, resultName); if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) { size_t scalarResultIndex = cellResultsStorage->cellResults()->addEmptyScalarResult(resultType, resultName, needsToBeStored); cellResultsStorage->cellResults()->setTimeStepDates(scalarResultIndex, timeStepDates); std::vector< std::vector >& dataValues = cellResultsStorage->cellResults()->cellScalarResults(scalarResultIndex); dataValues.resize(timeStepDates.size()); } } cellResultsStorage->cellResults()->createPlaceholderResultEntries(); } } // "Load" the statistical cases for (size_t i = 0; i < statisticsCaseCollection()->reservoirs.size(); i++) { RimCase* rimReservoir = statisticsCaseCollection()->reservoirs[i]; rimReservoir->openEclipseGridFile(); if (i == 0) { rimReservoir->reservoirData()->computeActiveCellBoundingBoxes(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() { if (m_unionOfMatrixActiveCells->reservoirActiveCellCount() > 0) { return; } if (caseCollection->reservoirs.size() == 0 || !m_mainGrid) { this->clearActiveCellUnions(); return; } m_unionOfMatrixActiveCells->setReservoirCellCount(m_mainGrid->cells().size()); m_unionOfFractureActiveCells->setReservoirCellCount(m_mainGrid->cells().size()); m_unionOfMatrixActiveCells->setGridCount(m_mainGrid->gridCount()); m_unionOfFractureActiveCells->setGridCount(m_mainGrid->gridCount()); size_t globalActiveMatrixIndex = 0; size_t globalActiveFractureIndex = 0; for (size_t gridIdx = 0; gridIdx < m_mainGrid->gridCount(); gridIdx++) { RigGridBase* grid = m_mainGrid->gridByIndex(gridIdx); std::vector activeM(grid->cellCount(), 0); std::vector activeF(grid->cellCount(), 0); for (size_t gridLocalCellIndex = 0; gridLocalCellIndex < grid->cellCount(); gridLocalCellIndex++) { for (size_t caseIdx = 0; caseIdx < caseCollection->reservoirs.size(); caseIdx++) { size_t reservoirCellIndex = grid->reservoirCellIndex(gridLocalCellIndex); if (activeM[gridLocalCellIndex] == 0) { if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->isActive(reservoirCellIndex)) { activeM[gridLocalCellIndex] = 1; } } if (activeF[gridLocalCellIndex] == 0) { if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->isActive(reservoirCellIndex)) { activeF[gridLocalCellIndex] = 1; } } } } size_t activeMatrixIndex = 0; size_t activeFractureIndex = 0; for (size_t gridLocalCellIndex = 0; gridLocalCellIndex < grid->cellCount(); gridLocalCellIndex++) { size_t reservoirCellIndex = grid->reservoirCellIndex(gridLocalCellIndex); if (activeM[gridLocalCellIndex] != 0) { m_unionOfMatrixActiveCells->setCellResultIndex(reservoirCellIndex, globalActiveMatrixIndex++); activeMatrixIndex++; } if (activeF[gridLocalCellIndex] != 0) { m_unionOfFractureActiveCells->setCellResultIndex(reservoirCellIndex, globalActiveFractureIndex++); activeFractureIndex++; } } m_unionOfMatrixActiveCells->setGridActiveCellCounts(gridIdx, activeMatrixIndex); m_unionOfFractureActiveCells->setGridActiveCellCounts(gridIdx, activeFractureIndex); } m_unionOfMatrixActiveCells->computeDerivedData(); m_unionOfFractureActiveCells->computeDerivedData(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimStatisticsCase* RimIdenticalGridCaseGroup::createAndAppendStatisticsCase() { RimStatisticsCase* newStatisticsCase = new RimStatisticsCase; newStatisticsCase->caseUserDescription = QString("Statistics ") + QString::number(statisticsCaseCollection()->reservoirs.size()+1); statisticsCaseCollection()->reservoirs.push_back(newStatisticsCase); newStatisticsCase->openEclipseGridFile(); return newStatisticsCase; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimIdenticalGridCaseGroup::updateMainGridAndActiveCellsForStatisticsCases() { for (size_t i = 0; i < statisticsCaseCollection->reservoirs().size(); i++) { RimCase* rimStaticsCase = statisticsCaseCollection->reservoirs[i]; rimStaticsCase->reservoirData()->setMainGrid(this->mainGrid()); if (i == 0) { rimStaticsCase->reservoirData()->computeActiveCellBoundingBoxes(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimIdenticalGridCaseGroup::clearStatisticsResults() { for (size_t i = 0; i < statisticsCaseCollection->reservoirs().size(); i++) { RimCase* rimStaticsCase = statisticsCaseCollection->reservoirs[i]; if (!rimStaticsCase) continue; rimStaticsCase->results(RifReaderInterface::MATRIX_RESULTS)->cellResults()->clearAllResults(); rimStaticsCase->results(RifReaderInterface::FRACTURE_RESULTS)->cellResults()->clearAllResults(); for (size_t j = 0; j < rimStaticsCase->reservoirViews.size(); j++) { RimReservoirView* rimReservoirView = rimStaticsCase->reservoirViews[j]; rimReservoirView->cellResult()->setResultVariable(RimDefines::undefinedResultName()); rimReservoirView->cellEdgeResult()->resultVariable = RimDefines::undefinedResultName(); rimReservoirView->loadDataAndUpdate(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimIdenticalGridCaseGroup::clearActiveCellUnions() { m_unionOfMatrixActiveCells->clear(); m_unionOfFractureActiveCells->clear(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimIdenticalGridCaseGroup::contains(RimCase* reservoir) const { CVF_ASSERT(reservoir); for (size_t i = 0; i < caseCollection()->reservoirs().size(); i++) { RimCase* rimReservoir = caseCollection()->reservoirs()[i]; if (reservoir->gridFileName() == rimReservoir->gridFileName()) { return true; } } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigActiveCellInfo* RimIdenticalGridCaseGroup::unionOfActiveCells(RifReaderInterface::PorosityModelResultType porosityType) { if (porosityType == RifReaderInterface::MATRIX_RESULTS) { return m_unionOfMatrixActiveCells.p(); } else { return m_unionOfFractureActiveCells.p(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimIdenticalGridCaseGroup::isStatisticsCaseCollection(RimCaseCollection* rimCaseCollection) { std::vector fields; rimCaseCollection->parentFields(fields); if (fields.size() == 1) { if (fields[0]->keyword() == "StatisticsCaseCollection") { return true; } } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimCase* RimIdenticalGridCaseGroup::mainCase() { if(caseCollection()->reservoirs().size()) { return caseCollection()->reservoirs()[0]; } else { return NULL; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimIdenticalGridCaseGroup::canCaseBeAdded(RimCase* reservoir) const { CVF_ASSERT(reservoir && reservoir->reservoirData() && reservoir->reservoirData()->mainGrid()); if (!m_mainGrid) { // Empty case group, reservoir can be added return true; } RigMainGrid* incomingMainGrid = reservoir->reservoirData()->mainGrid(); if (RigGridManager::isEqual(m_mainGrid, incomingMainGrid)) { return true; } return false; }