///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) Statoil ASA // Copyright (C) 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 "RimReservoirCellResultsStorage.h" #include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RigCell.h" #include "RigMainGrid.h" #include "RimEclipseCase.h" #include "RimTools.h" #include "cafProgressInfo.h" #include "cvfGeometryTools.h" #include #include #include #include #include CAF_PDM_SOURCE_INIT(RimReservoirCellResultsStorage, "ReservoirCellResultStorage"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimReservoirCellResultsStorage::RimReservoirCellResultsStorage() : m_cellResults(NULL), m_ownerMainGrid(NULL) { CAF_PDM_InitObject("Cacher", "", "", ""); CAF_PDM_InitField(&m_resultCacheFileName, "ResultCacheFileName", QString(), "UiDummyname", "", "" ,""); m_resultCacheFileName.uiCapability()->setUiHidden(true); CAF_PDM_InitFieldNoDefault(&m_resultCacheMetaData, "ResultCacheEntries", "UiDummyname", "", "", ""); m_resultCacheMetaData.uiCapability()->setUiHidden(true); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimReservoirCellResultsStorage::~RimReservoirCellResultsStorage() { m_resultCacheMetaData.deleteAllChildObjects(); } //-------------------------------------------------------------------------------------------------- /// This override populates the metainfo regarding the cell results data in the RigCaseCellResultsData /// object. This metainfo will then be written to the project file when saving, and thus read on project file open. /// This method then writes the actual double arrays to the data file in a simple format: /// MagicNumber, Version, ResultVariables< Array < TimeStep< CellDataArraySize, CellData< Array > > > /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::setupBeforeSave() { m_resultCacheMetaData.deleteAllChildObjects(); QString newValidCacheFileName = getValidCacheFileName(); // Delete the storage file QFileInfo storageFileInfo(newValidCacheFileName); if (storageFileInfo.exists()) { QDir storageDir = storageFileInfo.dir(); storageDir.remove(storageFileInfo.fileName()); } if (!m_cellResults) return; const std::vector& resInfo = m_cellResults->infoForEachResultIndex(); bool hasResultsToStore = false; for (size_t rIdx = 0; rIdx < resInfo.size(); ++rIdx) { if (resInfo[rIdx].m_needsToBeStored) { hasResultsToStore = true; break; } } if(resInfo.size() && hasResultsToStore) { QDir::root().mkpath(getCacheDirectoryPath()); QFile cacheFile(newValidCacheFileName); if (!cacheFile.open(QIODevice::WriteOnly)) { qWarning() << "Saving project: Can't open the cache file : " + newValidCacheFileName; return; } m_resultCacheFileName = newValidCacheFileName; QDataStream stream(&cacheFile); stream.setVersion(QDataStream::Qt_4_6); stream << (quint32)0xCEECAC4E; // magic number stream << (quint32)1; // Version number. Increment if needing to extend the format in ways that can not be handled generically by the reader caf::ProgressInfo progInfo(resInfo.size(), "Saving generated and imported properties"); for (size_t rIdx = 0; rIdx < resInfo.size(); ++rIdx) { // If there is no data, we do not store anything for the current result variable // (Even not the metadata, of cause) size_t timestepCount = m_cellResults->cellScalarResults(resInfo[rIdx].m_gridScalarResultIndex).size(); if (timestepCount && resInfo[rIdx].m_needsToBeStored) { progInfo.setProgressDescription(resInfo[rIdx].m_resultName); // Create and setup the cache information for this result RimReservoirCellResultsStorageEntryInfo* cacheEntry = new RimReservoirCellResultsStorageEntryInfo; m_resultCacheMetaData.push_back(cacheEntry); cacheEntry->m_resultType = resInfo[rIdx].m_resultType; cacheEntry->m_resultName = resInfo[rIdx].m_resultName; cacheEntry->m_timeStepDates = resInfo[rIdx].m_timeStepDates; // Take note of the file position for fast lookup later cacheEntry->m_filePosition = cacheFile.pos(); // Write all the scalar values for each time step to the stream, // starting with the number of values for (size_t tsIdx = 0; tsIdx < resInfo[rIdx].m_timeStepDates.size() ; ++tsIdx) { const std::vector* data = NULL; if (tsIdx < timestepCount) { data = &(m_cellResults->cellScalarResults(resInfo[rIdx].m_gridScalarResultIndex, tsIdx)); } if (data && data->size()) { stream << (quint64)(data->size()); for (size_t cIdx = 0; cIdx < data->size(); ++cIdx) { stream << (*data)[cIdx]; } } else { stream << (quint64)0; } } } progInfo.incrementProgress(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimReservoirCellResultsStorage::getValidCacheFileName() { QString cacheFileName; if (m_resultCacheFileName().isEmpty()) { QString newCacheDirPath = getCacheDirectoryPath(); QUuid guid = QUuid::createUuid(); cacheFileName = newCacheDirPath + "/" + guid.toString(); } else { // Make the path correct related to the possibly new project filename QString newCacheDirPath = getCacheDirectoryPath(); QFileInfo oldCacheFile(m_resultCacheFileName()); cacheFileName = newCacheDirPath + "/" + oldCacheFile.fileName(); } return cacheFileName; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimReservoirCellResultsStorage::getCacheDirectoryPath() { QString cacheDirPath = RimTools::getCacheRootDirectoryPathFromProject(); cacheDirPath += "_cache"; return cacheDirPath; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::setReaderInterface(RifReaderInterface* readerInterface) { m_readerInterface = readerInterface; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RifReaderInterface* RimReservoirCellResultsStorage::readerInterface() { return m_readerInterface.p(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(const QString& resultName) { if (!m_cellResults) return cvf::UNDEFINED_SIZE_T; size_t scalarResultIndex = this->findOrLoadScalarResult(RimDefines::STATIC_NATIVE, resultName); if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) { scalarResultIndex = this->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, resultName); } if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) { scalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::GENERATED, resultName); } if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) { scalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::INPUT_PROPERTY, resultName); } return scalarResultIndex; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::ResultCatType type, const QString& resultName) { if (!m_cellResults) return cvf::UNDEFINED_SIZE_T; size_t scalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) return cvf::UNDEFINED_SIZE_T; // Load dependency data sets if (type == RimDefines::STATIC_NATIVE) { if (resultName == RimDefines::combinedTransmissibilityResultName()) { this->findOrLoadScalarResult(type, "TRANX"); this->findOrLoadScalarResult(type, "TRANY"); this->findOrLoadScalarResult(type, "TRANZ"); } else if (resultName == RimDefines::combinedMultResultName()) { this->findOrLoadScalarResult(type, "MULTX"); this->findOrLoadScalarResult(type, "MULTX-"); this->findOrLoadScalarResult(type, "MULTY"); this->findOrLoadScalarResult(type, "MULTY-"); this->findOrLoadScalarResult(type, "MULTZ"); this->findOrLoadScalarResult(type, "MULTZ-"); } else if (resultName == RimDefines::combinedRiTranResultName()) { computeRiTransComponent(RimDefines::riTranXResultName()); computeRiTransComponent(RimDefines::riTranYResultName()); computeRiTransComponent(RimDefines::riTranZResultName()); computeNncCombRiTrans(); } else if (resultName == RimDefines::riTranXResultName() || resultName == RimDefines::riTranYResultName() || resultName == RimDefines::riTranZResultName()) { computeRiTransComponent(resultName); } else if (resultName == RimDefines::combinedRiMultResultName()) { computeRiMULTComponent(RimDefines::riMultXResultName()); computeRiMULTComponent(RimDefines::riMultYResultName()); computeRiMULTComponent(RimDefines::riMultZResultName()); computeNncCombRiTrans(); computeNncCombRiMULT(); } else if (resultName == RimDefines::riMultXResultName() || resultName == RimDefines::riMultYResultName() || resultName == RimDefines::riMultZResultName()) { computeRiMULTComponent(resultName); } else if (resultName == RimDefines::combinedRiAreaNormTranResultName()) { computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTranXResultName()); computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTranYResultName()); computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTranZResultName()); computeNncCombRiTRANSbyArea(); } else if (resultName == RimDefines::riAreaNormTranXResultName() || resultName == RimDefines::riAreaNormTranYResultName() || resultName == RimDefines::riAreaNormTranZResultName()) { computeRiTRANSbyAreaComponent(resultName); } } if (isDataPresent(scalarResultIndex)) { return scalarResultIndex; } if (resultName == "SOIL") { if (m_cellResults->mustBeCalculated(scalarResultIndex)) { // Trigger loading of SWAT, SGAS to establish time step count if no data has been loaded from file at this point findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); m_cellResults->cellScalarResults(scalarResultIndex).resize(m_cellResults->maxTimeStepCount()); for (size_t timeStepIdx = 0; timeStepIdx < m_cellResults->maxTimeStepCount(); timeStepIdx++) { std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[timeStepIdx]; if (values.size() == 0) { computeSOILForTimeStep(timeStepIdx); } } return scalarResultIndex; } } if (type == RimDefines::GENERATED) { return cvf::UNDEFINED_SIZE_T; } if (m_readerInterface.notNull()) { // Add one more result to result container size_t timeStepCount = m_cellResults->infoForEachResultIndex()[scalarResultIndex].m_timeStepDates.size(); bool resultLoadingSucess = true; if (type == RimDefines::DYNAMIC_NATIVE && timeStepCount > 0) { m_cellResults->cellScalarResults(scalarResultIndex).resize(timeStepCount); size_t i; for (i = 0; i < timeStepCount; i++) { std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[i]; if (!m_readerInterface->dynamicResult(resultName, RifReaderInterface::MATRIX_RESULTS, i, &values)) { resultLoadingSucess = false; } } } else if (type == RimDefines::STATIC_NATIVE) { m_cellResults->cellScalarResults(scalarResultIndex).resize(1); std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[0]; if (!m_readerInterface->staticResult(resultName, RifReaderInterface::MATRIX_RESULTS, &values)) { resultLoadingSucess = false; } } if (!resultLoadingSucess) { // Remove last scalar result because loading of result failed m_cellResults->cellScalarResults(scalarResultIndex).clear(); } } return scalarResultIndex; } //-------------------------------------------------------------------------------------------------- /// This method is intended to be used for multicase cross statistical calculations, when /// we need process one timestep at a time, freeing memory as we go. //-------------------------------------------------------------------------------------------------- size_t RimReservoirCellResultsStorage::findOrLoadScalarResultForTimeStep(RimDefines::ResultCatType type, const QString& resultName, size_t timeStepIndex) { if (!m_cellResults) return cvf::UNDEFINED_SIZE_T; // Special handling for SOIL if (type == RimDefines::DYNAMIC_NATIVE && resultName.toUpper() == "SOIL") { size_t soilScalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); if (m_cellResults->mustBeCalculated(soilScalarResultIndex)) { m_cellResults->cellScalarResults(soilScalarResultIndex).resize(m_cellResults->maxTimeStepCount()); std::vector& values = m_cellResults->cellScalarResults(soilScalarResultIndex)[timeStepIndex]; if (values.size() == 0) { computeSOILForTimeStep(timeStepIndex); } return soilScalarResultIndex; } } size_t scalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) return cvf::UNDEFINED_SIZE_T; if (type == RimDefines::GENERATED) { return cvf::UNDEFINED_SIZE_T; } if (m_readerInterface.notNull()) { size_t timeStepCount = m_cellResults->infoForEachResultIndex()[scalarResultIndex].m_timeStepDates.size(); bool resultLoadingSucess = true; if (type == RimDefines::DYNAMIC_NATIVE && timeStepCount > 0) { m_cellResults->cellScalarResults(scalarResultIndex).resize(timeStepCount); std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[timeStepIndex]; if (values.size() == 0) { if (!m_readerInterface->dynamicResult(resultName, RifReaderInterface::MATRIX_RESULTS, timeStepIndex, &values)) { resultLoadingSucess = false; } } } else if (type == RimDefines::STATIC_NATIVE) { m_cellResults->cellScalarResults(scalarResultIndex).resize(1); std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[0]; if (!m_readerInterface->staticResult(resultName, RifReaderInterface::MATRIX_RESULTS, &values)) { resultLoadingSucess = false; } } if (!resultLoadingSucess) { // Error logging CVF_ASSERT(false); } } return scalarResultIndex; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::computeSOILForTimeStep(size_t timeStepIndex) { size_t scalarIndexSWAT = findOrLoadScalarResultForTimeStep(RimDefines::DYNAMIC_NATIVE, "SWAT", timeStepIndex); size_t scalarIndexSGAS = findOrLoadScalarResultForTimeStep(RimDefines::DYNAMIC_NATIVE, "SGAS", timeStepIndex); // Early exit if none of SWAT or SGAS is present if (scalarIndexSWAT == cvf::UNDEFINED_SIZE_T && scalarIndexSGAS == cvf::UNDEFINED_SIZE_T) { return; } CVF_ASSERT(m_cellResults); size_t soilResultValueCount = 0; size_t soilTimeStepCount = 0; if (scalarIndexSWAT != cvf::UNDEFINED_SIZE_T) { std::vector& swatForTimeStep = m_cellResults->cellScalarResults(scalarIndexSWAT, timeStepIndex); if (swatForTimeStep.size() > 0) { soilResultValueCount = swatForTimeStep.size(); soilTimeStepCount = m_cellResults->infoForEachResultIndex()[scalarIndexSWAT].m_timeStepDates.size(); } } if (scalarIndexSGAS != cvf::UNDEFINED_SIZE_T) { std::vector& sgasForTimeStep = m_cellResults->cellScalarResults(scalarIndexSGAS, timeStepIndex); if (sgasForTimeStep.size() > 0) { soilResultValueCount = qMax(soilResultValueCount, sgasForTimeStep.size()); size_t sgasTimeStepCount = m_cellResults->infoForEachResultIndex()[scalarIndexSGAS].m_timeStepDates.size(); soilTimeStepCount = qMax(soilTimeStepCount, sgasTimeStepCount); } } // Make sure memory is allocated for the new SOIL results size_t soilResultScalarIndex = m_cellResults->findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SOIL"); m_cellResults->cellScalarResults(soilResultScalarIndex).resize(soilTimeStepCount); if (m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex).size() > 0) { // Data is computed and allocated, nothing more to do return; } m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex).resize(soilResultValueCount); std::vector* swatForTimeStep = NULL; std::vector* sgasForTimeStep = NULL; if (scalarIndexSWAT != cvf::UNDEFINED_SIZE_T) { swatForTimeStep = &(m_cellResults->cellScalarResults(scalarIndexSWAT, timeStepIndex)); if (swatForTimeStep->size() == 0) { swatForTimeStep = NULL; } } if (scalarIndexSGAS != cvf::UNDEFINED_SIZE_T) { sgasForTimeStep = &(m_cellResults->cellScalarResults(scalarIndexSGAS, timeStepIndex)); if (sgasForTimeStep->size() == 0) { sgasForTimeStep = NULL; } } std::vector& soilForTimeStep = m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex); #pragma omp parallel for for (int idx = 0; idx < static_cast(soilResultValueCount); idx++) { double soilValue = 1.0; if (sgasForTimeStep) { soilValue -= sgasForTimeStep->at(idx); } if (swatForTimeStep) { soilValue -= swatForTimeStep->at(idx); } soilForTimeStep[idx] = soilValue; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::computeDepthRelatedResults() { if (!m_cellResults) return; size_t depthResultGridIndex = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "DEPTH"); size_t dxResultGridIndex = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "DX"); size_t dyResultGridIndex = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "DY"); size_t dzResultGridIndex = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "DZ"); size_t topsResultGridIndex = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "TOPS"); size_t bottomResultGridIndex = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "BOTTOM"); bool computeDepth = false; bool computeDx = false; bool computeDy = false; bool computeDz = false; bool computeTops = false; bool computeBottom = false; size_t resultValueCount = m_ownerMainGrid->globalCellArray().size(); if (depthResultGridIndex == cvf::UNDEFINED_SIZE_T) { depthResultGridIndex = m_cellResults->addStaticScalarResult(RimDefines::STATIC_NATIVE, "DEPTH", false, resultValueCount); computeDepth = true; } if (dxResultGridIndex == cvf::UNDEFINED_SIZE_T) { dxResultGridIndex = m_cellResults->addStaticScalarResult(RimDefines::STATIC_NATIVE, "DX", false, resultValueCount); computeDx = true; } if (dyResultGridIndex == cvf::UNDEFINED_SIZE_T) { dyResultGridIndex = m_cellResults->addStaticScalarResult(RimDefines::STATIC_NATIVE, "DY", false, resultValueCount); computeDy = true; } if (dzResultGridIndex == cvf::UNDEFINED_SIZE_T) { dzResultGridIndex = m_cellResults->addStaticScalarResult(RimDefines::STATIC_NATIVE, "DZ", false, resultValueCount); computeDz = true; } if (topsResultGridIndex == cvf::UNDEFINED_SIZE_T) { topsResultGridIndex = m_cellResults->addStaticScalarResult(RimDefines::STATIC_NATIVE, "TOPS", false, resultValueCount); computeTops = true; } if (bottomResultGridIndex == cvf::UNDEFINED_SIZE_T) { bottomResultGridIndex = m_cellResults->addStaticScalarResult(RimDefines::STATIC_NATIVE, "BOTTOM", false, resultValueCount); computeBottom = true; } std::vector< std::vector >& depth = m_cellResults->cellScalarResults(depthResultGridIndex); std::vector< std::vector >& dx = m_cellResults->cellScalarResults(dxResultGridIndex); std::vector< std::vector >& dy = m_cellResults->cellScalarResults(dyResultGridIndex); std::vector< std::vector >& dz = m_cellResults->cellScalarResults(dzResultGridIndex); std::vector< std::vector >& tops = m_cellResults->cellScalarResults(topsResultGridIndex); std::vector< std::vector >& bottom = m_cellResults->cellScalarResults(bottomResultGridIndex); size_t cellIdx = 0; for (cellIdx = 0; cellIdx < m_ownerMainGrid->globalCellArray().size(); cellIdx++) { const RigCell& cell = m_ownerMainGrid->globalCellArray()[cellIdx]; if (computeDepth) { depth[0][cellIdx] = cvf::Math::abs(cell.center().z()); } if (computeDx) { cvf::Vec3d cellWidth = cell.faceCenter(cvf::StructGridInterface::NEG_I) - cell.faceCenter(cvf::StructGridInterface::POS_I); dx[0][cellIdx] = cvf::Math::abs(cellWidth.x()); } if (computeDy) { cvf::Vec3d cellWidth = cell.faceCenter(cvf::StructGridInterface::NEG_J) - cell.faceCenter(cvf::StructGridInterface::POS_J); dy[0][cellIdx] = cvf::Math::abs(cellWidth.y()); } if (computeDz) { cvf::Vec3d cellWidth = cell.faceCenter(cvf::StructGridInterface::NEG_K) - cell.faceCenter(cvf::StructGridInterface::POS_K); dz[0][cellIdx] = cvf::Math::abs(cellWidth.z()); } if (computeTops) { tops[0][cellIdx] = cvf::Math::abs(cell.faceCenter(cvf::StructGridInterface::NEG_K).z()); } if (computeBottom) { bottom[0][cellIdx] = cvf::Math::abs(cell.faceCenter(cvf::StructGridInterface::POS_K).z()); } } } namespace RigTransmissibilityCalcTools { void calculateConnectionGeometry(const RigCell& c1, const RigCell& c2, const std::vector& nodes, cvf::StructGridInterface::FaceType faceId, cvf::Vec3d* faceAreaVec) { CVF_TIGHT_ASSERT(faceAreaVec); *faceAreaVec = cvf::Vec3d::ZERO; std::vector polygon; std::vector intersections; caf::SizeTArray4 face1; caf::SizeTArray4 face2; c1.faceIndices(faceId, &face1); c2.faceIndices(cvf::StructGridInterface::oppositeFace(faceId), &face2); bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( &polygon, &intersections, (cvf::EdgeIntersectStorage*)NULL, cvf::wrapArrayConst(&nodes), face1.data(), face2.data(), 1e-6); if (foundOverlap) { std::vector realPolygon; for (size_t pIdx = 0; pIdx < polygon.size(); ++pIdx) { if (polygon[pIdx] < nodes.size()) realPolygon.push_back(nodes[polygon[pIdx]]); else realPolygon.push_back(intersections[polygon[pIdx] - nodes.size()]); } // Polygon area vector *faceAreaVec = cvf::GeometryTools::polygonAreaNormal3D(realPolygon); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double halfCellTransmissibility(double perm, double ntg, const cvf::Vec3d& centerToFace, const cvf::Vec3d& faceAreaVec) { return perm*ntg*(faceAreaVec*centerToFace) / (centerToFace*centerToFace); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double newtran(double cdarchy, double mult, double halfCellTrans, double neighborHalfCellTrans) { if (cvf::Math::abs(halfCellTrans) < 1e-15 || cvf::Math::abs(neighborHalfCellTrans) < 1e-15) { return 0.0; } double result = cdarchy * mult / ((1 / halfCellTrans) + (1 / neighborHalfCellTrans)); CVF_TIGHT_ASSERT(result == result); return result; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- typedef size_t(*ResultIndexFunction)(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t directReservoirCellIndex(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex) { return reservoirCellIndex; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t reservoirActiveCellIndex(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex) { return activeCellinfo->cellResultIndex(reservoirCellIndex); } } using namespace RigTransmissibilityCalcTools; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTransComponentResultName) { if (!m_cellResults) return; // Set up which component to compute cvf::StructGridInterface::FaceType faceId = cvf::StructGridInterface::NO_FACE; QString permCompName; if (riTransComponentResultName == RimDefines::riTranXResultName()) { permCompName = "PERMX"; faceId = cvf::StructGridInterface::POS_I; } else if (riTransComponentResultName == RimDefines::riTranYResultName()) { permCompName = "PERMY"; faceId = cvf::StructGridInterface::POS_J; } else if (riTransComponentResultName == RimDefines::riTranZResultName()) { permCompName = "PERMZ"; faceId = cvf::StructGridInterface::POS_K; } else { CVF_ASSERT(false); } double cdarchy = darchysValue(); // Get the needed result indices we depend on size_t permResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, permCompName); size_t ntgResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "NTG"); bool hasNTGResults = ntgResultIdx != cvf::UNDEFINED_SIZE_T; // Get the result index of the output size_t riTransResultIdx = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, riTransComponentResultName); CVF_ASSERT(riTransResultIdx != cvf::UNDEFINED_SIZE_T); // Get the result count, to handle that one of them might be globally defined size_t permxResultValueCount = m_cellResults->cellScalarResults(permResultIdx)[0].size(); size_t resultValueCount = permxResultValueCount; if (hasNTGResults) { size_t ntgResultValueCount = m_cellResults->cellScalarResults(ntgResultIdx)[0].size(); resultValueCount = CVF_MIN(permxResultValueCount, ntgResultValueCount); } // Get all the actual result values std::vector & permResults = m_cellResults->cellScalarResults(permResultIdx)[0]; std::vector & riTransResults = m_cellResults->cellScalarResults(riTransResultIdx)[0]; std::vector * ntgResults = NULL; if (hasNTGResults) { ntgResults = &(m_cellResults->cellScalarResults(ntgResultIdx)[0]); } // Set up output container to correct number of results riTransResults.resize(resultValueCount); // Prepare how to index the result values: ResultIndexFunction riTranIdxFunc = NULL; ResultIndexFunction permIdxFunc = NULL; ResultIndexFunction ntgIdxFunc = NULL; { bool isPermUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(permResultIdx); bool isTransUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(riTransResultIdx); bool isNtgUsingResIdx = false; if (hasNTGResults) { isNtgUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(ntgResultIdx); } // Set up result index function pointers riTranIdxFunc = isTransUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; permIdxFunc = isPermUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; if (hasNTGResults) { ntgIdxFunc = isNtgUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; } } const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); const std::vector& nodes = m_ownerMainGrid->nodes(); bool isFaceNormalsOutwards = m_ownerMainGrid->isFaceNormalsOutwards(); for (size_t nativeResvCellIndex = 0; nativeResvCellIndex < m_ownerMainGrid->globalCellArray().size(); nativeResvCellIndex++) { // Do nothing if we are only dealing with active cells, and this cell is not active: size_t tranResIdx = (*riTranIdxFunc)(activeCellInfo, nativeResvCellIndex); if (tranResIdx == cvf::UNDEFINED_SIZE_T) continue; const RigCell& nativeCell = m_ownerMainGrid->globalCellArray()[nativeResvCellIndex]; RigGridBase* grid = nativeCell.hostGrid(); size_t gridLocalNativeCellIndex = nativeCell.gridLocalCellIndex(); size_t i, j, k, gridLocalNeighborCellIdx; grid->ijkFromCellIndex(gridLocalNativeCellIndex, &i, &j, &k); if (grid->cellIJKNeighbor(i, j, k, faceId, &gridLocalNeighborCellIdx)) { size_t neighborResvCellIdx = grid->reservoirCellIndex(gridLocalNeighborCellIdx); const RigCell& neighborCell = m_ownerMainGrid->globalCellArray()[neighborResvCellIdx]; // Do nothing if neighbor cell has no results size_t neighborCellPermResIdx = (*permIdxFunc)(activeCellInfo, neighborResvCellIdx); if (neighborCellPermResIdx == cvf::UNDEFINED_SIZE_T) continue; // Connection geometry const RigFault* fault = grid->mainGrid()->findFaultFromCellIndexAndCellFace(nativeResvCellIndex, faceId); bool isOnFault = fault; cvf::Vec3d faceAreaVec; cvf::Vec3d faceCenter; if (isOnFault) { calculateConnectionGeometry(nativeCell, neighborCell, nodes, faceId, &faceAreaVec); } else { faceAreaVec = nativeCell.faceNormalWithAreaLenght(faceId); } if (!isFaceNormalsOutwards) faceAreaVec = -faceAreaVec; double halfCellTrans = 0; double neighborHalfCellTrans = 0; // Native cell half cell transm { cvf::Vec3d centerToFace = nativeCell.faceCenter(faceId) - nativeCell.center(); size_t permResIdx = (*permIdxFunc)(activeCellInfo, nativeResvCellIndex); double perm = permResults[permResIdx]; double ntg = 1.0; if (hasNTGResults && faceId != cvf::StructGridInterface::POS_K) { size_t ntgResIdx = (*ntgIdxFunc)(activeCellInfo, nativeResvCellIndex); ntg = (*ntgResults)[ntgResIdx]; } halfCellTrans = halfCellTransmissibility(perm, ntg, centerToFace, faceAreaVec); } // Neighbor cell half cell transm { cvf::Vec3d centerToFace = neighborCell.faceCenter(cvf::StructGridInterface::oppositeFace(faceId)) - neighborCell.center(); double perm = permResults[neighborCellPermResIdx]; double ntg = 1.0; if (hasNTGResults && faceId != cvf::StructGridInterface::POS_K) { size_t ntgResIdx = (*ntgIdxFunc)(activeCellInfo, neighborResvCellIdx); ntg = (*ntgResults)[ntgResIdx]; } neighborHalfCellTrans = halfCellTransmissibility(perm, ntg, centerToFace, -faceAreaVec); } riTransResults[tranResIdx] = newtran(cdarchy, 1.0, halfCellTrans, neighborHalfCellTrans); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::computeNncCombRiTrans() { if (!m_cellResults) return; size_t riCombTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTranResultName()); if (m_ownerMainGrid->nncData()->connectionScalarResult(riCombTransScalarResultIndex)) return; double cdarchy = darchysValue(); // Get the needed result indices we depend on size_t permXResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "PERMX"); size_t permYResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "PERMY"); size_t permZResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "PERMZ"); size_t ntgResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "NTG"); bool hasNTGResults = ntgResultIdx != cvf::UNDEFINED_SIZE_T; // Get all the actual result values std::vector & permXResults = m_cellResults->cellScalarResults(permXResultIdx)[0]; std::vector & permYResults = m_cellResults->cellScalarResults(permYResultIdx)[0]; std::vector & permZResults = m_cellResults->cellScalarResults(permZResultIdx)[0]; std::vector & riCombTransResults = m_ownerMainGrid->nncData()->makeConnectionScalarResult(riCombTransScalarResultIndex); std::vector * ntgResults = NULL; if (hasNTGResults) { ntgResults = &(m_cellResults->cellScalarResults(ntgResultIdx)[0]); } // Prepare how to index the result values: ResultIndexFunction permXIdxFunc = NULL; ResultIndexFunction permYIdxFunc = NULL; ResultIndexFunction permZIdxFunc = NULL; ResultIndexFunction ntgIdxFunc = NULL; { bool isPermXUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(permXResultIdx); bool isPermYUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(permYResultIdx); bool isPermZUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(permZResultIdx); bool isNtgUsingResIdx = false; if (hasNTGResults) { isNtgUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(ntgResultIdx); } // Set up result index function pointers permXIdxFunc = isPermXUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; permYIdxFunc = isPermYUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; permZIdxFunc = isPermZUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; if (hasNTGResults) { ntgIdxFunc = isNtgUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; } } const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); bool isFaceNormalsOutwards = m_ownerMainGrid->isFaceNormalsOutwards(); // NNC calculation std::vector& nncConnections = m_ownerMainGrid->nncData()->connections(); for (size_t connIdx = 0; connIdx < nncConnections.size(); connIdx++) { size_t nativeResvCellIndex = nncConnections[connIdx].m_c1GlobIdx; size_t neighborResvCellIdx = nncConnections[connIdx].m_c2GlobIdx; cvf::StructGridInterface::FaceType faceId = nncConnections[connIdx].m_c1Face; ResultIndexFunction permIdxFunc = NULL; std::vector * permResults; switch (faceId) { case cvf::StructGridInterface::POS_I: case cvf::StructGridInterface::NEG_I: permIdxFunc = permXIdxFunc; permResults = &permXResults; break; case cvf::StructGridInterface::POS_J: case cvf::StructGridInterface::NEG_J: permIdxFunc = permYIdxFunc; permResults = &permYResults; break; case cvf::StructGridInterface::POS_K: case cvf::StructGridInterface::NEG_K: permIdxFunc = permZIdxFunc; permResults = &permZResults; break; } if (!permIdxFunc) continue; // Do nothing if we are only dealing with active cells, and this cell is not active: size_t nativeCellPermResIdx = (*permIdxFunc)(activeCellInfo, nativeResvCellIndex); if (nativeCellPermResIdx == cvf::UNDEFINED_SIZE_T) continue; // Do nothing if neighbor cell has no results size_t neighborCellPermResIdx = (*permIdxFunc)(activeCellInfo, neighborResvCellIdx); if (neighborCellPermResIdx == cvf::UNDEFINED_SIZE_T) continue; const RigCell& nativeCell = m_ownerMainGrid->globalCellArray()[nativeResvCellIndex]; const RigCell& neighborCell = m_ownerMainGrid->globalCellArray()[neighborResvCellIdx]; // Connection geometry cvf::Vec3d faceAreaVec = cvf::Vec3d::ZERO;; cvf::Vec3d faceCenter = cvf::Vec3d::ZERO;; // Polygon center const std::vector& realPolygon = nncConnections[connIdx].m_polygon; for (size_t pIdx = 0; pIdx < realPolygon.size(); ++pIdx) { faceCenter += realPolygon[pIdx]; } faceCenter *= 1.0 / realPolygon.size(); // Polygon area vector faceAreaVec = cvf::GeometryTools::polygonAreaNormal3D(realPolygon); if (!isFaceNormalsOutwards) faceAreaVec = -faceAreaVec; double halfCellTrans = 0; double neighborHalfCellTrans = 0; // Native cell half cell transm { cvf::Vec3d centerToFace = nativeCell.faceCenter(faceId) - nativeCell.center(); double perm = (*permResults)[nativeCellPermResIdx]; double ntg = 1.0; if (hasNTGResults && faceId != cvf::StructGridInterface::POS_K) { size_t ntgResIdx = (*ntgIdxFunc)(activeCellInfo, nativeResvCellIndex); ntg = (*ntgResults)[ntgResIdx]; } halfCellTrans = halfCellTransmissibility(perm, ntg, centerToFace, faceAreaVec); } // Neighbor cell half cell transm { cvf::Vec3d centerToFace = neighborCell.faceCenter(cvf::StructGridInterface::oppositeFace(faceId)) - neighborCell.center(); double perm = (*permResults)[neighborCellPermResIdx]; double ntg = 1.0; if (hasNTGResults && faceId != cvf::StructGridInterface::POS_K) { size_t ntgResIdx = (*ntgIdxFunc)(activeCellInfo, neighborResvCellIdx); ntg = (*ntgResults)[ntgResIdx]; } neighborHalfCellTrans = halfCellTransmissibility(perm, ntg, centerToFace, -faceAreaVec); } double newtranTemp = newtran(cdarchy, 1.0, halfCellTrans, neighborHalfCellTrans); riCombTransResults[connIdx] = newtranTemp; } } double riMult(double transResults, double riTransResults) { if (transResults == HUGE_VAL || riTransResults == HUGE_VAL) return HUGE_VAL; // To make 0.0 values give 1.0 in mult value if (cvf::Math::abs (riTransResults) < 1e-12) { if (cvf::Math::abs (transResults) < 1e-12) { return 1.0; } return HUGE_VAL; } double result = transResults / riTransResults; return result; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::computeRiMULTComponent(const QString& riMultCompName) { if (!m_cellResults) return; // Set up which component to compute QString riTransCompName; QString transCompName; if (riMultCompName == RimDefines::riMultXResultName()) { riTransCompName = RimDefines::riTranXResultName(); transCompName = "TRANX"; } else if (riMultCompName == RimDefines::riMultYResultName()) { riTransCompName = RimDefines::riTranYResultName(); transCompName = "TRANY"; } else if (riMultCompName == RimDefines::riMultZResultName()) { riTransCompName = RimDefines::riTranZResultName(); transCompName = "TRANZ"; } else { CVF_ASSERT(false); } // Get the needed result indices we depend on size_t transResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, transCompName); size_t riTransResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, riTransCompName); // Get the result index of the output size_t riMultResultIdx = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, riMultCompName); CVF_ASSERT(riMultResultIdx != cvf::UNDEFINED_SIZE_T); // Get the result count, to handle that one of them might be globally defined CVF_ASSERT(m_cellResults->cellScalarResults(riTransResultIdx)[0].size() == m_cellResults->cellScalarResults(transResultIdx)[0].size()); size_t resultValueCount = m_cellResults->cellScalarResults(transResultIdx)[0].size(); // Get all the actual result values std::vector & riTransResults = m_cellResults->cellScalarResults(riTransResultIdx)[0]; std::vector & transResults = m_cellResults->cellScalarResults(transResultIdx)[0]; std::vector & riMultResults = m_cellResults->cellScalarResults(riMultResultIdx)[0]; // Set up output container to correct number of results riMultResults.resize(resultValueCount); for (size_t vIdx = 0; vIdx < transResults.size(); ++vIdx) { riMultResults[vIdx] = riMult(transResults[vIdx], riTransResults[vIdx]); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::computeNncCombRiMULT() { if (!m_cellResults) return; size_t riCombMultScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiMultResultName()); size_t riCombTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTranResultName()); size_t combTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); if (m_ownerMainGrid->nncData()->connectionScalarResult(riCombMultScalarResultIndex)) return; std::vector & riMultResults = m_ownerMainGrid->nncData()->makeConnectionScalarResult(riCombMultScalarResultIndex); const std::vector * riTransResults = m_ownerMainGrid->nncData()->connectionScalarResult(riCombTransScalarResultIndex); const std::vector * transResults = m_ownerMainGrid->nncData()->connectionScalarResult(combTransScalarResultIndex); for (size_t nncConIdx = 0; nncConIdx < riMultResults.size(); ++nncConIdx) { riMultResults[nncConIdx] = riMult((*transResults)[nncConIdx], (*riTransResults)[nncConIdx]); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::computeRiTRANSbyAreaComponent(const QString& riTransByAreaCompResultName) { if (!m_cellResults) return; // Set up which component to compute cvf::StructGridInterface::FaceType faceId = cvf::StructGridInterface::NO_FACE; QString transCompName; if (riTransByAreaCompResultName == RimDefines::riAreaNormTranXResultName()) { transCompName = "TRANX"; faceId = cvf::StructGridInterface::POS_I; } else if (riTransByAreaCompResultName == RimDefines::riAreaNormTranYResultName()) { transCompName = "TRANY"; faceId = cvf::StructGridInterface::POS_J; } else if (riTransByAreaCompResultName == RimDefines::riAreaNormTranZResultName()) { transCompName = "TRANZ"; faceId = cvf::StructGridInterface::POS_K; } else { CVF_ASSERT(false); } // Get the needed result indices we depend on size_t tranCompScResIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, transCompName); // Get the result index of the output size_t riTranByAreaScResIdx = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, riTransByAreaCompResultName); CVF_ASSERT(riTranByAreaScResIdx != cvf::UNDEFINED_SIZE_T); // Get the result count, to handle that one of them might be globally defined size_t resultValueCount = m_cellResults->cellScalarResults(tranCompScResIdx)[0].size(); // Get all the actual result values std::vector & transResults = m_cellResults->cellScalarResults(tranCompScResIdx)[0]; std::vector & riTransByAreaResults = m_cellResults->cellScalarResults(riTranByAreaScResIdx)[0]; // Set up output container to correct number of results riTransByAreaResults.resize(resultValueCount); // Prepare how to index the result values: bool isUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(tranCompScResIdx); // Set up result index function pointers ResultIndexFunction resValIdxFunc = isUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); const std::vector& nodes = m_ownerMainGrid->nodes(); for (size_t nativeResvCellIndex = 0; nativeResvCellIndex < m_ownerMainGrid->globalCellArray().size(); nativeResvCellIndex++) { // Do nothing if we are only dealing with active cells, and this cell is not active: size_t nativeCellResValIdx = (*resValIdxFunc)(activeCellInfo, nativeResvCellIndex); if (nativeCellResValIdx == cvf::UNDEFINED_SIZE_T) continue; const RigCell& nativeCell = m_ownerMainGrid->globalCellArray()[nativeResvCellIndex]; RigGridBase* grid = nativeCell.hostGrid(); size_t gridLocalNativeCellIndex = nativeCell.gridLocalCellIndex(); size_t i, j, k, gridLocalNeighborCellIdx; grid->ijkFromCellIndex(gridLocalNativeCellIndex, &i, &j, &k); if (grid->cellIJKNeighbor(i, j, k, faceId, &gridLocalNeighborCellIdx)) { size_t neighborResvCellIdx = grid->reservoirCellIndex(gridLocalNeighborCellIdx); const RigCell& neighborCell = m_ownerMainGrid->globalCellArray()[neighborResvCellIdx]; // Connection geometry const RigFault* fault = grid->mainGrid()->findFaultFromCellIndexAndCellFace(nativeResvCellIndex, faceId); bool isOnFault = fault; cvf::Vec3d faceAreaVec; if (isOnFault) { calculateConnectionGeometry(nativeCell, neighborCell, nodes, faceId, &faceAreaVec); } else { faceAreaVec = nativeCell.faceNormalWithAreaLenght(faceId); } double areaOfOverlap = faceAreaVec.length(); double transCompValue = transResults[nativeCellResValIdx]; riTransByAreaResults[nativeCellResValIdx] = transCompValue / areaOfOverlap; } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::computeNncCombRiTRANSbyArea() { if (!m_cellResults) return; size_t riCombTransByAreaScResIdx = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiAreaNormTranResultName()); size_t combTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); if (m_ownerMainGrid->nncData()->connectionScalarResult(riCombTransByAreaScResIdx)) return; std::vector & riAreaNormTransResults = m_ownerMainGrid->nncData()->makeConnectionScalarResult(riCombTransByAreaScResIdx); const std::vector * transResults = m_ownerMainGrid->nncData()->connectionScalarResult(combTransScalarResultIndex); const std::vector& connections = m_ownerMainGrid->nncData()->connections(); for (size_t nncConIdx = 0; nncConIdx < riAreaNormTransResults.size(); ++nncConIdx) { const std::vector& realPolygon = connections[nncConIdx].m_polygon; cvf::Vec3d faceAreaVec = cvf::GeometryTools::polygonAreaNormal3D(realPolygon); double areaOfOverlap = faceAreaVec.length(); riAreaNormTransResults[nncConIdx] = (*transResults)[nncConIdx] / areaOfOverlap; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::setCellResults(RigCaseCellResultsData* cellResults) { m_cellResults = cellResults; if (m_cellResults == NULL) return; // Now that we have got the results container, we can finally // Read data from the internal storage and populate it if (m_resultCacheFileName().isEmpty()) return; // 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()) { qWarning() << "Reading stored results: Missing the storage file : " + newValidCacheFileName; return; } if (!storageFile.open(QIODevice::ReadOnly)) { qWarning() << "Reading stored results: Can't open the file : " + newValidCacheFileName; return; } QDataStream stream(&storageFile); stream.setVersion(QDataStream::Qt_4_6); quint32 magicNumber = 0; quint32 versionNumber = 0; stream >> magicNumber; if (magicNumber != 0xCEECAC4E) { qWarning() << "Reading stored results: The storage file has wrong type "; return; } stream >> versionNumber; if (versionNumber > 1 ) { qWarning() << "Reading stored results: The storage file has been written by a newer version of ResInsight"; return; } caf::ProgressInfo progress(m_resultCacheMetaData.size(), "Reading internally stored results"); // Fill the object with data from the storage for (size_t rIdx = 0; rIdx < m_resultCacheMetaData.size(); ++rIdx) { 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()); progress.setProgressDescription(resInfo->m_resultName); for (size_t tsIdx = 0; tsIdx < resInfo->m_timeStepDates().size(); ++tsIdx) { std::vector* data = NULL; data = &(m_cellResults->cellScalarResults(rIdx, tsIdx)); quint64 cellCount = 0; stream >> cellCount; data->resize(cellCount, HUGE_VAL); for (size_t cIdx = 0; cIdx < cellCount; ++cIdx) { stream >> (*data)[cIdx]; } } progress.incrementProgress(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimReservoirCellResultsStorage::setMainGrid(RigMainGrid* mainGrid) { m_ownerMainGrid = mainGrid; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RimReservoirCellResultsStorage::storedResultsCount() { return m_resultCacheMetaData.size(); } //-------------------------------------------------------------------------------------------------- /// If we have any results on any time step, assume we have loaded results //-------------------------------------------------------------------------------------------------- bool RimReservoirCellResultsStorage::isDataPresent(size_t scalarResultIndex) const { if (scalarResultIndex >= m_cellResults->resultCount()) { return false; } const std::vector< std::vector > data = m_cellResults->cellScalarResults(scalarResultIndex); for (size_t tsIdx = 0; tsIdx < data.size(); ++tsIdx) { if (data[tsIdx].size()) { return true; } } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimReservoirCellResultsStorage::darchysValue() { // See "Cartesian transmissibility calculations" in the "Eclipse Technical Description" // CDARCY Darcys constant // = 0.00852702 (E300); 0.008527 (ECLIPSE 100) (METRIC) // = 0.00112712 (E300); 0.001127 (ECLIPSE 100) (FIELD) // = 3.6 (LAB) // = 0.00864 (PVT - M) double darchy = 0.008527; // (ECLIPSE 100) (METRIC) RimEclipseCase* rimCase = NULL; this->firstAncestorOrThisOfType(rimCase); if (rimCase && rimCase->reservoirData()) { RigCaseData::UnitsType unitsType = rimCase->reservoirData()->unitsType(); if (unitsType == RigCaseData::UNITS_FIELD) { darchy = 0.001127; } else if (unitsType == RigCaseData::UNITS_METRIC) { darchy = 0.008527; } else if (unitsType == RigCaseData::UNITS_LAB) { darchy = 3.6; } else { darchy = 0.00864; // Assuming (PVT - M) CVF_TIGHT_ASSERT(false); // The enum and doc does not state that the PVT-M actually exists, so to trap this in debug } } return darchy; } CAF_PDM_SOURCE_INIT(RimReservoirCellResultsStorageEntryInfo, "ResultStorageEntryInfo"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimReservoirCellResultsStorageEntryInfo::RimReservoirCellResultsStorageEntryInfo() { CAF_PDM_InitObject("Cache Entry", "", "", ""); 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_InitField(&m_filePosition, "FilePositionDataStart", qint64(-1), "FilePositionDataStart", "", "" ,""); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimReservoirCellResultsStorageEntryInfo::~RimReservoirCellResultsStorageEntryInfo() { }